1+ pub (crate ) mod cursor ;
2+ pub (crate ) mod discovered_handshakes ;
3+ pub (crate ) mod rewindable_register ;
4+
5+ use crate::sync:: {cursor::SyncCursor , discovered_handshakes:: record_discovered_handshake };
16use aztec:: {
2- capsules::CapsuleArray ,
37 context::UtilityContext ,
48 ephemeral::EphemeralArray ,
9+ facts::OriginBlock ,
510 messages ::{
611 delivery::handshake::DiscoveredHandshake ,
712 discovery ::{
@@ -14,7 +19,7 @@ use aztec::{
1419 offchain::OffchainInboxSync ,
1520 },
1621 },
17- oracle ::{ capsules , message_processing } ,
22+ oracle:: message_processing ,
1823 protocol ::{
1924 address::AztecAddress ,
2025 constants::DOM_SEP__NON_INTERACTIVE_HANDSHAKE_LOG_TAG ,
@@ -24,25 +29,18 @@ use aztec::{
2429 utils::point:: point_from_x_coord_and_sign ,
2530};
2631
27- /// Capsule base slot for the per-recipient list of discovered handshakes populated by
28- /// [`handshake_registry_sync`] and read by [`get_all_handshakes`].
29- global HANDSHAKES_CAPSULE_SLOT : Field = sha256_to_field ("HANDSHAKE_REGISTRY::HANDSHAKES" .as_bytes ());
30-
31- /// Capsule slot for the per-recipient sync cursor: the next block (inclusive) the discovery scan should start from.
32- global SYNC_CURSOR_CAPSULE_SLOT : Field = sha256_to_field ("HANDSHAKE_REGISTRY::SYNC_CURSOR" .as_bytes ());
33-
3432/// Ephemeral-array slot used by [`get_handshake_logs_in_range`] to batch a single log-retrieval request to the oracle.
3533global LOG_RETRIEVAL_REQUEST_ARRAY_SLOT : Field =
3634 sha256_to_field ("HANDSHAKE_REGISTRY::LOG_RETRIEVAL_REQUEST_ARRAY" .as_bytes ());
3735
3836/// Discovers non-interactive handshakes addressed to the syncing account.
3937///
4038/// On every sync, scans the recipient-keyed bootstrap tag over the blocks mined since the previous sync, decrypts
41- /// each matching log to recover the handshake `eph_pk`, and appends it to the recipient's
42- /// capsule list. It then falls through to [`do_sync_state`] so that normal note/event/partial-note discovery still
43- /// happens.
39+ /// each matching log to recover the handshake `eph_pk`, and records it as a retractable fact whose origin is the block
40+ /// the log landed in, so a reorg pruning that block makes the handshake invisible again. It then falls through to
41+ /// [`do_sync_state`] so that normal note/event/partial-note discovery still happens.
4442///
45- /// `scope` is the account PXE is syncing for, which doubles as both the recipient whose tag we scan and the capsule
43+ /// `scope` is the account PXE is syncing for, which doubles as both the recipient whose tag we scan and the fact
4644/// scope we persist under, so handshakes for one account never leak into another's list.
4745pub (crate ) unconstrained fn handshake_registry_sync (
4846 contract_address : AztecAddress ,
@@ -52,37 +50,36 @@ pub(crate) unconstrained fn handshake_registry_sync(
5250 offchain_inbox_sync : Option <OffchainInboxSync >,
5351 scope : AztecAddress ,
5452) {
55- let cursor = capsules:: load ::<u32 >(contract_address , SYNC_CURSOR_CAPSULE_SLOT , scope );
56- let anchor_block = UtilityContext ::new ().block_number ();
53+ let cursor = SyncCursor ::at (contract_address , scope );
54+ let from_block = cursor .next_block_to_scan ();
55+ let anchor_block_header = UtilityContext ::new ().block_header ();
56+ let anchor_block = anchor_block_header .block_number ();
5757
5858 // `to_block` is exclusive, so we add 1 to include the anchor block in the scan
5959 let next_block = anchor_block + 1 ;
60- let should_scan = cursor .map (|c | c != next_block ).unwrap_or (true );
60+ let should_scan = from_block .map (|b | b != next_block ).unwrap_or (true );
6161 if should_scan {
6262 // Find all handshakes for the given recipient
6363 let tag = compute_log_tag (scope .to_field (), DOM_SEP__NON_INTERACTIVE_HANDSHAKE_LOG_TAG );
64- let logs = get_handshake_logs_in_range (contract_address , tag , cursor , Option ::some (next_block ));
64+ let logs = get_handshake_logs_in_range (contract_address , tag , from_block , Option ::some (next_block ));
6565
66- // Store all valid handshakes
67- let handshakes : CapsuleArray <DiscoveredHandshake > =
68- CapsuleArray ::at (contract_address , HANDSHAKES_CAPSULE_SLOT , scope );
66+ // Record all valid handshakes
6967 logs .for_each (|_i , log | {
7068 let ciphertext = aztec::utils::array:: subbvec (log .log_payload , 0 );
7169
7270 let _ = AES128 ::decrypt (ciphertext , scope , contract_address )
7371 .and_then (|pt | {
7472 point_from_x_coord_and_sign (pt .get (0 ), true ).map (|pk | DiscoveredHandshake { eph_pk : pk })
7573 })
76- .map (|h | handshakes .push (h ));
74+ .map (|h | record_discovered_handshake (
75+ contract_address ,
76+ scope ,
77+ h ,
78+ OriginBlock { block_number : log .block_number , block_hash : log .block_hash },
79+ ));
7780 });
7881
79- // Update the cursor
80- capsules:: store (
81- contract_address ,
82- SYNC_CURSOR_CAPSULE_SLOT ,
83- next_block ,
84- scope ,
85- );
82+ cursor .advance (anchor_block_header );
8683 }
8784
8885 do_sync_state_without_handshake_discovery (
@@ -95,14 +92,6 @@ pub(crate) unconstrained fn handshake_registry_sync(
9592 );
9693}
9794
98- /// Returns the capsule array of discovered handshakes for `recipient`.
99- pub (crate ) unconstrained fn get_all_handshakes (
100- contract_address : AztecAddress ,
101- recipient : AztecAddress ,
102- ) -> CapsuleArray <DiscoveredHandshake > {
103- CapsuleArray ::at (contract_address , HANDSHAKES_CAPSULE_SLOT , recipient )
104- }
105-
10695/// Fetches all private logs emitted under `tag` in the block range `[from_block, to_block)`.
10796///
10897/// Thin wrapper around [`message_processing::get_logs_by_tag`] that batches a single request and unwraps the single
0 commit comments