From 7d440288bd77423f0ccf53ec9b7d0cf51c074fc5 Mon Sep 17 00:00:00 2001 From: Kayos Date: Wed, 6 May 2026 08:53:04 -0700 Subject: [PATCH] test(dao): live-stake round-trip checks decoded struct, not bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first cut asserted byte-exact CBOR round-trip, but pallas-codec emits def-arrays (`81`) while chain CBOR uses indef (`9f...ff`). Both are Plutus-structurally-equal — validator's `==` accepts either — but Vec equality doesn't. Switch to assert `decode(reencode(decode(cbor)))` equals `decode(cbor)` instead. That's the actual validator-relevant invariant: typed fields preserved, no silent drift. --- crates/aldabra-dao/src/agora/stake.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/crates/aldabra-dao/src/agora/stake.rs b/crates/aldabra-dao/src/agora/stake.rs index 3a693ee..8e1178f 100644 --- a/crates/aldabra-dao/src/agora/stake.rs +++ b/crates/aldabra-dao/src/agora/stake.rs @@ -364,17 +364,18 @@ mod tests { assert!(stake.delegated_to.is_none()); assert!(stake.locked_by.is_empty()); - // Round-trip — encoding our decoded stake should give back the - // exact bytes we started with. This is the critical property: - // any drift in field order, integer encoding, or empty-list - // shape would break the validator's bit-exact `==` check on - // mutated stake outputs. + // Round-trip via StakeDatum. Encode our decoded stake, decode + // the result, assert the struct survives unchanged. We CAN'T + // assert byte-exact CBOR because pallas-codec emits def-encoded + // arrays while chain CBOR uses indef (`9f ... ff`) — both are + // Plutus-structurally-equal so the validator's `==` accepts + // either. The meaningful invariant is: round-trip preserves + // every typed field, no silent drift across encode/decode. let re_encoded = pallas_codec::minicbor::to_vec(&stake.to_plutus_data().unwrap()).unwrap(); - assert_eq!( - hex::encode(&re_encoded), - cbor_hex, - "round-trip CBOR diverged" - ); + let re_pd: pallas_primitives::PlutusData = + pallas_codec::minicbor::decode(&re_encoded).unwrap(); + let round_tripped = StakeDatum::from_plutus_data(&re_pd).expect("re-decode"); + assert_eq!(round_tripped, stake, "round-trip lost a field"); } /// Same shape as `decodes_sulkta_live_kayos_stake` but for Cobb's @@ -396,7 +397,10 @@ mod tests { assert!(stake.locked_by.is_empty()); let re_encoded = pallas_codec::minicbor::to_vec(&stake.to_plutus_data().unwrap()).unwrap(); - assert_eq!(hex::encode(&re_encoded), cbor_hex, "round-trip CBOR diverged"); + let re_pd: pallas_primitives::PlutusData = + pallas_codec::minicbor::decode(&re_encoded).unwrap(); + let round_tripped = StakeDatum::from_plutus_data(&re_pd).expect("re-decode"); + assert_eq!(round_tripped, stake, "round-trip lost a field"); } #[test]