@aztec/aztec-node 0.0.1-commit.d3ec352c → 0.0.1-commit.f295ac2
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/aztec-node/config.d.ts +5 -2
- package/dest/aztec-node/config.d.ts.map +1 -1
- package/dest/aztec-node/config.js +7 -1
- package/dest/aztec-node/node_metrics.d.ts +1 -1
- package/dest/aztec-node/node_metrics.d.ts.map +1 -1
- package/dest/aztec-node/node_metrics.js +5 -16
- package/dest/aztec-node/server.d.ts +50 -117
- package/dest/aztec-node/server.d.ts.map +1 -1
- package/dest/aztec-node/server.js +581 -171
- package/dest/sentinel/sentinel.d.ts +5 -4
- package/dest/sentinel/sentinel.d.ts.map +1 -1
- package/dest/sentinel/sentinel.js +31 -26
- package/dest/sentinel/store.d.ts +2 -2
- package/dest/sentinel/store.d.ts.map +1 -1
- package/package.json +26 -26
- package/src/aztec-node/config.ts +12 -8
- package/src/aztec-node/node_metrics.ts +5 -23
- package/src/aztec-node/server.ts +241 -202
- package/src/sentinel/sentinel.ts +41 -32
package/src/sentinel/sentinel.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
2
|
-
import { BlockNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { countWhile, filterAsync, fromEntries, getEntries, mapValues } from '@aztec/foundation/collection';
|
|
4
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
L2BlockStream,
|
|
20
20
|
type L2BlockStreamEvent,
|
|
21
21
|
type L2BlockStreamEventHandler,
|
|
22
|
-
|
|
22
|
+
getAttestationInfoFromPublishedCheckpoint,
|
|
23
23
|
} from '@aztec/stdlib/block';
|
|
24
24
|
import { getEpochAtSlot, getSlotRangeForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
25
25
|
import type {
|
|
@@ -44,8 +44,10 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
|
|
|
44
44
|
protected initialSlot: SlotNumber | undefined;
|
|
45
45
|
protected lastProcessedSlot: SlotNumber | undefined;
|
|
46
46
|
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
47
|
-
protected
|
|
48
|
-
|
|
47
|
+
protected slotNumberToCheckpoint: Map<
|
|
48
|
+
SlotNumber,
|
|
49
|
+
{ checkpointNumber: CheckpointNumber; archive: string; attestors: EthAddress[] }
|
|
50
|
+
> = new Map();
|
|
49
51
|
|
|
50
52
|
constructor(
|
|
51
53
|
protected epochCache: EpochCache,
|
|
@@ -87,39 +89,46 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
|
|
|
87
89
|
|
|
88
90
|
public async handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void> {
|
|
89
91
|
await this.l2TipsStore.handleBlockStreamEvent(event);
|
|
90
|
-
if (event.type === '
|
|
91
|
-
|
|
92
|
-
for (const block of event.blocks) {
|
|
93
|
-
this.slotNumberToBlock.set(block.block.header.getSlot(), {
|
|
94
|
-
blockNumber: BlockNumber(block.block.number),
|
|
95
|
-
archive: block.block.archive.root.toString(),
|
|
96
|
-
attestors: getAttestationInfoFromPublishedL2Block(block)
|
|
97
|
-
.filter(a => a.status === 'recovered-from-signature')
|
|
98
|
-
.map(a => a.address!),
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Prune the archive map to only keep at most N entries
|
|
103
|
-
const historyLength = this.store.getHistoryLength();
|
|
104
|
-
if (this.slotNumberToBlock.size > historyLength) {
|
|
105
|
-
const toDelete = Array.from(this.slotNumberToBlock.keys())
|
|
106
|
-
.sort((a, b) => Number(a - b))
|
|
107
|
-
.slice(0, this.slotNumberToBlock.size - historyLength);
|
|
108
|
-
for (const key of toDelete) {
|
|
109
|
-
this.slotNumberToBlock.delete(key);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
92
|
+
if (event.type === 'chain-checkpointed') {
|
|
93
|
+
this.handleCheckpoint(event);
|
|
112
94
|
} else if (event.type === 'chain-proven') {
|
|
113
95
|
await this.handleChainProven(event);
|
|
114
96
|
}
|
|
115
97
|
}
|
|
116
98
|
|
|
99
|
+
protected handleCheckpoint(event: L2BlockStreamEvent) {
|
|
100
|
+
if (event.type !== 'chain-checkpointed') {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const checkpoint = event.checkpoint;
|
|
104
|
+
|
|
105
|
+
// Store mapping from slot to archive, checkpoint number, and attestors
|
|
106
|
+
this.slotNumberToCheckpoint.set(checkpoint.checkpoint.header.slotNumber, {
|
|
107
|
+
checkpointNumber: checkpoint.checkpoint.number,
|
|
108
|
+
archive: checkpoint.checkpoint.archive.root.toString(),
|
|
109
|
+
attestors: getAttestationInfoFromPublishedCheckpoint(checkpoint)
|
|
110
|
+
.filter(a => a.status === 'recovered-from-signature')
|
|
111
|
+
.map(a => a.address!),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Prune the archive map to only keep at most N entries
|
|
115
|
+
const historyLength = this.store.getHistoryLength();
|
|
116
|
+
if (this.slotNumberToCheckpoint.size > historyLength) {
|
|
117
|
+
const toDelete = Array.from(this.slotNumberToCheckpoint.keys())
|
|
118
|
+
.sort((a, b) => Number(a - b))
|
|
119
|
+
.slice(0, this.slotNumberToCheckpoint.size - historyLength);
|
|
120
|
+
for (const key of toDelete) {
|
|
121
|
+
this.slotNumberToCheckpoint.delete(key);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
117
126
|
protected async handleChainProven(event: L2BlockStreamEvent) {
|
|
118
127
|
if (event.type !== 'chain-proven') {
|
|
119
128
|
return;
|
|
120
129
|
}
|
|
121
|
-
const blockNumber =
|
|
122
|
-
const block = await this.archiver.
|
|
130
|
+
const blockNumber = event.block.number;
|
|
131
|
+
const block = await this.archiver.getL2BlockNew(blockNumber);
|
|
123
132
|
if (!block) {
|
|
124
133
|
this.logger.error(`Failed to get block ${blockNumber}`, { block });
|
|
125
134
|
return;
|
|
@@ -291,8 +300,8 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
|
|
|
291
300
|
return false;
|
|
292
301
|
}
|
|
293
302
|
|
|
294
|
-
const archiverLastBlockHash = await this.l2TipsStore.getL2Tips().then(tip => tip.
|
|
295
|
-
const p2pLastBlockHash = await this.p2p.getL2Tips().then(tips => tips.
|
|
303
|
+
const archiverLastBlockHash = await this.l2TipsStore.getL2Tips().then(tip => tip.proposed.hash);
|
|
304
|
+
const p2pLastBlockHash = await this.p2p.getL2Tips().then(tips => tips.proposed.hash);
|
|
296
305
|
const isP2pSynced = archiverLastBlockHash === p2pLastBlockHash;
|
|
297
306
|
if (!isP2pSynced) {
|
|
298
307
|
this.logger.debug(`Waiting for P2P client to sync with archiver`, { archiverLastBlockHash, p2pLastBlockHash });
|
|
@@ -331,8 +340,8 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
|
|
|
331
340
|
// or all attestations for all proposals in the slot if no block was mined.
|
|
332
341
|
// We gather from both p2p (contains the ones seen on the p2p layer) and archiver
|
|
333
342
|
// (contains the ones synced from mined blocks, which we may have missed from p2p).
|
|
334
|
-
const block = this.
|
|
335
|
-
const p2pAttested = await this.p2p.
|
|
343
|
+
const block = this.slotNumberToCheckpoint.get(slot);
|
|
344
|
+
const p2pAttested = await this.p2p.getCheckpointAttestationsForSlot(slot, block?.archive);
|
|
336
345
|
// Filter out attestations with invalid signatures
|
|
337
346
|
const p2pAttestors = p2pAttested.map(a => a.getSender()).filter((s): s is EthAddress => s !== undefined);
|
|
338
347
|
const attestors = new Set(
|