@aztec/aztec-node 0.86.0 → 0.87.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/aztec-node/config.d.ts +2 -5
- package/dest/aztec-node/config.d.ts.map +1 -1
- package/dest/aztec-node/config.js +2 -10
- package/dest/aztec-node/server.d.ts +9 -6
- package/dest/aztec-node/server.d.ts.map +1 -1
- package/dest/aztec-node/server.js +72 -17
- package/dest/sentinel/sentinel.d.ts +6 -2
- package/dest/sentinel/sentinel.d.ts.map +1 -1
- package/dest/sentinel/sentinel.js +24 -15
- package/dest/sentinel/store.d.ts.map +1 -1
- package/package.json +25 -24
- package/src/aztec-node/config.ts +4 -17
- package/src/aztec-node/server.ts +102 -22
- package/src/sentinel/sentinel.ts +25 -14
- package/src/sentinel/store.ts +4 -1
|
@@ -6,6 +6,7 @@ import { type SharedNodeConfig } from '@aztec/node-lib/config';
|
|
|
6
6
|
import { type P2PConfig } from '@aztec/p2p/config';
|
|
7
7
|
import { type ProverClientUserConfig } from '@aztec/prover-client/config';
|
|
8
8
|
import { type SequencerClientConfig, sequencerClientConfigMappings } from '@aztec/sequencer-client/config';
|
|
9
|
+
import { type NodeRPCConfig } from '@aztec/stdlib/config';
|
|
9
10
|
import { type ValidatorClientConfig } from '@aztec/validator-client/config';
|
|
10
11
|
import { type WorldStateConfig } from '@aztec/world-state/config';
|
|
11
12
|
import { type SentinelConfig } from '../sentinel/config.js';
|
|
@@ -13,7 +14,7 @@ export { sequencerClientConfigMappings, type SequencerClientConfig };
|
|
|
13
14
|
/**
|
|
14
15
|
* The configuration the aztec node.
|
|
15
16
|
*/
|
|
16
|
-
export type AztecNodeConfig = ArchiverConfig & SequencerClientConfig & ValidatorClientConfig & ProverClientUserConfig & WorldStateConfig & Pick<ProverClientUserConfig, 'bbBinaryPath' | 'bbWorkingDirectory' | 'realProofs'> & P2PConfig & DataStoreConfig & SentinelConfig & SharedNodeConfig & GenesisStateConfig & {
|
|
17
|
+
export type AztecNodeConfig = ArchiverConfig & SequencerClientConfig & ValidatorClientConfig & ProverClientUserConfig & WorldStateConfig & Pick<ProverClientUserConfig, 'bbBinaryPath' | 'bbWorkingDirectory' | 'realProofs'> & P2PConfig & DataStoreConfig & SentinelConfig & SharedNodeConfig & GenesisStateConfig & NodeRPCConfig & {
|
|
17
18
|
/** L1 contracts addresses */
|
|
18
19
|
l1Contracts: L1ContractAddresses;
|
|
19
20
|
/** Whether the validator is disabled for this node */
|
|
@@ -25,8 +26,4 @@ export declare const aztecNodeConfigMappings: ConfigMappingsType<AztecNodeConfig
|
|
|
25
26
|
* @returns A valid aztec node config.
|
|
26
27
|
*/
|
|
27
28
|
export declare function getConfigEnvVars(): AztecNodeConfig;
|
|
28
|
-
/**
|
|
29
|
-
* Returns package version.
|
|
30
|
-
*/
|
|
31
|
-
export declare function getPackageVersion(): any;
|
|
32
29
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/aztec-node/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,wBAAwB,CAAC;AACrF,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EAGzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,kBAAkB,EAA8C,MAAM,0BAA0B,CAAC;AAC/G,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,KAAK,sBAAsB,EAA8B,MAAM,6BAA6B,CAAC;AACtG,OAAO,EAAE,KAAK,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,KAAK,qBAAqB,EAAiC,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/aztec-node/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,wBAAwB,CAAC;AACrF,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EAGzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,kBAAkB,EAA8C,MAAM,0BAA0B,CAAC;AAC/G,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,KAAK,sBAAsB,EAA8B,MAAM,6BAA6B,CAAC;AACtG,OAAO,EAAE,KAAK,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,KAAK,aAAa,EAAyB,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,KAAK,qBAAqB,EAAiC,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,KAAK,gBAAgB,EAA4B,MAAM,2BAA2B,CAAC;AAE5F,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,uBAAuB,CAAC;AAEpF,OAAO,EAAE,6BAA6B,EAAE,KAAK,qBAAqB,EAAE,CAAC;AAErE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,GAC1C,qBAAqB,GACrB,qBAAqB,GACrB,sBAAsB,GACtB,gBAAgB,GAChB,IAAI,CAAC,sBAAsB,EAAE,cAAc,GAAG,oBAAoB,GAAG,YAAY,CAAC,GAClF,SAAS,GACT,eAAe,GACf,cAAc,GACd,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GAAG;IACd,6BAA6B;IAC7B,WAAW,EAAE,mBAAmB,CAAC;IACjC,sDAAsD;IACtD,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEJ,eAAO,MAAM,uBAAuB,EAAE,kBAAkB,CAAC,eAAe,CAqBvE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,CAElD"}
|
|
@@ -6,11 +6,9 @@ import { sharedNodeConfigMappings } from '@aztec/node-lib/config';
|
|
|
6
6
|
import { p2pConfigMappings } from '@aztec/p2p/config';
|
|
7
7
|
import { proverClientConfigMappings } from '@aztec/prover-client/config';
|
|
8
8
|
import { sequencerClientConfigMappings } from '@aztec/sequencer-client/config';
|
|
9
|
+
import { nodeRpcConfigMappings } from '@aztec/stdlib/config';
|
|
9
10
|
import { validatorClientConfigMappings } from '@aztec/validator-client/config';
|
|
10
11
|
import { worldStateConfigMappings } from '@aztec/world-state/config';
|
|
11
|
-
import { readFileSync } from 'fs';
|
|
12
|
-
import { dirname, resolve } from 'path';
|
|
13
|
-
import { fileURLToPath } from 'url';
|
|
14
12
|
import { sentinelConfigMappings } from '../sentinel/config.js';
|
|
15
13
|
export { sequencerClientConfigMappings };
|
|
16
14
|
export const aztecNodeConfigMappings = {
|
|
@@ -24,6 +22,7 @@ export const aztecNodeConfigMappings = {
|
|
|
24
22
|
...sentinelConfigMappings,
|
|
25
23
|
...sharedNodeConfigMappings,
|
|
26
24
|
...genesisStateConfigMappings,
|
|
25
|
+
...nodeRpcConfigMappings,
|
|
27
26
|
l1Contracts: {
|
|
28
27
|
description: 'The deployed L1 contract addresses',
|
|
29
28
|
nested: l1ContractAddressesMapping
|
|
@@ -40,10 +39,3 @@ export const aztecNodeConfigMappings = {
|
|
|
40
39
|
*/ export function getConfigEnvVars() {
|
|
41
40
|
return getConfigFromMappings(aztecNodeConfigMappings);
|
|
42
41
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Returns package version.
|
|
45
|
-
*/ export function getPackageVersion() {
|
|
46
|
-
const releasePleaseManifestPath = resolve(dirname(fileURLToPath(import.meta.url)), '../../../../.release-please-manifest.json');
|
|
47
|
-
const version = JSON.parse(readFileSync(releasePleaseManifestPath).toString());
|
|
48
|
-
return version['.'];
|
|
49
|
-
}
|
|
@@ -6,7 +6,7 @@ import { type Logger } from '@aztec/foundation/log';
|
|
|
6
6
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
7
7
|
import { SiblingPath } from '@aztec/foundation/trees';
|
|
8
8
|
import { type P2P } from '@aztec/p2p';
|
|
9
|
-
import {
|
|
9
|
+
import { SequencerClient, type SequencerPublisher } from '@aztec/sequencer-client';
|
|
10
10
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
11
11
|
import type { InBlock, L2Block, L2BlockNumber, L2BlockSource, PublishedL2Block } from '@aztec/stdlib/block';
|
|
12
12
|
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress, NodeInfo, ProtocolContractAddresses } from '@aztec/stdlib/contract';
|
|
@@ -17,11 +17,11 @@ import type { LogFilter, PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
|
17
17
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
18
18
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
19
19
|
import { MerkleTreeId, NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
20
|
-
import { type BlockHeader, type IndexedTxEffect, PublicSimulationOutput, Tx, type TxHash, TxReceipt, type TxValidationResult } from '@aztec/stdlib/tx';
|
|
20
|
+
import { type BlockHeader, type GlobalVariableBuilder as GlobalVariableBuilderInterface, type IndexedTxEffect, PublicSimulationOutput, Tx, type TxHash, TxReceipt, type TxValidationResult } from '@aztec/stdlib/tx';
|
|
21
21
|
import type { ValidatorsStats } from '@aztec/stdlib/validators';
|
|
22
22
|
import { type TelemetryClient, type Traceable, type Tracer } from '@aztec/telemetry-client';
|
|
23
23
|
import { Sentinel } from '../sentinel/sentinel.js';
|
|
24
|
-
import {
|
|
24
|
+
import type { AztecNodeConfig } from './config.js';
|
|
25
25
|
/**
|
|
26
26
|
* The aztec node.
|
|
27
27
|
*/
|
|
@@ -38,16 +38,16 @@ export declare class AztecNodeService implements AztecNode, AztecNodeAdmin, Trac
|
|
|
38
38
|
protected readonly validatorsSentinel: Sentinel | undefined;
|
|
39
39
|
protected readonly l1ChainId: number;
|
|
40
40
|
protected readonly version: number;
|
|
41
|
-
protected readonly globalVariableBuilder:
|
|
41
|
+
protected readonly globalVariableBuilder: GlobalVariableBuilderInterface;
|
|
42
|
+
private readonly packageVersion;
|
|
42
43
|
private proofVerifier;
|
|
43
44
|
private telemetry;
|
|
44
45
|
private log;
|
|
45
|
-
private packageVersion;
|
|
46
46
|
private metrics;
|
|
47
47
|
private isUploadingSnapshot;
|
|
48
48
|
private txQueue;
|
|
49
49
|
readonly tracer: Tracer;
|
|
50
|
-
constructor(config: AztecNodeConfig, p2pClient: P2P, blockSource: L2BlockSource & Partial<Service>, logsSource: L2LogsSource, contractDataSource: ContractDataSource, l1ToL2MessageSource: L1ToL2MessageSource, worldStateSynchronizer: WorldStateSynchronizer, sequencer: SequencerClient | undefined, validatorsSentinel: Sentinel | undefined, l1ChainId: number, version: number, globalVariableBuilder:
|
|
50
|
+
constructor(config: AztecNodeConfig, p2pClient: P2P, blockSource: L2BlockSource & Partial<Service>, logsSource: L2LogsSource, contractDataSource: ContractDataSource, l1ToL2MessageSource: L1ToL2MessageSource, worldStateSynchronizer: WorldStateSynchronizer, sequencer: SequencerClient | undefined, validatorsSentinel: Sentinel | undefined, l1ChainId: number, version: number, globalVariableBuilder: GlobalVariableBuilderInterface, packageVersion: string, proofVerifier: ClientProtocolCircuitVerifier, telemetry?: TelemetryClient, log?: Logger);
|
|
51
51
|
getWorldStateSyncStatus(): Promise<WorldStateSyncStatus>;
|
|
52
52
|
getL2Tips(): Promise<import("@aztec/stdlib/block").L2Tips>;
|
|
53
53
|
/**
|
|
@@ -297,5 +297,8 @@ export declare class AztecNodeService implements AztecNode, AztecNodeAdmin, Trac
|
|
|
297
297
|
flushTxs(): Promise<void>;
|
|
298
298
|
getValidatorsStats(): Promise<ValidatorsStats>;
|
|
299
299
|
startSnapshotUpload(location: string): Promise<void>;
|
|
300
|
+
rollbackTo(targetBlock: number, force?: boolean): Promise<void>;
|
|
301
|
+
pauseSync(): Promise<void>;
|
|
302
|
+
resumeSync(): Promise<void>;
|
|
300
303
|
}
|
|
301
304
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/aztec-node/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,uBAAuB,EAAwB,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC7B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,KAAK,mBAAmB,EAAyC,MAAM,iBAAiB,CAAC;AAGlG,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/aztec-node/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,8 +13,10 @@ import { RegistryContract, createEthereumChain } from '@aztec/ethereum';
|
|
|
13
13
|
import { compactArray } from '@aztec/foundation/collection';
|
|
14
14
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
15
15
|
import { Fr } from '@aztec/foundation/fields';
|
|
16
|
+
import { BadRequestError } from '@aztec/foundation/json-rpc';
|
|
16
17
|
import { createLogger } from '@aztec/foundation/log';
|
|
17
18
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
19
|
+
import { count } from '@aztec/foundation/string';
|
|
18
20
|
import { DateProvider, Timer } from '@aztec/foundation/timer';
|
|
19
21
|
import { SiblingPath } from '@aztec/foundation/trees';
|
|
20
22
|
import { openTmpStore } from '@aztec/kv-store/lmdb';
|
|
@@ -31,12 +33,12 @@ import { tryStop } from '@aztec/stdlib/interfaces/server';
|
|
|
31
33
|
import { P2PClientType } from '@aztec/stdlib/p2p';
|
|
32
34
|
import { MerkleTreeId, NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
33
35
|
import { PublicSimulationOutput, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
|
|
36
|
+
import { getPackageVersion } from '@aztec/stdlib/update-checker';
|
|
34
37
|
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
35
38
|
import { createValidatorClient } from '@aztec/validator-client';
|
|
36
39
|
import { createWorldStateSynchronizer } from '@aztec/world-state';
|
|
37
40
|
import { createPublicClient, fallback, getContract, http } from 'viem';
|
|
38
41
|
import { createSentinel } from '../sentinel/factory.js';
|
|
39
|
-
import { getPackageVersion } from './config.js';
|
|
40
42
|
import { NodeMetrics } from './node_metrics.js';
|
|
41
43
|
/**
|
|
42
44
|
* The aztec node.
|
|
@@ -53,17 +55,17 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
53
55
|
l1ChainId;
|
|
54
56
|
version;
|
|
55
57
|
globalVariableBuilder;
|
|
58
|
+
packageVersion;
|
|
56
59
|
proofVerifier;
|
|
57
60
|
telemetry;
|
|
58
61
|
log;
|
|
59
|
-
packageVersion;
|
|
60
62
|
metrics;
|
|
61
63
|
// Prevent two snapshot operations to happen simultaneously
|
|
62
64
|
isUploadingSnapshot;
|
|
63
65
|
// Serial queue to ensure that we only send one tx at a time
|
|
64
66
|
txQueue;
|
|
65
67
|
tracer;
|
|
66
|
-
constructor(config, p2pClient, blockSource, logsSource, contractDataSource, l1ToL2MessageSource, worldStateSynchronizer, sequencer, validatorsSentinel, l1ChainId, version, globalVariableBuilder, proofVerifier, telemetry = getTelemetryClient(), log = createLogger('node')){
|
|
68
|
+
constructor(config, p2pClient, blockSource, logsSource, contractDataSource, l1ToL2MessageSource, worldStateSynchronizer, sequencer, validatorsSentinel, l1ChainId, version, globalVariableBuilder, packageVersion, proofVerifier, telemetry = getTelemetryClient(), log = createLogger('node')){
|
|
67
69
|
this.config = config;
|
|
68
70
|
this.p2pClient = p2pClient;
|
|
69
71
|
this.blockSource = blockSource;
|
|
@@ -76,12 +78,12 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
76
78
|
this.l1ChainId = l1ChainId;
|
|
77
79
|
this.version = version;
|
|
78
80
|
this.globalVariableBuilder = globalVariableBuilder;
|
|
81
|
+
this.packageVersion = packageVersion;
|
|
79
82
|
this.proofVerifier = proofVerifier;
|
|
80
83
|
this.telemetry = telemetry;
|
|
81
84
|
this.log = log;
|
|
82
85
|
this.isUploadingSnapshot = false;
|
|
83
86
|
this.txQueue = new SerialQueue();
|
|
84
|
-
this.packageVersion = getPackageVersion();
|
|
85
87
|
this.metrics = new NodeMetrics(telemetry, 'AztecNodeService');
|
|
86
88
|
this.tracer = telemetry.getTracer('AztecNodeService');
|
|
87
89
|
this.txQueue.start();
|
|
@@ -100,8 +102,9 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
100
102
|
* @param config - The configuration to be used by the aztec node.
|
|
101
103
|
* @returns - A fully synced Aztec Node for use in development/testing.
|
|
102
104
|
*/ static async createAndSync(config, deps = {}, options = {}) {
|
|
103
|
-
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
104
105
|
const log = deps.logger ?? createLogger('node');
|
|
106
|
+
const packageVersion = getPackageVersion() ?? '';
|
|
107
|
+
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
105
108
|
const dateProvider = deps.dateProvider ?? new DateProvider();
|
|
106
109
|
const blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config, {
|
|
107
110
|
logger: createLogger('node:blob-sink:client')
|
|
@@ -147,7 +150,7 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
147
150
|
dateProvider
|
|
148
151
|
});
|
|
149
152
|
// create the tx pool and the p2p client, which will need the l2 block source
|
|
150
|
-
const p2pClient = await createP2PClient(P2PClientType.Full, config, archiver, proofVerifier, worldStateSynchronizer, epochCache, telemetry);
|
|
153
|
+
const p2pClient = await createP2PClient(P2PClientType.Full, config, archiver, proofVerifier, worldStateSynchronizer, epochCache, packageVersion, telemetry);
|
|
151
154
|
// Start world state and wait for it to sync to the archiver.
|
|
152
155
|
await worldStateSynchronizer.start();
|
|
153
156
|
// Start p2p. Note that it depends on world state to be running.
|
|
@@ -158,7 +161,8 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
158
161
|
p2pClient,
|
|
159
162
|
telemetry,
|
|
160
163
|
dateProvider,
|
|
161
|
-
epochCache
|
|
164
|
+
epochCache,
|
|
165
|
+
blockSource: archiver
|
|
162
166
|
});
|
|
163
167
|
const validatorsSentinel = await createSentinel(epochCache, archiver, p2pClient, config);
|
|
164
168
|
await validatorsSentinel?.start();
|
|
@@ -177,7 +181,7 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
177
181
|
dateProvider,
|
|
178
182
|
blobSinkClient
|
|
179
183
|
});
|
|
180
|
-
return new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, validatorsSentinel, ethereumChain.chainInfo.id, config.rollupVersion, new GlobalVariableBuilder(config), proofVerifier, telemetry, log);
|
|
184
|
+
return new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, validatorsSentinel, ethereumChain.chainInfo.id, config.rollupVersion, new GlobalVariableBuilder(config), packageVersion, proofVerifier, telemetry, log);
|
|
181
185
|
}
|
|
182
186
|
/**
|
|
183
187
|
* Returns the sequencer client instance.
|
|
@@ -375,9 +379,8 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
375
379
|
*/ getPendingTxs() {
|
|
376
380
|
return this.p2pClient.getPendingTxs();
|
|
377
381
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
return pendingTxs.length;
|
|
382
|
+
getPendingTxCount() {
|
|
383
|
+
return this.p2pClient.getPendingTxCount();
|
|
381
384
|
}
|
|
382
385
|
/**
|
|
383
386
|
* Method to retrieve a single tx from the mempool or unfinalised chain.
|
|
@@ -518,14 +521,14 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
518
521
|
}
|
|
519
522
|
const tempStores = [];
|
|
520
523
|
// Construct message subtrees
|
|
521
|
-
const l2toL1Subtrees =
|
|
524
|
+
const l2toL1Subtrees = l2ToL1Messages.map((msgs, i)=>{
|
|
522
525
|
const store = openTmpStore(true);
|
|
523
526
|
tempStores.push(store);
|
|
524
527
|
const treeHeight = msgs.length <= 1 ? 1 : Math.ceil(Math.log2(msgs.length));
|
|
525
528
|
const tree = new StandardTree(store, new SHA256Trunc(), `temp_msgs_subtrees_${i}`, treeHeight, 0n, Fr);
|
|
526
|
-
|
|
529
|
+
tree.appendLeaves(msgs);
|
|
527
530
|
return tree;
|
|
528
|
-
})
|
|
531
|
+
});
|
|
529
532
|
// path of the input msg from leaf -> first out hash calculated in base rolllup
|
|
530
533
|
const subtreePathOfL2ToL1Message = await l2toL1Subtrees[indexOfMsgTx].getSiblingPath(BigInt(indexOfMsgInSubtree), true);
|
|
531
534
|
const numTxs = block.body.txEffects.length;
|
|
@@ -535,7 +538,8 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
535
538
|
subtreePathOfL2ToL1Message
|
|
536
539
|
];
|
|
537
540
|
}
|
|
538
|
-
|
|
541
|
+
// For a tx with no messages, we have to set an out hash of 0 to match the circuit/contract behavior
|
|
542
|
+
const l2toL1SubtreeRoots = l2toL1Subtrees.map((t)=>t.getNumLeaves(true) == 0n ? Fr.ZERO : Fr.fromBuffer(t.getRoot(true)));
|
|
539
543
|
const maxTreeHeight = Math.ceil(Math.log2(l2toL1SubtreeRoots.length));
|
|
540
544
|
// The root of this tree is the out_hash calculated in Noir => we truncate to match Noir's SHA
|
|
541
545
|
const outHashTree = new UnbalancedTree(new SHA256Trunc(), 'temp_outhash_sibling_path', maxTreeHeight, Fr);
|
|
@@ -662,6 +666,13 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
662
666
|
* Simulates the public part of a transaction with the current state.
|
|
663
667
|
* @param tx - The transaction to simulate.
|
|
664
668
|
**/ async simulatePublicCalls(tx, skipFeeEnforcement = false) {
|
|
669
|
+
// Check total gas limit for simulation
|
|
670
|
+
const gasSettings = tx.data.constants.txContext.gasSettings;
|
|
671
|
+
const txGasLimit = gasSettings.gasLimits.l2Gas;
|
|
672
|
+
const teardownGasLimit = gasSettings.teardownGasLimits.l2Gas;
|
|
673
|
+
if (txGasLimit + teardownGasLimit > this.config.rpcSimulatePublicMaxGasLimit) {
|
|
674
|
+
throw new BadRequestError(`Transaction total gas limit ${txGasLimit + teardownGasLimit} (${txGasLimit} + ${teardownGasLimit}) exceeds maximum gas limit ${this.config.rpcSimulatePublicMaxGasLimit} for simulation`);
|
|
675
|
+
}
|
|
665
676
|
const txHash = await tx.getTxHash();
|
|
666
677
|
const blockNumber = await this.blockSource.getBlockNumber() + 1;
|
|
667
678
|
// If sequencer is not initialized, we just set these values to zero for simulation.
|
|
@@ -676,9 +687,9 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
676
687
|
});
|
|
677
688
|
const merkleTreeFork = await this.worldStateSynchronizer.fork();
|
|
678
689
|
try {
|
|
679
|
-
const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, skipFeeEnforcement);
|
|
690
|
+
const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, skipFeeEnforcement, /*clientInitiatedSimulation*/ true);
|
|
680
691
|
// REFACTOR: Consider merging ProcessReturnValues into ProcessedTx
|
|
681
|
-
const [processedTxs, failedTxs, returns] = await processor.process([
|
|
692
|
+
const [processedTxs, failedTxs, _usedTxs, returns] = await processor.process([
|
|
682
693
|
tx
|
|
683
694
|
]);
|
|
684
695
|
// REFACTOR: Consider returning the error rather than throwing
|
|
@@ -773,6 +784,50 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
773
784
|
});
|
|
774
785
|
return Promise.resolve();
|
|
775
786
|
}
|
|
787
|
+
async rollbackTo(targetBlock, force) {
|
|
788
|
+
const archiver = this.blockSource;
|
|
789
|
+
if (!('rollbackTo' in archiver)) {
|
|
790
|
+
throw new Error('Archiver implementation does not support rollbacks.');
|
|
791
|
+
}
|
|
792
|
+
const finalizedBlock = await archiver.getL2Tips().then((tips)=>tips.finalized.number);
|
|
793
|
+
if (targetBlock < finalizedBlock) {
|
|
794
|
+
if (force) {
|
|
795
|
+
this.log.warn(`Clearing world state database to allow rolling back behind finalized block ${finalizedBlock}`);
|
|
796
|
+
await this.worldStateSynchronizer.clear();
|
|
797
|
+
await this.p2pClient.clear();
|
|
798
|
+
} else {
|
|
799
|
+
throw new Error(`Cannot rollback to block ${targetBlock} as it is before finalized ${finalizedBlock}`);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
try {
|
|
803
|
+
this.log.info(`Pausing archiver and world state sync to start rollback`);
|
|
804
|
+
await archiver.stop();
|
|
805
|
+
await this.worldStateSynchronizer.stopSync();
|
|
806
|
+
const currentBlock = await archiver.getBlockNumber();
|
|
807
|
+
const blocksToUnwind = currentBlock - targetBlock;
|
|
808
|
+
this.log.info(`Unwinding ${count(blocksToUnwind, 'block')} from L2 block ${currentBlock} to ${targetBlock}`);
|
|
809
|
+
await archiver.rollbackTo(targetBlock);
|
|
810
|
+
this.log.info(`Unwinding complete.`);
|
|
811
|
+
} catch (err) {
|
|
812
|
+
this.log.error(`Error during rollback`, err);
|
|
813
|
+
throw err;
|
|
814
|
+
} finally{
|
|
815
|
+
this.log.info(`Resuming world state and archiver sync.`);
|
|
816
|
+
this.worldStateSynchronizer.resumeSync();
|
|
817
|
+
archiver.resume();
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
async pauseSync() {
|
|
821
|
+
this.log.info(`Pausing archiver and world state sync`);
|
|
822
|
+
await this.blockSource.stop();
|
|
823
|
+
await this.worldStateSynchronizer.stopSync();
|
|
824
|
+
}
|
|
825
|
+
resumeSync() {
|
|
826
|
+
this.log.info(`Resuming world state and archiver sync.`);
|
|
827
|
+
this.worldStateSynchronizer.resumeSync();
|
|
828
|
+
this.blockSource.resume();
|
|
829
|
+
return Promise.resolve();
|
|
830
|
+
}
|
|
776
831
|
/**
|
|
777
832
|
* Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
|
|
778
833
|
* @param blockNumber - The block number at which to get the data.
|
|
@@ -17,7 +17,11 @@ export declare class Sentinel implements L2BlockStreamEventHandler {
|
|
|
17
17
|
protected l2TipsStore: L2TipsStore;
|
|
18
18
|
protected initialSlot: bigint | undefined;
|
|
19
19
|
protected lastProcessedSlot: bigint | undefined;
|
|
20
|
-
protected
|
|
20
|
+
protected slotNumberToBlock: Map<bigint, {
|
|
21
|
+
blockNumber: number;
|
|
22
|
+
archive: string;
|
|
23
|
+
attestors: EthAddress[];
|
|
24
|
+
}>;
|
|
21
25
|
constructor(epochCache: EpochCache, archiver: L2BlockSource, p2p: P2PClient, store: SentinelStore, logger?: import("@aztec/foundation/log").Logger);
|
|
22
26
|
start(): Promise<void>;
|
|
23
27
|
/** Loads initial slot and initializes blockstream. We will not process anything at or before the initial slot. */
|
|
@@ -52,7 +56,7 @@ export declare class Sentinel implements L2BlockStreamEventHandler {
|
|
|
52
56
|
protected computeStatsForValidator(address: `0x${string}`, allHistory: ValidatorStatusHistory, fromSlot?: bigint): ValidatorStats;
|
|
53
57
|
protected computeMissed(history: ValidatorStatusHistory, computeOverPrefix: ValidatorStatusType, filter: ValidatorStatusInSlot): {
|
|
54
58
|
currentStreak: number;
|
|
55
|
-
rate: number;
|
|
59
|
+
rate: number | undefined;
|
|
56
60
|
count: number;
|
|
57
61
|
};
|
|
58
62
|
protected computeFromSlot(slot: bigint | undefined): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentinel.d.ts","sourceRoot":"","sources":["../../src/sentinel/sentinel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,
|
|
1
|
+
{"version":3,"file":"sentinel.d.ts","sourceRoot":"","sources":["../../src/sentinel/sentinel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAE/B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,qBAAa,QAAS,YAAW,yBAAyB;IAWtD,SAAS,CAAC,UAAU,EAAE,UAAU;IAChC,SAAS,CAAC,QAAQ,EAAE,aAAa;IACjC,SAAS,CAAC,GAAG,EAAE,SAAS;IACxB,SAAS,CAAC,KAAK,EAAE,aAAa;IAC9B,SAAS,CAAC,MAAM;IAdlB,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IACzC,SAAS,CAAC,WAAW,EAAG,aAAa,CAAC;IACtC,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,SAAS,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAC/F;gBAGA,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,aAAa,EACpB,MAAM,yCAAgC;IAOrC,KAAK;IAKlB,kHAAkH;cAClG,IAAI;IAOb,IAAI;IAIE,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB7E;;;;OAIG;IACU,IAAI;IAmBjB;;;;OAIG;cACa,gBAAgB,CAAC,WAAW,EAAE,MAAM;IAkCpD;;;OAGG;cACa,WAAW,CAAC,IAAI,EAAE,MAAM;IAexC,0CAA0C;cAC1B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE;;;IAwD1G,wDAAwD;IACxD,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAIxG,0DAA0D;IAC7C,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC;IAiBrD,SAAS,CAAC,wBAAwB,CAChC,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,UAAU,EAAE,sBAAsB,EAClC,QAAQ,CAAC,EAAE,MAAM,GAChB,cAAc;IAejB,SAAS,CAAC,aAAa,CACrB,OAAO,EAAE,sBAAsB,EAC/B,iBAAiB,EAAE,mBAAmB,EACtC,MAAM,EAAE,qBAAqB;;;;;IAW/B,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;;;;;CAOnD"}
|
|
@@ -3,7 +3,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
|
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
5
5
|
import { L2TipsMemoryStore } from '@aztec/kv-store/stores';
|
|
6
|
-
import { L2BlockStream } from '@aztec/stdlib/block';
|
|
6
|
+
import { L2BlockStream, getAttestationsFromPublishedL2Block } from '@aztec/stdlib/block';
|
|
7
7
|
import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
8
8
|
export class Sentinel {
|
|
9
9
|
epochCache;
|
|
@@ -16,14 +16,14 @@ export class Sentinel {
|
|
|
16
16
|
l2TipsStore;
|
|
17
17
|
initialSlot;
|
|
18
18
|
lastProcessedSlot;
|
|
19
|
-
|
|
19
|
+
slotNumberToBlock;
|
|
20
20
|
constructor(epochCache, archiver, p2p, store, logger = createLogger('node:sentinel')){
|
|
21
21
|
this.epochCache = epochCache;
|
|
22
22
|
this.archiver = archiver;
|
|
23
23
|
this.p2p = p2p;
|
|
24
24
|
this.store = store;
|
|
25
25
|
this.logger = logger;
|
|
26
|
-
this.
|
|
26
|
+
this.slotNumberToBlock = new Map();
|
|
27
27
|
this.l2TipsStore = new L2TipsMemoryStore();
|
|
28
28
|
const interval = epochCache.getL1Constants().ethereumSlotDuration * 1000 / 4;
|
|
29
29
|
this.runningPromise = new RunningPromise(this.work.bind(this), logger, interval);
|
|
@@ -46,16 +46,20 @@ export class Sentinel {
|
|
|
46
46
|
async handleBlockStreamEvent(event) {
|
|
47
47
|
await this.l2TipsStore.handleBlockStreamEvent(event);
|
|
48
48
|
if (event.type === 'blocks-added') {
|
|
49
|
-
// Store mapping from slot to archive
|
|
49
|
+
// Store mapping from slot to archive, block number, and attestors
|
|
50
50
|
for (const block of event.blocks){
|
|
51
|
-
this.
|
|
51
|
+
this.slotNumberToBlock.set(block.block.header.getSlot(), {
|
|
52
|
+
blockNumber: block.block.number,
|
|
53
|
+
archive: block.block.archive.root.toString(),
|
|
54
|
+
attestors: getAttestationsFromPublishedL2Block(block).map((att)=>att.getSender())
|
|
55
|
+
});
|
|
52
56
|
}
|
|
53
57
|
// Prune the archive map to only keep at most N entries
|
|
54
58
|
const historyLength = this.store.getHistoryLength();
|
|
55
|
-
if (this.
|
|
56
|
-
const toDelete = Array.from(this.
|
|
59
|
+
if (this.slotNumberToBlock.size > historyLength) {
|
|
60
|
+
const toDelete = Array.from(this.slotNumberToBlock.keys()).sort((a, b)=>Number(a - b)).slice(0, this.slotNumberToBlock.size - historyLength);
|
|
57
61
|
for (const key of toDelete){
|
|
58
|
-
this.
|
|
62
|
+
this.slotNumberToBlock.delete(key);
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
}
|
|
@@ -147,16 +151,21 @@ export class Sentinel {
|
|
|
147
151
|
// Check if there is an L2 block in L1 for this L2 slot
|
|
148
152
|
// Here we get all attestations for the block mined at the given slot,
|
|
149
153
|
// or all attestations for all proposals in the slot if no block was mined.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const
|
|
154
|
+
// We gather from both p2p (contains the ones seen on the p2p layer) and archiver
|
|
155
|
+
// (contains the ones synced from mined blocks, which we may have missed from p2p).
|
|
156
|
+
const block = this.slotNumberToBlock.get(slot);
|
|
157
|
+
const p2pAttested = await this.p2p.getAttestationsForSlot(slot, block?.archive);
|
|
158
|
+
const attestors = new Set([
|
|
159
|
+
...p2pAttested.map((a)=>a.getSender().toString()),
|
|
160
|
+
...block?.attestors.map((a)=>a.toString()) ?? []
|
|
161
|
+
]);
|
|
153
162
|
// We assume that there was a block proposal if at least one of the validators attested to it.
|
|
154
163
|
// It could be the case that every single validator failed, and we could differentiate it by having
|
|
155
164
|
// this node re-execute every block proposal it sees and storing it in the attestation pool.
|
|
156
165
|
// But we'll leave that corner case out to reduce pressure on the node.
|
|
157
|
-
const blockStatus =
|
|
166
|
+
const blockStatus = block ? 'mined' : attestors.size > 0 ? 'proposed' : 'missed';
|
|
158
167
|
this.logger.debug(`Block for slot ${slot} was ${blockStatus}`, {
|
|
159
|
-
|
|
168
|
+
...block,
|
|
160
169
|
slot
|
|
161
170
|
});
|
|
162
171
|
// Get attestors that failed their duties for this block, but only if there was a block proposed
|
|
@@ -164,7 +173,7 @@ export class Sentinel {
|
|
|
164
173
|
this.logger.debug(`Retrieved ${attestors.size} attestors out of ${committee.length} for slot ${slot}`, {
|
|
165
174
|
blockStatus,
|
|
166
175
|
proposer: proposer.toString(),
|
|
167
|
-
|
|
176
|
+
...block,
|
|
168
177
|
slot,
|
|
169
178
|
attestors: [
|
|
170
179
|
...attestors
|
|
@@ -229,7 +238,7 @@ export class Sentinel {
|
|
|
229
238
|
currentStreak: countWhile([
|
|
230
239
|
...relevantHistory
|
|
231
240
|
].reverse(), (h)=>h.status === filter),
|
|
232
|
-
rate: filteredHistory.length / relevantHistory.length,
|
|
241
|
+
rate: relevantHistory.length === 0 ? undefined : filteredHistory.length / relevantHistory.length,
|
|
233
242
|
count: filteredHistory.length
|
|
234
243
|
};
|
|
235
244
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sentinel/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAE9F,qBAAa,aAAa;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sentinel/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAE9F,qBAAa,aAAa;IAMtB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IANhB,gBAAuB,cAAc,KAAK;IAE1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;gBAGjD,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE;IAKpC,gBAAgB;IAIV,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC;YAUhG,0BAA0B;IAU3B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC;YAQrE,UAAU;IAKxB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,gBAAgB;CAgBzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/aztec-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.87.0",
|
|
4
4
|
"main": "dest/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -61,26 +61,27 @@
|
|
|
61
61
|
]
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@aztec/archiver": "0.
|
|
65
|
-
"@aztec/bb-prover": "0.
|
|
66
|
-
"@aztec/blob-sink": "0.
|
|
67
|
-
"@aztec/constants": "0.
|
|
68
|
-
"@aztec/epoch-cache": "0.
|
|
69
|
-
"@aztec/ethereum": "0.
|
|
70
|
-
"@aztec/foundation": "0.
|
|
71
|
-
"@aztec/kv-store": "0.
|
|
72
|
-
"@aztec/l1-artifacts": "0.
|
|
73
|
-
"@aztec/merkle-tree": "0.
|
|
74
|
-
"@aztec/node-lib": "0.
|
|
75
|
-
"@aztec/
|
|
76
|
-
"@aztec/
|
|
77
|
-
"@aztec/
|
|
78
|
-
"@aztec/
|
|
79
|
-
"@aztec/
|
|
80
|
-
"@aztec/
|
|
81
|
-
"@aztec/
|
|
82
|
-
"@aztec/
|
|
83
|
-
"@aztec/
|
|
64
|
+
"@aztec/archiver": "0.87.0",
|
|
65
|
+
"@aztec/bb-prover": "0.87.0",
|
|
66
|
+
"@aztec/blob-sink": "0.87.0",
|
|
67
|
+
"@aztec/constants": "0.87.0",
|
|
68
|
+
"@aztec/epoch-cache": "0.87.0",
|
|
69
|
+
"@aztec/ethereum": "0.87.0",
|
|
70
|
+
"@aztec/foundation": "0.87.0",
|
|
71
|
+
"@aztec/kv-store": "0.87.0",
|
|
72
|
+
"@aztec/l1-artifacts": "0.87.0",
|
|
73
|
+
"@aztec/merkle-tree": "0.87.0",
|
|
74
|
+
"@aztec/node-lib": "0.87.0",
|
|
75
|
+
"@aztec/noir-protocol-circuits-types": "0.87.0",
|
|
76
|
+
"@aztec/p2p": "0.87.0",
|
|
77
|
+
"@aztec/protocol-contracts": "0.87.0",
|
|
78
|
+
"@aztec/prover-client": "0.87.0",
|
|
79
|
+
"@aztec/sequencer-client": "0.87.0",
|
|
80
|
+
"@aztec/simulator": "0.87.0",
|
|
81
|
+
"@aztec/stdlib": "0.87.0",
|
|
82
|
+
"@aztec/telemetry-client": "0.87.0",
|
|
83
|
+
"@aztec/validator-client": "0.87.0",
|
|
84
|
+
"@aztec/world-state": "0.87.0",
|
|
84
85
|
"koa": "^2.16.1",
|
|
85
86
|
"koa-router": "^12.0.0",
|
|
86
87
|
"tslib": "^2.4.0",
|
|
@@ -89,11 +90,11 @@
|
|
|
89
90
|
"devDependencies": {
|
|
90
91
|
"@jest/globals": "^29.5.0",
|
|
91
92
|
"@types/jest": "^29.5.0",
|
|
92
|
-
"@types/node": "^
|
|
93
|
+
"@types/node": "^22.15.17",
|
|
93
94
|
"jest": "^29.5.0",
|
|
94
95
|
"jest-mock-extended": "^3.0.3",
|
|
95
96
|
"ts-node": "^10.9.1",
|
|
96
|
-
"typescript": "^5.
|
|
97
|
+
"typescript": "^5.3.3"
|
|
97
98
|
},
|
|
98
99
|
"files": [
|
|
99
100
|
"dest",
|
|
@@ -102,6 +103,6 @@
|
|
|
102
103
|
],
|
|
103
104
|
"types": "./dest/index.d.ts",
|
|
104
105
|
"engines": {
|
|
105
|
-
"node": ">=
|
|
106
|
+
"node": ">=20.10"
|
|
106
107
|
}
|
|
107
108
|
}
|
package/src/aztec-node/config.ts
CHANGED
|
@@ -11,13 +11,10 @@ import { type SharedNodeConfig, sharedNodeConfigMappings } from '@aztec/node-lib
|
|
|
11
11
|
import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
|
|
12
12
|
import { type ProverClientUserConfig, proverClientConfigMappings } from '@aztec/prover-client/config';
|
|
13
13
|
import { type SequencerClientConfig, sequencerClientConfigMappings } from '@aztec/sequencer-client/config';
|
|
14
|
+
import { type NodeRPCConfig, nodeRpcConfigMappings } from '@aztec/stdlib/config';
|
|
14
15
|
import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client/config';
|
|
15
16
|
import { type WorldStateConfig, worldStateConfigMappings } from '@aztec/world-state/config';
|
|
16
17
|
|
|
17
|
-
import { readFileSync } from 'fs';
|
|
18
|
-
import { dirname, resolve } from 'path';
|
|
19
|
-
import { fileURLToPath } from 'url';
|
|
20
|
-
|
|
21
18
|
import { type SentinelConfig, sentinelConfigMappings } from '../sentinel/config.js';
|
|
22
19
|
|
|
23
20
|
export { sequencerClientConfigMappings, type SequencerClientConfig };
|
|
@@ -35,7 +32,8 @@ export type AztecNodeConfig = ArchiverConfig &
|
|
|
35
32
|
DataStoreConfig &
|
|
36
33
|
SentinelConfig &
|
|
37
34
|
SharedNodeConfig &
|
|
38
|
-
GenesisStateConfig &
|
|
35
|
+
GenesisStateConfig &
|
|
36
|
+
NodeRPCConfig & {
|
|
39
37
|
/** L1 contracts addresses */
|
|
40
38
|
l1Contracts: L1ContractAddresses;
|
|
41
39
|
/** Whether the validator is disabled for this node */
|
|
@@ -53,6 +51,7 @@ export const aztecNodeConfigMappings: ConfigMappingsType<AztecNodeConfig> = {
|
|
|
53
51
|
...sentinelConfigMappings,
|
|
54
52
|
...sharedNodeConfigMappings,
|
|
55
53
|
...genesisStateConfigMappings,
|
|
54
|
+
...nodeRpcConfigMappings,
|
|
56
55
|
l1Contracts: {
|
|
57
56
|
description: 'The deployed L1 contract addresses',
|
|
58
57
|
nested: l1ContractAddressesMapping,
|
|
@@ -71,15 +70,3 @@ export const aztecNodeConfigMappings: ConfigMappingsType<AztecNodeConfig> = {
|
|
|
71
70
|
export function getConfigEnvVars(): AztecNodeConfig {
|
|
72
71
|
return getConfigFromMappings<AztecNodeConfig>(aztecNodeConfigMappings);
|
|
73
72
|
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Returns package version.
|
|
77
|
-
*/
|
|
78
|
-
export function getPackageVersion() {
|
|
79
|
-
const releasePleaseManifestPath = resolve(
|
|
80
|
-
dirname(fileURLToPath(import.meta.url)),
|
|
81
|
-
'../../../../.release-please-manifest.json',
|
|
82
|
-
);
|
|
83
|
-
const version = JSON.parse(readFileSync(releasePleaseManifestPath).toString());
|
|
84
|
-
return version['.'];
|
|
85
|
-
}
|
package/src/aztec-node/server.ts
CHANGED
|
@@ -14,8 +14,10 @@ import { type L1ContractAddresses, RegistryContract, createEthereumChain } from
|
|
|
14
14
|
import { compactArray } from '@aztec/foundation/collection';
|
|
15
15
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
16
16
|
import { Fr } from '@aztec/foundation/fields';
|
|
17
|
+
import { BadRequestError } from '@aztec/foundation/json-rpc';
|
|
17
18
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
18
19
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
20
|
+
import { count } from '@aztec/foundation/string';
|
|
19
21
|
import { DateProvider, Timer } from '@aztec/foundation/timer';
|
|
20
22
|
import { SiblingPath } from '@aztec/foundation/trees';
|
|
21
23
|
import type { AztecKVStore } from '@aztec/kv-store';
|
|
@@ -67,6 +69,7 @@ import type { NullifierLeafPreimage, PublicDataTreeLeaf, PublicDataTreeLeafPreim
|
|
|
67
69
|
import { MerkleTreeId, NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
68
70
|
import {
|
|
69
71
|
type BlockHeader,
|
|
72
|
+
type GlobalVariableBuilder as GlobalVariableBuilderInterface,
|
|
70
73
|
type IndexedTxEffect,
|
|
71
74
|
PublicSimulationOutput,
|
|
72
75
|
Tx,
|
|
@@ -75,6 +78,7 @@ import {
|
|
|
75
78
|
TxStatus,
|
|
76
79
|
type TxValidationResult,
|
|
77
80
|
} from '@aztec/stdlib/tx';
|
|
81
|
+
import { getPackageVersion } from '@aztec/stdlib/update-checker';
|
|
78
82
|
import type { ValidatorsStats } from '@aztec/stdlib/validators';
|
|
79
83
|
import {
|
|
80
84
|
Attributes,
|
|
@@ -91,14 +95,13 @@ import { createPublicClient, fallback, getContract, http } from 'viem';
|
|
|
91
95
|
|
|
92
96
|
import { createSentinel } from '../sentinel/factory.js';
|
|
93
97
|
import { Sentinel } from '../sentinel/sentinel.js';
|
|
94
|
-
import {
|
|
98
|
+
import type { AztecNodeConfig } from './config.js';
|
|
95
99
|
import { NodeMetrics } from './node_metrics.js';
|
|
96
100
|
|
|
97
101
|
/**
|
|
98
102
|
* The aztec node.
|
|
99
103
|
*/
|
|
100
104
|
export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
101
|
-
private packageVersion: string;
|
|
102
105
|
private metrics: NodeMetrics;
|
|
103
106
|
|
|
104
107
|
// Prevent two snapshot operations to happen simultaneously
|
|
@@ -121,12 +124,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
121
124
|
protected readonly validatorsSentinel: Sentinel | undefined,
|
|
122
125
|
protected readonly l1ChainId: number,
|
|
123
126
|
protected readonly version: number,
|
|
124
|
-
protected readonly globalVariableBuilder:
|
|
127
|
+
protected readonly globalVariableBuilder: GlobalVariableBuilderInterface,
|
|
128
|
+
private readonly packageVersion: string,
|
|
125
129
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
126
130
|
private telemetry: TelemetryClient = getTelemetryClient(),
|
|
127
131
|
private log = createLogger('node'),
|
|
128
132
|
) {
|
|
129
|
-
this.packageVersion = getPackageVersion();
|
|
130
133
|
this.metrics = new NodeMetrics(telemetry, 'AztecNodeService');
|
|
131
134
|
this.tracer = telemetry.getTracer('AztecNodeService');
|
|
132
135
|
this.txQueue.start();
|
|
@@ -162,8 +165,9 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
162
165
|
prefilledPublicData?: PublicDataTreeLeaf[];
|
|
163
166
|
} = {},
|
|
164
167
|
): Promise<AztecNodeService> {
|
|
165
|
-
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
166
168
|
const log = deps.logger ?? createLogger('node');
|
|
169
|
+
const packageVersion = getPackageVersion() ?? '';
|
|
170
|
+
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
167
171
|
const dateProvider = deps.dateProvider ?? new DateProvider();
|
|
168
172
|
const blobSinkClient =
|
|
169
173
|
deps.blobSinkClient ?? createBlobSinkClient(config, { logger: createLogger('node:blob-sink:client') });
|
|
@@ -234,6 +238,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
234
238
|
proofVerifier,
|
|
235
239
|
worldStateSynchronizer,
|
|
236
240
|
epochCache,
|
|
241
|
+
packageVersion,
|
|
237
242
|
telemetry,
|
|
238
243
|
);
|
|
239
244
|
|
|
@@ -246,7 +251,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
246
251
|
const slasherClient = createSlasherClient(config, archiver, telemetry);
|
|
247
252
|
slasherClient.start();
|
|
248
253
|
|
|
249
|
-
const validatorClient = createValidatorClient(config, {
|
|
254
|
+
const validatorClient = createValidatorClient(config, {
|
|
255
|
+
p2pClient,
|
|
256
|
+
telemetry,
|
|
257
|
+
dateProvider,
|
|
258
|
+
epochCache,
|
|
259
|
+
blockSource: archiver,
|
|
260
|
+
});
|
|
250
261
|
|
|
251
262
|
const validatorsSentinel = await createSentinel(epochCache, archiver, p2pClient, config);
|
|
252
263
|
await validatorsSentinel?.start();
|
|
@@ -283,6 +294,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
283
294
|
ethereumChain.chainInfo.id,
|
|
284
295
|
config.rollupVersion,
|
|
285
296
|
new GlobalVariableBuilder(config),
|
|
297
|
+
packageVersion,
|
|
286
298
|
proofVerifier,
|
|
287
299
|
telemetry,
|
|
288
300
|
log,
|
|
@@ -534,9 +546,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
534
546
|
return this.p2pClient!.getPendingTxs();
|
|
535
547
|
}
|
|
536
548
|
|
|
537
|
-
public
|
|
538
|
-
|
|
539
|
-
return pendingTxs.length;
|
|
549
|
+
public getPendingTxCount() {
|
|
550
|
+
return this.p2pClient!.getPendingTxCount();
|
|
540
551
|
}
|
|
541
552
|
|
|
542
553
|
/**
|
|
@@ -724,16 +735,14 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
724
735
|
const tempStores: AztecKVStore[] = [];
|
|
725
736
|
|
|
726
737
|
// Construct message subtrees
|
|
727
|
-
const l2toL1Subtrees =
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
}),
|
|
736
|
-
);
|
|
738
|
+
const l2toL1Subtrees = l2ToL1Messages.map((msgs, i) => {
|
|
739
|
+
const store = openTmpStore(true);
|
|
740
|
+
tempStores.push(store);
|
|
741
|
+
const treeHeight = msgs.length <= 1 ? 1 : Math.ceil(Math.log2(msgs.length));
|
|
742
|
+
const tree = new StandardTree(store, new SHA256Trunc(), `temp_msgs_subtrees_${i}`, treeHeight, 0n, Fr);
|
|
743
|
+
tree.appendLeaves(msgs);
|
|
744
|
+
return tree;
|
|
745
|
+
});
|
|
737
746
|
|
|
738
747
|
// path of the input msg from leaf -> first out hash calculated in base rolllup
|
|
739
748
|
const subtreePathOfL2ToL1Message = await l2toL1Subtrees[indexOfMsgTx].getSiblingPath(
|
|
@@ -746,7 +755,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
746
755
|
return [BigInt(indexOfMsgInSubtree), subtreePathOfL2ToL1Message];
|
|
747
756
|
}
|
|
748
757
|
|
|
749
|
-
|
|
758
|
+
// For a tx with no messages, we have to set an out hash of 0 to match the circuit/contract behavior
|
|
759
|
+
const l2toL1SubtreeRoots = l2toL1Subtrees.map(t =>
|
|
760
|
+
t.getNumLeaves(true) == 0n ? Fr.ZERO : Fr.fromBuffer(t.getRoot(true)),
|
|
761
|
+
);
|
|
750
762
|
const maxTreeHeight = Math.ceil(Math.log2(l2toL1SubtreeRoots.length));
|
|
751
763
|
// The root of this tree is the out_hash calculated in Noir => we truncate to match Noir's SHA
|
|
752
764
|
const outHashTree = new UnbalancedTree(new SHA256Trunc(), 'temp_outhash_sibling_path', maxTreeHeight, Fr);
|
|
@@ -926,6 +938,20 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
926
938
|
[Attributes.TX_HASH]: (await tx.getTxHash()).toString(),
|
|
927
939
|
}))
|
|
928
940
|
public async simulatePublicCalls(tx: Tx, skipFeeEnforcement = false): Promise<PublicSimulationOutput> {
|
|
941
|
+
// Check total gas limit for simulation
|
|
942
|
+
const gasSettings = tx.data.constants.txContext.gasSettings;
|
|
943
|
+
const txGasLimit = gasSettings.gasLimits.l2Gas;
|
|
944
|
+
const teardownGasLimit = gasSettings.teardownGasLimits.l2Gas;
|
|
945
|
+
if (txGasLimit + teardownGasLimit > this.config.rpcSimulatePublicMaxGasLimit) {
|
|
946
|
+
throw new BadRequestError(
|
|
947
|
+
`Transaction total gas limit ${
|
|
948
|
+
txGasLimit + teardownGasLimit
|
|
949
|
+
} (${txGasLimit} + ${teardownGasLimit}) exceeds maximum gas limit ${
|
|
950
|
+
this.config.rpcSimulatePublicMaxGasLimit
|
|
951
|
+
} for simulation`,
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
|
|
929
955
|
const txHash = await tx.getTxHash();
|
|
930
956
|
const blockNumber = (await this.blockSource.getBlockNumber()) + 1;
|
|
931
957
|
|
|
@@ -952,10 +978,15 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
952
978
|
|
|
953
979
|
const merkleTreeFork = await this.worldStateSynchronizer.fork();
|
|
954
980
|
try {
|
|
955
|
-
const processor = publicProcessorFactory.create(
|
|
981
|
+
const processor = publicProcessorFactory.create(
|
|
982
|
+
merkleTreeFork,
|
|
983
|
+
newGlobalVariables,
|
|
984
|
+
skipFeeEnforcement,
|
|
985
|
+
/*clientInitiatedSimulation*/ true,
|
|
986
|
+
);
|
|
956
987
|
|
|
957
988
|
// REFACTOR: Consider merging ProcessReturnValues into ProcessedTx
|
|
958
|
-
const [processedTxs, failedTxs, returns] = await processor.process([tx]);
|
|
989
|
+
const [processedTxs, failedTxs, _usedTxs, returns] = await processor.process([tx]);
|
|
959
990
|
// REFACTOR: Consider returning the error rather than throwing
|
|
960
991
|
if (failedTxs.length) {
|
|
961
992
|
this.log.warn(`Simulated tx ${txHash} fails: ${failedTxs[0].error}`, { txHash });
|
|
@@ -1068,6 +1099,55 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1068
1099
|
return Promise.resolve();
|
|
1069
1100
|
}
|
|
1070
1101
|
|
|
1102
|
+
public async rollbackTo(targetBlock: number, force?: boolean): Promise<void> {
|
|
1103
|
+
const archiver = this.blockSource as Archiver;
|
|
1104
|
+
if (!('rollbackTo' in archiver)) {
|
|
1105
|
+
throw new Error('Archiver implementation does not support rollbacks.');
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
const finalizedBlock = await archiver.getL2Tips().then(tips => tips.finalized.number);
|
|
1109
|
+
if (targetBlock < finalizedBlock) {
|
|
1110
|
+
if (force) {
|
|
1111
|
+
this.log.warn(`Clearing world state database to allow rolling back behind finalized block ${finalizedBlock}`);
|
|
1112
|
+
await this.worldStateSynchronizer.clear();
|
|
1113
|
+
await this.p2pClient.clear();
|
|
1114
|
+
} else {
|
|
1115
|
+
throw new Error(`Cannot rollback to block ${targetBlock} as it is before finalized ${finalizedBlock}`);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
try {
|
|
1120
|
+
this.log.info(`Pausing archiver and world state sync to start rollback`);
|
|
1121
|
+
await archiver.stop();
|
|
1122
|
+
await this.worldStateSynchronizer.stopSync();
|
|
1123
|
+
const currentBlock = await archiver.getBlockNumber();
|
|
1124
|
+
const blocksToUnwind = currentBlock - targetBlock;
|
|
1125
|
+
this.log.info(`Unwinding ${count(blocksToUnwind, 'block')} from L2 block ${currentBlock} to ${targetBlock}`);
|
|
1126
|
+
await archiver.rollbackTo(targetBlock);
|
|
1127
|
+
this.log.info(`Unwinding complete.`);
|
|
1128
|
+
} catch (err) {
|
|
1129
|
+
this.log.error(`Error during rollback`, err);
|
|
1130
|
+
throw err;
|
|
1131
|
+
} finally {
|
|
1132
|
+
this.log.info(`Resuming world state and archiver sync.`);
|
|
1133
|
+
this.worldStateSynchronizer.resumeSync();
|
|
1134
|
+
archiver.resume();
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
public async pauseSync(): Promise<void> {
|
|
1139
|
+
this.log.info(`Pausing archiver and world state sync`);
|
|
1140
|
+
await (this.blockSource as Archiver).stop();
|
|
1141
|
+
await this.worldStateSynchronizer.stopSync();
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
public resumeSync(): Promise<void> {
|
|
1145
|
+
this.log.info(`Resuming world state and archiver sync.`);
|
|
1146
|
+
this.worldStateSynchronizer.resumeSync();
|
|
1147
|
+
(this.blockSource as Archiver).resume();
|
|
1148
|
+
return Promise.resolve();
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1071
1151
|
/**
|
|
1072
1152
|
* Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
|
|
1073
1153
|
* @param blockNumber - The block number at which to get the data.
|
package/src/sentinel/sentinel.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
L2BlockStream,
|
|
11
11
|
type L2BlockStreamEvent,
|
|
12
12
|
type L2BlockStreamEventHandler,
|
|
13
|
+
getAttestationsFromPublishedL2Block,
|
|
13
14
|
} from '@aztec/stdlib/block';
|
|
14
15
|
import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
15
16
|
import type {
|
|
@@ -29,7 +30,8 @@ export class Sentinel implements L2BlockStreamEventHandler {
|
|
|
29
30
|
|
|
30
31
|
protected initialSlot: bigint | undefined;
|
|
31
32
|
protected lastProcessedSlot: bigint | undefined;
|
|
32
|
-
protected
|
|
33
|
+
protected slotNumberToBlock: Map<bigint, { blockNumber: number; archive: string; attestors: EthAddress[] }> =
|
|
34
|
+
new Map();
|
|
33
35
|
|
|
34
36
|
constructor(
|
|
35
37
|
protected epochCache: EpochCache,
|
|
@@ -63,19 +65,23 @@ export class Sentinel implements L2BlockStreamEventHandler {
|
|
|
63
65
|
public async handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void> {
|
|
64
66
|
await this.l2TipsStore.handleBlockStreamEvent(event);
|
|
65
67
|
if (event.type === 'blocks-added') {
|
|
66
|
-
// Store mapping from slot to archive
|
|
68
|
+
// Store mapping from slot to archive, block number, and attestors
|
|
67
69
|
for (const block of event.blocks) {
|
|
68
|
-
this.
|
|
70
|
+
this.slotNumberToBlock.set(block.block.header.getSlot(), {
|
|
71
|
+
blockNumber: block.block.number,
|
|
72
|
+
archive: block.block.archive.root.toString(),
|
|
73
|
+
attestors: getAttestationsFromPublishedL2Block(block).map(att => att.getSender()),
|
|
74
|
+
});
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
// Prune the archive map to only keep at most N entries
|
|
72
78
|
const historyLength = this.store.getHistoryLength();
|
|
73
|
-
if (this.
|
|
74
|
-
const toDelete = Array.from(this.
|
|
79
|
+
if (this.slotNumberToBlock.size > historyLength) {
|
|
80
|
+
const toDelete = Array.from(this.slotNumberToBlock.keys())
|
|
75
81
|
.sort((a, b) => Number(a - b))
|
|
76
|
-
.slice(0, this.
|
|
82
|
+
.slice(0, this.slotNumberToBlock.size - historyLength);
|
|
77
83
|
for (const key of toDelete) {
|
|
78
|
-
this.
|
|
84
|
+
this.slotNumberToBlock.delete(key);
|
|
79
85
|
}
|
|
80
86
|
}
|
|
81
87
|
}
|
|
@@ -171,16 +177,21 @@ export class Sentinel implements L2BlockStreamEventHandler {
|
|
|
171
177
|
|
|
172
178
|
// Here we get all attestations for the block mined at the given slot,
|
|
173
179
|
// or all attestations for all proposals in the slot if no block was mined.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const
|
|
180
|
+
// We gather from both p2p (contains the ones seen on the p2p layer) and archiver
|
|
181
|
+
// (contains the ones synced from mined blocks, which we may have missed from p2p).
|
|
182
|
+
const block = this.slotNumberToBlock.get(slot);
|
|
183
|
+
const p2pAttested = await this.p2p.getAttestationsForSlot(slot, block?.archive);
|
|
184
|
+
const attestors = new Set([
|
|
185
|
+
...p2pAttested.map(a => a.getSender().toString()),
|
|
186
|
+
...(block?.attestors.map(a => a.toString()) ?? []),
|
|
187
|
+
]);
|
|
177
188
|
|
|
178
189
|
// We assume that there was a block proposal if at least one of the validators attested to it.
|
|
179
190
|
// It could be the case that every single validator failed, and we could differentiate it by having
|
|
180
191
|
// this node re-execute every block proposal it sees and storing it in the attestation pool.
|
|
181
192
|
// But we'll leave that corner case out to reduce pressure on the node.
|
|
182
|
-
const blockStatus =
|
|
183
|
-
this.logger.debug(`Block for slot ${slot} was ${blockStatus}`, {
|
|
193
|
+
const blockStatus = block ? 'mined' : attestors.size > 0 ? 'proposed' : 'missed';
|
|
194
|
+
this.logger.debug(`Block for slot ${slot} was ${blockStatus}`, { ...block, slot });
|
|
184
195
|
|
|
185
196
|
// Get attestors that failed their duties for this block, but only if there was a block proposed
|
|
186
197
|
const missedAttestors = new Set(
|
|
@@ -192,7 +203,7 @@ export class Sentinel implements L2BlockStreamEventHandler {
|
|
|
192
203
|
this.logger.debug(`Retrieved ${attestors.size} attestors out of ${committee.length} for slot ${slot}`, {
|
|
193
204
|
blockStatus,
|
|
194
205
|
proposer: proposer.toString(),
|
|
195
|
-
|
|
206
|
+
...block,
|
|
196
207
|
slot,
|
|
197
208
|
attestors: [...attestors],
|
|
198
209
|
missedAttestors: [...missedAttestors],
|
|
@@ -266,7 +277,7 @@ export class Sentinel implements L2BlockStreamEventHandler {
|
|
|
266
277
|
const filteredHistory = relevantHistory.filter(h => h.status === filter);
|
|
267
278
|
return {
|
|
268
279
|
currentStreak: countWhile([...relevantHistory].reverse(), h => h.status === filter),
|
|
269
|
-
rate: filteredHistory.length / relevantHistory.length,
|
|
280
|
+
rate: relevantHistory.length === 0 ? undefined : filteredHistory.length / relevantHistory.length,
|
|
270
281
|
count: filteredHistory.length,
|
|
271
282
|
};
|
|
272
283
|
}
|
package/src/sentinel/store.ts
CHANGED
|
@@ -7,7 +7,10 @@ export class SentinelStore {
|
|
|
7
7
|
|
|
8
8
|
private readonly map: AztecAsyncMap<`0x${string}`, Buffer>;
|
|
9
9
|
|
|
10
|
-
constructor(
|
|
10
|
+
constructor(
|
|
11
|
+
private store: AztecAsyncKVStore,
|
|
12
|
+
private config: { historyLength: number },
|
|
13
|
+
) {
|
|
11
14
|
this.map = store.openMap('sentinel-validator-status');
|
|
12
15
|
}
|
|
13
16
|
|