From b98035da2b1dcd06ff95b41d9d981ac7a68b4356 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 2 Mar 2024 01:17:53 +0100 Subject: [PATCH 01/40] initial --- .../aztec-node/src/aztec-node/server.ts | 28 +++++++++++++++++++ .../src/interfaces/aztec-node.ts | 7 +++++ 2 files changed, 35 insertions(+) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 9a15fa6502bf..b2aa1ea2b829 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -32,6 +32,7 @@ import { Fr, Header, L1_TO_L2_MSG_TREE_HEIGHT, + L2_TO_L1_MESSAGE_LENGTH, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, NullifierLeafPreimage, @@ -62,6 +63,7 @@ import { } from '@aztec/world-state'; import { AztecNodeConfig } from './config.js'; +import { Pedersen, StandardTree } from '@aztec/merkle-tree'; /** * The aztec node. @@ -424,6 +426,32 @@ export class AztecNodeService implements AztecNode { return committedDb.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex); } + public async getL2ToL1MessageSiblingPath( + blockNumber: number | 'latest', + l2ToL1Message: Fr, + ): Promise> { + const block = await this.blockSource.getBlock(blockNumber === 'latest' ? await this.getBlockNumber() : blockNumber); + + if (block === undefined) { + throw new Error('Block is not defined'); + } + + // Note: This is how I would calculate it (with assumed tx/block val), but would rather have a hardcoded value in a const file + const transactionsPerBlock = 16; + const treeHeight = Math.log2(L2_TO_L1_MESSAGE_LENGTH * transactionsPerBlock); + + const tree = new StandardTree(AztecLmdbStore.open(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); + await tree.appendLeaves(block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs.map(l2ToL1Msg => l2ToL1Msg.toBuffer()))); + + const indexOfL2ToL1Message = tree.findLeafIndex(l2ToL1Message.toBuffer(), true); + + if (indexOfL2ToL1Message === undefined) { + throw new Error('The L2ToL1Message you are trying to prove inclusion of does not exist'); + } + + return tree.getSiblingPath(indexOfL2ToL1Message, true); + } + /** * Returns a sibling path for a leaf in the committed blocks tree. * @param blockNumber - The block number at which to get the data. diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index c9b7bd55d0fd..d9448aeae6bc 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -3,6 +3,7 @@ import { CONTRACT_TREE_HEIGHT, Header, L1_TO_L2_MSG_TREE_HEIGHT, + L2_TO_L1_MSG_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, @@ -93,6 +94,12 @@ export interface AztecNode { leafIndex: bigint, ): Promise>; + getL2ToL1MessageSiblingPath( + blockNumber: BlockNumber, + l2ToL1Message: Fr, + // TODO: Replace with actual temp tree height + ): Promise>; + /** * Returns a sibling path for a leaf in the committed historic blocks tree. * @param blockNumber - The block number at which to get the data. From c28bfe1e1f79611596319d03e915af595534de03 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 2 Mar 2024 01:24:22 +0100 Subject: [PATCH 02/40] Fix --- yarn-project/aztec-node/src/aztec-node/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index b2aa1ea2b829..68397cea0ac2 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -438,7 +438,7 @@ export class AztecNodeService implements AztecNode { // Note: This is how I would calculate it (with assumed tx/block val), but would rather have a hardcoded value in a const file const transactionsPerBlock = 16; - const treeHeight = Math.log2(L2_TO_L1_MESSAGE_LENGTH * transactionsPerBlock); + const treeHeight = Math.ceil(Math.log2(L2_TO_L1_MESSAGE_LENGTH * transactionsPerBlock)); const tree = new StandardTree(AztecLmdbStore.open(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); await tree.appendLeaves(block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs.map(l2ToL1Msg => l2ToL1Msg.toBuffer()))); From 49b21ea74a2f5b5c4f35a4288decb61d77b333fa Mon Sep 17 00:00:00 2001 From: Esau Date: Mon, 4 Mar 2024 13:43:08 +0100 Subject: [PATCH 03/40] fix --- yarn-project/aztec-node/src/aztec-node/server.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 68397cea0ac2..53269cd771ce 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -436,9 +436,7 @@ export class AztecNodeService implements AztecNode { throw new Error('Block is not defined'); } - // Note: This is how I would calculate it (with assumed tx/block val), but would rather have a hardcoded value in a const file - const transactionsPerBlock = 16; - const treeHeight = Math.ceil(Math.log2(L2_TO_L1_MESSAGE_LENGTH * transactionsPerBlock)); + const treeHeight = Math.ceil(Math.log2(L2_TO_L1_MESSAGE_LENGTH * block.body.txEffects.length)); const tree = new StandardTree(AztecLmdbStore.open(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); await tree.appendLeaves(block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs.map(l2ToL1Msg => l2ToL1Msg.toBuffer()))); From 60a74df69aa66e2c06821a7935ffbb1b27d5d3d2 Mon Sep 17 00:00:00 2001 From: Esau Date: Mon, 4 Mar 2024 14:36:42 +0100 Subject: [PATCH 04/40] Fix --- .../aztec-node/src/aztec-node/server.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 53269cd771ce..286aacfa7a14 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -436,18 +436,24 @@ export class AztecNodeService implements AztecNode { throw new Error('Block is not defined'); } - const treeHeight = Math.ceil(Math.log2(L2_TO_L1_MESSAGE_LENGTH * block.body.txEffects.length)); + const l2ToL1Messages = block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - const tree = new StandardTree(AztecLmdbStore.open(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); - await tree.appendLeaves(block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs.map(l2ToL1Msg => l2ToL1Msg.toBuffer()))); + if (l2ToL1Messages.length !== L2_TO_L1_MESSAGE_LENGTH * block.body.txEffects.length) { + throw new Error('L2 to L1 Messages are not padded'); + } - const indexOfL2ToL1Message = tree.findLeafIndex(l2ToL1Message.toBuffer(), true); + const indexOfL2ToL1Message = l2ToL1Messages.findIndex(l2ToL1MessageInBlock => l2ToL1MessageInBlock.equals(l2ToL1Message)); - if (indexOfL2ToL1Message === undefined) { + if (indexOfL2ToL1Message === -1) { throw new Error('The L2ToL1Message you are trying to prove inclusion of does not exist'); } - return tree.getSiblingPath(indexOfL2ToL1Message, true); + const treeHeight = Math.ceil(Math.log2(l2ToL1Messages.length)); + + const tree = new StandardTree(AztecLmdbStore.open(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); + await tree.appendLeaves(l2ToL1Messages.map(l2ToL1Msg => l2ToL1Msg.toBuffer())); + + return tree.getSiblingPath(BigInt(indexOfL2ToL1Message), true); } /** From a7ddb10d3b8692c5fea04b444a5e8d0aa9b96686 Mon Sep 17 00:00:00 2001 From: Esau Date: Mon, 4 Mar 2024 17:23:19 +0100 Subject: [PATCH 05/40] test --- yarn-project/aztec-node/src/aztec-node/server.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 286aacfa7a14..92eb1820ace9 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -45,7 +45,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { createDebugLogger } from '@aztec/foundation/log'; import { AztecKVStore } from '@aztec/kv-store'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; -import { initStoreForRollup } from '@aztec/kv-store/utils'; +import { initStoreForRollup, openTmpStore } from '@aztec/kv-store/utils'; import { AztecKVTxPool, P2P, createP2PClient } from '@aztec/p2p'; import { GlobalVariableBuilder, @@ -450,7 +450,9 @@ export class AztecNodeService implements AztecNode { const treeHeight = Math.ceil(Math.log2(l2ToL1Messages.length)); - const tree = new StandardTree(AztecLmdbStore.open(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); + // @TODO: Figure out a way to make the below in memory only + // Replace this with SHA hasher + const tree = new StandardTree(openTmpStore(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); await tree.appendLeaves(l2ToL1Messages.map(l2ToL1Msg => l2ToL1Msg.toBuffer())); return tree.getSiblingPath(BigInt(indexOfL2ToL1Message), true); From 938bd24850c32ccbd52cac7da61f847e909cb6ac Mon Sep 17 00:00:00 2001 From: Esau Date: Mon, 4 Mar 2024 20:04:44 +0100 Subject: [PATCH 06/40] Fix --- .../aztec-node/src/aztec-node/server.ts | 5 ++-- .../src/interfaces/aztec-node.ts | 8 ++++-- yarn-project/merkle-tree/src/index.ts | 1 + yarn-project/merkle-tree/src/sha_256.ts | 25 +++++++++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 yarn-project/merkle-tree/src/sha_256.ts diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 92eb1820ace9..cadbd3b45e52 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -63,7 +63,7 @@ import { } from '@aztec/world-state'; import { AztecNodeConfig } from './config.js'; -import { Pedersen, StandardTree } from '@aztec/merkle-tree'; +import { SHA256, StandardTree } from '@aztec/merkle-tree'; /** * The aztec node. @@ -451,8 +451,7 @@ export class AztecNodeService implements AztecNode { const treeHeight = Math.ceil(Math.log2(l2ToL1Messages.length)); // @TODO: Figure out a way to make the below in memory only - // Replace this with SHA hasher - const tree = new StandardTree(openTmpStore(), new Pedersen(), 'temp_outhash_sibling_path', treeHeight); + const tree = new StandardTree(openTmpStore(), new SHA256(), 'temp_outhash_sibling_path', treeHeight); await tree.appendLeaves(l2ToL1Messages.map(l2ToL1Msg => l2ToL1Msg.toBuffer())); return tree.getSiblingPath(BigInt(indexOfL2ToL1Message), true); diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index d9448aeae6bc..e5963fbdfd22 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -3,7 +3,6 @@ import { CONTRACT_TREE_HEIGHT, Header, L1_TO_L2_MSG_TREE_HEIGHT, - L2_TO_L1_MSG_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, @@ -94,10 +93,15 @@ export interface AztecNode { leafIndex: bigint, ): Promise>; + /** + * Returns a sibling path for a leaf in a virtual l2 to l1 data tree. + * @param blockNumber - The block number at which to get the data. + * @param l2ToL1Message - The l2ToL1Message get the sibling path for. + * @returns The sibling path. + */ getL2ToL1MessageSiblingPath( blockNumber: BlockNumber, l2ToL1Message: Fr, - // TODO: Replace with actual temp tree height ): Promise>; /** diff --git a/yarn-project/merkle-tree/src/index.ts b/yarn-project/merkle-tree/src/index.ts index 45ae1771bbf8..45b453dccb46 100644 --- a/yarn-project/merkle-tree/src/index.ts +++ b/yarn-project/merkle-tree/src/index.ts @@ -3,6 +3,7 @@ export * from './interfaces/indexed_tree.js'; export * from './interfaces/merkle_tree.js'; export * from './interfaces/update_only_tree.js'; export * from './pedersen.js'; +export * from './sha_256.js'; export * from './sparse_tree/sparse_tree.js'; export { StandardIndexedTree } from './standard_indexed_tree/standard_indexed_tree.js'; export * from './standard_tree/standard_tree.js'; diff --git a/yarn-project/merkle-tree/src/sha_256.ts b/yarn-project/merkle-tree/src/sha_256.ts new file mode 100644 index 000000000000..0033862cdc5b --- /dev/null +++ b/yarn-project/merkle-tree/src/sha_256.ts @@ -0,0 +1,25 @@ +import { sha256 } from '@aztec/foundation/crypto'; +import { Hasher } from '@aztec/types/interfaces'; + +/** + * A helper class encapsulating Pedersen hash functionality. + * @deprecated Don't call pedersen directly in production code. Instead, create suitably-named functions for specific + * purposes. + */ +export class SHA256 implements Hasher { + /* + * @deprecated Don't call pedersen directly in production code. Instead, create suitably-named functions for specific + * purposes. + */ + public hash(lhs: Uint8Array, rhs: Uint8Array): Buffer { + return sha256(Buffer.concat([Buffer.from(lhs), Buffer.from(rhs)])); + } + + /* + * @deprecated Don't call pedersen directly in production code. Instead, create suitably-named functions for specific + * purposes. + */ + public hashInputs(inputs: Buffer[]): Buffer { + return sha256(Buffer.concat(inputs)); + } +} From af629339b278f81fa9e147335fa5b3291eb3b730 Mon Sep 17 00:00:00 2001 From: Esau Date: Mon, 4 Mar 2024 20:07:44 +0100 Subject: [PATCH 07/40] yarn fmt --- yarn-project/aztec-node/src/aztec-node/server.ts | 6 ++++-- yarn-project/circuit-types/src/interfaces/aztec-node.ts | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index cadbd3b45e52..d017f6bffae9 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -46,6 +46,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { AztecKVStore } from '@aztec/kv-store'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; import { initStoreForRollup, openTmpStore } from '@aztec/kv-store/utils'; +import { SHA256, StandardTree } from '@aztec/merkle-tree'; import { AztecKVTxPool, P2P, createP2PClient } from '@aztec/p2p'; import { GlobalVariableBuilder, @@ -63,7 +64,6 @@ import { } from '@aztec/world-state'; import { AztecNodeConfig } from './config.js'; -import { SHA256, StandardTree } from '@aztec/merkle-tree'; /** * The aztec node. @@ -442,7 +442,9 @@ export class AztecNodeService implements AztecNode { throw new Error('L2 to L1 Messages are not padded'); } - const indexOfL2ToL1Message = l2ToL1Messages.findIndex(l2ToL1MessageInBlock => l2ToL1MessageInBlock.equals(l2ToL1Message)); + const indexOfL2ToL1Message = l2ToL1Messages.findIndex(l2ToL1MessageInBlock => + l2ToL1MessageInBlock.equals(l2ToL1Message), + ); if (indexOfL2ToL1Message === -1) { throw new Error('The L2ToL1Message you are trying to prove inclusion of does not exist'); diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index e5963fbdfd22..33c180cb5801 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -99,10 +99,7 @@ export interface AztecNode { * @param l2ToL1Message - The l2ToL1Message get the sibling path for. * @returns The sibling path. */ - getL2ToL1MessageSiblingPath( - blockNumber: BlockNumber, - l2ToL1Message: Fr, - ): Promise>; + getL2ToL1MessageSiblingPath(blockNumber: BlockNumber, l2ToL1Message: Fr): Promise>; /** * Returns a sibling path for a leaf in the committed historic blocks tree. From 7d07e4555cde286194323271ff96d5692c7cbbfc Mon Sep 17 00:00:00 2001 From: Esau Date: Tue, 5 Mar 2024 00:51:54 +0100 Subject: [PATCH 08/40] test --- .../end-to-end/src/e2e_outbox.test.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 yarn-project/end-to-end/src/e2e_outbox.test.ts diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts new file mode 100644 index 000000000000..cac4e5fcafa0 --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -0,0 +1,78 @@ +import { AztecNodeConfig } from '@aztec/aztec-node'; +import { AztecNode, Fr } from '@aztec/aztec.js'; +import { SiblingPath } from '@aztec/circuit-types'; +import { DeployL1Contracts, createEthereumChain } from '@aztec/ethereum'; +import { openTmpStore } from '@aztec/kv-store/utils'; +import { SHA256 } from '@aztec/merkle-tree'; +import { + EmptyRollupProver, + L1Publisher, + RealRollupCircuitSimulator, + SoloBlockBuilder, + getL1Publisher, + getVerificationKeys, +} from '@aztec/sequencer-client'; +import { MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; + +import { beforeEach, describe, expect, it } from '@jest/globals'; + +import { setup } from './fixtures/utils.js'; + +describe('L1Publisher integration', () => { + const sequencerPK = '0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a'; + + let publisher: L1Publisher; + + let builder: SoloBlockBuilder; + let builderDb: MerkleTreeOperations; + + let teardown: () => void; + let aztecNode: AztecNode; + let deployL1ContractsValues: DeployL1Contracts; + let config: AztecNodeConfig; + const sha256 = new SHA256(); + let chainId: number; + + beforeEach(async () => { + ({ teardown, aztecNode, config, deployL1ContractsValues } = await setup(1)); + chainId = createEthereumChain(config.rpcUrl, config.apiKey).chainInfo.id; + publisher = getL1Publisher({ + rpcUrl: config.rpcUrl, + apiKey: '', + requiredConfirmations: 1, + l1Contracts: deployL1ContractsValues.l1ContractAddresses, + publisherPrivateKey: sequencerPK, + l1BlockPublishRetryIntervalMS: 100, + }); + + builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); + const vks = getVerificationKeys(); + const simulator = new RealRollupCircuitSimulator(); + const prover = new EmptyRollupProver(); + builder = new SoloBlockBuilder(builderDb, vks, simulator, prover); + }, 100_000); + + afterAll(() => teardown()); + + it('Checks the sibling path of the empty setup of two blocks of two empty tx effects each', async () => { + const blockNumber = await aztecNode.getBlockNumber(); + + const block = await aztecNode.getBlock(blockNumber); + + const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => + txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), + ); + + expect(l2ToL1Messages?.length).toBe(4); + + const siblingPath = await aztecNode.getL2ToL1MessageSiblingPath(blockNumber, Fr.ZERO); + + expect(siblingPath.pathSize).toBe(2); + + const expectedSiblingPath = new SiblingPath(siblingPath.pathSize, [ + Fr.ZERO.toBuffer(), + sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), + ]); + expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); + }, 36_000); +}); From 8c78f290684c50d3a3bac9bea7ab551ddd44229c Mon Sep 17 00:00:00 2001 From: Esau Date: Tue, 5 Mar 2024 00:56:12 +0100 Subject: [PATCH 09/40] fix --- .../end-to-end/src/e2e_outbox.test.ts | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index cac4e5fcafa0..ffe24e45e1ff 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,55 +1,18 @@ -import { AztecNodeConfig } from '@aztec/aztec-node'; import { AztecNode, Fr } from '@aztec/aztec.js'; import { SiblingPath } from '@aztec/circuit-types'; -import { DeployL1Contracts, createEthereumChain } from '@aztec/ethereum'; -import { openTmpStore } from '@aztec/kv-store/utils'; import { SHA256 } from '@aztec/merkle-tree'; -import { - EmptyRollupProver, - L1Publisher, - RealRollupCircuitSimulator, - SoloBlockBuilder, - getL1Publisher, - getVerificationKeys, -} from '@aztec/sequencer-client'; -import { MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { beforeEach, describe, expect, it } from '@jest/globals'; import { setup } from './fixtures/utils.js'; describe('L1Publisher integration', () => { - const sequencerPK = '0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a'; - - let publisher: L1Publisher; - - let builder: SoloBlockBuilder; - let builderDb: MerkleTreeOperations; - let teardown: () => void; let aztecNode: AztecNode; - let deployL1ContractsValues: DeployL1Contracts; - let config: AztecNodeConfig; const sha256 = new SHA256(); - let chainId: number; beforeEach(async () => { - ({ teardown, aztecNode, config, deployL1ContractsValues } = await setup(1)); - chainId = createEthereumChain(config.rpcUrl, config.apiKey).chainInfo.id; - publisher = getL1Publisher({ - rpcUrl: config.rpcUrl, - apiKey: '', - requiredConfirmations: 1, - l1Contracts: deployL1ContractsValues.l1ContractAddresses, - publisherPrivateKey: sequencerPK, - l1BlockPublishRetryIntervalMS: 100, - }); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - const vks = getVerificationKeys(); - const simulator = new RealRollupCircuitSimulator(); - const prover = new EmptyRollupProver(); - builder = new SoloBlockBuilder(builderDb, vks, simulator, prover); + ({ teardown, aztecNode } = await setup(1)); }, 100_000); afterAll(() => teardown()); From 537746c2a406e066afd91d31b5e22ce3e1cf6eab Mon Sep 17 00:00:00 2001 From: Esau Date: Tue, 5 Mar 2024 01:01:13 +0100 Subject: [PATCH 10/40] fix --- yarn-project/aztec.js/src/index.ts | 1 + yarn-project/end-to-end/src/e2e_outbox.test.ts | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 1c7812aa56fb..ca8bd77e3785 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -115,6 +115,7 @@ export { merkleTreeIds, mockTx, Comparator, + SiblingPath, } from '@aztec/circuit-types'; export { NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index ffe24e45e1ff..987f94c6810d 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,5 +1,4 @@ -import { AztecNode, Fr } from '@aztec/aztec.js'; -import { SiblingPath } from '@aztec/circuit-types'; +import { AztecNode, Fr, SiblingPath } from '@aztec/aztec.js'; import { SHA256 } from '@aztec/merkle-tree'; import { beforeEach, describe, expect, it } from '@jest/globals'; From cc0c9db6fbfe1b416208486423d5d1e653f0995e Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 14:26:07 +0100 Subject: [PATCH 11/40] fix --- yarn-project/merkle-tree/src/sha_256.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn-project/merkle-tree/src/sha_256.ts b/yarn-project/merkle-tree/src/sha_256.ts index 0033862cdc5b..2ed2ba5a35d0 100644 --- a/yarn-project/merkle-tree/src/sha_256.ts +++ b/yarn-project/merkle-tree/src/sha_256.ts @@ -2,13 +2,13 @@ import { sha256 } from '@aztec/foundation/crypto'; import { Hasher } from '@aztec/types/interfaces'; /** - * A helper class encapsulating Pedersen hash functionality. - * @deprecated Don't call pedersen directly in production code. Instead, create suitably-named functions for specific + * A helper class encapsulating SHA256 hash functionality. + * @deprecated Don't call SHA256 directly in production code. Instead, create suitably-named functions for specific * purposes. */ export class SHA256 implements Hasher { /* - * @deprecated Don't call pedersen directly in production code. Instead, create suitably-named functions for specific + * @deprecated Don't call SHA256 directly in production code. Instead, create suitably-named functions for specific * purposes. */ public hash(lhs: Uint8Array, rhs: Uint8Array): Buffer { @@ -16,7 +16,7 @@ export class SHA256 implements Hasher { } /* - * @deprecated Don't call pedersen directly in production code. Instead, create suitably-named functions for specific + * @deprecated Don't call SHA256 directly in production code. Instead, create suitably-named functions for specific * purposes. */ public hashInputs(inputs: Buffer[]): Buffer { From a8645ed183755fb452680bbfeb944696b72e2b7f Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 14:35:49 +0100 Subject: [PATCH 12/40] Fix --- yarn-project/aztec-node/src/aztec-node/server.ts | 5 ++--- yarn-project/aztec/src/cli/cmds/start_archiver.ts | 2 +- yarn-project/kv-store/src/lmdb/store.ts | 7 +++++-- yarn-project/kv-store/src/utils.ts | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 708b3c67337e..22c9369806a6 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -113,7 +113,7 @@ export class AztecNodeService implements AztecNode { const log = createDebugLogger('aztec:node'); const storeLog = createDebugLogger('aztec:node:lmdb'); const store = await initStoreForRollup( - AztecLmdbStore.open(config.dataDirectory, storeLog), + AztecLmdbStore.open(config.dataDirectory, false, storeLog), config.l1Contracts.rollupAddress, storeLog, ); @@ -452,8 +452,7 @@ export class AztecNodeService implements AztecNode { const treeHeight = Math.ceil(Math.log2(l2ToL1Messages.length)); - // @TODO: Figure out a way to make the below in memory only - const tree = new StandardTree(openTmpStore(), new SHA256(), 'temp_outhash_sibling_path', treeHeight); + const tree = new StandardTree(openTmpStore(true), new SHA256(), 'temp_outhash_sibling_path', treeHeight); await tree.appendLeaves(l2ToL1Messages.map(l2ToL1Msg => l2ToL1Msg.toBuffer())); return tree.getSiblingPath(BigInt(indexOfL2ToL1Message), true); diff --git a/yarn-project/aztec/src/cli/cmds/start_archiver.ts b/yarn-project/aztec/src/cli/cmds/start_archiver.ts index 653636f8c8fc..96cee4c34eec 100644 --- a/yarn-project/aztec/src/cli/cmds/start_archiver.ts +++ b/yarn-project/aztec/src/cli/cmds/start_archiver.ts @@ -24,7 +24,7 @@ export const startArchiver = async (options: any, signalHandlers: (() => Promise const storeLog = createDebugLogger('aztec:archiver:lmdb'); const store = await initStoreForRollup( - AztecLmdbStore.open(archiverConfig.dataDirectory, storeLog), + AztecLmdbStore.open(archiverConfig.dataDirectory, false, storeLog), archiverConfig.l1Contracts.rollupAddress, storeLog, ); diff --git a/yarn-project/kv-store/src/lmdb/store.ts b/yarn-project/kv-store/src/lmdb/store.ts index 02fc4cc787a6..2c8a0fa3bdb4 100644 --- a/yarn-project/kv-store/src/lmdb/store.ts +++ b/yarn-project/kv-store/src/lmdb/store.ts @@ -48,9 +48,12 @@ export class AztecLmdbStore implements AztecKVStore { * @param log - A logger to use. Optional * @returns The store */ - static open(path?: string, log = createDebugLogger('aztec:kv-store:lmdb')): AztecLmdbStore { + static open(path?: string, ephemeral: boolean = false, log = createDebugLogger('aztec:kv-store:lmdb')): AztecLmdbStore { log.info(`Opening LMDB database at ${path || 'temporary location'}`); - const rootDb = open({ path }); + const rootDb = open({ + path, + noSync: ephemeral, + }); return new AztecLmdbStore(rootDb); } diff --git a/yarn-project/kv-store/src/utils.ts b/yarn-project/kv-store/src/utils.ts index 7cab23f58271..621255a6bafb 100644 --- a/yarn-project/kv-store/src/utils.ts +++ b/yarn-project/kv-store/src/utils.ts @@ -36,6 +36,6 @@ export async function initStoreForRollup( * Opens a temporary store for testing purposes. * @returns A new store */ -export function openTmpStore(): AztecKVStore { - return AztecLmdbStore.open(); +export function openTmpStore(ephemeral: boolean = false): AztecKVStore { + return AztecLmdbStore.open(undefined, ephemeral); } From 4733842edc2f1063f9397bc38f3317dd5ab1784a Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 14:37:23 +0100 Subject: [PATCH 13/40] formatting --- yarn-project/kv-store/src/lmdb/store.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/yarn-project/kv-store/src/lmdb/store.ts b/yarn-project/kv-store/src/lmdb/store.ts index 2c8a0fa3bdb4..5438a416d11f 100644 --- a/yarn-project/kv-store/src/lmdb/store.ts +++ b/yarn-project/kv-store/src/lmdb/store.ts @@ -48,12 +48,16 @@ export class AztecLmdbStore implements AztecKVStore { * @param log - A logger to use. Optional * @returns The store */ - static open(path?: string, ephemeral: boolean = false, log = createDebugLogger('aztec:kv-store:lmdb')): AztecLmdbStore { + static open( + path?: string, + ephemeral: boolean = false, + log = createDebugLogger('aztec:kv-store:lmdb'), + ): AztecLmdbStore { log.info(`Opening LMDB database at ${path || 'temporary location'}`); - const rootDb = open({ + const rootDb = open({ path, noSync: ephemeral, - }); + }); return new AztecLmdbStore(rootDb); } From a5c4a459d35e7606f4ee24362b91efdc50ae3e6d Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 14:43:22 +0100 Subject: [PATCH 14/40] comment --- yarn-project/aztec-node/src/aztec-node/server.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 22c9369806a6..811c112b2e69 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -426,6 +426,12 @@ export class AztecNodeService implements AztecNode { return committedDb.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex); } + /** + * Returns a sibling path for a leaf in a virtual l2 to l1 data tree. + * @param blockNumber - The block number at which to get the data. + * @param l2ToL1Message - The l2ToL1Message get the sibling path for. + * @returns The sibling path. + */ public async getL2ToL1MessageSiblingPath( blockNumber: number | 'latest', l2ToL1Message: Fr, From 18e0373973abcb06b4f365bea3c07fed2a2a883f Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 14:44:02 +0100 Subject: [PATCH 15/40] comment --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 987f94c6810d..8dfbd6edb2b7 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -5,7 +5,7 @@ import { beforeEach, describe, expect, it } from '@jest/globals'; import { setup } from './fixtures/utils.js'; -describe('L1Publisher integration', () => { +describe('E2E Outbox Tests', () => { let teardown: () => void; let aztecNode: AztecNode; const sha256 = new SHA256(); From 65b767b580732537ed7b4199c57eb13aac634b38 Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 15:21:42 +0100 Subject: [PATCH 16/40] add outbox to test --- .circleci/config.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 92ba22e97a74..3ef427f34b3e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -900,6 +900,18 @@ jobs: name: "Test" command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_ordering.test.ts aztec_manifest_key: end-to-end + + e2e-outbox: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Test" + command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_outbox.test.ts + aztec_manifest_key: end-to-end uniswap-trade-on-l1-from-l2: docker: @@ -1467,6 +1479,7 @@ workflows: - e2e-inclusion-proofs-contract: *e2e_test - e2e-pending-note-hashes-contract: *e2e_test - e2e-ordering: *e2e_test + - e2e-outbox: *e2e_test - e2e-counter: *e2e_test - e2e-private-voting: *e2e_test - uniswap-trade-on-l1-from-l2: *e2e_test @@ -1530,6 +1543,7 @@ workflows: - e2e-inclusion-proofs-contract - e2e-pending-note-hashes-contract - e2e-ordering + - e2e-outbox - e2e-counter - e2e-private-voting - uniswap-trade-on-l1-from-l2 From 0649e1e8bdfcbf71301020406daafe65c3586684 Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 16:04:47 +0100 Subject: [PATCH 17/40] why --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 8dfbd6edb2b7..89925ad743e6 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -25,6 +25,8 @@ describe('E2E Outbox Tests', () => { txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), ); + expect(block?.body.txEffects.length).toBe(2); + expect(l2ToL1Messages?.length).toBe(4); const siblingPath = await aztecNode.getL2ToL1MessageSiblingPath(blockNumber, Fr.ZERO); From 3b23aba7b1c2b13e8993ac0e92661e2b8622dfda Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 16:41:14 +0100 Subject: [PATCH 18/40] test --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 89925ad743e6..29d60e299ca2 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -19,12 +19,16 @@ describe('E2E Outbox Tests', () => { it('Checks the sibling path of the empty setup of two blocks of two empty tx effects each', async () => { const blockNumber = await aztecNode.getBlockNumber(); - const block = await aztecNode.getBlock(blockNumber); + console.log(blockNumber); + + const block = await aztecNode.getBlock(1); const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), ); + console.log(block?.body.txEffects); + expect(block?.body.txEffects.length).toBe(2); expect(l2ToL1Messages?.length).toBe(4); From 5cc60d8bfe36a60e9523f799cc8a23938cd48f17 Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 18:35:37 +0100 Subject: [PATCH 19/40] fix test --- .../end-to-end/src/e2e_outbox.test.ts | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 29d60e299ca2..7b5727b1a099 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,46 +1,58 @@ -import { AztecNode, Fr, SiblingPath } from '@aztec/aztec.js'; +import { AccountWalletWithPrivateKey, AztecNode, EthAddress, Fr, SiblingPath } from '@aztec/aztec.js'; import { SHA256 } from '@aztec/merkle-tree'; import { beforeEach, describe, expect, it } from '@jest/globals'; import { setup } from './fixtures/utils.js'; +import { TestContract } from '@aztec/noir-contracts.js'; describe('E2E Outbox Tests', () => { let teardown: () => void; let aztecNode: AztecNode; const sha256 = new SHA256(); + let contract: TestContract; + let wallets: AccountWalletWithPrivateKey[]; + beforeEach(async () => { - ({ teardown, aztecNode } = await setup(1)); + ({ teardown, aztecNode, wallets } = await setup(1)); + + const receipt = await TestContract.deploy(wallets[0]).send().wait(); + contract = receipt.contract; }, 100_000); afterAll(() => teardown()); - it('Checks the sibling path of the empty setup of two blocks of two empty tx effects each', async () => { - const blockNumber = await aztecNode.getBlockNumber(); + it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { + const { blockNumber } = await contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.ZERO).send().wait(); - console.log(blockNumber); - - const block = await aztecNode.getBlock(1); + const block = await aztecNode.getBlock(blockNumber!); const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), ); - console.log(block?.body.txEffects); + const siblingPath = await aztecNode.getL2ToL1MessageSiblingPath(blockNumber!, Fr.ZERO); - expect(block?.body.txEffects.length).toBe(2); + expect(siblingPath.pathSize).toBe(2); + + const expectedSiblingPath = new SiblingPath(siblingPath.pathSize, [ + l2ToL1Messages![0], + sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), + ]); - expect(l2ToL1Messages?.length).toBe(4); + expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); - const siblingPath = await aztecNode.getL2ToL1MessageSiblingPath(blockNumber, Fr.ZERO); + const siblingPathAlt = await aztecNode.getL2ToL1MessageSiblingPath(blockNumber!, Fr.fromBuffer(l2ToL1Messages![0])); - expect(siblingPath.pathSize).toBe(2); + expect(siblingPathAlt.pathSize).toBe(2); - const expectedSiblingPath = new SiblingPath(siblingPath.pathSize, [ + const expectedSiblingPathAlt = new SiblingPath(siblingPath.pathSize, [ Fr.ZERO.toBuffer(), sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), ]); - expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); - }, 36_000); + + expect(siblingPathAlt.toString()).toBe(expectedSiblingPathAlt.toString()); + + }, 360_000); }); From 1ecf545528a5631078111991150511338bcc4ae2 Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 18:38:41 +0100 Subject: [PATCH 20/40] yarn format --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 7b5727b1a099..4ab9092ac113 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,10 +1,10 @@ import { AccountWalletWithPrivateKey, AztecNode, EthAddress, Fr, SiblingPath } from '@aztec/aztec.js'; import { SHA256 } from '@aztec/merkle-tree'; +import { TestContract } from '@aztec/noir-contracts.js'; import { beforeEach, describe, expect, it } from '@jest/globals'; import { setup } from './fixtures/utils.js'; -import { TestContract } from '@aztec/noir-contracts.js'; describe('E2E Outbox Tests', () => { let teardown: () => void; @@ -13,7 +13,6 @@ describe('E2E Outbox Tests', () => { let contract: TestContract; let wallets: AccountWalletWithPrivateKey[]; - beforeEach(async () => { ({ teardown, aztecNode, wallets } = await setup(1)); @@ -24,7 +23,10 @@ describe('E2E Outbox Tests', () => { afterAll(() => teardown()); it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { - const { blockNumber } = await contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.ZERO).send().wait(); + const { blockNumber } = await contract.methods + .create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.ZERO) + .send() + .wait(); const block = await aztecNode.getBlock(blockNumber!); @@ -53,6 +55,5 @@ describe('E2E Outbox Tests', () => { ]); expect(siblingPathAlt.toString()).toBe(expectedSiblingPathAlt.toString()); - }, 360_000); }); From 262d12ff63ed093f9ffc63bbcacb96737995471d Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 18:51:09 +0100 Subject: [PATCH 21/40] add index --- yarn-project/aztec-node/src/aztec-node/server.ts | 12 ++++++------ .../circuit-types/src/interfaces/aztec-node.ts | 11 +++++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 811c112b2e69..1c9092501b5a 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -427,15 +427,15 @@ export class AztecNodeService implements AztecNode { } /** - * Returns a sibling path for a leaf in a virtual l2 to l1 data tree. + * Returns the index of a l2ToL1Message in a virtual l2 to l1 data tree as well as its sibling path. * @param blockNumber - The block number at which to get the data. - * @param l2ToL1Message - The l2ToL1Message get the sibling path for. - * @returns The sibling path. + * @param l2ToL1Message - The l2ToL1Message get the index / sibling path for. + * @returns A tuple of the index and the sibling path of the L2ToL1Message. */ - public async getL2ToL1MessageSiblingPath( + public async getL2ToL1MessageIndexAndSiblingPath( blockNumber: number | 'latest', l2ToL1Message: Fr, - ): Promise> { + ): Promise<[number, SiblingPath]> { const block = await this.blockSource.getBlock(blockNumber === 'latest' ? await this.getBlockNumber() : blockNumber); if (block === undefined) { @@ -461,7 +461,7 @@ export class AztecNodeService implements AztecNode { const tree = new StandardTree(openTmpStore(true), new SHA256(), 'temp_outhash_sibling_path', treeHeight); await tree.appendLeaves(l2ToL1Messages.map(l2ToL1Msg => l2ToL1Msg.toBuffer())); - return tree.getSiblingPath(BigInt(indexOfL2ToL1Message), true); + return [indexOfL2ToL1Message, await tree.getSiblingPath(BigInt(indexOfL2ToL1Message), true)]; } /** diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 33c180cb5801..2c108a869835 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -94,12 +94,15 @@ export interface AztecNode { ): Promise>; /** - * Returns a sibling path for a leaf in a virtual l2 to l1 data tree. + * Returns the index of a l2ToL1Message in a virtual l2 to l1 data tree as well as its sibling path. * @param blockNumber - The block number at which to get the data. - * @param l2ToL1Message - The l2ToL1Message get the sibling path for. - * @returns The sibling path. + * @param l2ToL1Message - The l2ToL1Message get the index / sibling path for. + * @returns A tuple of the index and the sibling path of the L2ToL1Message. */ - getL2ToL1MessageSiblingPath(blockNumber: BlockNumber, l2ToL1Message: Fr): Promise>; + getL2ToL1MessageIndexAndSiblingPath( + blockNumber: number | 'latest', + l2ToL1Message: Fr, + ): Promise<[number, SiblingPath]>; /** * Returns a sibling path for a leaf in the committed historic blocks tree. From 8e90550f790e978ecfcbfec370829a07df1d4e94 Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 18:52:05 +0100 Subject: [PATCH 22/40] fix test --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 4ab9092ac113..035b10d3bd0f 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -34,7 +34,7 @@ describe('E2E Outbox Tests', () => { txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), ); - const siblingPath = await aztecNode.getL2ToL1MessageSiblingPath(blockNumber!, Fr.ZERO); + const [, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber!, Fr.ZERO); expect(siblingPath.pathSize).toBe(2); @@ -45,7 +45,7 @@ describe('E2E Outbox Tests', () => { expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); - const siblingPathAlt = await aztecNode.getL2ToL1MessageSiblingPath(blockNumber!, Fr.fromBuffer(l2ToL1Messages![0])); + const [, siblingPathAlt] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber!, Fr.fromBuffer(l2ToL1Messages![0])); expect(siblingPathAlt.pathSize).toBe(2); From 8d505f045b8b87edee7e34f7569c78423c5823ad Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 19:00:55 +0100 Subject: [PATCH 23/40] yarn fmt --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 035b10d3bd0f..e986a5454638 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -45,7 +45,10 @@ describe('E2E Outbox Tests', () => { expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); - const [, siblingPathAlt] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber!, Fr.fromBuffer(l2ToL1Messages![0])); + const [, siblingPathAlt] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + blockNumber!, + Fr.fromBuffer(l2ToL1Messages![0]), + ); expect(siblingPathAlt.pathSize).toBe(2); From b5deb10a02db0d66947773b698e6f1917b46e27f Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 19:53:44 +0100 Subject: [PATCH 24/40] addressing comments --- yarn-project/kv-store/src/lmdb/store.ts | 1 + yarn-project/kv-store/src/utils.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/yarn-project/kv-store/src/lmdb/store.ts b/yarn-project/kv-store/src/lmdb/store.ts index 5438a416d11f..af949224e971 100644 --- a/yarn-project/kv-store/src/lmdb/store.ts +++ b/yarn-project/kv-store/src/lmdb/store.ts @@ -45,6 +45,7 @@ export class AztecLmdbStore implements AztecKVStore { * different rollup instances. * * @param path - A path on the disk to store the database. Optional + * @param ephemeral - true if the store should only exist in memory and not automatically be flushed to disk. Optional * @param log - A logger to use. Optional * @returns The store */ diff --git a/yarn-project/kv-store/src/utils.ts b/yarn-project/kv-store/src/utils.ts index 621255a6bafb..e41297b9e825 100644 --- a/yarn-project/kv-store/src/utils.ts +++ b/yarn-project/kv-store/src/utils.ts @@ -34,6 +34,7 @@ export async function initStoreForRollup( /** * Opens a temporary store for testing purposes. + * @param ephemeral - true if the store should only exist in memory and not automatically be flushed to disk. Optional * @returns A new store */ export function openTmpStore(ephemeral: boolean = false): AztecKVStore { From 49a52e43a4d0c242a02b082a5b82ec20fd89ff44 Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 6 Mar 2024 20:03:39 +0100 Subject: [PATCH 25/40] add comment --- yarn-project/aztec-node/src/aztec-node/server.ts | 3 +++ yarn-project/circuit-types/src/interfaces/aztec-node.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 1c9092501b5a..eff8efc95bfd 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -428,6 +428,9 @@ export class AztecNodeService implements AztecNode { /** * Returns the index of a l2ToL1Message in a virtual l2 to l1 data tree as well as its sibling path. + * This tree is considered virtual because it is created on-demand by: taking all the l2ToL1 messages + * in a single block, and then using them to make a variable depth append-only tree with these messages as leaves. + * The tree is discarded immediately after calculating what we need from it. * @param blockNumber - The block number at which to get the data. * @param l2ToL1Message - The l2ToL1Message get the index / sibling path for. * @returns A tuple of the index and the sibling path of the L2ToL1Message. diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 2c108a869835..35b0b9729c2c 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -95,6 +95,9 @@ export interface AztecNode { /** * Returns the index of a l2ToL1Message in a virtual l2 to l1 data tree as well as its sibling path. + * This tree is considered virtual because it is created on-demand by: taking all the l2ToL1 messages + * in a single block, and then using them to make a variable depth append-only tree with these messages as leaves. + * The tree is discarded immediately after calculating what we need from it. * @param blockNumber - The block number at which to get the data. * @param l2ToL1Message - The l2ToL1Message get the index / sibling path for. * @returns A tuple of the index and the sibling path of the L2ToL1Message. From 8951eab457486bcc092f06e23579b4eaab7ed97c Mon Sep 17 00:00:00 2001 From: Esau Date: Thu, 7 Mar 2024 20:00:22 +0100 Subject: [PATCH 26/40] adf --- .../end-to-end/src/e2e_outbox.test.ts | 81 +++++++++++++------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index e986a5454638..5f4a2df95db4 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,10 +1,13 @@ -import { AccountWalletWithPrivateKey, AztecNode, EthAddress, Fr, SiblingPath } from '@aztec/aztec.js'; +import { AccountWalletWithPrivateKey, AztecNode, BatchCall, EthAddress, Fr, SiblingPath } from '@aztec/aztec.js'; import { SHA256 } from '@aztec/merkle-tree'; import { TestContract } from '@aztec/noir-contracts.js'; import { beforeEach, describe, expect, it } from '@jest/globals'; import { setup } from './fixtures/utils.js'; +import { L2ToL1Message } from '@aztec/circuits.js'; +import { sha256 as hash } from '@aztec/foundation/crypto'; + describe('E2E Outbox Tests', () => { let teardown: () => void; @@ -23,40 +26,66 @@ describe('E2E Outbox Tests', () => { afterAll(() => teardown()); it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { - const { blockNumber } = await contract.methods - .create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.ZERO) - .send() - .wait(); + // We split two calls up, because BatchCall sends both calls in a single transaction. There are a max of 2 L2 to L1 messages per transaction + const call1 = new BatchCall(wallets[0], [ + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.fromString("123")).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(53170, EthAddress.fromString("123")).request(), + ]); - const block = await aztecNode.getBlock(blockNumber!); + const call2 = new BatchCall(wallets[0], [ + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(64281, EthAddress.fromString("123")).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(75392, EthAddress.fromString("123")).request(), + ]); - const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => - txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), - ); + const sentMessage1 = call1.send(); + const sentMessage2 = call2.send(); - const [, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber!, Fr.ZERO); + const [ + {blockNumber: blockNumber1}, + {blockNumber: blockNumber2}, + ] = await Promise.all([sentMessage1.wait(), sentMessage2.wait()]); - expect(siblingPath.pathSize).toBe(2); + expect(blockNumber1).toBe(blockNumber2); - const expectedSiblingPath = new SiblingPath(siblingPath.pathSize, [ - l2ToL1Messages![0], - sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), - ]); + const block = await aztecNode.getBlock(blockNumber1!); - expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); + console.log(block?.body.txEffects.length); + console.log(block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs)); - const [, siblingPathAlt] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - blockNumber!, - Fr.fromBuffer(l2ToL1Messages![0]), - ); + const message1 = new L2ToL1Message(EthAddress.ZERO, new Fr(42069)); + console.log(hash(message1.toBuffer())) - expect(siblingPathAlt.pathSize).toBe(2); - const expectedSiblingPathAlt = new SiblingPath(siblingPath.pathSize, [ - Fr.ZERO.toBuffer(), - sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), - ]); + // Use a full tree, check root as well, check index expected to be what we need considering we are hardcoding + // block header outhash === root of created sibling path tree. + + // const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => + // txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), + // ); + + // const [, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber!, Fr.ZERO); + + // expect(siblingPath.pathSize).toBe(2); + + // const expectedSiblingPath = new SiblingPath(siblingPath.pathSize, [ + // l2ToL1Messages![0], + // sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), + // ]); + + // expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); + + // const [, siblingPathAlt] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + // blockNumber!, + // Fr.fromBuffer(l2ToL1Messages![0]), + // ); + + // expect(siblingPathAlt.pathSize).toBe(2); + + // const expectedSiblingPathAlt = new SiblingPath(siblingPath.pathSize, [ + // Fr.ZERO.toBuffer(), + // sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), + // ]); - expect(siblingPathAlt.toString()).toBe(expectedSiblingPathAlt.toString()); + // expect(siblingPathAlt.toString()).toBe(expectedSiblingPathAlt.toString()); }, 360_000); }); From 88b78f3c68c836f678abf85ea5fb18cbfa7e4ace Mon Sep 17 00:00:00 2001 From: Esau Date: Thu, 7 Mar 2024 23:49:44 +0100 Subject: [PATCH 27/40] fix test finally --- .../end-to-end/src/e2e_outbox.test.ts | 107 ++++++++++-------- 1 file changed, 60 insertions(+), 47 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 5f4a2df95db4..5c053b81e3b6 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -5,9 +5,6 @@ import { TestContract } from '@aztec/noir-contracts.js'; import { beforeEach, describe, expect, it } from '@jest/globals'; import { setup } from './fixtures/utils.js'; -import { L2ToL1Message } from '@aztec/circuits.js'; -import { sha256 as hash } from '@aztec/foundation/crypto'; - describe('E2E Outbox Tests', () => { let teardown: () => void; @@ -19,7 +16,7 @@ describe('E2E Outbox Tests', () => { beforeEach(async () => { ({ teardown, aztecNode, wallets } = await setup(1)); - const receipt = await TestContract.deploy(wallets[0]).send().wait(); + const receipt = await TestContract.deploy(wallets[0]).send({ contractAddressSalt: Fr.ZERO }).wait(); contract = receipt.contract; }, 100_000); @@ -28,64 +25,80 @@ describe('E2E Outbox Tests', () => { it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { // We split two calls up, because BatchCall sends both calls in a single transaction. There are a max of 2 L2 to L1 messages per transaction const call1 = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.fromString("123")).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(53170, EthAddress.fromString("123")).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.random()).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(53170, EthAddress.random()).request(), ]); const call2 = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(64281, EthAddress.fromString("123")).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(75392, EthAddress.fromString("123")).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(64281, EthAddress.random()).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(75392, EthAddress.random()).request(), ]); const sentMessage1 = call1.send(); const sentMessage2 = call2.send(); - const [ - {blockNumber: blockNumber1}, - {blockNumber: blockNumber2}, - ] = await Promise.all([sentMessage1.wait(), sentMessage2.wait()]); + const [{ blockNumber: blockNumber1 }, { blockNumber: blockNumber2 }] = await Promise.all([ + sentMessage1.wait(), + sentMessage2.wait(), + ]); expect(blockNumber1).toBe(blockNumber2); const block = await aztecNode.getBlock(blockNumber1!); - console.log(block?.body.txEffects.length); - console.log(block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs)); - - const message1 = new L2ToL1Message(EthAddress.ZERO, new Fr(42069)); - console.log(hash(message1.toBuffer())) - - - // Use a full tree, check root as well, check index expected to be what we need considering we are hardcoding - // block header outhash === root of created sibling path tree. - - // const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => - // txEffect.l2ToL1Msgs.map(l2ToL1Message => l2ToL1Message.toBuffer()), - // ); - - // const [, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber!, Fr.ZERO); + const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - // expect(siblingPath.pathSize).toBe(2); - - // const expectedSiblingPath = new SiblingPath(siblingPath.pathSize, [ - // l2ToL1Messages![0], - // sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), + // expect(l2ToL1Messages!.map(l2ToL1Message => l2ToL1Message.toString())).toStrictEqual([ + // '0x04da3cef62599a6fe6141d3bcfde4ecd80ee0c34c8392b79bfc5da146d5f59a1', + // '0x2821af5da3956d9353aeb0768e8080f30b92947a6148362b67329c38b160cc62', + // '0x1870ebdd5912ddef86240a7d89241d868254dcbaaf5f486ff606b8d4c380a672', + // '0x1102e0512534c5c7343f1ab9ce05960dc0b7072c9b3dc2bd26acc0304839356b', // ]); - // expect(siblingPath.toString()).toBe(expectedSiblingPath.toString()); - - // const [, siblingPathAlt] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - // blockNumber!, - // Fr.fromBuffer(l2ToL1Messages![0]), - // ); - - // expect(siblingPathAlt.pathSize).toBe(2); - - // const expectedSiblingPathAlt = new SiblingPath(siblingPath.pathSize, [ - // Fr.ZERO.toBuffer(), - // sha256.hash(Fr.ZERO.toBuffer(), Fr.ZERO.toBuffer()), - // ]); - - // expect(siblingPathAlt.toString()).toBe(expectedSiblingPathAlt.toString()); + const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber1!, l2ToL1Messages![0]); + + expect(siblingPath.pathSize).toBe(2); + expect(index).toBe(0); + const expectedRoot = calculateExpectedRoot(l2ToL1Messages![0], siblingPath as SiblingPath<2>, index); + expect(expectedRoot.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + + const [index2, siblingPath2] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + blockNumber1!, + l2ToL1Messages![1], + ); + expect(siblingPath2.pathSize).toBe(2); + expect(index2).toBe(1); + const expectedRoot2 = calculateExpectedRoot(l2ToL1Messages![1], siblingPath2 as SiblingPath<2>, index2); + expect(expectedRoot2.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + + const [index3, siblingPath3] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + blockNumber1!, + l2ToL1Messages![2], + ); + expect(siblingPath3.pathSize).toBe(2); + expect(index3).toBe(2); + const expectedRoot3 = calculateExpectedRoot(l2ToL1Messages![2], siblingPath3 as SiblingPath<2>, index3); + expect(expectedRoot3.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + + const [index4, siblingPath4] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + blockNumber1!, + l2ToL1Messages![3], + ); + expect(siblingPath4.pathSize).toBe(2); + expect(index4).toBe(3); + const expectedRoot4 = calculateExpectedRoot(l2ToL1Messages![3], siblingPath4 as SiblingPath<2>, index4); + expect(expectedRoot4.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); }, 360_000); + + function calculateExpectedRoot(l2ToL1Message: Fr, siblingPath: SiblingPath<2>, index: number): Buffer { + const firstLayerInput: [Buffer, Buffer] = + index & 0x1 + ? [siblingPath.toBufferArray()[0], l2ToL1Message.toBuffer()] + : [l2ToL1Message.toBuffer(), siblingPath.toBufferArray()[0]]; + const firstLayer = sha256.hash(...firstLayerInput); + index /= 2; + const secondLayerInput: [Buffer, Buffer] = + index & 0x1 ? [siblingPath.toBufferArray()[1], firstLayer] : [firstLayer, siblingPath.toBufferArray()[1]]; + return sha256.hash(...secondLayerInput); + } }); From 3c718ee0d699411af00bb8398501c7849e88eff8 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:50:31 -0600 Subject: [PATCH 28/40] Update yarn-project/aztec-node/src/aztec-node/server.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/aztec-node/src/aztec-node/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index eff8efc95bfd..c870bf31dfaf 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -428,7 +428,7 @@ export class AztecNodeService implements AztecNode { /** * Returns the index of a l2ToL1Message in a virtual l2 to l1 data tree as well as its sibling path. - * This tree is considered virtual because it is created on-demand by: taking all the l2ToL1 messages + * @remarks This tree is considered virtual because it is created on-demand by: taking all the l2ToL1 messages * in a single block, and then using them to make a variable depth append-only tree with these messages as leaves. * The tree is discarded immediately after calculating what we need from it. * @param blockNumber - The block number at which to get the data. From 46bfb8a1c04c50953bdd7cd4162f9b5f3137033e Mon Sep 17 00:00:00 2001 From: Esau Date: Thu, 7 Mar 2024 23:51:37 +0100 Subject: [PATCH 29/40] comments --- yarn-project/aztec-node/src/aztec-node/server.ts | 4 ++-- yarn-project/circuit-types/src/interfaces/aztec-node.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index eff8efc95bfd..d857de8c8ef0 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -427,8 +427,8 @@ export class AztecNodeService implements AztecNode { } /** - * Returns the index of a l2ToL1Message in a virtual l2 to l1 data tree as well as its sibling path. - * This tree is considered virtual because it is created on-demand by: taking all the l2ToL1 messages + * Returns the index of a l2ToL1Message in a ephemeral l2 to l1 data tree as well as its sibling path. + * This tree is considered ephemeral because it is created on-demand by: taking all the l2ToL1 messages * in a single block, and then using them to make a variable depth append-only tree with these messages as leaves. * The tree is discarded immediately after calculating what we need from it. * @param blockNumber - The block number at which to get the data. diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 35b0b9729c2c..e07c721ca410 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -94,8 +94,8 @@ export interface AztecNode { ): Promise>; /** - * Returns the index of a l2ToL1Message in a virtual l2 to l1 data tree as well as its sibling path. - * This tree is considered virtual because it is created on-demand by: taking all the l2ToL1 messages + * Returns the index of a l2ToL1Message in a ephemeral l2 to l1 data tree as well as its sibling path. + * This tree is considered ephemeral because it is created on-demand by: taking all the l2ToL1 messages * in a single block, and then using them to make a variable depth append-only tree with these messages as leaves. * The tree is discarded immediately after calculating what we need from it. * @param blockNumber - The block number at which to get the data. From 389f9f53f7ecae1fe57b17faccc881a4444f0803 Mon Sep 17 00:00:00 2001 From: Esau Date: Thu, 7 Mar 2024 23:53:09 +0100 Subject: [PATCH 30/40] fix --- yarn-project/aztec-node/src/aztec-node/server.ts | 2 +- yarn-project/circuit-types/src/interfaces/aztec-node.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index d857de8c8ef0..cc1ccfa34e7e 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -428,7 +428,7 @@ export class AztecNodeService implements AztecNode { /** * Returns the index of a l2ToL1Message in a ephemeral l2 to l1 data tree as well as its sibling path. - * This tree is considered ephemeral because it is created on-demand by: taking all the l2ToL1 messages + * @remarks This tree is considered ephemeral because it is created on-demand by: taking all the l2ToL1 messages * in a single block, and then using them to make a variable depth append-only tree with these messages as leaves. * The tree is discarded immediately after calculating what we need from it. * @param blockNumber - The block number at which to get the data. diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index e07c721ca410..72bc6a5d8a87 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -95,7 +95,7 @@ export interface AztecNode { /** * Returns the index of a l2ToL1Message in a ephemeral l2 to l1 data tree as well as its sibling path. - * This tree is considered ephemeral because it is created on-demand by: taking all the l2ToL1 messages + * @remarks This tree is considered ephemeral because it is created on-demand by: taking all the l2ToL1 messages * in a single block, and then using them to make a variable depth append-only tree with these messages as leaves. * The tree is discarded immediately after calculating what we need from it. * @param blockNumber - The block number at which to get the data. From 3d6f4b1221575560ad0ba268645acd1cb343bcce Mon Sep 17 00:00:00 2001 From: Esau Date: Fri, 8 Mar 2024 00:15:24 +0100 Subject: [PATCH 31/40] comments --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 5c053b81e3b6..44b8ad3bf30d 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -6,6 +6,9 @@ import { beforeEach, describe, expect, it } from '@jest/globals'; import { setup } from './fixtures/utils.js'; +// @remark - This does not test the Outbox Contract yet. All this test does is create L2 to L1 messages in a block, +// verify their existence, and produce a sibling path that is also checked for validity against the circuit produced +// out_hash in the header. describe('E2E Outbox Tests', () => { let teardown: () => void; let aztecNode: AztecNode; @@ -42,21 +45,21 @@ describe('E2E Outbox Tests', () => { sentMessage2.wait(), ]); + // We verify that both transactions were processed in the same block expect(blockNumber1).toBe(blockNumber2); const block = await aztecNode.getBlock(blockNumber1!); const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - // expect(l2ToL1Messages!.map(l2ToL1Message => l2ToL1Message.toString())).toStrictEqual([ - // '0x04da3cef62599a6fe6141d3bcfde4ecd80ee0c34c8392b79bfc5da146d5f59a1', - // '0x2821af5da3956d9353aeb0768e8080f30b92947a6148362b67329c38b160cc62', - // '0x1870ebdd5912ddef86240a7d89241d868254dcbaaf5f486ff606b8d4c380a672', - // '0x1102e0512534c5c7343f1ab9ce05960dc0b7072c9b3dc2bd26acc0304839356b', - // ]); + // We make sure there are no suprise gifts inside the blocks L2 to L1 Messages + expect(l2ToL1Messages?.length).toStrictEqual(4); + // For each individual message, we are using our node API to grab the index and sibling path. We expect + // the index to match the order of the block we obtained earlier. We also then use this sibling path to hash up to the root, + // verifying that the expected root obtained through the message and the sibling path match the actual root + // that was returned by the circuits in the header as out_hash. const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber1!, l2ToL1Messages![0]); - expect(siblingPath.pathSize).toBe(2); expect(index).toBe(0); const expectedRoot = calculateExpectedRoot(l2ToL1Messages![0], siblingPath as SiblingPath<2>, index); From ddbd6d033ae208695ef5a8a49bd8d21ff5c00ffe Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 13:28:06 +0100 Subject: [PATCH 32/40] try this --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 44b8ad3bf30d..d50b51124eaa 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -37,12 +37,9 @@ describe('E2E Outbox Tests', () => { contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(75392, EthAddress.random()).request(), ]); - const sentMessage1 = call1.send(); - const sentMessage2 = call2.send(); - const [{ blockNumber: blockNumber1 }, { blockNumber: blockNumber2 }] = await Promise.all([ - sentMessage1.wait(), - sentMessage2.wait(), + call1.send().wait(), + call2.send().wait(), ]); // We verify that both transactions were processed in the same block @@ -52,7 +49,7 @@ describe('E2E Outbox Tests', () => { const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - // We make sure there are no suprise gifts inside the blocks L2 to L1 Messages + // We make sure there are no surprise gifts inside the blocks L2 to L1 Messages expect(l2ToL1Messages?.length).toStrictEqual(4); // For each individual message, we are using our node API to grab the index and sibling path. We expect From 8d27808d00514b79f22646237c12d9986db0cb33 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 13:42:56 +0100 Subject: [PATCH 33/40] test --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index d50b51124eaa..59e1d176deb2 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -27,6 +27,11 @@ describe('E2E Outbox Tests', () => { it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { // We split two calls up, because BatchCall sends both calls in a single transaction. There are a max of 2 L2 to L1 messages per transaction + const call0 = new BatchCall(wallets[0], [ + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), + ]); + const call1 = new BatchCall(wallets[0], [ contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.random()).request(), contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(53170, EthAddress.random()).request(), @@ -37,6 +42,8 @@ describe('E2E Outbox Tests', () => { contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(75392, EthAddress.random()).request(), ]); + await call0.send().wait(); + const [{ blockNumber: blockNumber1 }, { blockNumber: blockNumber2 }] = await Promise.all([ call1.send().wait(), call2.send().wait(), From 0726c849fd3cc041915cf03edb5461160df2bee6 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 13:58:55 +0100 Subject: [PATCH 34/40] asdf --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 59e1d176deb2..6caf4f987424 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -50,11 +50,17 @@ describe('E2E Outbox Tests', () => { ]); // We verify that both transactions were processed in the same block - expect(blockNumber1).toBe(blockNumber2); + // expect(blockNumber1).toBe(blockNumber2); - const block = await aztecNode.getBlock(blockNumber1!); - const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); + const block1 = await aztecNode.getBlock(blockNumber1!); + + const block2 = await aztecNode.getBlock(blockNumber2!); + + console.log('block1', block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs)); + console.log('block2', block2?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs)); + + const l2ToL1Messages = block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); // We make sure there are no surprise gifts inside the blocks L2 to L1 Messages expect(l2ToL1Messages?.length).toStrictEqual(4); From 94ab3912c6427f59e8b16168acdbf222376c9935 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 14:14:57 +0100 Subject: [PATCH 35/40] test --- .../end-to-end/src/e2e_outbox.test.ts | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 6caf4f987424..484b71cda57d 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -50,8 +50,6 @@ describe('E2E Outbox Tests', () => { ]); // We verify that both transactions were processed in the same block - // expect(blockNumber1).toBe(blockNumber2); - const block1 = await aztecNode.getBlock(blockNumber1!); @@ -65,42 +63,44 @@ describe('E2E Outbox Tests', () => { // We make sure there are no surprise gifts inside the blocks L2 to L1 Messages expect(l2ToL1Messages?.length).toStrictEqual(4); + expect(blockNumber1).toBe(blockNumber2); + // For each individual message, we are using our node API to grab the index and sibling path. We expect // the index to match the order of the block we obtained earlier. We also then use this sibling path to hash up to the root, // verifying that the expected root obtained through the message and the sibling path match the actual root // that was returned by the circuits in the header as out_hash. - const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber1!, l2ToL1Messages![0]); - expect(siblingPath.pathSize).toBe(2); - expect(index).toBe(0); - const expectedRoot = calculateExpectedRoot(l2ToL1Messages![0], siblingPath as SiblingPath<2>, index); - expect(expectedRoot.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); - - const [index2, siblingPath2] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - blockNumber1!, - l2ToL1Messages![1], - ); - expect(siblingPath2.pathSize).toBe(2); - expect(index2).toBe(1); - const expectedRoot2 = calculateExpectedRoot(l2ToL1Messages![1], siblingPath2 as SiblingPath<2>, index2); - expect(expectedRoot2.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); - - const [index3, siblingPath3] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - blockNumber1!, - l2ToL1Messages![2], - ); - expect(siblingPath3.pathSize).toBe(2); - expect(index3).toBe(2); - const expectedRoot3 = calculateExpectedRoot(l2ToL1Messages![2], siblingPath3 as SiblingPath<2>, index3); - expect(expectedRoot3.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); - - const [index4, siblingPath4] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - blockNumber1!, - l2ToL1Messages![3], - ); - expect(siblingPath4.pathSize).toBe(2); - expect(index4).toBe(3); - const expectedRoot4 = calculateExpectedRoot(l2ToL1Messages![3], siblingPath4 as SiblingPath<2>, index4); - expect(expectedRoot4.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + // const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber1!, l2ToL1Messages![0]); + // expect(siblingPath.pathSize).toBe(2); + // expect(index).toBe(0); + // const expectedRoot = calculateExpectedRoot(l2ToL1Messages![0], siblingPath as SiblingPath<2>, index); + // expect(expectedRoot.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + + // const [index2, siblingPath2] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + // blockNumber1!, + // l2ToL1Messages![1], + // ); + // expect(siblingPath2.pathSize).toBe(2); + // expect(index2).toBe(1); + // const expectedRoot2 = calculateExpectedRoot(l2ToL1Messages![1], siblingPath2 as SiblingPath<2>, index2); + // expect(expectedRoot2.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + + // const [index3, siblingPath3] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + // blockNumber1!, + // l2ToL1Messages![2], + // ); + // expect(siblingPath3.pathSize).toBe(2); + // expect(index3).toBe(2); + // const expectedRoot3 = calculateExpectedRoot(l2ToL1Messages![2], siblingPath3 as SiblingPath<2>, index3); + // expect(expectedRoot3.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + + // const [index4, siblingPath4] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + // blockNumber1!, + // l2ToL1Messages![3], + // ); + // expect(siblingPath4.pathSize).toBe(2); + // expect(index4).toBe(3); + // const expectedRoot4 = calculateExpectedRoot(l2ToL1Messages![3], siblingPath4 as SiblingPath<2>, index4); + // expect(expectedRoot4.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); }, 360_000); function calculateExpectedRoot(l2ToL1Message: Fr, siblingPath: SiblingPath<2>, index: number): Buffer { From 8e0c88e871608ab9e0e594753c9e6f7ce5cc3fe3 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 14:37:39 +0100 Subject: [PATCH 36/40] asdf --- .../end-to-end/src/e2e_outbox.test.ts | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 484b71cda57d..1e3762c90891 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -33,16 +33,25 @@ describe('E2E Outbox Tests', () => { ]); const call1 = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(42069, EthAddress.random()).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(53170, EthAddress.random()).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), ]); const call2 = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(64281, EthAddress.random()).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(75392, EthAddress.random()).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), ]); - await call0.send().wait(); + const {blockNumber: blockNumber0 } = await call0.send().wait(); + + console.log(blockNumber0); + + const block0 = await aztecNode.getBlock(blockNumber0!); + + console.log( + 'block0', + block0?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs), + ); const [{ blockNumber: blockNumber1 }, { blockNumber: blockNumber2 }] = await Promise.all([ call1.send().wait(), @@ -55,8 +64,14 @@ describe('E2E Outbox Tests', () => { const block2 = await aztecNode.getBlock(blockNumber2!); - console.log('block1', block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs)); - console.log('block2', block2?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs)); + console.log( + 'block1', + block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs), + ); + console.log( + 'block2', + block2?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs), + ); const l2ToL1Messages = block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); From 3b8c350f1816e352bd5fdeaa1144c6be2bd54878 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 16:05:19 +0100 Subject: [PATCH 37/40] test --- .../end-to-end/src/e2e_outbox.test.ts | 104 ++++++++++-------- 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 1e3762c90891..5a827fd62644 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,4 +1,6 @@ -import { AccountWalletWithPrivateKey, AztecNode, BatchCall, EthAddress, Fr, SiblingPath } from '@aztec/aztec.js'; +import { AccountWalletWithPrivateKey, AztecNode, BatchCall, DeployL1Contracts, EthAddress, Fr, SiblingPath, + sha256, + } from '@aztec/aztec.js'; import { SHA256 } from '@aztec/merkle-tree'; import { TestContract } from '@aztec/noir-contracts.js'; @@ -12,12 +14,13 @@ import { setup } from './fixtures/utils.js'; describe('E2E Outbox Tests', () => { let teardown: () => void; let aztecNode: AztecNode; - const sha256 = new SHA256(); + const merkleSha256 = new SHA256(); let contract: TestContract; let wallets: AccountWalletWithPrivateKey[]; + let deployL1ContractsValues: DeployL1Contracts; beforeEach(async () => { - ({ teardown, aztecNode, wallets } = await setup(1)); + ({ teardown, aztecNode, wallets, deployL1ContractsValues } = await setup(1)); const receipt = await TestContract.deploy(wallets[0]).send({ contractAddressSalt: Fr.ZERO }).wait(); contract = receipt.contract; @@ -26,59 +29,48 @@ describe('E2E Outbox Tests', () => { afterAll(() => teardown()); it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { - // We split two calls up, because BatchCall sends both calls in a single transaction. There are a max of 2 L2 to L1 messages per transaction - const call0 = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), + const recipient1 = EthAddress.random(); + const recipient2 = EthAddress.random(); + + const content = Fr.random(); + + // We can't put any more l2 to L1 messages here There are a max of 2 L2 to L1 messages per transaction + const call = new BatchCall(wallets[0], [ + contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient1).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient2).request(), ]); - const call1 = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), + const callPrivate = new BatchCall(wallets[0], [ + contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient1).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient2).request(), ]); - const call2 = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_public(0, EthAddress.random()).request(), - ]); - - const {blockNumber: blockNumber0 } = await call0.send().wait(); - - console.log(blockNumber0); - - const block0 = await aztecNode.getBlock(blockNumber0!); + + // TODO: When able to guarantee multiple txs in a single block, make this populate a full tree. Right now we are + // Unable to do this because in CI, the tx's are handled in different blocks, so it is impossible to make a full tree of L2 -> L1 messages. - console.log( - 'block0', - block0?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs), - ); + const [txReceipt1, txReceipt2] = await Promise.all([call.send().wait(), callPrivate.send().wait()]); - const [{ blockNumber: blockNumber1 }, { blockNumber: blockNumber2 }] = await Promise.all([ - call1.send().wait(), - call2.send().wait(), - ]); + const block1 = await aztecNode.getBlock(txReceipt1.blockNumber!); + const block2 = await aztecNode.getBlock(txReceipt2.blockNumber!); - // We verify that both transactions were processed in the same block + console.log(block1?.body.txEffects[0].l2ToL1Msgs); + console.log(block1?.body.txEffects[1].l2ToL1Msgs); + + const l2ToL1Messages1 = block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); + const l2ToL1Messages2 = block2?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); + console.log('first', l2ToL1Messages1); + console.log('second', l2ToL1Messages2) - const block1 = await aztecNode.getBlock(blockNumber1!); + console.log('expected', makeL2ToL1Message(recipient1, content)) + console.log('expected', makeL2ToL1Message(recipient2, content)) - const block2 = await aztecNode.getBlock(blockNumber2!); + expect(txReceipt1.blockNumber!).toStrictEqual(txReceipt2.blockNumber!) + + // expect(l2ToL1Messages1).toStrictEqual([makeL2ToL1Message(recipient1, content), makeL2ToL1Message(recipient2, content), Fr.ZERO, Fr.ZERO]); + // expect(l2ToL1Messages2).toStrictEqual([makeL2ToL1Message(recipient1, content), makeL2ToL1Message(recipient2, content), Fr.ZERO, Fr.ZERO]); - console.log( - 'block1', - block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs), - ); - console.log( - 'block2', - block2?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs), - ); - - const l2ToL1Messages = block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - - // We make sure there are no surprise gifts inside the blocks L2 to L1 Messages - expect(l2ToL1Messages?.length).toStrictEqual(4); - - expect(blockNumber1).toBe(blockNumber2); + // expect(blockNumber1).toBe(blockNumber2); // For each individual message, we are using our node API to grab the index and sibling path. We expect // the index to match the order of the block we obtained earlier. We also then use this sibling path to hash up to the root, @@ -123,10 +115,26 @@ describe('E2E Outbox Tests', () => { index & 0x1 ? [siblingPath.toBufferArray()[0], l2ToL1Message.toBuffer()] : [l2ToL1Message.toBuffer(), siblingPath.toBufferArray()[0]]; - const firstLayer = sha256.hash(...firstLayerInput); + const firstLayer = merkleSha256.hash(...firstLayerInput); index /= 2; const secondLayerInput: [Buffer, Buffer] = index & 0x1 ? [siblingPath.toBufferArray()[1], firstLayer] : [firstLayer, siblingPath.toBufferArray()[1]]; - return sha256.hash(...secondLayerInput); + return merkleSha256.hash(...secondLayerInput); + } + + function makeL2ToL1Message(recipient: EthAddress, content: Fr = Fr.ZERO): Fr { + const leaf = Fr.fromBufferReduce( + sha256( + Buffer.concat([ + contract.address.toBuffer(), + new Fr(1).toBuffer(), // aztec version + recipient.toBuffer32(), + new Fr(deployL1ContractsValues.publicClient.chain.id).toBuffer(), // chain id + content.toBuffer(), + ]), + ), + ); + + return leaf; } }); From ed4227a83a53019e6b867a23a93da3db22aff4b5 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 16:48:05 +0100 Subject: [PATCH 38/40] test --- .../end-to-end/src/e2e_outbox.test.ts | 77 ++++++++----------- 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 5a827fd62644..5e39e83ef84b 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -29,67 +29,50 @@ describe('E2E Outbox Tests', () => { afterAll(() => teardown()); it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { - const recipient1 = EthAddress.random(); - const recipient2 = EthAddress.random(); + const [[recipient1, content1], [recipient2, content2]] = [[EthAddress.random(), Fr.random()], [EthAddress.random(), Fr.random()]]; - const content = Fr.random(); - // We can't put any more l2 to L1 messages here There are a max of 2 L2 to L1 messages per transaction const call = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient1).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient2).request(), - ]); - - const callPrivate = new BatchCall(wallets[0], [ - contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient1).request(), - contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content, recipient2).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content1, recipient1).request(), + contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content2, recipient2).request(), ]); - // TODO: When able to guarantee multiple txs in a single block, make this populate a full tree. Right now we are - // Unable to do this because in CI, the tx's are handled in different blocks, so it is impossible to make a full tree of L2 -> L1 messages. + // unable to do this because in CI, for some reason, the tx's are handled in different blocks, so it is impossible + // to make a full tree of L2 -> L1 messages as we are only able to set one tx's worth of L1 -> L2 messages in a block (2 messages out of 4) + const txReceipt = await call.send().wait(); - const [txReceipt1, txReceipt2] = await Promise.all([call.send().wait(), callPrivate.send().wait()]); - - const block1 = await aztecNode.getBlock(txReceipt1.blockNumber!); - const block2 = await aztecNode.getBlock(txReceipt2.blockNumber!); - - console.log(block1?.body.txEffects[0].l2ToL1Msgs); - console.log(block1?.body.txEffects[1].l2ToL1Msgs); + const block = await aztecNode.getBlock(txReceipt.blockNumber!); - const l2ToL1Messages1 = block1?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - const l2ToL1Messages2 = block2?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - console.log('first', l2ToL1Messages1); - console.log('second', l2ToL1Messages2) + const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - console.log('expected', makeL2ToL1Message(recipient1, content)) - console.log('expected', makeL2ToL1Message(recipient2, content)) - - expect(txReceipt1.blockNumber!).toStrictEqual(txReceipt2.blockNumber!) - - // expect(l2ToL1Messages1).toStrictEqual([makeL2ToL1Message(recipient1, content), makeL2ToL1Message(recipient2, content), Fr.ZERO, Fr.ZERO]); - // expect(l2ToL1Messages2).toStrictEqual([makeL2ToL1Message(recipient1, content), makeL2ToL1Message(recipient2, content), Fr.ZERO, Fr.ZERO]); - - // expect(blockNumber1).toBe(blockNumber2); + expect(l2ToL1Messages?.map(l2ToL1Message => l2ToL1Message.toString())) + .toStrictEqual([ + makeL2ToL1Message(recipient2, content2), + makeL2ToL1Message(recipient1, content1), + Fr.ZERO, + Fr.ZERO] + .map(expectedL2ToL1Message => expectedL2ToL1Message.toString()) + ); // For each individual message, we are using our node API to grab the index and sibling path. We expect // the index to match the order of the block we obtained earlier. We also then use this sibling path to hash up to the root, // verifying that the expected root obtained through the message and the sibling path match the actual root // that was returned by the circuits in the header as out_hash. - // const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(blockNumber1!, l2ToL1Messages![0]); - // expect(siblingPath.pathSize).toBe(2); - // expect(index).toBe(0); - // const expectedRoot = calculateExpectedRoot(l2ToL1Messages![0], siblingPath as SiblingPath<2>, index); - // expect(expectedRoot.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); - - // const [index2, siblingPath2] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - // blockNumber1!, - // l2ToL1Messages![1], - // ); - // expect(siblingPath2.pathSize).toBe(2); - // expect(index2).toBe(1); - // const expectedRoot2 = calculateExpectedRoot(l2ToL1Messages![1], siblingPath2 as SiblingPath<2>, index2); - // expect(expectedRoot2.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(txReceipt.blockNumber!, l2ToL1Messages![0]); + expect(siblingPath.pathSize).toBe(2); + expect(index).toBe(0); + const expectedRoot = calculateExpectedRoot(l2ToL1Messages![0], siblingPath as SiblingPath<2>, index); + expect(expectedRoot.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); + + const [index2, siblingPath2] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + txReceipt.blockNumber!, + l2ToL1Messages![1], + ); + expect(siblingPath2.pathSize).toBe(2); + expect(index2).toBe(1); + const expectedRoot2 = calculateExpectedRoot(l2ToL1Messages![1], siblingPath2 as SiblingPath<2>, index2); + expect(expectedRoot2.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); // const [index3, siblingPath3] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( // blockNumber1!, From 11158770a2bc9b713fac0015555342504346bf44 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 17:37:13 +0100 Subject: [PATCH 39/40] fix --- .../end-to-end/src/e2e_outbox.test.ts | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 5e39e83ef84b..f8fdf2d33eca 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,6 +1,13 @@ -import { AccountWalletWithPrivateKey, AztecNode, BatchCall, DeployL1Contracts, EthAddress, Fr, SiblingPath, +import { + AccountWalletWithPrivateKey, + AztecNode, + BatchCall, + DeployL1Contracts, + EthAddress, + Fr, + SiblingPath, sha256, - } from '@aztec/aztec.js'; +} from '@aztec/aztec.js'; import { SHA256 } from '@aztec/merkle-tree'; import { TestContract } from '@aztec/noir-contracts.js'; @@ -29,37 +36,40 @@ describe('E2E Outbox Tests', () => { afterAll(() => teardown()); it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { - const [[recipient1, content1], [recipient2, content2]] = [[EthAddress.random(), Fr.random()], [EthAddress.random(), Fr.random()]]; + const [[recipient1, content1], [recipient2, content2]] = [ + [EthAddress.random(), Fr.random()], + [EthAddress.random(), Fr.random()], + ]; // We can't put any more l2 to L1 messages here There are a max of 2 L2 to L1 messages per transaction const call = new BatchCall(wallets[0], [ contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content1, recipient1).request(), contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content2, recipient2).request(), ]); - + // TODO: When able to guarantee multiple txs in a single block, make this populate a full tree. Right now we are // unable to do this because in CI, for some reason, the tx's are handled in different blocks, so it is impossible // to make a full tree of L2 -> L1 messages as we are only able to set one tx's worth of L1 -> L2 messages in a block (2 messages out of 4) const txReceipt = await call.send().wait(); const block = await aztecNode.getBlock(txReceipt.blockNumber!); - + const l2ToL1Messages = block?.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); - expect(l2ToL1Messages?.map(l2ToL1Message => l2ToL1Message.toString())) - .toStrictEqual([ - makeL2ToL1Message(recipient2, content2), - makeL2ToL1Message(recipient1, content1), - Fr.ZERO, - Fr.ZERO] - .map(expectedL2ToL1Message => expectedL2ToL1Message.toString()) - ); + expect(l2ToL1Messages?.map(l2ToL1Message => l2ToL1Message.toString())).toStrictEqual( + [makeL2ToL1Message(recipient2, content2), makeL2ToL1Message(recipient1, content1), Fr.ZERO, Fr.ZERO].map( + expectedL2ToL1Message => expectedL2ToL1Message.toString(), + ), + ); // For each individual message, we are using our node API to grab the index and sibling path. We expect // the index to match the order of the block we obtained earlier. We also then use this sibling path to hash up to the root, // verifying that the expected root obtained through the message and the sibling path match the actual root // that was returned by the circuits in the header as out_hash. - const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath(txReceipt.blockNumber!, l2ToL1Messages![0]); + const [index, siblingPath] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( + txReceipt.blockNumber!, + l2ToL1Messages![0], + ); expect(siblingPath.pathSize).toBe(2); expect(index).toBe(0); const expectedRoot = calculateExpectedRoot(l2ToL1Messages![0], siblingPath as SiblingPath<2>, index); @@ -73,24 +83,6 @@ describe('E2E Outbox Tests', () => { expect(index2).toBe(1); const expectedRoot2 = calculateExpectedRoot(l2ToL1Messages![1], siblingPath2 as SiblingPath<2>, index2); expect(expectedRoot2.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); - - // const [index3, siblingPath3] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - // blockNumber1!, - // l2ToL1Messages![2], - // ); - // expect(siblingPath3.pathSize).toBe(2); - // expect(index3).toBe(2); - // const expectedRoot3 = calculateExpectedRoot(l2ToL1Messages![2], siblingPath3 as SiblingPath<2>, index3); - // expect(expectedRoot3.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); - - // const [index4, siblingPath4] = await aztecNode.getL2ToL1MessageIndexAndSiblingPath( - // blockNumber1!, - // l2ToL1Messages![3], - // ); - // expect(siblingPath4.pathSize).toBe(2); - // expect(index4).toBe(3); - // const expectedRoot4 = calculateExpectedRoot(l2ToL1Messages![3], siblingPath4 as SiblingPath<2>, index4); - // expect(expectedRoot4.toString('hex')).toEqual(block?.header.contentCommitment.outHash.toString('hex')); }, 360_000); function calculateExpectedRoot(l2ToL1Message: Fr, siblingPath: SiblingPath<2>, index: number): Buffer { From 25f3ae4303ec3cc39cbf888e898b55ae2c583f11 Mon Sep 17 00:00:00 2001 From: Esau Date: Sat, 9 Mar 2024 17:55:06 +0100 Subject: [PATCH 40/40] fix comment --- yarn-project/end-to-end/src/e2e_outbox.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index f8fdf2d33eca..dd63b6964f7f 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -35,7 +35,7 @@ describe('E2E Outbox Tests', () => { afterAll(() => teardown()); - it('Inserts a new out message, and verifies sibling paths of both the new message, and its zeroed sibling', async () => { + it('Inserts a new transaction with two out messages, and verifies sibling paths of both the new messages', async () => { const [[recipient1, content1], [recipient2, content2]] = [ [EthAddress.random(), Fr.random()], [EthAddress.random(), Fr.random()], @@ -47,7 +47,7 @@ describe('E2E Outbox Tests', () => { contract.methods.create_l2_to_l1_message_arbitrary_recipient_private(content2, recipient2).request(), ]); - // TODO: When able to guarantee multiple txs in a single block, make this populate a full tree. Right now we are + // TODO (#5104): When able to guarantee multiple txs in a single block, make this populate a full tree. Right now we are // unable to do this because in CI, for some reason, the tx's are handled in different blocks, so it is impossible // to make a full tree of L2 -> L1 messages as we are only able to set one tx's worth of L1 -> L2 messages in a block (2 messages out of 4) const txReceipt = await call.send().wait();