@aztec/validator-client 0.0.1-commit.033589e → 0.0.1-commit.04852196a
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 +42 -0
- package/dest/block_proposal_handler.d.ts +2 -2
- package/dest/block_proposal_handler.d.ts.map +1 -1
- package/dest/block_proposal_handler.js +45 -26
- package/dest/checkpoint_builder.d.ts +8 -1
- package/dest/checkpoint_builder.d.ts.map +1 -1
- package/dest/checkpoint_builder.js +52 -7
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +22 -1
- package/dest/duties/validation_service.d.ts +1 -1
- package/dest/duties/validation_service.d.ts.map +1 -1
- package/dest/duties/validation_service.js +2 -8
- package/dest/factory.js +1 -1
- package/dest/validator.d.ts +3 -3
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +37 -25
- package/package.json +19 -19
- package/src/block_proposal_handler.ts +52 -33
- package/src/checkpoint_builder.ts +67 -8
- package/src/config.ts +22 -1
- package/src/duties/validation_service.ts +2 -8
- package/src/factory.ts +1 -1
- package/src/validator.ts +34 -28
package/src/validator.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { AuthRequest, AuthResponse, BlockProposalValidator, ReqRespSubProtocol }
|
|
|
24
24
|
import { OffenseType, WANT_TO_SLASH_EVENT, type Watcher, type WatcherEmitter } from '@aztec/slasher';
|
|
25
25
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
26
26
|
import type { CommitteeAttestationsAndSigners, L2Block, L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
|
|
27
|
+
import { validateCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
27
28
|
import { getEpochAtSlot, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
28
29
|
import type {
|
|
29
30
|
CreateCheckpointProposalLastBlockData,
|
|
@@ -45,7 +46,7 @@ import type { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
|
45
46
|
import type { BlockHeader, CheckpointGlobalVariables, Tx } from '@aztec/stdlib/tx';
|
|
46
47
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
47
48
|
import { type TelemetryClient, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
48
|
-
import { createHASigner } from '@aztec/validator-ha-signer/factory';
|
|
49
|
+
import { createHASigner, createLocalSignerWithProtection } from '@aztec/validator-ha-signer/factory';
|
|
49
50
|
import { DutyType, type SigningContext } from '@aztec/validator-ha-signer/types';
|
|
50
51
|
import type { ValidatorHASigner } from '@aztec/validator-ha-signer/validator-ha-signer';
|
|
51
52
|
|
|
@@ -108,7 +109,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
108
109
|
private l1ToL2MessageSource: L1ToL2MessageSource,
|
|
109
110
|
private config: ValidatorClientFullConfig,
|
|
110
111
|
private blobClient: BlobClientInterface,
|
|
111
|
-
private
|
|
112
|
+
private slashingProtectionSigner: ValidatorHASigner,
|
|
112
113
|
private dateProvider: DateProvider = new DateProvider(),
|
|
113
114
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
114
115
|
log = createLogger('validator'),
|
|
@@ -200,7 +201,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
200
201
|
const metrics = new ValidatorMetrics(telemetry);
|
|
201
202
|
const blockProposalValidator = new BlockProposalValidator(epochCache, {
|
|
202
203
|
txsPermitted: !config.disableTransactions,
|
|
203
|
-
maxTxsPerBlock: config.
|
|
204
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock,
|
|
204
205
|
});
|
|
205
206
|
const blockProposalHandler = new BlockProposalHandler(
|
|
206
207
|
checkpointsBuilder,
|
|
@@ -217,18 +218,27 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
217
218
|
);
|
|
218
219
|
|
|
219
220
|
const nodeKeystoreAdapter = NodeKeystoreAdapter.fromKeyStoreManager(keyStoreManager);
|
|
220
|
-
let
|
|
221
|
-
let haSigner: ValidatorHASigner | undefined;
|
|
221
|
+
let slashingProtectionSigner: ValidatorHASigner;
|
|
222
222
|
if (config.haSigningEnabled) {
|
|
223
|
+
// Multi-node HA mode: use PostgreSQL-backed distributed locking.
|
|
223
224
|
// If maxStuckDutiesAgeMs is not explicitly set, compute it from Aztec slot duration
|
|
224
225
|
const haConfig = {
|
|
225
226
|
...config,
|
|
226
227
|
maxStuckDutiesAgeMs: config.maxStuckDutiesAgeMs ?? epochCache.getL1Constants().slotDuration * 2 * 1000,
|
|
227
228
|
};
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
({ signer: slashingProtectionSigner } = await createHASigner(haConfig, {
|
|
230
|
+
telemetryClient: telemetry,
|
|
231
|
+
dateProvider,
|
|
232
|
+
}));
|
|
233
|
+
} else {
|
|
234
|
+
// Single-node mode: use LMDB-backed local signing protection.
|
|
235
|
+
// This prevents double-signing if the node crashes and restarts mid-proposal.
|
|
236
|
+
({ signer: slashingProtectionSigner } = await createLocalSignerWithProtection(config, {
|
|
237
|
+
telemetryClient: telemetry,
|
|
238
|
+
dateProvider,
|
|
239
|
+
}));
|
|
231
240
|
}
|
|
241
|
+
const validatorKeyStore: ExtendedValidatorKeyStore = new HAKeyStore(nodeKeystoreAdapter, slashingProtectionSigner);
|
|
232
242
|
|
|
233
243
|
const validator = new ValidatorClient(
|
|
234
244
|
validatorKeyStore,
|
|
@@ -241,7 +251,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
241
251
|
l1ToL2MessageSource,
|
|
242
252
|
config,
|
|
243
253
|
blobClient,
|
|
244
|
-
|
|
254
|
+
slashingProtectionSigner,
|
|
245
255
|
dateProvider,
|
|
246
256
|
telemetry,
|
|
247
257
|
);
|
|
@@ -280,24 +290,8 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
280
290
|
}
|
|
281
291
|
|
|
282
292
|
public reloadKeystore(newManager: KeystoreManager): void {
|
|
283
|
-
if (this.config.haSigningEnabled && !this.haSigner) {
|
|
284
|
-
this.log.warn(
|
|
285
|
-
'HA signing is enabled in config but was not initialized at startup. ' +
|
|
286
|
-
'Restart the node to enable HA signing.',
|
|
287
|
-
);
|
|
288
|
-
} else if (!this.config.haSigningEnabled && this.haSigner) {
|
|
289
|
-
this.log.warn(
|
|
290
|
-
'HA signing was disabled via config update but the HA signer is still active. ' +
|
|
291
|
-
'Restart the node to fully disable HA signing.',
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
293
|
const newAdapter = NodeKeystoreAdapter.fromKeyStoreManager(newManager);
|
|
296
|
-
|
|
297
|
-
this.keyStore = new HAKeyStore(newAdapter, this.haSigner);
|
|
298
|
-
} else {
|
|
299
|
-
this.keyStore = newAdapter;
|
|
300
|
-
}
|
|
294
|
+
this.keyStore = new HAKeyStore(newAdapter, this.slashingProtectionSigner);
|
|
301
295
|
this.validationService = new ValidationService(this.keyStore, this.log.createChild('validation-service'));
|
|
302
296
|
}
|
|
303
297
|
|
|
@@ -519,11 +513,9 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
519
513
|
slotNumber,
|
|
520
514
|
archive: proposal.archive.toString(),
|
|
521
515
|
proposer: proposer.toString(),
|
|
522
|
-
txCount: proposal.txHashes.length,
|
|
523
516
|
};
|
|
524
517
|
this.log.info(`Received checkpoint proposal for slot ${slotNumber}`, {
|
|
525
518
|
...proposalInfo,
|
|
526
|
-
txHashes: proposal.txHashes.map(t => t.toString()),
|
|
527
519
|
fishermanMode: this.config.fishermanMode || false,
|
|
528
520
|
});
|
|
529
521
|
|
|
@@ -766,6 +758,20 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
766
758
|
return { isValid: false, reason: 'out_hash_mismatch' };
|
|
767
759
|
}
|
|
768
760
|
|
|
761
|
+
// Final round of validations on the checkpoint, just in case.
|
|
762
|
+
try {
|
|
763
|
+
validateCheckpoint(computedCheckpoint, {
|
|
764
|
+
rollupManaLimit: this.checkpointsBuilder.getConfig().rollupManaLimit,
|
|
765
|
+
maxDABlockGas: this.config.validateMaxDABlockGas,
|
|
766
|
+
maxL2BlockGas: this.config.validateMaxL2BlockGas,
|
|
767
|
+
maxTxsPerBlock: this.config.validateMaxTxsPerBlock,
|
|
768
|
+
maxTxsPerCheckpoint: this.config.validateMaxTxsPerCheckpoint,
|
|
769
|
+
});
|
|
770
|
+
} catch (err) {
|
|
771
|
+
this.log.warn(`Checkpoint validation failed: ${err}`, proposalInfo);
|
|
772
|
+
return { isValid: false, reason: 'checkpoint_validation_failed' };
|
|
773
|
+
}
|
|
774
|
+
|
|
769
775
|
this.log.verbose(`Checkpoint proposal validation successful for slot ${slot}`, proposalInfo);
|
|
770
776
|
return { isValid: true };
|
|
771
777
|
} finally {
|