use proptest::{arbitrary::any, collection::vec, option, prelude::*}; use crate::{ serialization::{ZcashDeserialize, ZcashSerialize}, types::LockTime, }; use super::*; mod arbitrary; mod test_vectors; impl Transaction { pub fn v1_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), ) .prop_map(|(inputs, outputs, lock_time)| Transaction::V1 { inputs, outputs, lock_time, }) .boxed() } pub fn v2_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), option::of(any::>()), ) .prop_map( |(inputs, outputs, lock_time, joinsplit_data)| Transaction::V2 { inputs, outputs, lock_time, joinsplit_data, }, ) .boxed() } pub fn v3_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), any::(), option::of(any::>()), ) .prop_map( |(inputs, outputs, lock_time, expiry_height, joinsplit_data)| Transaction::V3 { inputs, outputs, lock_time, expiry_height, joinsplit_data, }, ) .boxed() } pub fn v4_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), any::(), any::(), option::of(any::()), option::of(any::>()), ) .prop_map( |( inputs, outputs, lock_time, expiry_height, value_balance, shielded_data, joinsplit_data, )| Transaction::V4 { inputs, outputs, lock_time, expiry_height, value_balance, shielded_data, joinsplit_data, }, ) .boxed() } } #[test] fn librustzcash_tx_deserialize_and_round_trip() { let tx = Transaction::zcash_deserialize(&test_vectors::GENERIC_TESTNET_TX[..]) .expect("transaction test vector from librustzcash should deserialize"); let mut data2 = Vec::new(); tx.zcash_serialize(&mut data2).expect("tx should serialize"); assert_eq!(&test_vectors::GENERIC_TESTNET_TX[..], &data2[..]); } proptest! { #[test] fn transaction_roundtrip(tx in any::()) { let mut data = Vec::new(); tx.zcash_serialize(&mut data).expect("tx should serialize"); let tx2 = Transaction::zcash_deserialize(&data[..]).expect("randomized tx should deserialize"); prop_assert_eq![tx, tx2]; } }