@aztec/aztec-node 0.0.1-commit.f504929 → 0.0.1-commit.f650c0a5c
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 +23 -24
- package/dest/aztec-node/server.d.ts.map +1 -1
- package/dest/aztec-node/server.js +224 -137
- package/dest/sentinel/factory.d.ts +2 -2
- package/dest/sentinel/factory.d.ts.map +1 -1
- package/dest/sentinel/sentinel.js +8 -8
- package/package.json +26 -27
- package/src/aztec-node/config.ts +1 -1
- package/src/aztec-node/server.ts +233 -143
- package/src/sentinel/factory.ts +1 -1
- package/src/sentinel/sentinel.ts +8 -8
package/src/aztec-node/server.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Archiver, createArchiver } from '@aztec/archiver';
|
|
2
|
-
import { BBCircuitVerifier,
|
|
2
|
+
import { BBCircuitVerifier, BatchChonkVerifier, QueuedIVCVerifier } from '@aztec/bb-prover';
|
|
3
|
+
import { TestCircuitVerifier } from '@aztec/bb-prover/test';
|
|
3
4
|
import { type BlobClientInterface, createBlobClientWithFileStores } from '@aztec/blob-client/client';
|
|
4
5
|
import { Blob } from '@aztec/blob-lib';
|
|
5
6
|
import { ARCHIVE_HEIGHT, type L1_TO_L2_MSG_TREE_HEIGHT, type NOTE_HASH_TREE_HEIGHT } from '@aztec/constants';
|
|
6
7
|
import { EpochCache, type EpochCacheInterface } from '@aztec/epoch-cache';
|
|
7
8
|
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
8
|
-
import { getPublicClient } from '@aztec/ethereum/client';
|
|
9
|
+
import { getPublicClient, makeL1HttpTransport } from '@aztec/ethereum/client';
|
|
9
10
|
import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
10
11
|
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
12
|
+
import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
|
|
11
13
|
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
12
|
-
import { compactArray, pick, unique } from '@aztec/foundation/collection';
|
|
14
|
+
import { chunkBy, compactArray, pick, unique } from '@aztec/foundation/collection';
|
|
13
15
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
14
16
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
15
17
|
import { BadRequestError } from '@aztec/foundation/json-rpc';
|
|
@@ -79,8 +81,8 @@ import {
|
|
|
79
81
|
import type { DebugLogStore, LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
80
82
|
import { InMemoryDebugLogStore, NullDebugLogStore } from '@aztec/stdlib/logs';
|
|
81
83
|
import { InboxLeaf, type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
82
|
-
import type { Offense
|
|
83
|
-
import type { NullifierLeafPreimage,
|
|
84
|
+
import type { Offense } from '@aztec/stdlib/slashing';
|
|
85
|
+
import type { NullifierLeafPreimage, PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees';
|
|
84
86
|
import { MerkleTreeId, NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
85
87
|
import {
|
|
86
88
|
type BlockHeader,
|
|
@@ -95,6 +97,7 @@ import {
|
|
|
95
97
|
} from '@aztec/stdlib/tx';
|
|
96
98
|
import { getPackageVersion } from '@aztec/stdlib/update-checker';
|
|
97
99
|
import type { SingleValidatorStats, ValidatorsStats } from '@aztec/stdlib/validators';
|
|
100
|
+
import type { GenesisData } from '@aztec/stdlib/world-state';
|
|
98
101
|
import {
|
|
99
102
|
Attributes,
|
|
100
103
|
type TelemetryClient,
|
|
@@ -108,12 +111,13 @@ import {
|
|
|
108
111
|
FullNodeCheckpointsBuilder,
|
|
109
112
|
NodeKeystoreAdapter,
|
|
110
113
|
ValidatorClient,
|
|
111
|
-
|
|
114
|
+
createProposalHandler,
|
|
112
115
|
createValidatorClient,
|
|
113
116
|
} from '@aztec/validator-client';
|
|
117
|
+
import type { SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
|
|
114
118
|
import { createWorldStateSynchronizer } from '@aztec/world-state';
|
|
115
119
|
|
|
116
|
-
import { createPublicClient
|
|
120
|
+
import { createPublicClient } from 'viem';
|
|
117
121
|
|
|
118
122
|
import { createSentinel } from '../sentinel/factory.js';
|
|
119
123
|
import { Sentinel } from '../sentinel/sentinel.js';
|
|
@@ -150,7 +154,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
150
154
|
protected readonly globalVariableBuilder: GlobalVariableBuilderInterface,
|
|
151
155
|
protected readonly epochCache: EpochCacheInterface,
|
|
152
156
|
protected readonly packageVersion: string,
|
|
153
|
-
private
|
|
157
|
+
private peerProofVerifier: ClientProtocolCircuitVerifier,
|
|
158
|
+
private rpcProofVerifier: ClientProtocolCircuitVerifier,
|
|
154
159
|
private telemetry: TelemetryClient = getTelemetryClient(),
|
|
155
160
|
private log = createLogger('node'),
|
|
156
161
|
private blobClient?: BlobClientInterface,
|
|
@@ -172,6 +177,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
172
177
|
}
|
|
173
178
|
}
|
|
174
179
|
|
|
180
|
+
/** @internal Exposed for testing — returns the RPC proof verifier. */
|
|
181
|
+
public getProofVerifier(): ClientProtocolCircuitVerifier {
|
|
182
|
+
return this.rpcProofVerifier;
|
|
183
|
+
}
|
|
184
|
+
|
|
175
185
|
public async getWorldStateSyncStatus(): Promise<WorldStateSyncStatus> {
|
|
176
186
|
const status = await this.worldStateSynchronizer.status();
|
|
177
187
|
return status.syncSummary;
|
|
@@ -195,9 +205,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
195
205
|
dateProvider?: DateProvider;
|
|
196
206
|
p2pClientDeps?: P2PClientDeps;
|
|
197
207
|
proverNodeDeps?: Partial<ProverNodeDeps>;
|
|
208
|
+
slashingProtectionDb?: SlashingProtectionDatabase;
|
|
198
209
|
} = {},
|
|
199
210
|
options: {
|
|
200
|
-
|
|
211
|
+
genesis?: GenesisData;
|
|
201
212
|
dontStartSequencer?: boolean;
|
|
202
213
|
dontStartProverNode?: boolean;
|
|
203
214
|
} = {},
|
|
@@ -257,7 +268,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
257
268
|
|
|
258
269
|
const publicClient = createPublicClient({
|
|
259
270
|
chain: ethereumChain.chainInfo,
|
|
260
|
-
transport:
|
|
271
|
+
transport: makeL1HttpTransport(config.l1RpcUrls, { timeout: config.l1HttpTimeoutMS }),
|
|
261
272
|
pollingInterval: config.viemPollingIntervalMS,
|
|
262
273
|
});
|
|
263
274
|
|
|
@@ -271,10 +282,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
271
282
|
config.l1Contracts = { ...config.l1Contracts, ...l1ContractsAddresses };
|
|
272
283
|
|
|
273
284
|
const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
|
|
274
|
-
const [l1GenesisTime, slotDuration, rollupVersionFromRollup] = await Promise.all([
|
|
285
|
+
const [l1GenesisTime, slotDuration, rollupVersionFromRollup, rollupManaLimit] = await Promise.all([
|
|
275
286
|
rollupContract.getL1GenesisTime(),
|
|
276
287
|
rollupContract.getSlotDuration(),
|
|
277
288
|
rollupContract.getVersion(),
|
|
289
|
+
rollupContract.getManaLimit().then(Number),
|
|
278
290
|
] as const);
|
|
279
291
|
|
|
280
292
|
config.rollupVersion ??= Number(rollupVersionFromRollup);
|
|
@@ -299,16 +311,18 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
299
311
|
);
|
|
300
312
|
|
|
301
313
|
// now create the merkle trees and the world state synchronizer
|
|
302
|
-
const worldStateSynchronizer = await createWorldStateSynchronizer(
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
314
|
+
const worldStateSynchronizer = await createWorldStateSynchronizer(config, archiver, options.genesis, telemetry);
|
|
315
|
+
const useRealVerifiers = config.realProofs || config.debugForceTxProofVerification;
|
|
316
|
+
let peerProofVerifier: ClientProtocolCircuitVerifier;
|
|
317
|
+
let rpcProofVerifier: ClientProtocolCircuitVerifier;
|
|
318
|
+
if (useRealVerifiers) {
|
|
319
|
+
peerProofVerifier = await BatchChonkVerifier.new(config, config.bbChonkVerifyMaxBatch, 'peer');
|
|
320
|
+
const rpcVerifier = await BBCircuitVerifier.new(config);
|
|
321
|
+
rpcProofVerifier = new QueuedIVCVerifier(rpcVerifier, config.numConcurrentIVCVerifiers);
|
|
322
|
+
} else {
|
|
323
|
+
peerProofVerifier = new TestCircuitVerifier(config.proverTestVerificationDelayMs);
|
|
324
|
+
rpcProofVerifier = new TestCircuitVerifier(config.proverTestVerificationDelayMs);
|
|
325
|
+
}
|
|
312
326
|
|
|
313
327
|
let debugLogStore: DebugLogStore;
|
|
314
328
|
if (!config.realProofs) {
|
|
@@ -322,8 +336,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
322
336
|
debugLogStore = new NullDebugLogStore();
|
|
323
337
|
}
|
|
324
338
|
|
|
325
|
-
const proofVerifier = new QueuedIVCVerifier(config, circuitVerifier);
|
|
326
|
-
|
|
327
339
|
const proverOnly = config.enableProverNode && config.disableValidator;
|
|
328
340
|
if (proverOnly) {
|
|
329
341
|
log.info('Starting in prover-only mode: skipping validator, sequencer, sentinel, and slasher subsystems');
|
|
@@ -333,7 +345,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
333
345
|
const p2pClient = await createP2PClient(
|
|
334
346
|
config,
|
|
335
347
|
archiver,
|
|
336
|
-
|
|
348
|
+
peerProofVerifier,
|
|
337
349
|
worldStateSynchronizer,
|
|
338
350
|
epochCache,
|
|
339
351
|
packageVersion,
|
|
@@ -345,9 +357,16 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
345
357
|
// We'll accumulate sentinel watchers here
|
|
346
358
|
const watchers: Watcher[] = [];
|
|
347
359
|
|
|
348
|
-
// Create FullNodeCheckpointsBuilder for block proposal handling and tx validation
|
|
360
|
+
// Create FullNodeCheckpointsBuilder for block proposal handling and tx validation.
|
|
361
|
+
// Override maxTxsPerCheckpoint with the validator-specific limit if set.
|
|
349
362
|
const validatorCheckpointsBuilder = new FullNodeCheckpointsBuilder(
|
|
350
|
-
{
|
|
363
|
+
{
|
|
364
|
+
...config,
|
|
365
|
+
l1GenesisTime,
|
|
366
|
+
slotDuration: Number(slotDuration),
|
|
367
|
+
rollupManaLimit,
|
|
368
|
+
maxTxsPerCheckpoint: config.validateMaxTxsPerCheckpoint,
|
|
369
|
+
},
|
|
351
370
|
worldStateSynchronizer,
|
|
352
371
|
archiver,
|
|
353
372
|
dateProvider,
|
|
@@ -369,6 +388,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
369
388
|
l1ToL2MessageSource: archiver,
|
|
370
389
|
keyStoreManager,
|
|
371
390
|
blobClient,
|
|
391
|
+
slashingProtectionDb: deps.slashingProtectionDb,
|
|
372
392
|
});
|
|
373
393
|
|
|
374
394
|
// If we have a validator client, register it as a source of offenses for the slasher,
|
|
@@ -376,26 +396,35 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
376
396
|
// like attestations or auths will fail.
|
|
377
397
|
if (validatorClient) {
|
|
378
398
|
watchers.push(validatorClient);
|
|
399
|
+
|
|
400
|
+
const vc = validatorClient;
|
|
401
|
+
const getValidatorAddresses = () => vc.getValidatorAddresses().map(a => a.toString());
|
|
402
|
+
validatorClient.getProposalHandler().register(p2pClient, true, archiver, getValidatorAddresses);
|
|
403
|
+
|
|
379
404
|
if (!options.dontStartSequencer) {
|
|
380
405
|
await validatorClient.registerHandlers();
|
|
381
406
|
}
|
|
382
407
|
}
|
|
408
|
+
}
|
|
383
409
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
410
|
+
// If there's no validator client, create a ProposalHandler to handle block and checkpoint proposals
|
|
411
|
+
// for monitoring or reexecution. Reexecution (default) allows us to follow the pending chain,
|
|
412
|
+
// while non-reexecution is used for validating the proposals and collecting their txs.
|
|
413
|
+
// Checkpoint proposals rebuild blobs if the blob client can upload blobs.
|
|
414
|
+
if (!validatorClient) {
|
|
415
|
+
const reexecute = !!config.alwaysReexecuteBlockProposals;
|
|
416
|
+
log.info(`Setting up proposal handler` + (reexecute ? ' with reexecution of proposals' : ''));
|
|
417
|
+
createProposalHandler(config, {
|
|
418
|
+
checkpointsBuilder: validatorCheckpointsBuilder,
|
|
419
|
+
worldState: worldStateSynchronizer,
|
|
420
|
+
epochCache,
|
|
421
|
+
blockSource: archiver,
|
|
422
|
+
l1ToL2MessageSource: archiver,
|
|
423
|
+
p2pClient,
|
|
424
|
+
blobClient,
|
|
425
|
+
dateProvider,
|
|
426
|
+
telemetry,
|
|
427
|
+
}).register(p2pClient, reexecute, archiver);
|
|
399
428
|
}
|
|
400
429
|
|
|
401
430
|
// Start world state and wait for it to sync to the archiver.
|
|
@@ -445,6 +474,14 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
445
474
|
})
|
|
446
475
|
.catch(err => log.error('Failed to start p2p services after archiver sync', err));
|
|
447
476
|
|
|
477
|
+
const globalVariableBuilder = new GlobalVariableBuilder(dateProvider, publicClient, {
|
|
478
|
+
l1Contracts: config.l1Contracts,
|
|
479
|
+
ethereumSlotDuration: config.ethereumSlotDuration,
|
|
480
|
+
rollupVersion: BigInt(config.rollupVersion),
|
|
481
|
+
l1GenesisTime,
|
|
482
|
+
slotDuration: Number(slotDuration),
|
|
483
|
+
});
|
|
484
|
+
|
|
448
485
|
// Validator enabled, create/start relevant service
|
|
449
486
|
let sequencer: SequencerClient | undefined;
|
|
450
487
|
let slasherClient: SlasherClientInterface | undefined;
|
|
@@ -482,9 +519,22 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
482
519
|
{ telemetry, logger: log.createChild('l1-tx-utils'), dateProvider, kzg: Blob.getViemKzgInstance() },
|
|
483
520
|
);
|
|
484
521
|
|
|
522
|
+
// Create a funder L1TxUtils from the keystore funding account (if configured)
|
|
523
|
+
const fundingSigner = keyStoreManager?.createFundingSigner();
|
|
524
|
+
let funderL1TxUtils: L1TxUtils | undefined;
|
|
525
|
+
if (fundingSigner) {
|
|
526
|
+
const [funder] = await createL1TxUtilsFromSigners(
|
|
527
|
+
publicClient,
|
|
528
|
+
[fundingSigner],
|
|
529
|
+
{ ...config, scope: 'sequencer' },
|
|
530
|
+
{ telemetry, logger: log.createChild('l1-tx-utils:funder'), dateProvider },
|
|
531
|
+
);
|
|
532
|
+
funderL1TxUtils = funder;
|
|
533
|
+
}
|
|
534
|
+
|
|
485
535
|
// Create and start the sequencer client
|
|
486
536
|
const checkpointsBuilder = new CheckpointsBuilder(
|
|
487
|
-
{ ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
|
|
537
|
+
{ ...config, l1GenesisTime, slotDuration: Number(slotDuration), rollupManaLimit },
|
|
488
538
|
worldStateSynchronizer,
|
|
489
539
|
archiver,
|
|
490
540
|
dateProvider,
|
|
@@ -496,6 +546,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
496
546
|
...deps,
|
|
497
547
|
epochCache,
|
|
498
548
|
l1TxUtils,
|
|
549
|
+
funderL1TxUtils,
|
|
499
550
|
validatorClient,
|
|
500
551
|
p2pClient,
|
|
501
552
|
worldStateSynchronizer,
|
|
@@ -507,6 +558,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
507
558
|
dateProvider,
|
|
508
559
|
blobClient,
|
|
509
560
|
nodeKeyStore: keyStoreManager!,
|
|
561
|
+
globalVariableBuilder,
|
|
510
562
|
});
|
|
511
563
|
}
|
|
512
564
|
|
|
@@ -540,13 +592,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
540
592
|
}
|
|
541
593
|
}
|
|
542
594
|
|
|
543
|
-
const globalVariableBuilder = new GlobalVariableBuilder({
|
|
544
|
-
...config,
|
|
545
|
-
rollupVersion: BigInt(config.rollupVersion),
|
|
546
|
-
l1GenesisTime,
|
|
547
|
-
slotDuration: Number(slotDuration),
|
|
548
|
-
});
|
|
549
|
-
|
|
550
595
|
const node = new AztecNodeService(
|
|
551
596
|
config,
|
|
552
597
|
p2pClient,
|
|
@@ -565,7 +610,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
565
610
|
globalVariableBuilder,
|
|
566
611
|
epochCache,
|
|
567
612
|
packageVersion,
|
|
568
|
-
|
|
613
|
+
peerProofVerifier,
|
|
614
|
+
rpcProofVerifier,
|
|
569
615
|
telemetry,
|
|
570
616
|
log,
|
|
571
617
|
blobClient,
|
|
@@ -710,6 +756,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
710
756
|
return (await this.blockSource.getCheckpointedBlocks(from, limit)) ?? [];
|
|
711
757
|
}
|
|
712
758
|
|
|
759
|
+
public getCheckpointsDataForEpoch(epochNumber: EpochNumber) {
|
|
760
|
+
return this.blockSource.getCheckpointsDataForEpoch(epochNumber);
|
|
761
|
+
}
|
|
762
|
+
|
|
713
763
|
/**
|
|
714
764
|
* Method to fetch the current min L2 fees.
|
|
715
765
|
* @returns The current min L2 fees.
|
|
@@ -742,6 +792,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
742
792
|
return await this.blockSource.getCheckpointedL2BlockNumber();
|
|
743
793
|
}
|
|
744
794
|
|
|
795
|
+
public getCheckpointNumber(): Promise<CheckpointNumber> {
|
|
796
|
+
return this.blockSource.getCheckpointNumber();
|
|
797
|
+
}
|
|
798
|
+
|
|
745
799
|
/**
|
|
746
800
|
* Method to fetch the version of the package.
|
|
747
801
|
* @returns The node package version
|
|
@@ -779,18 +833,22 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
779
833
|
page?: number,
|
|
780
834
|
referenceBlock?: BlockHash,
|
|
781
835
|
): Promise<TxScopedL2Log[][]> {
|
|
836
|
+
let upToBlockNumber: BlockNumber | undefined;
|
|
782
837
|
if (referenceBlock) {
|
|
783
838
|
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
784
|
-
if (
|
|
839
|
+
if (referenceBlock.equals(initialBlockHash)) {
|
|
840
|
+
upToBlockNumber = BlockNumber(0);
|
|
841
|
+
} else {
|
|
785
842
|
const header = await this.blockSource.getBlockHeaderByHash(referenceBlock);
|
|
786
843
|
if (!header) {
|
|
787
844
|
throw new Error(
|
|
788
845
|
`Block ${referenceBlock.toString()} not found in the node. This might indicate a reorg has occurred.`,
|
|
789
846
|
);
|
|
790
847
|
}
|
|
848
|
+
upToBlockNumber = header.globalVariables.blockNumber;
|
|
791
849
|
}
|
|
792
850
|
}
|
|
793
|
-
return this.logsSource.getPrivateLogsByTags(tags, page);
|
|
851
|
+
return this.logsSource.getPrivateLogsByTags(tags, page, upToBlockNumber);
|
|
794
852
|
}
|
|
795
853
|
|
|
796
854
|
public async getPublicLogsByTagsFromContract(
|
|
@@ -799,18 +857,22 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
799
857
|
page?: number,
|
|
800
858
|
referenceBlock?: BlockHash,
|
|
801
859
|
): Promise<TxScopedL2Log[][]> {
|
|
860
|
+
let upToBlockNumber: BlockNumber | undefined;
|
|
802
861
|
if (referenceBlock) {
|
|
803
862
|
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
804
|
-
if (
|
|
863
|
+
if (referenceBlock.equals(initialBlockHash)) {
|
|
864
|
+
upToBlockNumber = BlockNumber(0);
|
|
865
|
+
} else {
|
|
805
866
|
const header = await this.blockSource.getBlockHeaderByHash(referenceBlock);
|
|
806
867
|
if (!header) {
|
|
807
868
|
throw new Error(
|
|
808
869
|
`Block ${referenceBlock.toString()} not found in the node. This might indicate a reorg has occurred.`,
|
|
809
870
|
);
|
|
810
871
|
}
|
|
872
|
+
upToBlockNumber = header.globalVariables.blockNumber;
|
|
811
873
|
}
|
|
812
874
|
}
|
|
813
|
-
return this.logsSource.getPublicLogsByTagsFromContract(contractAddress, tags, page);
|
|
875
|
+
return this.logsSource.getPublicLogsByTagsFromContract(contractAddress, tags, page, upToBlockNumber);
|
|
814
876
|
}
|
|
815
877
|
|
|
816
878
|
/**
|
|
@@ -896,7 +958,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
896
958
|
await tryStop(this.validatorsSentinel);
|
|
897
959
|
await tryStop(this.epochPruneWatcher);
|
|
898
960
|
await tryStop(this.slasherClient);
|
|
899
|
-
await tryStop(this.
|
|
961
|
+
await Promise.all([tryStop(this.peerProofVerifier), tryStop(this.rpcProofVerifier)]);
|
|
900
962
|
await tryStop(this.sequencer);
|
|
901
963
|
await tryStop(this.proverNode);
|
|
902
964
|
await tryStop(this.p2pClient);
|
|
@@ -952,58 +1014,64 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
952
1014
|
treeId: MerkleTreeId,
|
|
953
1015
|
leafValues: Fr[],
|
|
954
1016
|
): Promise<(DataInBlock<bigint> | undefined)[]> {
|
|
955
|
-
const committedDb = await this
|
|
1017
|
+
const committedDb = await this.getWorldState(referenceBlock);
|
|
956
1018
|
const maybeIndices = await committedDb.findLeafIndices(
|
|
957
1019
|
treeId,
|
|
958
1020
|
leafValues.map(x => x.toBuffer()),
|
|
959
1021
|
);
|
|
960
|
-
//
|
|
961
|
-
const
|
|
1022
|
+
// Filter out undefined values to query block numbers only for found leaves
|
|
1023
|
+
const definedIndices = maybeIndices.filter(x => x !== undefined);
|
|
962
1024
|
|
|
963
|
-
// Now we find the block numbers for the indices
|
|
964
|
-
const blockNumbers = await committedDb.getBlockNumbersForLeafIndices(treeId,
|
|
1025
|
+
// Now we find the block numbers for the defined indices
|
|
1026
|
+
const blockNumbers = await committedDb.getBlockNumbersForLeafIndices(treeId, definedIndices);
|
|
965
1027
|
|
|
966
|
-
//
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1028
|
+
// Build a map from leaf index to block number
|
|
1029
|
+
const indexToBlockNumber = new Map<bigint, BlockNumber>();
|
|
1030
|
+
for (let i = 0; i < definedIndices.length; i++) {
|
|
1031
|
+
const blockNumber = blockNumbers[i];
|
|
1032
|
+
if (blockNumber === undefined) {
|
|
1033
|
+
throw new Error(
|
|
1034
|
+
`Block number is undefined for leaf index ${definedIndices[i]} in tree ${MerkleTreeId[treeId]}`,
|
|
1035
|
+
);
|
|
970
1036
|
}
|
|
1037
|
+
indexToBlockNumber.set(definedIndices[i], blockNumber);
|
|
971
1038
|
}
|
|
972
1039
|
|
|
973
1040
|
// Get unique block numbers in order to optimize num calls to getLeafValue function.
|
|
974
|
-
const uniqueBlockNumbers = [...new Set(
|
|
1041
|
+
const uniqueBlockNumbers = [...new Set(indexToBlockNumber.values())];
|
|
975
1042
|
|
|
976
|
-
// Now we obtain the block hashes from the archive tree
|
|
977
|
-
// (note that block number corresponds to the leaf index in the archive tree).
|
|
1043
|
+
// Now we obtain the block hashes from the archive tree (block number = leaf index in archive tree).
|
|
978
1044
|
const blockHashes = await Promise.all(
|
|
979
1045
|
uniqueBlockNumbers.map(blockNumber => {
|
|
980
1046
|
return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
|
|
981
1047
|
}),
|
|
982
1048
|
);
|
|
983
1049
|
|
|
984
|
-
//
|
|
1050
|
+
// Build a map from block number to block hash
|
|
1051
|
+
const blockNumberToHash = new Map<BlockNumber, Fr>();
|
|
985
1052
|
for (let i = 0; i < uniqueBlockNumbers.length; i++) {
|
|
986
|
-
|
|
1053
|
+
const blockHash = blockHashes[i];
|
|
1054
|
+
if (blockHash === undefined) {
|
|
987
1055
|
throw new Error(`Block hash is undefined for block number ${uniqueBlockNumbers[i]}`);
|
|
988
1056
|
}
|
|
1057
|
+
blockNumberToHash.set(uniqueBlockNumbers[i], blockHash);
|
|
989
1058
|
}
|
|
990
1059
|
|
|
991
1060
|
// Create DataInBlock objects by combining indices, blockNumbers and blockHashes and return them.
|
|
992
|
-
return maybeIndices.map(
|
|
1061
|
+
return maybeIndices.map(index => {
|
|
993
1062
|
if (index === undefined) {
|
|
994
1063
|
return undefined;
|
|
995
1064
|
}
|
|
996
|
-
const blockNumber =
|
|
1065
|
+
const blockNumber = indexToBlockNumber.get(index);
|
|
997
1066
|
if (blockNumber === undefined) {
|
|
998
|
-
|
|
1067
|
+
throw new Error(`Block number not found for leaf index ${index} in tree ${MerkleTreeId[treeId]}`);
|
|
999
1068
|
}
|
|
1000
|
-
const
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
return undefined;
|
|
1069
|
+
const blockHash = blockNumberToHash.get(blockNumber);
|
|
1070
|
+
if (blockHash === undefined) {
|
|
1071
|
+
throw new Error(`Block hash not found for block number ${blockNumber}`);
|
|
1004
1072
|
}
|
|
1005
1073
|
return {
|
|
1006
|
-
l2BlockNumber:
|
|
1074
|
+
l2BlockNumber: blockNumber,
|
|
1007
1075
|
l2BlockHash: new BlockHash(blockHash),
|
|
1008
1076
|
data: index,
|
|
1009
1077
|
};
|
|
@@ -1014,7 +1082,15 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1014
1082
|
referenceBlock: BlockParameter,
|
|
1015
1083
|
blockHash: BlockHash,
|
|
1016
1084
|
): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
|
|
1017
|
-
|
|
1085
|
+
// The Noir circuit checks the archive membership proof against `anchor_block_header.last_archive.root`,
|
|
1086
|
+
// which is the archive tree root BEFORE the anchor block was added (i.e. the state after block N-1).
|
|
1087
|
+
// So we need the world state at block N-1, not block N, to produce a sibling path matching that root.
|
|
1088
|
+
const referenceBlockNumber = await this.resolveBlockNumber(referenceBlock);
|
|
1089
|
+
if (referenceBlockNumber === BlockNumber.ZERO) {
|
|
1090
|
+
// Block 0 (the initial block) has an empty archive, so no membership witness can exist.
|
|
1091
|
+
return undefined;
|
|
1092
|
+
}
|
|
1093
|
+
const committedDb = await this.getWorldState(BlockNumber(referenceBlockNumber - 1));
|
|
1018
1094
|
const [pathAndIndex] = await committedDb.findSiblingPaths<MerkleTreeId.ARCHIVE>(MerkleTreeId.ARCHIVE, [blockHash]);
|
|
1019
1095
|
return pathAndIndex === undefined
|
|
1020
1096
|
? undefined
|
|
@@ -1025,7 +1101,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1025
1101
|
referenceBlock: BlockParameter,
|
|
1026
1102
|
noteHash: Fr,
|
|
1027
1103
|
): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
|
|
1028
|
-
const committedDb = await this
|
|
1104
|
+
const committedDb = await this.getWorldState(referenceBlock);
|
|
1029
1105
|
const [pathAndIndex] = await committedDb.findSiblingPaths<MerkleTreeId.NOTE_HASH_TREE>(
|
|
1030
1106
|
MerkleTreeId.NOTE_HASH_TREE,
|
|
1031
1107
|
[noteHash],
|
|
@@ -1039,7 +1115,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1039
1115
|
referenceBlock: BlockParameter,
|
|
1040
1116
|
l1ToL2Message: Fr,
|
|
1041
1117
|
): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>] | undefined> {
|
|
1042
|
-
const db = await this
|
|
1118
|
+
const db = await this.getWorldState(referenceBlock);
|
|
1043
1119
|
const [witness] = await db.findSiblingPaths(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, [l1ToL2Message]);
|
|
1044
1120
|
if (!witness) {
|
|
1045
1121
|
return undefined;
|
|
@@ -1049,11 +1125,9 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1049
1125
|
return [witness.index, witness.path];
|
|
1050
1126
|
}
|
|
1051
1127
|
|
|
1052
|
-
public async
|
|
1128
|
+
public async getL1ToL2MessageCheckpoint(l1ToL2Message: Fr): Promise<CheckpointNumber | undefined> {
|
|
1053
1129
|
const messageIndex = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
|
|
1054
|
-
return messageIndex
|
|
1055
|
-
? BlockNumber.fromCheckpointNumber(InboxLeaf.checkpointNumberFromIndex(messageIndex))
|
|
1056
|
-
: undefined;
|
|
1130
|
+
return messageIndex ? InboxLeaf.checkpointNumberFromIndex(messageIndex) : undefined;
|
|
1057
1131
|
}
|
|
1058
1132
|
|
|
1059
1133
|
/**
|
|
@@ -1074,19 +1148,9 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1074
1148
|
public async getL2ToL1Messages(epoch: EpochNumber): Promise<Fr[][][][]> {
|
|
1075
1149
|
// Assumes `getCheckpointedBlocksForEpoch` returns blocks in ascending order of block number.
|
|
1076
1150
|
const checkpointedBlocks = await this.blockSource.getCheckpointedBlocksForEpoch(epoch);
|
|
1077
|
-
const blocksInCheckpoints
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
for (const checkpointedBlock of checkpointedBlocks) {
|
|
1081
|
-
const block = checkpointedBlock.block;
|
|
1082
|
-
const slotNumber = block.header.globalVariables.slotNumber;
|
|
1083
|
-
if (slotNumber !== previousSlotNumber) {
|
|
1084
|
-
checkpointIndex++;
|
|
1085
|
-
blocksInCheckpoints.push([]);
|
|
1086
|
-
previousSlotNumber = slotNumber;
|
|
1087
|
-
}
|
|
1088
|
-
blocksInCheckpoints[checkpointIndex].push(block);
|
|
1089
|
-
}
|
|
1151
|
+
const blocksInCheckpoints = chunkBy(checkpointedBlocks, cb => cb.block.header.globalVariables.slotNumber).map(
|
|
1152
|
+
group => group.map(cb => cb.block),
|
|
1153
|
+
);
|
|
1090
1154
|
return blocksInCheckpoints.map(blocks =>
|
|
1091
1155
|
blocks.map(block => block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs)),
|
|
1092
1156
|
);
|
|
@@ -1096,7 +1160,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1096
1160
|
referenceBlock: BlockParameter,
|
|
1097
1161
|
nullifier: Fr,
|
|
1098
1162
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
1099
|
-
const db = await this
|
|
1163
|
+
const db = await this.getWorldState(referenceBlock);
|
|
1100
1164
|
const [witness] = await db.findSiblingPaths(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
1101
1165
|
if (!witness) {
|
|
1102
1166
|
return undefined;
|
|
@@ -1111,33 +1175,20 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1111
1175
|
return new NullifierMembershipWitness(index, leafPreimage as NullifierLeafPreimage, path);
|
|
1112
1176
|
}
|
|
1113
1177
|
|
|
1114
|
-
/**
|
|
1115
|
-
* Returns a low nullifier membership witness for a given nullifier at a given block.
|
|
1116
|
-
* @param referenceBlock - The block parameter (block number, block hash, or 'latest') at which to get the data
|
|
1117
|
-
* (which contains the root of the nullifier tree in which we are searching for the nullifier).
|
|
1118
|
-
* @param nullifier - Nullifier we try to find the low nullifier witness for.
|
|
1119
|
-
* @returns The low nullifier membership witness (if found).
|
|
1120
|
-
* @remarks Low nullifier witness can be used to perform a nullifier non-inclusion proof by leveraging the "linked
|
|
1121
|
-
* list structure" of leaves and proving that a lower nullifier is pointing to a bigger next value than the nullifier
|
|
1122
|
-
* we are trying to prove non-inclusion for.
|
|
1123
|
-
*
|
|
1124
|
-
* Note: This function returns the membership witness of the nullifier itself and not the low nullifier when
|
|
1125
|
-
* the nullifier already exists in the tree. This is because the `getPreviousValueIndex` function returns the
|
|
1126
|
-
* index of the nullifier itself when it already exists in the tree.
|
|
1127
|
-
* TODO: This is a confusing behavior and we should eventually address that.
|
|
1128
|
-
*/
|
|
1129
1178
|
public async getLowNullifierMembershipWitness(
|
|
1130
1179
|
referenceBlock: BlockParameter,
|
|
1131
1180
|
nullifier: Fr,
|
|
1132
1181
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
1133
|
-
const committedDb = await this
|
|
1182
|
+
const committedDb = await this.getWorldState(referenceBlock);
|
|
1134
1183
|
const findResult = await committedDb.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
1135
1184
|
if (!findResult) {
|
|
1136
1185
|
return undefined;
|
|
1137
1186
|
}
|
|
1138
1187
|
const { index, alreadyPresent } = findResult;
|
|
1139
1188
|
if (alreadyPresent) {
|
|
1140
|
-
|
|
1189
|
+
throw new Error(
|
|
1190
|
+
`Cannot prove nullifier non-inclusion: nullifier ${nullifier.toBigInt()} already exists in the tree`,
|
|
1191
|
+
);
|
|
1141
1192
|
}
|
|
1142
1193
|
const preimageData = (await committedDb.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))!;
|
|
1143
1194
|
|
|
@@ -1146,7 +1197,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1146
1197
|
}
|
|
1147
1198
|
|
|
1148
1199
|
async getPublicDataWitness(referenceBlock: BlockParameter, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
1149
|
-
const committedDb = await this
|
|
1200
|
+
const committedDb = await this.getWorldState(referenceBlock);
|
|
1150
1201
|
const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
1151
1202
|
if (!lowLeafResult) {
|
|
1152
1203
|
return undefined;
|
|
@@ -1161,7 +1212,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1161
1212
|
}
|
|
1162
1213
|
|
|
1163
1214
|
public async getPublicStorageAt(referenceBlock: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr> {
|
|
1164
|
-
const committedDb = await this
|
|
1215
|
+
const committedDb = await this.getWorldState(referenceBlock);
|
|
1165
1216
|
const leafSlot = await computePublicDataTreeLeafSlot(contract, slot);
|
|
1166
1217
|
|
|
1167
1218
|
const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
@@ -1275,7 +1326,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1275
1326
|
const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, config);
|
|
1276
1327
|
|
|
1277
1328
|
// REFACTOR: Consider merging ProcessReturnValues into ProcessedTx
|
|
1278
|
-
const [processedTxs, failedTxs, _usedTxs, returns,
|
|
1329
|
+
const [processedTxs, failedTxs, _usedTxs, returns, debugLogs] = await processor.process([tx]);
|
|
1279
1330
|
// REFACTOR: Consider returning the error rather than throwing
|
|
1280
1331
|
if (failedTxs.length) {
|
|
1281
1332
|
this.log.warn(`Simulated tx ${txHash} fails: ${failedTxs[0].error}`, { txHash });
|
|
@@ -1301,11 +1352,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1301
1352
|
{ isSimulation, skipFeeEnforcement }: { isSimulation?: boolean; skipFeeEnforcement?: boolean } = {},
|
|
1302
1353
|
): Promise<TxValidationResult> {
|
|
1303
1354
|
const db = this.worldStateSynchronizer.getCommitted();
|
|
1304
|
-
const verifier = isSimulation ? undefined : this.
|
|
1355
|
+
const verifier = isSimulation ? undefined : this.rpcProofVerifier;
|
|
1305
1356
|
|
|
1306
1357
|
// We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
|
|
1307
1358
|
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1308
1359
|
const blockNumber = BlockNumber((await this.blockSource.getBlockNumber()) + 1);
|
|
1360
|
+
const l1Constants = await this.blockSource.getL1Constants();
|
|
1309
1361
|
const validator = createTxValidatorForAcceptingTxsOverRPC(
|
|
1310
1362
|
db,
|
|
1311
1363
|
this.contractDataSource,
|
|
@@ -1322,6 +1374,9 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1322
1374
|
gasFees: await this.getCurrentMinFees(),
|
|
1323
1375
|
skipFeeEnforcement,
|
|
1324
1376
|
txsPermitted: !this.config.disableTransactions,
|
|
1377
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
1378
|
+
maxBlockL2Gas: this.config.validateMaxL2BlockGas,
|
|
1379
|
+
maxBlockDAGas: this.config.validateMaxDABlockGas,
|
|
1325
1380
|
},
|
|
1326
1381
|
this.log.getBindings(),
|
|
1327
1382
|
);
|
|
@@ -1346,7 +1401,15 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1346
1401
|
archiver.updateConfig(config);
|
|
1347
1402
|
}
|
|
1348
1403
|
if (newConfig.realProofs !== this.config.realProofs) {
|
|
1349
|
-
|
|
1404
|
+
await Promise.all([tryStop(this.peerProofVerifier), tryStop(this.rpcProofVerifier)]);
|
|
1405
|
+
if (newConfig.realProofs) {
|
|
1406
|
+
this.peerProofVerifier = await BatchChonkVerifier.new(newConfig, newConfig.bbChonkVerifyMaxBatch, 'peer');
|
|
1407
|
+
const rpcVerifier = await BBCircuitVerifier.new(newConfig);
|
|
1408
|
+
this.rpcProofVerifier = new QueuedIVCVerifier(rpcVerifier, newConfig.numConcurrentIVCVerifiers);
|
|
1409
|
+
} else {
|
|
1410
|
+
this.peerProofVerifier = new TestCircuitVerifier();
|
|
1411
|
+
this.rpcProofVerifier = new TestCircuitVerifier();
|
|
1412
|
+
}
|
|
1350
1413
|
}
|
|
1351
1414
|
|
|
1352
1415
|
this.config = newConfig;
|
|
@@ -1421,7 +1484,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1421
1484
|
return Promise.resolve();
|
|
1422
1485
|
}
|
|
1423
1486
|
|
|
1424
|
-
public async rollbackTo(targetBlock: BlockNumber, force?: boolean): Promise<void> {
|
|
1487
|
+
public async rollbackTo(targetBlock: BlockNumber, force?: boolean, resumeSync = true): Promise<void> {
|
|
1425
1488
|
const archiver = this.blockSource as Archiver;
|
|
1426
1489
|
if (!('rollbackTo' in archiver)) {
|
|
1427
1490
|
throw new Error('Archiver implementation does not support rollbacks.');
|
|
@@ -1451,9 +1514,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1451
1514
|
this.log.error(`Error during rollback`, err);
|
|
1452
1515
|
throw err;
|
|
1453
1516
|
} finally {
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1517
|
+
if (resumeSync) {
|
|
1518
|
+
this.log.info(`Resuming world state and archiver sync.`);
|
|
1519
|
+
this.worldStateSynchronizer.resumeSync();
|
|
1520
|
+
archiver.resume();
|
|
1521
|
+
} else {
|
|
1522
|
+
this.log.info(`Sync left paused after rollback (resumeSync=false).`);
|
|
1523
|
+
}
|
|
1457
1524
|
}
|
|
1458
1525
|
}
|
|
1459
1526
|
|
|
@@ -1470,19 +1537,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1470
1537
|
return Promise.resolve();
|
|
1471
1538
|
}
|
|
1472
1539
|
|
|
1473
|
-
public getSlashPayloads(): Promise<SlashPayloadRound[]> {
|
|
1474
|
-
if (!this.slasherClient) {
|
|
1475
|
-
throw new Error(`Slasher client not enabled`);
|
|
1476
|
-
}
|
|
1477
|
-
return this.slasherClient.getSlashPayloads();
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
1540
|
public getSlashOffenses(round: bigint | 'all' | 'current'): Promise<Offense[]> {
|
|
1481
1541
|
if (!this.slasherClient) {
|
|
1482
1542
|
throw new Error(`Slasher client not enabled`);
|
|
1483
1543
|
}
|
|
1484
1544
|
if (round === 'all') {
|
|
1485
|
-
return this.slasherClient.
|
|
1545
|
+
return this.slasherClient.getOffenses();
|
|
1486
1546
|
} else {
|
|
1487
1547
|
return this.slasherClient.gatherOffensesForRound(round === 'current' ? undefined : BigInt(round));
|
|
1488
1548
|
}
|
|
@@ -1588,7 +1648,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1588
1648
|
* @param block - The block parameter (block number, block hash, or 'latest') at which to get the data.
|
|
1589
1649
|
* @returns An instance of a committed MerkleTreeOperations
|
|
1590
1650
|
*/
|
|
1591
|
-
async
|
|
1651
|
+
protected async getWorldState(block: BlockParameter) {
|
|
1592
1652
|
let blockSyncedTo: BlockNumber = BlockNumber.ZERO;
|
|
1593
1653
|
try {
|
|
1594
1654
|
// Attempt to sync the world state if necessary
|
|
@@ -1602,6 +1662,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1602
1662
|
return this.worldStateSynchronizer.getCommitted();
|
|
1603
1663
|
}
|
|
1604
1664
|
|
|
1665
|
+
// Get the block number, either directly from the parameter or by quering the archiver with the block hash
|
|
1666
|
+
let blockNumber: BlockNumber;
|
|
1605
1667
|
if (BlockHash.isBlockHash(block)) {
|
|
1606
1668
|
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
1607
1669
|
if (block.equals(initialBlockHash)) {
|
|
@@ -1615,22 +1677,50 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1615
1677
|
`Block hash ${block.toString()} not found when querying world state. If the node API has been queried with anchor block hash possibly a reorg has occurred.`,
|
|
1616
1678
|
);
|
|
1617
1679
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1680
|
+
|
|
1681
|
+
blockNumber = header.getBlockNumber();
|
|
1682
|
+
} else {
|
|
1683
|
+
blockNumber = block as BlockNumber;
|
|
1621
1684
|
}
|
|
1622
1685
|
|
|
1623
|
-
//
|
|
1624
|
-
{
|
|
1625
|
-
|
|
1686
|
+
// Check it's within world state sync range
|
|
1687
|
+
if (blockNumber > blockSyncedTo) {
|
|
1688
|
+
throw new Error(`Queried block ${block} not yet synced by the node (node is synced upto ${blockSyncedTo}).`);
|
|
1689
|
+
}
|
|
1690
|
+
this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
1626
1691
|
|
|
1627
|
-
|
|
1628
|
-
|
|
1692
|
+
const snapshot = this.worldStateSynchronizer.getSnapshot(blockNumber);
|
|
1693
|
+
|
|
1694
|
+
// Double-check world-state synced to the same block hash as was requested
|
|
1695
|
+
if (BlockHash.isBlockHash(block)) {
|
|
1696
|
+
const blockHash = await snapshot.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
|
|
1697
|
+
if (!blockHash || !new BlockHash(blockHash).equals(block)) {
|
|
1698
|
+
throw new Error(
|
|
1699
|
+
`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.`,
|
|
1700
|
+
);
|
|
1629
1701
|
}
|
|
1702
|
+
}
|
|
1630
1703
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1704
|
+
return snapshot;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
/** Resolves a block parameter to a block number. */
|
|
1708
|
+
protected async resolveBlockNumber(block: BlockParameter): Promise<BlockNumber> {
|
|
1709
|
+
if (block === 'latest') {
|
|
1710
|
+
return BlockNumber(await this.blockSource.getBlockNumber());
|
|
1711
|
+
}
|
|
1712
|
+
if (BlockHash.isBlockHash(block)) {
|
|
1713
|
+
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
1714
|
+
if (block.equals(initialBlockHash)) {
|
|
1715
|
+
return BlockNumber.ZERO;
|
|
1716
|
+
}
|
|
1717
|
+
const header = await this.blockSource.getBlockHeaderByHash(block);
|
|
1718
|
+
if (!header) {
|
|
1719
|
+
throw new Error(`Block hash ${block.toString()} not found.`);
|
|
1720
|
+
}
|
|
1721
|
+
return header.getBlockNumber();
|
|
1633
1722
|
}
|
|
1723
|
+
return block as BlockNumber;
|
|
1634
1724
|
}
|
|
1635
1725
|
|
|
1636
1726
|
/**
|