@aztec/pxe 6.0.0-nightly.20260821 → 6.0.0-nightly.20260823
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/block_synchronizer/block_synchronizer.d.ts +4 -8
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +6 -10
- package/dest/config/index.d.ts +1 -1
- package/dest/contract/contract_call_graph.d.ts +18 -19
- package/dest/contract/contract_call_graph.d.ts.map +1 -1
- package/dest/contract/contract_call_graph.js +26 -26
- package/dest/contract/contract_sync_service.d.ts +17 -18
- package/dest/contract/contract_sync_service.d.ts.map +1 -1
- package/dest/contract/contract_sync_service.js +44 -47
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +6 -5
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +6 -6
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +5 -5
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +4 -3
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +20 -20
- package/dest/debug/pxe_debug_utils.d.ts +5 -4
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/debug/pxe_debug_utils.js +7 -7
- package/dest/entrypoints/server/index.d.ts +3 -2
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +2 -1
- package/dest/events/event_service.d.ts +4 -5
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +4 -6
- package/dest/logs/log_service.d.ts +4 -3
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +4 -4
- package/dest/notes/note_service.d.ts +4 -3
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +8 -8
- package/dest/operation_lifecycle.d.ts +45 -0
- package/dest/operation_lifecycle.d.ts.map +1 -0
- package/dest/operation_lifecycle.js +60 -0
- package/dest/operation_queue.d.ts +75 -0
- package/dest/operation_queue.d.ts.map +1 -0
- package/dest/operation_queue.js +100 -0
- package/dest/pxe.d.ts +3 -17
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +65 -120
- package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts +1 -1
- package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts.map +1 -1
- package/dest/storage/backwards_compatibility_tests/schema_tests.js +42 -42
- package/dest/storage/capsule_store/capsule_service.d.ts +9 -8
- package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_service.js +14 -14
- package/dest/storage/capsule_store/capsule_store.d.ts +17 -17
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +68 -72
- package/dest/storage/fact_store/fact_service.d.ts +6 -5
- package/dest/storage/fact_store/fact_service.d.ts.map +1 -1
- package/dest/storage/fact_store/fact_service.js +8 -8
- package/dest/storage/fact_store/fact_store.d.ts +19 -17
- package/dest/storage/fact_store/fact_store.d.ts.map +1 -1
- package/dest/storage/fact_store/fact_store.js +41 -40
- package/dest/storage/note_store/note_store.d.ts +21 -20
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +81 -84
- package/dest/storage/private_event_store/private_event_store.d.ts +18 -16
- package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
- package/dest/storage/private_event_store/private_event_store.js +54 -53
- package/dest/storage/rollbackable.d.ts +15 -0
- package/dest/storage/rollbackable.d.ts.map +1 -0
- package/dest/storage/rollbackable.js +3 -0
- package/dest/storage/staged_write_coordinator.d.ts +82 -0
- package/dest/storage/staged_write_coordinator.d.ts.map +1 -0
- package/dest/storage/staged_write_coordinator.js +93 -0
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts +11 -10
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/recipient_tagging_store.js +50 -49
- package/dest/storage/tagging_store/sender_tagging_store.d.ts +22 -18
- package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/sender_tagging_store.js +85 -81
- package/dest/tagging/persist_sender_tagging_index_ranges.d.ts +5 -3
- package/dest/tagging/persist_sender_tagging_index_ranges.d.ts.map +1 -1
- package/dest/tagging/persist_sender_tagging_index_ranges.js +4 -3
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts +3 -2
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts.map +1 -1
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.js +11 -11
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +3 -2
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +9 -9
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +5 -4
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +4 -4
- package/dest/test_utils.d.ts +3 -0
- package/dest/test_utils.d.ts.map +1 -0
- package/dest/test_utils.js +1 -0
- package/package.json +14 -16
- package/src/block_synchronizer/block_synchronizer.ts +5 -9
- package/src/config/index.ts +1 -1
- package/src/contract/contract_call_graph.ts +37 -29
- package/src/contract/contract_sync_service.ts +65 -58
- package/src/contract_function_simulator/contract_function_simulator.ts +9 -8
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +5 -5
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +22 -21
- package/src/debug/pxe_debug_utils.ts +11 -10
- package/src/entrypoints/server/index.ts +2 -1
- package/src/events/event_service.ts +3 -4
- package/src/logs/log_service.ts +3 -2
- package/src/notes/note_service.ts +7 -6
- package/src/operation_lifecycle.ts +93 -0
- package/src/operation_queue.ts +149 -0
- package/src/pxe.ts +70 -145
- package/src/storage/backwards_compatibility_tests/schema_tests.ts +48 -42
- package/src/storage/capsule_store/capsule_service.ts +26 -14
- package/src/storage/capsule_store/capsule_store.ts +91 -74
- package/src/storage/fact_store/fact_service.ts +9 -8
- package/src/storage/fact_store/fact_store.ts +51 -47
- package/src/storage/note_store/note_store.ts +85 -88
- package/src/storage/private_event_store/private_event_store.ts +59 -58
- package/src/storage/rollbackable.ts +14 -0
- package/src/storage/staged_write_coordinator.ts +153 -0
- package/src/storage/tagging_store/recipient_tagging_store.ts +51 -50
- package/src/storage/tagging_store/sender_tagging_store.ts +98 -82
- package/src/tagging/persist_sender_tagging_index_ranges.ts +5 -3
- package/src/tagging/recipient_sync/sync_tagged_private_logs.ts +13 -12
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +18 -9
- package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +5 -4
- package/src/test_utils.ts +2 -0
- package/dest/job_coordinator/job_coordinator.d.ts +0 -84
- package/dest/job_coordinator/job_coordinator.d.ts.map +0 -1
- package/dest/job_coordinator/job_coordinator.js +0 -113
- package/src/job_coordinator/job_coordinator.ts +0 -180
|
@@ -6,9 +6,7 @@ import type { BlockSynchronizerConfig } from '../config/index.js';
|
|
|
6
6
|
import type { ContractSyncService } from '../contract/contract_sync_service.js';
|
|
7
7
|
import type { CachingAztecNode } from '../node/caching_aztec_node.js';
|
|
8
8
|
import type { AnchorBlockStore } from '../storage/anchor_block_store/index.js';
|
|
9
|
-
import type {
|
|
10
|
-
import type { NoteStore } from '../storage/note_store/index.js';
|
|
11
|
-
import type { PrivateEventStore } from '../storage/private_event_store/private_event_store.js';
|
|
9
|
+
import type { Rollbackable } from '../storage/rollbackable.js';
|
|
12
10
|
/**
|
|
13
11
|
* The BlockSynchronizer class orchestrates synchronization between PXE and Aztec node, maintaining an up-to-date
|
|
14
12
|
* view of the L2 chain state. It handles block header retrieval, chain reorganizations, and provides an interface
|
|
@@ -18,9 +16,7 @@ export declare class BlockSynchronizer implements L2BlockStreamEventHandler {
|
|
|
18
16
|
private readonly node;
|
|
19
17
|
private readonly store;
|
|
20
18
|
private readonly anchorBlockStore;
|
|
21
|
-
private readonly
|
|
22
|
-
private readonly privateEventStore;
|
|
23
|
-
private readonly factStore;
|
|
19
|
+
private readonly rollbackables;
|
|
24
20
|
private readonly l2TipsStore;
|
|
25
21
|
private readonly contractSyncService;
|
|
26
22
|
private readonly config;
|
|
@@ -28,7 +24,7 @@ export declare class BlockSynchronizer implements L2BlockStreamEventHandler {
|
|
|
28
24
|
private isSyncing;
|
|
29
25
|
private readonly eventQueue;
|
|
30
26
|
protected readonly blockStream: L2BlockStream;
|
|
31
|
-
constructor(node: CachingAztecNode, store: AztecAsyncKVStore, anchorBlockStore: AnchorBlockStore,
|
|
27
|
+
constructor(node: CachingAztecNode, store: AztecAsyncKVStore, anchorBlockStore: AnchorBlockStore, rollbackables: Rollbackable[], l2TipsStore: L2TipsKVStore, contractSyncService: ContractSyncService, config?: Partial<BlockSynchronizerConfig>, bindings?: LoggerBindings);
|
|
32
28
|
protected createBlockStream(): L2BlockStream;
|
|
33
29
|
/** Handle events emitted by the block stream. Serialized to prevent concurrent mutations to anchor state. */
|
|
34
30
|
handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void>;
|
|
@@ -48,4 +44,4 @@ export declare class BlockSynchronizer implements L2BlockStreamEventHandler {
|
|
|
48
44
|
stop(): Promise<void>;
|
|
49
45
|
private doSync;
|
|
50
46
|
}
|
|
51
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfc3luY2hyb25pemVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmxvY2tfc3luY2hyb25pemVyL2Jsb2NrX3N5bmNocm9uaXplci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQWUsS0FBSyxjQUFjLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFFdkYsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLEVBQWEsYUFBYSxFQUFFLEtBQUssa0JBQWtCLEVBQUUsS0FBSyx5QkFBeUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBR3hILE9BQU8sS0FBSyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUNoRixPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3RFLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDL0UsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFHL0Q7Ozs7R0FJRztBQUNILHFCQUFhLGlCQUFrQixZQUFXLHlCQUF5QjtJQU8vRCxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFDckIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLO0lBQ3RCLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCO0lBQ2pDLE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYTtJQUM5QixPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVc7SUFDNUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxtQkFBbUI7SUFDcEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNO0lBWnpCLE9BQU8sQ0FBQyxHQUFHLENBQVM7SUFDcEIsT0FBTyxDQUFDLFNBQVMsQ0FBNEI7SUFDN0MsT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQXFCO0lBQ2hELFNBQVMsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLGFBQWEsQ0FBQztJQUU5QyxZQUNtQixJQUFJLEVBQUUsZ0JBQWdCLEVBQ3RCLEtBQUssRUFBRSxpQkFBaUIsRUFDeEIsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQ2xDLGFBQWEsRUFBRSxZQUFZLEVBQUUsRUFDN0IsV0FBVyxFQUFFLGFBQWEsRUFDMUIsbUJBQW1CLEVBQUUsbUJBQW1CLEVBQ3hDLE1BQU0sR0FBRSxPQUFPLENBQUMsdUJBQXVCLENBQU0sRUFDOUQsUUFBUSxDQUFDLEVBQUUsY0FBYyxFQUsxQjtJQUVELFNBQVMsQ0FBQyxpQkFBaUIsSUFBSSxhQUFhLENBWTNDO0lBRUQsNkdBQTZHO0lBQ3RHLHNCQUFzQixDQUFDLEtBQUssRUFBRSxrQkFBa0IsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBRXRFO1lBRWEsd0JBQXdCO1lBZ0d4Qix1QkFBdUI7SUFjckM7Ozs7Ozs7O09BUUc7SUFDVSxJQUFJLGtCQWlCaEI7SUFFRCxvR0FBb0c7SUFDdkYsSUFBSSxrQkFJaEI7WUFFYSxNQUFNO0NBY3JCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_synchronizer.d.ts","sourceRoot":"","sources":["../../src/block_synchronizer/block_synchronizer.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAa,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAGxH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"block_synchronizer.d.ts","sourceRoot":"","sources":["../../src/block_synchronizer/block_synchronizer.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAa,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAGxH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,yBAAyB;IAO/D,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAZzB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC;IAE9C,YACmB,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,iBAAiB,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,aAAa,EAAE,YAAY,EAAE,EAC7B,WAAW,EAAE,aAAa,EAC1B,mBAAmB,EAAE,mBAAmB,EACxC,MAAM,GAAE,OAAO,CAAC,uBAAuB,CAAM,EAC9D,QAAQ,CAAC,EAAE,cAAc,EAK1B;IAED,SAAS,CAAC,iBAAiB,IAAI,aAAa,CAY3C;IAED,6GAA6G;IACtG,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;YAEa,wBAAwB;YAgGxB,uBAAuB;IAcrC;;;;;;;;OAQG;IACU,IAAI,kBAiBhB;IAED,oGAAoG;IACvF,IAAI,kBAIhB;YAEa,MAAM;CAcrB"}
|
|
@@ -11,9 +11,7 @@ import { blockStreamSourceFromAztecNode } from './block_stream_source.js';
|
|
|
11
11
|
node;
|
|
12
12
|
store;
|
|
13
13
|
anchorBlockStore;
|
|
14
|
-
|
|
15
|
-
privateEventStore;
|
|
16
|
-
factStore;
|
|
14
|
+
rollbackables;
|
|
17
15
|
l2TipsStore;
|
|
18
16
|
contractSyncService;
|
|
19
17
|
config;
|
|
@@ -21,13 +19,11 @@ import { blockStreamSourceFromAztecNode } from './block_stream_source.js';
|
|
|
21
19
|
isSyncing;
|
|
22
20
|
eventQueue;
|
|
23
21
|
blockStream;
|
|
24
|
-
constructor(node, store, anchorBlockStore,
|
|
22
|
+
constructor(node, store, anchorBlockStore, rollbackables, l2TipsStore, contractSyncService, config = {}, bindings){
|
|
25
23
|
this.node = node;
|
|
26
24
|
this.store = store;
|
|
27
25
|
this.anchorBlockStore = anchorBlockStore;
|
|
28
|
-
this.
|
|
29
|
-
this.privateEventStore = privateEventStore;
|
|
30
|
-
this.factStore = factStore;
|
|
26
|
+
this.rollbackables = rollbackables;
|
|
31
27
|
this.l2TipsStore = l2TipsStore;
|
|
32
28
|
this.contractSyncService = contractSyncService;
|
|
33
29
|
this.config = config;
|
|
@@ -121,9 +117,9 @@ import { blockStreamSourceFromAztecNode } from './block_stream_source.js';
|
|
|
121
117
|
}
|
|
122
118
|
// Operations are wrapped in a single transaction to ensure atomicity.
|
|
123
119
|
await this.store.transactionAsync(async ()=>{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
for (const rollbackable of this.rollbackables){
|
|
121
|
+
await rollbackable.rollbackToBlock(event.block.number);
|
|
122
|
+
}
|
|
127
123
|
await this.updateAnchorBlockHeader(newAnchorBlockHeader);
|
|
128
124
|
});
|
|
129
125
|
break;
|
package/dest/config/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface ContractSyncConfig {
|
|
|
32
32
|
/**
|
|
33
33
|
* Whether PXE speculatively syncs contracts it predicts will follow the one requested, running them concurrently
|
|
34
34
|
* with it instead of waiting for execution to reach them. When enabled, repeated flows sync faster, but a wrong
|
|
35
|
-
* prediction spends unnecessary node requests syncing contracts the
|
|
35
|
+
* prediction spends unnecessary node requests syncing contracts the operation never uses.
|
|
36
36
|
*
|
|
37
37
|
* Experimental, off by default.
|
|
38
38
|
*/
|
|
@@ -1,41 +1,42 @@
|
|
|
1
1
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
2
2
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
|
+
import type { ChangeSetId } from '../storage/staged_write_coordinator.js';
|
|
3
4
|
/** Confidence a call must reach to be predicted. */
|
|
4
5
|
export declare const PREDICTION_THRESHOLD = 2;
|
|
5
|
-
/** Cap on a call's confidence, so a function called by many
|
|
6
|
+
/** Cap on a call's confidence, so a function called by many operations is still dropped within a few missed ones. */
|
|
6
7
|
export declare const MAX_CONFIDENCE = 5;
|
|
7
8
|
/**
|
|
8
|
-
* A call graph over contract functions - who calls whom - learned from the direct calls observed in past
|
|
9
|
+
* A call graph over contract functions - who calls whom - learned from the direct calls observed in past operations, so
|
|
9
10
|
* a function's predicted callees can sync their contracts before execution reaches them.
|
|
10
11
|
*
|
|
11
|
-
* A function's direct calls tend to repeat across
|
|
12
|
-
* may call an authwit, an AMM calls its tokens. The same function does not always make the same calls, though:
|
|
13
|
-
* can depend on context or storage state. A call must therefore repeat often enough to earn confidence before it
|
|
14
|
-
* predicted. Calls are keyed per function, not per contract, since different functions of a contract call different
|
|
15
|
-
* contracts. See {@link
|
|
12
|
+
* A function's direct calls tend to repeat across operations: constrained delivery calls the handshake registry, a
|
|
13
|
+
* transfer may call an authwit, an AMM calls its tokens. The same function does not always make the same calls, though:
|
|
14
|
+
* they can depend on context or storage state. A call must therefore repeat often enough to earn confidence before it
|
|
15
|
+
* is predicted. Calls are keyed per function, not per contract, since different functions of a contract call different
|
|
16
|
+
* contracts. See {@link learn} for how each call's confidence is learned from committed operations.
|
|
16
17
|
*
|
|
17
18
|
* Purely in-memory bookkeeping: the graph is lost when PXE is rebuilt (e.g. on restart).
|
|
18
19
|
*/
|
|
19
20
|
export declare class ContractCallGraph {
|
|
20
21
|
private readonly enabled;
|
|
21
|
-
private readonly
|
|
22
|
+
private readonly activeChangeSets;
|
|
22
23
|
private readonly callConfidence;
|
|
23
24
|
constructor(enabled: boolean);
|
|
24
|
-
/** Records that `caller` directly called `callee` in the given
|
|
25
|
-
recordCall({
|
|
26
|
-
|
|
25
|
+
/** Records that `caller` directly called `callee` in the given change set. */
|
|
26
|
+
recordCall({ changeSetId, caller, callee }: {
|
|
27
|
+
changeSetId: ChangeSetId;
|
|
27
28
|
caller: ContractFunction;
|
|
28
29
|
callee: ContractFunction;
|
|
29
30
|
}): void;
|
|
30
31
|
/** Predicts the functions `caller` will call directly. */
|
|
31
32
|
predictDirectCallees(caller: ContractFunction): ContractFunction[];
|
|
32
33
|
/**
|
|
33
|
-
*
|
|
34
|
-
* callees untouched, so read-only uses (e.g. reading notes or events) erode nothing.
|
|
34
|
+
* Learns from a committed change set: the calls it observed update each caller's confidence. A function that called
|
|
35
|
+
* nothing keeps its callees untouched, so read-only uses (e.g. reading notes or events) erode nothing.
|
|
35
36
|
*/
|
|
36
|
-
|
|
37
|
-
/** Drops a discarded
|
|
38
|
-
|
|
37
|
+
learn(changeSetId: ChangeSetId): void;
|
|
38
|
+
/** Drops a discarded change set without learning. */
|
|
39
|
+
discard(changeSetId: ChangeSetId): void;
|
|
39
40
|
}
|
|
40
41
|
/** A specific function of a contract, as observed in a call. */
|
|
41
42
|
export type ContractFunction = {
|
|
@@ -44,9 +45,7 @@ export type ContractFunction = {
|
|
|
44
45
|
/** The selector of the function. */
|
|
45
46
|
selector: FunctionSelector;
|
|
46
47
|
};
|
|
47
|
-
type JobId = string;
|
|
48
48
|
/** A {@link ContractFunction} flattened to a `contractAddress:selector` string, so maps can key on it. */
|
|
49
49
|
export type CallKey = `0x${string}:${string}`;
|
|
50
50
|
export declare function toCallKey({ address, selector }: ContractFunction): CallKey;
|
|
51
|
-
|
|
52
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RfY2FsbF9ncmFwaC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnRyYWN0L2NvbnRyYWN0X2NhbGxfZ3JhcGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDckQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRTNELG9EQUFvRDtBQUNwRCxlQUFPLE1BQU0sb0JBQW9CLElBQUksQ0FBQztBQUV0QywrR0FBK0c7QUFDL0csZUFBTyxNQUFNLGNBQWMsSUFBSSxDQUFDO0FBRWhDOzs7Ozs7Ozs7OztHQVdHO0FBQ0gscUJBQWEsaUJBQWlCO0lBT2hCLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTztJQUxwQyxPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBcUQ7SUFHaEYsT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQWlEO0lBRWhGLFlBQTZCLE9BQU8sRUFBRSxPQUFPLEVBQUk7SUFFakQsdUVBQXVFO0lBQ3ZFLFVBQVUsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDO1FBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDO1FBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFBO0tBQUUsR0FBRyxJQUFJLENBaUJoSDtJQUVELDBEQUEwRDtJQUMxRCxvQkFBb0IsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLEdBQUcsZ0JBQWdCLEVBQUUsQ0FLakU7SUFFRDs7O09BR0c7SUFDSCxTQUFTLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxJQUFJLENBc0I1QjtJQUVELDhDQUE4QztJQUM5QyxVQUFVLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxJQUFJLENBRTdCO0NBQ0Y7QUFFRCxnRUFBZ0U7QUFDaEUsTUFBTSxNQUFNLGdCQUFnQixHQUFHO0lBQzdCLDJEQUEyRDtJQUMzRCxPQUFPLEVBQUUsWUFBWSxDQUFDO0lBQ3RCLG9DQUFvQztJQUNwQyxRQUFRLEVBQUUsZ0JBQWdCLENBQUM7Q0FDNUIsQ0FBQztBQUVGLEtBQUssS0FBSyxHQUFHLE1BQU0sQ0FBQztBQUVwQiwwR0FBMEc7QUFDMUcsTUFBTSxNQUFNLE9BQU8sR0FBRyxLQUFLLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztBQUU5Qyx3QkFBZ0IsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FFMUUifQ==
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RfY2FsbF9ncmFwaC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnRyYWN0L2NvbnRyYWN0X2NhbGxfZ3JhcGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDckQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRTNELE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBRTFFLG9EQUFvRDtBQUNwRCxlQUFPLE1BQU0sb0JBQW9CLElBQUksQ0FBQztBQUV0QyxxSEFBcUg7QUFDckgsZUFBTyxNQUFNLGNBQWMsSUFBSSxDQUFDO0FBRWhDOzs7Ozs7Ozs7OztHQVdHO0FBQ0gscUJBQWEsaUJBQWlCO0lBT2hCLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTztJQUxwQyxPQUFPLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUEyRDtJQUc1RixPQUFPLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBaUQ7SUFFaEYsWUFBNkIsT0FBTyxFQUFFLE9BQU8sRUFBSTtJQUVqRCw4RUFBOEU7SUFDOUUsVUFBVSxDQUFDLEVBQ1QsV0FBVyxFQUNYLE1BQU0sRUFDTixNQUFNLEVBQ1AsRUFBRTtRQUNELFdBQVcsRUFBRSxXQUFXLENBQUM7UUFDekIsTUFBTSxFQUFFLGdCQUFnQixDQUFDO1FBQ3pCLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQztLQUMxQixHQUFHLElBQUksQ0FpQlA7SUFFRCwwREFBMEQ7SUFDMUQsb0JBQW9CLENBQUMsTUFBTSxFQUFFLGdCQUFnQixHQUFHLGdCQUFnQixFQUFFLENBS2pFO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsSUFBSSxDQXNCcEM7SUFFRCxxREFBcUQ7SUFDckQsT0FBTyxDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsSUFBSSxDQUV0QztDQUNGO0FBRUQsZ0VBQWdFO0FBQ2hFLE1BQU0sTUFBTSxnQkFBZ0IsR0FBRztJQUM3QiwyREFBMkQ7SUFDM0QsT0FBTyxFQUFFLFlBQVksQ0FBQztJQUN0QixvQ0FBb0M7SUFDcEMsUUFBUSxFQUFFLGdCQUFnQixDQUFDO0NBQzVCLENBQUM7QUFFRiwwR0FBMEc7QUFDMUcsTUFBTSxNQUFNLE9BQU8sR0FBRyxLQUFLLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztBQUU5Qyx3QkFBZ0IsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FFMUUifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract_call_graph.d.ts","sourceRoot":"","sources":["../../src/contract/contract_call_graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,oDAAoD;AACpD,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC
|
|
1
|
+
{"version":3,"file":"contract_call_graph.d.ts","sourceRoot":"","sources":["../../src/contract/contract_call_graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAE1E,oDAAoD;AACpD,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,qHAAqH;AACrH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAiB;IAOhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2D;IAG5F,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiD;IAEhF,YAA6B,OAAO,EAAE,OAAO,EAAI;IAEjD,8EAA8E;IAC9E,UAAU,CAAC,EACT,WAAW,EACX,MAAM,EACN,MAAM,EACP,EAAE;QACD,WAAW,EAAE,WAAW,CAAC;QACzB,MAAM,EAAE,gBAAgB,CAAC;QACzB,MAAM,EAAE,gBAAgB,CAAC;KAC1B,GAAG,IAAI,CAiBP;IAED,0DAA0D;IAC1D,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAKjE;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAsBpC;IAED,qDAAqD;IACrD,OAAO,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAEtC;CACF;AAED,gEAAgE;AAChE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,2DAA2D;IAC3D,OAAO,EAAE,YAAY,CAAC;IACtB,oCAAoC;IACpC,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,CAAC;AAEF,0GAA0G;AAC1G,MAAM,MAAM,OAAO,GAAG,KAAK,MAAM,IAAI,MAAM,EAAE,CAAC;AAE9C,wBAAgB,SAAS,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAE1E"}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
2
2
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
3
|
/** Confidence a call must reach to be predicted. */ export const PREDICTION_THRESHOLD = 2;
|
|
4
|
-
/** Cap on a call's confidence, so a function called by many
|
|
4
|
+
/** Cap on a call's confidence, so a function called by many operations is still dropped within a few missed ones. */ export const MAX_CONFIDENCE = 5;
|
|
5
5
|
/**
|
|
6
|
-
* A call graph over contract functions - who calls whom - learned from the direct calls observed in past
|
|
6
|
+
* A call graph over contract functions - who calls whom - learned from the direct calls observed in past operations, so
|
|
7
7
|
* a function's predicted callees can sync their contracts before execution reaches them.
|
|
8
8
|
*
|
|
9
|
-
* A function's direct calls tend to repeat across
|
|
10
|
-
* may call an authwit, an AMM calls its tokens. The same function does not always make the same calls, though:
|
|
11
|
-
* can depend on context or storage state. A call must therefore repeat often enough to earn confidence before it
|
|
12
|
-
* predicted. Calls are keyed per function, not per contract, since different functions of a contract call different
|
|
13
|
-
* contracts. See {@link
|
|
9
|
+
* A function's direct calls tend to repeat across operations: constrained delivery calls the handshake registry, a
|
|
10
|
+
* transfer may call an authwit, an AMM calls its tokens. The same function does not always make the same calls, though:
|
|
11
|
+
* they can depend on context or storage state. A call must therefore repeat often enough to earn confidence before it
|
|
12
|
+
* is predicted. Calls are keyed per function, not per contract, since different functions of a contract call different
|
|
13
|
+
* contracts. See {@link learn} for how each call's confidence is learned from committed operations.
|
|
14
14
|
*
|
|
15
15
|
* Purely in-memory bookkeeping: the graph is lost when PXE is rebuilt (e.g. on restart).
|
|
16
16
|
*/ export class ContractCallGraph {
|
|
17
17
|
enabled;
|
|
18
|
-
//
|
|
19
|
-
|
|
18
|
+
// change set -> caller function -> functions it called directly
|
|
19
|
+
activeChangeSets;
|
|
20
20
|
// caller function -> function it calls directly -> confidence score
|
|
21
21
|
callConfidence;
|
|
22
22
|
constructor(enabled){
|
|
23
23
|
this.enabled = enabled;
|
|
24
|
-
this.
|
|
24
|
+
this.activeChangeSets = new Map();
|
|
25
25
|
this.callConfidence = new Map();
|
|
26
26
|
}
|
|
27
|
-
/** Records that `caller` directly called `callee` in the given
|
|
27
|
+
/** Records that `caller` directly called `callee` in the given change set. */ recordCall({ changeSetId, caller, callee }) {
|
|
28
28
|
// Same-contract calls are ignored: our goal is to warm a callee's contract ahead of use, and the target of such
|
|
29
29
|
// a call is already warm.
|
|
30
30
|
if (!this.enabled || caller.address.equals(callee.address)) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
let
|
|
34
|
-
if (!
|
|
35
|
-
|
|
36
|
-
this.
|
|
33
|
+
let callsInChangeSet = this.activeChangeSets.get(changeSetId);
|
|
34
|
+
if (!callsInChangeSet) {
|
|
35
|
+
callsInChangeSet = new Map();
|
|
36
|
+
this.activeChangeSets.set(changeSetId, callsInChangeSet);
|
|
37
37
|
}
|
|
38
|
-
let callees =
|
|
38
|
+
let callees = callsInChangeSet.get(toCallKey(caller));
|
|
39
39
|
if (!callees) {
|
|
40
40
|
callees = new Set();
|
|
41
|
-
|
|
41
|
+
callsInChangeSet.set(toCallKey(caller), callees);
|
|
42
42
|
}
|
|
43
43
|
callees.add(toCallKey(callee));
|
|
44
44
|
}
|
|
@@ -49,15 +49,15 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
49
49
|
].filter(([, confidence])=>confidence >= PREDICTION_THRESHOLD).map(([callee])=>fromCallKey(callee));
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
*
|
|
53
|
-
* callees untouched, so read-only uses (e.g. reading notes or events) erode nothing.
|
|
54
|
-
*/
|
|
55
|
-
const
|
|
56
|
-
this.
|
|
57
|
-
if (!
|
|
52
|
+
* Learns from a committed change set: the calls it observed update each caller's confidence. A function that called
|
|
53
|
+
* nothing keeps its callees untouched, so read-only uses (e.g. reading notes or events) erode nothing.
|
|
54
|
+
*/ learn(changeSetId) {
|
|
55
|
+
const callsInChangeSet = this.activeChangeSets.get(changeSetId);
|
|
56
|
+
this.activeChangeSets.delete(changeSetId);
|
|
57
|
+
if (!callsInChangeSet) {
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
|
-
for (const [caller, observed] of
|
|
60
|
+
for (const [caller, observed] of callsInChangeSet){
|
|
61
61
|
const callees = this.callConfidence.get(caller) ?? new Map();
|
|
62
62
|
for (const [callee, confidence] of callees){
|
|
63
63
|
const delta = observed.has(callee) ? 1 : -1;
|
|
@@ -75,8 +75,8 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
75
75
|
this.callConfidence.set(caller, callees);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
/** Drops a discarded
|
|
79
|
-
this.
|
|
78
|
+
/** Drops a discarded change set without learning. */ discard(changeSetId) {
|
|
79
|
+
this.activeChangeSets.delete(changeSetId);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
export function toCallKey({ address, selector }) {
|
|
@@ -4,9 +4,10 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
4
4
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
5
5
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
6
6
|
import type { ContractSyncConfig } from '../config/index.js';
|
|
7
|
-
import type {
|
|
7
|
+
import type { OperationContributor } from '../operation_lifecycle.js';
|
|
8
8
|
import type { ContractStore } from '../storage/contract_store/contract_store.js';
|
|
9
9
|
import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
10
|
+
import type { ChangeSetId } from '../storage/staged_write_coordinator.js';
|
|
10
11
|
import { type ContractFunction } from './contract_call_graph.js';
|
|
11
12
|
import type { ContractClassService } from './contract_class_service.js';
|
|
12
13
|
/**
|
|
@@ -23,37 +24,36 @@ export declare const SYNC_STATE_SELECTOR: FunctionSelector;
|
|
|
23
24
|
* Service for syncing the private state of contracts. It uses a cache to avoid redundant sync operations - the cache
|
|
24
25
|
* is wiped when the anchor block changes.
|
|
25
26
|
*
|
|
26
|
-
*
|
|
27
|
+
* Contributes to every synced operation (see {@link OperationContributor}): its syncs write into the operation's change
|
|
28
|
+
* set, so it settles them before the change set is decided and releases its per-change-set state on the outcome.
|
|
27
29
|
*/
|
|
28
|
-
export declare class ContractSyncService implements
|
|
30
|
+
export declare class ContractSyncService implements OperationContributor {
|
|
29
31
|
#private;
|
|
30
32
|
private aztecNode;
|
|
31
33
|
private contractStore;
|
|
32
34
|
private contractClassService;
|
|
33
35
|
private noteStore;
|
|
34
36
|
private log;
|
|
35
|
-
readonly storeName = "contract_sync";
|
|
36
37
|
private readonly syncedContracts;
|
|
37
|
-
private readonly
|
|
38
|
+
private readonly speculationByChangeSet;
|
|
38
39
|
private readonly callGraph;
|
|
39
40
|
constructor(aztecNode: AztecNode, contractStore: ContractStore, contractClassService: ContractClassService, noteStore: NoteStore, log: Logger, { concurrentContractSyncEnabled }: ContractSyncConfig);
|
|
40
41
|
/**
|
|
41
42
|
* Ensures a contract's private state is synchronized.
|
|
42
43
|
* Uses a cache to avoid redundant sync operations - the cache is wiped when the anchor block changes.
|
|
43
44
|
*/
|
|
44
|
-
ensureContractSynced({ contract, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader,
|
|
45
|
+
ensureContractSynced({ contract, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader, changeSetId, scopes, triggeredBy }: ContractSyncRequest): Promise<void>;
|
|
45
46
|
/**
|
|
46
|
-
* Waits until every speculative sync the
|
|
47
|
-
* instead of committing. This is needed because a sync that fails midway can leave partial staged writes,
|
|
48
|
-
* speculative failure might not be surfaced by any request.
|
|
47
|
+
* Waits until every speculative sync the change set fired has finished, then rejects if any failed, so the change set
|
|
48
|
+
* discards instead of committing. This is needed because a sync that fails midway can leave partial staged writes,
|
|
49
|
+
* and a speculative failure might not be surfaced by any request.
|
|
49
50
|
*/
|
|
50
|
-
settle(
|
|
51
|
+
settle(changeSetId: ChangeSetId): Promise<void>;
|
|
51
52
|
/** Clears sync cache entries for the given scopes of a contract. */
|
|
52
53
|
invalidateContractForScopes(contractAddress: AztecAddress, scopes: AztecAddress[]): void;
|
|
53
54
|
/** Clears sync cache. Called by BlockSynchronizer when anchor block changes. */
|
|
54
55
|
wipe(): void;
|
|
55
|
-
|
|
56
|
-
discardStaged(jobId: JobId): Promise<void>;
|
|
56
|
+
onOperationEnd(changeSetId: ChangeSetId, outcome: 'committed' | 'discarded'): void;
|
|
57
57
|
}
|
|
58
58
|
/** A request to synchronize a contract's private state. */
|
|
59
59
|
type ContractSyncRequest = {
|
|
@@ -68,16 +68,15 @@ type ContractSyncRequest = {
|
|
|
68
68
|
utilityExecutor: (call: FunctionCall, scopes: AztecAddress[]) => Promise<any>;
|
|
69
69
|
/** The anchor block to sync at. */
|
|
70
70
|
anchorBlockHeader: BlockHeader;
|
|
71
|
-
/** The
|
|
72
|
-
|
|
71
|
+
/** The change set requesting the sync. */
|
|
72
|
+
changeSetId: ChangeSetId;
|
|
73
73
|
/** Access scopes to pass through to the utility executor (affects whose account's private state is discovered). */
|
|
74
74
|
scopes: AztecAddress[];
|
|
75
75
|
/**
|
|
76
|
-
* The function whose execution triggered this sync request, or undefined when the request is a
|
|
77
|
-
* (an entry call or a direct read) rather than a nested call.
|
|
76
|
+
* The function whose execution triggered this sync request, or undefined when the request is a change set's top-level
|
|
77
|
+
* use (an entry call or a direct read) rather than a nested call.
|
|
78
78
|
*/
|
|
79
79
|
triggeredBy: ContractFunction | undefined;
|
|
80
80
|
};
|
|
81
|
-
type JobId = string;
|
|
82
81
|
export {};
|
|
83
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3Rfc3luY19zZXJ2aWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29udHJhY3QvY29udHJhY3Rfc3luY19zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBSXBELE9BQU8sRUFBRSxLQUFLLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3hFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXBELE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFN0QsT0FBTyxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN0RSxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUNqRixPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUMxRSxPQUFPLEVBQW1DLEtBQUssZ0JBQWdCLEVBQWEsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RyxPQUFPLEtBQUssRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3hFOzs7R0FHRztBQUNILGVBQU8sTUFBTSwwQkFBMEIsSUFBSSxDQUFDO0FBRTVDOzs7R0FHRztBQUNILGVBQU8sTUFBTSxtQkFBbUIsa0JBQTRDLENBQUM7QUFFN0U7Ozs7OztHQU1HO0FBQ0gscUJBQWEsbUJBQW9CLFlBQVcsb0JBQW9COztJQVk1RCxPQUFPLENBQUMsU0FBUztJQUNqQixPQUFPLENBQUMsYUFBYTtJQUNyQixPQUFPLENBQUMsb0JBQW9CO0lBQzVCLE9BQU8sQ0FBQyxTQUFTO0lBQ2pCLE9BQU8sQ0FBQyxHQUFHO0lBYmIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQTBDO0lBRzFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQXFEO0lBRzVGLE9BQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFvQjtJQUU5QyxZQUNVLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLGFBQWEsRUFBRSxhQUFhLEVBQzVCLG9CQUFvQixFQUFFLG9CQUFvQixFQUMxQyxTQUFTLEVBQUUsU0FBUyxFQUNwQixHQUFHLEVBQUUsTUFBTSxFQUNuQixFQUFFLDZCQUE2QixFQUFFLEVBQUUsa0JBQWtCLEVBR3REO0lBRUQ7OztPQUdHO0lBQ0csb0JBQW9CLENBQUMsRUFDekIsUUFBUSxFQUNSLHlCQUF5QixFQUN6QixlQUFlLEVBQ2YsaUJBQWlCLEVBQ2pCLFdBQVcsRUFDWCxNQUFNLEVBQ04sV0FBVyxFQUNaLEVBQUUsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWtCckM7SUFFRDs7OztPQUlHO0lBQ0csTUFBTSxDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWVwRDtJQUVELG9FQUFvRTtJQUNwRSwyQkFBMkIsQ0FBQyxlQUFlLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsR0FBRyxJQUFJLENBS3ZGO0lBRUQsZ0ZBQWdGO0lBQ2hGLElBQUksSUFBSSxJQUFJLENBR1g7SUFFRCxjQUFjLENBQUMsV0FBVyxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsV0FBVyxHQUFHLFdBQVcsR0FBRyxJQUFJLENBVWpGO0NBaUtGO0FBRUQsMkRBQTJEO0FBQzNELEtBQUssbUJBQW1CLEdBQUc7SUFDekIsNEJBQTRCO0lBQzVCLFFBQVEsRUFBRSxZQUFZLENBQUM7SUFDdkI7OztPQUdHO0lBQ0gseUJBQXlCLEVBQUUsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0lBQ25ELGdIQUFnSDtJQUNoSCxlQUFlLEVBQUUsQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsS0FBSyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUUsbUNBQW1DO0lBQ25DLGlCQUFpQixFQUFFLFdBQVcsQ0FBQztJQUMvQiwwQ0FBMEM7SUFDMUMsV0FBVyxFQUFFLFdBQVcsQ0FBQztJQUN6QixtSEFBbUg7SUFDbkgsTUFBTSxFQUFFLFlBQVksRUFBRSxDQUFDO0lBQ3ZCOzs7T0FHRztJQUNILFdBQVcsRUFBRSxnQkFBZ0IsR0FBRyxTQUFTLENBQUM7Q0FDM0MsQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract_sync_service.d.ts","sourceRoot":"","sources":["../../src/contract/contract_sync_service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAIpD,OAAO,EAAE,KAAK,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"contract_sync_service.d.ts","sourceRoot":"","sources":["../../src/contract/contract_sync_service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAIpD,OAAO,EAAE,KAAK,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAmC,KAAK,gBAAgB,EAAa,MAAM,0BAA0B,CAAC;AAC7G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGxE;;;GAGG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,mBAAmB,kBAA4C,CAAC;AAE7E;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,oBAAoB;;IAY5D,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,oBAAoB;IAC5B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IAbb,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0C;IAG1E,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAqD;IAG5F,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAE9C,YACU,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa,EAC5B,oBAAoB,EAAE,oBAAoB,EAC1C,SAAS,EAAE,SAAS,EACpB,GAAG,EAAE,MAAM,EACnB,EAAE,6BAA6B,EAAE,EAAE,kBAAkB,EAGtD;IAED;;;OAGG;IACG,oBAAoB,CAAC,EACzB,QAAQ,EACR,yBAAyB,EACzB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,MAAM,EACN,WAAW,EACZ,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBrC;IAED;;;;OAIG;IACG,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAepD;IAED,oEAAoE;IACpE,2BAA2B,CAAC,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAKvF;IAED,gFAAgF;IAChF,IAAI,IAAI,IAAI,CAGX;IAED,cAAc,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAUjF;CAiKF;AAED,2DAA2D;AAC3D,KAAK,mBAAmB,GAAG;IACzB,4BAA4B;IAC5B,QAAQ,EAAE,YAAY,CAAC;IACvB;;;OAGG;IACH,yBAAyB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnD,gHAAgH;IAChH,eAAe,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9E,mCAAmC;IACnC,iBAAiB,EAAE,WAAW,CAAC;IAC/B,0CAA0C;IAC1C,WAAW,EAAE,WAAW,CAAC;IACzB,mHAAmH;IACnH,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB;;;OAGG;IACH,WAAW,EAAE,gBAAgB,GAAG,SAAS,CAAC;CAC3C,CAAC"}
|
|
@@ -17,20 +17,20 @@ import { syncScope } from './helpers.js';
|
|
|
17
17
|
* Service for syncing the private state of contracts. It uses a cache to avoid redundant sync operations - the cache
|
|
18
18
|
* is wiped when the anchor block changes.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* Contributes to every synced operation (see {@link OperationContributor}): its syncs write into the operation's change
|
|
21
|
+
* set, so it settles them before the change set is decided and releases its per-change-set state on the outcome.
|
|
21
22
|
*/ export class ContractSyncService {
|
|
22
23
|
aztecNode;
|
|
23
24
|
contractStore;
|
|
24
25
|
contractClassService;
|
|
25
26
|
noteStore;
|
|
26
27
|
log;
|
|
27
|
-
storeName;
|
|
28
28
|
// Tracks contracts synced since last wipe. The cache is keyed per individual scope address
|
|
29
29
|
// (`contractAddress:scopeAddress`). The value is a promise that resolves when the contract is synced.
|
|
30
30
|
syncedContracts;
|
|
31
|
-
// Per-
|
|
32
|
-
|
|
33
|
-
// Predicts a function's callees from the calls observed in past
|
|
31
|
+
// Per-change-set speculation state, dropped when the change set commits or discards.
|
|
32
|
+
speculationByChangeSet;
|
|
33
|
+
// Predicts a function's callees from the calls observed in past operations, driving speculative sync.
|
|
34
34
|
callGraph;
|
|
35
35
|
constructor(aztecNode, contractStore, contractClassService, noteStore, log, { concurrentContractSyncEnabled }){
|
|
36
36
|
this.aztecNode = aztecNode;
|
|
@@ -38,19 +38,18 @@ import { syncScope } from './helpers.js';
|
|
|
38
38
|
this.contractClassService = contractClassService;
|
|
39
39
|
this.noteStore = noteStore;
|
|
40
40
|
this.log = log;
|
|
41
|
-
this.storeName = 'contract_sync';
|
|
42
41
|
this.syncedContracts = new Map();
|
|
43
|
-
this.
|
|
42
|
+
this.speculationByChangeSet = new Map();
|
|
44
43
|
this.callGraph = new ContractCallGraph(concurrentContractSyncEnabled);
|
|
45
44
|
}
|
|
46
45
|
/**
|
|
47
46
|
* Ensures a contract's private state is synchronized.
|
|
48
47
|
* Uses a cache to avoid redundant sync operations - the cache is wiped when the anchor block changes.
|
|
49
|
-
*/ async ensureContractSynced({ contract, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader,
|
|
48
|
+
*/ async ensureContractSynced({ contract, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader, changeSetId, scopes, triggeredBy }) {
|
|
50
49
|
// A call is recorded only when both functions are known: the invoked callee and the caller that triggered it.
|
|
51
50
|
if (functionToInvokeAfterSync && triggeredBy) {
|
|
52
51
|
this.callGraph.recordCall({
|
|
53
|
-
|
|
52
|
+
changeSetId,
|
|
54
53
|
caller: triggeredBy,
|
|
55
54
|
callee: {
|
|
56
55
|
address: contract,
|
|
@@ -58,23 +57,23 @@ import { syncScope } from './helpers.js';
|
|
|
58
57
|
}
|
|
59
58
|
});
|
|
60
59
|
}
|
|
61
|
-
await this.#startSyncIfNeeded(contract, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader,
|
|
60
|
+
await this.#startSyncIfNeeded(contract, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader, changeSetId, scopes);
|
|
62
61
|
}
|
|
63
62
|
/**
|
|
64
|
-
* Waits until every speculative sync the
|
|
65
|
-
* instead of committing. This is needed because a sync that fails midway can leave partial staged writes,
|
|
66
|
-
* speculative failure might not be surfaced by any request.
|
|
67
|
-
*/ async settle(
|
|
63
|
+
* Waits until every speculative sync the change set fired has finished, then rejects if any failed, so the change set
|
|
64
|
+
* discards instead of committing. This is needed because a sync that fails midway can leave partial staged writes,
|
|
65
|
+
* and a speculative failure might not be surfaced by any request.
|
|
66
|
+
*/ async settle(changeSetId) {
|
|
68
67
|
// A speculative sync's execution can fire more speculative syncs mid-drain, so loop until no new promises
|
|
69
68
|
// appear, and only escalate once nothing is still writing.
|
|
70
|
-
const { syncs } = this.#
|
|
69
|
+
const { syncs } = this.#speculationForChangeSet(changeSetId);
|
|
71
70
|
const failures = [];
|
|
72
71
|
while(syncs.length > 0){
|
|
73
72
|
const results = await Promise.allSettled(syncs.splice(0));
|
|
74
73
|
failures.push(...results.filter((result)=>result.status === 'rejected').map((result)=>result.reason));
|
|
75
74
|
}
|
|
76
75
|
if (failures.length > 0) {
|
|
77
|
-
throw new AggregateError(failures, 'Speculative syncs failed, so the
|
|
76
|
+
throw new AggregateError(failures, 'Speculative syncs failed, so the operation must discard its staged writes instead of committing');
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
79
|
/** Clears sync cache entries for the given scopes of a contract. */ invalidateContractForScopes(contractAddress, scopes) {
|
|
@@ -87,18 +86,16 @@ import { syncScope } from './helpers.js';
|
|
|
87
86
|
this.log.debug(`Wiping contract sync cache (${this.syncedContracts.size} entries)`);
|
|
88
87
|
this.syncedContracts.clear();
|
|
89
88
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.
|
|
100
|
-
this.speculationByJob.delete(jobId);
|
|
101
|
-
return Promise.resolve();
|
|
89
|
+
onOperationEnd(changeSetId, outcome) {
|
|
90
|
+
if (outcome === 'committed') {
|
|
91
|
+
this.callGraph.learn(changeSetId);
|
|
92
|
+
} else {
|
|
93
|
+
// We clear the synced contracts cache here because, when the change set is discarded, any associated database
|
|
94
|
+
// writes from the sync are also undone.
|
|
95
|
+
this.syncedContracts.clear();
|
|
96
|
+
this.callGraph.discard(changeSetId);
|
|
97
|
+
}
|
|
98
|
+
this.speculationByChangeSet.delete(changeSetId);
|
|
102
99
|
}
|
|
103
100
|
/**
|
|
104
101
|
* For each unsynced scope, creates a promise that waits on:
|
|
@@ -109,12 +106,12 @@ import { syncScope } from './helpers.js';
|
|
|
109
106
|
* {@link #speculativelySync}).
|
|
110
107
|
* @returns A promise that resolves once every requested scope is synced, including syncs already in flight from
|
|
111
108
|
* concurrent calls. Speculative syncs are not included: those are only awaited by a later request that needs
|
|
112
|
-
* their contract, or by the
|
|
113
|
-
*/ async #startSyncIfNeeded(contractAddress, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader,
|
|
109
|
+
* their contract, or by the change set's {@link settle}.
|
|
110
|
+
*/ async #startSyncIfNeeded(contractAddress, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader, changeSetId, scopes) {
|
|
114
111
|
const scopesToSync = scopes.filter((scope)=>!this.syncedContracts.has(toKey(contractAddress, scope)));
|
|
115
112
|
if (scopesToSync.length > 0) {
|
|
116
113
|
this.log.debug(`Syncing contract ${contractAddress} for ${scopesToSync.length} scope(s)`);
|
|
117
|
-
const syncNullifiersPromise = this.#syncNoteNullifiers(contractAddress, anchorBlockHeader,
|
|
114
|
+
const syncNullifiersPromise = this.#syncNoteNullifiers(contractAddress, anchorBlockHeader, changeSetId, scopesToSync);
|
|
118
115
|
// We build a new semaphore for each sync call, so it rate-limits the scopes within that single call. We do
|
|
119
116
|
// this so that if these scope syncs trigger nested syncs, the nested ones can execute without causing a deadlock.
|
|
120
117
|
const syncSlot = new Semaphore(MAX_CONCURRENT_SCOPE_SYNCS);
|
|
@@ -135,8 +132,8 @@ import { syncScope } from './helpers.js';
|
|
|
135
132
|
}
|
|
136
133
|
// `sync_state` itself calls other contracts (e.g. most contract syncs query the handshake registry), so its
|
|
137
134
|
// predicted callees start syncing alongside the contract's own syncs.
|
|
138
|
-
this.#speculativelySync(contractAddress, SYNC_STATE_SELECTOR, utilityExecutor, anchorBlockHeader,
|
|
139
|
-
this.#speculativelySync(contractAddress, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader,
|
|
135
|
+
this.#speculativelySync(contractAddress, SYNC_STATE_SELECTOR, utilityExecutor, anchorBlockHeader, changeSetId, scopes);
|
|
136
|
+
this.#speculativelySync(contractAddress, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader, changeSetId, scopes);
|
|
140
137
|
await this.#awaitSync(contractAddress, scopes);
|
|
141
138
|
}
|
|
142
139
|
/**
|
|
@@ -144,54 +141,54 @@ import { syncScope } from './helpers.js';
|
|
|
144
141
|
* predictions are learned). Each started sync speculates from its own function in turn, so the whole predicted call
|
|
145
142
|
* tree syncs in parallel with the contract instead of one contract at a time as execution reaches it.
|
|
146
143
|
*
|
|
147
|
-
* A wrong prediction is cheap: the extra node requests are batched into round trips the
|
|
148
|
-
* synced data simply goes unused.
|
|
149
|
-
*/ #speculativelySync(contractAddress, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader,
|
|
144
|
+
* A wrong prediction is cheap: the extra node requests are batched into round trips the operation already makes, and
|
|
145
|
+
* the synced data simply goes unused.
|
|
146
|
+
*/ #speculativelySync(contractAddress, functionToInvokeAfterSync, utilityExecutor, anchorBlockHeader, changeSetId, scopes) {
|
|
150
147
|
// Without a function there is no key to predict from (the request is a direct read).
|
|
151
148
|
if (!functionToInvokeAfterSync) {
|
|
152
149
|
return;
|
|
153
150
|
}
|
|
154
|
-
const speculation = this.#
|
|
151
|
+
const speculation = this.#speculationForChangeSet(changeSetId);
|
|
155
152
|
const caller = {
|
|
156
153
|
address: contractAddress,
|
|
157
154
|
selector: functionToInvokeAfterSync
|
|
158
155
|
};
|
|
159
156
|
for (const callee of this.callGraph.predictDirectCallees(caller)){
|
|
160
|
-
// The
|
|
157
|
+
// The change set's set of already-speculated functions stops the recursion when the predicted graph has a cycle.
|
|
161
158
|
if (speculation.speculated.has(toCallKey(callee))) {
|
|
162
159
|
continue;
|
|
163
160
|
}
|
|
164
161
|
speculation.speculated.add(toCallKey(callee));
|
|
165
|
-
const syncPromise = this.#startSyncIfNeeded(callee.address, callee.selector, utilityExecutor, anchorBlockHeader,
|
|
162
|
+
const syncPromise = this.#startSyncIfNeeded(callee.address, callee.selector, utilityExecutor, anchorBlockHeader, changeSetId, scopes);
|
|
166
163
|
speculation.syncs.push(syncPromise);
|
|
167
|
-
// `settle` only escalates these failures at the end of the
|
|
168
|
-
// rejection before then, and log it.
|
|
164
|
+
// `settle` only escalates these failures at the end of the change set: catch here so one does not become an
|
|
165
|
+
// unhandled rejection before then, and log it.
|
|
169
166
|
syncPromise.catch((err)=>{
|
|
170
167
|
this.log.warn(`Speculative sync of ${callee.address} failed`, {
|
|
171
|
-
|
|
168
|
+
changeSetId,
|
|
172
169
|
error: err?.message
|
|
173
170
|
});
|
|
174
171
|
});
|
|
175
172
|
}
|
|
176
173
|
}
|
|
177
|
-
/** Syncs note nullifiers across all unsynced scopes in a single batched call. */ async #syncNoteNullifiers(contractAddress, anchorBlockHeader,
|
|
174
|
+
/** Syncs note nullifiers across all unsynced scopes in a single batched call. */ async #syncNoteNullifiers(contractAddress, anchorBlockHeader, changeSetId, scopes) {
|
|
178
175
|
// Protocol contracts don't have private state to sync
|
|
179
176
|
if (isProtocolContract(contractAddress)) {
|
|
180
177
|
return;
|
|
181
178
|
}
|
|
182
179
|
// This runs in parallel with per-scope sync (which also writes to the note store). That's safe because
|
|
183
180
|
// the note store handles concurrent operations.
|
|
184
|
-
const noteService = new NoteService(this.noteStore, this.aztecNode, anchorBlockHeader,
|
|
181
|
+
const noteService = new NoteService(this.noteStore, this.aztecNode, anchorBlockHeader, changeSetId);
|
|
185
182
|
await noteService.syncNoteNullifiers(contractAddress, scopes);
|
|
186
183
|
}
|
|
187
|
-
#
|
|
188
|
-
let speculation = this.
|
|
184
|
+
#speculationForChangeSet(changeSetId) {
|
|
185
|
+
let speculation = this.speculationByChangeSet.get(changeSetId);
|
|
189
186
|
if (!speculation) {
|
|
190
187
|
speculation = {
|
|
191
188
|
speculated: new Set(),
|
|
192
189
|
syncs: []
|
|
193
190
|
};
|
|
194
|
-
this.
|
|
191
|
+
this.speculationByChangeSet.set(changeSetId, speculation);
|
|
195
192
|
}
|
|
196
193
|
return speculation;
|
|
197
194
|
}
|