@aztec/aztec-node 0.0.0-test.1 → 0.0.1-commit.b655e406
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 +14 -9
- package/dest/aztec-node/config.d.ts.map +1 -1
- package/dest/aztec-node/config.js +75 -14
- package/dest/aztec-node/node_metrics.d.ts +4 -0
- package/dest/aztec-node/node_metrics.d.ts.map +1 -1
- package/dest/aztec-node/node_metrics.js +21 -0
- package/dest/aztec-node/server.d.ts +90 -50
- package/dest/aztec-node/server.d.ts.map +1 -1
- package/dest/aztec-node/server.js +526 -218
- package/dest/bin/index.js +4 -2
- package/dest/index.d.ts +0 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +0 -1
- package/dest/sentinel/config.d.ts +8 -0
- package/dest/sentinel/config.d.ts.map +1 -0
- package/dest/sentinel/config.js +29 -0
- package/dest/sentinel/factory.d.ts +9 -0
- package/dest/sentinel/factory.d.ts.map +1 -0
- package/dest/sentinel/factory.js +17 -0
- package/dest/sentinel/index.d.ts +3 -0
- package/dest/sentinel/index.d.ts.map +1 -0
- package/dest/sentinel/index.js +1 -0
- package/dest/sentinel/sentinel.d.ts +91 -0
- package/dest/sentinel/sentinel.d.ts.map +1 -0
- package/dest/sentinel/sentinel.js +391 -0
- package/dest/sentinel/store.d.ts +34 -0
- package/dest/sentinel/store.d.ts.map +1 -0
- package/dest/sentinel/store.js +169 -0
- package/dest/test/index.d.ts +31 -0
- package/dest/test/index.d.ts.map +1 -0
- package/dest/test/index.js +1 -0
- package/package.json +42 -32
- package/src/aztec-node/config.ts +128 -25
- package/src/aztec-node/node_metrics.ts +28 -0
- package/src/aztec-node/server.ts +684 -278
- package/src/bin/index.ts +4 -2
- package/src/index.ts +0 -1
- package/src/sentinel/config.ts +37 -0
- package/src/sentinel/factory.ts +36 -0
- package/src/sentinel/index.ts +8 -0
- package/src/sentinel/sentinel.ts +489 -0
- package/src/sentinel/store.ts +184 -0
- package/src/test/index.ts +32 -0
- package/dest/aztec-node/http_rpc_server.d.ts +0 -8
- package/dest/aztec-node/http_rpc_server.d.ts.map +0 -1
- package/dest/aztec-node/http_rpc_server.js +0 -9
- package/src/aztec-node/http_rpc_server.ts +0 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sentinel/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,0BAA0B,CAAC;AAElC,qBAAa,aAAa;IAWtB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IAXhB,gBAAuB,cAAc,KAAK;IAG1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;IAIlE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;gBAGvD,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,+BAA+B,EAAE,MAAM,CAAA;KAAE;IAM7E,gBAAgB;IAIhB,kCAAkC;IAI5B,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B;IAQ9E,oBAAoB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;YAKjG,sCAAsC;IA6BvC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC;YAUhG,0BAA0B;IAY3B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAQtE,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;IAKzF,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,gBAAgB;CAgBzB"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import { BufferReader, numToUInt8, numToUInt32BE, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
3
|
+
export class SentinelStore {
|
|
4
|
+
store;
|
|
5
|
+
config;
|
|
6
|
+
static SCHEMA_VERSION = 2;
|
|
7
|
+
// a map from validator address to their ValidatorStatusHistory
|
|
8
|
+
historyMap;
|
|
9
|
+
// a map from validator address to their historical proven epoch performance
|
|
10
|
+
// e.g. { validator: [{ epoch: 1, missed: 1, total: 10 }, { epoch: 2, missed: 3, total: 7 }, ...] }
|
|
11
|
+
provenMap;
|
|
12
|
+
constructor(store, config){
|
|
13
|
+
this.store = store;
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.historyMap = store.openMap('sentinel-validator-status');
|
|
16
|
+
this.provenMap = store.openMap('sentinel-validator-proven');
|
|
17
|
+
}
|
|
18
|
+
getHistoryLength() {
|
|
19
|
+
return this.config.historyLength;
|
|
20
|
+
}
|
|
21
|
+
getHistoricProvenPerformanceLength() {
|
|
22
|
+
return this.config.historicProvenPerformanceLength;
|
|
23
|
+
}
|
|
24
|
+
async updateProvenPerformance(epoch, performance) {
|
|
25
|
+
await this.store.transactionAsync(async ()=>{
|
|
26
|
+
for (const [who, { missed, total }] of Object.entries(performance)){
|
|
27
|
+
await this.pushValidatorProvenPerformanceForEpoch({
|
|
28
|
+
who: EthAddress.fromString(who),
|
|
29
|
+
missed,
|
|
30
|
+
total,
|
|
31
|
+
epoch
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async getProvenPerformance(who) {
|
|
37
|
+
const currentPerformanceBuffer = await this.provenMap.getAsync(who.toString());
|
|
38
|
+
return currentPerformanceBuffer ? this.deserializePerformance(currentPerformanceBuffer) : [];
|
|
39
|
+
}
|
|
40
|
+
async pushValidatorProvenPerformanceForEpoch({ who, missed, total, epoch }) {
|
|
41
|
+
const currentPerformance = await this.getProvenPerformance(who);
|
|
42
|
+
const existingIndex = currentPerformance.findIndex((p)=>p.epoch === epoch);
|
|
43
|
+
if (existingIndex !== -1) {
|
|
44
|
+
currentPerformance[existingIndex] = {
|
|
45
|
+
missed,
|
|
46
|
+
total,
|
|
47
|
+
epoch
|
|
48
|
+
};
|
|
49
|
+
} else {
|
|
50
|
+
currentPerformance.push({
|
|
51
|
+
missed,
|
|
52
|
+
total,
|
|
53
|
+
epoch
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// This should be sorted by epoch, but just in case.
|
|
57
|
+
// Since we keep the size small, this is not a big deal.
|
|
58
|
+
currentPerformance.sort((a, b)=>Number(a.epoch - b.epoch));
|
|
59
|
+
// keep the most recent `historicProvenPerformanceLength` entries.
|
|
60
|
+
const performanceToKeep = currentPerformance.slice(-this.config.historicProvenPerformanceLength);
|
|
61
|
+
await this.provenMap.set(who.toString(), this.serializePerformance(performanceToKeep));
|
|
62
|
+
}
|
|
63
|
+
async updateValidators(slot, statuses) {
|
|
64
|
+
await this.store.transactionAsync(async ()=>{
|
|
65
|
+
for (const [who, status] of Object.entries(statuses)){
|
|
66
|
+
if (status) {
|
|
67
|
+
await this.pushValidatorStatusForSlot(EthAddress.fromString(who), slot, status);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async pushValidatorStatusForSlot(who, slot, status) {
|
|
73
|
+
await this.store.transactionAsync(async ()=>{
|
|
74
|
+
const currentHistory = await this.getHistory(who) ?? [];
|
|
75
|
+
const newHistory = [
|
|
76
|
+
...currentHistory,
|
|
77
|
+
{
|
|
78
|
+
slot,
|
|
79
|
+
status
|
|
80
|
+
}
|
|
81
|
+
].slice(-this.config.historyLength);
|
|
82
|
+
await this.historyMap.set(who.toString(), this.serializeHistory(newHistory));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
async getHistories() {
|
|
86
|
+
const histories = {};
|
|
87
|
+
for await (const [address, history] of this.historyMap.entriesAsync()){
|
|
88
|
+
histories[address] = this.deserializeHistory(history);
|
|
89
|
+
}
|
|
90
|
+
return histories;
|
|
91
|
+
}
|
|
92
|
+
async getHistory(address) {
|
|
93
|
+
const data = await this.historyMap.getAsync(address.toString());
|
|
94
|
+
return data && this.deserializeHistory(data);
|
|
95
|
+
}
|
|
96
|
+
serializePerformance(performance) {
|
|
97
|
+
return serializeToBuffer(performance.map((p)=>[
|
|
98
|
+
numToUInt32BE(Number(p.epoch)),
|
|
99
|
+
numToUInt32BE(p.missed),
|
|
100
|
+
numToUInt32BE(p.total)
|
|
101
|
+
]));
|
|
102
|
+
}
|
|
103
|
+
deserializePerformance(buffer) {
|
|
104
|
+
const reader = new BufferReader(buffer);
|
|
105
|
+
const performance = [];
|
|
106
|
+
while(!reader.isEmpty()){
|
|
107
|
+
performance.push({
|
|
108
|
+
epoch: BigInt(reader.readNumber()),
|
|
109
|
+
missed: reader.readNumber(),
|
|
110
|
+
total: reader.readNumber()
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return performance;
|
|
114
|
+
}
|
|
115
|
+
serializeHistory(history) {
|
|
116
|
+
return serializeToBuffer(history.map((h)=>[
|
|
117
|
+
numToUInt32BE(Number(h.slot)),
|
|
118
|
+
numToUInt8(this.statusToNumber(h.status))
|
|
119
|
+
]));
|
|
120
|
+
}
|
|
121
|
+
deserializeHistory(buffer) {
|
|
122
|
+
const reader = new BufferReader(buffer);
|
|
123
|
+
const history = [];
|
|
124
|
+
while(!reader.isEmpty()){
|
|
125
|
+
const slot = BigInt(reader.readNumber());
|
|
126
|
+
const status = this.statusFromNumber(reader.readUInt8());
|
|
127
|
+
history.push({
|
|
128
|
+
slot,
|
|
129
|
+
status
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return history;
|
|
133
|
+
}
|
|
134
|
+
statusToNumber(status) {
|
|
135
|
+
switch(status){
|
|
136
|
+
case 'block-mined':
|
|
137
|
+
return 1;
|
|
138
|
+
case 'block-proposed':
|
|
139
|
+
return 2;
|
|
140
|
+
case 'block-missed':
|
|
141
|
+
return 3;
|
|
142
|
+
case 'attestation-sent':
|
|
143
|
+
return 4;
|
|
144
|
+
case 'attestation-missed':
|
|
145
|
+
return 5;
|
|
146
|
+
default:
|
|
147
|
+
{
|
|
148
|
+
const _exhaustive = status;
|
|
149
|
+
throw new Error(`Unknown status: ${status}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
statusFromNumber(status) {
|
|
154
|
+
switch(status){
|
|
155
|
+
case 1:
|
|
156
|
+
return 'block-mined';
|
|
157
|
+
case 2:
|
|
158
|
+
return 'block-proposed';
|
|
159
|
+
case 3:
|
|
160
|
+
return 'block-missed';
|
|
161
|
+
case 4:
|
|
162
|
+
return 'attestation-sent';
|
|
163
|
+
case 5:
|
|
164
|
+
return 'attestation-missed';
|
|
165
|
+
default:
|
|
166
|
+
throw new Error(`Unknown status: ${status}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
+
import type { P2P } from '@aztec/p2p';
|
|
3
|
+
import { SequencerClient } from '@aztec/sequencer-client';
|
|
4
|
+
import { EpochPruneWatcher, type SlasherClientInterface } from '@aztec/slasher';
|
|
5
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
6
|
+
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
7
|
+
import type { L2LogsSource, Service, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
8
|
+
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
9
|
+
import type { GlobalVariableBuilder as GlobalVariableBuilderInterface } from '@aztec/stdlib/tx';
|
|
10
|
+
import type { AztecNodeConfig } from '../aztec-node/config.js';
|
|
11
|
+
import { AztecNodeService } from '../aztec-node/server.js';
|
|
12
|
+
import { Sentinel } from '../sentinel/sentinel.js';
|
|
13
|
+
export declare class TestAztecNodeService extends AztecNodeService {
|
|
14
|
+
config: AztecNodeConfig;
|
|
15
|
+
p2pClient: P2P;
|
|
16
|
+
blockSource: L2BlockSource & Partial<Service>;
|
|
17
|
+
logsSource: L2LogsSource;
|
|
18
|
+
contractDataSource: ContractDataSource;
|
|
19
|
+
l1ToL2MessageSource: L1ToL2MessageSource;
|
|
20
|
+
worldStateSynchronizer: WorldStateSynchronizer;
|
|
21
|
+
sequencer: SequencerClient | undefined;
|
|
22
|
+
slasherClient: SlasherClientInterface | undefined;
|
|
23
|
+
validatorsSentinel: Sentinel | undefined;
|
|
24
|
+
epochPruneWatcher: EpochPruneWatcher | undefined;
|
|
25
|
+
l1ChainId: number;
|
|
26
|
+
version: number;
|
|
27
|
+
globalVariableBuilder: GlobalVariableBuilderInterface;
|
|
28
|
+
epochCache: EpochCacheInterface;
|
|
29
|
+
packageVersion: string;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACrG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,IAAI,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,gBAAgB;IACjD,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,GAAG,CAAC;IACf,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,UAAU,EAAE,YAAY,CAAC;IACzB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,SAAS,EAAE,eAAe,GAAG,SAAS,CAAC;IACvC,aAAa,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAClD,kBAAkB,EAAE,QAAQ,GAAG,SAAS,CAAC;IACzC,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB,EAAE,8BAA8B,CAAC;IACtD,UAAU,EAAE,mBAAmB,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;CACvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { AztecNodeService } from '../aztec-node/server.js';
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/aztec-node",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1-commit.b655e406",
|
|
4
4
|
"main": "dest/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./dest/index.js",
|
|
8
|
-
"./config": "./dest/aztec-node/config.js"
|
|
8
|
+
"./config": "./dest/aztec-node/config.js",
|
|
9
|
+
"./sentinel": "./dest/aztec-node/sentinel.js",
|
|
10
|
+
"./test": "./dest/test/index.js"
|
|
9
11
|
},
|
|
10
12
|
"bin": "./dest/bin/index.js",
|
|
11
13
|
"typedocOptions": {
|
|
@@ -21,8 +23,6 @@
|
|
|
21
23
|
"build": "yarn clean && tsc -b",
|
|
22
24
|
"build:dev": "tsc -b --watch",
|
|
23
25
|
"clean": "rm -rf ./dest .tsbuildinfo",
|
|
24
|
-
"formatting": "run -T prettier --check ./src && run -T eslint ./src",
|
|
25
|
-
"formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
|
|
26
26
|
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
|
|
27
27
|
},
|
|
28
28
|
"inherits": [
|
|
@@ -59,39 +59,49 @@
|
|
|
59
59
|
"testTimeout": 120000,
|
|
60
60
|
"setupFiles": [
|
|
61
61
|
"../../foundation/src/jest/setup.mjs"
|
|
62
|
+
],
|
|
63
|
+
"testEnvironment": "../../foundation/src/jest/env.mjs",
|
|
64
|
+
"setupFilesAfterEnv": [
|
|
65
|
+
"../../foundation/src/jest/setupAfterEnv.mjs"
|
|
62
66
|
]
|
|
63
67
|
},
|
|
64
68
|
"dependencies": {
|
|
65
|
-
"@aztec/archiver": "0.0.
|
|
66
|
-
"@aztec/bb-prover": "0.0.
|
|
67
|
-
"@aztec/blob-sink": "0.0.
|
|
68
|
-
"@aztec/constants": "0.0.
|
|
69
|
-
"@aztec/epoch-cache": "0.0.
|
|
70
|
-
"@aztec/ethereum": "0.0.
|
|
71
|
-
"@aztec/foundation": "0.0.
|
|
72
|
-
"@aztec/kv-store": "0.0.
|
|
73
|
-
"@aztec/
|
|
74
|
-
"@aztec/
|
|
75
|
-
"@aztec/
|
|
76
|
-
"@aztec/
|
|
77
|
-
"@aztec/
|
|
78
|
-
"@aztec/
|
|
79
|
-
"@aztec/
|
|
80
|
-
"@aztec/
|
|
81
|
-
"@aztec/
|
|
82
|
-
"@aztec/
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
69
|
+
"@aztec/archiver": "0.0.1-commit.b655e406",
|
|
70
|
+
"@aztec/bb-prover": "0.0.1-commit.b655e406",
|
|
71
|
+
"@aztec/blob-sink": "0.0.1-commit.b655e406",
|
|
72
|
+
"@aztec/constants": "0.0.1-commit.b655e406",
|
|
73
|
+
"@aztec/epoch-cache": "0.0.1-commit.b655e406",
|
|
74
|
+
"@aztec/ethereum": "0.0.1-commit.b655e406",
|
|
75
|
+
"@aztec/foundation": "0.0.1-commit.b655e406",
|
|
76
|
+
"@aztec/kv-store": "0.0.1-commit.b655e406",
|
|
77
|
+
"@aztec/l1-artifacts": "0.0.1-commit.b655e406",
|
|
78
|
+
"@aztec/merkle-tree": "0.0.1-commit.b655e406",
|
|
79
|
+
"@aztec/node-keystore": "0.0.1-commit.b655e406",
|
|
80
|
+
"@aztec/node-lib": "0.0.1-commit.b655e406",
|
|
81
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.b655e406",
|
|
82
|
+
"@aztec/p2p": "0.0.1-commit.b655e406",
|
|
83
|
+
"@aztec/protocol-contracts": "0.0.1-commit.b655e406",
|
|
84
|
+
"@aztec/prover-client": "0.0.1-commit.b655e406",
|
|
85
|
+
"@aztec/sequencer-client": "0.0.1-commit.b655e406",
|
|
86
|
+
"@aztec/simulator": "0.0.1-commit.b655e406",
|
|
87
|
+
"@aztec/slasher": "0.0.1-commit.b655e406",
|
|
88
|
+
"@aztec/stdlib": "0.0.1-commit.b655e406",
|
|
89
|
+
"@aztec/telemetry-client": "0.0.1-commit.b655e406",
|
|
90
|
+
"@aztec/validator-client": "0.0.1-commit.b655e406",
|
|
91
|
+
"@aztec/world-state": "0.0.1-commit.b655e406",
|
|
92
|
+
"koa": "^2.16.1",
|
|
93
|
+
"koa-router": "^13.1.1",
|
|
94
|
+
"tslib": "^2.4.0",
|
|
95
|
+
"viem": "npm:@spalladino/viem@2.38.2-eip7594.0"
|
|
86
96
|
},
|
|
87
97
|
"devDependencies": {
|
|
88
|
-
"@jest/globals": "^
|
|
89
|
-
"@types/jest": "^
|
|
90
|
-
"@types/node": "^
|
|
91
|
-
"jest": "^
|
|
92
|
-
"jest-mock-extended": "^
|
|
98
|
+
"@jest/globals": "^30.0.0",
|
|
99
|
+
"@types/jest": "^30.0.0",
|
|
100
|
+
"@types/node": "^22.15.17",
|
|
101
|
+
"jest": "^30.0.0",
|
|
102
|
+
"jest-mock-extended": "^4.0.0",
|
|
93
103
|
"ts-node": "^10.9.1",
|
|
94
|
-
"typescript": "^5.
|
|
104
|
+
"typescript": "^5.3.3"
|
|
95
105
|
},
|
|
96
106
|
"files": [
|
|
97
107
|
"dest",
|
|
@@ -100,6 +110,6 @@
|
|
|
100
110
|
],
|
|
101
111
|
"types": "./dest/index.d.ts",
|
|
102
112
|
"engines": {
|
|
103
|
-
"node": ">=
|
|
113
|
+
"node": ">=20.10"
|
|
104
114
|
}
|
|
105
115
|
}
|
package/src/aztec-node/config.ts
CHANGED
|
@@ -1,15 +1,37 @@
|
|
|
1
1
|
import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config';
|
|
2
|
+
import {
|
|
3
|
+
type GenesisStateConfig,
|
|
4
|
+
type L1ContractAddresses,
|
|
5
|
+
genesisStateConfigMappings,
|
|
6
|
+
l1ContractAddressesMapping,
|
|
7
|
+
} from '@aztec/ethereum';
|
|
2
8
|
import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config';
|
|
9
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
10
|
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
|
|
11
|
+
import {
|
|
12
|
+
type KeyStore,
|
|
13
|
+
type ValidatorKeyStore,
|
|
14
|
+
ethPrivateKeySchema,
|
|
15
|
+
keyStoreConfigMappings,
|
|
16
|
+
} from '@aztec/node-keystore';
|
|
17
|
+
import { type SharedNodeConfig, sharedNodeConfigMappings } from '@aztec/node-lib/config';
|
|
4
18
|
import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
|
|
5
|
-
import { type
|
|
6
|
-
import {
|
|
19
|
+
import { type ProverClientUserConfig, proverClientConfigMappings } from '@aztec/prover-client/config';
|
|
20
|
+
import {
|
|
21
|
+
type SequencerClientConfig,
|
|
22
|
+
type TxSenderConfig,
|
|
23
|
+
sequencerClientConfigMappings,
|
|
24
|
+
} from '@aztec/sequencer-client/config';
|
|
25
|
+
import { slasherConfigMappings } from '@aztec/slasher';
|
|
26
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
27
|
+
import { type NodeRPCConfig, nodeRpcConfigMappings } from '@aztec/stdlib/config';
|
|
28
|
+
import type { SlasherConfig } from '@aztec/stdlib/interfaces/server';
|
|
7
29
|
import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client/config';
|
|
8
30
|
import { type WorldStateConfig, worldStateConfigMappings } from '@aztec/world-state/config';
|
|
9
31
|
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
import {
|
|
32
|
+
import { privateKeyToAddress } from 'viem/accounts';
|
|
33
|
+
|
|
34
|
+
import { type SentinelConfig, sentinelConfigMappings } from '../sentinel/config.js';
|
|
13
35
|
|
|
14
36
|
export { sequencerClientConfigMappings, type SequencerClientConfig };
|
|
15
37
|
|
|
@@ -19,34 +41,51 @@ export { sequencerClientConfigMappings, type SequencerClientConfig };
|
|
|
19
41
|
export type AztecNodeConfig = ArchiverConfig &
|
|
20
42
|
SequencerClientConfig &
|
|
21
43
|
ValidatorClientConfig &
|
|
22
|
-
|
|
44
|
+
ProverClientUserConfig &
|
|
23
45
|
WorldStateConfig &
|
|
24
|
-
Pick<
|
|
46
|
+
Pick<ProverClientUserConfig, 'bbBinaryPath' | 'bbWorkingDirectory' | 'realProofs'> &
|
|
25
47
|
P2PConfig &
|
|
26
|
-
DataStoreConfig &
|
|
48
|
+
DataStoreConfig &
|
|
49
|
+
SentinelConfig &
|
|
50
|
+
SharedNodeConfig &
|
|
51
|
+
GenesisStateConfig &
|
|
52
|
+
NodeRPCConfig &
|
|
53
|
+
SlasherConfig & {
|
|
54
|
+
/** L1 contracts addresses */
|
|
55
|
+
l1Contracts: L1ContractAddresses;
|
|
27
56
|
/** Whether the validator is disabled for this node */
|
|
28
57
|
disableValidator: boolean;
|
|
29
|
-
/** Whether to
|
|
30
|
-
|
|
58
|
+
/** Whether to skip waiting for the archiver to be fully synced before starting other services */
|
|
59
|
+
skipArchiverInitialSync: boolean;
|
|
31
60
|
};
|
|
32
61
|
|
|
33
62
|
export const aztecNodeConfigMappings: ConfigMappingsType<AztecNodeConfig> = {
|
|
63
|
+
...dataConfigMappings,
|
|
64
|
+
...keyStoreConfigMappings,
|
|
34
65
|
...archiverConfigMappings,
|
|
35
66
|
...sequencerClientConfigMappings,
|
|
36
67
|
...validatorClientConfigMappings,
|
|
37
68
|
...proverClientConfigMappings,
|
|
38
69
|
...worldStateConfigMappings,
|
|
39
70
|
...p2pConfigMappings,
|
|
40
|
-
...
|
|
71
|
+
...sentinelConfigMappings,
|
|
72
|
+
...sharedNodeConfigMappings,
|
|
73
|
+
...genesisStateConfigMappings,
|
|
74
|
+
...nodeRpcConfigMappings,
|
|
75
|
+
...slasherConfigMappings,
|
|
76
|
+
l1Contracts: {
|
|
77
|
+
description: 'The deployed L1 contract addresses',
|
|
78
|
+
nested: l1ContractAddressesMapping,
|
|
79
|
+
},
|
|
41
80
|
disableValidator: {
|
|
42
81
|
env: 'VALIDATOR_DISABLED',
|
|
43
82
|
description: 'Whether the validator is disabled for this node.',
|
|
44
83
|
...booleanConfigHelper(),
|
|
45
84
|
},
|
|
46
|
-
|
|
47
|
-
env: '
|
|
48
|
-
description: 'Whether to
|
|
49
|
-
...booleanConfigHelper(),
|
|
85
|
+
skipArchiverInitialSync: {
|
|
86
|
+
env: 'SKIP_ARCHIVER_INITIAL_SYNC',
|
|
87
|
+
description: 'Whether to skip waiting for the archiver to be fully synced before starting other services.',
|
|
88
|
+
...booleanConfigHelper(false),
|
|
50
89
|
},
|
|
51
90
|
};
|
|
52
91
|
|
|
@@ -58,14 +97,78 @@ export function getConfigEnvVars(): AztecNodeConfig {
|
|
|
58
97
|
return getConfigFromMappings<AztecNodeConfig>(aztecNodeConfigMappings);
|
|
59
98
|
}
|
|
60
99
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
100
|
+
type ConfigRequiredToBuildKeyStore = TxSenderConfig & SequencerClientConfig & SharedNodeConfig & ValidatorClientConfig;
|
|
101
|
+
|
|
102
|
+
function createKeyStoreFromWeb3Signer(config: ConfigRequiredToBuildKeyStore): KeyStore | undefined {
|
|
103
|
+
const validatorKeyStores: ValidatorKeyStore[] = [];
|
|
104
|
+
|
|
105
|
+
if (
|
|
106
|
+
config.web3SignerUrl === undefined ||
|
|
107
|
+
config.web3SignerUrl.length === 0 ||
|
|
108
|
+
config.validatorAddresses === undefined ||
|
|
109
|
+
config.validatorAddresses.length === 0
|
|
110
|
+
) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
validatorKeyStores.push({
|
|
115
|
+
attester: config.validatorAddresses,
|
|
116
|
+
feeRecipient: config.feeRecipient ?? AztecAddress.ZERO,
|
|
117
|
+
coinbase: config.coinbase ?? config.validatorAddresses[0],
|
|
118
|
+
remoteSigner: config.web3SignerUrl,
|
|
119
|
+
publisher: config.publisherAddresses ?? [],
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const keyStore: KeyStore = {
|
|
123
|
+
schemaVersion: 1,
|
|
124
|
+
slasher: undefined,
|
|
125
|
+
prover: undefined,
|
|
126
|
+
remoteSigner: undefined,
|
|
127
|
+
validators: validatorKeyStores,
|
|
128
|
+
};
|
|
129
|
+
return keyStore;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function createKeyStoreFromPrivateKeys(config: ConfigRequiredToBuildKeyStore): KeyStore | undefined {
|
|
133
|
+
const validatorKeyStores: ValidatorKeyStore[] = [];
|
|
134
|
+
const ethPrivateKeys = config.validatorPrivateKeys
|
|
135
|
+
? config.validatorPrivateKeys.getValue().map(x => ethPrivateKeySchema.parse(x))
|
|
136
|
+
: [];
|
|
137
|
+
|
|
138
|
+
if (!ethPrivateKeys.length) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
const coinbase = config.coinbase ?? EthAddress.fromString(privateKeyToAddress(ethPrivateKeys[0]));
|
|
142
|
+
const feeRecipient = config.feeRecipient ?? AztecAddress.ZERO;
|
|
143
|
+
|
|
144
|
+
const publisherKeys = config.publisherPrivateKeys
|
|
145
|
+
? config.publisherPrivateKeys.map(k => ethPrivateKeySchema.parse(k.getValue()))
|
|
146
|
+
: [];
|
|
147
|
+
|
|
148
|
+
validatorKeyStores.push({
|
|
149
|
+
attester: ethPrivateKeys,
|
|
150
|
+
feeRecipient: feeRecipient,
|
|
151
|
+
coinbase: coinbase,
|
|
152
|
+
remoteSigner: undefined,
|
|
153
|
+
publisher: publisherKeys,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const keyStore: KeyStore = {
|
|
157
|
+
schemaVersion: 1,
|
|
158
|
+
slasher: undefined,
|
|
159
|
+
prover: undefined,
|
|
160
|
+
remoteSigner: undefined,
|
|
161
|
+
validators: validatorKeyStores,
|
|
162
|
+
};
|
|
163
|
+
return keyStore;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function createKeyStoreForValidator(
|
|
167
|
+
config: TxSenderConfig & SequencerClientConfig & SharedNodeConfig,
|
|
168
|
+
): KeyStore | undefined {
|
|
169
|
+
if (config.web3SignerUrl !== undefined && config.web3SignerUrl.length > 0) {
|
|
170
|
+
return createKeyStoreFromWeb3Signer(config);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return createKeyStoreFromPrivateKeys(config);
|
|
71
174
|
}
|
|
@@ -11,6 +11,9 @@ export class NodeMetrics {
|
|
|
11
11
|
private receiveTxCount: UpDownCounter;
|
|
12
12
|
private receiveTxDuration: Histogram;
|
|
13
13
|
|
|
14
|
+
private snapshotErrorCount: UpDownCounter;
|
|
15
|
+
private snapshotDuration: Histogram;
|
|
16
|
+
|
|
14
17
|
constructor(client: TelemetryClient, name = 'AztecNode') {
|
|
15
18
|
const meter = client.getMeter(name);
|
|
16
19
|
this.receiveTxCount = meter.createUpDownCounter(Metrics.NODE_RECEIVE_TX_COUNT, {});
|
|
@@ -19,6 +22,19 @@ export class NodeMetrics {
|
|
|
19
22
|
unit: 'ms',
|
|
20
23
|
valueType: ValueType.INT,
|
|
21
24
|
});
|
|
25
|
+
|
|
26
|
+
this.snapshotDuration = meter.createHistogram(Metrics.NODE_SNAPSHOT_DURATION, {
|
|
27
|
+
description: 'How long taking a snapshot takes',
|
|
28
|
+
unit: 'ms',
|
|
29
|
+
valueType: ValueType.INT,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
this.snapshotErrorCount = meter.createUpDownCounter(Metrics.NODE_SNAPSHOT_ERROR_COUNT, {
|
|
33
|
+
description: 'How many snapshot errors have happened',
|
|
34
|
+
valueType: ValueType.INT,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
this.snapshotErrorCount.add(0);
|
|
22
38
|
}
|
|
23
39
|
|
|
24
40
|
receivedTx(durationMs: number, isAccepted: boolean) {
|
|
@@ -29,4 +45,16 @@ export class NodeMetrics {
|
|
|
29
45
|
[Attributes.OK]: isAccepted,
|
|
30
46
|
});
|
|
31
47
|
}
|
|
48
|
+
|
|
49
|
+
recordSnapshot(durationMs: number) {
|
|
50
|
+
if (isNaN(durationMs)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.snapshotDuration.record(Math.ceil(durationMs));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
recordSnapshotError() {
|
|
58
|
+
this.snapshotErrorCount.add(1);
|
|
59
|
+
}
|
|
32
60
|
}
|