Skip to content

Commit 4121ad7

Browse files
committed
fix(fast-inbox): expose getL1ToL2MessageIndex on the node so wait-for-message-seen works pre-consumption (A-1384)
The flip repointed getL1ToL2MessageCheckpoint to answer from block records (it now returns undefined until a block consumes the message), silently breaking waitForL1ToL2MessageSeen's contract that it only confirms the archiver ingested the message from L1, without requiring the L2 chain to advance. Every caller uses the two-phase wait-seen-then-advance pattern with tight windows, so the l1-reorgs messages e2e (and message harnesses) time out waiting for a checkpoint that needs inbox lag plus a consuming block. Add getL1ToL2MessageIndex to the AztecNode interface/schema/server (delegating to the existing message source method) and repoint waitForL1ToL2MessageSeen to it, restoring the pre-consumption lookup over a remote-capable node.
1 parent e8df63d commit 4121ad7

5 files changed

Lines changed: 28 additions & 2 deletions

File tree

yarn-project/aztec-node/src/aztec-node/server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, AztecNodeDeb
678678
return this.worldStateQueries.getL1ToL2MessageCheckpoint(l1ToL2Message);
679679
}
680680

681+
public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
682+
return this.worldStateQueries.getL1ToL2MessageIndex(l1ToL2Message);
683+
}
684+
681685
/**
682686
* Returns all the L2 to L1 messages in an epoch.
683687
*

yarn-project/aztec-node/src/modules/node_world_state_queries.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ export class NodeWorldStateQueries {
183183
return [witness.index, witness.path];
184184
}
185185

186+
public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
187+
return this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
188+
}
189+
186190
public async getL1ToL2MessageCheckpoint(l1ToL2Message: Fr): Promise<CheckpointNumber | undefined> {
187191
const messageIndex = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
188192
if (messageIndex === undefined) {

yarn-project/end-to-end/src/shared/wait_for_l1_to_l2_message.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ import { retryUntil } from '@aztec/foundation/retry';
1010
* blocks afterwards to make the message consumable.
1111
*/
1212
export function waitForL1ToL2MessageSeen(
13-
node: Pick<AztecNode, 'getL1ToL2MessageCheckpoint'>,
13+
node: Pick<AztecNode, 'getL1ToL2MessageIndex'>,
1414
l1ToL2MessageHash: Fr,
1515
opts: { timeoutSeconds: number },
1616
) {
1717
return retryUntil(
18-
async () => (await node.getL1ToL2MessageCheckpoint(l1ToL2MessageHash)) !== undefined,
18+
async () => (await node.getL1ToL2MessageIndex(l1ToL2MessageHash)) !== undefined,
1919
`L1 to L2 message ${l1ToL2MessageHash.toString()} seen`,
2020
opts.timeoutSeconds,
2121
0.25,

yarn-project/stdlib/src/interfaces/aztec-node.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ describe('AztecNodeApiSchema', () => {
159159
expect(response).toEqual(5);
160160
});
161161

162+
it('getL1ToL2MessageIndex', async () => {
163+
const response = await context.client.getL1ToL2MessageIndex(Fr.random());
164+
expect(response).toEqual(5n);
165+
});
166+
162167
it('getL2ToL1Messages', async () => {
163168
const response = await context.client.getL2ToL1Messages(EpochNumber(1));
164169
expect(response.length).toBe(3);
@@ -714,6 +719,10 @@ class MockAztecNode implements AztecNode {
714719
expect(l1ToL2Message).toBeInstanceOf(Fr);
715720
return Promise.resolve(CheckpointNumber(5));
716721
}
722+
getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
723+
expect(l1ToL2Message).toBeInstanceOf(Fr);
724+
return Promise.resolve(5n);
725+
}
717726
getL2ToL1Messages(_epoch: EpochNumber): Promise<Fr[][][][]> {
718727
return Promise.resolve(
719728
Array.from({ length: 3 }, (_, i) =>

yarn-project/stdlib/src/interfaces/aztec-node.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,13 @@ export interface AztecNode {
203203
/** Returns the L2 checkpoint number in which this L1 to L2 message becomes available, or undefined if not found. */
204204
getL1ToL2MessageCheckpoint(l1ToL2Message: Fr): Promise<CheckpointNumber | undefined>;
205205

206+
/**
207+
* Returns the compact leaf index assigned to this L1 to L2 message as soon as the node has ingested it from L1,
208+
* before any L2 block consumes it. Returns undefined if the node has not yet seen the message. Unlike
209+
* {@link getL1ToL2MessageCheckpoint}, this does not require the L2 chain to have advanced past the message.
210+
*/
211+
getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined>;
212+
206213
/**
207214
* Returns all the L2 to L1 messages in an epoch.
208215
*
@@ -611,6 +618,8 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
611618

612619
getL1ToL2MessageCheckpoint: z.function({ input: z.tuple([schemas.Fr]), output: CheckpointNumberSchema.optional() }),
613620

621+
getL1ToL2MessageIndex: z.function({ input: z.tuple([schemas.Fr]), output: schemas.BigInt.optional() }),
622+
614623
getL2ToL1Messages: z.function({
615624
input: z.tuple([EpochNumberSchema]),
616625
output: z.array(z.array(z.array(z.array(schemas.Fr)))),

0 commit comments

Comments
 (0)