Skip to content
20 changes: 20 additions & 0 deletions zebra-chain/src/block/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,26 @@ pub enum CommitmentError {
actual: [u8; 32],
},

#[error(
"invalid auth data root: expected {:?}, actual: {:?}",
hex::encode(expected),
hex::encode(actual)
)]
InvalidAuthDataRoot {
expected: [u8; 32],
actual: [u8; 32],
},

#[error(
"invalid pre-NU5 orchard root: expected the empty-tree root {:?}, actual: {:?}",
hex::encode(expected),
hex::encode(actual)
)]
InvalidPreNu5OrchardRoot {
expected: [u8; 32],
actual: [u8; 32],
},

#[error("missing required block height: block commitments can't be parsed without a block height, block hash: {block_hash:?}")]
MissingBlockHeight { block_hash: block::Hash },

Expand Down
1 change: 0 additions & 1 deletion zebra-state/src/service/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ pub(crate) fn block_commitment_is_valid_for_chain_history(
);
let auth_data_root =
precomputed_auth_data_root.unwrap_or_else(|| block.auth_data_root());

let hash_block_commitments = ChainHistoryBlockTxAuthCommitmentHash::from_commitments(
&history_tree_root,
&auth_data_root,
Expand Down
76 changes: 76 additions & 0 deletions zebra-state/src/service/check/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
use chrono::{DateTime, Duration};

use zebra_chain::{
block::{merkle::AuthDataRoot, ChainHistoryBlockTxAuthCommitmentHash, CommitmentError},
history_tree::HistoryTree,
parameters::{Network, NetworkUpgrade},
sapling,
serialization::ZcashDeserializeInto,
work::difficulty::ParameterDifficulty,
};

use super::super::*;
use crate::tests::FakeChainHelper;

#[test]
fn test_orphan_consensus_check() {
Expand Down Expand Up @@ -53,6 +57,78 @@ fn test_sequential_height_check() {
.expect_err("parent height is way more, should panic");
}

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

let network = Network::Mainnet;
let parent_height = 1_687_106;
let (blocks, sapling_roots) = network.block_sapling_roots_map();

let parent = Arc::new(
blocks
.get(&parent_height)
.expect("NU5 parent test vector exists")
.zcash_deserialize_into::<Block>()
.expect("NU5 parent block deserializes"),
);
let sapling_root = sapling::tree::Root::try_from(
**sapling_roots
.get(&parent_height)
.expect("NU5 parent Sapling root exists"),
)
.expect("Sapling root vector is valid");
let history_tree = HistoryTree::from_block(
&network,
parent.clone(),
&sapling_root,
&Default::default(),
&Default::default(),
)
.expect("NU5 parent builds a history tree");

let child = parent.make_fake_child();
let auth_data_root = child.auth_data_root();
let hash_block_commitments = ChainHistoryBlockTxAuthCommitmentHash::from_commitments(
&history_tree
.hash()
.expect("NU5 parent history tree has a root"),
&auth_data_root,
);
let block_commitment: [u8; 32] = hash_block_commitments.into();
let child = child.set_block_commitment(block_commitment);

block_commitment_is_valid_for_chain_history(
child.clone(),
&network,
&history_tree,
Some(auth_data_root),
)
.expect("a matching precomputed auth data root is accepted");

let forged_auth_data_root = AuthDataRoot::from([0x42; 32]);
assert_ne!(
forged_auth_data_root, auth_data_root,
"the forged root must differ from the block body root"
);
let error = block_commitment_is_valid_for_chain_history(
child,
&network,
&history_tree,
Some(forged_auth_data_root),
)
.expect_err("a forged precomputed auth data root must be rejected");

assert!(matches!(
error,
ValidateContextError::InvalidBlockCommitment(CommitmentError::InvalidAuthDataRoot {
expected,
actual,
}) if expected == <[u8; 32]>::from(auth_data_root)
&& actual == <[u8; 32]>::from(forged_auth_data_root)
));
}

#[test]
fn header_daa_accepts_valid_threshold_with_full_context() {
let _init_guard = zebra_test::init();
Expand Down
1 change: 1 addition & 0 deletions zebra-state/src/service/finalized_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static COMMIT_COMPUTE_POOL: LazyLock<rayon::ThreadPool> = LazyLock::new(|| {
pub mod column_family;

pub(crate) mod commitment_aux;
pub(crate) mod commitment_aux_verify;
mod disk_db;
mod disk_format;
mod zebra_db;
Expand Down
Loading
Loading