@aztec/aztec-node 0.0.1-commit.c7c42ec → 0.0.1-commit.f295ac2
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/node_metrics.d.ts +1 -1
- package/dest/aztec-node/node_metrics.d.ts.map +1 -1
- package/dest/aztec-node/node_metrics.js +5 -16
- package/dest/aztec-node/server.d.ts +42 -97
- package/dest/aztec-node/server.d.ts.map +1 -1
- package/dest/aztec-node/server.js +539 -157
- package/dest/sentinel/sentinel.d.ts +5 -4
- package/dest/sentinel/sentinel.d.ts.map +1 -1
- package/dest/sentinel/sentinel.js +31 -26
- package/dest/sentinel/store.d.ts +2 -2
- package/dest/sentinel/store.d.ts.map +1 -1
- package/package.json +26 -26
- package/src/aztec-node/node_metrics.ts +5 -23
- package/src/aztec-node/server.ts +182 -182
- package/src/sentinel/sentinel.ts +41 -32
package/src/aztec-node/server.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { Archiver, createArchiver } from '@aztec/archiver';
|
|
2
2
|
import { BBCircuitVerifier, QueuedIVCVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
|
|
3
|
-
import { type BlobClientInterface,
|
|
4
|
-
import {
|
|
5
|
-
type BlobFileStoreMetadata,
|
|
6
|
-
createReadOnlyFileStoreBlobClients,
|
|
7
|
-
createWritableFileStoreBlobClient,
|
|
8
|
-
} from '@aztec/blob-client/filestore';
|
|
3
|
+
import { type BlobClientInterface, createBlobClientWithFileStores } from '@aztec/blob-client/client';
|
|
9
4
|
import {
|
|
10
5
|
ARCHIVE_HEIGHT,
|
|
11
|
-
INITIAL_L2_BLOCK_NUM,
|
|
12
6
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
13
7
|
type NOTE_HASH_TREE_HEIGHT,
|
|
14
8
|
type NULLIFIER_TREE_HEIGHT,
|
|
@@ -19,7 +13,7 @@ import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
|
19
13
|
import { getPublicClient } from '@aztec/ethereum/client';
|
|
20
14
|
import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
21
15
|
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
22
|
-
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
16
|
+
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
23
17
|
import { compactArray, pick } from '@aztec/foundation/collection';
|
|
24
18
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
25
19
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -36,14 +30,7 @@ import {
|
|
|
36
30
|
} from '@aztec/node-lib/factories';
|
|
37
31
|
import { type P2P, type P2PClientDeps, createP2PClient, getDefaultAllowedSetupFunctions } from '@aztec/p2p';
|
|
38
32
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
39
|
-
import {
|
|
40
|
-
BlockBuilder,
|
|
41
|
-
GlobalVariableBuilder,
|
|
42
|
-
SequencerClient,
|
|
43
|
-
type SequencerPublisher,
|
|
44
|
-
createValidatorForAcceptingTxs,
|
|
45
|
-
} from '@aztec/sequencer-client';
|
|
46
|
-
import { CheckpointsBuilder } from '@aztec/sequencer-client';
|
|
33
|
+
import { GlobalVariableBuilder, SequencerClient, type SequencerPublisher } from '@aztec/sequencer-client';
|
|
47
34
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
48
35
|
import {
|
|
49
36
|
AttestationsBlockWatcher,
|
|
@@ -56,12 +43,13 @@ import { CollectionLimitsConfig, PublicSimulatorConfig } from '@aztec/stdlib/avm
|
|
|
56
43
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
57
44
|
import {
|
|
58
45
|
type BlockParameter,
|
|
46
|
+
type CheckpointedL2Block,
|
|
59
47
|
type DataInBlock,
|
|
60
|
-
type L2Block,
|
|
61
48
|
L2BlockHash,
|
|
49
|
+
L2BlockNew,
|
|
62
50
|
type L2BlockSource,
|
|
63
|
-
type PublishedL2Block,
|
|
64
51
|
} from '@aztec/stdlib/block';
|
|
52
|
+
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
65
53
|
import type {
|
|
66
54
|
ContractClassPublic,
|
|
67
55
|
ContractDataSource,
|
|
@@ -116,10 +104,13 @@ import {
|
|
|
116
104
|
trackSpan,
|
|
117
105
|
} from '@aztec/telemetry-client';
|
|
118
106
|
import {
|
|
107
|
+
FullNodeCheckpointsBuilder as CheckpointsBuilder,
|
|
108
|
+
FullNodeCheckpointsBuilder,
|
|
119
109
|
NodeKeystoreAdapter,
|
|
120
110
|
ValidatorClient,
|
|
121
111
|
createBlockProposalHandler,
|
|
122
112
|
createValidatorClient,
|
|
113
|
+
createValidatorForAcceptingTxs,
|
|
123
114
|
} from '@aztec/validator-client';
|
|
124
115
|
import { createWorldStateSynchronizer } from '@aztec/world-state';
|
|
125
116
|
|
|
@@ -135,6 +126,7 @@ import { NodeMetrics } from './node_metrics.js';
|
|
|
135
126
|
*/
|
|
136
127
|
export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
137
128
|
private metrics: NodeMetrics;
|
|
129
|
+
private initialHeaderHashPromise: Promise<L2BlockHash> | undefined = undefined;
|
|
138
130
|
|
|
139
131
|
// Prevent two snapshot operations to happen simultaneously
|
|
140
132
|
private isUploadingSnapshot = false;
|
|
@@ -191,7 +183,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
191
183
|
logger?: Logger;
|
|
192
184
|
publisher?: SequencerPublisher;
|
|
193
185
|
dateProvider?: DateProvider;
|
|
194
|
-
blobClient?: BlobClientInterface;
|
|
195
186
|
p2pClientDeps?: P2PClientDeps<P2PClientType.Full>;
|
|
196
187
|
} = {},
|
|
197
188
|
options: {
|
|
@@ -271,24 +262,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
271
262
|
);
|
|
272
263
|
}
|
|
273
264
|
|
|
274
|
-
const
|
|
275
|
-
l1ChainId: config.l1ChainId,
|
|
276
|
-
rollupVersion: config.rollupVersion,
|
|
277
|
-
rollupAddress: config.l1Contracts.rollupAddress.toString(),
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
const [fileStoreClients, fileStoreUploadClient] = await Promise.all([
|
|
281
|
-
createReadOnlyFileStoreBlobClients(config.blobFileStoreUrls, blobFileStoreMetadata, log),
|
|
282
|
-
createWritableFileStoreBlobClient(config.blobFileStoreUploadUrl, blobFileStoreMetadata, log),
|
|
283
|
-
]);
|
|
284
|
-
|
|
285
|
-
const blobClient =
|
|
286
|
-
deps.blobClient ??
|
|
287
|
-
createBlobClient(config, {
|
|
288
|
-
logger: createLogger('node:blob-client:client'),
|
|
289
|
-
fileStoreClients,
|
|
290
|
-
fileStoreUploadClient,
|
|
291
|
-
});
|
|
265
|
+
const blobClient = await createBlobClientWithFileStores(config, createLogger('node:blob-client:client'));
|
|
292
266
|
|
|
293
267
|
// attempt snapshot sync if possible
|
|
294
268
|
await trySnapshotSync(config, log);
|
|
@@ -334,7 +308,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
334
308
|
// We should really not be modifying the config object
|
|
335
309
|
config.txPublicSetupAllowList = config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
|
|
336
310
|
|
|
337
|
-
|
|
311
|
+
// Create FullNodeCheckpointsBuilder for validator and non-validator block proposal handling
|
|
312
|
+
const validatorCheckpointsBuilder = new FullNodeCheckpointsBuilder(
|
|
338
313
|
{ ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
|
|
339
314
|
worldStateSynchronizer,
|
|
340
315
|
archiver,
|
|
@@ -346,16 +321,17 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
346
321
|
const watchers: Watcher[] = [];
|
|
347
322
|
|
|
348
323
|
// Create validator client if required
|
|
349
|
-
const validatorClient = createValidatorClient(config, {
|
|
324
|
+
const validatorClient = await createValidatorClient(config, {
|
|
325
|
+
checkpointsBuilder: validatorCheckpointsBuilder,
|
|
326
|
+
worldState: worldStateSynchronizer,
|
|
350
327
|
p2pClient,
|
|
351
328
|
telemetry,
|
|
352
329
|
dateProvider,
|
|
353
330
|
epochCache,
|
|
354
|
-
blockBuilder,
|
|
355
331
|
blockSource: archiver,
|
|
356
332
|
l1ToL2MessageSource: archiver,
|
|
357
333
|
keyStoreManager,
|
|
358
|
-
|
|
334
|
+
blobClient,
|
|
359
335
|
});
|
|
360
336
|
|
|
361
337
|
// If we have a validator client, register it as a source of offenses for the slasher,
|
|
@@ -373,7 +349,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
373
349
|
if (!validatorClient && config.alwaysReexecuteBlockProposals) {
|
|
374
350
|
log.info('Setting up block proposal reexecution for monitoring');
|
|
375
351
|
createBlockProposalHandler(config, {
|
|
376
|
-
|
|
352
|
+
checkpointsBuilder: validatorCheckpointsBuilder,
|
|
353
|
+
worldState: worldStateSynchronizer,
|
|
377
354
|
epochCache,
|
|
378
355
|
blockSource: archiver,
|
|
379
356
|
l1ToL2MessageSource: archiver,
|
|
@@ -401,7 +378,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
401
378
|
archiver,
|
|
402
379
|
epochCache,
|
|
403
380
|
p2pClient.getTxProvider(),
|
|
404
|
-
|
|
381
|
+
validatorCheckpointsBuilder,
|
|
405
382
|
config,
|
|
406
383
|
);
|
|
407
384
|
watchers.push(epochPruneWatcher);
|
|
@@ -466,6 +443,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
466
443
|
// Create and start the sequencer client
|
|
467
444
|
const checkpointsBuilder = new CheckpointsBuilder(
|
|
468
445
|
{ ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
|
|
446
|
+
worldStateSynchronizer,
|
|
469
447
|
archiver,
|
|
470
448
|
dateProvider,
|
|
471
449
|
telemetry,
|
|
@@ -594,13 +572,19 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
594
572
|
}
|
|
595
573
|
|
|
596
574
|
/**
|
|
597
|
-
* Get a block specified by its number.
|
|
598
|
-
* @param
|
|
575
|
+
* Get a block specified by its block number, block hash, or 'latest'.
|
|
576
|
+
* @param block - The block parameter (block number, block hash, or 'latest').
|
|
599
577
|
* @returns The requested block.
|
|
600
578
|
*/
|
|
601
|
-
public async getBlock(
|
|
602
|
-
|
|
603
|
-
|
|
579
|
+
public async getBlock(block: BlockParameter): Promise<L2BlockNew | undefined> {
|
|
580
|
+
if (L2BlockHash.isL2BlockHash(block)) {
|
|
581
|
+
return this.getBlockByHash(Fr.fromBuffer(block.toBuffer()));
|
|
582
|
+
}
|
|
583
|
+
const blockNumber = block === 'latest' ? await this.getBlockNumber() : (block as BlockNumber);
|
|
584
|
+
if (blockNumber === BlockNumber.ZERO) {
|
|
585
|
+
return this.buildInitialBlock();
|
|
586
|
+
}
|
|
587
|
+
return await this.blockSource.getL2BlockNew(blockNumber);
|
|
604
588
|
}
|
|
605
589
|
|
|
606
590
|
/**
|
|
@@ -608,9 +592,17 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
608
592
|
* @param blockHash - The block hash being requested.
|
|
609
593
|
* @returns The requested block.
|
|
610
594
|
*/
|
|
611
|
-
public async getBlockByHash(blockHash: Fr): Promise<
|
|
612
|
-
const
|
|
613
|
-
|
|
595
|
+
public async getBlockByHash(blockHash: Fr): Promise<L2BlockNew | undefined> {
|
|
596
|
+
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
597
|
+
if (blockHash.equals(Fr.fromBuffer(initialBlockHash.toBuffer()))) {
|
|
598
|
+
return this.buildInitialBlock();
|
|
599
|
+
}
|
|
600
|
+
return await this.blockSource.getL2BlockNewByHash(blockHash);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
private buildInitialBlock(): L2BlockNew {
|
|
604
|
+
const initialHeader = this.worldStateSynchronizer.getCommitted().getInitialHeader();
|
|
605
|
+
return L2BlockNew.empty(initialHeader);
|
|
614
606
|
}
|
|
615
607
|
|
|
616
608
|
/**
|
|
@@ -618,9 +610,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
618
610
|
* @param archive - The archive root being requested.
|
|
619
611
|
* @returns The requested block.
|
|
620
612
|
*/
|
|
621
|
-
public async getBlockByArchive(archive: Fr): Promise<
|
|
622
|
-
|
|
623
|
-
return publishedBlock?.block;
|
|
613
|
+
public async getBlockByArchive(archive: Fr): Promise<L2BlockNew | undefined> {
|
|
614
|
+
return await this.blockSource.getL2BlockNewByArchive(archive);
|
|
624
615
|
}
|
|
625
616
|
|
|
626
617
|
/**
|
|
@@ -629,20 +620,32 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
629
620
|
* @param limit - The maximum number of blocks to obtain.
|
|
630
621
|
* @returns The blocks requested.
|
|
631
622
|
*/
|
|
632
|
-
public async getBlocks(from: BlockNumber, limit: number): Promise<
|
|
633
|
-
return (await this.blockSource.
|
|
623
|
+
public async getBlocks(from: BlockNumber, limit: number): Promise<L2BlockNew[]> {
|
|
624
|
+
return (await this.blockSource.getL2BlocksNew(from, limit)) ?? [];
|
|
634
625
|
}
|
|
635
626
|
|
|
636
|
-
public async getPublishedBlocks(from: BlockNumber, limit: number): Promise<
|
|
627
|
+
public async getPublishedBlocks(from: BlockNumber, limit: number): Promise<CheckpointedL2Block[]> {
|
|
637
628
|
return (await this.blockSource.getPublishedBlocks(from, limit)) ?? [];
|
|
638
629
|
}
|
|
639
630
|
|
|
631
|
+
public async getPublishedCheckpoints(from: CheckpointNumber, limit: number): Promise<PublishedCheckpoint[]> {
|
|
632
|
+
return (await this.blockSource.getPublishedCheckpoints(from, limit)) ?? [];
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
public async getL2BlocksNew(from: BlockNumber, limit: number): Promise<L2BlockNew[]> {
|
|
636
|
+
return (await this.blockSource.getL2BlocksNew(from, limit)) ?? [];
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
public async getCheckpointedBlocks(from: BlockNumber, limit: number, proven?: boolean) {
|
|
640
|
+
return (await this.blockSource.getCheckpointedBlocks(from, limit, proven)) ?? [];
|
|
641
|
+
}
|
|
642
|
+
|
|
640
643
|
/**
|
|
641
|
-
* Method to fetch the current
|
|
642
|
-
* @returns The current
|
|
644
|
+
* Method to fetch the current min L2 fees.
|
|
645
|
+
* @returns The current min L2 fees.
|
|
643
646
|
*/
|
|
644
|
-
public async
|
|
645
|
-
return await this.globalVariableBuilder.
|
|
647
|
+
public async getCurrentMinFees(): Promise<GasFees> {
|
|
648
|
+
return await this.globalVariableBuilder.getCurrentMinFees();
|
|
646
649
|
}
|
|
647
650
|
|
|
648
651
|
public async getMaxPriorityFees(): Promise<GasFees> {
|
|
@@ -788,6 +791,14 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
788
791
|
this.log.info(`Stopped Aztec Node`);
|
|
789
792
|
}
|
|
790
793
|
|
|
794
|
+
/**
|
|
795
|
+
* Returns the blob client used by this node.
|
|
796
|
+
* @internal - Exposed for testing purposes only.
|
|
797
|
+
*/
|
|
798
|
+
public getBlobClient(): BlobClientInterface | undefined {
|
|
799
|
+
return this.blobClient;
|
|
800
|
+
}
|
|
801
|
+
|
|
791
802
|
/**
|
|
792
803
|
* Method to retrieve pending txs.
|
|
793
804
|
* @param limit - The number of items to returns
|
|
@@ -820,20 +831,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
820
831
|
return compactArray(await Promise.all(txHashes.map(txHash => this.getTxByHash(txHash))));
|
|
821
832
|
}
|
|
822
833
|
|
|
823
|
-
/**
|
|
824
|
-
* Find the indexes of the given leaves in the given tree along with a block metadata pointing to the block in which
|
|
825
|
-
* the leaves were inserted.
|
|
826
|
-
* @param blockNumber - The block number at which to get the data or 'latest' for latest data.
|
|
827
|
-
* @param treeId - The tree to search in.
|
|
828
|
-
* @param leafValues - The values to search for.
|
|
829
|
-
* @returns The indices of leaves and the block metadata of a block in which the leaves were inserted.
|
|
830
|
-
*/
|
|
831
834
|
public async findLeavesIndexes(
|
|
832
|
-
|
|
835
|
+
block: BlockParameter,
|
|
833
836
|
treeId: MerkleTreeId,
|
|
834
837
|
leafValues: Fr[],
|
|
835
838
|
): Promise<(DataInBlock<bigint> | undefined)[]> {
|
|
836
|
-
const committedDb = await this.#getWorldState(
|
|
839
|
+
const committedDb = await this.#getWorldState(block);
|
|
837
840
|
const maybeIndices = await committedDb.findLeafIndices(
|
|
838
841
|
treeId,
|
|
839
842
|
leafValues.map(x => x.toBuffer()),
|
|
@@ -891,39 +894,27 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
891
894
|
});
|
|
892
895
|
}
|
|
893
896
|
|
|
894
|
-
/**
|
|
895
|
-
* Returns a sibling path for the given index in the nullifier tree.
|
|
896
|
-
* @param blockNumber - The block number at which to get the data.
|
|
897
|
-
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
898
|
-
* @returns The sibling path for the leaf index.
|
|
899
|
-
*/
|
|
900
897
|
public async getNullifierSiblingPath(
|
|
901
|
-
|
|
898
|
+
block: BlockParameter,
|
|
902
899
|
leafIndex: bigint,
|
|
903
900
|
): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>> {
|
|
904
|
-
const committedDb = await this.#getWorldState(
|
|
901
|
+
const committedDb = await this.#getWorldState(block);
|
|
905
902
|
return committedDb.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, leafIndex);
|
|
906
903
|
}
|
|
907
904
|
|
|
908
|
-
/**
|
|
909
|
-
* Returns a sibling path for the given index in the data tree.
|
|
910
|
-
* @param blockNumber - The block number at which to get the data.
|
|
911
|
-
* @param leafIndex - The index of the leaf for which the sibling path is required.
|
|
912
|
-
* @returns The sibling path for the leaf index.
|
|
913
|
-
*/
|
|
914
905
|
public async getNoteHashSiblingPath(
|
|
915
|
-
|
|
906
|
+
block: BlockParameter,
|
|
916
907
|
leafIndex: bigint,
|
|
917
908
|
): Promise<SiblingPath<typeof NOTE_HASH_TREE_HEIGHT>> {
|
|
918
|
-
const committedDb = await this.#getWorldState(
|
|
909
|
+
const committedDb = await this.#getWorldState(block);
|
|
919
910
|
return committedDb.getSiblingPath(MerkleTreeId.NOTE_HASH_TREE, leafIndex);
|
|
920
911
|
}
|
|
921
912
|
|
|
922
913
|
public async getArchiveMembershipWitness(
|
|
923
|
-
|
|
914
|
+
block: BlockParameter,
|
|
924
915
|
archive: Fr,
|
|
925
916
|
): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
|
|
926
|
-
const committedDb = await this.#getWorldState(
|
|
917
|
+
const committedDb = await this.#getWorldState(block);
|
|
927
918
|
const [pathAndIndex] = await committedDb.findSiblingPaths<MerkleTreeId.ARCHIVE>(MerkleTreeId.ARCHIVE, [archive]);
|
|
928
919
|
return pathAndIndex === undefined
|
|
929
920
|
? undefined
|
|
@@ -931,10 +922,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
931
922
|
}
|
|
932
923
|
|
|
933
924
|
public async getNoteHashMembershipWitness(
|
|
934
|
-
|
|
925
|
+
block: BlockParameter,
|
|
935
926
|
noteHash: Fr,
|
|
936
927
|
): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
|
|
937
|
-
const committedDb = await this.#getWorldState(
|
|
928
|
+
const committedDb = await this.#getWorldState(block);
|
|
938
929
|
const [pathAndIndex] = await committedDb.findSiblingPaths<MerkleTreeId.NOTE_HASH_TREE>(
|
|
939
930
|
MerkleTreeId.NOTE_HASH_TREE,
|
|
940
931
|
[noteHash],
|
|
@@ -944,17 +935,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
944
935
|
: MembershipWitness.fromSiblingPath(pathAndIndex.index, pathAndIndex.path);
|
|
945
936
|
}
|
|
946
937
|
|
|
947
|
-
/**
|
|
948
|
-
* Returns the index and a sibling path for a leaf in the committed l1 to l2 data tree.
|
|
949
|
-
* @param blockNumber - The block number at which to get the data.
|
|
950
|
-
* @param l1ToL2Message - The l1ToL2Message to get the index / sibling path for.
|
|
951
|
-
* @returns A tuple of the index and the sibling path of the L1ToL2Message (undefined if not found).
|
|
952
|
-
*/
|
|
953
938
|
public async getL1ToL2MessageMembershipWitness(
|
|
954
|
-
|
|
939
|
+
block: BlockParameter,
|
|
955
940
|
l1ToL2Message: Fr,
|
|
956
941
|
): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>] | undefined> {
|
|
957
|
-
const db = await this.#getWorldState(
|
|
942
|
+
const db = await this.#getWorldState(block);
|
|
958
943
|
const [witness] = await db.findSiblingPaths(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, [l1ToL2Message]);
|
|
959
944
|
if (!witness) {
|
|
960
945
|
return undefined;
|
|
@@ -982,56 +967,51 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
982
967
|
}
|
|
983
968
|
|
|
984
969
|
/**
|
|
985
|
-
* Returns all the L2 to L1 messages in
|
|
986
|
-
* @param
|
|
987
|
-
* @returns The L2 to L1 messages (
|
|
970
|
+
* Returns all the L2 to L1 messages in an epoch.
|
|
971
|
+
* @param epoch - The epoch at which to get the data.
|
|
972
|
+
* @returns The L2 to L1 messages (empty array if the epoch is not found).
|
|
988
973
|
*/
|
|
989
|
-
public async getL2ToL1Messages(
|
|
990
|
-
|
|
991
|
-
|
|
974
|
+
public async getL2ToL1Messages(epoch: EpochNumber): Promise<Fr[][][][]> {
|
|
975
|
+
// Assumes `getBlocksForEpoch` returns blocks in ascending order of block number.
|
|
976
|
+
const blocks = await this.blockSource.getBlocksForEpoch(epoch);
|
|
977
|
+
const blocksInCheckpoints: L2BlockNew[][] = [];
|
|
978
|
+
let previousSlotNumber = SlotNumber.ZERO;
|
|
979
|
+
let checkpointIndex = -1;
|
|
980
|
+
for (const block of blocks) {
|
|
981
|
+
const slotNumber = block.header.globalVariables.slotNumber;
|
|
982
|
+
if (slotNumber !== previousSlotNumber) {
|
|
983
|
+
checkpointIndex++;
|
|
984
|
+
blocksInCheckpoints.push([]);
|
|
985
|
+
previousSlotNumber = slotNumber;
|
|
986
|
+
}
|
|
987
|
+
blocksInCheckpoints[checkpointIndex].push(block);
|
|
988
|
+
}
|
|
989
|
+
return blocksInCheckpoints.map(blocks =>
|
|
990
|
+
blocks.map(block => block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs)),
|
|
992
991
|
);
|
|
993
|
-
return block?.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs);
|
|
994
992
|
}
|
|
995
993
|
|
|
996
|
-
/**
|
|
997
|
-
* Returns a sibling path for a leaf in the committed blocks tree.
|
|
998
|
-
* @param blockNumber - The block number at which to get the data.
|
|
999
|
-
* @param leafIndex - Index of the leaf in the tree.
|
|
1000
|
-
* @returns The sibling path.
|
|
1001
|
-
*/
|
|
1002
994
|
public async getArchiveSiblingPath(
|
|
1003
|
-
|
|
995
|
+
block: BlockParameter,
|
|
1004
996
|
leafIndex: bigint,
|
|
1005
997
|
): Promise<SiblingPath<typeof ARCHIVE_HEIGHT>> {
|
|
1006
|
-
const committedDb = await this.#getWorldState(
|
|
998
|
+
const committedDb = await this.#getWorldState(block);
|
|
1007
999
|
return committedDb.getSiblingPath(MerkleTreeId.ARCHIVE, leafIndex);
|
|
1008
1000
|
}
|
|
1009
1001
|
|
|
1010
|
-
/**
|
|
1011
|
-
* Returns a sibling path for a leaf in the committed public data tree.
|
|
1012
|
-
* @param blockNumber - The block number at which to get the data.
|
|
1013
|
-
* @param leafIndex - Index of the leaf in the tree.
|
|
1014
|
-
* @returns The sibling path.
|
|
1015
|
-
*/
|
|
1016
1002
|
public async getPublicDataSiblingPath(
|
|
1017
|
-
|
|
1003
|
+
block: BlockParameter,
|
|
1018
1004
|
leafIndex: bigint,
|
|
1019
1005
|
): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>> {
|
|
1020
|
-
const committedDb = await this.#getWorldState(
|
|
1006
|
+
const committedDb = await this.#getWorldState(block);
|
|
1021
1007
|
return committedDb.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex);
|
|
1022
1008
|
}
|
|
1023
1009
|
|
|
1024
|
-
/**
|
|
1025
|
-
* Returns a nullifier membership witness for a given nullifier at a given block.
|
|
1026
|
-
* @param blockNumber - The block number at which to get the index.
|
|
1027
|
-
* @param nullifier - Nullifier we try to find witness for.
|
|
1028
|
-
* @returns The nullifier membership witness (if found).
|
|
1029
|
-
*/
|
|
1030
1010
|
public async getNullifierMembershipWitness(
|
|
1031
|
-
|
|
1011
|
+
block: BlockParameter,
|
|
1032
1012
|
nullifier: Fr,
|
|
1033
1013
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
1034
|
-
const db = await this.#getWorldState(
|
|
1014
|
+
const db = await this.#getWorldState(block);
|
|
1035
1015
|
const [witness] = await db.findSiblingPaths(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
1036
1016
|
if (!witness) {
|
|
1037
1017
|
return undefined;
|
|
@@ -1048,7 +1028,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1048
1028
|
|
|
1049
1029
|
/**
|
|
1050
1030
|
* Returns a low nullifier membership witness for a given nullifier at a given block.
|
|
1051
|
-
* @param
|
|
1031
|
+
* @param block - The block parameter (block number, block hash, or 'latest') at which to get the data.
|
|
1052
1032
|
* @param nullifier - Nullifier we try to find the low nullifier witness for.
|
|
1053
1033
|
* @returns The low nullifier membership witness (if found).
|
|
1054
1034
|
* @remarks Low nullifier witness can be used to perform a nullifier non-inclusion proof by leveraging the "linked
|
|
@@ -1061,10 +1041,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1061
1041
|
* TODO: This is a confusing behavior and we should eventually address that.
|
|
1062
1042
|
*/
|
|
1063
1043
|
public async getLowNullifierMembershipWitness(
|
|
1064
|
-
|
|
1044
|
+
block: BlockParameter,
|
|
1065
1045
|
nullifier: Fr,
|
|
1066
1046
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
1067
|
-
const committedDb = await this.#getWorldState(
|
|
1047
|
+
const committedDb = await this.#getWorldState(block);
|
|
1068
1048
|
const findResult = await committedDb.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
1069
1049
|
if (!findResult) {
|
|
1070
1050
|
return undefined;
|
|
@@ -1079,8 +1059,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1079
1059
|
return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath);
|
|
1080
1060
|
}
|
|
1081
1061
|
|
|
1082
|
-
async getPublicDataWitness(
|
|
1083
|
-
const committedDb = await this.#getWorldState(
|
|
1062
|
+
async getPublicDataWitness(block: BlockParameter, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
1063
|
+
const committedDb = await this.#getWorldState(block);
|
|
1084
1064
|
const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
1085
1065
|
if (!lowLeafResult) {
|
|
1086
1066
|
return undefined;
|
|
@@ -1094,19 +1074,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1094
1074
|
}
|
|
1095
1075
|
}
|
|
1096
1076
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
*
|
|
1100
|
-
* @remarks The storage slot here refers to the slot as it is defined in Noir not the index in the merkle tree.
|
|
1101
|
-
* Aztec's version of `eth_getStorageAt`.
|
|
1102
|
-
*
|
|
1103
|
-
* @param contract - Address of the contract to query.
|
|
1104
|
-
* @param slot - Slot to query.
|
|
1105
|
-
* @param blockNumber - The block number at which to get the data or 'latest'.
|
|
1106
|
-
* @returns Storage value at the given contract slot.
|
|
1107
|
-
*/
|
|
1108
|
-
public async getPublicStorageAt(blockNumber: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr> {
|
|
1109
|
-
const committedDb = await this.#getWorldState(blockNumber);
|
|
1077
|
+
public async getPublicStorageAt(block: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr> {
|
|
1078
|
+
const committedDb = await this.#getWorldState(block);
|
|
1110
1079
|
const leafSlot = await computePublicDataTreeLeafSlot(contract, slot);
|
|
1111
1080
|
|
|
1112
1081
|
const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
@@ -1120,24 +1089,23 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1120
1089
|
return preimage.leaf.value;
|
|
1121
1090
|
}
|
|
1122
1091
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
return await this.blockSource.getBlockHeaderByHash(blockHash);
|
|
1092
|
+
public async getBlockHeader(block: BlockParameter = 'latest'): Promise<BlockHeader | undefined> {
|
|
1093
|
+
if (L2BlockHash.isL2BlockHash(block)) {
|
|
1094
|
+
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
1095
|
+
if (block.equals(initialBlockHash)) {
|
|
1096
|
+
// Block source doesn't handle initial header so we need to handle the case separately.
|
|
1097
|
+
return this.worldStateSynchronizer.getCommitted().getInitialHeader();
|
|
1098
|
+
}
|
|
1099
|
+
const blockHashFr = Fr.fromBuffer(block.toBuffer());
|
|
1100
|
+
return this.blockSource.getBlockHeaderByHash(blockHashFr);
|
|
1101
|
+
} else {
|
|
1102
|
+
// Block source doesn't handle initial header so we need to handle the case separately.
|
|
1103
|
+
const blockNumber = block === 'latest' ? await this.getBlockNumber() : (block as BlockNumber);
|
|
1104
|
+
if (blockNumber === BlockNumber.ZERO) {
|
|
1105
|
+
return this.worldStateSynchronizer.getCommitted().getInitialHeader();
|
|
1106
|
+
}
|
|
1107
|
+
return this.blockSource.getBlockHeader(block);
|
|
1108
|
+
}
|
|
1141
1109
|
}
|
|
1142
1110
|
|
|
1143
1111
|
/**
|
|
@@ -1246,7 +1214,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1246
1214
|
l1ChainId: this.l1ChainId,
|
|
1247
1215
|
rollupVersion: this.version,
|
|
1248
1216
|
setupAllowList: this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions()),
|
|
1249
|
-
gasFees: await this.
|
|
1217
|
+
gasFees: await this.getCurrentMinFees(),
|
|
1250
1218
|
skipFeeEnforcement,
|
|
1251
1219
|
txsPermitted: !this.config.disableTransactions,
|
|
1252
1220
|
});
|
|
@@ -1318,7 +1286,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1318
1286
|
}
|
|
1319
1287
|
|
|
1320
1288
|
// And it has an L2 block hash
|
|
1321
|
-
const l2BlockHash = await archiver.getL2Tips().then(tips => tips.
|
|
1289
|
+
const l2BlockHash = await archiver.getL2Tips().then(tips => tips.proposed.hash);
|
|
1322
1290
|
if (!l2BlockHash) {
|
|
1323
1291
|
this.metrics.recordSnapshotError();
|
|
1324
1292
|
throw new Error(`Archiver has no latest L2 block hash downloaded. Cannot start snapshot.`);
|
|
@@ -1352,7 +1320,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1352
1320
|
throw new Error('Archiver implementation does not support rollbacks.');
|
|
1353
1321
|
}
|
|
1354
1322
|
|
|
1355
|
-
const finalizedBlock = await archiver.getL2Tips().then(tips => tips.finalized.number);
|
|
1323
|
+
const finalizedBlock = await archiver.getL2Tips().then(tips => tips.finalized.block.number);
|
|
1356
1324
|
if (targetBlock < finalizedBlock) {
|
|
1357
1325
|
if (force) {
|
|
1358
1326
|
this.log.warn(`Clearing world state database to allow rolling back behind finalized block ${finalizedBlock}`);
|
|
@@ -1413,16 +1381,23 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1413
1381
|
}
|
|
1414
1382
|
}
|
|
1415
1383
|
|
|
1384
|
+
#getInitialHeaderHash(): Promise<L2BlockHash> {
|
|
1385
|
+
if (!this.initialHeaderHashPromise) {
|
|
1386
|
+
this.initialHeaderHashPromise = this.worldStateSynchronizer
|
|
1387
|
+
.getCommitted()
|
|
1388
|
+
.getInitialHeader()
|
|
1389
|
+
.hash()
|
|
1390
|
+
.then(hash => L2BlockHash.fromField(hash));
|
|
1391
|
+
}
|
|
1392
|
+
return this.initialHeaderHashPromise;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1416
1395
|
/**
|
|
1417
1396
|
* Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
|
|
1418
|
-
* @param
|
|
1397
|
+
* @param block - The block parameter (block number, block hash, or 'latest') at which to get the data.
|
|
1419
1398
|
* @returns An instance of a committed MerkleTreeOperations
|
|
1420
1399
|
*/
|
|
1421
|
-
async #getWorldState(
|
|
1422
|
-
if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM - 1) {
|
|
1423
|
-
throw new Error('Invalid block number to get world state for: ' + blockNumber);
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1400
|
+
async #getWorldState(block: BlockParameter) {
|
|
1426
1401
|
let blockSyncedTo: BlockNumber = BlockNumber.ZERO;
|
|
1427
1402
|
try {
|
|
1428
1403
|
// Attempt to sync the world state if necessary
|
|
@@ -1431,15 +1406,40 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
|
|
|
1431
1406
|
this.log.error(`Error getting world state: ${err}`);
|
|
1432
1407
|
}
|
|
1433
1408
|
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
this.log.debug(`Using committed db for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
1409
|
+
if (block === 'latest') {
|
|
1410
|
+
this.log.debug(`Using committed db for block 'latest', world state synced upto ${blockSyncedTo}`);
|
|
1437
1411
|
return this.worldStateSynchronizer.getCommitted();
|
|
1438
|
-
}
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
if (L2BlockHash.isL2BlockHash(block)) {
|
|
1415
|
+
const initialBlockHash = await this.#getInitialHeaderHash();
|
|
1416
|
+
if (block.equals(initialBlockHash)) {
|
|
1417
|
+
// Block source doesn't handle initial header so we need to handle the case separately.
|
|
1418
|
+
return this.worldStateSynchronizer.getSnapshot(BlockNumber.ZERO);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
const blockHashFr = Fr.fromBuffer(block.toBuffer());
|
|
1422
|
+
const header = await this.blockSource.getBlockHeaderByHash(blockHashFr);
|
|
1423
|
+
if (!header) {
|
|
1424
|
+
throw new Error(
|
|
1425
|
+
`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.`,
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
const blockNumber = header.getBlockNumber();
|
|
1439
1429
|
this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
1440
|
-
return this.worldStateSynchronizer.getSnapshot(blockNumber
|
|
1441
|
-
}
|
|
1442
|
-
|
|
1430
|
+
return this.worldStateSynchronizer.getSnapshot(blockNumber);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
// Block number provided
|
|
1434
|
+
{
|
|
1435
|
+
const blockNumber = block as BlockNumber;
|
|
1436
|
+
|
|
1437
|
+
if (blockNumber > blockSyncedTo) {
|
|
1438
|
+
throw new Error(`Queried block ${block} not yet synced by the node (node is synced upto ${blockSyncedTo}).`);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
|
|
1442
|
+
return this.worldStateSynchronizer.getSnapshot(blockNumber);
|
|
1443
1443
|
}
|
|
1444
1444
|
}
|
|
1445
1445
|
|