diff --git a/yarn-project/aztec-nr/aztec/src/oracle/header.nr b/yarn-project/aztec-nr/aztec/src/oracle/header.nr index ab9ee0a15ca..33718bf206b 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/header.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/header.nr @@ -18,32 +18,40 @@ unconstrained pub fn get_header_at_internal(block_number: u32) -> 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 + let historical_header_block_number = context.historical_header.global_variables.block_number as u32; + + if (block_number == historical_header_block_number) { + // If the block number we want to prove against is the same as the block number in the historical header we + // skip the inclusion proofs and just return the historical header from context. + context.historical_header + } else { + // 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 = historical_header_block_number - 1; + + // 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 + } } diff --git a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts index ab27e47bdab..ecdf8561360 100644 --- a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts @@ -70,11 +70,6 @@ describe('e2e_inclusion_proofs_contract', () => { expect(receivedOwner).toEqual(owner.toField()); } - // We advance block to be able to prove against block with `noteCreationBlockNumber` --> we have to do this - // because `last_archive` root in the `Header` of aztec-nr contexts is the root of the archive after applying - // the previous block and not the current one. - await advanceBlock(); - { // Prove note inclusion in a given block. const ignoredCommitment = 0; // Not ignored only when the note doesn't exist @@ -88,7 +83,7 @@ describe('e2e_inclusion_proofs_contract', () => { // Prove that the note has not been nullified // TODO(#3535): Prove the nullifier non-inclusion at older block to test archival node. This is currently not // possible because of issue https://github.com/AztecProtocol/aztec-packages/issues/3535 - const blockNumber = await getLatestUsableBlockNumber(); + const blockNumber = await pxe.getBlockNumber(); const ignoredNullifier = 0; // Not ignored only when the note doesn't exist await contract.methods.test_nullifier_non_inclusion_proof(owner, blockNumber, ignoredNullifier).send().wait(); } @@ -99,10 +94,7 @@ describe('e2e_inclusion_proofs_contract', () => { const { newNullifiers } = receipt.debugInfo!; expect(newNullifiers.length).toBe(2); - // Once again we advance the block to be able to access the correct archive root, - await advanceBlock(); - - const blockNumber = await getLatestUsableBlockNumber(); + const blockNumber = await pxe.getBlockNumber(); const nullifier = newNullifiers[1]; // Note: getLowNullifierMembershipWitness returns the membership witness of the nullifier itself and not // the low nullifier when the nullifier already exists in the tree and for this reason the execution fails @@ -134,11 +126,6 @@ describe('e2e_inclusion_proofs_contract', () => { expect(receivedOwner).toEqual(owner.toField()); } - // We advance block to be able to prove against block with `noteCreationBlockNumber` --> we have to do this - // because `last_archive` root in the `Header` of aztec-nr contexts is the root of the archive after applying - // the previous block and not the current one. - await advanceBlock(); - { // Prove note validity await contract.methods.test_note_validity_proof(owner, noteCreationBlockNumber).send().wait(); @@ -264,26 +251,10 @@ describe('e2e_inclusion_proofs_contract', () => { }); const getRandomBlockNumberSinceDeployment = async () => { - return ( - deploymentBlockNumber + Math.floor(Math.random() * ((await getLatestUsableBlockNumber()) - deploymentBlockNumber)) - ); + return deploymentBlockNumber + Math.floor(Math.random() * ((await pxe.getBlockNumber()) - deploymentBlockNumber)); }; const getRandomBlockNumber = async () => { - return ( - deploymentBlockNumber + Math.floor(Math.random() * ((await getLatestUsableBlockNumber()) - INITIAL_L2_BLOCK_NUM)) - ); - }; - - const getLatestUsableBlockNumber = async () => { - const currentBlockNumber = await pxe.getBlockNumber(); - // Note: We subtract 1 from current because the `last_archive` root in the `Header` of aztec-nr contexts is - // the root of the archive after applying the previous block and not the current one. - return currentBlockNumber - 1; - }; - - // We advance block by sending a transaction calling empty function on our contract. - const advanceBlock = async () => { - await contract.methods.empty().send().wait(); + return deploymentBlockNumber + Math.floor(Math.random() * ((await pxe.getBlockNumber()) - INITIAL_L2_BLOCK_NUM)); }; }); diff --git a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 3867148bcd6..1ee01400f07 100644 --- a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -234,9 +234,6 @@ contract InclusionProofs { // Here typically the factory would add the contract address to its internal map of deployed contracts. } - #[aztec(private)] - fn empty() {} - // Computes note hash and nullifier. // Note 1: Needs to be defined by every contract producing logs. // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes.