Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -8358,7 +8358,7 @@ next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000
root = "0x04522891b206ed43de89ad1f2bf6701ff8589b78893ee32d43a231522f99bfa3"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000009"

[inputs.constants.last_l1_to_l2]
[inputs.constants.new_l1_to_l2]
root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000080"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ accumulated_mana_used = "0x00000000000000000000000000000000000000000000000000000
root = "0x11ec690ae2d1a79033acbde89cb053a6bfeb7713fdc47a18b28fde85057afb4d"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000008"

[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.last_l1_to_l2]
[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.new_l1_to_l2]
root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000070"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000080"

[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.global_variables]
chain_id = "0x0000000000000000000000000000000000000000000000000000000000007a69"
Expand Down Expand Up @@ -781,9 +781,9 @@ accumulated_mana_used = "0x00000000000000000000000000000000000000000000000000000
root = "0x11ec690ae2d1a79033acbde89cb053a6bfeb7713fdc47a18b28fde85057afb4d"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000008"

[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.last_l1_to_l2]
[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.new_l1_to_l2]
root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000070"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000080"

[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.global_variables]
chain_id = "0x0000000000000000000000000000000000000000000000000000000000007a69"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl PublicBaseRollupInputs {

BlockConstantData {
last_archive: self.last_archive,
last_l1_to_l2: avm_data.start_tree_snapshots.l1_to_l2_message_tree,
new_l1_to_l2: avm_data.start_tree_snapshots.l1_to_l2_message_tree,
global_variables: avm_data.global_variables,
vk_tree_root: tube_data.constants.vk_tree_root,
protocol_contract_tree_root: tube_data.constants.protocol_contract_tree_root,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,13 +372,13 @@ pub(crate) mod tests {
let _ = builder.execute();
}

#[test(should_fail_with = "last_l1_to_l2 in constants does not match the value in the previous block header")]
unconstrained fn mismatch_last_l1_to_l2_snapshot_fails() {
#[test(should_fail_with = "new_l1_to_l2 in constants does not match the computed value")]
unconstrained fn mismatch_new_l1_to_l2_snapshot_fails() {
let mut builder = TestBuilder::new();

builder.inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.last_l1_to_l2.root +=
builder.inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.new_l1_to_l2.root +=
1;
builder.inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.last_l1_to_l2.root +=
builder.inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.new_l1_to_l2.root +=
1;

let _ = builder.execute();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,5 @@ impl<let NUM_ROLLUPS: u32, let N: u32> BlockRootRollupInputsValidator<NUM_ROLLUP
),
"hash of the previous block header is not the last leaf in the archive tree",
);

// Validate last_l1_to_l2.
assert_eq(
constants.last_l1_to_l2,
previous_block_header.state.l1_to_l2_message_tree,
"last_l1_to_l2 in constants does not match the value in the previous block header",
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,15 @@ impl BlockRootRollupOutputComposer {
self.data.l1_to_l2_roots.public_inputs.converted_root,
L1_TO_L2_MSG_SUBTREE_HEIGHT as u8,
);

// Check that the `new_l1_to_l2` tree snapshot in the constants matches the computed value.
// This snapshot is used in the avm to validate the l1 to l2 message read requests
assert_eq(
constants.new_l1_to_l2,
new_l1_to_l2_message_tree_snapshot,
"new_l1_to_l2 in constants does not match the computed value",
);

let state = StateReference {
l1_to_l2_message_tree: new_l1_to_l2_message_tree_snapshot,
partial: end_partial_state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use types::{
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, L1_TO_L2_MSG_TREE_HEIGHT,
PUBLIC_BASE_ROLLUP_VK_INDEX, ROOT_PARITY_INDEX,
},
merkle_tree::MerkleTree,
merkle_tree::{append_only_tree, calculate_empty_tree_root, MerkleTree},
proof::vk_data::VkData,
tests::{fixtures, merkle_tree_utils::{compute_zero_hashes, NonEmptyMerkleTree}},
traits::{Empty, Hash, Serialize},
Expand All @@ -31,6 +31,7 @@ pub struct RollupFixtureBuilder {
pub previous_block_hash: Field,
pub last_l1_to_l2: AppendOnlyTreeSnapshot,
pub last_l1_to_l2_subtree_sibling_path: [Field; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH],
pub new_l1_to_l2: AppendOnlyTreeSnapshot,
pub last_archive: AppendOnlyTreeSnapshot,
pub last_archive_sibling_path: [Field; ARCHIVE_HEIGHT],
pub new_archive: AppendOnlyTreeSnapshot,
Expand Down Expand Up @@ -61,6 +62,7 @@ impl RollupFixtureBuilder {
previous_block_hash: 0,
last_l1_to_l2: AppendOnlyTreeSnapshot::empty(),
last_l1_to_l2_subtree_sibling_path: [0; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH],
new_l1_to_l2: AppendOnlyTreeSnapshot::empty(),
last_archive: AppendOnlyTreeSnapshot::empty(),
last_archive_sibling_path: [0; ARCHIVE_HEIGHT],
new_archive: AppendOnlyTreeSnapshot::empty(),
Expand Down Expand Up @@ -201,6 +203,16 @@ impl RollupFixtureBuilder {
self.last_l1_to_l2 = snapshot;
self.last_l1_to_l2_subtree_sibling_path = sibling_path;

let converted_root = self.to_root_rollup_parity_input().public_inputs.converted_root;
let empty_l1_to_l2_subtree_root = calculate_empty_tree_root(L1_TO_L2_MSG_SUBTREE_HEIGHT);
self.new_l1_to_l2 = append_only_tree::insert_subtree_to_snapshot_tree(
snapshot,
sibling_path,
empty_l1_to_l2_subtree_root,
converted_root,
L1_TO_L2_MSG_SUBTREE_HEIGHT as u8,
);

*self
}

Expand Down Expand Up @@ -237,7 +249,7 @@ impl RollupFixtureBuilder {
pub fn to_block_constant_data(self) -> BlockConstantData {
BlockConstantData {
last_archive: self.last_archive,
last_l1_to_l2: self.last_l1_to_l2,
new_l1_to_l2: self.new_l1_to_l2,
vk_tree_root: self.vk_tree_root,
protocol_contract_tree_root: self.protocol_contract_tree_root,
global_variables: self.global_variables,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ accumulated_mana_used = "0x00000000000000000000000000000000000000000000000000000
root = "0x11ec690ae2d1a79033acbde89cb053a6bfeb7713fdc47a18b28fde85057afb4d"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000008"

[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.last_l1_to_l2]
[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.new_l1_to_l2]
root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000070"

Expand Down Expand Up @@ -781,7 +781,7 @@ accumulated_mana_used = "0x00000000000000000000000000000000000000000000000000000
root = "0x11ec690ae2d1a79033acbde89cb053a6bfeb7713fdc47a18b28fde85057afb4d"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000008"

[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.last_l1_to_l2]
[inputs.previous_rollup_data.base_or_merge_rollup_public_inputs.constants.new_l1_to_l2]
root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6"
next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000070"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use std::meta::derive;
pub struct BlockConstantData {
// Archive tree snapshot at the very beginning of the entire block.
pub last_archive: AppendOnlyTreeSnapshot,
// L1toL2Message tree snapshot at the very beginning of the entire block.
pub last_l1_to_l2: AppendOnlyTreeSnapshot,
// L1toL2Message tree snapshot after this block lands.
pub new_l1_to_l2: AppendOnlyTreeSnapshot,
pub vk_tree_root: Field,
pub protocol_contract_tree_root: Field,
pub global_variables: GlobalVariables,
Expand All @@ -19,7 +19,7 @@ impl Empty for BlockConstantData {
fn empty() -> Self {
BlockConstantData {
last_archive: AppendOnlyTreeSnapshot::empty(),
last_l1_to_l2: AppendOnlyTreeSnapshot::empty(),
new_l1_to_l2: AppendOnlyTreeSnapshot::empty(),
vk_tree_root: 0,
protocol_contract_tree_root: 0,
global_variables: GlobalVariables::empty(),
Expand All @@ -43,7 +43,7 @@ mod test {
fn serialization_of_block_constant_data() {
let item = BlockConstantData {
last_archive: AppendOnlyTreeSnapshot { root: 123, next_available_leaf_index: 456 },
last_l1_to_l2: AppendOnlyTreeSnapshot { root: 789, next_available_leaf_index: 101112 },
new_l1_to_l2: AppendOnlyTreeSnapshot { root: 789, next_available_leaf_index: 101112 },
vk_tree_root: 131415,
protocol_contract_tree_root: 161718,
global_variables: GlobalVariables {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ pub global AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = GLOBAL_VARIABLES_LENGTH
+ 1 /* reverted */;

pub global BLOCK_CONSTANT_DATA_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH /* last_archive */
+ APPEND_ONLY_TREE_SNAPSHOT_LENGTH /* last_l1_to_l2_message_tree */
+ APPEND_ONLY_TREE_SNAPSHOT_LENGTH /* new_l1_to_l2_message_tree */
+ 1 /* vk_tree_root */
+ 1 /* protocol_contract_tree_root */
+ GLOBAL_VARIABLES_LENGTH;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ impl FixtureBuilder {
pub fn to_block_constant_data(self) -> BlockConstantData {
BlockConstantData {
last_archive: self.archive_tree,
last_l1_to_l2: self.start_snapshots.l1_to_l2_message_tree,
new_l1_to_l2: self.start_snapshots.l1_to_l2_message_tree,
vk_tree_root: self.vk_tree_root,
protocol_contract_tree_root: self.protocol_contract_tree_root,
global_variables: self.global_variables,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Fr, type Logger, TxStatus, generateClaimSecret, retryUntil } from '@aztec/aztec.js';
import { EthAddress } from '@aztec/foundation/eth-address';
import { TestContract } from '@aztec/noir-test-contracts.js/Test';

import { jest } from '@jest/globals';

import { sendL1ToL2Message } from '../fixtures/l1_to_l2_messaging.js';
import type { EndToEndContext } from '../fixtures/utils.js';
import { EpochsTestContext } from './epochs_test.js';

jest.setTimeout(1000 * 60 * 10);

// Proves an epoch that contains txs with public function calls that consume L1 to L2 messages
// Regression for this issue https://aztecprotocol.slack.com/archives/C085C1942HG/p1754400213976059
describe('e2e_epochs/epochs_proof_public_cross_chain', () => {
let context: EndToEndContext;
let logger: Logger;

let test: EpochsTestContext;

beforeEach(async () => {
test = await EpochsTestContext.setup({ numberOfAccounts: 1, minTxsPerBlock: 1, disableAnvilTestWatcher: true });
({ context, logger } = test);
});

afterEach(async () => {
jest.restoreAllMocks();
await test.teardown();
});

it('submits proof with a tx with public l1-to-l2 message claim', async () => {
// Deploy a contract that consumes L1 to L2 messages
await context.aztecNodeAdmin!.setConfig({ minTxsPerBlock: 0 });
logger.warn(`Deploying test contract`);
const testContract = await TestContract.deploy(context.wallet).send({ from: context.accounts[0] }).deployed();
logger.warn(`Test contract deployed at ${testContract.address}`);

// Send an l1 to l2 message to be consumed from the contract
const [secret, secretHash] = await generateClaimSecret();
const message = { recipient: testContract.address, content: Fr.random(), secretHash };
logger.warn(`Sending L1 to L2 message ${message.content.toString()} to be consumed by ${testContract.address}`);
const { msgHash, globalLeafIndex } = await sendL1ToL2Message(message, context.deployL1ContractsValues);

logger.warn(`Waiting for message ${msgHash} with index ${globalLeafIndex} to be synced`);
await retryUntil(
() => context.aztecNode.isL1ToL2MessageSynced(msgHash),
'message sync',
test.L2_SLOT_DURATION_IN_S * 4,
);

// And we consume the message using the test contract. It's important that we don't wait for the membership witness
// to be available, since we want to test the scenario where the message becomes available on the same block the tx lands.
logger.warn(`Consuming message ${message.content.toString()} from the contract at ${testContract.address}`);
const txReceipt = await testContract.methods
.consume_message_from_arbitrary_sender_public(
message.content,
secret,
EthAddress.fromString(context.deployL1ContractsValues.l1Client.account.address),
globalLeafIndex.toBigInt(),
)
.send({ from: context.accounts[0] })
.wait();
expect(txReceipt.blockNumber).toBeGreaterThan(0);

// Wait until a proof lands for the transaction
logger.warn(`Waiting for proof for tx ${txReceipt.txHash} mined at ${txReceipt.blockNumber!}`);
await retryUntil(
async () => {
const provenBlockNumber = await context.aztecNode.getProvenBlockNumber();
logger.info(`Proven block number is ${provenBlockNumber}`);
return provenBlockNumber >= txReceipt.blockNumber!;
},
'Proof has been submitted',
test.L2_SLOT_DURATION_IN_S * test.epochDuration * 3,
);

const provenBlockNumber = await context.aztecNode.getProvenBlockNumber();
expect(provenBlockNumber).toBeGreaterThanOrEqual(txReceipt.blockNumber!);

// Should not be able to consume the message again.
const failedReceipt = await testContract.methods
.consume_message_from_arbitrary_sender_public(
message.content,
secret,
EthAddress.fromString(context.deployL1ContractsValues.l1Client.account.address),
globalLeafIndex.toBigInt(),
)
.send({ from: context.accounts[0] })
.wait({ dontThrowOnRevert: true });
expect(failedReceipt.status).toBe(TxStatus.APP_LOGIC_REVERTED);

logger.info(`Test succeeded`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ function mapPublicDataHintToNoir(hint: PublicDataHint): PublicDataHintNoir {
function mapBlockConstantDataToNoir(constants: BlockConstantData): BlockConstantDataNoir {
return {
last_archive: mapAppendOnlyTreeSnapshotToNoir(constants.lastArchive),
last_l1_to_l2: mapAppendOnlyTreeSnapshotToNoir(constants.lastL1ToL2),
new_l1_to_l2: mapAppendOnlyTreeSnapshotToNoir(constants.newL1ToL2),
vk_tree_root: mapFieldToNoir(constants.vkTreeRoot),
protocol_contract_tree_root: mapFieldToNoir(constants.protocolContractTreeRoot),
global_variables: mapGlobalVariablesToNoir(constants.globalVariables),
Expand All @@ -380,7 +380,7 @@ function mapBlockConstantDataToNoir(constants: BlockConstantData): BlockConstant
function mapBlockConstantDataFromNoir(constants: BlockConstantDataNoir) {
return new BlockConstantData(
mapAppendOnlyTreeSnapshotFromNoir(constants.last_archive),
mapAppendOnlyTreeSnapshotFromNoir(constants.last_l1_to_l2),
mapAppendOnlyTreeSnapshotFromNoir(constants.new_l1_to_l2),
mapFieldFromNoir(constants.vk_tree_root),
mapFieldFromNoir(constants.protocol_contract_tree_root),
mapGlobalVariablesFromNoir(constants.global_variables),
Expand Down
Loading
Loading