@@ -287,8 +287,8 @@ unconstrained fn to_payload(message: OffchainMessage) -> EphemeralArray<Field> {
287287
288288mod test {
289289 use crate:: {
290- messages::processing:: offchain ::{ OffchainMessage , receive , sync_inbox } ,
291- oracle::random:: random ,
290+ messages::processing::offchain::OffchainMessage ,
291+ oracle ::{ random:: random , tx_resolution::ResolvedTx } ,
292292 protocol::address::AztecAddress ,
293293 test::helpers::test_environment::TestEnvironment ,
294294 };
@@ -305,196 +305,115 @@ mod test {
305305 OffchainMessage { ciphertext : BoundedVec ::new (), recipient , tx_hash , anchor_block_timestamp }
306306 }
307307
308- /// Advances the TXE block timestamp by `offset` seconds and returns the resulting timestamp.
309- unconstrained fn advance_by (env : TestEnvironment , offset : u64 ) -> u64 {
310- env .advance_next_block_timestamp_by (offset );
311- env .mine_block ();
312- env .last_block_timestamp ()
313- }
314-
315- #[test]
316- unconstrained fn tx_bound_msg_expires_after_max_msg_ttl () {
317- let (env , scope ) = setup ();
318- let anchor_ts = advance_by (env , 10 );
319- let tx_hash = random ();
320- let msg = make_msg (scope , Option ::some (tx_hash ), anchor_ts );
321-
322- env .utility_context (|context | { receive (context .this_address (), BoundedVec ::from_array ([msg ])); });
323-
324- // Advance past anchor_ts + MAX_MSG_TTL.
325- let _now = advance_by (env , MAX_MSG_TTL + 1 );
326-
327- env .utility_context (|context | {
328- let address = context .this_address ();
329- let result = sync_inbox (address , scope );
330-
331- assert_eq (result .len (), 0 ); // context is None, not ready
332- assert (!OffchainReception ::is_active (address , scope , msg ), "expired reception should be terminated" );
333- });
334- }
335-
336- #[test]
337- unconstrained fn tx_bound_msg_not_expired_before_max_msg_ttl () {
338- let (env , scope ) = setup ();
339- let anchor_ts = advance_by (env , 10 );
340- let tx_hash = random ();
341- let msg = make_msg (scope , Option ::some (tx_hash ), anchor_ts );
342-
343- env .utility_context (|context | { receive (context .this_address (), BoundedVec ::from_array ([msg ])); });
344-
345- // Advance, but not past anchor_ts + MAX_MSG_TTL.
346- let _now = advance_by (env , 100 );
347-
348- env .utility_context (|context | {
349- let address = context .this_address ();
350- let result = sync_inbox (address , scope );
351-
352- assert_eq (result .len (), 0 ); // context is None, not ready
353- assert (OffchainReception ::is_active (address , scope , msg ), "not expired reception should stay active" );
354- assert (!OffchainReception ::is_processed (address , scope , msg ), "should still be unprocessed" );
355- });
308+ /// Builds the resolved-tx context PXE would return for `tx_hash`.
309+ fn resolved_tx (tx_hash : Field ) -> ResolvedTx {
310+ ResolvedTx {
311+ tx_hash ,
312+ unique_note_hashes_in_tx : BoundedVec ::new (),
313+ first_nullifier_in_tx : 0 ,
314+ block_number : 1 ,
315+ block_hash : 0 ,
316+ }
356317 }
357318
358319 #[test]
359- unconstrained fn tx_less_msg_expires_after_max_msg_ttl () {
320+ unconstrained fn expired_reception_is_terminated () {
360321 let (env , scope ) = setup ();
361- let anchor_ts = advance_by (env , 10 );
362- // A tx-less message normalizes to tx_hash 0.
363- let msg = make_msg (scope , Option ::none (), anchor_ts );
364-
365- env .utility_context (|context | { receive (context .this_address (), BoundedVec ::from_array ([msg ])); });
366-
367- // Advance past anchor_ts + MAX_MSG_TTL.
368- let _now = advance_by (env , MAX_MSG_TTL + 1 );
322+ let msg = make_msg (scope , Option ::some (random ()), 0 );
369323
370324 env .utility_context (|context | {
371325 let address = context .this_address ();
372- let result = sync_inbox (address , scope );
326+ OffchainReception ::init (address , msg );
327+ let reception = OffchainReception ::load_all (address , scope ).get (0 );
373328
374- assert_eq (result .len (), 0 ); // context is None, not ready
329+ // Past the TTL with no resolved tx: the reception is terminated.
330+ assert (reception .step (Option ::none (), MAX_MSG_TTL + 1 ).is_none ());
375331 assert (!OffchainReception ::is_active (address , scope , msg ), "expired reception should be terminated" );
376332 });
377333 }
378334
379335 #[test]
380- unconstrained fn unresolved_tx_stays_in_inbox () {
336+ unconstrained fn unresolved_reception_stays_active () {
381337 let (env , scope ) = setup ();
382- let anchor_ts = advance_by (env , 10 );
383- let tx_hash = random ();
384- let msg = make_msg (scope , Option ::some (tx_hash ), anchor_ts );
385-
386- env .utility_context (|context | { receive (context .this_address (), BoundedVec ::from_array ([msg ])); });
387-
388- let _now = advance_by (env , 100 );
338+ let msg = make_msg (scope , Option ::some (random ()), 0 );
389339
390340 env .utility_context (|context | {
391341 let address = context .this_address ();
392- let result = sync_inbox (address , scope );
342+ OffchainReception ::init (address , msg );
343+ let reception = OffchainReception ::load_all (address , scope ).get (0 );
393344
394- assert_eq (result .len (), 0 ); // not resolved, not ready
345+ // Within the TTL with no resolved tx: nothing to process, the reception stays.
346+ assert (reception .step (Option ::none (), 100 ).is_none ());
395347 assert (OffchainReception ::is_active (address , scope , msg ), "unresolved reception should stay active" );
396348 assert (!OffchainReception ::is_processed (address , scope , msg ), "should still be unprocessed" );
397349 });
398350 }
399351
400- // -- Resolved context (ready to process) ------------------------------
401-
402352 #[test]
403- unconstrained fn resolved_msg_is_ready_to_process () {
353+ unconstrained fn resolved_reception_is_ready_to_process () {
404354 let (env , scope ) = setup ();
405- // In TXE, tx hashes equal Fr(blockNumber), so Fr(1) is the tx effect from block 1.
406- // We use this as a "known resolvable" tx hash.
407- let known_tx_hash : Field = 1 ;
408- let anchor_ts = advance_by (env , 10 );
409- let msg = make_msg (scope , Option ::some (known_tx_hash ), anchor_ts );
410-
411- env .utility_context (|context | { receive (context .this_address (), BoundedVec ::from_array ([msg ])); });
412-
413- let _now = advance_by (env , 100 );
355+ let tx_hash = random ();
356+ let msg = make_msg (scope , Option ::some (tx_hash ), 0 );
414357
415358 env .utility_context (|context | {
416359 let address = context .this_address ();
417- let result = sync_inbox (address , scope );
418-
419- // The message should be ready to process since its tx context was resolved.
420- assert_eq (result .len (), 1 );
360+ OffchainReception ::init (address , msg );
361+ let reception = OffchainReception ::load_all (address , scope ).get (0 );
421362
422- let ctx = result .get (0 ).message_context ;
423- assert_eq (ctx .tx_hash , known_tx_hash );
363+ // A resolved tx within the TTL: the message is handed off with its tx context attached.
364+ let processable = reception .step (Option ::some (resolved_tx (tx_hash )), 100 );
365+ assert (processable .is_some ());
366+ assert_eq (processable .unwrap ().message_context .tx_hash , tx_hash );
424367
425- // Reception stays active (not expired) and is now marked processed, with a Processed fact recorded.
426- assert (
427- OffchainReception ::is_active (address , scope , msg ),
428- "processed reception should stay active for reorg safety" ,
429- );
368+ // It stays active for reorg safety and is now marked processed.
369+ assert (OffchainReception ::is_active (address , scope , msg ), "processed reception should stay active" );
430370 assert (OffchainReception ::is_processed (address , scope , msg ), "should be processed" );
431371 });
432372 }
433373
434374 #[test]
435- unconstrained fn already_processed_is_not_re_pushed () {
375+ unconstrained fn already_processed_reception_is_not_re_pushed () {
436376 let (env , scope ) = setup ();
437- let known_tx_hash : Field = 1 ;
438- let anchor_ts = advance_by (env , 10 );
439- let msg = make_msg (scope , Option ::some (known_tx_hash ), anchor_ts );
440-
441- env .utility_context (|context | { receive (context .this_address (), BoundedVec ::from_array ([msg ])); });
442-
443- let _now = advance_by (env , 100 );
377+ let tx_hash = random ();
378+ let msg = make_msg (scope , Option ::some (tx_hash ), 0 );
444379
445- // First sync: the message resolves, is pushed for processing.
446380 env .utility_context (|context | {
447381 let address = context .this_address ();
448- let first = sync_inbox (address , scope );
449- assert_eq (first .len (), 1 );
450- assert (OffchainReception ::is_processed (address , scope , msg ), "should be processed" );
451- });
382+ OffchainReception ::init (address , msg );
452383
453- // Second sync with the same resolvable context the reception remains active (not expired) .
454- env . utility_context (| context | {
455- let address = context . this_address ( );
456- let second = sync_inbox ( address , scope );
384+ // First step processes the message .
385+ let reception = OffchainReception :: load_all ( address , scope ). get ( 0 );
386+ assert ( reception . step ( Option :: some ( resolved_tx ( tx_hash )), 100 ). is_some () );
387+ assert ( OffchainReception :: is_processed ( address , scope , msg ), "should be processed" );
457388
458- assert_eq (second .len (), 0 ); // already processed, not re-pushed
389+ // Second step (still resolved, not expired) recognizes it as processed and does not re-push it.
390+ let reloaded = OffchainReception ::load_all (address , scope ).get (0 );
391+ assert (reloaded .step (Option ::some (resolved_tx (tx_hash )), 100 ).is_none (), "already processed" );
459392 assert (OffchainReception ::is_active (address , scope , msg ), "processed reception should still be active" );
460- assert (OffchainReception ::is_processed (address , scope , msg ), "should remain processed" );
461393 });
462394 }
463395
464396 #[test]
465- unconstrained fn expired_resolved_msg_is_processed_once_before_termination () {
397+ unconstrained fn expired_resolved_reception_is_processed_once_before_termination () {
466398 let (env , scope ) = setup ();
467- let known_tx_hash : Field = 1 ;
468- let anchor_ts = advance_by (env , 10 );
469- let msg = make_msg (scope , Option ::some (known_tx_hash ), anchor_ts );
470-
471- env .utility_context (|context | { receive (context .this_address (), BoundedVec ::from_array ([msg ])); });
472-
473- // Advance past anchor_ts + MAX_MSG_TTL so the message is expired on the next sync.
474- let _now = advance_by (env , MAX_MSG_TTL + 1 );
399+ let tx_hash = random ();
400+ let msg = make_msg (scope , Option ::some (tx_hash ), 0 );
475401
476- // First sync: even though the message is expired, its context resolves, so it is handed off for processing.
477402 env .utility_context (|context | {
478403 let address = context .this_address ();
479- let result = sync_inbox (address , scope );
404+ OffchainReception :: init (address , msg );
480405
481- assert_eq (result .len (), 1 );
482- assert (
483- OffchainReception ::is_active (address , scope , msg ),
484- "expired-but-resolved reception is processed, not terminated yet" ,
485- );
406+ // Expired but resolved: the message is processed once (not terminated yet).
407+ let reception = OffchainReception ::load_all (address , scope ).get (0 );
408+ assert (reception .step (Option ::some (resolved_tx (tx_hash )), MAX_MSG_TTL + 1 ).is_some ());
486409 assert (OffchainReception ::is_processed (address , scope , msg ), "should be processed" );
487- });
488-
489- // Second sync: still expired and now processed, so the reception is terminated.
490- env .utility_context (|context | {
491- let address = context .this_address ();
492- let second = sync_inbox (address , scope );
493410
494- assert_eq (second .len (), 0 ); // already processed, not re-pushed
411+ // Next step: still expired and now processed, so the reception is terminated.
412+ let reloaded = OffchainReception ::load_all (address , scope ).get (0 );
413+ assert (reloaded .step (Option ::some (resolved_tx (tx_hash )), MAX_MSG_TTL + 1 ).is_none ());
495414 assert (
496415 !OffchainReception ::is_active (address , scope , msg ),
497- "expired processed reception is terminated on the next sync " ,
416+ "expired processed reception is terminated on the next step " ,
498417 );
499418 });
500419 }
0 commit comments