From 6cc9f5a56032e8e74af7436034179412775e9f40 Mon Sep 17 00:00:00 2001 From: benesjan Date: Sun, 17 Mar 2024 15:42:04 +0000 Subject: [PATCH 01/13] refactor: l1 l2 messages cleanup --- .../noir-protocol-circuits/crates/rollup-lib/src/root.nr | 4 ---- .../crates/rollup-lib/src/root/root_rollup_inputs.nr | 4 +--- .../rollup-lib/src/root/root_rollup_public_inputs.nr | 7 ++----- yarn-project/circuits.js/src/structs/rollup/root_rollup.ts | 6 +----- yarn-project/circuits.js/src/tests/factories.ts | 1 - .../noir-protocol-circuits-types/src/type_conversion.ts | 1 - 6 files changed, 4 insertions(+), 19 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr index 10de29dfc6cf..5494edf34d76 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr @@ -64,8 +64,6 @@ mod tests { #[test] fn check_block_hashes_empty_blocks() { - let expected_messages_hash = U256::from_bytes32(dep::std::hash::sha256([0; NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP_NUM_BYTES])).to_u128_limbs(); - let expected_txs_effects_hash = accumulate_sha256( [ U128::from_integer(0), @@ -80,8 +78,6 @@ mod tests { // check txs effects hash assert_eq(outputs.header.content_commitment.txs_effects_hash, expected_txs_effects_hash); - // Check messages hash - assert_eq(outputs.l1_to_l2_messages_hash, expected_messages_hash); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 229b8e340732..17a655ed2821 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -87,9 +87,7 @@ impl RootRollupInputs { RootRollupPublicInputs { aggregation_object, archive, - header, - // TODO(#5264): update this when implementing the new message model - l1_to_l2_messages_hash: compute_messages_hash(self.new_l1_to_l2_messages) + header } } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr index c38a0151d1c8..da448ee010f2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr @@ -1,6 +1,6 @@ use dep::types::{ - abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, global_variables::GlobalVariables}, - constants::{NUM_FIELDS_PER_SHA256}, header::Header + abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, + header::Header }; use dep::types::mocked::AggregationObject; @@ -13,7 +13,4 @@ struct RootRollupPublicInputs { // New block header header: Header, - - // TODO(#5264): Nuke this once message hashing is moved out - l1_to_l2_messages_hash : [Field; NUM_FIELDS_PER_SHA256], } diff --git a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts index c2a88501eb7f..e3fce3863c10 100644 --- a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -6,7 +6,6 @@ import { ARCHIVE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, - NUM_FIELDS_PER_SHA256, } from '../../constants.gen.js'; import { AggregationObject } from '../aggregation_object.js'; import { Header } from '../header.js'; @@ -85,12 +84,10 @@ export class RootRollupPublicInputs { public archive: AppendOnlyTreeSnapshot, /** A header of an L2 block. */ public header: Header, - /** Hash of the L1 to L2 messages. */ - public l1ToL2MessagesHash: [Fr, Fr], ) {} static getFields(fields: FieldsOf) { - return [fields.aggregationObject, fields.archive, fields.header, fields.l1ToL2MessagesHash] as const; + return [fields.aggregationObject, fields.archive, fields.header] as const; } toBuffer() { @@ -112,7 +109,6 @@ export class RootRollupPublicInputs { reader.readObject(AggregationObject), reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(Header), - reader.readArray(NUM_FIELDS_PER_SHA256, Fr) as [Fr, Fr], ); } } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 75ea5e922ae0..c87f70c978f6 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -1067,7 +1067,6 @@ export function makeRootRollupPublicInputs( aggregationObject: makeAggregationObject(seed), archive: makeAppendOnlyTreeSnapshot(seed + 0x100), header: makeHeader(seed + 0x200, blockNumber), - l1ToL2MessagesHash: [new Fr(3n), new Fr(4n)], }); } diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 1c165f6b4379..8f2ffd894c76 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1700,7 +1700,6 @@ export function mapRootRollupPublicInputsFromNoir( AggregationObject.makeFake(), mapAppendOnlyTreeSnapshotFromNoir(rootRollupPublicInputs.archive), mapHeaderFromNoir(rootRollupPublicInputs.header), - mapTupleFromNoir(rootRollupPublicInputs.l1_to_l2_messages_hash, 2, mapFieldFromNoir), ); } From 4607876df8ac002646ec89bc43c0da7cecf8f544 Mon Sep 17 00:00:00 2001 From: benesjan Date: Sun, 17 Mar 2024 15:55:06 +0000 Subject: [PATCH 02/13] DataRetrieval cleanup --- yarn-project/archiver/src/archiver/archiver.ts | 7 +------ .../archiver/src/archiver/archiver_store.ts | 6 +++--- .../src/archiver/archiver_store_test_suite.ts | 8 ++++---- .../archiver/src/archiver/data_retrieval.ts | 18 +++++++++--------- .../kv_archiver_store/kv_archiver_store.ts | 8 ++++---- .../kv_archiver_store/message_store.ts | 12 ++++++------ .../memory_archiver_store.ts | 12 ++++++------ 7 files changed, 33 insertions(+), 38 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 395c227343e1..0f0f09628f00 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -195,12 +195,7 @@ export class Archiver implements ArchiveSource { ); } - await this.store.addL1ToL2Messages( - retrievedL1ToL2Messages.retrievedData, - // -1n because the function expects the last block in which the message was emitted and not the one after next - // TODO(#5264): Check whether this could be cleaned up - `nextEthBlockNumber` value doesn't seem to be used much - retrievedL1ToL2Messages.nextEthBlockNumber - 1n, - ); + await this.store.addL1ToL2Messages(retrievedL1ToL2Messages); // Read all data from chain and then write to our stores at the end const nextExpectedL2BlockNum = BigInt((await this.store.getSynchedL2BlockNumber()) + 1); diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 30876c75e9bd..4f151ba4f5dd 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -13,6 +13,7 @@ import { import { Fr } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/types/contracts'; +import { DataRetrieval } from './data_retrieval.js'; /** * Represents the latest L1 block processed by the archiver for various objects in L2. @@ -88,11 +89,10 @@ export interface ArchiverDataStore { /** * Append L1 to L2 messages to the store. - * @param messages - The L1 to L2 messages to be added to the store. - * @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted. + * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block. * @returns True if the operation is successful. */ - addL1ToL2Messages(messages: InboxLeaf[], lastMessageL1BlockNumber: bigint): Promise; + addL1ToL2Messages(messages: DataRetrieval): Promise; /** * Gets L1 to L2 message (to be) included in a given block. diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 2bb4badb706e..80956dfdcdc2 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -98,7 +98,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); it('returns the L1 block number that most recently added messages from inbox', async () => { - await store.addL1ToL2Messages([new InboxLeaf(0n, 0n, Fr.ZERO)], 1n); + await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 1n, retrievedData: [new InboxLeaf(0n, 0n, Fr.ZERO)]}); await expect(store.getSynchedL1BlockNumbers()).resolves.toEqual({ blocks: 0n, messages: 1n, @@ -169,7 +169,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch it('returns messages in correct order', async () => { const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize); const shuffledMessages = msgs.slice().sort(() => randomInt(1) - 0.5); - await store.addL1ToL2Messages(shuffledMessages, 100n); + await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 100n, retrievedData: shuffledMessages}); const retrievedMessages = await store.getL1ToL2Messages(l2BlockNumber); const expectedLeavesOrder = msgs.map(msg => msg.leaf); @@ -182,7 +182,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch // --> with that there will be a gap and it will be impossible to sequence the messages msgs[4] = new InboxLeaf(l2BlockNumber, BigInt(l1ToL2MessageSubtreeSize - 1), Fr.random()); - await store.addL1ToL2Messages(msgs, 100n); + await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 100n, retrievedData: msgs}); await expect(async () => { await store.getL1ToL2Messages(l2BlockNumber); }).rejects.toThrow(`L1 to L2 message gap found in block ${l2BlockNumber}`); @@ -192,7 +192,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize + 1); await expect(async () => { - await store.addL1ToL2Messages(msgs, 100n); + await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 100n, retrievedData: msgs}); }).rejects.toThrow(`Message index ${l1ToL2MessageSubtreeSize} out of subtree range`); }); }); diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index 25d4f90be2df..b5271cb62343 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -16,11 +16,11 @@ import { /** * Data retrieved from logs */ -type DataRetrieval = { +export type DataRetrieval = { /** - * The next block number. + * Blocknumber of the last L1 block from which we obtained data. */ - nextEthBlockNumber: bigint; + lastProcessedL1BlockNumber: bigint; /** * The data returned. */ @@ -66,10 +66,10 @@ export async function retrieveBlockMetadataFromRollup( l2BlockProcessedLogs, ); retrievedBlockMetadata.push(...newBlockMetadata); - searchStartBlock = l2BlockProcessedLogs[l2BlockProcessedLogs.length - 1].blockNumber! + 1n; + searchStartBlock = l2BlockProcessedLogs[l2BlockProcessedLogs.length - 1].blockNumber!; expectedNextL2BlockNum += BigInt(newBlockMetadata.length); } while (blockUntilSynced && searchStartBlock <= searchEndBlock); - return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedBlockMetadata }; + return { lastProcessedL1BlockNumber: searchStartBlock, retrievedData: retrievedBlockMetadata }; } /** @@ -106,9 +106,9 @@ export async function retrieveBlockBodiesFromAvailabilityOracle( const newBlockBodies = await processTxsPublishedLogs(publicClient, l2TxsPublishedLogs); retrievedBlockBodies.push(...newBlockBodies); - searchStartBlock = l2TxsPublishedLogs[l2TxsPublishedLogs.length - 1].blockNumber! + 1n; + searchStartBlock = l2TxsPublishedLogs[l2TxsPublishedLogs.length - 1].blockNumber!; } while (blockUntilSynced && searchStartBlock <= searchEndBlock); - return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedBlockBodies }; + return { lastProcessedL1BlockNumber: searchStartBlock, retrievedData: retrievedBlockBodies }; } /** @@ -139,7 +139,7 @@ export async function retrieveL1ToL2Messages( const l1ToL2Messages = processLeafInsertedLogs(leafInsertedLogs); retrievedL1ToL2Messages.push(...l1ToL2Messages); // handles the case when there are no new messages: - searchStartBlock = (leafInsertedLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock) + 1n; + searchStartBlock = (leafInsertedLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock); } while (blockUntilSynced && searchStartBlock <= searchEndBlock); - return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedL1ToL2Messages }; + return { lastProcessedL1BlockNumber: searchStartBlock, retrievedData: retrievedL1ToL2Messages }; } diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index 834737e5a9d7..9172b16076b4 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -23,6 +23,7 @@ import { ContractClassStore } from './contract_class_store.js'; import { ContractInstanceStore } from './contract_instance_store.js'; import { LogStore } from './log_store.js'; import { MessageStore } from './message_store.js'; +import { DataRetrieval } from '../data_retrieval.js'; /** * LMDB implementation of the ArchiverDataStore interface. @@ -145,12 +146,11 @@ export class KVArchiverDataStore implements ArchiverDataStore { /** * Append L1 to L2 messages to the store. - * @param messages - The L1 to L2 messages to be added to the store. - * @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted. + * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block. * @returns True if the operation is successful. */ - addL1ToL2Messages(messages: InboxLeaf[], lastMessageL1BlockNumber: bigint): Promise { - return Promise.resolve(this.#messageStore.addL1ToL2Messages(messages, lastMessageL1BlockNumber)); + addL1ToL2Messages(messages: DataRetrieval): Promise { + return Promise.resolve(this.#messageStore.addL1ToL2Messages(messages)); } /** diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts index 758f261c6ca7..ba1e5cede919 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts @@ -7,6 +7,7 @@ import { } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { AztecKVStore, AztecMap, AztecSingleton } from '@aztec/kv-store'; +import { DataRetrieval } from '../data_retrieval.js'; /** * LMDB implementation of the ArchiverDataStore interface. @@ -36,20 +37,19 @@ export class MessageStore { /** * Append L1 to L2 messages to the store. - * @param messages - The L1 to L2 messages to be added to the store. - * @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted. + * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block. * @returns True if the operation is successful. */ - addL1ToL2Messages(messages: InboxLeaf[], lastMessageL1BlockNumber: bigint): Promise { + addL1ToL2Messages(messages: DataRetrieval): Promise { return this.db.transaction(() => { const lastL1BlockNumber = this.#lastL1BlockMessages.get() ?? 0n; - if (lastL1BlockNumber >= lastMessageL1BlockNumber) { + if (lastL1BlockNumber >= messages.lastProcessedL1BlockNumber) { return false; } - void this.#lastL1BlockMessages.set(lastMessageL1BlockNumber); + void this.#lastL1BlockMessages.set(messages.lastProcessedL1BlockNumber); - for (const message of messages) { + for (const message of messages.retrievedData) { if (message.index >= this.#l1ToL2MessagesSubtreeSize) { throw new Error(`Message index ${message.index} out of subtree range`); } diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index 657ea8679c08..bbebf4e9f80d 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -21,6 +21,7 @@ import { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/types/c import { ArchiverDataStore, ArchiverL1SynchPoint } from '../archiver_store.js'; import { L1ToL2MessageStore } from './l1_to_l2_message_store.js'; +import { DataRetrieval } from '../data_retrieval.js'; /** * Simple, in-memory implementation of an archiver data store. @@ -156,17 +157,16 @@ export class MemoryArchiverStore implements ArchiverDataStore { /** * Append L1 to L2 messages to the store. - * @param messages - The L1 to L2 messages to be added to the store. - * @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted. + * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block. * @returns True if the operation is successful. */ - public addL1ToL2Messages(messages: InboxLeaf[], lastMessageL1BlockNumber: bigint): Promise { - if (lastMessageL1BlockNumber <= this.lastL1BlockNewMessages) { + public addL1ToL2Messages(messages: DataRetrieval): Promise { + if (messages.lastProcessedL1BlockNumber <= this.lastL1BlockNewMessages) { return Promise.resolve(false); } - this.lastL1BlockNewMessages = lastMessageL1BlockNumber; - for (const message of messages) { + this.lastL1BlockNewMessages = messages.lastProcessedL1BlockNumber; + for (const message of messages.retrievedData) { this.l1ToL2Messages.addMessage(message); } return Promise.resolve(true); From d9fd5c8768651b0a13c0c3efd016b04cb0b08ed3 Mon Sep 17 00:00:00 2001 From: benesjan Date: Sun, 17 Mar 2024 16:35:39 +0000 Subject: [PATCH 03/13] WIP --- .../archiver/src/archiver/archiver_store.ts | 1 + .../src/archiver/archiver_store_test_suite.ts | 11 +- .../archiver/src/archiver/data_retrieval.ts | 2 +- .../kv_archiver_store/kv_archiver_store.ts | 2 +- .../kv_archiver_store/message_store.ts | 1 + .../memory_archiver_store.ts | 2 +- yarn-project/circuit-types/src/index.ts | 2 +- .../circuit-types/src/l1_to_l2_message.ts | 203 ------------------ .../circuit-types/src/messaging/inbox_leaf.ts | 26 +++ .../circuit-types/src/messaging/index.ts | 5 + .../circuit-types/src/messaging/l1_actor.ts | 43 ++++ .../{ => messaging}/l1_to_l2_message.test.ts | 0 .../src/messaging/l1_to_l2_message.ts | 76 +++++++ .../src/messaging/l1_to_l2_message_source.ts | 26 +++ .../circuit-types/src/messaging/l2_actor.ts | 43 ++++ 15 files changed, 232 insertions(+), 211 deletions(-) delete mode 100644 yarn-project/circuit-types/src/l1_to_l2_message.ts create mode 100644 yarn-project/circuit-types/src/messaging/inbox_leaf.ts create mode 100644 yarn-project/circuit-types/src/messaging/index.ts create mode 100644 yarn-project/circuit-types/src/messaging/l1_actor.ts rename yarn-project/circuit-types/src/{ => messaging}/l1_to_l2_message.test.ts (100%) create mode 100644 yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts create mode 100644 yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts create mode 100644 yarn-project/circuit-types/src/messaging/l2_actor.ts diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 4f151ba4f5dd..472a52fed08c 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -13,6 +13,7 @@ import { import { Fr } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/types/contracts'; + import { DataRetrieval } from './data_retrieval.js'; /** diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 80956dfdcdc2..3045ae32b36e 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -98,7 +98,10 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); it('returns the L1 block number that most recently added messages from inbox', async () => { - await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 1n, retrievedData: [new InboxLeaf(0n, 0n, Fr.ZERO)]}); + await store.addL1ToL2Messages({ + lastProcessedL1BlockNumber: 1n, + retrievedData: [new InboxLeaf(0n, 0n, Fr.ZERO)], + }); await expect(store.getSynchedL1BlockNumbers()).resolves.toEqual({ blocks: 0n, messages: 1n, @@ -169,7 +172,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch it('returns messages in correct order', async () => { const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize); const shuffledMessages = msgs.slice().sort(() => randomInt(1) - 0.5); - await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 100n, retrievedData: shuffledMessages}); + await store.addL1ToL2Messages({ lastProcessedL1BlockNumber: 100n, retrievedData: shuffledMessages }); const retrievedMessages = await store.getL1ToL2Messages(l2BlockNumber); const expectedLeavesOrder = msgs.map(msg => msg.leaf); @@ -182,7 +185,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch // --> with that there will be a gap and it will be impossible to sequence the messages msgs[4] = new InboxLeaf(l2BlockNumber, BigInt(l1ToL2MessageSubtreeSize - 1), Fr.random()); - await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 100n, retrievedData: msgs}); + await store.addL1ToL2Messages({ lastProcessedL1BlockNumber: 100n, retrievedData: msgs }); await expect(async () => { await store.getL1ToL2Messages(l2BlockNumber); }).rejects.toThrow(`L1 to L2 message gap found in block ${l2BlockNumber}`); @@ -192,7 +195,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize + 1); await expect(async () => { - await store.addL1ToL2Messages({lastProcessedL1BlockNumber: 100n, retrievedData: msgs}); + await store.addL1ToL2Messages({ lastProcessedL1BlockNumber: 100n, retrievedData: msgs }); }).rejects.toThrow(`Message index ${l1ToL2MessageSubtreeSize} out of subtree range`); }); }); diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index b5271cb62343..af630a1f6b19 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -139,7 +139,7 @@ export async function retrieveL1ToL2Messages( const l1ToL2Messages = processLeafInsertedLogs(leafInsertedLogs); retrievedL1ToL2Messages.push(...l1ToL2Messages); // handles the case when there are no new messages: - searchStartBlock = (leafInsertedLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock); + searchStartBlock = leafInsertedLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock; } while (blockUntilSynced && searchStartBlock <= searchEndBlock); return { lastProcessedL1BlockNumber: searchStartBlock, retrievedData: retrievedL1ToL2Messages }; } diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index 9172b16076b4..cd52432d4882 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -17,13 +17,13 @@ import { AztecKVStore } from '@aztec/kv-store'; import { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/types/contracts'; import { ArchiverDataStore, ArchiverL1SynchPoint } from '../archiver_store.js'; +import { DataRetrieval } from '../data_retrieval.js'; import { BlockBodyStore } from './block_body_store.js'; import { BlockStore } from './block_store.js'; import { ContractClassStore } from './contract_class_store.js'; import { ContractInstanceStore } from './contract_instance_store.js'; import { LogStore } from './log_store.js'; import { MessageStore } from './message_store.js'; -import { DataRetrieval } from '../data_retrieval.js'; /** * LMDB implementation of the ArchiverDataStore interface. diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts index ba1e5cede919..25a4c7b74ffb 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts @@ -7,6 +7,7 @@ import { } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { AztecKVStore, AztecMap, AztecSingleton } from '@aztec/kv-store'; + import { DataRetrieval } from '../data_retrieval.js'; /** diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index bbebf4e9f80d..d8d1b4ad08d9 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -20,8 +20,8 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/types/contracts'; import { ArchiverDataStore, ArchiverL1SynchPoint } from '../archiver_store.js'; -import { L1ToL2MessageStore } from './l1_to_l2_message_store.js'; import { DataRetrieval } from '../data_retrieval.js'; +import { L1ToL2MessageStore } from './l1_to_l2_message_store.js'; /** * Simple, in-memory implementation of an archiver data store. diff --git a/yarn-project/circuit-types/src/index.ts b/yarn-project/circuit-types/src/index.ts index 5928dc19c185..31213c9cb9bb 100644 --- a/yarn-project/circuit-types/src/index.ts +++ b/yarn-project/circuit-types/src/index.ts @@ -1,7 +1,7 @@ export * from './function_call.js'; export * from './keys/index.js'; export * from './notes/index.js'; -export * from './l1_to_l2_message.js'; +export * from './messaging/index.js'; export * from './l2_block.js'; export * from './body.js'; export * from './l2_block_context.js'; diff --git a/yarn-project/circuit-types/src/l1_to_l2_message.ts b/yarn-project/circuit-types/src/l1_to_l2_message.ts deleted file mode 100644 index eabc17cc934b..000000000000 --- a/yarn-project/circuit-types/src/l1_to_l2_message.ts +++ /dev/null @@ -1,203 +0,0 @@ -// TODO(#5264) Separate classes here to individual files, rename InboxLeaf to something less ugly and check usage of L1ToL2Message. -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; -import { randomInt, sha256 } from '@aztec/foundation/crypto'; -import { EthAddress } from '@aztec/foundation/eth-address'; -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; - -/** - * Interface of classes allowing for the retrieval of L1 to L2 messages. - */ -export interface L1ToL2MessageSource { - /** - * Gets new L1 to L2 message (to be) included in a given block. - * @param blockNumber - L2 block number to get messages for. - * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found). - */ - getL1ToL2Messages(blockNumber: bigint): Promise; - - /** - * Gets the L1 to L2 message index in the L1 to L2 message tree. - * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. - */ - getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise; - - /** - * Gets the number of the latest L2 block processed by the implementation. - * @returns The number of the latest L2 block processed by the implementation. - */ - getBlockNumber(): Promise; -} - -export class InboxLeaf { - constructor( - /** L2 block number in which the message will be included. */ - public readonly blockNumber: bigint, - /** Index of the leaf in L2 block message subtree. */ - public readonly index: bigint, - /** Leaf of the subtree. */ - public readonly leaf: Fr, - ) {} - - toBuffer(): Buffer { - return serializeToBuffer([this.blockNumber, this.index, this.leaf]); - } - - fromBuffer(buffer: Buffer | BufferReader): InboxLeaf { - const reader = BufferReader.asReader(buffer); - const blockNumber = toBigIntBE(reader.readBytes(32)); - const index = toBigIntBE(reader.readBytes(32)); - const leaf = reader.readObject(Fr); - return new InboxLeaf(blockNumber, index, leaf); - } -} - -/** - * The format of an L1 to L2 Message. - */ -export class L1ToL2Message { - constructor( - /** - * The sender of the message on L1. - */ - public readonly sender: L1Actor, - /** - * The recipient of the message on L2. - */ - public readonly recipient: L2Actor, - /** - * The message content. - */ - public readonly content: Fr, - /** - * The hash of the spending secret. - */ - public readonly secretHash: Fr, - /** - * The entry key for the message - optional. - */ - public readonly entryKey?: Fr, - ) {} - - /** - * Returns each element within its own field so that it can be consumed by an acvm oracle call. - * @returns The message as an array of fields (in order). - */ - toFields(): Fr[] { - return [...this.sender.toFields(), ...this.recipient.toFields(), this.content, this.secretHash]; - } - - toBuffer(): Buffer { - return serializeToBuffer(this.sender, this.recipient, this.content, this.secretHash); - } - - hash(): Fr { - return Fr.fromBufferReduce(sha256(serializeToBuffer(...this.toFields()))); - } - - static fromBuffer(buffer: Buffer | BufferReader): L1ToL2Message { - const reader = BufferReader.asReader(buffer); - const sender = reader.readObject(L1Actor); - const recipient = reader.readObject(L2Actor); - const content = Fr.fromBuffer(reader); - const secretHash = Fr.fromBuffer(reader); - return new L1ToL2Message(sender, recipient, content, secretHash); - } - - toString(): string { - return this.toBuffer().toString('hex'); - } - - static fromString(data: string): L1ToL2Message { - const buffer = Buffer.from(data, 'hex'); - return L1ToL2Message.fromBuffer(buffer); - } - - static empty(): L1ToL2Message { - return new L1ToL2Message(L1Actor.empty(), L2Actor.empty(), Fr.ZERO, Fr.ZERO); - } - - static random(entryKey?: Fr): L1ToL2Message { - return new L1ToL2Message(L1Actor.random(), L2Actor.random(), Fr.random(), Fr.random(), entryKey); - } -} - -/** - * The sender of an L1 to L2 message. - */ -export class L1Actor { - constructor( - /** - * The sender of the message. - */ - public readonly sender: EthAddress, - /** - * The chain id on which the message was sent. - */ - public readonly chainId: number, - ) {} - - static empty() { - return new L1Actor(EthAddress.ZERO, 0); - } - - toFields(): Fr[] { - return [this.sender.toField(), new Fr(BigInt(this.chainId))]; - } - - toBuffer(): Buffer { - return serializeToBuffer(this.sender, this.chainId); - } - - static fromBuffer(buffer: Buffer | BufferReader): L1Actor { - const reader = BufferReader.asReader(buffer); - const ethAddr = reader.readObject(EthAddress); - const chainId = reader.readNumber(); - return new L1Actor(ethAddr, chainId); - } - - static random(): L1Actor { - return new L1Actor(EthAddress.random(), randomInt(1000)); - } -} - -/** - * The recipient of an L2 message. - */ -export class L2Actor { - constructor( - /** - * The recipient of the message. - */ - public readonly recipient: AztecAddress, - /** - * The version of the protocol. - */ - public readonly version: number, - ) {} - - static empty() { - return new L2Actor(AztecAddress.ZERO, 0); - } - - toFields(): Fr[] { - return [this.recipient.toField(), new Fr(BigInt(this.version))]; - } - - toBuffer(): Buffer { - return serializeToBuffer(this.recipient, this.version); - } - - static fromBuffer(buffer: Buffer | BufferReader): L2Actor { - const reader = BufferReader.asReader(buffer); - const aztecAddr = AztecAddress.fromBuffer(reader); - const version = reader.readNumber(); - return new L2Actor(aztecAddr, version); - } - - static random(): L2Actor { - return new L2Actor(AztecAddress.random(), randomInt(1000)); - } -} diff --git a/yarn-project/circuit-types/src/messaging/inbox_leaf.ts b/yarn-project/circuit-types/src/messaging/inbox_leaf.ts new file mode 100644 index 000000000000..cad0db349d23 --- /dev/null +++ b/yarn-project/circuit-types/src/messaging/inbox_leaf.ts @@ -0,0 +1,26 @@ +import { Fr } from '@aztec/circuits.js'; +import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +export class InboxLeaf { + constructor( + /** L2 block number in which the message will be included. */ + public readonly blockNumber: bigint, + /** Index of the leaf in L2 block message subtree. */ + public readonly index: bigint, + /** Leaf of the subtree. */ + public readonly leaf: Fr, + ) {} + + toBuffer(): Buffer { + return serializeToBuffer([this.blockNumber, this.index, this.leaf]); + } + + fromBuffer(buffer: Buffer | BufferReader): InboxLeaf { + const reader = BufferReader.asReader(buffer); + const blockNumber = toBigIntBE(reader.readBytes(32)); + const index = toBigIntBE(reader.readBytes(32)); + const leaf = reader.readObject(Fr); + return new InboxLeaf(blockNumber, index, leaf); + } +} diff --git a/yarn-project/circuit-types/src/messaging/index.ts b/yarn-project/circuit-types/src/messaging/index.ts new file mode 100644 index 000000000000..9cbe7158e6f9 --- /dev/null +++ b/yarn-project/circuit-types/src/messaging/index.ts @@ -0,0 +1,5 @@ +export * from './inbox_leaf.js'; +export * from './l1_to_l2_message.js'; +export * from './l1_to_l2_message_source.js'; +export * from './l1_actor.js'; +export * from './l2_actor.js'; diff --git a/yarn-project/circuit-types/src/messaging/l1_actor.ts b/yarn-project/circuit-types/src/messaging/l1_actor.ts new file mode 100644 index 000000000000..e30e001cbf30 --- /dev/null +++ b/yarn-project/circuit-types/src/messaging/l1_actor.ts @@ -0,0 +1,43 @@ +import { randomInt } from '@aztec/foundation/crypto'; +import { EthAddress } from '@aztec/foundation/eth-address'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +/** + * The sender of an L1 to L2 message. + */ +export class L1Actor { + constructor( + /** + * The sender of the message. + */ + public readonly sender: EthAddress, + /** + * The chain id on which the message was sent. + */ + public readonly chainId: number, + ) {} + + static empty() { + return new L1Actor(EthAddress.ZERO, 0); + } + + toFields(): Fr[] { + return [this.sender.toField(), new Fr(BigInt(this.chainId))]; + } + + toBuffer(): Buffer { + return serializeToBuffer(this.sender, this.chainId); + } + + static fromBuffer(buffer: Buffer | BufferReader): L1Actor { + const reader = BufferReader.asReader(buffer); + const ethAddr = reader.readObject(EthAddress); + const chainId = reader.readNumber(); + return new L1Actor(ethAddr, chainId); + } + + static random(): L1Actor { + return new L1Actor(EthAddress.random(), randomInt(1000)); + } +} diff --git a/yarn-project/circuit-types/src/l1_to_l2_message.test.ts b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.test.ts similarity index 100% rename from yarn-project/circuit-types/src/l1_to_l2_message.test.ts rename to yarn-project/circuit-types/src/messaging/l1_to_l2_message.test.ts diff --git a/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts new file mode 100644 index 000000000000..551753c8061b --- /dev/null +++ b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts @@ -0,0 +1,76 @@ +import { sha256 } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { L1Actor } from './l1_actor.js'; +import { L2Actor } from './l2_actor.js'; + +/** + * The format of an L1 to L2 Message. + */ +export class L1ToL2Message { + constructor( + /** + * The sender of the message on L1. + */ + public readonly sender: L1Actor, + /** + * The recipient of the message on L2. + */ + public readonly recipient: L2Actor, + /** + * The message content. + */ + public readonly content: Fr, + /** + * The hash of the spending secret. + */ + public readonly secretHash: Fr, + /** + * The entry key for the message - optional. + */ + public readonly entryKey?: Fr, + ) {} + + /** + * Returns each element within its own field so that it can be consumed by an acvm oracle call. + * @returns The message as an array of fields (in order). + */ + toFields(): Fr[] { + return [...this.sender.toFields(), ...this.recipient.toFields(), this.content, this.secretHash]; + } + + toBuffer(): Buffer { + return serializeToBuffer(this.sender, this.recipient, this.content, this.secretHash); + } + + hash(): Fr { + return Fr.fromBufferReduce(sha256(serializeToBuffer(...this.toFields()))); + } + + static fromBuffer(buffer: Buffer | BufferReader): L1ToL2Message { + const reader = BufferReader.asReader(buffer); + const sender = reader.readObject(L1Actor); + const recipient = reader.readObject(L2Actor); + const content = Fr.fromBuffer(reader); + const secretHash = Fr.fromBuffer(reader); + return new L1ToL2Message(sender, recipient, content, secretHash); + } + + toString(): string { + return this.toBuffer().toString('hex'); + } + + static fromString(data: string): L1ToL2Message { + const buffer = Buffer.from(data, 'hex'); + return L1ToL2Message.fromBuffer(buffer); + } + + static empty(): L1ToL2Message { + return new L1ToL2Message(L1Actor.empty(), L2Actor.empty(), Fr.ZERO, Fr.ZERO); + } + + static random(entryKey?: Fr): L1ToL2Message { + return new L1ToL2Message(L1Actor.random(), L2Actor.random(), Fr.random(), Fr.random(), entryKey); + } +} diff --git a/yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts b/yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts new file mode 100644 index 000000000000..4e4771404670 --- /dev/null +++ b/yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts @@ -0,0 +1,26 @@ +import { Fr } from '@aztec/foundation/fields'; + +/** + * Interface of classes allowing for the retrieval of L1 to L2 messages. + */ +export interface L1ToL2MessageSource { + /** + * Gets new L1 to L2 message (to be) included in a given block. + * @param blockNumber - L2 block number to get messages for. + * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found). + */ + getL1ToL2Messages(blockNumber: bigint): Promise; + + /** + * Gets the L1 to L2 message index in the L1 to L2 message tree. + * @param l1ToL2Message - The L1 to L2 message. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + */ + getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise; + + /** + * Gets the number of the latest L2 block processed by the implementation. + * @returns The number of the latest L2 block processed by the implementation. + */ + getBlockNumber(): Promise; +} diff --git a/yarn-project/circuit-types/src/messaging/l2_actor.ts b/yarn-project/circuit-types/src/messaging/l2_actor.ts new file mode 100644 index 000000000000..9581a454f1a9 --- /dev/null +++ b/yarn-project/circuit-types/src/messaging/l2_actor.ts @@ -0,0 +1,43 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { randomInt } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +/** + * The recipient of an L2 message. + */ +export class L2Actor { + constructor( + /** + * The recipient of the message. + */ + public readonly recipient: AztecAddress, + /** + * The version of the protocol. + */ + public readonly version: number, + ) {} + + static empty() { + return new L2Actor(AztecAddress.ZERO, 0); + } + + toFields(): Fr[] { + return [this.recipient.toField(), new Fr(BigInt(this.version))]; + } + + toBuffer(): Buffer { + return serializeToBuffer(this.recipient, this.version); + } + + static fromBuffer(buffer: Buffer | BufferReader): L2Actor { + const reader = BufferReader.asReader(buffer); + const aztecAddr = AztecAddress.fromBuffer(reader); + const version = reader.readNumber(); + return new L2Actor(aztecAddr, version); + } + + static random(): L2Actor { + return new L2Actor(AztecAddress.random(), randomInt(1000)); + } +} From 17518eb12ac6e4b3d8d01fde5f213c872ecc3601 Mon Sep 17 00:00:00 2001 From: benesjan Date: Sun, 17 Mar 2024 17:10:17 +0000 Subject: [PATCH 04/13] WIP --- l1-contracts/test/Inbox.t.sol | 5 ++--- l1-contracts/test/Rollup.t.sol | 1 - l1-contracts/test/portals/TokenPortal.t.sol | 10 ++++------ l1-contracts/test/portals/UniswapPortal.t.sol | 4 ++-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/l1-contracts/test/Inbox.t.sol b/l1-contracts/test/Inbox.t.sol index b98d7bc2abdf..a9f02c7f6a5f 100644 --- a/l1-contracts/test/Inbox.t.sol +++ b/l1-contracts/test/Inbox.t.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.18; import {Test} from "forge-std/Test.sol"; +import {IInbox} from "../src/core/interfaces/messagebridge/IInbox.sol"; import {InboxHarness} from "./harnesses/InboxHarness.sol"; import {Constants} from "../src/core/libraries/ConstantsGen.sol"; import {Errors} from "../src/core/libraries/Errors.sol"; @@ -19,8 +20,6 @@ contract InboxTest is Test { uint256 internal version = 0; bytes32 internal emptyTreeRoot; - event LeafInserted(uint256 indexed blockNumber, uint256 index, bytes32 value); - function setUp() public { address rollup = address(this); // We set low depth (5) to ensure we sufficiently test the tree transitions @@ -82,7 +81,7 @@ contract InboxTest is Test { bytes32 leaf = message.sha256ToField(); vm.expectEmit(true, true, true, true); // event we expect - emit LeafInserted(FIRST_REAL_TREE_NUM, 0, leaf); + emit IInbox.LeafInserted(FIRST_REAL_TREE_NUM, 0, leaf); // event we will get bytes32 insertedLeaf = inbox.sendL2Message(message.recipient, message.content, message.secretHash); diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 540b23d69a81..97865988f557 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -137,7 +137,6 @@ contract RollupTest is DecoderBase { assertEq(inbox.toConsume(), toConsume + 1, "Message subtree not consumed"); - (, bytes32[] memory inboxWrites) = vm.accesses(address(inbox)); (, bytes32[] memory outboxWrites) = vm.accesses(address(outbox)); { diff --git a/l1-contracts/test/portals/TokenPortal.t.sol b/l1-contracts/test/portals/TokenPortal.t.sol index 9230214d09dc..6a171b91e4da 100644 --- a/l1-contracts/test/portals/TokenPortal.t.sol +++ b/l1-contracts/test/portals/TokenPortal.t.sol @@ -25,7 +25,6 @@ contract TokenPortalTest is Test { uint256 internal constant FIRST_REAL_TREE_NUM = Constants.INITIAL_L2_BLOCK_NUM + 1; - event LeafInserted(uint256 indexed blockNumber, uint256 index, bytes32 value); event MessageConsumed(bytes32 indexed entryKey, address indexed recipient); Registry internal registry; @@ -69,7 +68,7 @@ contract TokenPortalTest is Test { vm.deal(address(this), 100 ether); } - function _createExpectedMintPrivateL1ToL2Message(address _canceller) + function _createExpectedMintPrivateL1ToL2Message() internal view returns (DataStructures.L1ToL2Msg memory) @@ -105,15 +104,14 @@ contract TokenPortalTest is Test { portalERC20.approve(address(tokenPortal), mintAmount); // Check for the expected message - DataStructures.L1ToL2Msg memory expectedMessage = - _createExpectedMintPrivateL1ToL2Message(address(this)); + DataStructures.L1ToL2Msg memory expectedMessage = _createExpectedMintPrivateL1ToL2Message(); bytes32 expectedLeaf = expectedMessage.sha256ToField(); // Check the event was emitted vm.expectEmit(true, true, true, true); // event we expect - emit LeafInserted(FIRST_REAL_TREE_NUM, 0, expectedLeaf); + emit IInbox.LeafInserted(FIRST_REAL_TREE_NUM, 0, expectedLeaf); // event we will get // Perform op @@ -138,7 +136,7 @@ contract TokenPortalTest is Test { // Check the event was emitted vm.expectEmit(true, true, true, true); // event we expect - emit LeafInserted(FIRST_REAL_TREE_NUM, 0, expectedLeaf); + emit IInbox.LeafInserted(FIRST_REAL_TREE_NUM, 0, expectedLeaf); // Perform op bytes32 leaf = tokenPortal.depositToAztecPublic(to, amount, secretHashForL2MessageConsumption); diff --git a/l1-contracts/test/portals/UniswapPortal.t.sol b/l1-contracts/test/portals/UniswapPortal.t.sol index caf48bf6137a..51caae33470a 100644 --- a/l1-contracts/test/portals/UniswapPortal.t.sol +++ b/l1-contracts/test/portals/UniswapPortal.t.sol @@ -231,7 +231,7 @@ contract UniswapPortalTest is Test { bytes32 swapEntryKey = _createUniswapSwapMessagePublic(aztecRecipient, address(this)); _addMessagesToOutbox(daiWithdrawEntryKey, swapEntryKey); - bytes32 l1ToL2EntryKey = uniswapPortal.swapPublic( + uniswapPortal.swapPublic( address(daiTokenPortal), amount, uniswapFeePool, @@ -260,7 +260,7 @@ contract UniswapPortalTest is Test { _addMessagesToOutbox(daiWithdrawEntryKey, swapEntryKey); vm.prank(_caller); - bytes32 l1ToL2EntryKey = uniswapPortal.swapPublic( + uniswapPortal.swapPublic( address(daiTokenPortal), amount, uniswapFeePool, From c2a316172b1ccf1dc5d35cde28d73cb1e9bbbe0c Mon Sep 17 00:00:00 2001 From: benesjan Date: Sun, 17 Mar 2024 17:18:24 +0000 Subject: [PATCH 05/13] WIP --- .../aztec-node/src/aztec-node/server.ts | 20 +++++++++---------- .../src/interfaces/aztec-node.ts | 4 +--- .../src/interfaces/block_number.ts | 2 ++ .../circuit-types/src/interfaces/index.ts | 1 + 4 files changed, 14 insertions(+), 13 deletions(-) create mode 100644 yarn-project/circuit-types/src/interfaces/block_number.ts diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index cc851ee4258b..8ba10d552989 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -327,7 +327,7 @@ export class AztecNodeService implements AztecNode { * @returns The index of the given leaf in the given tree or undefined if not found. */ public async findLeafIndex( - blockNumber: number | 'latest', + blockNumber: BlockNumber, treeId: MerkleTreeId, leafValue: Fr, ): Promise { @@ -342,7 +342,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path for the leaf index. */ public async getNullifierSiblingPath( - blockNumber: number | 'latest', + blockNumber: BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -356,7 +356,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path for the leaf index. */ public async getNoteHashSiblingPath( - blockNumber: number | 'latest', + blockNumber: BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -393,7 +393,7 @@ export class AztecNodeService implements AztecNode { * @returns A tuple of the index and the sibling path of the L2ToL1Message. */ public async getL2ToL1MessageIndexAndSiblingPath( - blockNumber: number | 'latest', + blockNumber: BlockNumber, l2ToL1Message: Fr, ): Promise<[number, SiblingPath]> { const block = await this.blockSource.getBlock(blockNumber === 'latest' ? await this.getBlockNumber() : blockNumber); @@ -431,7 +431,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path. */ public async getArchiveSiblingPath( - blockNumber: number | 'latest', + blockNumber: BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -445,7 +445,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path. */ public async getPublicDataSiblingPath( - blockNumber: number | 'latest', + blockNumber: BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -459,7 +459,7 @@ export class AztecNodeService implements AztecNode { * @returns The nullifier membership witness (if found). */ public async getNullifierMembershipWitness( - blockNumber: number | 'latest', + blockNumber: BlockNumber, nullifier: Fr, ): Promise { const db = await this.#getWorldState(blockNumber); @@ -498,7 +498,7 @@ export class AztecNodeService implements AztecNode { * TODO: This is a confusing behavior and we should eventually address that. */ public async getLowNullifierMembershipWitness( - blockNumber: number | 'latest', + blockNumber: BlockNumber, nullifier: Fr, ): Promise { const committedDb = await this.#getWorldState(blockNumber); @@ -519,7 +519,7 @@ export class AztecNodeService implements AztecNode { return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath); } - async getPublicDataTreeWitness(blockNumber: number | 'latest', leafSlot: Fr): Promise { + async getPublicDataTreeWitness(blockNumber: BlockNumber, leafSlot: Fr): Promise { const committedDb = await this.#getWorldState(blockNumber); const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt()); if (!lowLeafResult) { @@ -631,7 +631,7 @@ export class AztecNodeService implements AztecNode { * @param blockNumber - The block number at which to get the data. * @returns An instance of a committed MerkleTreeOperations */ - async #getWorldState(blockNumber: number | 'latest') { + async #getWorldState(blockNumber: BlockNumber) { if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM) { throw new Error('Invalid block number to get world state for: ' + blockNumber); } diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index dffadd90541f..2d25ab3a0b8c 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -17,13 +17,11 @@ import { MerkleTreeId } from '../merkle_tree_id.js'; import { SiblingPath } from '../sibling_path/index.js'; import { Tx, TxHash, TxReceipt } from '../tx/index.js'; import { TxEffect } from '../tx_effect.js'; +import { BlockNumber } from './block_number.js'; import { SequencerConfig } from './configs.js'; import { NullifierMembershipWitness } from './nullifier_tree.js'; import { PublicDataWitness } from './public_data_tree.js'; -/** Helper type for a specific L2 block number or the latest block number */ -export type BlockNumber = number | 'latest'; - /** * The aztec node. * We will probably implement the additional interfaces by means other than Aztec Node as it's currently a privacy leak diff --git a/yarn-project/circuit-types/src/interfaces/block_number.ts b/yarn-project/circuit-types/src/interfaces/block_number.ts new file mode 100644 index 000000000000..aaf0c954d66c --- /dev/null +++ b/yarn-project/circuit-types/src/interfaces/block_number.ts @@ -0,0 +1,2 @@ +/** Helper type for a specific L2 block number or the latest block number */ +export type BlockNumber = number | 'latest'; diff --git a/yarn-project/circuit-types/src/interfaces/index.ts b/yarn-project/circuit-types/src/interfaces/index.ts index c658367b918f..21d47639fc72 100644 --- a/yarn-project/circuit-types/src/interfaces/index.ts +++ b/yarn-project/circuit-types/src/interfaces/index.ts @@ -1,4 +1,5 @@ export * from './aztec-node.js'; +export * from './block_number.js'; export * from './pxe.js'; export * from './sync-status.js'; export * from './configs.js'; From 0528d33d0b83aebc8adb4e46c22b116440291229 Mon Sep 17 00:00:00 2001 From: benesjan Date: Sun, 17 Mar 2024 18:31:57 +0000 Subject: [PATCH 06/13] trying to re-trigger messed up CI --- l1-contracts/src/core/interfaces/messagebridge/IInbox.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/src/core/interfaces/messagebridge/IInbox.sol b/l1-contracts/src/core/interfaces/messagebridge/IInbox.sol index 8bc025a54f07..b5a261d0ef38 100644 --- a/l1-contracts/src/core/interfaces/messagebridge/IInbox.sol +++ b/l1-contracts/src/core/interfaces/messagebridge/IInbox.sol @@ -7,7 +7,7 @@ import {DataStructures} from "../../libraries/DataStructures.sol"; /** * @title Inbox * @author Aztec Labs - * @notice Lives on L1 and is used to pass messages into the rollup, e.g., L1 -> L2 messages. + * @notice Lives on L1 and is used to pass messages into the rollup from L1. */ interface IInbox { event LeafInserted(uint256 indexed blockNumber, uint256 index, bytes32 value); From dfd769a1533ac597b2373fb9b3627239fa07f1e1 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 18 Mar 2024 11:20:33 +0000 Subject: [PATCH 07/13] BlockNumber -> L2BlockNumber --- .../aztec-node/src/aztec-node/server.ts | 24 +++++++++---------- .../src/interfaces/aztec-node.ts | 22 ++++++++--------- .../circuit-types/src/interfaces/index.ts | 2 +- .../{block_number.ts => l2_block_number.ts} | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) rename yarn-project/circuit-types/src/interfaces/{block_number.ts => l2_block_number.ts} (62%) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 8ba10d552989..3eaed4684823 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -1,11 +1,11 @@ import { ArchiveSource, Archiver, KVArchiverDataStore, createArchiverClient } from '@aztec/archiver'; import { AztecNode, - BlockNumber, GetUnencryptedLogsResponse, L1ToL2MessageSource, L2Block, L2BlockL2Logs, + L2BlockNumber, L2BlockSource, L2LogsSource, LogFilter, @@ -327,7 +327,7 @@ export class AztecNodeService implements AztecNode { * @returns The index of the given leaf in the given tree or undefined if not found. */ public async findLeafIndex( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, treeId: MerkleTreeId, leafValue: Fr, ): Promise { @@ -342,7 +342,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path for the leaf index. */ public async getNullifierSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -356,7 +356,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path for the leaf index. */ public async getNoteHashSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -371,7 +371,7 @@ export class AztecNodeService implements AztecNode { * @returns A tuple of the index and the sibling path of the L1ToL2Message. */ public async getL1ToL2MessageIndexAndSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, l1ToL2Message: Fr, ): Promise<[bigint, SiblingPath]> { const index = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message); @@ -393,7 +393,7 @@ export class AztecNodeService implements AztecNode { * @returns A tuple of the index and the sibling path of the L2ToL1Message. */ public async getL2ToL1MessageIndexAndSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, l2ToL1Message: Fr, ): Promise<[number, SiblingPath]> { const block = await this.blockSource.getBlock(blockNumber === 'latest' ? await this.getBlockNumber() : blockNumber); @@ -431,7 +431,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path. */ public async getArchiveSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -445,7 +445,7 @@ export class AztecNodeService implements AztecNode { * @returns The sibling path. */ public async getPublicDataSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, leafIndex: bigint, ): Promise> { const committedDb = await this.#getWorldState(blockNumber); @@ -459,7 +459,7 @@ export class AztecNodeService implements AztecNode { * @returns The nullifier membership witness (if found). */ public async getNullifierMembershipWitness( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, nullifier: Fr, ): Promise { const db = await this.#getWorldState(blockNumber); @@ -498,7 +498,7 @@ export class AztecNodeService implements AztecNode { * TODO: This is a confusing behavior and we should eventually address that. */ public async getLowNullifierMembershipWitness( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, nullifier: Fr, ): Promise { const committedDb = await this.#getWorldState(blockNumber); @@ -519,7 +519,7 @@ export class AztecNodeService implements AztecNode { return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath); } - async getPublicDataTreeWitness(blockNumber: BlockNumber, leafSlot: Fr): Promise { + async getPublicDataTreeWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise { const committedDb = await this.#getWorldState(blockNumber); const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt()); if (!lowLeafResult) { @@ -631,7 +631,7 @@ export class AztecNodeService implements AztecNode { * @param blockNumber - The block number at which to get the data. * @returns An instance of a committed MerkleTreeOperations */ - async #getWorldState(blockNumber: BlockNumber) { + async #getWorldState(blockNumber: L2BlockNumber) { if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM) { throw new Error('Invalid block number to get world state for: ' + blockNumber); } diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 2d25ab3a0b8c..e1b0955d22f0 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -17,8 +17,8 @@ import { MerkleTreeId } from '../merkle_tree_id.js'; import { SiblingPath } from '../sibling_path/index.js'; import { Tx, TxHash, TxReceipt } from '../tx/index.js'; import { TxEffect } from '../tx_effect.js'; -import { BlockNumber } from './block_number.js'; import { SequencerConfig } from './configs.js'; +import { L2BlockNumber } from './l2_block_number.js'; import { NullifierMembershipWitness } from './nullifier_tree.js'; import { PublicDataWitness } from './public_data_tree.js'; @@ -34,7 +34,7 @@ export interface AztecNode { * @param leafValue - The value to search for * @returns The index of the given leaf in the given tree or undefined if not found. */ - findLeafIndex(blockNumber: BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise; + findLeafIndex(blockNumber: L2BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise; /** * Returns a sibling path for the given index in the nullifier tree. @@ -43,7 +43,7 @@ export interface AztecNode { * @returns The sibling path for the leaf index. */ getNullifierSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, leafIndex: bigint, ): Promise>; @@ -54,7 +54,7 @@ export interface AztecNode { * @returns The sibling path for the leaf index. */ getNoteHashSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, leafIndex: bigint, ): Promise>; @@ -66,7 +66,7 @@ export interface AztecNode { * @returns A tuple of the index and the sibling path of the message. */ getL1ToL2MessageIndexAndSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, l1ToL2Message: Fr, ): Promise<[bigint, SiblingPath]>; @@ -80,7 +80,7 @@ export interface AztecNode { * @returns A tuple of the index and the sibling path of the L2ToL1Message. */ getL2ToL1MessageIndexAndSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, l2ToL1Message: Fr, ): Promise<[number, SiblingPath]>; @@ -90,7 +90,7 @@ export interface AztecNode { * @param leafIndex - Index of the leaf in the tree. * @returns The sibling path. */ - getArchiveSiblingPath(blockNumber: BlockNumber, leafIndex: bigint): Promise>; + getArchiveSiblingPath(blockNumber: L2BlockNumber, leafIndex: bigint): Promise>; /** * Returns a sibling path for a leaf in the committed public data tree. @@ -99,7 +99,7 @@ export interface AztecNode { * @returns The sibling path. */ getPublicDataSiblingPath( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, leafIndex: bigint, ): Promise>; @@ -110,7 +110,7 @@ export interface AztecNode { * @returns The nullifier membership witness (if found). */ getNullifierMembershipWitness( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, nullifier: Fr, ): Promise; @@ -124,7 +124,7 @@ export interface AztecNode { * we are trying to prove non-inclusion for. */ getLowNullifierMembershipWitness( - blockNumber: BlockNumber, + blockNumber: L2BlockNumber, nullifier: Fr, ): Promise; @@ -137,7 +137,7 @@ export interface AztecNode { * "in range" slot, means that the slot doesn't exist and the value is 0. If the low leaf preimage corresponds to the exact slot, the current value * is contained in the leaf preimage. */ - getPublicDataTreeWitness(blockNumber: BlockNumber, leafSlot: Fr): Promise; + getPublicDataTreeWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise; /** * Get a block specified by its number. diff --git a/yarn-project/circuit-types/src/interfaces/index.ts b/yarn-project/circuit-types/src/interfaces/index.ts index 21d47639fc72..8997ca87955c 100644 --- a/yarn-project/circuit-types/src/interfaces/index.ts +++ b/yarn-project/circuit-types/src/interfaces/index.ts @@ -1,5 +1,5 @@ export * from './aztec-node.js'; -export * from './block_number.js'; +export * from './l2_block_number.js'; export * from './pxe.js'; export * from './sync-status.js'; export * from './configs.js'; diff --git a/yarn-project/circuit-types/src/interfaces/block_number.ts b/yarn-project/circuit-types/src/interfaces/l2_block_number.ts similarity index 62% rename from yarn-project/circuit-types/src/interfaces/block_number.ts rename to yarn-project/circuit-types/src/interfaces/l2_block_number.ts index aaf0c954d66c..f6aba5eec1ad 100644 --- a/yarn-project/circuit-types/src/interfaces/block_number.ts +++ b/yarn-project/circuit-types/src/interfaces/l2_block_number.ts @@ -1,2 +1,2 @@ /** Helper type for a specific L2 block number or the latest block number */ -export type BlockNumber = number | 'latest'; +export type L2BlockNumber = number | 'latest'; From ed27e7103354b773110c4ebfeb472b67a5902d7d Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 18 Mar 2024 11:25:29 +0000 Subject: [PATCH 08/13] comment fixes --- yarn-project/circuit-types/src/messaging/inbox_leaf.ts | 2 +- yarn-project/circuit-types/src/messaging/l1_actor.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/circuit-types/src/messaging/inbox_leaf.ts b/yarn-project/circuit-types/src/messaging/inbox_leaf.ts index cad0db349d23..eff95b07d0af 100644 --- a/yarn-project/circuit-types/src/messaging/inbox_leaf.ts +++ b/yarn-project/circuit-types/src/messaging/inbox_leaf.ts @@ -8,7 +8,7 @@ export class InboxLeaf { public readonly blockNumber: bigint, /** Index of the leaf in L2 block message subtree. */ public readonly index: bigint, - /** Leaf of the subtree. */ + /** Leaf in the subtree. */ public readonly leaf: Fr, ) {} diff --git a/yarn-project/circuit-types/src/messaging/l1_actor.ts b/yarn-project/circuit-types/src/messaging/l1_actor.ts index e30e001cbf30..12b149ea79f8 100644 --- a/yarn-project/circuit-types/src/messaging/l1_actor.ts +++ b/yarn-project/circuit-types/src/messaging/l1_actor.ts @@ -4,7 +4,7 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; /** - * The sender of an L1 to L2 message. + * The sender of an L1 to L2 message or recipient of an L2 to L1 message. */ export class L1Actor { constructor( @@ -13,7 +13,7 @@ export class L1Actor { */ public readonly sender: EthAddress, /** - * The chain id on which the message was sent. + * The chain id on which the message was sent (L1 -> L2) or on which the message will be received (L2 -> L1). */ public readonly chainId: number, ) {} From cd9deb0f5169acde940a2b798cf440fbf7c1cf09 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 18 Mar 2024 14:09:32 +0000 Subject: [PATCH 09/13] bug fix --- .../archiver/src/archiver/archiver.ts | 4 ++-- .../archiver/src/archiver/archiver_store.ts | 4 ++-- .../kv_archiver_store/kv_archiver_store.ts | 4 ++-- .../kv_archiver_store/message_store.ts | 7 ++---- .../l1_to_l2_message_store.ts | 6 ++--- .../memory_archiver_store.ts | 4 ++-- .../aztec-node/src/aztec-node/server.ts | 19 ++++++++++++---- .../src/interfaces/aztec-node.ts | 14 ++++++++---- .../src/messaging/l1_to_l2_message_source.ts | 4 ++-- .../src/e2e_cross_chain_messaging.test.ts | 2 +- .../e2e_public_cross_chain_messaging.test.ts | 2 +- .../src/shared/cross_chain_test_harness.ts | 22 ++++--------------- .../pxe/src/simulator_oracle/index.ts | 8 +++++-- 13 files changed, 52 insertions(+), 48 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 0f0f09628f00..6d3bff5f357b 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -425,9 +425,9 @@ export class Archiver implements ArchiveSource { /** * Gets the L1 to L2 message index in the L1 to L2 message tree. * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found). */ - getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { + getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { return this.store.getL1ToL2MessageIndex(l1ToL2Message); } diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 472a52fed08c..e68990c88d55 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -105,9 +105,9 @@ export interface ArchiverDataStore { /** * Gets the L1 to L2 message index in the L1 to L2 message tree. * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found). */ - getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise; + getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise; /** * Gets up to `limit` amount of logs starting from `from`. diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index cd52432d4882..c556a3cf9bc5 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -156,9 +156,9 @@ export class KVArchiverDataStore implements ArchiverDataStore { /** * Gets the L1 to L2 message index in the L1 to L2 message tree. * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found). */ - public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { + public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { return Promise.resolve(this.#messageStore.getL1ToL2MessageIndex(l1ToL2Message)); } diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts index 25a4c7b74ffb..3d3b5ca57a4d 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts @@ -70,13 +70,10 @@ export class MessageStore { /** * Gets the L1 to L2 message index in the L1 to L2 message tree. * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found). */ - public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { + public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { const index = this.#l1ToL2MessageIndices.get(l1ToL2Message.toString()); - if (index === undefined) { - throw new Error(`L1 to L2 message index not found in the store for message ${l1ToL2Message.toString()}`); - } return Promise.resolve(index); } diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts index 6cd0074c8d94..3cae18ea47b4 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts @@ -52,9 +52,9 @@ export class L1ToL2MessageStore { /** * Gets the L1 to L2 message index in the L1 to L2 message tree. * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found). */ - getMessageIndex(l1ToL2Message: Fr): bigint { + getMessageIndex(l1ToL2Message: Fr): bigint | undefined { for (const [key, message] of this.store.entries()) { if (message.equals(l1ToL2Message)) { const [blockNumber, messageIndex] = key.split('-'); @@ -64,6 +64,6 @@ export class L1ToL2MessageStore { return indexInTheWholeTree; } } - throw new Error(`L1 to L2 message index not found in the store for message ${l1ToL2Message.toString()}`); + return undefined; } } diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index d8d1b4ad08d9..763ea765e9a8 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -175,9 +175,9 @@ export class MemoryArchiverStore implements ArchiverDataStore { /** * Gets the L1 to L2 message index in the L1 to L2 message tree. * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found). */ - public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { + public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise { return Promise.resolve(this.l1ToL2Messages.getMessageIndex(l1ToL2Message)); } diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 3eaed4684823..e2a666d6f54d 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -367,14 +367,16 @@ export class AztecNodeService implements AztecNode { * Returns the index and a sibling path for a leaf in the committed l1 to l2 data tree. * @param blockNumber - The block number at which to get the data. * @param l1ToL2Message - The l1ToL2Message to get the index / sibling path for. - * @throws If the message is not found. - * @returns A tuple of the index and the sibling path of the L1ToL2Message. + * @returns A tuple of the index and the sibling path of the L1ToL2Message (undefined if not found). */ - public async getL1ToL2MessageIndexAndSiblingPath( + public async getL1ToL2MessageMembershipWitness( blockNumber: L2BlockNumber, l1ToL2Message: Fr, - ): Promise<[bigint, SiblingPath]> { + ): Promise<[bigint, SiblingPath] | undefined> { const index = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message); + if (index === undefined) { + return undefined; + } const committedDb = await this.#getWorldState(blockNumber); const siblingPath = await committedDb.getSiblingPath( MerkleTreeId.L1_TO_L2_MESSAGE_TREE, @@ -383,6 +385,15 @@ export class AztecNodeService implements AztecNode { return [index, siblingPath]; } + /** + * Returns whether an L1 to L2 message is synced by archiver and if it's ready to be included in a block. + * @param l1ToL2Message - The L1 to L2 message to check. + * @returns Whether the message is synced and ready to be included in a block. + */ + public async isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise { + return (await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message)) !== undefined; + } + /** * Returns the index of a l2ToL1Message in a ephemeral l2 to l1 data tree as well as its sibling path. * @remarks This tree is considered ephemeral because it is created on-demand by: taking all the l2ToL1 messages diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index e1b0955d22f0..619208b8400f 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -62,13 +62,19 @@ export interface AztecNode { * Returns the index and a sibling path for a leaf in the committed l1 to l2 data tree. * @param blockNumber - The block number at which to get the data. * @param l1ToL2Message - The l1ToL2Message to get the index / sibling path for. - * @throws If the message is not found. - * @returns A tuple of the index and the sibling path of the message. + * @returns A tuple of the index and the sibling path of the message (undefined if not found). */ - getL1ToL2MessageIndexAndSiblingPath( + getL1ToL2MessageMembershipWitness( blockNumber: L2BlockNumber, l1ToL2Message: Fr, - ): Promise<[bigint, SiblingPath]>; + ): Promise<[bigint, SiblingPath] | undefined>; + + /** + * Returns whether an L1 to L2 message is synced by archiver and if it's ready to be included in a block. + * @param l1ToL2Message - The L1 to L2 message to check. + * @returns Whether the message is synced and ready to be included in a block. + */ + isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise; /** * Returns the index of a l2ToL1Message in a ephemeral l2 to l1 data tree as well as its sibling path. diff --git a/yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts b/yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts index 4e4771404670..7ba544e5af55 100644 --- a/yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts +++ b/yarn-project/circuit-types/src/messaging/l1_to_l2_message_source.ts @@ -14,9 +14,9 @@ export interface L1ToL2MessageSource { /** * Gets the L1 to L2 message index in the L1 to L2 message tree. * @param l1ToL2Message - The L1 to L2 message. - * @returns The index of the L1 to L2 message in the L1 to L2 message tree. + * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found). */ - getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise; + getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise; /** * Gets the number of the latest L2 block processed by the implementation. diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts index 8c68a9bd71f6..d1784a4c0e01 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts @@ -162,7 +162,7 @@ describe('e2e_cross_chain_messaging', () => { .withWallet(user2Wallet) .methods.claim_private(secretHashForL2MessageConsumption, bridgeAmount, secretForL2MessageConsumption) .simulate(), - ).rejects.toThrow(`L1 to L2 message index not found in the store for message ${wrongMessage.hash().toString()}`); + ).rejects.toThrow(`No L1 to L2 message found for entry key ${wrongMessage.hash().toString()}`); // send the right one - const consumptionReceipt = await l2Bridge diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts index 60469994cd6b..f11215642d86 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts @@ -212,7 +212,7 @@ describe('e2e_public_cross_chain_messaging', () => { await expect( l2Bridge.withWallet(user2Wallet).methods.claim_private(secretHash, bridgeAmount, secret).simulate(), - ).rejects.toThrow(`L1 to L2 message index not found in the store for message ${wrongMessage.hash().toString()}`); + ).rejects.toThrow(`No L1 to L2 message found for entry key ${wrongMessage.hash().toString()}`); }, 60_000); // Note: We register one portal address when deploying contract but that address is no-longer the only address diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index ceb75a21bbac..70132899c728 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -12,8 +12,8 @@ import { Wallet, computeMessageSecretHash, deployL1Contract, + retryUntil, sha256, - sleep, } from '@aztec/aztec.js'; import { InboxAbi, @@ -435,25 +435,11 @@ export class CrossChainTestHarness { * it's included it becomes available for consumption in the next block because the l1 to l2 message tree. */ async makeMessageConsumable(msgLeaf: Fr) { - const messageBlock = Number(await this.inbox.read.inProgress()); + // We poll isL1ToL2MessageSynced endpoint until the message is available + await retryUntil(async () => await this.aztecNode.isL1ToL2MessageSynced(msgLeaf), 'message sync', 10); + await this.mintTokensPublicOnL2(0n); await this.mintTokensPublicOnL2(0n); - - // We poll getL1ToL2MessageIndexAndSiblingPath endpoint until the message is available (it's most likely already - // available given that we waited for 2 blocks). - let i = 0; - while (i < 5) { - try { - // The function throws if message is not found - await this.aztecNode.getL1ToL2MessageIndexAndSiblingPath(messageBlock, msgLeaf); - } catch (e) { - i++; - await sleep(1000); - continue; - } - return; - } - throw new Error('Message not available after 5 seconds'); } } // docs:end:cross_chain_test_harness diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index f21b842a3364..ff524c63f995 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -122,14 +122,18 @@ export class SimulatorOracle implements DBOracle { /** * Retrieves the L1ToL2Message associated with a specific entry key - * Throws an error if the entry key is not found * + * @throws If the entry key is not found * @param entryKey - The key of the message to be retrieved * @returns A promise that resolves to the message data, a sibling path and the * index of the message in the l1ToL2MessageTree */ async getL1ToL2MembershipWitness(entryKey: Fr): Promise> { - const [index, siblingPath] = await this.aztecNode.getL1ToL2MessageIndexAndSiblingPath('latest', entryKey); + const response = await this.aztecNode.getL1ToL2MessageMembershipWitness('latest', entryKey); + if (!response) { + throw new Error(`No L1 to L2 message found for entry key ${entryKey.toString()}`); + } + const [index, siblingPath] = response; return new MessageLoadOracleInputs(index, siblingPath); } From 3d9914dc3103280b0a70d7941fdf42ab93e12f31 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 18 Mar 2024 15:21:41 +0000 Subject: [PATCH 10/13] bumping timeout --- yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 70132899c728..8b700f231fe5 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -436,7 +436,7 @@ export class CrossChainTestHarness { */ async makeMessageConsumable(msgLeaf: Fr) { // We poll isL1ToL2MessageSynced endpoint until the message is available - await retryUntil(async () => await this.aztecNode.isL1ToL2MessageSynced(msgLeaf), 'message sync', 10); + await retryUntil(async () => await this.aztecNode.isL1ToL2MessageSynced(msgLeaf), 'message sync', 100); await this.mintTokensPublicOnL2(0n); await this.mintTokensPublicOnL2(0n); From 588a1adf64ec013ddc507876ea8fe685b3ae10cf Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 19 Mar 2024 08:23:48 +0000 Subject: [PATCH 11/13] incorrect search block fix --- yarn-project/archiver/src/archiver/data_retrieval.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index af630a1f6b19..6ea1bf9391d3 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -139,7 +139,7 @@ export async function retrieveL1ToL2Messages( const l1ToL2Messages = processLeafInsertedLogs(leafInsertedLogs); retrievedL1ToL2Messages.push(...l1ToL2Messages); // handles the case when there are no new messages: - searchStartBlock = leafInsertedLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock; + searchStartBlock = (leafInsertedLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock) + 1n; } while (blockUntilSynced && searchStartBlock <= searchEndBlock); - return { lastProcessedL1BlockNumber: searchStartBlock, retrievedData: retrievedL1ToL2Messages }; + return { lastProcessedL1BlockNumber: searchStartBlock - 1n, retrievedData: retrievedL1ToL2Messages }; } From e27707fe08c8e6a490e4e152fd502e18dcb206c0 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 19 Mar 2024 08:43:33 +0000 Subject: [PATCH 12/13] Revert "bumping timeout" This reverts commit 4d3722ff659cf269c5fd4882aad36af71c90e327. --- yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 8b700f231fe5..70132899c728 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -436,7 +436,7 @@ export class CrossChainTestHarness { */ async makeMessageConsumable(msgLeaf: Fr) { // We poll isL1ToL2MessageSynced endpoint until the message is available - await retryUntil(async () => await this.aztecNode.isL1ToL2MessageSynced(msgLeaf), 'message sync', 100); + await retryUntil(async () => await this.aztecNode.isL1ToL2MessageSynced(msgLeaf), 'message sync', 10); await this.mintTokensPublicOnL2(0n); await this.mintTokensPublicOnL2(0n); From e779f929ceea7d6edfc5188895510eb6cbaa7b97 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 19 Mar 2024 10:33:55 +0000 Subject: [PATCH 13/13] incorrect search block fix 2 --- yarn-project/archiver/src/archiver/data_retrieval.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index 6ea1bf9391d3..ae18697a91a4 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -66,10 +66,10 @@ export async function retrieveBlockMetadataFromRollup( l2BlockProcessedLogs, ); retrievedBlockMetadata.push(...newBlockMetadata); - searchStartBlock = l2BlockProcessedLogs[l2BlockProcessedLogs.length - 1].blockNumber!; + searchStartBlock = l2BlockProcessedLogs[l2BlockProcessedLogs.length - 1].blockNumber! + 1n; expectedNextL2BlockNum += BigInt(newBlockMetadata.length); } while (blockUntilSynced && searchStartBlock <= searchEndBlock); - return { lastProcessedL1BlockNumber: searchStartBlock, retrievedData: retrievedBlockMetadata }; + return { lastProcessedL1BlockNumber: searchStartBlock - 1n, retrievedData: retrievedBlockMetadata }; } /** @@ -106,9 +106,9 @@ export async function retrieveBlockBodiesFromAvailabilityOracle( const newBlockBodies = await processTxsPublishedLogs(publicClient, l2TxsPublishedLogs); retrievedBlockBodies.push(...newBlockBodies); - searchStartBlock = l2TxsPublishedLogs[l2TxsPublishedLogs.length - 1].blockNumber!; + searchStartBlock = l2TxsPublishedLogs[l2TxsPublishedLogs.length - 1].blockNumber! + 1n; } while (blockUntilSynced && searchStartBlock <= searchEndBlock); - return { lastProcessedL1BlockNumber: searchStartBlock, retrievedData: retrievedBlockBodies }; + return { lastProcessedL1BlockNumber: searchStartBlock - 1n, retrievedData: retrievedBlockBodies }; } /**