rustfmt inside nullifier and utxo proptests (#2515)

* rustfmt inside nullifier and utxo proptests

* Fix a comment typo

* Use a `chain` binding to simplify test assertions
This commit is contained in:
teor 2021-07-26 13:10:24 +10:00 committed by GitHub
parent 064bef62a5
commit a7b0a521d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 292 additions and 289 deletions

View File

@ -52,8 +52,8 @@ proptest! {
/// (And that the test infrastructure generally works.)
#[test]
fn accept_distinct_arbitrary_sprout_nullifiers_in_one_block(
mut joinsplit in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
joinsplit_data in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
mut joinsplit in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
joinsplit_data in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
use_finalized_state in any::<bool>(),
) {
zebra_test::init();
@ -70,9 +70,7 @@ proptest! {
// convert the coinbase transaction to a version that the non-finalized state will accept
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(transaction.into());
block1.transactions.push(transaction.into());
let (mut state, _genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
@ -90,12 +88,15 @@ proptest! {
prop_assert!(state.mem.eq_internal_state(&previous_mem));
// the finalized state has the nullifiers
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[1]));
prop_assert!(state
.disk
.contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state
.disk
.contains_sprout_nullifier(&expected_nullifiers[1]));
} else {
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1.clone());
let commit_result = state.validate_and_commit(block1.clone());
// the block was committed
prop_assert_eq!(commit_result, Ok(()));
@ -106,8 +107,12 @@ proptest! {
// the non-finalized state has the nullifiers
prop_assert_eq!(state.mem.chain_set.len(), 1);
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[1]));
prop_assert!(state
.mem
.best_contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state
.mem
.best_contains_sprout_nullifier(&expected_nullifiers[1]));
}
}
@ -115,8 +120,8 @@ proptest! {
/// if they come from the same JoinSplit.
#[test]
fn reject_duplicate_sprout_nullifiers_in_joinsplit(
mut joinsplit in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
joinsplit_data in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
mut joinsplit in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
joinsplit_data in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
) {
zebra_test::init();
@ -133,27 +138,23 @@ proptest! {
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(transaction.into());
block1.transactions.push(transaction.into());
let (mut state, genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1);
let commit_result = state.validate_and_commit(block1);
// if the random proptest data produces other errors,
// we might need to just check `is_err()` here
prop_assert_eq!(
commit_result,
Err(
DuplicateSproutNullifier {
Err(DuplicateSproutNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: false,
}.into()
)
}
.into())
);
// block was rejected
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
@ -164,9 +165,9 @@ proptest! {
/// if they come from different JoinSplits in the same JoinSplitData/Transaction.
#[test]
fn reject_duplicate_sprout_nullifiers_in_transaction(
mut joinsplit1 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
mut joinsplit2 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
joinsplit_data in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
mut joinsplit1 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
mut joinsplit2 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
joinsplit_data in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
) {
zebra_test::init();
@ -174,38 +175,37 @@ proptest! {
.zcash_deserialize_into::<Block>()
.expect("block should deserialize");
make_distinct_nullifiers(&mut joinsplit1.nullifiers.iter_mut().chain(joinsplit2.nullifiers.iter_mut()));
make_distinct_nullifiers(
&mut joinsplit1
.nullifiers
.iter_mut()
.chain(joinsplit2.nullifiers.iter_mut()),
);
// create a double-spend across two joinsplits
let duplicate_nullifier = joinsplit1.nullifiers[0];
joinsplit2.nullifiers[0] = duplicate_nullifier;
let transaction = transaction_v4_with_joinsplit_data(
joinsplit_data.0,
[joinsplit1.0, joinsplit2.0]
);
let transaction =
transaction_v4_with_joinsplit_data(joinsplit_data.0, [joinsplit1.0, joinsplit2.0]);
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(transaction.into());
block1.transactions.push(transaction.into());
let (mut state, genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1);
let commit_result = state.validate_and_commit(block1);
prop_assert_eq!(
commit_result,
Err(
DuplicateSproutNullifier {
Err(DuplicateSproutNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: false,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -215,10 +215,10 @@ proptest! {
/// if they come from different transactions in the same block.
#[test]
fn reject_duplicate_sprout_nullifiers_in_block(
mut joinsplit1 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
mut joinsplit2 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
joinsplit_data1 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
joinsplit_data2 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
mut joinsplit1 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
mut joinsplit2 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
joinsplit_data1 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
joinsplit_data2 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
) {
zebra_test::init();
@ -226,7 +226,12 @@ proptest! {
.zcash_deserialize_into::<Block>()
.expect("block should deserialize");
make_distinct_nullifiers(&mut joinsplit1.nullifiers.iter_mut().chain(joinsplit2.nullifiers.iter_mut()));
make_distinct_nullifiers(
&mut joinsplit1
.nullifiers
.iter_mut()
.chain(joinsplit2.nullifiers.iter_mut()),
);
// create a double-spend across two transactions
let duplicate_nullifier = joinsplit1.nullifiers[0];
@ -245,17 +250,15 @@ proptest! {
let previous_mem = state.mem.clone();
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1);
let commit_result = state.validate_and_commit(block1);
prop_assert_eq!(
commit_result,
Err(
DuplicateSproutNullifier {
Err(DuplicateSproutNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: false,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -265,10 +268,10 @@ proptest! {
/// if they come from different blocks in the same chain.
#[test]
fn reject_duplicate_sprout_nullifiers_in_chain(
mut joinsplit1 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
mut joinsplit2 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
joinsplit_data1 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
joinsplit_data2 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
mut joinsplit1 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
mut joinsplit2 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
joinsplit_data1 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
joinsplit_data2 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
duplicate_in_finalized_state in any::<bool>(),
) {
zebra_test::init();
@ -280,7 +283,12 @@ proptest! {
.zcash_deserialize_into::<Block>()
.expect("block should deserialize");
make_distinct_nullifiers(&mut joinsplit1.nullifiers.iter_mut().chain(joinsplit2.nullifiers.iter_mut()));
make_distinct_nullifiers(
&mut joinsplit1
.nullifiers
.iter_mut()
.chain(joinsplit2.nullifiers.iter_mut()),
);
let expected_nullifiers = joinsplit1.nullifiers;
// create a double-spend across two blocks
@ -293,12 +301,8 @@ proptest! {
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
block1
.transactions
.push(transaction1.into());
block2
.transactions
.push(transaction2.into());
block1.transactions.push(transaction1.into());
block2.transactions.push(transaction2.into());
let (mut state, _genesis) = new_state_with_mainnet_genesis();
let mut previous_mem = state.mem.clone();
@ -312,37 +316,42 @@ proptest! {
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
prop_assert!(commit_result.is_ok());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[1]));
prop_assert!(state
.disk
.contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state
.disk
.contains_sprout_nullifier(&expected_nullifiers[1]));
block1_hash = block1.hash;
} else {
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1.clone());
let commit_result = state.validate_and_commit(block1.clone());
prop_assert_eq!(commit_result, Ok(()));
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[1]));
prop_assert!(state
.mem
.best_contains_sprout_nullifier(&expected_nullifiers[0]));
prop_assert!(state
.mem
.best_contains_sprout_nullifier(&expected_nullifiers[1]));
block1_hash = block1.hash;
previous_mem = state.mem.clone();
}
let block2 = Arc::new(block2).prepare();
let commit_result =
state.validate_and_commit(block2);
let commit_result = state.validate_and_commit(block2);
prop_assert_eq!(
commit_result,
Err(
DuplicateSproutNullifier {
Err(DuplicateSproutNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: duplicate_in_finalized_state,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -356,8 +365,8 @@ proptest! {
/// (And that the test infrastructure generally works.)
#[test]
fn accept_distinct_arbitrary_sapling_nullifiers_in_one_block(
spend in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
spend in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
use_finalized_state in any::<bool>(),
) {
zebra_test::init();
@ -368,17 +377,13 @@ proptest! {
let expected_nullifier = spend.nullifier;
let transaction = transaction_v4_with_sapling_shielded_data(
sapling_shielded_data.0,
[spend.0]
);
let transaction =
transaction_v4_with_sapling_shielded_data(sapling_shielded_data.0, [spend.0]);
// convert the coinbase transaction to a version that the non-finalized state will accept
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(transaction.into());
block1.transactions.push(transaction.into());
let (mut state, _genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
@ -394,13 +399,14 @@ proptest! {
prop_assert!(state.disk.contains_sapling_nullifier(&expected_nullifier));
} else {
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1.clone());
let commit_result = state.validate_and_commit(block1.clone());
prop_assert_eq!(commit_result, Ok(()));
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
prop_assert!(state.mem.best_contains_sapling_nullifier(&expected_nullifier));
prop_assert!(state
.mem
.best_contains_sapling_nullifier(&expected_nullifier));
}
}
@ -408,9 +414,9 @@ proptest! {
/// if they come from different Spends in the same sapling::ShieldedData/Transaction.
#[test]
fn reject_duplicate_sapling_nullifiers_in_transaction(
spend1 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
mut spend2 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
spend1 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
mut spend2 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
) {
zebra_test::init();
@ -429,25 +435,21 @@ proptest! {
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(transaction.into());
block1.transactions.push(transaction.into());
let (mut state, genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1);
let commit_result = state.validate_and_commit(block1);
prop_assert_eq!(
commit_result,
Err(
DuplicateSaplingNullifier {
Err(DuplicateSaplingNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: false,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -457,10 +459,10 @@ proptest! {
/// if they come from different transactions in the same block.
#[test]
fn reject_duplicate_sapling_nullifiers_in_block(
spend1 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
mut spend2 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data1 in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
spend1 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
mut spend2 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data1 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
) {
zebra_test::init();
@ -472,14 +474,10 @@ proptest! {
let duplicate_nullifier = spend1.nullifier;
spend2.nullifier = duplicate_nullifier;
let transaction1 = transaction_v4_with_sapling_shielded_data(
sapling_shielded_data1.0,
[spend1.0]
);
let transaction2 = transaction_v4_with_sapling_shielded_data(
sapling_shielded_data2.0,
[spend2.0]
);
let transaction1 =
transaction_v4_with_sapling_shielded_data(sapling_shielded_data1.0, [spend1.0]);
let transaction2 =
transaction_v4_with_sapling_shielded_data(sapling_shielded_data2.0, [spend2.0]);
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
@ -491,17 +489,15 @@ proptest! {
let previous_mem = state.mem.clone();
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1);
let commit_result = state.validate_and_commit(block1);
prop_assert_eq!(
commit_result,
Err(
DuplicateSaplingNullifier {
Err(DuplicateSaplingNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: false,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -511,10 +507,10 @@ proptest! {
/// if they come from different blocks in the same chain.
#[test]
fn reject_duplicate_sapling_nullifiers_in_chain(
spend1 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
mut spend2 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data1 in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
spend1 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
mut spend2 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data1 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
duplicate_in_finalized_state in any::<bool>(),
) {
zebra_test::init();
@ -530,24 +526,16 @@ proptest! {
let duplicate_nullifier = spend1.nullifier;
spend2.nullifier = duplicate_nullifier;
let transaction1 = transaction_v4_with_sapling_shielded_data(
sapling_shielded_data1.0,
[spend1.0]
);
let transaction2 = transaction_v4_with_sapling_shielded_data(
sapling_shielded_data2.0,
[spend2.0]
);
let transaction1 =
transaction_v4_with_sapling_shielded_data(sapling_shielded_data1.0, [spend1.0]);
let transaction2 =
transaction_v4_with_sapling_shielded_data(sapling_shielded_data2.0, [spend2.0]);
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
block1
.transactions
.push(transaction1.into());
block2
.transactions
.push(transaction2.into());
block1.transactions.push(transaction1.into());
block2.transactions.push(transaction2.into());
let (mut state, _genesis) = new_state_with_mainnet_genesis();
let mut previous_mem = state.mem.clone();
@ -566,30 +554,29 @@ proptest! {
block1_hash = block1.hash;
} else {
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1.clone());
let commit_result = state.validate_and_commit(block1.clone());
prop_assert_eq!(commit_result, Ok(()));
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
prop_assert!(state.mem.best_contains_sapling_nullifier(&duplicate_nullifier));
prop_assert!(state
.mem
.best_contains_sapling_nullifier(&duplicate_nullifier));
block1_hash = block1.hash;
previous_mem = state.mem.clone();
}
let block2 = Arc::new(block2).prepare();
let commit_result =
state.validate_and_commit(block2);
let commit_result = state.validate_and_commit(block2);
prop_assert_eq!(
commit_result,
Err(
DuplicateSaplingNullifier {
Err(DuplicateSaplingNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: duplicate_in_finalized_state,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -617,15 +604,13 @@ proptest! {
let transaction = transaction_v5_with_orchard_shielded_data(
orchard_shielded_data.0,
[authorized_action.0]
[authorized_action.0],
);
// convert the coinbase transaction to a version that the non-finalized state will accept
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(transaction.into());
block1.transactions.push(transaction.into());
let (mut state, _genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
@ -641,13 +626,14 @@ proptest! {
prop_assert!(state.disk.contains_orchard_nullifier(&expected_nullifier));
} else {
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1.clone());
let commit_result = state.validate_and_commit(block1.clone());
prop_assert_eq!(commit_result, Ok(()));
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
prop_assert!(state.mem.best_contains_orchard_nullifier(&expected_nullifier));
prop_assert!(state
.mem
.best_contains_orchard_nullifier(&expected_nullifier));
}
}
@ -676,25 +662,21 @@ proptest! {
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(transaction.into());
block1.transactions.push(transaction.into());
let (mut state, genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1);
let commit_result = state.validate_and_commit(block1);
prop_assert_eq!(
commit_result,
Err(
DuplicateOrchardNullifier {
Err(DuplicateOrchardNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: false,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -721,11 +703,11 @@ proptest! {
let transaction1 = transaction_v5_with_orchard_shielded_data(
orchard_shielded_data1.0,
[authorized_action1.0]
[authorized_action1.0],
);
let transaction2 = transaction_v5_with_orchard_shielded_data(
orchard_shielded_data2.0,
[authorized_action2.0]
[authorized_action2.0],
);
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
@ -738,17 +720,15 @@ proptest! {
let previous_mem = state.mem.clone();
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1);
let commit_result = state.validate_and_commit(block1);
prop_assert_eq!(
commit_result,
Err(
DuplicateOrchardNullifier {
Err(DuplicateOrchardNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: false,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));
@ -779,22 +759,18 @@ proptest! {
let transaction1 = transaction_v5_with_orchard_shielded_data(
orchard_shielded_data1.0,
[authorized_action1.0]
[authorized_action1.0],
);
let transaction2 = transaction_v5_with_orchard_shielded_data(
orchard_shielded_data2.0,
[authorized_action2.0]
[authorized_action2.0],
);
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
block1
.transactions
.push(transaction1.into());
block2
.transactions
.push(transaction2.into());
block1.transactions.push(transaction1.into());
block2.transactions.push(transaction2.into());
let (mut state, _genesis) = new_state_with_mainnet_genesis();
let mut previous_mem = state.mem.clone();
@ -813,30 +789,29 @@ proptest! {
block1_hash = block1.hash;
} else {
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1.clone());
let commit_result = state.validate_and_commit(block1.clone());
prop_assert_eq!(commit_result, Ok(()));
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
prop_assert!(state.mem.best_contains_orchard_nullifier(&duplicate_nullifier));
prop_assert!(state
.mem
.best_contains_orchard_nullifier(&duplicate_nullifier));
block1_hash = block1.hash;
previous_mem = state.mem.clone();
}
let block2 = Arc::new(block2).prepare();
let commit_result =
state.validate_and_commit(block2);
let commit_result = state.validate_and_commit(block2);
prop_assert_eq!(
commit_result,
Err(
DuplicateOrchardNullifier {
Err(DuplicateOrchardNullifier {
nullifier: duplicate_nullifier,
in_finalized_state: duplicate_in_finalized_state,
}.into()
)
}
.into())
);
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
prop_assert!(state.mem.eq_internal_state(&previous_mem));

View File

@ -66,7 +66,10 @@ proptest! {
let output_transaction = transaction_v4_with_transparent_data([], [output.0]);
// create a spend
let expected_outpoint = transparent::OutPoint { hash: output_transaction.hash(), index: 0 };
let expected_outpoint = transparent::OutPoint {
hash: output_transaction.hash(),
index: 0,
};
prevout_input.set_outpoint(expected_outpoint);
let spend_transaction = transaction_v4_with_transparent_data([prevout_input.0], []);
@ -98,8 +101,7 @@ proptest! {
prop_assert!(state.mem.any_utxo(&expected_outpoint).is_none());
} else {
let block1 = Arc::new(block1).prepare();
let commit_result =
state.validate_and_commit(block1.clone());
let commit_result = state.validate_and_commit(block1.clone());
// the block was committed
prop_assert_eq!(commit_result, Ok(()));
@ -108,11 +110,17 @@ proptest! {
// the block data is in the non-finalized state
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
// the non-finalized state has the spent its own UTXO
// the non-finalized state has created and spent the UTXO
prop_assert_eq!(state.mem.chain_set.len(), 1);
prop_assert!(!state.mem.chain_set.iter().next().unwrap().unspent_utxos().contains_key(&expected_outpoint));
prop_assert!(state.mem.chain_set.iter().next().unwrap().created_utxos.contains_key(&expected_outpoint));
prop_assert!(state.mem.chain_set.iter().next().unwrap().spent_utxos.contains(&expected_outpoint));
let chain = state
.mem
.chain_set
.iter()
.next()
.unwrap();
prop_assert!(!chain.unspent_utxos().contains_key(&expected_outpoint));
prop_assert!(chain.created_utxos.contains_key(&expected_outpoint));
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
// the finalized state does not have the UTXO
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
@ -140,10 +148,15 @@ proptest! {
.zcash_deserialize_into::<Block>()
.expect("block should deserialize");
let TestState { mut state, block1, .. } = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let TestState {
mut state, block1, ..
} = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let previous_mem = state.mem.clone();
let expected_outpoint = transparent::OutPoint { hash: block1.transactions[1].hash(), index: 0 };
let expected_outpoint = transparent::OutPoint {
hash: block1.transactions[1].hash(),
index: 0,
};
prevout_input.set_outpoint(expected_outpoint);
let spend_transaction = transaction_v4_with_transparent_data([prevout_input.0], []);
@ -151,9 +164,7 @@ proptest! {
// convert the coinbase transaction to a version that the non-finalized state will accept
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
block2
.transactions
.push(spend_transaction.into());
block2.transactions.push(spend_transaction.into());
if use_finalized_state_spend {
let block2 = FinalizedBlock::from(Arc::new(block2));
@ -170,8 +181,7 @@ proptest! {
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
} else {
let block2 = Arc::new(block2).prepare();
let commit_result =
state.validate_and_commit(block2.clone());
let commit_result = state.validate_and_commit(block2.clone());
// the block was committed
prop_assert_eq!(commit_result, Ok(()));
@ -182,19 +192,25 @@ proptest! {
// the UTXO is spent
prop_assert_eq!(state.mem.chain_set.len(), 1);
prop_assert!(!state.mem.chain_set.iter().next().unwrap().unspent_utxos().contains_key(&expected_outpoint));
let chain = state
.mem
.chain_set
.iter()
.next()
.unwrap();
prop_assert!(!chain.unspent_utxos().contains_key(&expected_outpoint));
if use_finalized_state_output {
// the chain has spent the UTXO from the finalized state
prop_assert!(!state.mem.chain_set.iter().next().unwrap().created_utxos.contains_key(&expected_outpoint));
prop_assert!(state.mem.chain_set.iter().next().unwrap().spent_utxos.contains(&expected_outpoint));
prop_assert!(!chain.created_utxos.contains_key(&expected_outpoint));
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
// the finalized state has the UTXO, but it will get deleted on commit
prop_assert!(state.disk.utxo(&expected_outpoint).is_some());
} else {
// the chain has spent its own UTXO
prop_assert!(!state.mem.chain_set.iter().next().unwrap().unspent_utxos().contains_key(&expected_outpoint));
prop_assert!(state.mem.chain_set.iter().next().unwrap().created_utxos.contains_key(&expected_outpoint));
prop_assert!(state.mem.chain_set.iter().next().unwrap().spent_utxos.contains(&expected_outpoint));
prop_assert!(!chain.unspent_utxos().contains_key(&expected_outpoint));
prop_assert!(chain.created_utxos.contains_key(&expected_outpoint));
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
// the finalized state does not have the UTXO
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
}
@ -218,11 +234,15 @@ proptest! {
let output_transaction = transaction_v4_with_transparent_data([], [output.0]);
let expected_outpoint = transparent::OutPoint { hash: output_transaction.hash(), index: 0 };
let expected_outpoint = transparent::OutPoint {
hash: output_transaction.hash(),
index: 0,
};
prevout_input1.set_outpoint(expected_outpoint);
prevout_input2.set_outpoint(expected_outpoint);
let spend_transaction = transaction_v4_with_transparent_data([prevout_input1.0, prevout_input2.0], []);
let spend_transaction =
transaction_v4_with_transparent_data([prevout_input1.0, prevout_input2.0], []);
// convert the coinbase transaction to a version that the non-finalized state will accept
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
@ -243,7 +263,8 @@ proptest! {
Err(DuplicateTransparentSpend {
outpoint: expected_outpoint,
location: "the same block",
}.into())
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
@ -270,21 +291,25 @@ proptest! {
.zcash_deserialize_into::<Block>()
.expect("block should deserialize");
let TestState { mut state, block1, .. } = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let TestState {
mut state, block1, ..
} = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let previous_mem = state.mem.clone();
let expected_outpoint = transparent::OutPoint { hash: block1.transactions[1].hash(), index: 0 };
let expected_outpoint = transparent::OutPoint {
hash: block1.transactions[1].hash(),
index: 0,
};
prevout_input1.set_outpoint(expected_outpoint);
prevout_input2.set_outpoint(expected_outpoint);
let spend_transaction = transaction_v4_with_transparent_data([prevout_input1.0, prevout_input2.0], []);
let spend_transaction =
transaction_v4_with_transparent_data([prevout_input1.0, prevout_input2.0], []);
// convert the coinbase transaction to a version that the non-finalized state will accept
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
block2
.transactions
.push(spend_transaction.into());
block2.transactions.push(spend_transaction.into());
let block2 = Arc::new(block2).prepare();
let commit_result = state.validate_and_commit(block2);
@ -295,7 +320,8 @@ proptest! {
Err(DuplicateTransparentSpend {
outpoint: expected_outpoint,
location: "the same block",
}.into())
}
.into())
);
prop_assert_eq!(Some((Height(1), block1.hash())), state.best_tip());
@ -308,8 +334,14 @@ proptest! {
// the non-finalized state has no chains (so it can't have the UTXO)
prop_assert!(state.mem.chain_set.iter().next().is_none());
} else {
let chain = state
.mem
.chain_set
.iter()
.next()
.unwrap();
// the non-finalized state has the UTXO
prop_assert!(state.mem.chain_set.iter().next().unwrap().unspent_utxos().contains_key(&expected_outpoint));
prop_assert!(chain.unspent_utxos().contains_key(&expected_outpoint));
// the finalized state does not have the UTXO
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
}
@ -332,10 +364,15 @@ proptest! {
.zcash_deserialize_into::<Block>()
.expect("block should deserialize");
let TestState { mut state, block1, .. } = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let TestState {
mut state, block1, ..
} = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let previous_mem = state.mem.clone();
let expected_outpoint = transparent::OutPoint { hash: block1.transactions[1].hash(), index: 0 };
let expected_outpoint = transparent::OutPoint {
hash: block1.transactions[1].hash(),
index: 0,
};
prevout_input1.set_outpoint(expected_outpoint);
prevout_input2.set_outpoint(expected_outpoint);
@ -358,7 +395,8 @@ proptest! {
Err(DuplicateTransparentSpend {
outpoint: expected_outpoint,
location: "the same block",
}.into())
}
.into())
);
prop_assert_eq!(Some((Height(1), block1.hash())), state.best_tip());
@ -371,8 +409,14 @@ proptest! {
// the non-finalized state has no chains (so it can't have the UTXO)
prop_assert!(state.mem.chain_set.iter().next().is_none());
} else {
let chain = state
.mem
.chain_set
.iter()
.next()
.unwrap();
// the non-finalized state has the UTXO
prop_assert!(state.mem.chain_set.iter().next().unwrap().unspent_utxos().contains_key(&expected_outpoint));
prop_assert!(chain.unspent_utxos().contains_key(&expected_outpoint));
// the finalized state does not have the UTXO
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
}
@ -405,10 +449,15 @@ proptest! {
.zcash_deserialize_into::<Block>()
.expect("block should deserialize");
let TestState { mut state, block1, .. } = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let TestState {
mut state, block1, ..
} = new_state_with_mainnet_transparent_data([], [output.0], use_finalized_state_output);
let mut previous_mem = state.mem.clone();
let expected_outpoint = transparent::OutPoint { hash: block1.transactions[1].hash(), index: 0 };
let expected_outpoint = transparent::OutPoint {
hash: block1.transactions[1].hash(),
index: 0,
};
prevout_input1.set_outpoint(expected_outpoint);
prevout_input2.set_outpoint(expected_outpoint);
@ -419,12 +468,8 @@ proptest! {
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
block3.transactions[0] = transaction_v4_from_coinbase(&block3.transactions[0]).into();
block2
.transactions
.push(spend_transaction1.into());
block3
.transactions
.push(spend_transaction2.into());
block2.transactions.push(spend_transaction1.into());
block3.transactions.push(spend_transaction2.into());
let block2 = Arc::new(block2);
@ -455,45 +500,23 @@ proptest! {
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
prop_assert_eq!(state.mem.chain_set.len(), 1);
let chain = state
.mem
.chain_set
.iter()
.next()
.unwrap();
if use_finalized_state_output {
// the finalized state has the unspent UTXO
prop_assert!(state.disk.utxo(&expected_outpoint).is_some());
// the non-finalized state has spent the UTXO
prop_assert!(state
.mem
.chain_set
.iter()
.next()
.unwrap()
.spent_utxos
.contains(&expected_outpoint));
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
} else {
// the non-finalized state has created and spent the UTXO
prop_assert!(!state
.mem
.chain_set
.iter()
.next()
.unwrap()
.unspent_utxos()
.contains_key(&expected_outpoint));
prop_assert!(state
.mem
.chain_set
.iter()
.next()
.unwrap()
.created_utxos
.contains_key(&expected_outpoint));
prop_assert!(state
.mem
.chain_set
.iter()
.next()
.unwrap()
.spent_utxos
.contains(&expected_outpoint));
prop_assert!(!chain.unspent_utxos().contains_key(&expected_outpoint));
prop_assert!(chain.created_utxos.contains_key(&expected_outpoint));
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
// the finalized state does not have the UTXO
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
}
@ -511,7 +534,8 @@ proptest! {
Err(MissingTransparentOutput {
outpoint: expected_outpoint,
location: "the non-finalized and finalized chain",
}.into())
}
.into())
);
} else {
prop_assert_eq!(
@ -519,7 +543,8 @@ proptest! {
Err(DuplicateTransparentSpend {
outpoint: expected_outpoint,
location: "the non-finalized chain",
}.into())
}
.into())
);
}
prop_assert_eq!(Some((Height(2), block2.hash())), state.best_tip());
@ -560,9 +585,7 @@ proptest! {
// convert the coinbase transaction to a version that the non-finalized state will accept
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
block1
.transactions
.push(spend_transaction.into());
block1.transactions.push(spend_transaction.into());
let (mut state, genesis) = new_state_with_mainnet_genesis();
let previous_mem = state.mem.clone();
@ -576,7 +599,8 @@ proptest! {
Err(MissingTransparentOutput {
outpoint: expected_outpoint,
location: "the non-finalized and finalized chain",
}.into())
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
@ -607,7 +631,10 @@ proptest! {
let output_transaction = transaction_v4_with_transparent_data([], [output.0]);
// create a spend
let expected_outpoint = transparent::OutPoint { hash: output_transaction.hash(), index: 0 };
let expected_outpoint = transparent::OutPoint {
hash: output_transaction.hash(),
index: 0,
};
prevout_input.set_outpoint(expected_outpoint);
let spend_transaction = transaction_v4_with_transparent_data([prevout_input.0], []);
@ -630,7 +657,8 @@ proptest! {
commit_result,
Err(EarlyTransparentSpend {
outpoint: expected_outpoint,
}.into())
}
.into())
);
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());