[Contracts] Slatepack v5 Deserialization fix (#698)

* add V5 deserialization test + fixes

* clarify comment

* upwrap fix during v4 deserialization

* further unwrap removal
This commit is contained in:
Yeastplume 2023-11-21 13:51:46 +00:00 committed by GitHub
parent febffd4c68
commit b3d90c92e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 10 deletions

View file

@ -27,7 +27,7 @@ use grin_wallet_libwallet as libwallet;
use impls::test_framework::{self}; use impls::test_framework::{self};
use libwallet::contract::my_fee_contribution; use libwallet::contract::my_fee_contribution;
use libwallet::contract::types::{ContractNewArgsAPI, ContractSetupArgsAPI}; use libwallet::contract::types::{ContractNewArgsAPI, ContractSetupArgsAPI};
use libwallet::{Slate, SlateState, TxLogEntryType}; use libwallet::{Slate, SlateState, Slatepack, Slatepacker, SlatepackerArgs, TxLogEntryType};
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
@ -66,12 +66,27 @@ fn contract_early_proofs_rsr_test_impl(test_dir: &'static str) -> Result<(), lib
..Default::default() ..Default::default()
}; };
args.setup_args.proof_args.sender_address = sender_address; args.setup_args.proof_args.sender_address = sender_address;
println!("SENDER ADDRESS: {:?}", sender_address);
slate = api.contract_new(m, args)?; slate = api.contract_new(m, args)?;
recipient_address = Some(api.get_slatepack_address(recv_mask, 0)?.pub_key); recipient_address = Some(api.get_slatepack_address(recv_mask, 0)?.pub_key);
Ok(()) Ok(())
})?; })?;
assert_eq!(slate.state, SlateState::Invoice1); assert_eq!(slate.state, SlateState::Invoice1);
println!("I1 State slate: {}", slate);
// Serialize slate into slatepack
let slatepacker_args = SlatepackerArgs {
sender: None,
recipients: vec![],
dec_key: None,
};
let slate_packer = Slatepacker::new(slatepacker_args);
let slate_packed = slate_packer.create_slatepack(&slate).unwrap();
let slate_unpacked = slate_packer.get_slate(&slate_packed).unwrap();
println!("I2 Slate unpacked: {}", slate_unpacked);
wallet::controller::owner_single_use(Some(send_wallet.clone()), send_mask, None, |api, m| { wallet::controller::owner_single_use(Some(send_wallet.clone()), send_mask, None, |api, m| {
// Sending wallet (invoice) signs // Sending wallet (invoice) signs
@ -79,9 +94,10 @@ fn contract_early_proofs_rsr_test_impl(test_dir: &'static str) -> Result<(), lib
net_change: Some(-5_000_000_000), net_change: Some(-5_000_000_000),
..Default::default() ..Default::default()
}; };
slate = api.contract_sign(m, &slate, args)?; slate = api.contract_sign(m, &slate_unpacked, args)?;
Ok(()) Ok(())
})?; })?;
println!("I2 State slate: {}", slate);
assert_eq!(slate.state, SlateState::Invoice2); assert_eq!(slate.state, SlateState::Invoice2);

View file

