@aztec/validator-ha-signer 0.0.1-commit.6d3c34e → 0.0.1-commit.7035c9bd6
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/README.md +50 -37
- package/dest/db/index.d.ts +2 -1
- package/dest/db/index.d.ts.map +1 -1
- package/dest/db/index.js +1 -0
- package/dest/db/lmdb.d.ts +66 -0
- package/dest/db/lmdb.d.ts.map +1 -0
- package/dest/db/lmdb.js +188 -0
- package/dest/db/postgres.d.ts +37 -6
- package/dest/db/postgres.d.ts.map +1 -1
- package/dest/db/postgres.js +86 -28
- package/dest/db/schema.d.ts +21 -10
- package/dest/db/schema.d.ts.map +1 -1
- package/dest/db/schema.js +49 -20
- package/dest/db/types.d.ts +109 -33
- package/dest/db/types.d.ts.map +1 -1
- package/dest/db/types.js +57 -8
- package/dest/errors.d.ts +9 -5
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +7 -4
- package/dest/factory.d.ts +42 -15
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +80 -15
- package/dest/metrics.d.ts +51 -0
- package/dest/metrics.d.ts.map +1 -0
- package/dest/metrics.js +103 -0
- package/dest/migrations.d.ts +1 -1
- package/dest/migrations.d.ts.map +1 -1
- package/dest/migrations.js +13 -2
- package/dest/slashing_protection_service.d.ts +25 -6
- package/dest/slashing_protection_service.d.ts.map +1 -1
- package/dest/slashing_protection_service.js +74 -22
- package/dest/test/pglite_pool.d.ts +92 -0
- package/dest/test/pglite_pool.d.ts.map +1 -0
- package/dest/test/pglite_pool.js +210 -0
- package/dest/types.d.ts +40 -16
- package/dest/types.d.ts.map +1 -1
- package/dest/types.js +4 -1
- package/dest/validator_ha_signer.d.ts +18 -13
- package/dest/validator_ha_signer.d.ts.map +1 -1
- package/dest/validator_ha_signer.js +45 -36
- package/package.json +15 -10
- package/src/db/index.ts +1 -0
- package/src/db/lmdb.ts +264 -0
- package/src/db/postgres.ts +109 -27
- package/src/db/schema.ts +51 -20
- package/src/db/types.ts +166 -32
- package/src/errors.ts +7 -2
- package/src/factory.ts +99 -15
- package/src/metrics.ts +138 -0
- package/src/migrations.ts +17 -1
- package/src/slashing_protection_service.ts +119 -27
- package/src/test/pglite_pool.ts +256 -0
- package/src/types.ts +65 -16
- package/src/validator_ha_signer.ts +64 -45
- package/dest/config.d.ts +0 -47
- package/dest/config.d.ts.map +0 -1
- package/dest/config.js +0 -64
- package/src/config.ts +0 -116
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored pg-compatible Pool/Client wrapper for PGlite.
|
|
3
|
+
*
|
|
4
|
+
* Copied from @middle-management/pglite-pg-adapter v0.0.3
|
|
5
|
+
* https://www.npmjs.com/package/@middle-management/pglite-pg-adapter
|
|
6
|
+
*
|
|
7
|
+
* Modifications:
|
|
8
|
+
* - Converted to ESM and TypeScript
|
|
9
|
+
* - Uses PGliteInterface instead of PGlite class to avoid TypeScript
|
|
10
|
+
* type mismatches from ESM/CJS dual package resolution with private fields
|
|
11
|
+
* - Simplified rowCount calculation to handle CTEs properly
|
|
12
|
+
*/ import { EventEmitter } from 'events';
|
|
13
|
+
import { Readable, Writable } from 'stream';
|
|
14
|
+
export class Client extends EventEmitter {
|
|
15
|
+
pglite;
|
|
16
|
+
_connected = false;
|
|
17
|
+
host;
|
|
18
|
+
port;
|
|
19
|
+
ssl;
|
|
20
|
+
connection;
|
|
21
|
+
// Stub implementations for pg compatibility
|
|
22
|
+
copyFrom = ()=>new Writable();
|
|
23
|
+
copyTo = ()=>new Readable();
|
|
24
|
+
pauseDrain = ()=>{};
|
|
25
|
+
resumeDrain = ()=>{};
|
|
26
|
+
escapeLiteral = (str)=>`'${str.replace(/'/g, "''")}'`;
|
|
27
|
+
escapeIdentifier = (str)=>`"${str.replace(/"/g, '""')}"`;
|
|
28
|
+
setTypeParser = ()=>{};
|
|
29
|
+
getTypeParser = ()=>(value)=>value;
|
|
30
|
+
constructor(config){
|
|
31
|
+
super();
|
|
32
|
+
this.pglite = config.pglite;
|
|
33
|
+
this.host = config.host || 'localhost';
|
|
34
|
+
this.port = config.port || 5432;
|
|
35
|
+
this.ssl = typeof config.ssl === 'boolean' ? config.ssl : !!config.ssl;
|
|
36
|
+
this.connection = {};
|
|
37
|
+
}
|
|
38
|
+
connect() {
|
|
39
|
+
if (this._connected) {
|
|
40
|
+
return Promise.resolve();
|
|
41
|
+
}
|
|
42
|
+
this._connected = true;
|
|
43
|
+
this.emit('connect');
|
|
44
|
+
return Promise.resolve();
|
|
45
|
+
}
|
|
46
|
+
end() {
|
|
47
|
+
if (!this._connected) {
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
}
|
|
50
|
+
this._connected = false;
|
|
51
|
+
this.emit('end');
|
|
52
|
+
return Promise.resolve();
|
|
53
|
+
}
|
|
54
|
+
async query(text, values) {
|
|
55
|
+
if (!this._connected) {
|
|
56
|
+
throw new Error('Client is not connected');
|
|
57
|
+
}
|
|
58
|
+
const result = await this.pglite.query(text, values);
|
|
59
|
+
return this.convertPGliteResult(result);
|
|
60
|
+
}
|
|
61
|
+
convertPGliteResult(result) {
|
|
62
|
+
return {
|
|
63
|
+
command: '',
|
|
64
|
+
rowCount: 'affectedRows' in result ? result.affectedRows ?? 0 : result.rows.length,
|
|
65
|
+
oid: 0,
|
|
66
|
+
fields: result.fields.map((field)=>({
|
|
67
|
+
name: field.name,
|
|
68
|
+
tableID: 0,
|
|
69
|
+
columnID: 0,
|
|
70
|
+
dataTypeID: field.dataTypeID,
|
|
71
|
+
dataTypeSize: -1,
|
|
72
|
+
dataTypeModifier: -1,
|
|
73
|
+
format: 'text'
|
|
74
|
+
})),
|
|
75
|
+
rows: result.rows
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
get connected() {
|
|
79
|
+
return this._connected;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class Pool extends EventEmitter {
|
|
83
|
+
clients = [];
|
|
84
|
+
availableClients = [];
|
|
85
|
+
waitingQueue = [];
|
|
86
|
+
_ended = false;
|
|
87
|
+
pglite;
|
|
88
|
+
_config;
|
|
89
|
+
expiredCount = 0;
|
|
90
|
+
options;
|
|
91
|
+
constructor(config){
|
|
92
|
+
super();
|
|
93
|
+
this._config = {
|
|
94
|
+
max: 10,
|
|
95
|
+
min: 0,
|
|
96
|
+
...config
|
|
97
|
+
};
|
|
98
|
+
this.pglite = config.pglite;
|
|
99
|
+
this.options = config;
|
|
100
|
+
}
|
|
101
|
+
get totalCount() {
|
|
102
|
+
return this.clients.length;
|
|
103
|
+
}
|
|
104
|
+
get idleCount() {
|
|
105
|
+
return this.availableClients.length;
|
|
106
|
+
}
|
|
107
|
+
get waitingCount() {
|
|
108
|
+
return this.waitingQueue.length;
|
|
109
|
+
}
|
|
110
|
+
get ending() {
|
|
111
|
+
return this._ended;
|
|
112
|
+
}
|
|
113
|
+
get ended() {
|
|
114
|
+
return this._ended;
|
|
115
|
+
}
|
|
116
|
+
connect() {
|
|
117
|
+
if (this._ended) {
|
|
118
|
+
return Promise.reject(new Error('Pool is ended'));
|
|
119
|
+
}
|
|
120
|
+
if (this.availableClients.length > 0) {
|
|
121
|
+
const client = this.availableClients.pop();
|
|
122
|
+
client._markInUse();
|
|
123
|
+
return Promise.resolve(client);
|
|
124
|
+
}
|
|
125
|
+
if (this.clients.length < (this._config.max || 10)) {
|
|
126
|
+
const client = new PoolClient(this.pglite, this);
|
|
127
|
+
this.clients.push(client);
|
|
128
|
+
return Promise.resolve(client);
|
|
129
|
+
}
|
|
130
|
+
return new Promise((resolve)=>{
|
|
131
|
+
this.waitingQueue.push(resolve);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async query(text, values) {
|
|
135
|
+
const client = await this.connect();
|
|
136
|
+
try {
|
|
137
|
+
return await client.query(text, values);
|
|
138
|
+
} finally{
|
|
139
|
+
client.release();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
releaseClient(client) {
|
|
143
|
+
const index = this.clients.indexOf(client);
|
|
144
|
+
if (index !== -1) {
|
|
145
|
+
client._markAvailable();
|
|
146
|
+
if (this.waitingQueue.length > 0) {
|
|
147
|
+
const resolve = this.waitingQueue.shift();
|
|
148
|
+
client._markInUse();
|
|
149
|
+
resolve(client);
|
|
150
|
+
} else {
|
|
151
|
+
this.availableClients.push(client);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
end() {
|
|
156
|
+
this._ended = true;
|
|
157
|
+
this.clients.forEach((client)=>client._markReleased());
|
|
158
|
+
this.clients = [];
|
|
159
|
+
this.availableClients = [];
|
|
160
|
+
this.emit('end');
|
|
161
|
+
return Promise.resolve();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export class PoolClient extends Client {
|
|
165
|
+
pool;
|
|
166
|
+
_released = false;
|
|
167
|
+
_inUse = true;
|
|
168
|
+
_userReleased = false;
|
|
169
|
+
constructor(pglite, pool){
|
|
170
|
+
super({
|
|
171
|
+
pglite
|
|
172
|
+
});
|
|
173
|
+
this.pool = pool;
|
|
174
|
+
this._connected = true;
|
|
175
|
+
}
|
|
176
|
+
async query(text, values) {
|
|
177
|
+
if (this._userReleased && !this._inUse) {
|
|
178
|
+
throw new Error('Client has been released back to the pool');
|
|
179
|
+
}
|
|
180
|
+
const result = await this.pglite.query(text, values);
|
|
181
|
+
return this.convertPGliteResult(result);
|
|
182
|
+
}
|
|
183
|
+
release() {
|
|
184
|
+
if (this._released || this._userReleased) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
this._userReleased = true;
|
|
188
|
+
this.pool.releaseClient(this);
|
|
189
|
+
}
|
|
190
|
+
end() {
|
|
191
|
+
this.release();
|
|
192
|
+
return Promise.resolve();
|
|
193
|
+
}
|
|
194
|
+
_markInUse() {
|
|
195
|
+
this._inUse = true;
|
|
196
|
+
this._userReleased = false;
|
|
197
|
+
}
|
|
198
|
+
_markAvailable() {
|
|
199
|
+
this._inUse = false;
|
|
200
|
+
this._userReleased = false;
|
|
201
|
+
}
|
|
202
|
+
_markReleased() {
|
|
203
|
+
this._released = true;
|
|
204
|
+
this._inUse = false;
|
|
205
|
+
this._userReleased = true;
|
|
206
|
+
}
|
|
207
|
+
get connected() {
|
|
208
|
+
return this._connected && !this._released;
|
|
209
|
+
}
|
|
210
|
+
}
|
package/dest/types.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
4
|
+
import { DutyType, type HAProtectedSigningContext, type SigningContext, type ValidatorHASignerConfig, getBlockNumberFromSigningContext as getBlockNumberFromSigningContextFromStdlib, isHAProtectedContext } from '@aztec/stdlib/ha-signing';
|
|
5
|
+
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
2
6
|
import type { Pool } from 'pg';
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
export {
|
|
7
|
+
import type { BlockProposalDutyIdentifier, CheckAndRecordParams, DeleteDutyParams, DutyIdentifier, DutyRow, OtherDutyIdentifier, RecordSuccessParams, ValidatorDutyRecord } from './db/types.js';
|
|
8
|
+
export type { BlockProposalDutyIdentifier, CheckAndRecordParams, DeleteDutyParams, DutyIdentifier, DutyRow, HAProtectedSigningContext, OtherDutyIdentifier, RecordSuccessParams, SigningContext, ValidatorDutyRecord, ValidatorHASignerConfig, };
|
|
9
|
+
export { DutyStatus, DutyType, getBlockIndexFromDutyIdentifier, normalizeBlockIndex } from './db/types.js';
|
|
10
|
+
export { isHAProtectedContext };
|
|
11
|
+
export { getBlockNumberFromSigningContextFromStdlib as getBlockNumberFromSigningContext };
|
|
7
12
|
/**
|
|
8
13
|
* Result of tryInsertOrGetExisting operation
|
|
9
14
|
*/
|
|
@@ -22,18 +27,19 @@ export interface CreateHASignerDeps {
|
|
|
22
27
|
* If provided, databaseUrl and poolConfig are ignored
|
|
23
28
|
*/
|
|
24
29
|
pool?: Pool;
|
|
30
|
+
/**
|
|
31
|
+
* Optional telemetry client for metrics
|
|
32
|
+
*/
|
|
33
|
+
telemetryClient?: TelemetryClient;
|
|
34
|
+
/**
|
|
35
|
+
* Optional date provider for timestamps
|
|
36
|
+
*/
|
|
37
|
+
dateProvider?: DateProvider;
|
|
25
38
|
}
|
|
26
39
|
/**
|
|
27
|
-
*
|
|
40
|
+
* deps for creating a local signing protection signer
|
|
28
41
|
*/
|
|
29
|
-
export
|
|
30
|
-
/** Slot number for this duty */
|
|
31
|
-
slot: bigint;
|
|
32
|
-
/** Block number for this duty */
|
|
33
|
-
blockNumber: bigint;
|
|
34
|
-
/** Type of duty being performed */
|
|
35
|
-
dutyType: DutyType;
|
|
36
|
-
}
|
|
42
|
+
export type CreateLocalSignerWithProtectionDeps = Omit<CreateHASignerDeps, 'pool'>;
|
|
37
43
|
/**
|
|
38
44
|
* Database interface for slashing protection operations
|
|
39
45
|
* This abstraction allows for different database implementations (PostgreSQL, SQLite, etc.)
|
|
@@ -57,7 +63,7 @@ export interface SlashingProtectionDatabase {
|
|
|
57
63
|
*
|
|
58
64
|
* @returns true if the update succeeded, false if token didn't match or duty not found
|
|
59
65
|
*/
|
|
60
|
-
updateDutySigned(validatorAddress: EthAddress, slot:
|
|
66
|
+
updateDutySigned(rollupAddress: EthAddress, validatorAddress: EthAddress, slot: SlotNumber, dutyType: DutyType, signature: string, lockToken: string, blockIndexWithinCheckpoint: number): Promise<boolean>;
|
|
61
67
|
/**
|
|
62
68
|
* Delete a duty record.
|
|
63
69
|
* Only succeeds if the lockToken matches (caller must be the one who created the duty).
|
|
@@ -65,11 +71,29 @@ export interface SlashingProtectionDatabase {
|
|
|
65
71
|
*
|
|
66
72
|
* @returns true if the delete succeeded, false if token didn't match or duty not found
|
|
67
73
|
*/
|
|
68
|
-
deleteDuty(validatorAddress: EthAddress, slot:
|
|
74
|
+
deleteDuty(rollupAddress: EthAddress, validatorAddress: EthAddress, slot: SlotNumber, dutyType: DutyType, lockToken: string, blockIndexWithinCheckpoint: number): Promise<boolean>;
|
|
69
75
|
/**
|
|
70
76
|
* Cleanup own stuck duties
|
|
71
77
|
* @returns the number of duties cleaned up
|
|
72
78
|
*/
|
|
73
79
|
cleanupOwnStuckDuties(nodeId: string, maxAgeMs: number): Promise<number>;
|
|
80
|
+
/**
|
|
81
|
+
* Cleanup duties with outdated rollup address.
|
|
82
|
+
* Removes all duties where the rollup address doesn't match the current one.
|
|
83
|
+
* Used after a rollup upgrade to clean up duties for the old rollup.
|
|
84
|
+
* @returns the number of duties cleaned up
|
|
85
|
+
*/
|
|
86
|
+
cleanupOutdatedRollupDuties(currentRollupAddress: EthAddress): Promise<number>;
|
|
87
|
+
/**
|
|
88
|
+
* Cleanup old signed duties.
|
|
89
|
+
* Removes only signed duties older than the specified age.
|
|
90
|
+
* @returns the number of duties cleaned up
|
|
91
|
+
*/
|
|
92
|
+
cleanupOldDuties(maxAgeMs: number): Promise<number>;
|
|
93
|
+
/**
|
|
94
|
+
* Close the database connection.
|
|
95
|
+
* Should be called during graceful shutdown.
|
|
96
|
+
*/
|
|
97
|
+
close(): Promise<void>;
|
|
74
98
|
}
|
|
75
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
99
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDN0QsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sRUFDTCxRQUFRLEVBQ1IsS0FBSyx5QkFBeUIsRUFDOUIsS0FBSyxjQUFjLEVBQ25CLEtBQUssdUJBQXVCLEVBQzVCLGdDQUFnQyxJQUFJLDBDQUEwQyxFQUM5RSxvQkFBb0IsRUFDckIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRCxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFFL0IsT0FBTyxLQUFLLEVBQ1YsMkJBQTJCLEVBQzNCLG9CQUFvQixFQUNwQixnQkFBZ0IsRUFDaEIsY0FBYyxFQUNkLE9BQU8sRUFDUCxtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLG1CQUFtQixFQUNwQixNQUFNLGVBQWUsQ0FBQztBQUV2QixZQUFZLEVBQ1YsMkJBQTJCLEVBQzNCLG9CQUFvQixFQUNwQixnQkFBZ0IsRUFDaEIsY0FBYyxFQUNkLE9BQU8sRUFDUCx5QkFBeUIsRUFDekIsbUJBQW1CLEVBQ25CLG1CQUFtQixFQUNuQixjQUFjLEVBQ2QsbUJBQW1CLEVBQ25CLHVCQUF1QixHQUN4QixDQUFDO0FBQ0YsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsK0JBQStCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0csT0FBTyxFQUFFLG9CQUFvQixFQUFFLENBQUM7QUFDaEMsT0FBTyxFQUFFLDBDQUEwQyxJQUFJLGdDQUFnQyxFQUFFLENBQUM7QUFFMUY7O0dBRUc7QUFDSCxNQUFNLFdBQVcsb0JBQW9CO0lBQ25DLDJFQUEyRTtJQUMzRSxLQUFLLEVBQUUsT0FBTyxDQUFDO0lBQ2YscURBQXFEO0lBQ3JELE1BQU0sRUFBRSxtQkFBbUIsQ0FBQztDQUM3QjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxXQUFXLGtCQUFrQjtJQUNqQzs7O09BR0c7SUFDSCxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUM7SUFDWjs7T0FFRztJQUNILGVBQWUsQ0FBQyxFQUFFLGVBQWUsQ0FBQztJQUNsQzs7T0FFRztJQUNILFlBQVksQ0FBQyxFQUFFLFlBQVksQ0FBQztDQUM3QjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxNQUFNLG1DQUFtQyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUVuRjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sV0FBVywwQkFBMEI7SUFDekM7Ozs7O09BS0c7SUFDSCxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsb0JBQW9CLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFFcEY7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FDZCxhQUFhLEVBQUUsVUFBVSxFQUN6QixnQkFBZ0IsRUFBRSxVQUFVLEVBQzVCLElBQUksRUFBRSxVQUFVLEVBQ2hCLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLFNBQVMsRUFBRSxNQUFNLEVBQ2pCLFNBQVMsRUFBRSxNQUFNLEVBQ2pCLDBCQUEwQixFQUFFLE1BQU0sR0FDakMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRXBCOzs7Ozs7T0FNRztJQUNILFVBQVUsQ0FDUixhQUFhLEVBQUUsVUFBVSxFQUN6QixnQkFBZ0IsRUFBRSxVQUFVLEVBQzVCLElBQUksRUFBRSxVQUFVLEVBQ2hCLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLFNBQVMsRUFBRSxNQUFNLEVBQ2pCLDBCQUEwQixFQUFFLE1BQU0sR0FDakMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRXBCOzs7T0FHRztJQUNILHFCQUFxQixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFekU7Ozs7O09BS0c7SUFDSCwyQkFBMkIsQ0FBQyxvQkFBb0IsRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRS9FOzs7O09BSUc7SUFDSCxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUVwRDs7O09BR0c7SUFDSCxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQ3hCIn0=
|
package/dest/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,QAAQ,EACR,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,gCAAgC,IAAI,0CAA0C,EAC9E,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B,OAAO,KAAK,EACV,2BAA2B,EAC3B,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,2BAA2B,EAC3B,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,uBAAuB,GACxB,CAAC;AACF,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,+BAA+B,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC3G,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,OAAO,EAAE,0CAA0C,IAAI,gCAAgC,EAAE,CAAC;AAE1F;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,KAAK,EAAE,OAAO,CAAC;IACf,qDAAqD;IACrD,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ;;OAEG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,mCAAmC,GAAG,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;AAEnF;;;;;;;;GAQG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEpF;;;;;OAKG;IACH,gBAAgB,CACd,aAAa,EAAE,UAAU,EACzB,gBAAgB,EAAE,UAAU,EAC5B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,0BAA0B,EAAE,MAAM,GACjC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB;;;;;;OAMG;IACH,UAAU,CACR,aAAa,EAAE,UAAU,EACzB,gBAAgB,EAAE,UAAU,EAC5B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,0BAA0B,EAAE,MAAM,GACjC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB;;;OAGG;IACH,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzE;;;;;OAKG;IACH,2BAA2B,CAAC,oBAAoB,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/E;;;;OAIG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEpD;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
package/dest/types.js
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { getBlockNumberFromSigningContext as getBlockNumberFromSigningContextFromStdlib, isHAProtectedContext } from '@aztec/stdlib/ha-signing';
|
|
2
|
+
export { DutyStatus, DutyType, getBlockIndexFromDutyIdentifier, normalizeBlockIndex } from './db/types.js';
|
|
3
|
+
export { isHAProtectedContext };
|
|
4
|
+
export { getBlockNumberFromSigningContextFromStdlib as getBlockNumberFromSigningContext };
|
|
@@ -6,10 +6,16 @@
|
|
|
6
6
|
* node will sign for a given duty (slot + duty type).
|
|
7
7
|
*/
|
|
8
8
|
import type { Buffer32 } from '@aztec/foundation/buffer';
|
|
9
|
-
import
|
|
9
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
10
10
|
import type { Signature } from '@aztec/foundation/eth-signature';
|
|
11
|
-
import type {
|
|
12
|
-
import type
|
|
11
|
+
import type { DateProvider } from '@aztec/foundation/timer';
|
|
12
|
+
import { type BaseSignerConfig, type HAProtectedSigningContext } from '@aztec/stdlib/ha-signing';
|
|
13
|
+
import type { HASignerMetrics } from './metrics.js';
|
|
14
|
+
import type { SlashingProtectionDatabase } from './types.js';
|
|
15
|
+
export interface ValidatorHASignerDeps {
|
|
16
|
+
metrics: HASignerMetrics;
|
|
17
|
+
dateProvider: DateProvider;
|
|
18
|
+
}
|
|
13
19
|
/**
|
|
14
20
|
* Validator High Availability Signer
|
|
15
21
|
*
|
|
@@ -33,7 +39,10 @@ export declare class ValidatorHASigner {
|
|
|
33
39
|
private readonly config;
|
|
34
40
|
private readonly log;
|
|
35
41
|
private readonly slashingProtection;
|
|
36
|
-
|
|
42
|
+
private readonly rollupAddress;
|
|
43
|
+
private readonly dateProvider;
|
|
44
|
+
private readonly metrics;
|
|
45
|
+
constructor(db: SlashingProtectionDatabase, config: BaseSignerConfig, deps: ValidatorHASignerDeps);
|
|
37
46
|
/**
|
|
38
47
|
* Sign a message with slashing protection.
|
|
39
48
|
*
|
|
@@ -44,18 +53,14 @@ export declare class ValidatorHASigner {
|
|
|
44
53
|
*
|
|
45
54
|
* @param validatorAddress - The validator's Ethereum address
|
|
46
55
|
* @param messageHash - The hash to be signed
|
|
47
|
-
* @param context - The signing context (
|
|
56
|
+
* @param context - The signing context (HA-protected duty types only)
|
|
48
57
|
* @param signFn - Function that performs the actual signing
|
|
49
58
|
* @returns The signature
|
|
50
59
|
*
|
|
51
60
|
* @throws DutyAlreadySignedError if the duty was already signed (expected in HA)
|
|
52
61
|
* @throws SlashingProtectionError if attempting to sign different data for same slot (expected in HA)
|
|
53
62
|
*/
|
|
54
|
-
signWithProtection(validatorAddress: EthAddress, messageHash: Buffer32, context:
|
|
55
|
-
/**
|
|
56
|
-
* Check if slashing protection is enabled
|
|
57
|
-
*/
|
|
58
|
-
get isEnabled(): boolean;
|
|
63
|
+
signWithProtection(validatorAddress: EthAddress, messageHash: Buffer32, context: HAProtectedSigningContext, signFn: (messageHash: Buffer32) => Promise<Signature>): Promise<Signature>;
|
|
59
64
|
/**
|
|
60
65
|
* Get the node ID for this signer
|
|
61
66
|
*/
|
|
@@ -64,11 +69,11 @@ export declare class ValidatorHASigner {
|
|
|
64
69
|
* Start the HA signer background tasks (cleanup of stuck duties).
|
|
65
70
|
* Should be called after construction and before signing operations.
|
|
66
71
|
*/
|
|
67
|
-
start(): void
|
|
72
|
+
start(): Promise<void>;
|
|
68
73
|
/**
|
|
69
|
-
* Stop the HA signer background tasks.
|
|
74
|
+
* Stop the HA signer background tasks and close database connection.
|
|
70
75
|
* Should be called during graceful shutdown.
|
|
71
76
|
*/
|
|
72
77
|
stop(): Promise<void>;
|
|
73
78
|
}
|
|
74
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yX2hhX3NpZ25lci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3ZhbGlkYXRvcl9oYV9zaWduZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBQ0gsT0FBTyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzNELE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRWpFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzVELE9BQU8sRUFDTCxLQUFLLGdCQUFnQixFQUVyQixLQUFLLHlCQUF5QixFQUUvQixNQUFNLDBCQUEwQixDQUFDO0FBR2xDLE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUVwRCxPQUFPLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUU3RCxNQUFNLFdBQVcscUJBQXFCO0lBQ3BDLE9BQU8sRUFBRSxlQUFlLENBQUM7SUFDekIsWUFBWSxFQUFFLFlBQVksQ0FBQztDQUM1QjtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxxQkFBYSxpQkFBaUI7SUFVMUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNO0lBVHpCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFTO0lBQzdCLE9BQU8sQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQTRCO0lBQy9ELE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFhO0lBRTNDLE9BQU8sQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFlO0lBQzVDLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFrQjtJQUUxQyxZQUNFLEVBQUUsRUFBRSwwQkFBMEIsRUFDYixNQUFNLEVBQUUsZ0JBQWdCLEVBQ3pDLElBQUksRUFBRSxxQkFBcUIsRUFtQjVCO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7T0FnQkc7SUFDRyxrQkFBa0IsQ0FDdEIsZ0JBQWdCLEVBQUUsVUFBVSxFQUM1QixXQUFXLEVBQUUsUUFBUSxFQUNyQixPQUFPLEVBQUUseUJBQXlCLEVBQ2xDLE1BQU0sRUFBRSxDQUFDLFdBQVcsRUFBRSxRQUFRLEtBQUssT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUNwRCxPQUFPLENBQUMsU0FBUyxDQUFDLENBdURwQjtJQUVEOztPQUVHO0lBQ0gsSUFBSSxNQUFNLElBQUksTUFBTSxDQUVuQjtJQUVEOzs7T0FHRztJQUNHLEtBQUssa0JBRVY7SUFFRDs7O09BR0c7SUFDRyxJQUFJLGtCQUdUO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator_ha_signer.d.ts","sourceRoot":"","sources":["../src/validator_ha_signer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"validator_ha_signer.d.ts","sourceRoot":"","sources":["../src/validator_ha_signer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,yBAAyB,EAE/B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,eAAe,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,iBAAiB;IAU1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IATzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4B;IAC/D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAa;IAE3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAE1C,YACE,EAAE,EAAE,0BAA0B,EACb,MAAM,EAAE,gBAAgB,EACzC,IAAI,EAAE,qBAAqB,EAmB5B;IAED;;;;;;;;;;;;;;;;OAgBG;IACG,kBAAkB,CACtB,gBAAgB,EAAE,UAAU,EAC5B,WAAW,EAAE,QAAQ,EACrB,OAAO,EAAE,yBAAyB,EAClC,MAAM,EAAE,CAAC,WAAW,EAAE,QAAQ,KAAK,OAAO,CAAC,SAAS,CAAC,GACpD,OAAO,CAAC,SAAS,CAAC,CAuDpB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;OAGG;IACG,KAAK,kBAEV;IAED;;;OAGG;IACG,IAAI,kBAGT;CACF"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* This ensures that even with multiple validator nodes running, only one
|
|
6
6
|
* node will sign for a given duty (slot + duty type).
|
|
7
7
|
*/ import { createLogger } from '@aztec/foundation/log';
|
|
8
|
+
import { DutyType, getBlockNumberFromSigningContext } from '@aztec/stdlib/ha-signing';
|
|
8
9
|
import { SlashingProtectionService } from './slashing_protection_service.js';
|
|
9
10
|
/**
|
|
10
11
|
* Validator High Availability Signer
|
|
@@ -28,19 +29,25 @@ import { SlashingProtectionService } from './slashing_protection_service.js';
|
|
|
28
29
|
config;
|
|
29
30
|
log;
|
|
30
31
|
slashingProtection;
|
|
31
|
-
|
|
32
|
+
rollupAddress;
|
|
33
|
+
dateProvider;
|
|
34
|
+
metrics;
|
|
35
|
+
constructor(db, config, deps){
|
|
32
36
|
this.config = config;
|
|
33
37
|
this.log = createLogger('validator-ha-signer');
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
throw new Error('Validator HA Signer is not enabled in config');
|
|
37
|
-
}
|
|
38
|
+
this.metrics = deps.metrics;
|
|
39
|
+
this.dateProvider = deps.dateProvider;
|
|
38
40
|
if (!config.nodeId || config.nodeId === '') {
|
|
39
41
|
throw new Error('NODE_ID is required for high-availability setups');
|
|
40
42
|
}
|
|
41
|
-
this.
|
|
43
|
+
this.rollupAddress = config.l1Contracts.rollupAddress;
|
|
44
|
+
this.slashingProtection = new SlashingProtectionService(db, config, {
|
|
45
|
+
metrics: deps.metrics,
|
|
46
|
+
dateProvider: deps.dateProvider
|
|
47
|
+
});
|
|
42
48
|
this.log.info('Validator HA Signer initialized with slashing protection', {
|
|
43
|
-
nodeId: config.nodeId
|
|
49
|
+
nodeId: config.nodeId,
|
|
50
|
+
rollupAddress: this.rollupAddress.toString()
|
|
44
51
|
});
|
|
45
52
|
}
|
|
46
53
|
/**
|
|
@@ -53,31 +60,38 @@ import { SlashingProtectionService } from './slashing_protection_service.js';
|
|
|
53
60
|
*
|
|
54
61
|
* @param validatorAddress - The validator's Ethereum address
|
|
55
62
|
* @param messageHash - The hash to be signed
|
|
56
|
-
* @param context - The signing context (
|
|
63
|
+
* @param context - The signing context (HA-protected duty types only)
|
|
57
64
|
* @param signFn - Function that performs the actual signing
|
|
58
65
|
* @returns The signature
|
|
59
66
|
*
|
|
60
67
|
* @throws DutyAlreadySignedError if the duty was already signed (expected in HA)
|
|
61
68
|
* @throws SlashingProtectionError if attempting to sign different data for same slot (expected in HA)
|
|
62
69
|
*/ async signWithProtection(validatorAddress, messageHash, context, signFn) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
const startTime = this.dateProvider.now();
|
|
71
|
+
const dutyType = context.dutyType;
|
|
72
|
+
let dutyIdentifier;
|
|
73
|
+
if (context.dutyType === DutyType.BLOCK_PROPOSAL) {
|
|
74
|
+
dutyIdentifier = {
|
|
75
|
+
rollupAddress: this.rollupAddress,
|
|
76
|
+
validatorAddress,
|
|
69
77
|
slot: context.slot,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
blockIndexWithinCheckpoint: context.blockIndexWithinCheckpoint,
|
|
79
|
+
dutyType: context.dutyType
|
|
80
|
+
};
|
|
81
|
+
} else {
|
|
82
|
+
dutyIdentifier = {
|
|
83
|
+
rollupAddress: this.rollupAddress,
|
|
84
|
+
validatorAddress,
|
|
85
|
+
slot: context.slot,
|
|
86
|
+
dutyType: context.dutyType
|
|
87
|
+
};
|
|
73
88
|
}
|
|
74
|
-
const { slot, blockNumber, dutyType } = context;
|
|
75
89
|
// Acquire lock and get the token for ownership verification
|
|
90
|
+
// DutyAlreadySignedError and SlashingProtectionError may be thrown here and are recorded in the service
|
|
91
|
+
const blockNumber = getBlockNumberFromSigningContext(context);
|
|
76
92
|
const lockToken = await this.slashingProtection.checkAndRecord({
|
|
77
|
-
|
|
78
|
-
slot,
|
|
93
|
+
...dutyIdentifier,
|
|
79
94
|
blockNumber,
|
|
80
|
-
dutyType,
|
|
81
95
|
messageHash: messageHash.toString(),
|
|
82
96
|
nodeId: this.config.nodeId
|
|
83
97
|
});
|
|
@@ -88,30 +102,24 @@ import { SlashingProtectionService } from './slashing_protection_service.js';
|
|
|
88
102
|
} catch (error) {
|
|
89
103
|
// Delete duty to allow retry (only succeeds if we own the lock)
|
|
90
104
|
await this.slashingProtection.deleteDuty({
|
|
91
|
-
|
|
92
|
-
slot,
|
|
93
|
-
dutyType,
|
|
105
|
+
...dutyIdentifier,
|
|
94
106
|
lockToken
|
|
95
107
|
});
|
|
108
|
+
this.metrics.recordSigningError(dutyType);
|
|
96
109
|
throw error;
|
|
97
110
|
}
|
|
98
111
|
// Record success (only succeeds if we own the lock)
|
|
99
112
|
await this.slashingProtection.recordSuccess({
|
|
100
|
-
|
|
101
|
-
slot,
|
|
102
|
-
dutyType,
|
|
113
|
+
...dutyIdentifier,
|
|
103
114
|
signature,
|
|
104
115
|
nodeId: this.config.nodeId,
|
|
105
116
|
lockToken
|
|
106
117
|
});
|
|
118
|
+
const duration = this.dateProvider.now() - startTime;
|
|
119
|
+
this.metrics.recordSigningSuccess(dutyType, duration);
|
|
107
120
|
return signature;
|
|
108
121
|
}
|
|
109
122
|
/**
|
|
110
|
-
* Check if slashing protection is enabled
|
|
111
|
-
*/ get isEnabled() {
|
|
112
|
-
return this.slashingProtection !== undefined;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
123
|
* Get the node ID for this signer
|
|
116
124
|
*/ get nodeId() {
|
|
117
125
|
return this.config.nodeId;
|
|
@@ -119,13 +127,14 @@ import { SlashingProtectionService } from './slashing_protection_service.js';
|
|
|
119
127
|
/**
|
|
120
128
|
* Start the HA signer background tasks (cleanup of stuck duties).
|
|
121
129
|
* Should be called after construction and before signing operations.
|
|
122
|
-
*/ start() {
|
|
123
|
-
this.slashingProtection
|
|
130
|
+
*/ async start() {
|
|
131
|
+
await this.slashingProtection.start();
|
|
124
132
|
}
|
|
125
133
|
/**
|
|
126
|
-
* Stop the HA signer background tasks.
|
|
134
|
+
* Stop the HA signer background tasks and close database connection.
|
|
127
135
|
* Should be called during graceful shutdown.
|
|
128
136
|
*/ async stop() {
|
|
129
|
-
await this.slashingProtection
|
|
137
|
+
await this.slashingProtection.stop();
|
|
138
|
+
await this.slashingProtection.close();
|
|
130
139
|
}
|
|
131
140
|
}
|
package/package.json
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/validator-ha-signer",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.7035c9bd6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
|
-
"./config": "./dest/config.js",
|
|
7
6
|
"./db": "./dest/db/index.js",
|
|
8
7
|
"./errors": "./dest/errors.js",
|
|
9
8
|
"./factory": "./dest/factory.js",
|
|
9
|
+
"./metrics": "./dest/metrics.js",
|
|
10
10
|
"./migrations": "./dest/migrations.js",
|
|
11
11
|
"./slashing-protection-service": "./dest/slashing_protection_service.js",
|
|
12
12
|
"./types": "./dest/types.js",
|
|
13
|
-
"./validator-ha-signer": "./dest/validator_ha_signer.js"
|
|
13
|
+
"./validator-ha-signer": "./dest/validator_ha_signer.js",
|
|
14
|
+
"./test": "./dest/test/pglite_pool.js",
|
|
15
|
+
"./db/lmdb": "./dest/db/lmdb.js"
|
|
14
16
|
},
|
|
15
17
|
"typedocOptions": {
|
|
16
18
|
"entryPoints": [
|
|
17
|
-
"./src/config.ts",
|
|
18
19
|
"./src/db/index.ts",
|
|
19
20
|
"./src/errors.ts",
|
|
20
21
|
"./src/factory.ts",
|
|
22
|
+
"./src/metrics.ts",
|
|
21
23
|
"./src/migrations.ts",
|
|
22
24
|
"./src/slashing_protection_service.ts",
|
|
23
25
|
"./src/types.ts",
|
|
@@ -73,21 +75,24 @@
|
|
|
73
75
|
]
|
|
74
76
|
},
|
|
75
77
|
"dependencies": {
|
|
76
|
-
"@aztec/
|
|
77
|
-
"@aztec/
|
|
78
|
+
"@aztec/ethereum": "0.0.1-commit.7035c9bd6",
|
|
79
|
+
"@aztec/foundation": "0.0.1-commit.7035c9bd6",
|
|
80
|
+
"@aztec/kv-store": "0.0.1-commit.7035c9bd6",
|
|
81
|
+
"@aztec/stdlib": "0.0.1-commit.7035c9bd6",
|
|
82
|
+
"@aztec/telemetry-client": "0.0.1-commit.7035c9bd6",
|
|
78
83
|
"node-pg-migrate": "^8.0.4",
|
|
79
84
|
"pg": "^8.11.3",
|
|
80
|
-
"tslib": "^2.4.0"
|
|
85
|
+
"tslib": "^2.4.0",
|
|
86
|
+
"zod": "^3.23.8"
|
|
81
87
|
},
|
|
82
88
|
"devDependencies": {
|
|
83
|
-
"@electric-sql/pglite": "^0.
|
|
89
|
+
"@electric-sql/pglite": "^0.3.14",
|
|
84
90
|
"@jest/globals": "^30.0.0",
|
|
85
|
-
"@middle-management/pglite-pg-adapter": "^0.0.3",
|
|
86
91
|
"@types/jest": "^30.0.0",
|
|
87
92
|
"@types/node": "^22.15.17",
|
|
88
93
|
"@types/node-pg-migrate": "^2.3.1",
|
|
89
94
|
"@types/pg": "^8.10.9",
|
|
90
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
95
|
+
"@typescript/native-preview": "7.0.0-dev.20260113.1",
|
|
91
96
|
"jest": "^30.0.0",
|
|
92
97
|
"jest-mock-extended": "^4.0.0",
|
|
93
98
|
"ts-node": "^10.9.1",
|
package/src/db/index.ts
CHANGED