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:
parent
064bef62a5
commit
a7b0a521d5
|
|
@ -52,8 +52,8 @@ proptest! {
|
||||||
/// (And that the test infrastructure generally works.)
|
/// (And that the test infrastructure generally works.)
|
||||||
#[test]
|
#[test]
|
||||||
fn accept_distinct_arbitrary_sprout_nullifiers_in_one_block(
|
fn accept_distinct_arbitrary_sprout_nullifiers_in_one_block(
|
||||||
mut joinsplit in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
joinsplit_data in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
|
joinsplit_data in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
|
||||||
use_finalized_state in any::<bool>(),
|
use_finalized_state in any::<bool>(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
@ -70,9 +70,7 @@ proptest! {
|
||||||
// convert the coinbase transaction to a version that the non-finalized state will accept
|
// 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[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction.into());
|
||||||
.transactions
|
|
||||||
.push(transaction.into());
|
|
||||||
|
|
||||||
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
@ -90,12 +88,15 @@ proptest! {
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
||||||
// the finalized state has the nullifiers
|
// the finalized state has the nullifiers
|
||||||
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[0]));
|
prop_assert!(state
|
||||||
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[1]));
|
.disk
|
||||||
|
.contains_sprout_nullifier(&expected_nullifiers[0]));
|
||||||
|
prop_assert!(state
|
||||||
|
.disk
|
||||||
|
.contains_sprout_nullifier(&expected_nullifiers[1]));
|
||||||
} else {
|
} else {
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1.clone());
|
||||||
state.validate_and_commit(block1.clone());
|
|
||||||
|
|
||||||
// the block was committed
|
// the block was committed
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
|
|
@ -106,8 +107,12 @@ proptest! {
|
||||||
|
|
||||||
// the non-finalized state has the nullifiers
|
// the non-finalized state has the nullifiers
|
||||||
prop_assert_eq!(state.mem.chain_set.len(), 1);
|
prop_assert_eq!(state.mem.chain_set.len(), 1);
|
||||||
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[0]));
|
prop_assert!(state
|
||||||
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[1]));
|
.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.
|
/// if they come from the same JoinSplit.
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_duplicate_sprout_nullifiers_in_joinsplit(
|
fn reject_duplicate_sprout_nullifiers_in_joinsplit(
|
||||||
mut joinsplit in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
joinsplit_data in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
|
joinsplit_data in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
|
|
@ -133,27 +138,23 @@ proptest! {
|
||||||
|
|
||||||
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction.into());
|
||||||
.transactions
|
|
||||||
.push(transaction.into());
|
|
||||||
|
|
||||||
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1);
|
||||||
state.validate_and_commit(block1);
|
|
||||||
|
|
||||||
// if the random proptest data produces other errors,
|
// if the random proptest data produces other errors,
|
||||||
// we might need to just check `is_err()` here
|
// we might need to just check `is_err()` here
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateSproutNullifier {
|
||||||
DuplicateSproutNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: false,
|
in_finalized_state: false,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
// block was rejected
|
// block was rejected
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
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.
|
/// if they come from different JoinSplits in the same JoinSplitData/Transaction.
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_duplicate_sprout_nullifiers_in_transaction(
|
fn reject_duplicate_sprout_nullifiers_in_transaction(
|
||||||
mut joinsplit1 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit1 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
mut joinsplit2 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit2 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
joinsplit_data in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
|
joinsplit_data in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
|
|
@ -174,38 +175,37 @@ proptest! {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block should deserialize");
|
.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
|
// create a double-spend across two joinsplits
|
||||||
let duplicate_nullifier = joinsplit1.nullifiers[0];
|
let duplicate_nullifier = joinsplit1.nullifiers[0];
|
||||||
joinsplit2.nullifiers[0] = duplicate_nullifier;
|
joinsplit2.nullifiers[0] = duplicate_nullifier;
|
||||||
|
|
||||||
let transaction = transaction_v4_with_joinsplit_data(
|
let transaction =
|
||||||
joinsplit_data.0,
|
transaction_v4_with_joinsplit_data(joinsplit_data.0, [joinsplit1.0, joinsplit2.0]);
|
||||||
[joinsplit1.0, joinsplit2.0]
|
|
||||||
);
|
|
||||||
|
|
||||||
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction.into());
|
||||||
.transactions
|
|
||||||
.push(transaction.into());
|
|
||||||
|
|
||||||
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1);
|
||||||
state.validate_and_commit(block1);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateSproutNullifier {
|
||||||
DuplicateSproutNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: false,
|
in_finalized_state: false,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -215,10 +215,10 @@ proptest! {
|
||||||
/// if they come from different transactions in the same block.
|
/// if they come from different transactions in the same block.
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_duplicate_sprout_nullifiers_in_block(
|
fn reject_duplicate_sprout_nullifiers_in_block(
|
||||||
mut joinsplit1 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit1 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
mut joinsplit2 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit2 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
joinsplit_data1 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
|
joinsplit_data1 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
|
||||||
joinsplit_data2 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
|
joinsplit_data2 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
|
|
@ -226,7 +226,12 @@ proptest! {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block should deserialize");
|
.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
|
// create a double-spend across two transactions
|
||||||
let duplicate_nullifier = joinsplit1.nullifiers[0];
|
let duplicate_nullifier = joinsplit1.nullifiers[0];
|
||||||
|
|
@ -245,17 +250,15 @@ proptest! {
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1);
|
||||||
state.validate_and_commit(block1);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateSproutNullifier {
|
||||||
DuplicateSproutNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: false,
|
in_finalized_state: false,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -265,10 +268,10 @@ proptest! {
|
||||||
/// if they come from different blocks in the same chain.
|
/// if they come from different blocks in the same chain.
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_duplicate_sprout_nullifiers_in_chain(
|
fn reject_duplicate_sprout_nullifiers_in_chain(
|
||||||
mut joinsplit1 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit1 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
mut joinsplit2 in TypeNameToDebug::<JoinSplit::<Groth16Proof>>::arbitrary(),
|
mut joinsplit2 in TypeNameToDebug::<JoinSplit<Groth16Proof>>::arbitrary(),
|
||||||
joinsplit_data1 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
|
joinsplit_data1 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
|
||||||
joinsplit_data2 in TypeNameToDebug::<JoinSplitData::<Groth16Proof>>::arbitrary(),
|
joinsplit_data2 in TypeNameToDebug::<JoinSplitData<Groth16Proof>>::arbitrary(),
|
||||||
duplicate_in_finalized_state in any::<bool>(),
|
duplicate_in_finalized_state in any::<bool>(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
@ -280,7 +283,12 @@ proptest! {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block should deserialize");
|
.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;
|
let expected_nullifiers = joinsplit1.nullifiers;
|
||||||
|
|
||||||
// create a double-spend across two blocks
|
// create a double-spend across two blocks
|
||||||
|
|
@ -293,12 +301,8 @@ proptest! {
|
||||||
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction1.into());
|
||||||
.transactions
|
block2.transactions.push(transaction2.into());
|
||||||
.push(transaction1.into());
|
|
||||||
block2
|
|
||||||
.transactions
|
|
||||||
.push(transaction2.into());
|
|
||||||
|
|
||||||
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
||||||
let mut previous_mem = state.mem.clone();
|
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_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
||||||
prop_assert!(commit_result.is_ok());
|
prop_assert!(commit_result.is_ok());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[0]));
|
prop_assert!(state
|
||||||
prop_assert!(state.disk.contains_sprout_nullifier(&expected_nullifiers[1]));
|
.disk
|
||||||
|
.contains_sprout_nullifier(&expected_nullifiers[0]));
|
||||||
|
prop_assert!(state
|
||||||
|
.disk
|
||||||
|
.contains_sprout_nullifier(&expected_nullifiers[1]));
|
||||||
|
|
||||||
block1_hash = block1.hash;
|
block1_hash = block1.hash;
|
||||||
} else {
|
} else {
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1.clone());
|
||||||
state.validate_and_commit(block1.clone());
|
|
||||||
|
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
||||||
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
||||||
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[0]));
|
prop_assert!(state
|
||||||
prop_assert!(state.mem.best_contains_sprout_nullifier(&expected_nullifiers[1]));
|
.mem
|
||||||
|
.best_contains_sprout_nullifier(&expected_nullifiers[0]));
|
||||||
|
prop_assert!(state
|
||||||
|
.mem
|
||||||
|
.best_contains_sprout_nullifier(&expected_nullifiers[1]));
|
||||||
|
|
||||||
block1_hash = block1.hash;
|
block1_hash = block1.hash;
|
||||||
previous_mem = state.mem.clone();
|
previous_mem = state.mem.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let block2 = Arc::new(block2).prepare();
|
let block2 = Arc::new(block2).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block2);
|
||||||
state.validate_and_commit(block2);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateSproutNullifier {
|
||||||
DuplicateSproutNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: duplicate_in_finalized_state,
|
in_finalized_state: duplicate_in_finalized_state,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -356,8 +365,8 @@ proptest! {
|
||||||
/// (And that the test infrastructure generally works.)
|
/// (And that the test infrastructure generally works.)
|
||||||
#[test]
|
#[test]
|
||||||
fn accept_distinct_arbitrary_sapling_nullifiers_in_one_block(
|
fn accept_distinct_arbitrary_sapling_nullifiers_in_one_block(
|
||||||
spend in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
|
spend in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
|
||||||
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
|
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
|
||||||
use_finalized_state in any::<bool>(),
|
use_finalized_state in any::<bool>(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
@ -368,17 +377,13 @@ proptest! {
|
||||||
|
|
||||||
let expected_nullifier = spend.nullifier;
|
let expected_nullifier = spend.nullifier;
|
||||||
|
|
||||||
let transaction = transaction_v4_with_sapling_shielded_data(
|
let transaction =
|
||||||
sapling_shielded_data.0,
|
transaction_v4_with_sapling_shielded_data(sapling_shielded_data.0, [spend.0]);
|
||||||
[spend.0]
|
|
||||||
);
|
|
||||||
|
|
||||||
// convert the coinbase transaction to a version that the non-finalized state will accept
|
// 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[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction.into());
|
||||||
.transactions
|
|
||||||
.push(transaction.into());
|
|
||||||
|
|
||||||
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
@ -394,13 +399,14 @@ proptest! {
|
||||||
prop_assert!(state.disk.contains_sapling_nullifier(&expected_nullifier));
|
prop_assert!(state.disk.contains_sapling_nullifier(&expected_nullifier));
|
||||||
} else {
|
} else {
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1.clone());
|
||||||
state.validate_and_commit(block1.clone());
|
|
||||||
|
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
||||||
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
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.
|
/// if they come from different Spends in the same sapling::ShieldedData/Transaction.
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_duplicate_sapling_nullifiers_in_transaction(
|
fn reject_duplicate_sapling_nullifiers_in_transaction(
|
||||||
spend1 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
|
spend1 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
|
||||||
mut spend2 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
|
mut spend2 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
|
||||||
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
|
sapling_shielded_data in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
|
|
@ -429,25 +435,21 @@ proptest! {
|
||||||
|
|
||||||
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction.into());
|
||||||
.transactions
|
|
||||||
.push(transaction.into());
|
|
||||||
|
|
||||||
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1);
|
||||||
state.validate_and_commit(block1);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateSaplingNullifier {
|
||||||
DuplicateSaplingNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: false,
|
in_finalized_state: false,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -457,10 +459,10 @@ proptest! {
|
||||||
/// if they come from different transactions in the same block.
|
/// if they come from different transactions in the same block.
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_duplicate_sapling_nullifiers_in_block(
|
fn reject_duplicate_sapling_nullifiers_in_block(
|
||||||
spend1 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
|
spend1 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
|
||||||
mut spend2 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_data1 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
|
||||||
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
|
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
|
|
@ -472,14 +474,10 @@ proptest! {
|
||||||
let duplicate_nullifier = spend1.nullifier;
|
let duplicate_nullifier = spend1.nullifier;
|
||||||
spend2.nullifier = duplicate_nullifier;
|
spend2.nullifier = duplicate_nullifier;
|
||||||
|
|
||||||
let transaction1 = transaction_v4_with_sapling_shielded_data(
|
let transaction1 =
|
||||||
sapling_shielded_data1.0,
|
transaction_v4_with_sapling_shielded_data(sapling_shielded_data1.0, [spend1.0]);
|
||||||
[spend1.0]
|
let transaction2 =
|
||||||
);
|
transaction_v4_with_sapling_shielded_data(sapling_shielded_data2.0, [spend2.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();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
|
|
@ -491,17 +489,15 @@ proptest! {
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1);
|
||||||
state.validate_and_commit(block1);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateSaplingNullifier {
|
||||||
DuplicateSaplingNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: false,
|
in_finalized_state: false,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -511,10 +507,10 @@ proptest! {
|
||||||
/// if they come from different blocks in the same chain.
|
/// if they come from different blocks in the same chain.
|
||||||
#[test]
|
#[test]
|
||||||
fn reject_duplicate_sapling_nullifiers_in_chain(
|
fn reject_duplicate_sapling_nullifiers_in_chain(
|
||||||
spend1 in TypeNameToDebug::<sapling::Spend::<PerSpendAnchor>>::arbitrary(),
|
spend1 in TypeNameToDebug::<sapling::Spend<PerSpendAnchor>>::arbitrary(),
|
||||||
mut spend2 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_data1 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
|
||||||
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData::<PerSpendAnchor>>::arbitrary(),
|
sapling_shielded_data2 in TypeNameToDebug::<sapling::ShieldedData<PerSpendAnchor>>::arbitrary(),
|
||||||
duplicate_in_finalized_state in any::<bool>(),
|
duplicate_in_finalized_state in any::<bool>(),
|
||||||
) {
|
) {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
@ -530,24 +526,16 @@ proptest! {
|
||||||
let duplicate_nullifier = spend1.nullifier;
|
let duplicate_nullifier = spend1.nullifier;
|
||||||
spend2.nullifier = duplicate_nullifier;
|
spend2.nullifier = duplicate_nullifier;
|
||||||
|
|
||||||
let transaction1 = transaction_v4_with_sapling_shielded_data(
|
let transaction1 =
|
||||||
sapling_shielded_data1.0,
|
transaction_v4_with_sapling_shielded_data(sapling_shielded_data1.0, [spend1.0]);
|
||||||
[spend1.0]
|
let transaction2 =
|
||||||
);
|
transaction_v4_with_sapling_shielded_data(sapling_shielded_data2.0, [spend2.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();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction1.into());
|
||||||
.transactions
|
block2.transactions.push(transaction2.into());
|
||||||
.push(transaction1.into());
|
|
||||||
block2
|
|
||||||
.transactions
|
|
||||||
.push(transaction2.into());
|
|
||||||
|
|
||||||
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
||||||
let mut previous_mem = state.mem.clone();
|
let mut previous_mem = state.mem.clone();
|
||||||
|
|
@ -566,30 +554,29 @@ proptest! {
|
||||||
block1_hash = block1.hash;
|
block1_hash = block1.hash;
|
||||||
} else {
|
} else {
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1.clone());
|
||||||
state.validate_and_commit(block1.clone());
|
|
||||||
|
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
||||||
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
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;
|
block1_hash = block1.hash;
|
||||||
previous_mem = state.mem.clone();
|
previous_mem = state.mem.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let block2 = Arc::new(block2).prepare();
|
let block2 = Arc::new(block2).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block2);
|
||||||
state.validate_and_commit(block2);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateSaplingNullifier {
|
||||||
DuplicateSaplingNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: duplicate_in_finalized_state,
|
in_finalized_state: duplicate_in_finalized_state,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -617,15 +604,13 @@ proptest! {
|
||||||
|
|
||||||
let transaction = transaction_v5_with_orchard_shielded_data(
|
let transaction = transaction_v5_with_orchard_shielded_data(
|
||||||
orchard_shielded_data.0,
|
orchard_shielded_data.0,
|
||||||
[authorized_action.0]
|
[authorized_action.0],
|
||||||
);
|
);
|
||||||
|
|
||||||
// convert the coinbase transaction to a version that the non-finalized state will accept
|
// 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[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction.into());
|
||||||
.transactions
|
|
||||||
.push(transaction.into());
|
|
||||||
|
|
||||||
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
@ -641,13 +626,14 @@ proptest! {
|
||||||
prop_assert!(state.disk.contains_orchard_nullifier(&expected_nullifier));
|
prop_assert!(state.disk.contains_orchard_nullifier(&expected_nullifier));
|
||||||
} else {
|
} else {
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1.clone());
|
||||||
state.validate_and_commit(block1.clone());
|
|
||||||
|
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
||||||
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
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[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction.into());
|
||||||
.transactions
|
|
||||||
.push(transaction.into());
|
|
||||||
|
|
||||||
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1);
|
||||||
state.validate_and_commit(block1);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateOrchardNullifier {
|
||||||
DuplicateOrchardNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: false,
|
in_finalized_state: false,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -721,11 +703,11 @@ proptest! {
|
||||||
|
|
||||||
let transaction1 = transaction_v5_with_orchard_shielded_data(
|
let transaction1 = transaction_v5_with_orchard_shielded_data(
|
||||||
orchard_shielded_data1.0,
|
orchard_shielded_data1.0,
|
||||||
[authorized_action1.0]
|
[authorized_action1.0],
|
||||||
);
|
);
|
||||||
let transaction2 = transaction_v5_with_orchard_shielded_data(
|
let transaction2 = transaction_v5_with_orchard_shielded_data(
|
||||||
orchard_shielded_data2.0,
|
orchard_shielded_data2.0,
|
||||||
[authorized_action2.0]
|
[authorized_action2.0],
|
||||||
);
|
);
|
||||||
|
|
||||||
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
@ -738,17 +720,15 @@ proptest! {
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1);
|
||||||
state.validate_and_commit(block1);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateOrchardNullifier {
|
||||||
DuplicateOrchardNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: false,
|
in_finalized_state: false,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
@ -779,22 +759,18 @@ proptest! {
|
||||||
|
|
||||||
let transaction1 = transaction_v5_with_orchard_shielded_data(
|
let transaction1 = transaction_v5_with_orchard_shielded_data(
|
||||||
orchard_shielded_data1.0,
|
orchard_shielded_data1.0,
|
||||||
[authorized_action1.0]
|
[authorized_action1.0],
|
||||||
);
|
);
|
||||||
let transaction2 = transaction_v5_with_orchard_shielded_data(
|
let transaction2 = transaction_v5_with_orchard_shielded_data(
|
||||||
orchard_shielded_data2.0,
|
orchard_shielded_data2.0,
|
||||||
[authorized_action2.0]
|
[authorized_action2.0],
|
||||||
);
|
);
|
||||||
|
|
||||||
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
block1.transactions[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(transaction1.into());
|
||||||
.transactions
|
block2.transactions.push(transaction2.into());
|
||||||
.push(transaction1.into());
|
|
||||||
block2
|
|
||||||
.transactions
|
|
||||||
.push(transaction2.into());
|
|
||||||
|
|
||||||
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
let (mut state, _genesis) = new_state_with_mainnet_genesis();
|
||||||
let mut previous_mem = state.mem.clone();
|
let mut previous_mem = state.mem.clone();
|
||||||
|
|
@ -813,30 +789,29 @@ proptest! {
|
||||||
block1_hash = block1.hash;
|
block1_hash = block1.hash;
|
||||||
} else {
|
} else {
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1.clone());
|
||||||
state.validate_and_commit(block1.clone());
|
|
||||||
|
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1.hash)), state.best_tip());
|
||||||
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
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;
|
block1_hash = block1.hash;
|
||||||
previous_mem = state.mem.clone();
|
previous_mem = state.mem.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let block2 = Arc::new(block2).prepare();
|
let block2 = Arc::new(block2).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block2);
|
||||||
state.validate_and_commit(block2);
|
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(
|
Err(DuplicateOrchardNullifier {
|
||||||
DuplicateOrchardNullifier {
|
|
||||||
nullifier: duplicate_nullifier,
|
nullifier: duplicate_nullifier,
|
||||||
in_finalized_state: duplicate_in_finalized_state,
|
in_finalized_state: duplicate_in_finalized_state,
|
||||||
}.into()
|
}
|
||||||
)
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(1), block1_hash)), state.best_tip());
|
||||||
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,10 @@ proptest! {
|
||||||
let output_transaction = transaction_v4_with_transparent_data([], [output.0]);
|
let output_transaction = transaction_v4_with_transparent_data([], [output.0]);
|
||||||
|
|
||||||
// create a spend
|
// 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);
|
prevout_input.set_outpoint(expected_outpoint);
|
||||||
let spend_transaction = transaction_v4_with_transparent_data([prevout_input.0], []);
|
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());
|
prop_assert!(state.mem.any_utxo(&expected_outpoint).is_none());
|
||||||
} else {
|
} else {
|
||||||
let block1 = Arc::new(block1).prepare();
|
let block1 = Arc::new(block1).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block1.clone());
|
||||||
state.validate_and_commit(block1.clone());
|
|
||||||
|
|
||||||
// the block was committed
|
// the block was committed
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
|
|
@ -108,11 +110,17 @@ proptest! {
|
||||||
// the block data is in the non-finalized state
|
// the block data is in the non-finalized state
|
||||||
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
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_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
|
||||||
prop_assert!(state.mem.chain_set.iter().next().unwrap().created_utxos.contains_key(&expected_outpoint));
|
.mem
|
||||||
prop_assert!(state.mem.chain_set.iter().next().unwrap().spent_utxos.contains(&expected_outpoint));
|
.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
|
// the finalized state does not have the UTXO
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
||||||
|
|
@ -140,10 +148,15 @@ proptest! {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block should deserialize");
|
.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 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);
|
prevout_input.set_outpoint(expected_outpoint);
|
||||||
|
|
||||||
let spend_transaction = transaction_v4_with_transparent_data([prevout_input.0], []);
|
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
|
// 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[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
||||||
|
|
||||||
block2
|
block2.transactions.push(spend_transaction.into());
|
||||||
.transactions
|
|
||||||
.push(spend_transaction.into());
|
|
||||||
|
|
||||||
if use_finalized_state_spend {
|
if use_finalized_state_spend {
|
||||||
let block2 = FinalizedBlock::from(Arc::new(block2));
|
let block2 = FinalizedBlock::from(Arc::new(block2));
|
||||||
|
|
@ -170,8 +181,7 @@ proptest! {
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
||||||
} else {
|
} else {
|
||||||
let block2 = Arc::new(block2).prepare();
|
let block2 = Arc::new(block2).prepare();
|
||||||
let commit_result =
|
let commit_result = state.validate_and_commit(block2.clone());
|
||||||
state.validate_and_commit(block2.clone());
|
|
||||||
|
|
||||||
// the block was committed
|
// the block was committed
|
||||||
prop_assert_eq!(commit_result, Ok(()));
|
prop_assert_eq!(commit_result, Ok(()));
|
||||||
|
|
@ -182,19 +192,25 @@ proptest! {
|
||||||
|
|
||||||
// the UTXO is spent
|
// the UTXO is spent
|
||||||
prop_assert_eq!(state.mem.chain_set.len(), 1);
|
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 {
|
if use_finalized_state_output {
|
||||||
// the chain has spent the UTXO from the finalized state
|
// 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!(!chain.created_utxos.contains_key(&expected_outpoint));
|
||||||
prop_assert!(state.mem.chain_set.iter().next().unwrap().spent_utxos.contains(&expected_outpoint));
|
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
|
||||||
// the finalized state has the UTXO, but it will get deleted on commit
|
// the finalized state has the UTXO, but it will get deleted on commit
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_some());
|
prop_assert!(state.disk.utxo(&expected_outpoint).is_some());
|
||||||
} else {
|
} else {
|
||||||
// the chain has spent its own UTXO
|
// the chain has spent its own 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));
|
||||||
prop_assert!(state.mem.chain_set.iter().next().unwrap().created_utxos.contains_key(&expected_outpoint));
|
prop_assert!(chain.created_utxos.contains_key(&expected_outpoint));
|
||||||
prop_assert!(state.mem.chain_set.iter().next().unwrap().spent_utxos.contains(&expected_outpoint));
|
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
|
||||||
// the finalized state does not have the UTXO
|
// the finalized state does not have the UTXO
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
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 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_input1.set_outpoint(expected_outpoint);
|
||||||
prevout_input2.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
|
// 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[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
@ -243,7 +263,8 @@ proptest! {
|
||||||
Err(DuplicateTransparentSpend {
|
Err(DuplicateTransparentSpend {
|
||||||
outpoint: expected_outpoint,
|
outpoint: expected_outpoint,
|
||||||
location: "the same block",
|
location: "the same block",
|
||||||
}.into())
|
}
|
||||||
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
|
|
||||||
|
|
@ -270,21 +291,25 @@ proptest! {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block should deserialize");
|
.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 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_input1.set_outpoint(expected_outpoint);
|
||||||
prevout_input2.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
|
// 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[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
||||||
|
|
||||||
block2
|
block2.transactions.push(spend_transaction.into());
|
||||||
.transactions
|
|
||||||
.push(spend_transaction.into());
|
|
||||||
|
|
||||||
let block2 = Arc::new(block2).prepare();
|
let block2 = Arc::new(block2).prepare();
|
||||||
let commit_result = state.validate_and_commit(block2);
|
let commit_result = state.validate_and_commit(block2);
|
||||||
|
|
@ -295,7 +320,8 @@ proptest! {
|
||||||
Err(DuplicateTransparentSpend {
|
Err(DuplicateTransparentSpend {
|
||||||
outpoint: expected_outpoint,
|
outpoint: expected_outpoint,
|
||||||
location: "the same block",
|
location: "the same block",
|
||||||
}.into())
|
}
|
||||||
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(1), block1.hash())), state.best_tip());
|
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)
|
// the non-finalized state has no chains (so it can't have the UTXO)
|
||||||
prop_assert!(state.mem.chain_set.iter().next().is_none());
|
prop_assert!(state.mem.chain_set.iter().next().is_none());
|
||||||
} else {
|
} else {
|
||||||
|
let chain = state
|
||||||
|
.mem
|
||||||
|
.chain_set
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
// the non-finalized state has the UTXO
|
// 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
|
// the finalized state does not have the UTXO
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
||||||
}
|
}
|
||||||
|
|
@ -332,10 +364,15 @@ proptest! {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block should deserialize");
|
.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 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_input1.set_outpoint(expected_outpoint);
|
||||||
prevout_input2.set_outpoint(expected_outpoint);
|
prevout_input2.set_outpoint(expected_outpoint);
|
||||||
|
|
||||||
|
|
@ -358,7 +395,8 @@ proptest! {
|
||||||
Err(DuplicateTransparentSpend {
|
Err(DuplicateTransparentSpend {
|
||||||
outpoint: expected_outpoint,
|
outpoint: expected_outpoint,
|
||||||
location: "the same block",
|
location: "the same block",
|
||||||
}.into())
|
}
|
||||||
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(1), block1.hash())), state.best_tip());
|
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)
|
// the non-finalized state has no chains (so it can't have the UTXO)
|
||||||
prop_assert!(state.mem.chain_set.iter().next().is_none());
|
prop_assert!(state.mem.chain_set.iter().next().is_none());
|
||||||
} else {
|
} else {
|
||||||
|
let chain = state
|
||||||
|
.mem
|
||||||
|
.chain_set
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
// the non-finalized state has the UTXO
|
// 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
|
// the finalized state does not have the UTXO
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
||||||
}
|
}
|
||||||
|
|
@ -405,10 +449,15 @@ proptest! {
|
||||||
.zcash_deserialize_into::<Block>()
|
.zcash_deserialize_into::<Block>()
|
||||||
.expect("block should deserialize");
|
.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 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_input1.set_outpoint(expected_outpoint);
|
||||||
prevout_input2.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();
|
block2.transactions[0] = transaction_v4_from_coinbase(&block2.transactions[0]).into();
|
||||||
block3.transactions[0] = transaction_v4_from_coinbase(&block3.transactions[0]).into();
|
block3.transactions[0] = transaction_v4_from_coinbase(&block3.transactions[0]).into();
|
||||||
|
|
||||||
block2
|
block2.transactions.push(spend_transaction1.into());
|
||||||
.transactions
|
block3.transactions.push(spend_transaction2.into());
|
||||||
.push(spend_transaction1.into());
|
|
||||||
block3
|
|
||||||
.transactions
|
|
||||||
.push(spend_transaction2.into());
|
|
||||||
|
|
||||||
let block2 = Arc::new(block2);
|
let block2 = Arc::new(block2);
|
||||||
|
|
||||||
|
|
@ -455,45 +500,23 @@ proptest! {
|
||||||
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
prop_assert!(!state.mem.eq_internal_state(&previous_mem));
|
||||||
|
|
||||||
prop_assert_eq!(state.mem.chain_set.len(), 1);
|
prop_assert_eq!(state.mem.chain_set.len(), 1);
|
||||||
|
let chain = state
|
||||||
|
.mem
|
||||||
|
.chain_set
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if use_finalized_state_output {
|
if use_finalized_state_output {
|
||||||
// the finalized state has the unspent UTXO
|
// the finalized state has the unspent UTXO
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_some());
|
prop_assert!(state.disk.utxo(&expected_outpoint).is_some());
|
||||||
// the non-finalized state has spent the UTXO
|
// the non-finalized state has spent the UTXO
|
||||||
prop_assert!(state
|
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
|
||||||
.mem
|
|
||||||
.chain_set
|
|
||||||
.iter()
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.spent_utxos
|
|
||||||
.contains(&expected_outpoint));
|
|
||||||
} else {
|
} else {
|
||||||
// the non-finalized state has created and spent the UTXO
|
// the non-finalized state has created and spent the UTXO
|
||||||
prop_assert!(!state
|
prop_assert!(!chain.unspent_utxos().contains_key(&expected_outpoint));
|
||||||
.mem
|
prop_assert!(chain.created_utxos.contains_key(&expected_outpoint));
|
||||||
.chain_set
|
prop_assert!(chain.spent_utxos.contains(&expected_outpoint));
|
||||||
.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));
|
|
||||||
// the finalized state does not have the UTXO
|
// the finalized state does not have the UTXO
|
||||||
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
prop_assert!(state.disk.utxo(&expected_outpoint).is_none());
|
||||||
}
|
}
|
||||||
|
|
@ -511,7 +534,8 @@ proptest! {
|
||||||
Err(MissingTransparentOutput {
|
Err(MissingTransparentOutput {
|
||||||
outpoint: expected_outpoint,
|
outpoint: expected_outpoint,
|
||||||
location: "the non-finalized and finalized chain",
|
location: "the non-finalized and finalized chain",
|
||||||
}.into())
|
}
|
||||||
|
.into())
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
|
|
@ -519,7 +543,8 @@ proptest! {
|
||||||
Err(DuplicateTransparentSpend {
|
Err(DuplicateTransparentSpend {
|
||||||
outpoint: expected_outpoint,
|
outpoint: expected_outpoint,
|
||||||
location: "the non-finalized chain",
|
location: "the non-finalized chain",
|
||||||
}.into())
|
}
|
||||||
|
.into())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
prop_assert_eq!(Some((Height(2), block2.hash())), state.best_tip());
|
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
|
// 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[0] = transaction_v4_from_coinbase(&block1.transactions[0]).into();
|
||||||
|
|
||||||
block1
|
block1.transactions.push(spend_transaction.into());
|
||||||
.transactions
|
|
||||||
.push(spend_transaction.into());
|
|
||||||
|
|
||||||
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
let (mut state, genesis) = new_state_with_mainnet_genesis();
|
||||||
let previous_mem = state.mem.clone();
|
let previous_mem = state.mem.clone();
|
||||||
|
|
@ -576,7 +599,8 @@ proptest! {
|
||||||
Err(MissingTransparentOutput {
|
Err(MissingTransparentOutput {
|
||||||
outpoint: expected_outpoint,
|
outpoint: expected_outpoint,
|
||||||
location: "the non-finalized and finalized chain",
|
location: "the non-finalized and finalized chain",
|
||||||
}.into())
|
}
|
||||||
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
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]);
|
let output_transaction = transaction_v4_with_transparent_data([], [output.0]);
|
||||||
|
|
||||||
// create a spend
|
// 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);
|
prevout_input.set_outpoint(expected_outpoint);
|
||||||
let spend_transaction = transaction_v4_with_transparent_data([prevout_input.0], []);
|
let spend_transaction = transaction_v4_with_transparent_data([prevout_input.0], []);
|
||||||
|
|
||||||
|
|
@ -630,7 +657,8 @@ proptest! {
|
||||||
commit_result,
|
commit_result,
|
||||||
Err(EarlyTransparentSpend {
|
Err(EarlyTransparentSpend {
|
||||||
outpoint: expected_outpoint,
|
outpoint: expected_outpoint,
|
||||||
}.into())
|
}
|
||||||
|
.into())
|
||||||
);
|
);
|
||||||
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
prop_assert_eq!(Some((Height(0), genesis.hash)), state.best_tip());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue