diff --git a/zebra-chain/src/transaction/tests.rs b/zebra-chain/src/transaction/tests.rs index 2c86683a..263a67a8 100644 --- a/zebra-chain/src/transaction/tests.rs +++ b/zebra-chain/src/transaction/tests.rs @@ -1,169 +1,3 @@ -use proptest::{arbitrary::any, collection::vec, option, prelude::*}; - -use crate::{ - serialization::{ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize}, - types::LockTime, -}; - -use super::*; - mod arbitrary; - -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(&zebra_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!(&zebra_test::vectors::GENERIC_TESTNET_TX[..], &data2[..]); -} - -proptest! { - - #[test] - fn transaction_roundtrip(tx in any::()) { - let data = tx.zcash_serialize_to_vec().expect("tx should serialize"); - let tx2 = data.zcash_deserialize_into().expect("randomized tx should deserialize"); - - prop_assert_eq![tx, tx2]; - } -} - -#[test] -fn zip143_deserialize_and_round_trip() { - let tx1 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP143_1[..]) - .expect("transaction test vector from ZIP143 should deserialize"); - - let mut data1 = Vec::new(); - tx1.zcash_serialize(&mut data1) - .expect("tx should serialize"); - - assert_eq!(&zebra_test::vectors::ZIP143_1[..], &data1[..]); - - let tx2 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP143_2[..]) - .expect("transaction test vector from ZIP143 should deserialize"); - - let mut data2 = Vec::new(); - tx2.zcash_serialize(&mut data2) - .expect("tx should serialize"); - - assert_eq!(&zebra_test::vectors::ZIP143_2[..], &data2[..]); -} - -#[test] -fn zip243_deserialize_and_round_trip() { - let tx1 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP243_1[..]) - .expect("transaction test vector from ZIP243 should deserialize"); - - let mut data1 = Vec::new(); - tx1.zcash_serialize(&mut data1) - .expect("tx should serialize"); - - assert_eq!(&zebra_test::vectors::ZIP243_1[..], &data1[..]); - - let tx2 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP243_2[..]) - .expect("transaction test vector from ZIP243 should deserialize"); - - let mut data2 = Vec::new(); - tx2.zcash_serialize(&mut data2) - .expect("tx should serialize"); - - assert_eq!(&zebra_test::vectors::ZIP243_2[..], &data2[..]); - - let tx3 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP243_3[..]) - .expect("transaction test vector from ZIP243 should deserialize"); - - let mut data3 = Vec::new(); - tx3.zcash_serialize(&mut data3) - .expect("tx should serialize"); - - assert_eq!(&zebra_test::vectors::ZIP243_3[..], &data3[..]); -} +mod prop; +mod vectors; diff --git a/zebra-chain/src/transaction/tests/arbitrary.rs b/zebra-chain/src/transaction/tests/arbitrary.rs index da857f4f..f01c848c 100644 --- a/zebra-chain/src/transaction/tests/arbitrary.rs +++ b/zebra-chain/src/transaction/tests/arbitrary.rs @@ -1,17 +1,104 @@ +use futures::future::Either; +use proptest::{arbitrary::any, array, collection::vec, option, prelude::*}; + use crate::{ amount::{Amount, NonNegative}, commitments, keys, notes::{sapling, sprout}, - proofs::{Groth16Proof, ZkSnarkProof}, + proofs::{Bctv14Proof, Groth16Proof, ZkSnarkProof}, transaction::{ CoinbaseData, JoinSplit, JoinSplitData, OutPoint, Output, ShieldedData, Spend, Transaction, - TransparentInput, + TransparentInput, TransparentOutput, }, treestate::{self, note_commitment_tree::SaplingNoteTreeRootHash}, - types::{BlockHeight, Script}, + types::{BlockHeight, LockTime, Script}, }; -use futures::future::Either; -use proptest::{array, collection::vec, prelude::*}; + +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() + } +} impl Arbitrary for JoinSplit

{ type Parameters = (); diff --git a/zebra-chain/src/transaction/tests/prop.rs b/zebra-chain/src/transaction/tests/prop.rs new file mode 100644 index 00000000..ac9e9f6c --- /dev/null +++ b/zebra-chain/src/transaction/tests/prop.rs @@ -0,0 +1,16 @@ +use proptest::prelude::*; + +use super::super::*; + +use crate::serialization::{ZcashDeserializeInto, ZcashSerialize}; + +proptest! { + + #[test] + fn transaction_roundtrip(tx in any::()) { + let data = tx.zcash_serialize_to_vec().expect("tx should serialize"); + let tx2 = data.zcash_deserialize_into().expect("randomized tx should deserialize"); + + prop_assert_eq![tx, tx2]; + } +} diff --git a/zebra-chain/src/transaction/tests/vectors.rs b/zebra-chain/src/transaction/tests/vectors.rs new file mode 100644 index 00000000..0c2af3e2 --- /dev/null +++ b/zebra-chain/src/transaction/tests/vectors.rs @@ -0,0 +1,65 @@ +use super::super::*; + +use crate::serialization::{ZcashDeserialize, ZcashSerialize}; + +#[test] +fn librustzcash_tx_deserialize_and_round_trip() { + let tx = Transaction::zcash_deserialize(&zebra_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!(&zebra_test::vectors::GENERIC_TESTNET_TX[..], &data2[..]); +} + +#[test] +fn zip143_deserialize_and_round_trip() { + let tx1 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP143_1[..]) + .expect("transaction test vector from ZIP143 should deserialize"); + + let mut data1 = Vec::new(); + tx1.zcash_serialize(&mut data1) + .expect("tx should serialize"); + + assert_eq!(&zebra_test::vectors::ZIP143_1[..], &data1[..]); + + let tx2 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP143_2[..]) + .expect("transaction test vector from ZIP143 should deserialize"); + + let mut data2 = Vec::new(); + tx2.zcash_serialize(&mut data2) + .expect("tx should serialize"); + + assert_eq!(&zebra_test::vectors::ZIP143_2[..], &data2[..]); +} + +#[test] +fn zip243_deserialize_and_round_trip() { + let tx1 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP243_1[..]) + .expect("transaction test vector from ZIP243 should deserialize"); + + let mut data1 = Vec::new(); + tx1.zcash_serialize(&mut data1) + .expect("tx should serialize"); + + assert_eq!(&zebra_test::vectors::ZIP243_1[..], &data1[..]); + + let tx2 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP243_2[..]) + .expect("transaction test vector from ZIP243 should deserialize"); + + let mut data2 = Vec::new(); + tx2.zcash_serialize(&mut data2) + .expect("tx should serialize"); + + assert_eq!(&zebra_test::vectors::ZIP243_2[..], &data2[..]); + + let tx3 = Transaction::zcash_deserialize(&zebra_test::vectors::ZIP243_3[..]) + .expect("transaction test vector from ZIP243 should deserialize"); + + let mut data3 = Vec::new(); + tx3.zcash_serialize(&mut data3) + .expect("tx should serialize"); + + assert_eq!(&zebra_test::vectors::ZIP243_3[..], &data3[..]); +}