diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index aca6c09..8a6efca 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -267,6 +267,32 @@ pub mod tests { Ok(()) } + #[test] + fn create_slatepack_emits_lowest_version() -> Result<(), Error> { + set_local_chain_type(ChainTypes::Mainnet); + let packer = Slatepacker::new(SlatepackerArgs { + sender: None, + recipients: vec![], + dec_key: None, + }); + + // A slate carrying a payment proof needs V5 (the proof carries memo/timestamp + // that V4 can't represent), and the V5 fields survive the round trip. + let slate_with_proof = populate_test_slate()?; + assert!(slate_with_proof.payment_proof.is_some()); + let recovered_v5 = packer.get_slate(&packer.create_slatepack(&slate_with_proof)?)?; + assert_eq!(recovered_v5.version_info.version, 5); + assert!(recovered_v5.payment_proof.unwrap().memo.is_some()); + + // Without a proof, V4 is sufficient and is emitted for interoperability with V4 peers. + let mut slate_no_proof = populate_test_slate()?; + slate_no_proof.payment_proof = None; + let recovered_v4 = packer.get_slate(&packer.create_slatepack(&slate_no_proof)?)?; + assert_eq!(recovered_v4.version_info.version, 4); + + Ok(()) + } + #[test] fn slatepack_version_v4_v5() -> Result<(), Error> { set_local_chain_type(ChainTypes::Mainnet); diff --git a/libwallet/src/slatepack/packer.rs b/libwallet/src/slatepack/packer.rs index d44f5c6..32c3e41 100644 --- a/libwallet/src/slatepack/packer.rs +++ b/libwallet/src/slatepack/packer.rs @@ -94,7 +94,19 @@ impl<'a> Slatepacker<'a> { /// Create slatepack from slate and args pub fn create_slatepack(&self, slate: &Slate) -> Result { - let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V5)?; + // Emit the lowest version that can represent this slate, for maximum + // interoperability. Only the (opt-in) payment proof needs V5 fields + // (timestamp/memo) that V4 cannot carry; everything else stays V4. + let (version, version_num) = if slate.payment_proof.is_some() { + (SlateVersion::V5, 5) + } else { + (SlateVersion::V4, 4) + }; + // Keep the declared version consistent with the emitted structure so readers + // select the right variant. + let mut slate = slate.clone(); + slate.version_info.version = version_num; + let out_slate = VersionedSlate::into_version(slate, version)?; let bin_slate = VersionedBinSlate::try_from(out_slate).map_err(|_| Error::SlatepackSer)?; let mut slatepack = Slatepack::default(); slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| Error::SlatepackSer)?;