@aztec/aztec-node 0.0.1-commit.8c0b8ff → 0.0.1-commit.8cb2d04d8
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 -2
- package/dest/aztec-node/config.d.ts.map +1 -1
- package/dest/aztec-node/config.js +1 -1
- package/dest/aztec-node/server.d.ts +15 -14
- package/dest/aztec-node/server.d.ts.map +1 -1
- package/dest/aztec-node/server.js +104 -52
- package/dest/sentinel/factory.d.ts +2 -2
- package/dest/sentinel/factory.d.ts.map +1 -1
- package/dest/sentinel/sentinel.js +6 -6
- package/package.json +26 -27
- package/src/aztec-node/config.ts +1 -1
- package/src/aztec-node/server.ts +112 -65
- package/src/sentinel/factory.ts +1 -1
- package/src/sentinel/sentinel.ts +6 -6
|
@@ -372,7 +372,8 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
372
372
|
}
|
|
373
373
|
var _dec, _initProto;
|
|
374
374
|
import { createArchiver } from '@aztec/archiver';
|
|
375
|
-
import { BBCircuitVerifier,
|
|
375
|
+
import { BBCircuitVerifier, BatchChonkVerifier, QueuedIVCVerifier } from '@aztec/bb-prover';
|
|
376
|
+
import { TestCircuitVerifier } from '@aztec/bb-prover/test';
|
|
376
377
|
import { createBlobClientWithFileStores } from '@aztec/blob-client/client';
|
|
377
378
|
import { Blob } from '@aztec/blob-lib';
|
|
378
379
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
@@ -396,7 +397,7 @@ import { createP2PClient, createTxValidatorForAcceptingTxsOverRPC, getDefaultAll
|
|
|
396
397
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
397
398
|
import { createProverNode } from '@aztec/prover-node';
|
|
398
399
|
import { createKeyStoreForProver } from '@aztec/prover-node/config';
|
|
399
|
-
import { GlobalVariableBuilder, SequencerClient } from '@aztec/sequencer-client';
|
|
400
|
+
import { FeeProviderImpl, GlobalVariableBuilder, SequencerClient } from '@aztec/sequencer-client';
|
|
400
401
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
401
402
|
import { AttestationsBlockWatcher, EpochPruneWatcher, createSlasher } from '@aztec/slasher';
|
|
402
403
|
import { CollectionLimitsConfig, PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
@@ -439,9 +440,11 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
439
440
|
l1ChainId;
|
|
440
441
|
version;
|
|
441
442
|
globalVariableBuilder;
|
|
443
|
+
feeProvider;
|
|
442
444
|
epochCache;
|
|
443
445
|
packageVersion;
|
|
444
|
-
|
|
446
|
+
peerProofVerifier;
|
|
447
|
+
rpcProofVerifier;
|
|
445
448
|
telemetry;
|
|
446
449
|
log;
|
|
447
450
|
blobClient;
|
|
@@ -462,7 +465,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
462
465
|
// Prevent two snapshot operations to happen simultaneously
|
|
463
466
|
isUploadingSnapshot;
|
|
464
467
|
tracer;
|
|
465
|
-
constructor(config, p2pClient, blockSource, logsSource, contractDataSource, l1ToL2MessageSource, worldStateSynchronizer, sequencer, proverNode, slasherClient, validatorsSentinel, epochPruneWatcher, l1ChainId, version, globalVariableBuilder, epochCache, packageVersion,
|
|
468
|
+
constructor(config, p2pClient, blockSource, logsSource, contractDataSource, l1ToL2MessageSource, worldStateSynchronizer, sequencer, proverNode, slasherClient, validatorsSentinel, epochPruneWatcher, l1ChainId, version, globalVariableBuilder, feeProvider, epochCache, packageVersion, peerProofVerifier, rpcProofVerifier, telemetry = getTelemetryClient(), log = createLogger('node'), blobClient, validatorClient, keyStoreManager, debugLogStore = new NullDebugLogStore()){
|
|
466
469
|
this.config = config;
|
|
467
470
|
this.p2pClient = p2pClient;
|
|
468
471
|
this.blockSource = blockSource;
|
|
@@ -478,9 +481,11 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
478
481
|
this.l1ChainId = l1ChainId;
|
|
479
482
|
this.version = version;
|
|
480
483
|
this.globalVariableBuilder = globalVariableBuilder;
|
|
484
|
+
this.feeProvider = feeProvider;
|
|
481
485
|
this.epochCache = epochCache;
|
|
482
486
|
this.packageVersion = packageVersion;
|
|
483
|
-
this.
|
|
487
|
+
this.peerProofVerifier = peerProofVerifier;
|
|
488
|
+
this.rpcProofVerifier = rpcProofVerifier;
|
|
484
489
|
this.telemetry = telemetry;
|
|
485
490
|
this.log = log;
|
|
486
491
|
this.blobClient = blobClient;
|
|
@@ -500,6 +505,9 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
500
505
|
throw new Error('debugLogStore should never be enabled when realProofs are set');
|
|
501
506
|
}
|
|
502
507
|
}
|
|
508
|
+
/** @internal Exposed for testing — returns the RPC proof verifier. */ getProofVerifier() {
|
|
509
|
+
return this.rpcProofVerifier;
|
|
510
|
+
}
|
|
503
511
|
async getWorldStateSyncStatus() {
|
|
504
512
|
const status = await this.worldStateSynchronizer.status();
|
|
505
513
|
return status.syncSummary;
|
|
@@ -597,8 +605,18 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
597
605
|
blockUntilSync: !config.skipArchiverInitialSync
|
|
598
606
|
});
|
|
599
607
|
// now create the merkle trees and the world state synchronizer
|
|
600
|
-
const worldStateSynchronizer = await createWorldStateSynchronizer(config, archiver, options.
|
|
601
|
-
const
|
|
608
|
+
const worldStateSynchronizer = await createWorldStateSynchronizer(config, archiver, options.genesis, telemetry);
|
|
609
|
+
const useRealVerifiers = config.realProofs || config.debugForceTxProofVerification;
|
|
610
|
+
let peerProofVerifier;
|
|
611
|
+
let rpcProofVerifier;
|
|
612
|
+
if (useRealVerifiers) {
|
|
613
|
+
peerProofVerifier = await BatchChonkVerifier.new(config, config.bbChonkVerifyMaxBatch, 'peer');
|
|
614
|
+
const rpcVerifier = await BBCircuitVerifier.new(config);
|
|
615
|
+
rpcProofVerifier = new QueuedIVCVerifier(rpcVerifier, config.numConcurrentIVCVerifiers);
|
|
616
|
+
} else {
|
|
617
|
+
peerProofVerifier = new TestCircuitVerifier(config.proverTestVerificationDelayMs);
|
|
618
|
+
rpcProofVerifier = new TestCircuitVerifier(config.proverTestVerificationDelayMs);
|
|
619
|
+
}
|
|
602
620
|
let debugLogStore;
|
|
603
621
|
if (!config.realProofs) {
|
|
604
622
|
log.warn(`Aztec node is accepting fake proofs`);
|
|
@@ -607,13 +625,12 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
607
625
|
} else {
|
|
608
626
|
debugLogStore = new NullDebugLogStore();
|
|
609
627
|
}
|
|
610
|
-
const proofVerifier = new QueuedIVCVerifier(config, circuitVerifier);
|
|
611
628
|
const proverOnly = config.enableProverNode && config.disableValidator;
|
|
612
629
|
if (proverOnly) {
|
|
613
630
|
log.info('Starting in prover-only mode: skipping validator, sequencer, sentinel, and slasher subsystems');
|
|
614
631
|
}
|
|
615
632
|
// create the tx pool and the p2p client, which will need the l2 block source
|
|
616
|
-
const p2pClient = await createP2PClient(config, archiver,
|
|
633
|
+
const p2pClient = await createP2PClient(config, archiver, peerProofVerifier, worldStateSynchronizer, epochCache, packageVersion, dateProvider, telemetry, deps.p2pClientDeps);
|
|
617
634
|
// We'll accumulate sentinel watchers here
|
|
618
635
|
const watchers = [];
|
|
619
636
|
// Create FullNodeCheckpointsBuilder for block proposal handling and tx validation.
|
|
@@ -646,6 +663,9 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
646
663
|
// like attestations or auths will fail.
|
|
647
664
|
if (validatorClient) {
|
|
648
665
|
watchers.push(validatorClient);
|
|
666
|
+
const vc = validatorClient;
|
|
667
|
+
const getValidatorAddresses = ()=>vc.getValidatorAddresses().map((a)=>a.toString());
|
|
668
|
+
validatorClient.getProposalHandler().register(p2pClient, true, archiver, getValidatorAddresses);
|
|
649
669
|
if (!options.dontStartSequencer) {
|
|
650
670
|
await validatorClient.registerHandlers();
|
|
651
671
|
}
|
|
@@ -654,7 +674,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
654
674
|
// If there's no validator client, create a ProposalHandler to handle block and checkpoint proposals
|
|
655
675
|
// for monitoring or reexecution. Reexecution (default) allows us to follow the pending chain,
|
|
656
676
|
// while non-reexecution is used for validating the proposals and collecting their txs.
|
|
657
|
-
// Checkpoint proposals
|
|
677
|
+
// Checkpoint proposals rebuild blobs if the blob client can upload blobs.
|
|
658
678
|
if (!validatorClient) {
|
|
659
679
|
const reexecute = !!config.alwaysReexecuteBlockProposals;
|
|
660
680
|
log.info(`Setting up proposal handler` + (reexecute ? ' with reexecution of proposals' : ''));
|
|
@@ -668,7 +688,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
668
688
|
blobClient,
|
|
669
689
|
dateProvider,
|
|
670
690
|
telemetry
|
|
671
|
-
}).register(p2pClient, reexecute);
|
|
691
|
+
}).register(p2pClient, reexecute, archiver);
|
|
672
692
|
}
|
|
673
693
|
// Start world state and wait for it to sync to the archiver.
|
|
674
694
|
await worldStateSynchronizer.start();
|
|
@@ -694,19 +714,20 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
694
714
|
}
|
|
695
715
|
// Start p2p-related services once the archiver has completed sync
|
|
696
716
|
void archiver.waitForInitialSync().then(async ()=>{
|
|
697
|
-
await p2pClient.start();
|
|
698
717
|
await validatorsSentinel?.start();
|
|
699
718
|
await epochPruneWatcher?.start();
|
|
700
719
|
await attestationsBlockWatcher?.start();
|
|
701
720
|
log.info(`All p2p services started`);
|
|
702
721
|
}).catch((err)=>log.error('Failed to start p2p services after archiver sync', err));
|
|
703
|
-
const
|
|
722
|
+
const globalVariableBuilderConfig = {
|
|
704
723
|
l1Contracts: config.l1Contracts,
|
|
705
724
|
ethereumSlotDuration: config.ethereumSlotDuration,
|
|
706
725
|
rollupVersion: BigInt(config.rollupVersion),
|
|
707
726
|
l1GenesisTime,
|
|
708
727
|
slotDuration: Number(slotDuration)
|
|
709
|
-
}
|
|
728
|
+
};
|
|
729
|
+
const globalVariableBuilder = new GlobalVariableBuilder(dateProvider, publicClient, globalVariableBuilderConfig);
|
|
730
|
+
const feeProvider = new FeeProviderImpl(dateProvider, publicClient, globalVariableBuilderConfig);
|
|
710
731
|
// Validator enabled, create/start relevant service
|
|
711
732
|
let sequencer;
|
|
712
733
|
let slasherClient;
|
|
@@ -733,6 +754,22 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
733
754
|
dateProvider,
|
|
734
755
|
kzg: Blob.getViemKzgInstance()
|
|
735
756
|
});
|
|
757
|
+
// Create a funder L1TxUtils from the keystore funding account (if configured)
|
|
758
|
+
const fundingSigner = keyStoreManager?.createFundingSigner();
|
|
759
|
+
let funderL1TxUtils;
|
|
760
|
+
if (fundingSigner) {
|
|
761
|
+
const [funder] = await createL1TxUtilsFromSigners(publicClient, [
|
|
762
|
+
fundingSigner
|
|
763
|
+
], {
|
|
764
|
+
...config,
|
|
765
|
+
scope: 'sequencer'
|
|
766
|
+
}, {
|
|
767
|
+
telemetry,
|
|
768
|
+
logger: log.createChild('l1-tx-utils:funder'),
|
|
769
|
+
dateProvider
|
|
770
|
+
});
|
|
771
|
+
funderL1TxUtils = funder;
|
|
772
|
+
}
|
|
736
773
|
// Create and start the sequencer client
|
|
737
774
|
const checkpointsBuilder = new CheckpointsBuilder({
|
|
738
775
|
...config,
|
|
@@ -744,6 +781,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
744
781
|
...deps,
|
|
745
782
|
epochCache,
|
|
746
783
|
l1TxUtils,
|
|
784
|
+
funderL1TxUtils,
|
|
747
785
|
validatorClient,
|
|
748
786
|
p2pClient,
|
|
749
787
|
worldStateSynchronizer,
|
|
@@ -785,7 +823,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
785
823
|
log.info(`Prover node subsystem created but not started`);
|
|
786
824
|
}
|
|
787
825
|
}
|
|
788
|
-
const node = new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, proverNode, slasherClient, validatorsSentinel, epochPruneWatcher, ethereumChain.chainInfo.id, config.rollupVersion, globalVariableBuilder, epochCache, packageVersion,
|
|
826
|
+
const node = new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, proverNode, slasherClient, validatorsSentinel, epochPruneWatcher, ethereumChain.chainInfo.id, config.rollupVersion, globalVariableBuilder, feeProvider, epochCache, packageVersion, peerProofVerifier, rpcProofVerifier, telemetry, log, blobClient, validatorClient, keyStoreManager, debugLogStore);
|
|
789
827
|
return node;
|
|
790
828
|
}
|
|
791
829
|
/**
|
|
@@ -900,11 +938,11 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
900
938
|
getCheckpointsDataForEpoch(epochNumber) {
|
|
901
939
|
return this.blockSource.getCheckpointsDataForEpoch(epochNumber);
|
|
902
940
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
return await this.
|
|
941
|
+
async getCurrentMinFees() {
|
|
942
|
+
return await this.feeProvider.getCurrentMinFees();
|
|
943
|
+
}
|
|
944
|
+
/** Returns predicted min fees for the current slot and next N slots. */ async getPredictedMinFees(manaUsage) {
|
|
945
|
+
return await this.feeProvider.getPredictedMinFees(manaUsage);
|
|
908
946
|
}
|
|
909
947
|
async getMaxPriorityFees() {
|
|
910
948
|
for await (const tx of this.p2pClient.iteratePendingTxs()){
|
|
@@ -955,28 +993,36 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
955
993
|
return this.contractDataSource.getContract(address);
|
|
956
994
|
}
|
|
957
995
|
async getPrivateLogsByTags(tags, page, referenceBlock) {
|
|
996
|
+
let upToBlockNumber;
|
|
958
997
|
if (referenceBlock) {
|
|
959
998
|
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
960
|
-
if (
|
|
999
|
+
if (referenceBlock.equals(initialBlockHash)) {
|
|
1000
|
+
upToBlockNumber = BlockNumber(0);
|
|
1001
|
+
} else {
|
|
961
1002
|
const header = await this.blockSource.getBlockHeaderByHash(referenceBlock);
|
|
962
1003
|
if (!header) {
|
|
963
1004
|
throw new Error(`Block ${referenceBlock.toString()} not found in the node. This might indicate a reorg has occurred.`);
|
|
964
1005
|
}
|
|
1006
|
+
upToBlockNumber = header.globalVariables.blockNumber;
|
|
965
1007
|
}
|
|
966
1008
|
}
|
|
967
|
-
return this.logsSource.getPrivateLogsByTags(tags, page);
|
|
1009
|
+
return this.logsSource.getPrivateLogsByTags(tags, page, upToBlockNumber);
|
|
968
1010
|
}
|
|
969
1011
|
async getPublicLogsByTagsFromContract(contractAddress, tags, page, referenceBlock) {
|
|
1012
|
+
let upToBlockNumber;
|
|
970
1013
|
if (referenceBlock) {
|
|
971
1014
|
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
972
|
-
if (
|
|
1015
|
+
if (referenceBlock.equals(initialBlockHash)) {
|
|
1016
|
+
upToBlockNumber = BlockNumber(0);
|
|
1017
|
+
} else {
|
|
973
1018
|
const header = await this.blockSource.getBlockHeaderByHash(referenceBlock);
|
|
974
1019
|
if (!header) {
|
|
975
1020
|
throw new Error(`Block ${referenceBlock.toString()} not found in the node. This might indicate a reorg has occurred.`);
|
|
976
1021
|
}
|
|
1022
|
+
upToBlockNumber = header.globalVariables.blockNumber;
|
|
977
1023
|
}
|
|
978
1024
|
}
|
|
979
|
-
return this.logsSource.getPublicLogsByTagsFromContract(contractAddress, tags, page);
|
|
1025
|
+
return this.logsSource.getPublicLogsByTagsFromContract(contractAddress, tags, page, upToBlockNumber);
|
|
980
1026
|
}
|
|
981
1027
|
/**
|
|
982
1028
|
* Gets public logs based on the provided filter.
|
|
@@ -1049,7 +1095,10 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1049
1095
|
await tryStop(this.validatorsSentinel);
|
|
1050
1096
|
await tryStop(this.epochPruneWatcher);
|
|
1051
1097
|
await tryStop(this.slasherClient);
|
|
1052
|
-
await
|
|
1098
|
+
await Promise.all([
|
|
1099
|
+
tryStop(this.peerProofVerifier),
|
|
1100
|
+
tryStop(this.rpcProofVerifier)
|
|
1101
|
+
]);
|
|
1053
1102
|
await tryStop(this.sequencer);
|
|
1054
1103
|
await tryStop(this.proverNode);
|
|
1055
1104
|
await tryStop(this.p2pClient);
|
|
@@ -1132,32 +1181,26 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1132
1181
|
if (blockNumber === undefined) {
|
|
1133
1182
|
throw new Error(`Block number not found for leaf index ${index} in tree ${MerkleTreeId[treeId]}`);
|
|
1134
1183
|
}
|
|
1135
|
-
const
|
|
1136
|
-
if (
|
|
1184
|
+
const l2BlockHash = blockNumberToHash.get(blockNumber);
|
|
1185
|
+
if (l2BlockHash === undefined) {
|
|
1137
1186
|
throw new Error(`Block hash not found for block number ${blockNumber}`);
|
|
1138
1187
|
}
|
|
1139
1188
|
return {
|
|
1140
1189
|
l2BlockNumber: blockNumber,
|
|
1141
|
-
l2BlockHash
|
|
1190
|
+
l2BlockHash,
|
|
1142
1191
|
data: index
|
|
1143
1192
|
};
|
|
1144
1193
|
});
|
|
1145
1194
|
}
|
|
1146
1195
|
async getBlockHashMembershipWitness(referenceBlock, blockHash) {
|
|
1147
|
-
// Block 0 (the initial block) has an empty archive, so no membership witness can exist.
|
|
1148
|
-
if (referenceBlock === BlockNumber.ZERO) {
|
|
1149
|
-
return undefined;
|
|
1150
|
-
}
|
|
1151
|
-
if (BlockHash.isBlockHash(referenceBlock)) {
|
|
1152
|
-
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
1153
|
-
if (referenceBlock.equals(initialBlockHash)) {
|
|
1154
|
-
return undefined;
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
1196
|
// The Noir circuit checks the archive membership proof against `anchor_block_header.last_archive.root`,
|
|
1158
1197
|
// which is the archive tree root BEFORE the anchor block was added (i.e. the state after block N-1).
|
|
1159
1198
|
// So we need the world state at block N-1, not block N, to produce a sibling path matching that root.
|
|
1160
1199
|
const referenceBlockNumber = await this.resolveBlockNumber(referenceBlock);
|
|
1200
|
+
if (referenceBlockNumber === BlockNumber.ZERO) {
|
|
1201
|
+
// Block 0 (the initial block) has an empty archive, so no membership witness can exist.
|
|
1202
|
+
return undefined;
|
|
1203
|
+
}
|
|
1161
1204
|
const committedDb = await this.getWorldState(BlockNumber(referenceBlockNumber - 1));
|
|
1162
1205
|
const [pathAndIndex] = await committedDb.findSiblingPaths(MerkleTreeId.ARCHIVE, [
|
|
1163
1206
|
blockHash
|
|
@@ -1345,7 +1388,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1345
1388
|
}
|
|
1346
1389
|
async isValidTx(tx, { isSimulation, skipFeeEnforcement } = {}) {
|
|
1347
1390
|
const db = this.worldStateSynchronizer.getCommitted();
|
|
1348
|
-
const verifier = isSimulation ? undefined : this.
|
|
1391
|
+
const verifier = isSimulation ? undefined : this.rpcProofVerifier;
|
|
1349
1392
|
// We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
|
|
1350
1393
|
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1351
1394
|
const blockNumber = BlockNumber(await this.blockSource.getBlockNumber() + 1);
|
|
@@ -1387,7 +1430,18 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1387
1430
|
archiver.updateConfig(config);
|
|
1388
1431
|
}
|
|
1389
1432
|
if (newConfig.realProofs !== this.config.realProofs) {
|
|
1390
|
-
|
|
1433
|
+
await Promise.all([
|
|
1434
|
+
tryStop(this.peerProofVerifier),
|
|
1435
|
+
tryStop(this.rpcProofVerifier)
|
|
1436
|
+
]);
|
|
1437
|
+
if (newConfig.realProofs) {
|
|
1438
|
+
this.peerProofVerifier = await BatchChonkVerifier.new(newConfig, newConfig.bbChonkVerifyMaxBatch, 'peer');
|
|
1439
|
+
const rpcVerifier = await BBCircuitVerifier.new(newConfig);
|
|
1440
|
+
this.rpcProofVerifier = new QueuedIVCVerifier(rpcVerifier, newConfig.numConcurrentIVCVerifiers);
|
|
1441
|
+
} else {
|
|
1442
|
+
this.peerProofVerifier = new TestCircuitVerifier();
|
|
1443
|
+
this.rpcProofVerifier = new TestCircuitVerifier();
|
|
1444
|
+
}
|
|
1391
1445
|
}
|
|
1392
1446
|
this.config = newConfig;
|
|
1393
1447
|
}
|
|
@@ -1447,7 +1501,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1447
1501
|
});
|
|
1448
1502
|
return Promise.resolve();
|
|
1449
1503
|
}
|
|
1450
|
-
async rollbackTo(targetBlock, force) {
|
|
1504
|
+
async rollbackTo(targetBlock, force, resumeSync = true) {
|
|
1451
1505
|
const archiver = this.blockSource;
|
|
1452
1506
|
if (!('rollbackTo' in archiver)) {
|
|
1453
1507
|
throw new Error('Archiver implementation does not support rollbacks.');
|
|
@@ -1475,9 +1529,13 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1475
1529
|
this.log.error(`Error during rollback`, err);
|
|
1476
1530
|
throw err;
|
|
1477
1531
|
} finally{
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1532
|
+
if (resumeSync) {
|
|
1533
|
+
this.log.info(`Resuming world state and archiver sync.`);
|
|
1534
|
+
this.worldStateSynchronizer.resumeSync();
|
|
1535
|
+
archiver.resume();
|
|
1536
|
+
} else {
|
|
1537
|
+
this.log.info(`Sync left paused after rollback (resumeSync=false).`);
|
|
1538
|
+
}
|
|
1481
1539
|
}
|
|
1482
1540
|
}
|
|
1483
1541
|
async pauseSync() {
|
|
@@ -1491,18 +1549,12 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1491
1549
|
this.blockSource.resume();
|
|
1492
1550
|
return Promise.resolve();
|
|
1493
1551
|
}
|
|
1494
|
-
getSlashPayloads() {
|
|
1495
|
-
if (!this.slasherClient) {
|
|
1496
|
-
throw new Error(`Slasher client not enabled`);
|
|
1497
|
-
}
|
|
1498
|
-
return this.slasherClient.getSlashPayloads();
|
|
1499
|
-
}
|
|
1500
1552
|
getSlashOffenses(round) {
|
|
1501
1553
|
if (!this.slasherClient) {
|
|
1502
1554
|
throw new Error(`Slasher client not enabled`);
|
|
1503
1555
|
}
|
|
1504
1556
|
if (round === 'all') {
|
|
1505
|
-
return this.slasherClient.
|
|
1557
|
+
return this.slasherClient.getOffenses();
|
|
1506
1558
|
} else {
|
|
1507
1559
|
return this.slasherClient.gatherOffensesForRound(round === 'current' ? undefined : BigInt(round));
|
|
1508
1560
|
}
|
|
@@ -1648,7 +1700,7 @@ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
|
|
|
1648
1700
|
// Double-check world-state synced to the same block hash as was requested
|
|
1649
1701
|
if (BlockHash.isBlockHash(block)) {
|
|
1650
1702
|
const blockHash = await snapshot.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
|
|
1651
|
-
if (!blockHash || !
|
|
1703
|
+
if (!blockHash || !block.equals(blockHash)) {
|
|
1652
1704
|
throw new Error(`Block hash ${block.toString()} not found in world state at block number ${blockNumber}. If the node API has been queried with anchor block hash possibly a reorg has occurred.`);
|
|
1653
1705
|
}
|
|
1654
1706
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
2
|
-
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
3
2
|
import type { P2PClient } from '@aztec/p2p';
|
|
4
3
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
5
4
|
import type { SlasherConfig } from '@aztec/stdlib/interfaces/server';
|
|
5
|
+
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
6
6
|
import type { SentinelConfig } from './config.js';
|
|
7
7
|
import { Sentinel } from './sentinel.js';
|
|
8
8
|
export declare function createSentinel(epochCache: EpochCache, archiver: L2BlockSource, p2p: P2PClient, config: SentinelConfig & DataStoreConfig & SlasherConfig, logger?: import("@aztec/foundation/log").Logger): Promise<Sentinel | undefined>;
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlbnRpbmVsL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFHckQsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQzVDLE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3JFLE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTlELE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBR3pDLHdCQUFzQixjQUFjLENBQ2xDLFVBQVUsRUFBRSxVQUFVLEVBQ3RCLFFBQVEsRUFBRSxhQUFhLEVBQ3ZCLEdBQUcsRUFBRSxTQUFTLEVBQ2QsTUFBTSxFQUFFLGNBQWMsR0FBRyxlQUFlLEdBQUcsYUFBYSxFQUN4RCxNQUFNLHlDQUFnQyxHQUNyQyxPQUFPLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQyxDQVkvQiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/sentinel/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/sentinel/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,wBAAsB,cAAc,CAClC,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,cAAc,GAAG,eAAe,GAAG,aAAa,EACxD,MAAM,yCAAgC,GACrC,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAY/B"}
|
|
@@ -48,7 +48,7 @@ export class Sentinel extends EventEmitter {
|
|
|
48
48
|
this.runningPromise.start();
|
|
49
49
|
}
|
|
50
50
|
/** Loads initial slot and initializes blockstream. We will not process anything at or before the initial slot. */ async init() {
|
|
51
|
-
this.initialSlot = this.epochCache.
|
|
51
|
+
this.initialSlot = this.epochCache.getSlotNow();
|
|
52
52
|
const startingBlock = BlockNumber(await this.archiver.getBlockNumber());
|
|
53
53
|
this.logger.info(`Starting validator sentinel with initial slot ${this.initialSlot} and block ${startingBlock}`);
|
|
54
54
|
this.blockStream = new L2BlockStream(this.archiver, this.l2TipsStore, this, this.logger, {
|
|
@@ -157,13 +157,13 @@ export class Sentinel extends EventEmitter {
|
|
|
157
157
|
return false;
|
|
158
158
|
}
|
|
159
159
|
// Check that we have at least requiredConsecutiveEpochs and that all of them are above the inactivity threshold
|
|
160
|
-
return pastEpochs.slice(0, requiredConsecutiveEpochs).every((p)=>p.missed / p.total >= this.config.slashInactivityTargetPercentage);
|
|
160
|
+
return pastEpochs.slice(0, requiredConsecutiveEpochs).every((p)=>p.total === 0 ? false : p.missed / p.total >= this.config.slashInactivityTargetPercentage);
|
|
161
161
|
}
|
|
162
162
|
async handleProvenPerformance(epoch, performance) {
|
|
163
163
|
if (this.config.slashInactivityPenalty === 0n) {
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
|
-
const inactiveValidators = getEntries(performance).filter(([_, { missed, total }])=>missed / total >= this.config.slashInactivityTargetPercentage).map(([address])=>address);
|
|
166
|
+
const inactiveValidators = getEntries(performance).filter(([_, { missed, total }])=>total > 0 && missed / total >= this.config.slashInactivityTargetPercentage).map(([address])=>address);
|
|
167
167
|
this.logger.debug(`Found ${inactiveValidators.length} inactive validators in epoch ${epoch}`, {
|
|
168
168
|
inactiveValidators,
|
|
169
169
|
epoch,
|
|
@@ -190,7 +190,7 @@ export class Sentinel extends EventEmitter {
|
|
|
190
190
|
* Note that we do not process historical data, since we rely on p2p data for processing,
|
|
191
191
|
* and we don't have that data if we were offline during the period.
|
|
192
192
|
*/ async work() {
|
|
193
|
-
const
|
|
193
|
+
const currentSlot = this.epochCache.getSlotNow();
|
|
194
194
|
try {
|
|
195
195
|
// Manually sync the block stream to ensure we have the latest data.
|
|
196
196
|
// Note we never `start` the blockstream, so it loops at the same pace as we do.
|
|
@@ -351,7 +351,7 @@ export class Sentinel extends EventEmitter {
|
|
|
351
351
|
v.toString(),
|
|
352
352
|
await this.store.getHistory(v)
|
|
353
353
|
]))) : await this.store.getHistories();
|
|
354
|
-
const slotNow = this.epochCache.
|
|
354
|
+
const slotNow = this.epochCache.getSlotNow();
|
|
355
355
|
fromSlot ??= SlotNumber(Math.max((this.lastProcessedSlot ?? slotNow) - this.store.getHistoryLength(), 0));
|
|
356
356
|
toSlot ??= this.lastProcessedSlot ?? slotNow;
|
|
357
357
|
const stats = mapValues(histories, (history, address)=>this.computeStatsForValidator(address, history ?? [], fromSlot, toSlot));
|
|
@@ -367,7 +367,7 @@ export class Sentinel extends EventEmitter {
|
|
|
367
367
|
if (!history || history.length === 0) {
|
|
368
368
|
return undefined;
|
|
369
369
|
}
|
|
370
|
-
const slotNow = this.epochCache.
|
|
370
|
+
const slotNow = this.epochCache.getSlotNow();
|
|
371
371
|
const effectiveFromSlot = fromSlot ?? SlotNumber(Math.max((this.lastProcessedSlot ?? slotNow) - this.store.getHistoryLength(), 0));
|
|
372
372
|
const effectiveToSlot = toSlot ?? this.lastProcessedSlot ?? slotNow;
|
|
373
373
|
const historyLength = BigInt(this.store.getHistoryLength());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/aztec-node",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.8cb2d04d8",
|
|
4
4
|
"main": "dest/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -65,32 +65,31 @@
|
|
|
65
65
|
]
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@aztec/archiver": "0.0.1-commit.
|
|
69
|
-
"@aztec/bb-prover": "0.0.1-commit.
|
|
70
|
-
"@aztec/blob-client": "0.0.1-commit.
|
|
71
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
72
|
-
"@aztec/constants": "0.0.1-commit.
|
|
73
|
-
"@aztec/epoch-cache": "0.0.1-commit.
|
|
74
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
75
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
76
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
77
|
-
"@aztec/l1-artifacts": "0.0.1-commit.
|
|
78
|
-
"@aztec/
|
|
79
|
-
"@aztec/node-
|
|
80
|
-
"@aztec/
|
|
81
|
-
"@aztec/
|
|
82
|
-
"@aztec/
|
|
83
|
-
"@aztec/
|
|
84
|
-
"@aztec/prover-
|
|
85
|
-
"@aztec/
|
|
86
|
-
"@aztec/
|
|
87
|
-
"@aztec/
|
|
88
|
-
"@aztec/
|
|
89
|
-
"@aztec/
|
|
90
|
-
"@aztec/
|
|
91
|
-
"@aztec/validator-
|
|
92
|
-
"@aztec/
|
|
93
|
-
"@aztec/world-state": "0.0.1-commit.8c0b8ff",
|
|
68
|
+
"@aztec/archiver": "0.0.1-commit.8cb2d04d8",
|
|
69
|
+
"@aztec/bb-prover": "0.0.1-commit.8cb2d04d8",
|
|
70
|
+
"@aztec/blob-client": "0.0.1-commit.8cb2d04d8",
|
|
71
|
+
"@aztec/blob-lib": "0.0.1-commit.8cb2d04d8",
|
|
72
|
+
"@aztec/constants": "0.0.1-commit.8cb2d04d8",
|
|
73
|
+
"@aztec/epoch-cache": "0.0.1-commit.8cb2d04d8",
|
|
74
|
+
"@aztec/ethereum": "0.0.1-commit.8cb2d04d8",
|
|
75
|
+
"@aztec/foundation": "0.0.1-commit.8cb2d04d8",
|
|
76
|
+
"@aztec/kv-store": "0.0.1-commit.8cb2d04d8",
|
|
77
|
+
"@aztec/l1-artifacts": "0.0.1-commit.8cb2d04d8",
|
|
78
|
+
"@aztec/node-keystore": "0.0.1-commit.8cb2d04d8",
|
|
79
|
+
"@aztec/node-lib": "0.0.1-commit.8cb2d04d8",
|
|
80
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.8cb2d04d8",
|
|
81
|
+
"@aztec/p2p": "0.0.1-commit.8cb2d04d8",
|
|
82
|
+
"@aztec/protocol-contracts": "0.0.1-commit.8cb2d04d8",
|
|
83
|
+
"@aztec/prover-client": "0.0.1-commit.8cb2d04d8",
|
|
84
|
+
"@aztec/prover-node": "0.0.1-commit.8cb2d04d8",
|
|
85
|
+
"@aztec/sequencer-client": "0.0.1-commit.8cb2d04d8",
|
|
86
|
+
"@aztec/simulator": "0.0.1-commit.8cb2d04d8",
|
|
87
|
+
"@aztec/slasher": "0.0.1-commit.8cb2d04d8",
|
|
88
|
+
"@aztec/stdlib": "0.0.1-commit.8cb2d04d8",
|
|
89
|
+
"@aztec/telemetry-client": "0.0.1-commit.8cb2d04d8",
|
|
90
|
+
"@aztec/validator-client": "0.0.1-commit.8cb2d04d8",
|
|
91
|
+
"@aztec/validator-ha-signer": "0.0.1-commit.8cb2d04d8",
|
|
92
|
+
"@aztec/world-state": "0.0.1-commit.8cb2d04d8",
|
|
94
93
|
"koa": "^2.16.1",
|
|
95
94
|
"koa-router": "^13.1.1",
|
|
96
95
|
"tslib": "^2.4.0",
|
package/src/aztec-node/config.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { type GenesisStateConfig, genesisStateConfigMappings } from '@aztec/ethe
|
|
|
3
3
|
import { type L1ContractAddresses, l1ContractAddressesMapping } from '@aztec/ethereum/l1-contract-addresses';
|
|
4
4
|
import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config';
|
|
5
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
|
-
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
|
|
7
6
|
import {
|
|
8
7
|
type KeyStore,
|
|
9
8
|
type ValidatorKeyStore,
|
|
@@ -27,6 +26,7 @@ import { slasherConfigMappings } from '@aztec/slasher';
|
|
|
27
26
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
28
27
|
import { type NodeRPCConfig, nodeRpcConfigMappings } from '@aztec/stdlib/config';
|
|
29
28
|
import type { SlasherConfig } from '@aztec/stdlib/interfaces/server';
|
|
29
|
+
import { type DataStoreConfig, dataConfigMappings } from '@aztec/stdlib/kv-store';
|
|
30
30
|
import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client/config';
|
|
31
31
|
import { type WorldStateConfig, worldStateConfigMappings } from '@aztec/world-state/config';
|
|
32
32
|
|