Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add(test): Add serialized NU5 blocks to test vectors #9098

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7e15762
Add serialized Mainnet blocks for tests
upbqdn Dec 9, 2024
f1f83ac
Add Sapling anchors
upbqdn Dec 9, 2024
9c8058f
Add Mainnet Orchard anchors
upbqdn Dec 16, 2024
fe13db8
Remove wrong Testnet NU5 blocks
upbqdn Dec 17, 2024
bc759c7
Add Testnet blocks with V5 txs to test vectors
upbqdn Dec 17, 2024
d0d9e96
Move the Sapling treestate
upbqdn Dec 17, 2024
e1e0162
Add Sapling & Orchard anchors
upbqdn Dec 17, 2024
7228929
Remove unneeded test for fake V5 txs
upbqdn Dec 17, 2024
35513d0
Add `has_transparent_inputs` to `Transaction`
upbqdn Dec 18, 2024
e6422b1
Fix `v5_with_sapling_spends` test
upbqdn Dec 19, 2024
34e985b
Fix `binding_signatures` test
upbqdn Dec 19, 2024
883fb21
Refactor block test vectors
upbqdn Dec 19, 2024
d3f28b2
Use real V5 txs instead of fake ones
upbqdn Dec 19, 2024
1f15388
Fix `v5_transaction_is_rejected_before_nu5` test
upbqdn Dec 20, 2024
b83e826
Fix `v5_tx_is_accepted_after_nu5_activation` test
upbqdn Dec 20, 2024
6108571
Fix `v5_tx_with_no_outputs_fails_validation` test
upbqdn Dec 20, 2024
6c17f8d
Move `v5_tx_with_no_outputs_fails_validation` test
upbqdn Dec 20, 2024
72678c0
Fix `v5_tx_with_no_inputs_fails_verification` test
upbqdn Dec 20, 2024
c1393af
Fix `v5_tx_with_orchard_actions_has_inputs..` test
upbqdn Dec 20, 2024
dfb2d9e
Fix `v5_coinbase_tx_without_spends_flag_passes`
upbqdn Dec 20, 2024
3437af6
Simplify `orchard` imports
upbqdn Dec 20, 2024
363bf3a
Fix `v5_tx_with_orchard_actions_has_flags` test
upbqdn Dec 20, 2024
7ac677f
Fix `v5_coinbase_tx_with_enable_spends_fails`
upbqdn Dec 20, 2024
9327beb
Fix `v5_tx_with_duplicate_orchard_action` test
upbqdn Dec 20, 2024
27f9ed7
Fix `coinbase_outputs_are_decryptable_for_v5`
upbqdn Dec 20, 2024
e419e3b
Fix `shielded_outputs_are_not_decryptable_for_v5`
upbqdn Dec 20, 2024
2832612
Use `Network::iter` instead of Mainnet
upbqdn Dec 21, 2024
00f19df
Rename basic V5 tx test
upbqdn Dec 21, 2024
30f43f5
Merge branch 'main' into add-v5-txs
upbqdn Dec 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 61 additions & 71 deletions zebra-chain/src/block/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ use crate::{
block::{
serialize::MAX_BLOCK_BYTES, Block, BlockTimeError, Commitment::*, Hash, Header, Height,
},
parameters::{
Network::{self, *},
NetworkUpgrade::*,
},
parameters::{Network, NetworkUpgrade::*},
sapling,
serialization::{
sha256d, SerializationError, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize,
},
Expand Down Expand Up @@ -191,88 +189,80 @@ fn block_test_vectors_unique() {
);
}

/// Checks that:
///
/// - the block test vector indexes match the heights in the block data;
/// - each post-Sapling block has a corresponding final Sapling root;
/// - each post-Orchard block has a corresponding final Orchard root.
#[test]
fn block_test_vectors_height_mainnet() {
let _init_guard = zebra_test::init();

block_test_vectors_height(Mainnet);
}

#[test]
fn block_test_vectors_height_testnet() {
fn block_test_vectors() {
let _init_guard = zebra_test::init();

block_test_vectors_height(Network::new_default_testnet());
}
for net in Network::iter() {
let sapling_anchors = net.sapling_anchors();
let orchard_anchors = net.orchard_anchors();

/// Test that the block test vector indexes match the heights in the block data,
/// and that each post-sapling block has a corresponding final sapling root.
fn block_test_vectors_height(network: Network) {
let (block_iter, sapling_roots) = network.block_sapling_roots_iter();

for (&height, block) in block_iter {
let block = block
.zcash_deserialize_into::<Block>()
.expect("block is structurally valid");
assert_eq!(
block.coinbase_height().expect("block height is valid").0,
height,
"deserialized height must match BTreeMap key height"
);
for (&height, block) in net.block_iter() {
let block = block
.zcash_deserialize_into::<Block>()
.expect("block is structurally valid");
assert_eq!(
block.coinbase_height().expect("block height is valid").0,
height,
"deserialized height must match BTreeMap key height"
);

if height
>= Sapling
.activation_height(&network)
.expect("sapling activation height is set")
.0
{
assert!(
sapling_roots.contains_key(&height),
"post-sapling block test vectors must have matching sapling root test vectors: missing {network} {height}"
if height
>= Sapling
.activation_height(&net)
.expect("activation height")
.0
{
assert!(
sapling_anchors.contains_key(&height),
"post-sapling block test vectors must have matching sapling root test vectors: \
missing {net} {height}"
);
}

if height >= Nu5.activation_height(&net).expect("activation height").0 {
assert!(
orchard_anchors.contains_key(&height),
"post-nu5 block test vectors must have matching orchard root test vectors: \
missing {net} {height}"
);
}
}
}
}

#[test]
fn block_commitment_mainnet() {
let _init_guard = zebra_test::init();

block_commitment(Mainnet);
}

#[test]
fn block_commitment_testnet() {
let _init_guard = zebra_test::init();

block_commitment(Network::new_default_testnet());
}

/// Check that the block commitment field parses without errors.
/// Checks that the block commitment field parses without errors.
/// For sapling and blossom blocks, also check the final sapling root value.
///
/// TODO: add chain history test vectors?
fn block_commitment(network: Network) {
let (block_iter, sapling_roots) = network.block_sapling_roots_iter();

for (height, block) in block_iter {
let block = block
.zcash_deserialize_into::<Block>()
.expect("block is structurally valid");
#[test]
fn block_commitment() {
let _init_guard = zebra_test::init();

let commitment = block.commitment(&network).unwrap_or_else(|_| {
panic!("unexpected structurally invalid block commitment at {network} {height}")
});
for net in Network::iter() {
let sapling_anchors = net.sapling_anchors();

if let FinalSaplingRoot(final_sapling_root) = commitment {
let expected_final_sapling_root = *sapling_roots
.get(height)
.expect("unexpected missing final sapling root test vector");
assert_eq!(
final_sapling_root,
crate::sapling::tree::Root::try_from(*expected_final_sapling_root).unwrap(),
"unexpected invalid final sapling root commitment at {network} {height}"
);
for (height, block) in net.block_iter() {
if let FinalSaplingRoot(anchor) = block
.zcash_deserialize_into::<Block>()
.expect("block is structurally valid")
.commitment(&net)
.expect("unexpected structurally invalid block commitment at {net} {height}")
{
let expected_anchor = *sapling_anchors
.get(height)
.expect("unexpected missing final sapling root test vector");
assert_eq!(
anchor,
sapling::tree::Root::try_from(*expected_anchor).unwrap(),
"unexpected invalid final sapling root commitment at {net} {height}"
);
}
}
}
}
Expand Down
27 changes: 16 additions & 11 deletions zebra-chain/src/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ use zebra_test::vectors::{
BLOCK_MAINNET_1046400_BYTES, BLOCK_MAINNET_653599_BYTES, BLOCK_MAINNET_982681_BYTES,
BLOCK_TESTNET_1116000_BYTES, BLOCK_TESTNET_583999_BYTES, BLOCK_TESTNET_925483_BYTES,
CONTINUOUS_MAINNET_BLOCKS, CONTINUOUS_TESTNET_BLOCKS, MAINNET_BLOCKS,
MAINNET_FINAL_SAPLING_ROOTS, MAINNET_FINAL_SPROUT_ROOTS,
MAINNET_FINAL_ORCHARD_ROOTS, MAINNET_FINAL_SAPLING_ROOTS, MAINNET_FINAL_SPROUT_ROOTS,
SAPLING_FINAL_ROOT_MAINNET_1046400_BYTES, SAPLING_FINAL_ROOT_TESTNET_1116000_BYTES,
TESTNET_BLOCKS, TESTNET_FINAL_SAPLING_ROOTS, TESTNET_FINAL_SPROUT_ROOTS,
TESTNET_BLOCKS, TESTNET_FINAL_ORCHARD_ROOTS, TESTNET_FINAL_SAPLING_ROOTS,
TESTNET_FINAL_SPROUT_ROOTS,
};

/// Network methods for fetching blockchain vectors.
Expand Down Expand Up @@ -118,17 +119,21 @@ impl Network {
}
}

/// Returns iterator over blocks and sapling roots.
pub fn block_sapling_roots_iter(
&self,
) -> (
std::collections::btree_map::Iter<'_, u32, &[u8]>,
std::collections::BTreeMap<u32, &[u8; 32]>,
) {
/// Returns a [`BTreeMap`] of heights and Sapling anchors for this network.
pub fn sapling_anchors(&self) -> std::collections::BTreeMap<u32, &[u8; 32]> {
if self.is_mainnet() {
MAINNET_FINAL_SAPLING_ROOTS.clone()
} else {
TESTNET_FINAL_SAPLING_ROOTS.clone()
}
}

/// Returns a [`BTreeMap`] of heights and Orchard anchors for this network.
pub fn orchard_anchors(&self) -> std::collections::BTreeMap<u32, &[u8; 32]> {
if self.is_mainnet() {
(MAINNET_BLOCKS.iter(), MAINNET_FINAL_SAPLING_ROOTS.clone())
MAINNET_FINAL_ORCHARD_ROOTS.clone()
} else {
(TESTNET_BLOCKS.iter(), TESTNET_FINAL_SAPLING_ROOTS.clone())
TESTNET_FINAL_ORCHARD_ROOTS.clone()
}
}

Expand Down
7 changes: 6 additions & 1 deletion zebra-chain/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,14 @@ impl Transaction {

// other properties

/// Does this transaction have transparent inputs?
pub fn has_transparent_inputs(&self) -> bool {
!self.inputs().is_empty()
}

/// Does this transaction have transparent or shielded inputs?
pub fn has_transparent_or_shielded_inputs(&self) -> bool {
!self.inputs().is_empty() || self.has_shielded_inputs()
self.has_transparent_inputs() || self.has_shielded_inputs()
}

/// Does this transaction have shielded inputs?
Expand Down
17 changes: 9 additions & 8 deletions zebra-chain/src/transaction/arbitrary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,16 +992,17 @@ pub fn test_transactions(
transactions_from_blocks(blocks)
}

/// Generate an iterator over fake V5 transactions.
///
/// These transactions are converted from non-V5 transactions that exist in the provided network
/// blocks.
pub fn fake_v5_transactions_for_network<'b>(
network: &'b Network,
/// Returns an iterator over V5 transactions extracted from the given blocks.
pub fn v5_transactions<'b>(
blocks: impl DoubleEndedIterator<Item = (&'b u32, &'b &'static [u8])> + 'b,
) -> impl DoubleEndedIterator<Item = Transaction> + 'b {
transactions_from_blocks(blocks)
.map(move |(height, transaction)| transaction_to_fake_v5(&transaction, network, height))
transactions_from_blocks(blocks).filter_map(|(_, tx)| match *tx {
Transaction::V1 { .. }
| Transaction::V2 { .. }
| Transaction::V3 { .. }
| Transaction::V4 { .. } => None,
ref tx @ Transaction::V5 { .. } => Some(tx.clone()),
})
}

/// Generate an iterator over ([`block::Height`], [`Arc<Transaction>`]).
Expand Down
Loading
Loading