@aztec/validator-client 0.0.1-commit.0c875d939 → 0.0.1-commit.10bd49492
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 +5 -4
- package/dest/block_proposal_handler.d.ts.map +1 -1
- package/dest/block_proposal_handler.js +121 -61
- package/dest/checkpoint_builder.d.ts +13 -3
- package/dest/checkpoint_builder.d.ts.map +1 -1
- package/dest/checkpoint_builder.js +71 -18
- 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.d.ts +1 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +2 -1
- package/dest/index.d.ts +1 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +0 -1
- package/dest/key_store/ha_key_store.js +1 -1
- package/dest/metrics.d.ts +9 -1
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +12 -0
- package/dest/validator.d.ts +12 -4
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +73 -21
- package/package.json +19 -19
- package/src/block_proposal_handler.ts +148 -80
- package/src/checkpoint_builder.ts +83 -14
- package/src/config.ts +22 -1
- package/src/duties/validation_service.ts +2 -8
- package/src/factory.ts +1 -0
- package/src/index.ts +0 -1
- package/src/key_store/ha_key_store.ts +1 -1
- package/src/metrics.ts +18 -0
- package/src/validator.ts +73 -20
- package/dest/tx_validator/index.d.ts +0 -3
- package/dest/tx_validator/index.d.ts.map +0 -1
- package/dest/tx_validator/index.js +0 -2
- package/dest/tx_validator/nullifier_cache.d.ts +0 -14
- package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
- package/dest/tx_validator/nullifier_cache.js +0 -24
- package/dest/tx_validator/tx_validator_factory.d.ts +0 -19
- package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
- package/dest/tx_validator/tx_validator_factory.js +0 -54
- package/src/tx_validator/index.ts +0 -2
- package/src/tx_validator/nullifier_cache.ts +0 -30
- package/src/tx_validator/tx_validator_factory.ts +0 -154
package/dest/validator.js
CHANGED
|
@@ -9,11 +9,12 @@ import { sleep } from '@aztec/foundation/sleep';
|
|
|
9
9
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
10
10
|
import { AuthRequest, AuthResponse, BlockProposalValidator, ReqRespSubProtocol } from '@aztec/p2p';
|
|
11
11
|
import { OffenseType, WANT_TO_SLASH_EVENT } from '@aztec/slasher';
|
|
12
|
+
import { validateCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
12
13
|
import { getEpochAtSlot, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
13
14
|
import { accumulateCheckpointOutHashes } from '@aztec/stdlib/messaging';
|
|
14
15
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
15
16
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
16
|
-
import { createHASigner } from '@aztec/validator-ha-signer/factory';
|
|
17
|
+
import { createHASigner, createLocalSignerWithProtection } from '@aztec/validator-ha-signer/factory';
|
|
17
18
|
import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
18
19
|
import { EventEmitter } from 'events';
|
|
19
20
|
import { BlockProposalHandler } from './block_proposal_handler.js';
|
|
@@ -42,6 +43,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
42
43
|
l1ToL2MessageSource;
|
|
43
44
|
config;
|
|
44
45
|
blobClient;
|
|
46
|
+
slashingProtectionSigner;
|
|
45
47
|
dateProvider;
|
|
46
48
|
tracer;
|
|
47
49
|
validationService;
|
|
@@ -53,10 +55,11 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
53
55
|
/** Tracks the last checkpoint proposal we created. */ lastProposedCheckpoint;
|
|
54
56
|
lastEpochForCommitteeUpdateLoop;
|
|
55
57
|
epochCacheUpdateLoop;
|
|
58
|
+
/** Tracks the last epoch in which each attester successfully submitted at least one attestation. */ lastAttestedEpochByAttester;
|
|
56
59
|
proposersOfInvalidBlocks;
|
|
57
60
|
/** Tracks the last checkpoint proposal we attested to, to prevent equivocation. */ lastAttestedProposal;
|
|
58
|
-
constructor(keyStore, epochCache, p2pClient, blockProposalHandler, blockSource, checkpointsBuilder, worldState, l1ToL2MessageSource, config, blobClient, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator')){
|
|
59
|
-
super(), this.keyStore = keyStore, this.epochCache = epochCache, this.p2pClient = p2pClient, this.blockProposalHandler = blockProposalHandler, this.blockSource = blockSource, this.checkpointsBuilder = checkpointsBuilder, this.worldState = worldState, this.l1ToL2MessageSource = l1ToL2MessageSource, this.config = config, this.blobClient = blobClient, this.dateProvider = dateProvider, this.hasRegisteredHandlers = false, this.proposersOfInvalidBlocks = new Set();
|
|
61
|
+
constructor(keyStore, epochCache, p2pClient, blockProposalHandler, blockSource, checkpointsBuilder, worldState, l1ToL2MessageSource, config, blobClient, slashingProtectionSigner, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator')){
|
|
62
|
+
super(), this.keyStore = keyStore, this.epochCache = epochCache, this.p2pClient = p2pClient, this.blockProposalHandler = blockProposalHandler, this.blockSource = blockSource, this.checkpointsBuilder = checkpointsBuilder, this.worldState = worldState, this.l1ToL2MessageSource = l1ToL2MessageSource, this.config = config, this.blobClient = blobClient, this.slashingProtectionSigner = slashingProtectionSigner, this.dateProvider = dateProvider, this.hasRegisteredHandlers = false, this.lastAttestedEpochByAttester = new Map(), this.proposersOfInvalidBlocks = new Set();
|
|
60
63
|
// Create child logger with fisherman prefix if in fisherman mode
|
|
61
64
|
this.log = config.fishermanMode ? log.createChild('[FISHERMAN]') : log;
|
|
62
65
|
this.tracer = telemetry.getTracer('Validator');
|
|
@@ -95,6 +98,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
95
98
|
this.log.trace(`No committee found for slot`);
|
|
96
99
|
return;
|
|
97
100
|
}
|
|
101
|
+
this.metrics.setCurrentEpoch(epoch);
|
|
98
102
|
if (epoch !== this.lastEpochForCommitteeUpdateLoop) {
|
|
99
103
|
const me = this.getValidatorAddresses();
|
|
100
104
|
const committeeSet = new Set(committee.map((v)=>v.toString()));
|
|
@@ -113,20 +117,33 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
113
117
|
static async new(config, checkpointsBuilder, worldState, epochCache, p2pClient, blockSource, l1ToL2MessageSource, txProvider, keyStoreManager, blobClient, dateProvider = new DateProvider(), telemetry = getTelemetryClient()) {
|
|
114
118
|
const metrics = new ValidatorMetrics(telemetry);
|
|
115
119
|
const blockProposalValidator = new BlockProposalValidator(epochCache, {
|
|
116
|
-
txsPermitted: !config.disableTransactions
|
|
120
|
+
txsPermitted: !config.disableTransactions,
|
|
121
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock
|
|
117
122
|
});
|
|
118
123
|
const blockProposalHandler = new BlockProposalHandler(checkpointsBuilder, worldState, blockSource, l1ToL2MessageSource, txProvider, blockProposalValidator, epochCache, config, metrics, dateProvider, telemetry);
|
|
119
|
-
|
|
124
|
+
const nodeKeystoreAdapter = NodeKeystoreAdapter.fromKeyStoreManager(keyStoreManager);
|
|
125
|
+
let slashingProtectionSigner;
|
|
120
126
|
if (config.haSigningEnabled) {
|
|
127
|
+
// Multi-node HA mode: use PostgreSQL-backed distributed locking.
|
|
121
128
|
// If maxStuckDutiesAgeMs is not explicitly set, compute it from Aztec slot duration
|
|
122
129
|
const haConfig = {
|
|
123
130
|
...config,
|
|
124
131
|
maxStuckDutiesAgeMs: config.maxStuckDutiesAgeMs ?? epochCache.getL1Constants().slotDuration * 2 * 1000
|
|
125
132
|
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
({ signer: slashingProtectionSigner } = await createHASigner(haConfig, {
|
|
134
|
+
telemetryClient: telemetry,
|
|
135
|
+
dateProvider
|
|
136
|
+
}));
|
|
137
|
+
} else {
|
|
138
|
+
// Single-node mode: use LMDB-backed local signing protection.
|
|
139
|
+
// This prevents double-signing if the node crashes and restarts mid-proposal.
|
|
140
|
+
({ signer: slashingProtectionSigner } = await createLocalSignerWithProtection(config, {
|
|
141
|
+
telemetryClient: telemetry,
|
|
142
|
+
dateProvider
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
const validatorKeyStore = new HAKeyStore(nodeKeystoreAdapter, slashingProtectionSigner);
|
|
146
|
+
const validator = new ValidatorClient(validatorKeyStore, epochCache, p2pClient, blockProposalHandler, blockSource, checkpointsBuilder, worldState, l1ToL2MessageSource, config, blobClient, slashingProtectionSigner, dateProvider, telemetry);
|
|
130
147
|
return validator;
|
|
131
148
|
}
|
|
132
149
|
getValidatorAddresses() {
|
|
@@ -153,6 +170,11 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
153
170
|
...config
|
|
154
171
|
};
|
|
155
172
|
}
|
|
173
|
+
reloadKeystore(newManager) {
|
|
174
|
+
const newAdapter = NodeKeystoreAdapter.fromKeyStoreManager(newManager);
|
|
175
|
+
this.keyStore = new HAKeyStore(newAdapter, this.slashingProtectionSigner);
|
|
176
|
+
this.validationService = new ValidationService(this.keyStore, this.log.createChild('validation-service'));
|
|
177
|
+
}
|
|
156
178
|
async start() {
|
|
157
179
|
if (this.epochCacheUpdateLoop.isRunning()) {
|
|
158
180
|
this.log.warn(`Validator client already started`);
|
|
@@ -215,7 +237,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
215
237
|
}
|
|
216
238
|
// Ignore proposals from ourselves (may happen in HA setups)
|
|
217
239
|
if (this.getValidatorAddresses().some((addr)=>addr.equals(proposer))) {
|
|
218
|
-
this.log.
|
|
240
|
+
this.log.debug(`Ignoring block proposal from self for slot ${slotNumber}`, {
|
|
219
241
|
proposer: proposer.toString(),
|
|
220
242
|
slotNumber
|
|
221
243
|
});
|
|
@@ -239,8 +261,8 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
239
261
|
const shouldReexecute = fishermanMode || slashBroadcastedInvalidBlockPenalty > 0n && validatorReexecute || partOfCommittee && validatorReexecute || alwaysReexecuteBlockProposals || this.blobClient.canUpload();
|
|
240
262
|
const validationResult = await this.blockProposalHandler.handleBlockProposal(proposal, proposalSender, !!shouldReexecute && !escapeHatchOpen);
|
|
241
263
|
if (!validationResult.isValid) {
|
|
242
|
-
this.log.warn(`Block proposal validation failed: ${validationResult.reason}`, proposalInfo);
|
|
243
264
|
const reason = validationResult.reason || 'unknown';
|
|
265
|
+
this.log.warn(`Block proposal validation failed: ${reason}`, proposalInfo);
|
|
244
266
|
// Classify failure reason: bad proposal vs node issue
|
|
245
267
|
const badProposalReasons = [
|
|
246
268
|
'invalid_proposal',
|
|
@@ -294,7 +316,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
294
316
|
}
|
|
295
317
|
// Ignore proposals from ourselves (may happen in HA setups)
|
|
296
318
|
if (this.getValidatorAddresses().some((addr)=>addr.equals(proposer))) {
|
|
297
|
-
this.log.
|
|
319
|
+
this.log.debug(`Ignoring block proposal from self for slot ${slotNumber}`, {
|
|
298
320
|
proposer: proposer.toString(),
|
|
299
321
|
slotNumber
|
|
300
322
|
});
|
|
@@ -311,12 +333,10 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
311
333
|
const proposalInfo = {
|
|
312
334
|
slotNumber,
|
|
313
335
|
archive: proposal.archive.toString(),
|
|
314
|
-
proposer: proposer.toString()
|
|
315
|
-
txCount: proposal.txHashes.length
|
|
336
|
+
proposer: proposer.toString()
|
|
316
337
|
};
|
|
317
338
|
this.log.info(`Received checkpoint proposal for slot ${slotNumber}`, {
|
|
318
339
|
...proposalInfo,
|
|
319
|
-
txHashes: proposal.txHashes.map((t)=>t.toString()),
|
|
320
340
|
fishermanMode: this.config.fishermanMode || false
|
|
321
341
|
});
|
|
322
342
|
// Validate the checkpoint proposal before attesting (unless skipCheckpointProposalValidation is set)
|
|
@@ -346,6 +366,16 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
346
366
|
fishermanMode: this.config.fishermanMode || false
|
|
347
367
|
});
|
|
348
368
|
this.metrics.incSuccessfulAttestations(inCommittee.length);
|
|
369
|
+
// Track epoch participation per attester: count each (attester, epoch) pair at most once
|
|
370
|
+
const proposalEpoch = getEpochAtSlot(slotNumber, this.epochCache.getL1Constants());
|
|
371
|
+
for (const attester of inCommittee){
|
|
372
|
+
const key = attester.toString();
|
|
373
|
+
const lastEpoch = this.lastAttestedEpochByAttester.get(key);
|
|
374
|
+
if (lastEpoch === undefined || proposalEpoch > lastEpoch) {
|
|
375
|
+
this.lastAttestedEpochByAttester.set(key, proposalEpoch);
|
|
376
|
+
this.metrics.incAttestedEpochCount(attester);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
349
379
|
// Determine which validators should attest
|
|
350
380
|
let attestors;
|
|
351
381
|
if (partOfCommittee) {
|
|
@@ -442,6 +472,14 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
442
472
|
reason: 'no_blocks_for_slot'
|
|
443
473
|
};
|
|
444
474
|
}
|
|
475
|
+
// Ensure the last block for this slot matches the archive in the checkpoint proposal
|
|
476
|
+
if (!blocks.at(-1)?.archive.root.equals(proposal.archive)) {
|
|
477
|
+
this.log.warn(`Last block archive mismatch for checkpoint proposal`, proposalInfo);
|
|
478
|
+
return {
|
|
479
|
+
isValid: false,
|
|
480
|
+
reason: 'last_block_archive_mismatch'
|
|
481
|
+
};
|
|
482
|
+
}
|
|
445
483
|
this.log.debug(`Found ${blocks.length} blocks for slot ${slot}`, {
|
|
446
484
|
...proposalInfo,
|
|
447
485
|
blockNumbers: blocks.map((b)=>b.number)
|
|
@@ -452,12 +490,9 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
452
490
|
const checkpointNumber = firstBlock.checkpointNumber;
|
|
453
491
|
// Get L1-to-L2 messages for this checkpoint
|
|
454
492
|
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(checkpointNumber);
|
|
455
|
-
//
|
|
456
|
-
// TODO: There can be a more efficient way to get the previous checkpoint out hashes without having to fetch the
|
|
457
|
-
// actual checkpoints and the blocks/txs in them.
|
|
493
|
+
// Collect the out hashes of all the checkpoints before this one in the same epoch
|
|
458
494
|
const epoch = getEpochAtSlot(slot, this.epochCache.getL1Constants());
|
|
459
|
-
const
|
|
460
|
-
const previousCheckpointOutHashes = previousCheckpoints.map((c)=>c.getCheckpointOutHash());
|
|
495
|
+
const previousCheckpointOutHashes = (await this.blockSource.getCheckpointsDataForEpoch(epoch)).filter((c)=>c.checkpointNumber < checkpointNumber).map((c)=>c.checkpointOutHash);
|
|
461
496
|
// Fork world state at the block before the first block
|
|
462
497
|
const parentBlockNumber = BlockNumber(firstBlock.number - 1);
|
|
463
498
|
const fork = await this.worldState.fork(parentBlockNumber);
|
|
@@ -511,6 +546,22 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
511
546
|
reason: 'out_hash_mismatch'
|
|
512
547
|
};
|
|
513
548
|
}
|
|
549
|
+
// Final round of validations on the checkpoint, just in case.
|
|
550
|
+
try {
|
|
551
|
+
validateCheckpoint(computedCheckpoint, {
|
|
552
|
+
rollupManaLimit: this.checkpointsBuilder.getConfig().rollupManaLimit,
|
|
553
|
+
maxDABlockGas: this.config.validateMaxDABlockGas,
|
|
554
|
+
maxL2BlockGas: this.config.validateMaxL2BlockGas,
|
|
555
|
+
maxTxsPerBlock: this.config.validateMaxTxsPerBlock,
|
|
556
|
+
maxTxsPerCheckpoint: this.config.validateMaxTxsPerCheckpoint
|
|
557
|
+
});
|
|
558
|
+
} catch (err) {
|
|
559
|
+
this.log.warn(`Checkpoint validation failed: ${err}`, proposalInfo);
|
|
560
|
+
return {
|
|
561
|
+
isValid: false,
|
|
562
|
+
reason: 'checkpoint_validation_failed'
|
|
563
|
+
};
|
|
564
|
+
}
|
|
514
565
|
this.log.verbose(`Checkpoint proposal validation successful for slot ${slot}`, proposalInfo);
|
|
515
566
|
return {
|
|
516
567
|
isValid: true
|
|
@@ -527,6 +578,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
527
578
|
chainId: gv.chainId,
|
|
528
579
|
version: gv.version,
|
|
529
580
|
slotNumber: gv.slotNumber,
|
|
581
|
+
timestamp: gv.timestamp,
|
|
530
582
|
coinbase: gv.coinbase,
|
|
531
583
|
feeRecipient: gv.feeRecipient,
|
|
532
584
|
gasFees: gv.gasFees
|
|
@@ -547,7 +599,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
547
599
|
return;
|
|
548
600
|
}
|
|
549
601
|
const blobFields = blocks.flatMap((b)=>b.toBlobFields());
|
|
550
|
-
const blobs = getBlobsPerL1Block(blobFields);
|
|
602
|
+
const blobs = await getBlobsPerL1Block(blobFields);
|
|
551
603
|
await this.blobClient.sendBlobsToFilestore(blobs);
|
|
552
604
|
this.log.debug(`Uploaded ${blobs.length} blobs to filestore for checkpoint at slot ${proposal.slotNumber}`, {
|
|
553
605
|
...proposalInfo,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/validator-client",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.10bd49492",
|
|
4
4
|
"main": "dest/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -64,30 +64,30 @@
|
|
|
64
64
|
]
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@aztec/blob-client": "0.0.1-commit.
|
|
68
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
69
|
-
"@aztec/constants": "0.0.1-commit.
|
|
70
|
-
"@aztec/epoch-cache": "0.0.1-commit.
|
|
71
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
72
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
73
|
-
"@aztec/node-keystore": "0.0.1-commit.
|
|
74
|
-
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.
|
|
75
|
-
"@aztec/p2p": "0.0.1-commit.
|
|
76
|
-
"@aztec/protocol-contracts": "0.0.1-commit.
|
|
77
|
-
"@aztec/prover-client": "0.0.1-commit.
|
|
78
|
-
"@aztec/simulator": "0.0.1-commit.
|
|
79
|
-
"@aztec/slasher": "0.0.1-commit.
|
|
80
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
81
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
82
|
-
"@aztec/validator-ha-signer": "0.0.1-commit.
|
|
67
|
+
"@aztec/blob-client": "0.0.1-commit.10bd49492",
|
|
68
|
+
"@aztec/blob-lib": "0.0.1-commit.10bd49492",
|
|
69
|
+
"@aztec/constants": "0.0.1-commit.10bd49492",
|
|
70
|
+
"@aztec/epoch-cache": "0.0.1-commit.10bd49492",
|
|
71
|
+
"@aztec/ethereum": "0.0.1-commit.10bd49492",
|
|
72
|
+
"@aztec/foundation": "0.0.1-commit.10bd49492",
|
|
73
|
+
"@aztec/node-keystore": "0.0.1-commit.10bd49492",
|
|
74
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.10bd49492",
|
|
75
|
+
"@aztec/p2p": "0.0.1-commit.10bd49492",
|
|
76
|
+
"@aztec/protocol-contracts": "0.0.1-commit.10bd49492",
|
|
77
|
+
"@aztec/prover-client": "0.0.1-commit.10bd49492",
|
|
78
|
+
"@aztec/simulator": "0.0.1-commit.10bd49492",
|
|
79
|
+
"@aztec/slasher": "0.0.1-commit.10bd49492",
|
|
80
|
+
"@aztec/stdlib": "0.0.1-commit.10bd49492",
|
|
81
|
+
"@aztec/telemetry-client": "0.0.1-commit.10bd49492",
|
|
82
|
+
"@aztec/validator-ha-signer": "0.0.1-commit.10bd49492",
|
|
83
83
|
"koa": "^2.16.1",
|
|
84
84
|
"koa-router": "^13.1.1",
|
|
85
85
|
"tslib": "^2.4.0",
|
|
86
86
|
"viem": "npm:@aztec/viem@2.38.2"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@aztec/archiver": "0.0.1-commit.
|
|
90
|
-
"@aztec/world-state": "0.0.1-commit.
|
|
89
|
+
"@aztec/archiver": "0.0.1-commit.10bd49492",
|
|
90
|
+
"@aztec/world-state": "0.0.1-commit.10bd49492",
|
|
91
91
|
"@electric-sql/pglite": "^0.3.14",
|
|
92
92
|
"@jest/globals": "^30.0.0",
|
|
93
93
|
"@types/jest": "^30.0.0",
|