From d5bc0c2f1588ae45c588264176d96a23f33efdbb Mon Sep 17 00:00:00 2001 From: superstar0402 Date: Tue, 30 Jan 2024 11:54:25 +0100 Subject: [PATCH] refactor: nuking old `BlockHeader` (#4154) Fixes #3937 Fixes #3564 Fixes #4134 --- aztec/src/abi.nr | 6 +-- aztec/src/context.nr | 45 ++++++++-------- aztec/src/history/contract_inclusion.nr | 4 +- aztec/src/history/note_inclusion.nr | 4 +- aztec/src/history/nullifier_inclusion.nr | 4 +- aztec/src/history/nullifier_non_inclusion.nr | 4 +- aztec/src/history/public_value_inclusion.nr | 4 +- aztec/src/oracle.nr | 2 +- aztec/src/oracle/get_block_header.nr | 56 -------------------- aztec/src/oracle/header.nr | 49 +++++++++++++++++ 10 files changed, 85 insertions(+), 93 deletions(-) delete mode 100644 aztec/src/oracle/get_block_header.nr create mode 100644 aztec/src/oracle/header.nr diff --git a/aztec/src/abi.nr b/aztec/src/abi.nr index b6f5cfa..74ba77d 100644 --- a/aztec/src/abi.nr +++ b/aztec/src/abi.nr @@ -1,12 +1,12 @@ use dep::protocol_types::{ abis::{ - block_header::BlockHeader, call_context::CallContext, private_circuit_public_inputs::PrivateCircuitPublicInputs, public_circuit_public_inputs::PublicCircuitPublicInputs, }, contrakt::deployment_data::ContractDeploymentData, hash::hash_args, + header::Header, }; // docs:start:private-global-variables @@ -41,7 +41,7 @@ impl PublicGlobalVariables { // docs:start:private-context-inputs struct PrivateContextInputs { call_context : CallContext, - block_header: BlockHeader, + historical_header: Header, contract_deployment_data: ContractDeploymentData, private_global_variables: PrivateGlobalVariables, } @@ -51,7 +51,7 @@ struct PrivateContextInputs { // docs:start:public-context-inputs struct PublicContextInputs { call_context: CallContext, - block_header: BlockHeader, + historical_header: Header, public_global_variables: PublicGlobalVariables, } diff --git a/aztec/src/context.nr b/aztec/src/context.nr index fe10eb0..a563507 100644 --- a/aztec/src/context.nr +++ b/aztec/src/context.nr @@ -11,7 +11,7 @@ use crate::{ public_call::call_public_function_internal, enqueue_public_function_call::enqueue_public_function_call_internal, context::get_portal_address, - get_block_header::get_block_header, + header::get_header_at, nullifier_key::{get_nullifier_key_pair, NullifierKeyPair}, }, types::vec::BoundedVec, @@ -19,8 +19,9 @@ use crate::{ }; use dep::protocol_types::{ abis::{ - block_header::BlockHeader, + append_only_tree_snapshot::AppendOnlyTreeSnapshot, call_context::CallContext, + global_variables::GlobalVariables, function_data::FunctionData, function_selector::FunctionSelector, nullifier_key_validation_request::NullifierKeyValidationRequest, @@ -55,6 +56,8 @@ use dep::protocol_types::{ grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey, hash::hash_args, + header::Header, + state_reference::StateReference, }; use dep::std::{ option::Option, @@ -83,7 +86,7 @@ struct PrivateContext { new_l2_to_l1_msgs : BoundedVec, // docs:end:private-context - block_header: BlockHeader, + historical_header: Header, // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) // encrypted_logs_preimages: Vec, @@ -107,7 +110,7 @@ impl PrivateContext { new_commitments: BoundedVec::new(SideEffect::empty()), new_nullifiers: BoundedVec::new(SideEffectLinkedToNoteHash::empty()), - block_header: inputs.block_header, + historical_header: inputs.historical_header, private_call_stack_hashes: BoundedVec::new(0), public_call_stack_hashes: BoundedVec::new(0), @@ -145,8 +148,13 @@ impl PrivateContext { self.inputs.call_context.function_selector } - pub fn get_block_header(self, block_number: u32) -> BlockHeader { - get_block_header(block_number, self) + // Returns the header of a block whose state is used during private execution + pub fn get_header(self) -> Header { + self.historical_header + } + + pub fn get_header_at(self, block_number: u32) -> Header { + get_header_at(block_number, self) } pub fn finish(self) -> PrivateCircuitPublicInputs { @@ -172,7 +180,7 @@ impl PrivateContext { unencrypted_logs_hash: unencrypted_logs_hash, encrypted_log_preimages_length: encrypted_log_preimages_length, unencrypted_log_preimages_length: unencrypted_log_preimages_length, - block_header: self.block_header, + historical_header: self.historical_header, contract_deployment_data: self.inputs.contract_deployment_data, chain_id: self.inputs.private_global_variables.chain_id, version: self.inputs.private_global_variables.version, @@ -245,7 +253,7 @@ impl PrivateContext { ) // docs:end:context_consume_l1_to_l2_message { - let nullifier = process_l1_to_l2_message(self.block_header.l1_to_l2_message_tree_root, self.this_address(), self.this_portal_address(), self.chain_id(), self.version(), msg_key, content, secret); + let nullifier = process_l1_to_l2_message(self.historical_header.state.l1_to_l2_message_tree.root, self.this_address(), self.this_portal_address(), self.chain_id(), self.version(), msg_key, content, secret); // Push nullifier (and the "commitment" corresponding to this can be "empty") self.push_new_nullifier(nullifier, 0) @@ -330,16 +338,7 @@ impl PrivateContext { unencrypted_logs_hash: reader.read_array([0; NUM_FIELDS_PER_SHA256]), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), - block_header: BlockHeader{ - // Must match order in `private_circuit_public_inputs.hpp` - note_hash_tree_root : reader.read(), - nullifier_tree_root : reader.read(), - contract_tree_root : reader.read(), - l1_to_l2_message_tree_root : reader.read(), - archive_root : reader.read(), - public_data_tree_root: reader.read(), - global_variables_hash: reader.read(), - }, + historical_header: reader.read_struct(Header::deserialize), contract_deployment_data: ContractDeploymentData { deployer_public_key: GrumpkinPoint { x: reader.read(), @@ -446,7 +445,7 @@ impl PrivateContext { new_l2_to_l1_msgs:[0; MAX_NEW_L2_TO_L1_MSGS_PER_CALL], unencrypted_logs_hash:[0; NUM_FIELDS_PER_SHA256], unencrypted_log_preimages_length: 0, - block_header: BlockHeader::empty(), + historical_header: Header::empty(), prover_address: AztecAddress::zero(), }, is_execution_request: true, @@ -495,7 +494,7 @@ struct PublicContext { unencrypted_logs_hash: BoundedVec, unencrypted_logs_preimages_length: Field, - block_header: BlockHeader, + historical_header: Header, prover_address: AztecAddress, } @@ -523,7 +522,7 @@ impl PublicContext { unencrypted_logs_hash: BoundedVec::new(0), unencrypted_logs_preimages_length: 0, - block_header: inputs.block_header, + historical_header: inputs.historical_header, prover_address: AztecAddress::zero(), // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) @@ -583,7 +582,7 @@ impl PublicContext { new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, unencrypted_logs_hash: unencrypted_logs_hash, unencrypted_log_preimages_length: unencrypted_log_preimages_length, - block_header: self.inputs.block_header, + historical_header: self.inputs.historical_header, prover_address: self.prover_address, }; pub_circuit_pub_inputs @@ -616,7 +615,7 @@ impl PublicContext { // Note this returns self to get around an issue where mutable structs do not maintain mutations unless reassigned pub fn consume_l1_to_l2_message(&mut self, msg_key: Field, content: Field, secret: Field) { let this = (*self).this_address(); - let nullifier = process_l1_to_l2_message(self.block_header.l1_to_l2_message_tree_root, this, self.this_portal_address(), self.chain_id(), self.version(), msg_key, content, secret); + let nullifier = process_l1_to_l2_message(self.historical_header.state.l1_to_l2_message_tree.root, this, self.this_portal_address(), self.chain_id(), self.version(), msg_key, content, secret); // Push nullifier (and the "commitment" corresponding to this can be "empty") self.push_new_nullifier(nullifier, 0) diff --git a/aztec/src/history/contract_inclusion.nr b/aztec/src/history/contract_inclusion.nr index 053fb57..5610a0d 100644 --- a/aztec/src/history/contract_inclusion.nr +++ b/aztec/src/history/contract_inclusion.nr @@ -31,7 +31,7 @@ pub fn prove_contract_inclusion( context: PrivateContext ) -> AztecAddress { // 1) Get block header from oracle and ensure that the block is included in the archive. - let block_header = context.get_block_header(block_number); + let header = context.get_header_at(block_number); // 2) Compute the contract address let contract_address = CompleteAddress::compute( @@ -52,7 +52,7 @@ pub fn prove_contract_inclusion( // 6) Prove that the leaf is in the contract tree assert( - block_header.contract_tree_root + header.state.partial.contract_tree.root == compute_merkle_root(contract_leaf, witness.index, witness.path), "Proving contract inclusion failed" ); diff --git a/aztec/src/history/note_inclusion.nr b/aztec/src/history/note_inclusion.nr index 61e1541..1949395 100644 --- a/aztec/src/history/note_inclusion.nr +++ b/aztec/src/history/note_inclusion.nr @@ -16,14 +16,14 @@ pub fn prove_note_commitment_inclusion( context: PrivateContext ) { // 1) Get block header from oracle and ensure that the block is included in the archive. - let block_header = context.get_block_header(block_number); + let header = context.get_header_at(block_number); // 2) Get the membership witness of the note in the note hash tree let witness = get_note_hash_membership_witness(block_number, note_commitment); // 3) Prove that the commitment is in the note hash tree assert( - block_header.note_hash_tree_root + header.state.partial.note_hash_tree.root == compute_merkle_root(note_commitment, witness.index, witness.path), "Proving note inclusion failed" ); // --> Now we have traversed the trees all the way up to archive root. diff --git a/aztec/src/history/nullifier_inclusion.nr b/aztec/src/history/nullifier_inclusion.nr index 43976db..1d61313 100644 --- a/aztec/src/history/nullifier_inclusion.nr +++ b/aztec/src/history/nullifier_inclusion.nr @@ -11,7 +11,7 @@ pub fn prove_nullifier_inclusion( context: PrivateContext ) { // 1) Get block header from oracle and ensure that the block hash is included in the archive. - let block_header = context.get_block_header(block_number); + let header = context.get_header_at(block_number); // 2) Get the membership witness of the nullifier let witness = get_nullifier_membership_witness(block_number, nullifier); @@ -24,7 +24,7 @@ pub fn prove_nullifier_inclusion( // 5) Prove that the nullifier is in the nullifier tree assert( - block_header.nullifier_tree_root + header.state.partial.nullifier_tree.root == compute_merkle_root(nullifier_leaf, witness.index, witness.path), "Proving nullifier inclusion failed" ); // --> Now we have traversed the trees all the way up to archive root and verified that the nullifier diff --git a/aztec/src/history/nullifier_non_inclusion.nr b/aztec/src/history/nullifier_non_inclusion.nr index f4cb297..812165a 100644 --- a/aztec/src/history/nullifier_non_inclusion.nr +++ b/aztec/src/history/nullifier_non_inclusion.nr @@ -20,7 +20,7 @@ pub fn prove_nullifier_non_inclusion( context: PrivateContext ) { // 1) Get block header from oracle and ensure that the block is included in the archive. - let block_header = context.get_block_header(block_number); + let header = context.get_header_at(block_number); // 2) Get the membership witness of a low nullifier of the nullifier let witness = get_low_nullifier_membership_witness(block_number, nullifier); @@ -30,7 +30,7 @@ pub fn prove_nullifier_non_inclusion( // 3.a) Compute the low nullifier leaf and prove that it is in the nullifier tree let low_nullifier_leaf = witness.leaf_preimage.hash(); assert( - block_header.nullifier_tree_root + header.state.partial.nullifier_tree.root == compute_merkle_root(low_nullifier_leaf, witness.index, witness.path), "Proving nullifier non-inclusion failed: Could not prove low nullifier inclusion" ); diff --git a/aztec/src/history/public_value_inclusion.nr b/aztec/src/history/public_value_inclusion.nr index 45f2c54..62c65bf 100644 --- a/aztec/src/history/public_value_inclusion.nr +++ b/aztec/src/history/public_value_inclusion.nr @@ -22,7 +22,7 @@ pub fn prove_public_value_inclusion( context: PrivateContext ) { // 1) Get block header from oracle and ensure that the block hash is included in the archive. - let block_header = context.get_block_header(block_number); + let header = context.get_header_at(block_number); // 2) Compute the leaf slot by siloing the storage slot with our own address let public_value_leaf_slot = pedersen_hash( @@ -45,7 +45,7 @@ pub fn prove_public_value_inclusion( // 5) Prove that the leaf we validated is in the public data tree assert( - block_header.public_data_tree_root + header.state.partial.public_data_tree.root == compute_merkle_root(preimage.hash(), witness.index, witness.path), "Proving public value inclusion failed" ); // --> Now we have traversed the trees all the way up to archive root and that way verified that a specific diff --git a/aztec/src/oracle.nr b/aztec/src/oracle.nr index 81eb357..5d07eed 100644 --- a/aztec/src/oracle.nr +++ b/aztec/src/oracle.nr @@ -15,7 +15,7 @@ mod nullifier_key; mod get_sibling_path; mod rand; mod enqueue_public_function_call; -mod get_block_header; +mod header; mod public_call; mod notes; mod storage; diff --git a/aztec/src/oracle/get_block_header.nr b/aztec/src/oracle/get_block_header.nr deleted file mode 100644 index 3977f88..0000000 --- a/aztec/src/oracle/get_block_header.nr +++ /dev/null @@ -1,56 +0,0 @@ -use dep::std::merkle::compute_merkle_root; -use dep::protocol_types::{ - abis::block_header::BlockHeader, - constants::BLOCK_HEADER_LENGTH, -}; - -use crate::{ - context::PrivateContext, - oracle::get_membership_witness::get_archive_membership_witness, -}; - -// TODO(#3564) - Nuke this oracle and Inject the number directly to context -#[oracle(getNullifierRootBlockNumber)] -fn get_nullifier_root_block_number_oracle(_nullifier_tree_root: Field) -> Field {} - -unconstrained pub fn get_nullifier_root_block_number(nullifier_tree_root: Field) -> u32 { - get_nullifier_root_block_number_oracle(nullifier_tree_root) as u32 -} - -#[oracle(getBlockHeader)] -fn get_block_header_oracle(_block_number: u32) -> [Field; BLOCK_HEADER_LENGTH] {} - -unconstrained pub fn get_block_header_internal(block_number: u32) -> BlockHeader { - let block_header = get_block_header_oracle(block_number); - BlockHeader::deserialize(block_header) -} - -pub fn get_block_header(block_number: u32, context: PrivateContext) -> BlockHeader { - // 1) Get block number corresponding to block header inside context - // Using nullifier tree root to get the block header block number because that changes in every block (every tx emits a nullifier). - let block_header_block_number = get_nullifier_root_block_number(context.block_header.nullifier_tree_root); - - // 2) Check that the block header block number is more than or equal to the block number we want to prove against - // We could not perform the proof otherwise because the archive root from the header would not "contain" the block we want to prove against - assert( - block_header_block_number >= block_number, "Block header block number is smaller than the block number we want to prove against" - ); - - // 3) Get block header of a given block from oracle - let block_header = get_block_header_internal(block_number); - - // 4) Compute the block hash from the block header - let block_hash = block_header.block_hash(); - - // 5) Get the membership witness of the block in the archive - let witness = get_archive_membership_witness(block_header_block_number, block_hash); - - // 6) Check that the block is in the archive (i.e. the witness is valid) - assert( - context.block_header.archive_root - == compute_merkle_root(block_hash, witness.index, witness.path), "Proving membership of a block in archive failed" - ); - - // 7) Return the block header - block_header -} diff --git a/aztec/src/oracle/header.nr b/aztec/src/oracle/header.nr new file mode 100644 index 0000000..ab9ee0a --- /dev/null +++ b/aztec/src/oracle/header.nr @@ -0,0 +1,49 @@ +use dep::std::merkle::compute_merkle_root; +use dep::protocol_types::{ + constants::HEADER_LENGTH, + header::Header, +}; + +use crate::{ + context::PrivateContext, + oracle::get_membership_witness::get_archive_membership_witness, +}; + +#[oracle(getHeader)] +fn get_header_at_oracle(_block_number: u32) -> [Field; HEADER_LENGTH] {} + +unconstrained pub fn get_header_at_internal(block_number: u32) -> Header { + let header = get_header_at_oracle(block_number); + Header::deserialize(header) +} + +pub fn get_header_at(block_number: u32, context: PrivateContext) -> Header { + // 1) Get block number corresponding to the last_archive root in the header + // Note: We subtract 1 because the last_archive root is the root of the archive after applying the previous block + let last_archive_block_number = (context.historical_header.global_variables.block_number - 1) as u32; + + // 2) Check that the last archive block number is more than or equal to the block number we want to prove against + // We could not perform the proof otherwise because the last archive root from the header would not "contain" + // the header we want to prove against + assert( + last_archive_block_number >= block_number, "Last archive block number is smaller than the block number we want to prove against" + ); + + // 3) Get the header of a given block from oracle + let header = get_header_at_internal(block_number); + + // 4) Compute the block hash from the block header + let block_hash = header.block_hash(); + + // 5) Get the membership witness of the block in the archive + let witness = get_archive_membership_witness(last_archive_block_number, block_hash); + + // 6) Check that the block is in the archive (i.e. the witness is valid) + assert( + context.historical_header.last_archive.root + == compute_merkle_root(block_hash, witness.index, witness.path), "Proving membership of a block in archive failed" + ); + + // 7) Return the block header + header +}