@ -59,7 +59,7 @@ pub struct PaymentMemo {
pub memo: [u8; 32], pub memo: [u8; 32],
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct PaymentInfo { pub struct PaymentInfo {
/// Sender address /// Sender address
pub sender_address: Option<DalekPublicKey>, pub sender_address: Option<DalekPublicKey>,

View file

@ -94,11 +94,13 @@ impl From<VersionedSlate> for Slate {
#[serde(untagged)] #[serde(untagged)]
/// Binary versions, can only be parsed 1:1 into the appropriate /// Binary versions, can only be parsed 1:1 into the appropriate
/// version, and VersionedSlate can up/downgrade from there /// version, and VersionedSlate can up/downgrade from there
/// NB (IMPORTANT): Ensure the slates are listed in reverse chronological
/// order (latest first)
pub enum VersionedBinSlate { pub enum VersionedBinSlate {
/// Version 4, binary
V4(SlateV4Bin),
/// Version 5, binary /// Version 5, binary
V5(SlateV5Bin), V5(SlateV5Bin),
/// Version 4, binary
V4(SlateV4Bin),
} }
impl TryFrom<VersionedSlate> for VersionedBinSlate { impl TryFrom<VersionedSlate> for VersionedBinSlate {
@ -149,7 +151,9 @@ pub mod tests {
use crate::grin_util::secp::Signature; use crate::grin_util::secp::Signature;
use crate::slate::{KernelFeaturesArgs, ParticipantData, PaymentInfo, PaymentMemo}; use crate::slate::{KernelFeaturesArgs, ParticipantData, PaymentInfo, PaymentMemo};
use crate::slate_versions::v5::{CommitsV5, SlateV5}; use crate::slate_versions::v5::{CommitsV5, SlateV5};
use crate::{slate, Error, Slate, VersionedBinSlate, VersionedSlate}; use crate::{
slate, Error, Slate, Slatepacker, SlatepackerArgs, VersionedBinSlate, VersionedSlate,
};
use chrono::{DateTime, NaiveDateTime, Utc}; use chrono::{DateTime, NaiveDateTime, Utc};
use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::Signature as DalekSignature; use ed25519_dalek::Signature as DalekSignature;
@ -242,6 +246,27 @@ pub mod tests {
Ok(slate_internal) Ok(slate_internal)
} }
#[test]
fn ser_deser_current_slate() -> Result<(), Error> {
let slate_internal = populate_test_slate()?;
// Serialize slate into slatepack
let slatepacker_args = SlatepackerArgs {
sender: None,
recipients: vec![],
dec_key: None,
};
let slate_packer = Slatepacker::new(slatepacker_args);
let slate_packed = slate_packer.create_slatepack(&slate_internal).unwrap();
let slate_unpacked = slate_packer.get_slate(&slate_packed).unwrap();
// Just verifying payment proof for now, extend later to cover EQ for full slate if needs
// be
assert_eq!(slate_internal.payment_proof, slate_unpacked.payment_proof);
Ok(())
}
#[test] #[test]
fn slatepack_version_v4_v5() -> Result<(), Error> { fn slatepack_version_v4_v5() -> Result<(), Error> {
set_local_chain_type(ChainTypes::Mainnet); set_local_chain_type(ChainTypes::Mainnet);

View file

@ -25,6 +25,7 @@ use chrono::{DateTime, NaiveDateTime, Utc};
use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::Signature as DalekSignature; use ed25519_dalek::Signature as DalekSignature;
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::f64::consts::E;
use crate::slate_versions::v5::{ use crate::slate_versions::v5::{
CommitsV5, KernelFeaturesArgsV5, ParticipantDataV5, PaymentInfoV5, PaymentMemoV5, SlateStateV5, CommitsV5, KernelFeaturesArgsV5, ParticipantDataV5, PaymentInfoV5, PaymentMemoV5, SlateStateV5,
@ -246,9 +247,15 @@ impl Readable for ProofWrap {
fn read<R: Reader>(reader: &mut R) -> Result<ProofWrap, grin_ser::Error> { fn read<R: Reader>(reader: &mut R) -> Result<ProofWrap, grin_ser::Error> {
let saddr = DalekPublicKey::from_bytes(&reader.read_fixed_bytes(32)?).unwrap(); let saddr = DalekPublicKey::from_bytes(&reader.read_fixed_bytes(32)?).unwrap();
let raddr = DalekPublicKey::from_bytes(&reader.read_fixed_bytes(32)?).unwrap(); let raddr = DalekPublicKey::from_bytes(&reader.read_fixed_bytes(32)?).unwrap();
let ts_raw: i64 = reader.read_i64().unwrap(); let ts_raw: i64 = match reader.read_i64() {
let ts = Ok(v) => v,
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp_opt(ts_raw, 0).unwrap(), Utc); Err(_) => return Err(grin_ser::Error::CorruptedData),
};
let ts_opt = match NaiveDateTime::from_timestamp_opt(ts_raw, 0) {
Some(o) => o,
None => return Err(grin_ser::Error::CorruptedData),
};
let ts = DateTime::<Utc>::from_utc(ts_opt, Utc);
let psig = match reader.read_u8()? { let psig = match reader.read_u8()? {
0 => None, 0 => None,
1 | _ => Some(DalekSignature::try_from(&reader.read_fixed_bytes(64)?[..]).unwrap()), 1 | _ => Some(DalekSignature::try_from(&reader.read_fixed_bytes(64)?[..]).unwrap()),

View file

@ -94,7 +94,7 @@ impl<'a> Slatepacker<'a> {
/// Create slatepack from slate and args /// Create slatepack from slate and args
pub fn create_slatepack(&self, slate: &Slate) -> Result<Slatepack, Error> { pub fn create_slatepack(&self, slate: &Slate) -> Result<Slatepack, Error> {
let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?; let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V5)?;
let bin_slate = VersionedBinSlate::try_from(out_slate).map_err(|_| Error::SlatepackSer)?; let bin_slate = VersionedBinSlate::try_from(out_slate).map_err(|_| Error::SlatepackSer)?;
let mut slatepack = Slatepack::default(); let mut slatepack = Slatepack::default();
slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| Error::SlatepackSer)?; slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| Error::SlatepackSer)?;