@aztec/pxe 0.63.0 → 0.64.0
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/database/contracts/contract_artifact_db.d.ts +1 -0
- package/dest/database/contracts/contract_artifact_db.d.ts.map +1 -1
- package/dest/database/incoming_note_dao.d.ts +10 -1
- package/dest/database/incoming_note_dao.d.ts.map +1 -1
- package/dest/database/incoming_note_dao.js +18 -5
- package/dest/database/kv_pxe_database.d.ts +6 -3
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +123 -22
- package/dest/database/outgoing_note_dao.d.ts +10 -1
- package/dest/database/outgoing_note_dao.d.ts.map +1 -1
- package/dest/database/outgoing_note_dao.js +18 -5
- package/dest/database/pxe_database.d.ts +22 -5
- package/dest/database/pxe_database.d.ts.map +1 -1
- package/dest/database/pxe_database_test_suite.d.ts.map +1 -1
- package/dest/database/pxe_database_test_suite.js +65 -16
- package/dest/kernel_oracle/index.js +2 -2
- package/dest/note_decryption_utils/produce_note_daos.d.ts +1 -1
- package/dest/note_decryption_utils/produce_note_daos.d.ts.map +1 -1
- package/dest/note_decryption_utils/produce_note_daos.js +5 -5
- package/dest/note_decryption_utils/produce_note_daos_for_key.d.ts +1 -1
- package/dest/note_decryption_utils/produce_note_daos_for_key.d.ts.map +1 -1
- package/dest/note_decryption_utils/produce_note_daos_for_key.js +3 -3
- package/dest/pxe_service/create_pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/create_pxe_service.js +6 -3
- package/dest/pxe_service/pxe_service.d.ts +5 -4
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +51 -25
- package/dest/simulator_oracle/index.d.ts +8 -0
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +67 -10
- package/dest/synchronizer/synchronizer.d.ts +13 -28
- package/dest/synchronizer/synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.js +42 -64
- package/package.json +14 -14
- package/src/database/contracts/contract_artifact_db.ts +1 -0
- package/src/database/incoming_note_dao.ts +46 -1
- package/src/database/kv_pxe_database.ts +148 -23
- package/src/database/outgoing_note_dao.ts +43 -1
- package/src/database/pxe_database.ts +25 -5
- package/src/database/pxe_database_test_suite.ts +79 -17
- package/src/kernel_oracle/index.ts +1 -1
- package/src/note_decryption_utils/produce_note_daos.ts +8 -0
- package/src/note_decryption_utils/produce_note_daos_for_key.ts +5 -1
- package/src/pxe_service/create_pxe_service.ts +7 -4
- package/src/pxe_service/pxe_service.ts +109 -72
- package/src/simulator_oracle/index.ts +95 -17
- package/src/synchronizer/synchronizer.ts +60 -71
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AztecNode,
|
|
3
|
+
L2BlockStream,
|
|
4
|
+
type L2BlockStreamEvent,
|
|
5
|
+
type L2BlockStreamEventHandler,
|
|
6
|
+
} from '@aztec/circuit-types';
|
|
2
7
|
import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js';
|
|
3
8
|
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
4
|
-
import { type
|
|
5
|
-
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
9
|
+
import { type L2TipsStore } from '@aztec/kv-store/stores';
|
|
6
10
|
|
|
11
|
+
import { type PXEConfig } from '../config/index.js';
|
|
7
12
|
import { type PxeDatabase } from '../database/index.js';
|
|
8
13
|
|
|
9
14
|
/**
|
|
@@ -13,14 +18,51 @@ import { type PxeDatabase } from '../database/index.js';
|
|
|
13
18
|
* details, and fetch transactions by hash. The Synchronizer ensures that it maintains the note processors
|
|
14
19
|
* in sync with the blockchain while handling retries and errors gracefully.
|
|
15
20
|
*/
|
|
16
|
-
export class Synchronizer {
|
|
17
|
-
private runningPromise?: RunningPromise;
|
|
21
|
+
export class Synchronizer implements L2BlockStreamEventHandler {
|
|
18
22
|
private running = false;
|
|
19
23
|
private initialSyncBlockNumber = INITIAL_L2_BLOCK_NUM - 1;
|
|
20
24
|
private log: DebugLogger;
|
|
25
|
+
protected readonly blockStream: L2BlockStream;
|
|
21
26
|
|
|
22
|
-
constructor(
|
|
27
|
+
constructor(
|
|
28
|
+
private node: AztecNode,
|
|
29
|
+
private db: PxeDatabase,
|
|
30
|
+
private l2TipsStore: L2TipsStore,
|
|
31
|
+
config: Partial<Pick<PXEConfig, 'l2BlockPollingIntervalMS' | 'l2StartingBlock'>> = {},
|
|
32
|
+
logSuffix?: string,
|
|
33
|
+
) {
|
|
23
34
|
this.log = createDebugLogger(logSuffix ? `aztec:pxe_synchronizer_${logSuffix}` : 'aztec:pxe_synchronizer');
|
|
35
|
+
this.blockStream = this.createBlockStream(config);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected createBlockStream(config: Partial<Pick<PXEConfig, 'l2BlockPollingIntervalMS' | 'l2StartingBlock'>>) {
|
|
39
|
+
return new L2BlockStream(this.node, this.l2TipsStore, this, {
|
|
40
|
+
pollIntervalMS: config.l2BlockPollingIntervalMS,
|
|
41
|
+
startingBlock: config.l2StartingBlock,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Handle events emitted by the block stream. */
|
|
46
|
+
public async handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void> {
|
|
47
|
+
await this.l2TipsStore.handleBlockStreamEvent(event);
|
|
48
|
+
|
|
49
|
+
switch (event.type) {
|
|
50
|
+
case 'blocks-added':
|
|
51
|
+
this.log.verbose(`Processing blocks ${event.blocks[0].number} to ${event.blocks.at(-1)!.number}`);
|
|
52
|
+
await this.db.setHeader(event.blocks.at(-1)!.header);
|
|
53
|
+
break;
|
|
54
|
+
case 'chain-pruned':
|
|
55
|
+
this.log.info(`Pruning data after block ${event.blockNumber} due to reorg`);
|
|
56
|
+
// We first unnullify and then remove so that unnullified notes that were created after the block number end up deleted.
|
|
57
|
+
await this.db.unnullifyNotesAfter(event.blockNumber);
|
|
58
|
+
await this.db.removeNotesAfter(event.blockNumber);
|
|
59
|
+
// Remove all note tagging indexes to force a full resync. This is suboptimal, but unless we track the
|
|
60
|
+
// block number in which each index is used it's all we can do.
|
|
61
|
+
await this.db.resetNoteSyncData();
|
|
62
|
+
// Update the header to the last block.
|
|
63
|
+
await this.db.setHeader(await this.node.getBlockHeader(event.blockNumber));
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
24
66
|
}
|
|
25
67
|
|
|
26
68
|
/**
|
|
@@ -31,79 +73,21 @@ export class Synchronizer {
|
|
|
31
73
|
* @param limit - The maximum number of encrypted, unencrypted logs and blocks to fetch in each iteration.
|
|
32
74
|
* @param retryInterval - The time interval (in ms) to wait before retrying if no data is available.
|
|
33
75
|
*/
|
|
34
|
-
public async start(
|
|
76
|
+
public async start() {
|
|
35
77
|
if (this.running) {
|
|
36
78
|
return;
|
|
37
79
|
}
|
|
38
80
|
this.running = true;
|
|
39
81
|
|
|
40
|
-
|
|
82
|
+
// REFACTOR: We should know the header of the genesis block without having to request it from the node.
|
|
83
|
+
await this.db.setHeader(await this.node.getBlockHeader(0));
|
|
84
|
+
|
|
85
|
+
await this.trigger();
|
|
41
86
|
this.log.info('Initial sync complete');
|
|
42
|
-
this.
|
|
43
|
-
this.runningPromise.start();
|
|
87
|
+
this.blockStream.start();
|
|
44
88
|
this.log.debug('Started loop');
|
|
45
89
|
}
|
|
46
90
|
|
|
47
|
-
protected async initialSync() {
|
|
48
|
-
// fast forward to the latest block
|
|
49
|
-
const latestHeader = await this.node.getHeader();
|
|
50
|
-
this.initialSyncBlockNumber = Number(latestHeader.globalVariables.blockNumber.toBigInt());
|
|
51
|
-
await this.db.setHeader(latestHeader);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Fetches encrypted logs and blocks from the Aztec node and processes them for all note processors.
|
|
56
|
-
* If needed, catches up note processors that are lagging behind the main sync, e.g. because we just added a new account.
|
|
57
|
-
*
|
|
58
|
-
* Uses the job queue to ensure that
|
|
59
|
-
* - sync does not overlap with pxe simulations.
|
|
60
|
-
* - one sync is running at a time.
|
|
61
|
-
*
|
|
62
|
-
* @param limit - The maximum number of encrypted, unencrypted logs and blocks to fetch in each iteration.
|
|
63
|
-
* @returns a promise that resolves when the sync is complete
|
|
64
|
-
*/
|
|
65
|
-
protected sync(limit: number) {
|
|
66
|
-
return this.jobQueue.put(async () => {
|
|
67
|
-
let moreWork = true;
|
|
68
|
-
// keep external this.running flag to interrupt greedy sync
|
|
69
|
-
while (moreWork && this.running) {
|
|
70
|
-
moreWork = await this.work(limit);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Fetches encrypted logs and blocks from the Aztec node and processes them for all note processors.
|
|
77
|
-
*
|
|
78
|
-
* @param limit - The maximum number of encrypted, unencrypted logs and blocks to fetch in each iteration.
|
|
79
|
-
* @returns true if there could be more work, false if we're caught up or there was an error.
|
|
80
|
-
*/
|
|
81
|
-
protected async work(limit = 1): Promise<boolean> {
|
|
82
|
-
const from = this.getSynchedBlockNumber() + 1;
|
|
83
|
-
try {
|
|
84
|
-
const blocks = await this.node.getBlocks(from, limit);
|
|
85
|
-
if (blocks.length === 0) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Update latest tree roots from the most recent block
|
|
90
|
-
const latestBlock = blocks[blocks.length - 1];
|
|
91
|
-
await this.setHeaderFromBlock(latestBlock);
|
|
92
|
-
return true;
|
|
93
|
-
} catch (err) {
|
|
94
|
-
this.log.error(`Error in synchronizer work`, err);
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private async setHeaderFromBlock(latestBlock: L2Block) {
|
|
100
|
-
if (latestBlock.number < this.initialSyncBlockNumber) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
await this.db.setHeader(latestBlock.header);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
91
|
/**
|
|
108
92
|
* Stops the synchronizer gracefully, interrupting any ongoing sleep and waiting for the current
|
|
109
93
|
* iteration to complete before setting the running state to false. Once stopped, the synchronizer
|
|
@@ -113,10 +97,15 @@ export class Synchronizer {
|
|
|
113
97
|
*/
|
|
114
98
|
public async stop() {
|
|
115
99
|
this.running = false;
|
|
116
|
-
await this.
|
|
100
|
+
await this.blockStream.stop();
|
|
117
101
|
this.log.info('Stopped');
|
|
118
102
|
}
|
|
119
103
|
|
|
104
|
+
/** Triggers a single run. */
|
|
105
|
+
public async trigger() {
|
|
106
|
+
await this.blockStream.sync();
|
|
107
|
+
}
|
|
108
|
+
|
|
120
109
|
private getSynchedBlockNumber() {
|
|
121
110
|
return this.db.getBlockNumber() ?? this.initialSyncBlockNumber;
|
|
122
111
|
}
|