Test the manual eq impl on sapling::ShieldedData<PerSpend> (#1989)
This commit is contained in:
parent
375c8d8700
commit
f8094cdf5c
|
@ -86,7 +86,11 @@ proptest! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the
|
/// Return the following calculations on `spend`:
|
||||||
|
/// smallest_disallowed_vec_len
|
||||||
|
/// smallest_disallowed_serialized_len
|
||||||
|
/// largest_allowed_vec_len
|
||||||
|
/// largest_allowed_serialized_len
|
||||||
fn spend_max_allocation_is_big_enough<AnchorV>(
|
fn spend_max_allocation_is_big_enough<AnchorV>(
|
||||||
spend: Spend<AnchorV>,
|
spend: Spend<AnchorV>,
|
||||||
) -> (usize, usize, usize, usize)
|
) -> (usize, usize, usize, usize)
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
|
||||||
use super::super::super::transaction::*;
|
|
||||||
use super::super::shielded_data::*;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
block,
|
block,
|
||||||
|
sapling::{self, PerSpendAnchor},
|
||||||
serialization::{ZcashDeserializeInto, ZcashSerialize},
|
serialization::{ZcashDeserializeInto, ZcashSerialize},
|
||||||
|
transaction::{LockTime, Transaction},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use futures::future::Either;
|
||||||
|
|
||||||
proptest! {
|
proptest! {
|
||||||
|
// TODO: generalise this test for `ShieldedData<SharedAnchor>` (#1829)
|
||||||
#[test]
|
#[test]
|
||||||
fn shielded_data_roundtrip(shielded in any::<ShieldedData<PerSpendAnchor>>()) {
|
fn shielded_data_roundtrip(shielded in any::<sapling::ShieldedData<PerSpendAnchor>>()) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
// shielded data doesn't serialize by itself, so we have to stick it in
|
// shielded data doesn't serialize by itself, so we have to stick it in
|
||||||
|
@ -30,9 +32,70 @@ proptest! {
|
||||||
prop_assert_eq![tx, tx_parsed];
|
prop_assert_eq![tx, tx_parsed];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that ShieldedData serialization is equal if `shielded1 == shielded2`
|
/// Check that ShieldedData<PerSpendAnchor> is equal when `first` is swapped
|
||||||
|
/// between a spend and an output
|
||||||
|
//
|
||||||
|
// TODO: generalise this test for `ShieldedData<SharedAnchor>` (#1829)
|
||||||
#[test]
|
#[test]
|
||||||
fn shielded_data_serialize_eq(shielded1 in any::<ShieldedData<PerSpendAnchor>>(), shielded2 in any::<ShieldedData<PerSpendAnchor>>()) {
|
fn shielded_data_per_spend_swap_first_eq(shielded1 in any::<sapling::ShieldedData<PerSpendAnchor>>()) {
|
||||||
|
use Either::*;
|
||||||
|
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
// we need at least one spend and one output to swap them
|
||||||
|
prop_assume!(shielded1.spends().count() > 0 && shielded1.outputs().count() > 0);
|
||||||
|
|
||||||
|
let mut shielded2 = shielded1.clone();
|
||||||
|
let mut spends: Vec<_> = shielded2.spends().cloned().collect();
|
||||||
|
let mut outputs: Vec<_> = shielded2.outputs().cloned().collect();
|
||||||
|
match shielded2.first {
|
||||||
|
Left(_spend) => {
|
||||||
|
shielded2.first = Right(outputs.remove(0));
|
||||||
|
shielded2.rest_outputs = outputs;
|
||||||
|
shielded2.rest_spends = spends;
|
||||||
|
}
|
||||||
|
Right(_output) => {
|
||||||
|
shielded2.first = Left(spends.remove(0));
|
||||||
|
shielded2.rest_spends = spends;
|
||||||
|
shielded2.rest_outputs = outputs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_assert_eq![&shielded1, &shielded2];
|
||||||
|
|
||||||
|
// shielded data doesn't serialize by itself, so we have to stick it in
|
||||||
|
// a transaction
|
||||||
|
let tx1 = Transaction::V4 {
|
||||||
|
inputs: Vec::new(),
|
||||||
|
outputs: Vec::new(),
|
||||||
|
lock_time: LockTime::min_lock_time(),
|
||||||
|
expiry_height: block::Height(0),
|
||||||
|
joinsplit_data: None,
|
||||||
|
sapling_shielded_data: Some(shielded1),
|
||||||
|
};
|
||||||
|
let tx2 = Transaction::V4 {
|
||||||
|
inputs: Vec::new(),
|
||||||
|
outputs: Vec::new(),
|
||||||
|
lock_time: LockTime::min_lock_time(),
|
||||||
|
expiry_height: block::Height(0),
|
||||||
|
joinsplit_data: None,
|
||||||
|
sapling_shielded_data: Some(shielded2),
|
||||||
|
};
|
||||||
|
|
||||||
|
prop_assert_eq![&tx1, &tx2];
|
||||||
|
|
||||||
|
let data1 = tx1.zcash_serialize_to_vec().expect("tx1 should serialize");
|
||||||
|
let data2 = tx2.zcash_serialize_to_vec().expect("tx2 should serialize");
|
||||||
|
|
||||||
|
prop_assert_eq![data1, data2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check that ShieldedData<PerSpendAnchor> serialization is equal if
|
||||||
|
/// `shielded1 == shielded2`
|
||||||
|
//
|
||||||
|
// TODO: generalise this test for `ShieldedData<SharedAnchor>` (#1829)
|
||||||
|
#[test]
|
||||||
|
fn shielded_data_per_spend_serialize_eq(shielded1 in any::<sapling::ShieldedData<PerSpendAnchor>>(), shielded2 in any::<sapling::ShieldedData<PerSpendAnchor>>()) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let shielded_eq = shielded1 == shielded2;
|
let shielded_eq = shielded1 == shielded2;
|
||||||
|
@ -56,6 +119,12 @@ proptest! {
|
||||||
sapling_shielded_data: Some(shielded2),
|
sapling_shielded_data: Some(shielded2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if shielded_eq {
|
||||||
|
prop_assert_eq![&tx1, &tx2];
|
||||||
|
} else {
|
||||||
|
prop_assert_ne![&tx1, &tx2];
|
||||||
|
}
|
||||||
|
|
||||||
let data1 = tx1.zcash_serialize_to_vec().expect("tx1 should serialize");
|
let data1 = tx1.zcash_serialize_to_vec().expect("tx1 should serialize");
|
||||||
let data2 = tx2.zcash_serialize_to_vec().expect("tx2 should serialize");
|
let data2 = tx2.zcash_serialize_to_vec().expect("tx2 should serialize");
|
||||||
|
|
||||||
|
@ -65,4 +134,55 @@ proptest! {
|
||||||
prop_assert_ne![data1, data2];
|
prop_assert_ne![data1, data2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check that ShieldedData<PerSpendAnchor> serialization is equal when we
|
||||||
|
/// replace all the known fields.
|
||||||
|
///
|
||||||
|
/// This test checks for extra fields that are not in `ShieldedData::eq`.
|
||||||
|
//
|
||||||
|
// TODO: generalise this test for `ShieldedData<SharedAnchor>` (#1829)
|
||||||
|
#[test]
|
||||||
|
fn shielded_data_per_spend_field_assign_eq(shielded1 in any::<sapling::ShieldedData<PerSpendAnchor>>(), shielded2 in any::<sapling::ShieldedData<PerSpendAnchor>>()) {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
let mut shielded2 = shielded2;
|
||||||
|
|
||||||
|
// these fields must match ShieldedData::eq
|
||||||
|
// the spends() and outputs() checks cover first, rest_spends, and rest_outputs
|
||||||
|
shielded2.first = shielded1.first.clone();
|
||||||
|
shielded2.rest_spends = shielded1.rest_spends.clone();
|
||||||
|
shielded2.rest_outputs = shielded1.rest_outputs.clone();
|
||||||
|
// now for the fields that are checked literally
|
||||||
|
shielded2.value_balance = shielded1.value_balance;
|
||||||
|
shielded2.shared_anchor = shielded1.shared_anchor;
|
||||||
|
shielded2.binding_sig = shielded1.binding_sig;
|
||||||
|
|
||||||
|
prop_assert_eq![&shielded1, &shielded2];
|
||||||
|
|
||||||
|
// shielded data doesn't serialize by itself, so we have to stick it in
|
||||||
|
// a transaction
|
||||||
|
let tx1 = Transaction::V4 {
|
||||||
|
inputs: Vec::new(),
|
||||||
|
outputs: Vec::new(),
|
||||||
|
lock_time: LockTime::min_lock_time(),
|
||||||
|
expiry_height: block::Height(0),
|
||||||
|
joinsplit_data: None,
|
||||||
|
sapling_shielded_data: Some(shielded1),
|
||||||
|
};
|
||||||
|
let tx2 = Transaction::V4 {
|
||||||
|
inputs: Vec::new(),
|
||||||
|
outputs: Vec::new(),
|
||||||
|
lock_time: LockTime::min_lock_time(),
|
||||||
|
expiry_height: block::Height(0),
|
||||||
|
joinsplit_data: None,
|
||||||
|
sapling_shielded_data: Some(shielded2),
|
||||||
|
};
|
||||||
|
|
||||||
|
prop_assert_eq![&tx1, &tx2];
|
||||||
|
|
||||||
|
let data1 = tx1.zcash_serialize_to_vec().expect("tx1 should serialize");
|
||||||
|
let data2 = tx2.zcash_serialize_to_vec().expect("tx2 should serialize");
|
||||||
|
|
||||||
|
prop_assert_eq![data1, data2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue