@@ -4,7 +4,7 @@ import { padArrayEnd } from '@aztec/foundation/collection';
44import { Fr } from '@aztec/foundation/curves/bn254' ;
55import { EthAddress } from '@aztec/foundation/eth-address' ;
66import { createLogger } from '@aztec/foundation/log' ;
7- import { ScopedL2ToL1Message , computeBlockOutHash } from '@aztec/stdlib/messaging' ;
7+ import { L1ToL2MessageSponge , ScopedL2ToL1Message , computeBlockOutHash } from '@aztec/stdlib/messaging' ;
88import { makeScopedL2ToL1Message } from '@aztec/stdlib/testing' ;
99
1010import { TestContext , makeTestDeferredJobQueue } from '../mocks/test_context.js' ;
@@ -222,13 +222,15 @@ describe('prover/orchestrator/checkpoint-sub-tree', () => {
222222
223223 it ( 'slices L1-to-L2 messages per block across a multi-block checkpoint' , async ( ) => {
224224 // A checkpoint whose messages span more than one block: the first block carries a bundle, a middle block
225- // carries none (txs only), and a non-first block carries a bundle. The sub-tree must append each block's
226- // own slice at compact indices with contiguous, non-overlapping per-block snapshots (AZIP-22 Fast Inbox).
225+ // carries none (txs only), and the last block carries a bundle with zero txs (a message-only block, proven by
226+ // the msgs-only block root). The sub-tree must append each block's own slice at compact indices with
227+ // contiguous, non-overlapping per-block snapshots, and thread the message sponge across the blocks (AZIP-22
228+ // Fast Inbox).
227229 const l1ToL2MessagesPerBlock = [ [ new Fr ( 1001 ) , new Fr ( 1002 ) ] , [ ] , [ new Fr ( 1003 ) , new Fr ( 1004 ) , new Fr ( 1005 ) ] ] ;
228230 const numBlocks = l1ToL2MessagesPerBlock . length ;
229231 const { constants, blocks, l1ToL2Messages, previousBlockHeader } = await context . makeCheckpointWithMessagesPerBlock (
230232 l1ToL2MessagesPerBlock ,
231- { numTxsPerBlock : 1 } ,
233+ { numTxsPerBlock : [ 1 , 1 , 0 ] } ,
232234 ) ;
233235 expect ( l1ToL2Messages . length ) . toBe ( 5 ) ;
234236
@@ -271,6 +273,10 @@ describe('prover/orchestrator/checkpoint-sub-tree', () => {
271273 // L1-to-L2 tree state).
272274 const baseLeaf = ordered [ 0 ] . inputs . startState . l1ToL2MessageTree . nextAvailableLeafIndex ;
273275 let expectedStartLeaf = baseLeaf ;
276+ // The message sponge threads across the checkpoint's blocks: the first block starts from the empty sponge and
277+ // each block absorbs exactly its own slice (the block merge and checkpoint root circuits assert this
278+ // continuity against the InboxParity sponge).
279+ const expectedSponge = L1ToL2MessageSponge . empty ( ) ;
274280 for ( const [ i , output ] of ordered . entries ( ) ) {
275281 const inputs = output . inputs ;
276282 const startLeaf = inputs . startState . l1ToL2MessageTree . nextAvailableLeafIndex ;
@@ -284,10 +290,17 @@ describe('prover/orchestrator/checkpoint-sub-tree', () => {
284290 // Block slice = [prevBlockLeafCount, blockLeafCount): the tree grows by exactly this block's bundle size.
285291 expect ( endLeaf - startLeaf ) . toBe ( sliceLen ) ;
286292 expectedStartLeaf = endLeaf ;
293+
294+ // Sponge continuity: this block starts from the previous block's end sponge and absorbs its own slice.
295+ expect ( inputs . startMsgSponge . toBuffer ( ) ) . toEqual ( expectedSponge . toBuffer ( ) ) ;
296+ await expectedSponge . absorb ( l1ToL2MessagesPerBlock [ i ] ) ;
297+ expect ( inputs . endMsgSponge . toBuffer ( ) ) . toEqual ( expectedSponge . toBuffer ( ) ) ;
287298 }
288299
289300 // Every message is accounted for with no gap or overlap across the checkpoint's blocks.
290301 expect ( expectedStartLeaf - baseLeaf ) . toBe ( l1ToL2Messages . length ) ;
302+ // The last block's end sponge equals the checkpoint's InboxParity end sponge.
303+ expect ( result . inboxParityProof . inputs . endSponge . toBuffer ( ) ) . toEqual ( expectedSponge . toBuffer ( ) ) ;
291304 } finally {
292305 await subTree . stop ( ) ;
293306 }
0 commit comments