diff --git a/zebra-chain/src/transaction/tests.rs b/zebra-chain/src/transaction/tests.rs index c6f5e195..15d06b01 100644 --- a/zebra-chain/src/transaction/tests.rs +++ b/zebra-chain/src/transaction/tests.rs @@ -1,7 +1,40 @@ -use crate::serialization::{ZcashDeserialize, ZcashSerialize}; +use std::io::Cursor; + +use chrono::{TimeZone, Utc}; + +use proptest::{ + collection::{vec, SizeRange}, + option, + prelude::*, +}; + +use crate::{ + serialization::{ZcashDeserialize, ZcashSerialize}, + types::LockTime, +}; use super::*; +impl Arbitrary for Transaction { + type Parameters = (); + + fn arbitrary_with(_args: ()) -> Self::Strategy { + ( + vec(any::(), 0..10), + vec(any::(), 0..10), + any::(), + ) + .prop_map(|(inputs, outputs, lock_time)| Transaction::V1 { + inputs: inputs, + outputs: outputs, + lock_time: lock_time, + }) + .boxed() + } + + type Strategy = BoxedStrategy; +} + #[test] fn librustzcash_tx_deserialize_and_round_trip() { // Copied from librustzcash @@ -154,3 +187,28 @@ fn librustzcash_tx_deserialize_and_round_trip() { assert_eq!(&data[..], &data2[..]); } + +#[cfg(test)] +proptest! { + + #[test] + fn transaction_roundtrip(mut random in vec(any::(), 1982)) { + + // Standard header and version group id. + let mut data = vec![0x04, 0x00, 0x00, 0x80, 0x85, 0x20, 0x2f, 0x89]; + data.append(&mut random); + + // println!("{:?}", data); + + let tx = Transaction::zcash_deserialize(&data[..]).expect("randomized tx should deserialize"); + + println!("{:?}", tx); + + let mut data2 = Vec::new(); + tx.zcash_serialize(&mut data2).expect("tx should serialize"); + + assert_ne!(&data[..], &data2[..]); + + prop_assert_ne![data, data2]; + } +} diff --git a/zebra-chain/src/types.rs b/zebra-chain/src/types.rs index 53943324..36519905 100644 --- a/zebra-chain/src/types.rs +++ b/zebra-chain/src/types.rs @@ -9,6 +9,8 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use chrono::{DateTime, TimeZone, Utc}; use hex; #[cfg(test)] +use proptest::prelude::*; +#[cfg(test)] use proptest_derive::Arbitrary; use crate::serialization::{ @@ -83,6 +85,23 @@ impl ZcashDeserialize for LockTime { } } +#[cfg(test)] +impl Arbitrary for LockTime { + type Parameters = (); + + fn arbitrary_with(_args: ()) -> Self::Strategy { + prop_oneof![ + (0u32..500_000_000_u32).prop_map(|n| LockTime::Height(BlockHeight(n))), + Just(LockTime::Time( + Utc.timestamp(Utc::now().timestamp() as i64, 0) + )) + ] + .boxed() + } + + type Strategy = BoxedStrategy; +} + /// An encoding of a Bitcoin script. #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(test, derive(Arbitrary))] @@ -129,31 +148,31 @@ mod tests { } #[cfg(test)] -mod proptest { +mod proptests { use std::io::Cursor; - use chrono::{TimeZone, Utc}; use proptest::prelude::*; + use proptest_derive::Arbitrary; use super::{BlockHeight, LockTime, Script}; use crate::serialization::{ZcashDeserialize, ZcashSerialize}; - impl Arbitrary for LockTime { - type Parameters = (); + // impl Arbitrary for LockTime { + // type Parameters = (); - fn arbitrary_with(_args: ()) -> Self::Strategy { - prop_oneof![ - (0u32..500_000_000_u32).prop_map(|n| LockTime::Height(BlockHeight(n))), - Just(LockTime::Time( - Utc.timestamp(Utc::now().timestamp() as i64, 0) - )) - ] - .boxed() - } + // fn arbitrary_with(_args: ()) -> Self::Strategy { + // prop_oneof![ + // (0u32..500_000_000_u32).prop_map(|n| LockTime::Height(BlockHeight(n))), + // Just(LockTime::Time( + // Utc.timestamp(Utc::now().timestamp() as i64, 0) + // )) + // ] + // .boxed() + // } - type Strategy = BoxedStrategy; - } + // type Strategy = BoxedStrategy; + // } proptest! {