@aztec/archiver 3.0.3 → 4.0.0-devnet.1-patch.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -22
- package/dest/archiver.d.ts +136 -0
- package/dest/archiver.d.ts.map +1 -0
- package/dest/archiver.js +781 -0
- package/dest/{archiver/config.d.ts → config.d.ts} +11 -3
- package/dest/config.d.ts.map +1 -0
- package/dest/{archiver/config.js → config.js} +13 -4
- package/dest/errors.d.ts +41 -0
- package/dest/errors.d.ts.map +1 -0
- package/dest/errors.js +62 -0
- package/dest/factory.d.ts +9 -7
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +91 -11
- package/dest/index.d.ts +10 -4
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +8 -3
- package/dest/interfaces.d.ts +9 -0
- package/dest/interfaces.d.ts.map +1 -0
- package/dest/interfaces.js +3 -0
- package/dest/{archiver/l1 → l1}/bin/retrieve-calldata.d.ts +1 -1
- package/dest/l1/bin/retrieve-calldata.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/bin/retrieve-calldata.js +21 -20
- package/dest/{archiver/l1 → l1}/calldata_retriever.d.ts +18 -4
- package/dest/l1/calldata_retriever.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/calldata_retriever.js +75 -7
- package/dest/l1/data_retrieval.d.ts +88 -0
- package/dest/l1/data_retrieval.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/data_retrieval.js +61 -67
- package/dest/{archiver/l1 → l1}/debug_tx.d.ts +1 -1
- package/dest/l1/debug_tx.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/spire_proposer.d.ts +1 -1
- package/dest/l1/spire_proposer.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/trace_tx.d.ts +1 -1
- package/dest/l1/trace_tx.d.ts.map +1 -0
- package/dest/l1/types.d.ts +12 -0
- package/dest/l1/types.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/validate_trace.d.ts +6 -3
- package/dest/l1/validate_trace.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/validate_trace.js +14 -10
- package/dest/modules/data_source_base.d.ts +84 -0
- package/dest/modules/data_source_base.d.ts.map +1 -0
- package/dest/modules/data_source_base.js +260 -0
- package/dest/modules/data_store_updater.d.ts +73 -0
- package/dest/modules/data_store_updater.d.ts.map +1 -0
- package/dest/modules/data_store_updater.js +302 -0
- package/dest/modules/instrumentation.d.ts +37 -0
- package/dest/modules/instrumentation.d.ts.map +1 -0
- package/dest/{archiver → modules}/instrumentation.js +24 -65
- package/dest/modules/l1_synchronizer.d.ts +75 -0
- package/dest/modules/l1_synchronizer.d.ts.map +1 -0
- package/dest/modules/l1_synchronizer.js +1112 -0
- package/dest/modules/validation.d.ts +17 -0
- package/dest/modules/validation.d.ts.map +1 -0
- package/dest/{archiver → modules}/validation.js +7 -1
- package/dest/store/block_store.d.ts +192 -0
- package/dest/store/block_store.d.ts.map +1 -0
- package/dest/store/block_store.js +721 -0
- package/dest/store/contract_class_store.d.ts +18 -0
- package/dest/store/contract_class_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/contract_class_store.js +12 -8
- package/dest/store/contract_instance_store.d.ts +24 -0
- package/dest/store/contract_instance_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/contract_instance_store.js +1 -1
- package/dest/store/kv_archiver_store.d.ts +340 -0
- package/dest/store/kv_archiver_store.d.ts.map +1 -0
- package/dest/store/kv_archiver_store.js +446 -0
- package/dest/store/log_store.d.ts +54 -0
- package/dest/store/log_store.d.ts.map +1 -0
- package/dest/store/log_store.js +456 -0
- package/dest/{archiver/kv_archiver_store → store}/message_store.d.ts +1 -1
- package/dest/store/message_store.d.ts.map +1 -0
- package/dest/{archiver/structs → structs}/data_retrieval.d.ts +1 -1
- package/dest/structs/data_retrieval.d.ts.map +1 -0
- package/dest/structs/inbox_message.d.ts +15 -0
- package/dest/structs/inbox_message.d.ts.map +1 -0
- package/dest/structs/published.d.ts +2 -0
- package/dest/structs/published.d.ts.map +1 -0
- package/dest/test/fake_l1_state.d.ts +190 -0
- package/dest/test/fake_l1_state.d.ts.map +1 -0
- package/dest/test/fake_l1_state.js +383 -0
- package/dest/test/index.d.ts +2 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +4 -1
- package/dest/test/mock_archiver.d.ts +2 -2
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +1 -2
- package/dest/test/mock_l1_to_l2_message_source.d.ts +2 -2
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +12 -3
- package/dest/test/mock_l2_block_source.d.ts +29 -15
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +173 -66
- package/dest/test/mock_structs.d.ts +78 -3
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +140 -7
- package/dest/test/noop_l1_archiver.d.ts +23 -0
- package/dest/test/noop_l1_archiver.d.ts.map +1 -0
- package/dest/test/noop_l1_archiver.js +68 -0
- package/package.json +16 -17
- package/src/archiver.ts +543 -0
- package/src/{archiver/config.ts → config.ts} +20 -5
- package/src/errors.ts +102 -0
- package/src/factory.ts +133 -11
- package/src/index.ts +10 -3
- package/src/interfaces.ts +9 -0
- package/src/{archiver/l1 → l1}/bin/retrieve-calldata.ts +18 -19
- package/src/{archiver/l1 → l1}/calldata_retriever.ts +119 -9
- package/src/{archiver/l1 → l1}/data_retrieval.ts +91 -87
- package/src/{archiver/l1 → l1}/validate_trace.ts +25 -7
- package/src/modules/data_source_base.ts +367 -0
- package/src/modules/data_store_updater.ts +423 -0
- package/src/{archiver → modules}/instrumentation.ts +24 -68
- package/src/modules/l1_synchronizer.ts +930 -0
- package/src/{archiver → modules}/validation.ts +11 -6
- package/src/store/block_store.ts +966 -0
- package/src/{archiver/kv_archiver_store → store}/contract_class_store.ts +12 -8
- package/src/{archiver/kv_archiver_store → store}/contract_instance_store.ts +1 -1
- package/src/store/kv_archiver_store.ts +639 -0
- package/src/store/log_store.ts +637 -0
- package/src/{archiver/structs → structs}/published.ts +0 -1
- package/src/test/fake_l1_state.ts +599 -0
- package/src/test/index.ts +4 -0
- package/src/test/mock_archiver.ts +2 -2
- package/src/test/mock_l1_to_l2_message_source.ts +10 -4
- package/src/test/mock_l2_block_source.ts +189 -79
- package/src/test/mock_structs.ts +269 -8
- package/src/test/noop_l1_archiver.ts +109 -0
- package/dest/archiver/archiver.d.ts +0 -284
- package/dest/archiver/archiver.d.ts.map +0 -1
- package/dest/archiver/archiver.js +0 -1454
- package/dest/archiver/archiver_store.d.ts +0 -249
- package/dest/archiver/archiver_store.d.ts.map +0 -1
- package/dest/archiver/archiver_store.js +0 -4
- package/dest/archiver/archiver_store_test_suite.d.ts +0 -8
- package/dest/archiver/archiver_store_test_suite.d.ts.map +0 -1
- package/dest/archiver/archiver_store_test_suite.js +0 -1273
- package/dest/archiver/config.d.ts.map +0 -1
- package/dest/archiver/errors.d.ts +0 -12
- package/dest/archiver/errors.d.ts.map +0 -1
- package/dest/archiver/errors.js +0 -17
- package/dest/archiver/index.d.ts +0 -7
- package/dest/archiver/index.d.ts.map +0 -1
- package/dest/archiver/index.js +0 -4
- package/dest/archiver/instrumentation.d.ts +0 -37
- package/dest/archiver/instrumentation.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/block_store.d.ts +0 -125
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/block_store.js +0 -371
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +0 -18
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +0 -24
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +0 -162
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +0 -288
- package/dest/archiver/kv_archiver_store/log_store.d.ts +0 -42
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/log_store.js +0 -314
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +0 -1
- package/dest/archiver/l1/bin/retrieve-calldata.d.ts.map +0 -1
- package/dest/archiver/l1/calldata_retriever.d.ts.map +0 -1
- package/dest/archiver/l1/data_retrieval.d.ts +0 -87
- package/dest/archiver/l1/data_retrieval.d.ts.map +0 -1
- package/dest/archiver/l1/debug_tx.d.ts.map +0 -1
- package/dest/archiver/l1/spire_proposer.d.ts.map +0 -1
- package/dest/archiver/l1/trace_tx.d.ts.map +0 -1
- package/dest/archiver/l1/types.d.ts +0 -12
- package/dest/archiver/l1/types.d.ts.map +0 -1
- package/dest/archiver/l1/validate_trace.d.ts.map +0 -1
- package/dest/archiver/structs/data_retrieval.d.ts.map +0 -1
- package/dest/archiver/structs/inbox_message.d.ts +0 -15
- package/dest/archiver/structs/inbox_message.d.ts.map +0 -1
- package/dest/archiver/structs/published.d.ts +0 -3
- package/dest/archiver/structs/published.d.ts.map +0 -1
- package/dest/archiver/validation.d.ts +0 -17
- package/dest/archiver/validation.d.ts.map +0 -1
- package/dest/rpc/index.d.ts +0 -9
- package/dest/rpc/index.d.ts.map +0 -1
- package/dest/rpc/index.js +0 -15
- package/src/archiver/archiver.ts +0 -1906
- package/src/archiver/archiver_store.ts +0 -302
- package/src/archiver/archiver_store_test_suite.ts +0 -1286
- package/src/archiver/errors.ts +0 -26
- package/src/archiver/index.ts +0 -6
- package/src/archiver/kv_archiver_store/block_store.ts +0 -482
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +0 -413
- package/src/archiver/kv_archiver_store/log_store.ts +0 -380
- package/src/rpc/index.ts +0 -16
- /package/dest/{archiver/l1 → l1}/debug_tx.js +0 -0
- /package/dest/{archiver/l1 → l1}/spire_proposer.js +0 -0
- /package/dest/{archiver/l1 → l1}/trace_tx.js +0 -0
- /package/dest/{archiver/l1 → l1}/types.js +0 -0
- /package/dest/{archiver/kv_archiver_store → store}/message_store.js +0 -0
- /package/dest/{archiver/structs → structs}/data_retrieval.js +0 -0
- /package/dest/{archiver/structs → structs}/inbox_message.js +0 -0
- /package/dest/{archiver/structs → structs}/published.js +0 -0
- /package/src/{archiver/l1 → l1}/README.md +0 -0
- /package/src/{archiver/l1 → l1}/debug_tx.ts +0 -0
- /package/src/{archiver/l1 → l1}/spire_proposer.ts +0 -0
- /package/src/{archiver/l1 → l1}/trace_tx.ts +0 -0
- /package/src/{archiver/l1 → l1}/types.ts +0 -0
- /package/src/{archiver/kv_archiver_store → store}/message_store.ts +0 -0
- /package/src/{archiver/structs → structs}/data_retrieval.ts +0 -0
- /package/src/{archiver/structs → structs}/inbox_message.ts +0 -0
package/src/factory.ts
CHANGED
|
@@ -1,36 +1,51 @@
|
|
|
1
|
+
import { EpochCache } from '@aztec/epoch-cache';
|
|
2
|
+
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
3
|
+
import { InboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
4
|
+
import type { ViemPublicDebugClient } from '@aztec/ethereum/types';
|
|
1
5
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
-
import {
|
|
6
|
+
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
7
|
+
import { merge } from '@aztec/foundation/collection';
|
|
8
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
9
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
3
10
|
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
4
11
|
import { createStore } from '@aztec/kv-store/lmdb-v2';
|
|
5
12
|
import { protocolContractNames } from '@aztec/protocol-contracts';
|
|
6
13
|
import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
|
|
7
14
|
import { FunctionType, decodeFunctionSignature } from '@aztec/stdlib/abi';
|
|
15
|
+
import type { ArchiverEmitter } from '@aztec/stdlib/block';
|
|
8
16
|
import { type ContractClassPublic, computePublicBytecodeCommitment } from '@aztec/stdlib/contract';
|
|
17
|
+
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
18
|
+
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
9
19
|
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
|
|
20
|
+
import { EventEmitter } from 'events';
|
|
21
|
+
import { createPublicClient, fallback, http } from 'viem';
|
|
22
|
+
|
|
23
|
+
import { Archiver, type ArchiverDeps } from './archiver.js';
|
|
24
|
+
import { type ArchiverConfig, mapArchiverConfig } from './config.js';
|
|
25
|
+
import { ArchiverInstrumentation } from './modules/instrumentation.js';
|
|
26
|
+
import { ArchiverL1Synchronizer } from './modules/l1_synchronizer.js';
|
|
27
|
+
import { ARCHIVER_DB_VERSION, KVArchiverDataStore } from './store/kv_archiver_store.js';
|
|
13
28
|
|
|
14
29
|
export const ARCHIVER_STORE_NAME = 'archiver';
|
|
15
30
|
|
|
16
31
|
/** Creates an archiver store. */
|
|
17
32
|
export async function createArchiverStore(
|
|
18
33
|
userConfig: Pick<ArchiverConfig, 'archiverStoreMapSizeKb' | 'maxLogs'> & DataStoreConfig,
|
|
34
|
+
l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
19
35
|
) {
|
|
20
36
|
const config = {
|
|
21
37
|
...userConfig,
|
|
22
38
|
dataStoreMapSizeKb: userConfig.archiverStoreMapSizeKb ?? userConfig.dataStoreMapSizeKb,
|
|
23
39
|
};
|
|
24
|
-
const store = await createStore(ARCHIVER_STORE_NAME, ARCHIVER_DB_VERSION, config
|
|
25
|
-
return new KVArchiverDataStore(store, config.maxLogs);
|
|
40
|
+
const store = await createStore(ARCHIVER_STORE_NAME, ARCHIVER_DB_VERSION, config);
|
|
41
|
+
return new KVArchiverDataStore(store, config.maxLogs, l1Constants);
|
|
26
42
|
}
|
|
27
43
|
|
|
28
44
|
/**
|
|
29
45
|
* Creates a local archiver.
|
|
30
46
|
* @param config - The archiver configuration.
|
|
31
|
-
* @param
|
|
47
|
+
* @param deps - The archiver dependencies (blobClient, epochCache, dateProvider, telemetry).
|
|
32
48
|
* @param opts - The options.
|
|
33
|
-
* @param telemetry - The telemetry client.
|
|
34
49
|
* @returns The local archiver.
|
|
35
50
|
*/
|
|
36
51
|
export async function createArchiver(
|
|
@@ -38,12 +53,119 @@ export async function createArchiver(
|
|
|
38
53
|
deps: ArchiverDeps,
|
|
39
54
|
opts: { blockUntilSync: boolean } = { blockUntilSync: true },
|
|
40
55
|
): Promise<Archiver> {
|
|
41
|
-
const archiverStore = await createArchiverStore(config);
|
|
56
|
+
const archiverStore = await createArchiverStore(config, { epochDuration: config.aztecEpochDuration });
|
|
42
57
|
await registerProtocolContracts(archiverStore);
|
|
43
|
-
|
|
58
|
+
|
|
59
|
+
// Create Ethereum clients
|
|
60
|
+
const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
|
|
61
|
+
const publicClient = createPublicClient({
|
|
62
|
+
chain: chain.chainInfo,
|
|
63
|
+
transport: fallback(config.l1RpcUrls.map(url => http(url, { batch: false }))),
|
|
64
|
+
pollingInterval: config.viemPollingIntervalMS,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Create debug client using debug RPC URLs if available, otherwise fall back to regular RPC URLs
|
|
68
|
+
const debugRpcUrls = config.l1DebugRpcUrls.length > 0 ? config.l1DebugRpcUrls : config.l1RpcUrls;
|
|
69
|
+
const debugClient = createPublicClient({
|
|
70
|
+
chain: chain.chainInfo,
|
|
71
|
+
transport: fallback(debugRpcUrls.map(url => http(url, { batch: false }))),
|
|
72
|
+
pollingInterval: config.viemPollingIntervalMS,
|
|
73
|
+
}) as ViemPublicDebugClient;
|
|
74
|
+
|
|
75
|
+
// Create L1 contract instances
|
|
76
|
+
const rollup = new RollupContract(publicClient, config.l1Contracts.rollupAddress);
|
|
77
|
+
const inbox = new InboxContract(publicClient, config.l1Contracts.inboxAddress);
|
|
78
|
+
|
|
79
|
+
// Fetch L1 constants from rollup contract
|
|
80
|
+
const [
|
|
81
|
+
l1StartBlock,
|
|
82
|
+
l1GenesisTime,
|
|
83
|
+
proofSubmissionEpochs,
|
|
84
|
+
genesisArchiveRoot,
|
|
85
|
+
slashingProposerAddress,
|
|
86
|
+
targetCommitteeSize,
|
|
87
|
+
] = await Promise.all([
|
|
88
|
+
rollup.getL1StartBlock(),
|
|
89
|
+
rollup.getL1GenesisTime(),
|
|
90
|
+
rollup.getProofSubmissionEpochs(),
|
|
91
|
+
rollup.getGenesisArchiveTreeRoot(),
|
|
92
|
+
rollup.getSlashingProposerAddress(),
|
|
93
|
+
rollup.getTargetCommitteeSize(),
|
|
94
|
+
] as const);
|
|
95
|
+
|
|
96
|
+
const l1StartBlockHash = await publicClient
|
|
97
|
+
.getBlock({ blockNumber: l1StartBlock, includeTransactions: false })
|
|
98
|
+
.then(block => Buffer32.fromString(block.hash));
|
|
99
|
+
|
|
100
|
+
const { aztecEpochDuration: epochDuration, aztecSlotDuration: slotDuration, ethereumSlotDuration } = config;
|
|
101
|
+
|
|
102
|
+
const l1Constants = {
|
|
103
|
+
l1StartBlockHash,
|
|
104
|
+
l1StartBlock,
|
|
105
|
+
l1GenesisTime,
|
|
106
|
+
epochDuration,
|
|
107
|
+
slotDuration,
|
|
108
|
+
ethereumSlotDuration,
|
|
109
|
+
proofSubmissionEpochs: Number(proofSubmissionEpochs),
|
|
110
|
+
targetCommitteeSize,
|
|
111
|
+
genesisArchiveRoot: Fr.fromString(genesisArchiveRoot.toString()),
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const archiverConfig = merge(
|
|
115
|
+
{
|
|
116
|
+
pollingIntervalMs: 10_000,
|
|
117
|
+
batchSize: 100,
|
|
118
|
+
maxAllowedEthClientDriftSeconds: 300,
|
|
119
|
+
ethereumAllowNoDebugHosts: false,
|
|
120
|
+
},
|
|
121
|
+
mapArchiverConfig(config),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const epochCache = deps.epochCache ?? (await EpochCache.create(config.l1Contracts.rollupAddress, config, deps));
|
|
125
|
+
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
126
|
+
const instrumentation = await ArchiverInstrumentation.new(telemetry, () => archiverStore.estimateSize());
|
|
127
|
+
|
|
128
|
+
// Create the event emitter that will be shared by archiver and synchronizer
|
|
129
|
+
const events = new EventEmitter() as ArchiverEmitter;
|
|
130
|
+
|
|
131
|
+
// Create the L1 synchronizer
|
|
132
|
+
const synchronizer = new ArchiverL1Synchronizer(
|
|
133
|
+
publicClient,
|
|
134
|
+
debugClient,
|
|
135
|
+
rollup,
|
|
136
|
+
inbox,
|
|
137
|
+
{ ...config.l1Contracts, slashingProposerAddress },
|
|
138
|
+
archiverStore,
|
|
139
|
+
archiverConfig,
|
|
140
|
+
deps.blobClient,
|
|
141
|
+
epochCache,
|
|
142
|
+
deps.dateProvider ?? new DateProvider(),
|
|
143
|
+
instrumentation,
|
|
144
|
+
l1Constants,
|
|
145
|
+
events,
|
|
146
|
+
instrumentation.tracer,
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const archiver = new Archiver(
|
|
150
|
+
publicClient,
|
|
151
|
+
debugClient,
|
|
152
|
+
rollup,
|
|
153
|
+
{ ...config.l1Contracts, slashingProposerAddress },
|
|
154
|
+
archiverStore,
|
|
155
|
+
archiverConfig,
|
|
156
|
+
deps.blobClient,
|
|
157
|
+
instrumentation,
|
|
158
|
+
l1Constants,
|
|
159
|
+
synchronizer,
|
|
160
|
+
events,
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
await archiver.start(opts.blockUntilSync);
|
|
164
|
+
return archiver;
|
|
44
165
|
}
|
|
45
166
|
|
|
46
|
-
|
|
167
|
+
/** Registers protocol contracts in the archiver store. */
|
|
168
|
+
export async function registerProtocolContracts(store: KVArchiverDataStore) {
|
|
47
169
|
const blockNumber = 0;
|
|
48
170
|
for (const name of protocolContractNames) {
|
|
49
171
|
const provider = new BundledProtocolContractsProvider();
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
export * from './archiver/index.js';
|
|
2
1
|
export * from './factory.js';
|
|
3
|
-
export * from './
|
|
2
|
+
export * from './interfaces.js';
|
|
3
|
+
export * from './archiver.js';
|
|
4
|
+
export * from './modules/data_source_base.js';
|
|
5
|
+
export * from './modules/data_store_updater.js';
|
|
6
|
+
export * from './config.js';
|
|
4
7
|
|
|
5
|
-
export {
|
|
8
|
+
export { type L1PublishedData } from './structs/published.js';
|
|
9
|
+
export { KVArchiverDataStore, ARCHIVER_DB_VERSION } from './store/kv_archiver_store.js';
|
|
10
|
+
export { ContractInstanceStore } from './store/contract_instance_store.js';
|
|
11
|
+
|
|
12
|
+
export { retrieveCheckpointsFromRollup, retrieveL2ProofVerifiedEvents } from './l1/data_retrieval.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
2
|
+
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
3
|
+
import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
|
|
4
|
+
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Helper interface to combine all sources this archiver implementation provides.
|
|
8
|
+
*/
|
|
9
|
+
export type ArchiverDataSource = L2BlockSource & L2LogsSource & ContractDataSource & L1ToL2MessageSource;
|
|
@@ -3,8 +3,9 @@ import type { ViemPublicClient, ViemPublicDebugClient } from '@aztec/ethereum/ty
|
|
|
3
3
|
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
|
+
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
6
7
|
|
|
7
|
-
import { type Hex, createPublicClient, http } from 'viem';
|
|
8
|
+
import { type Hex, createPublicClient, getAbiItem, http, toEventSelector } from 'viem';
|
|
8
9
|
import { mainnet } from 'viem/chains';
|
|
9
10
|
|
|
10
11
|
import { CalldataRetriever } from '../calldata_retriever.js';
|
|
@@ -76,7 +77,7 @@ async function main() {
|
|
|
76
77
|
// Create viem public client
|
|
77
78
|
const publicClient = createPublicClient({
|
|
78
79
|
chain: mainnet,
|
|
79
|
-
transport: http(rpcUrl),
|
|
80
|
+
transport: http(rpcUrl, { batch: false }),
|
|
80
81
|
});
|
|
81
82
|
|
|
82
83
|
logger.info('Fetching transaction...');
|
|
@@ -111,38 +112,36 @@ async function main() {
|
|
|
111
112
|
},
|
|
112
113
|
);
|
|
113
114
|
|
|
114
|
-
// Extract
|
|
115
|
-
logger.info('Decoding transaction to extract
|
|
115
|
+
// Extract checkpoint number from transaction logs
|
|
116
|
+
logger.info('Decoding transaction to extract checkpoint number...');
|
|
116
117
|
const receipt = await publicClient.getTransactionReceipt({ hash: txHash });
|
|
117
|
-
|
|
118
|
+
|
|
119
|
+
// Look for CheckpointProposed event (emitted when a checkpoint is proposed to the rollup)
|
|
120
|
+
// Event signature: CheckpointProposed(uint256 indexed checkpointNumber, bytes32 indexed archive, bytes32[], bytes32, bytes32)
|
|
121
|
+
// Hash: keccak256("CheckpointProposed(uint256,bytes32,bytes32[],bytes32,bytes32)")
|
|
122
|
+
const checkpointProposedEvent = receipt.logs.find(log => {
|
|
118
123
|
try {
|
|
119
|
-
// Try to match the L2BlockProposed event
|
|
120
124
|
return (
|
|
121
125
|
log.address.toLowerCase() === rollupAddress.toString().toLowerCase() &&
|
|
122
|
-
log.topics[0] ===
|
|
126
|
+
log.topics[0] === toEventSelector(getAbiItem({ abi: RollupAbi, name: 'CheckpointProposed' }))
|
|
123
127
|
);
|
|
124
128
|
} catch {
|
|
125
129
|
return false;
|
|
126
130
|
}
|
|
127
131
|
});
|
|
128
132
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// L2 block number is typically the first indexed parameter
|
|
132
|
-
l2BlockNumber = Number(BigInt(l2BlockProposedEvent.topics[1]));
|
|
133
|
-
logger.info(`L2 Block Number (from event): ${l2BlockNumber}`);
|
|
134
|
-
} else {
|
|
135
|
-
// Fallback: try to extract from transaction data or use a default
|
|
136
|
-
logger.warn('Could not extract L2 block number from event, using block number as fallback');
|
|
137
|
-
l2BlockNumber = Number(tx.blockNumber);
|
|
133
|
+
if (!checkpointProposedEvent || checkpointProposedEvent.topics[1] === undefined) {
|
|
134
|
+
throw new Error(`Checkpoint proposed event not found`);
|
|
138
135
|
}
|
|
139
136
|
|
|
137
|
+
const checkpointNumber = CheckpointNumber.fromBigInt(BigInt(checkpointProposedEvent.topics[1]));
|
|
138
|
+
|
|
140
139
|
logger.info('');
|
|
141
|
-
logger.info('Retrieving
|
|
140
|
+
logger.info('Retrieving checkpoint from rollup transaction...');
|
|
142
141
|
logger.info('');
|
|
143
142
|
|
|
144
|
-
// For this script, we don't have blob hashes, so pass empty
|
|
145
|
-
const result = await retriever.getCheckpointFromRollupTx(txHash, [],
|
|
143
|
+
// For this script, we don't have blob hashes or expected hashes, so pass empty arrays/objects
|
|
144
|
+
const result = await retriever.getCheckpointFromRollupTx(txHash, [], checkpointNumber, {});
|
|
146
145
|
|
|
147
146
|
logger.info(' Successfully retrieved block header!');
|
|
148
147
|
logger.info('');
|
|
@@ -13,11 +13,22 @@ import {
|
|
|
13
13
|
TallySlashingProposerAbi,
|
|
14
14
|
} from '@aztec/l1-artifacts';
|
|
15
15
|
import { CommitteeAttestation } from '@aztec/stdlib/block';
|
|
16
|
+
import { ConsensusPayload, SignatureDomainSeparator } from '@aztec/stdlib/p2p';
|
|
16
17
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
17
18
|
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
import {
|
|
20
|
+
type AbiParameter,
|
|
21
|
+
type Hex,
|
|
22
|
+
type Transaction,
|
|
23
|
+
decodeFunctionData,
|
|
24
|
+
encodeAbiParameters,
|
|
25
|
+
hexToBytes,
|
|
26
|
+
keccak256,
|
|
27
|
+
multicall3Abi,
|
|
28
|
+
toFunctionSelector,
|
|
29
|
+
} from 'viem';
|
|
30
|
+
|
|
31
|
+
import type { ArchiverInstrumentation } from '../modules/instrumentation.js';
|
|
21
32
|
import { getSuccessfulCallsFromDebug } from './debug_tx.js';
|
|
22
33
|
import { getCallFromSpireProposer } from './spire_proposer.js';
|
|
23
34
|
import { getSuccessfulCallsFromTrace } from './trace_tx.js';
|
|
@@ -56,12 +67,17 @@ export class CalldataRetriever {
|
|
|
56
67
|
* @param txHash - Hash of the tx that published it.
|
|
57
68
|
* @param blobHashes - Blob hashes for the checkpoint.
|
|
58
69
|
* @param checkpointNumber - Checkpoint number.
|
|
70
|
+
* @param expectedHashes - Optional expected hashes from the CheckpointProposed event for validation
|
|
59
71
|
* @returns Checkpoint header and metadata from the calldata, deserialized
|
|
60
72
|
*/
|
|
61
73
|
async getCheckpointFromRollupTx(
|
|
62
74
|
txHash: `0x${string}`,
|
|
63
|
-
|
|
75
|
+
_blobHashes: Buffer[],
|
|
64
76
|
checkpointNumber: CheckpointNumber,
|
|
77
|
+
expectedHashes: {
|
|
78
|
+
attestationsHash?: Hex;
|
|
79
|
+
payloadDigest?: Hex;
|
|
80
|
+
},
|
|
65
81
|
): Promise<{
|
|
66
82
|
checkpointNumber: CheckpointNumber;
|
|
67
83
|
archiveRoot: Fr;
|
|
@@ -69,10 +85,14 @@ export class CalldataRetriever {
|
|
|
69
85
|
attestations: CommitteeAttestation[];
|
|
70
86
|
blockHash: string;
|
|
71
87
|
}> {
|
|
72
|
-
this.logger.trace(`Fetching checkpoint ${checkpointNumber} from rollup tx ${txHash}
|
|
88
|
+
this.logger.trace(`Fetching checkpoint ${checkpointNumber} from rollup tx ${txHash}`, {
|
|
89
|
+
willValidateHashes: !!expectedHashes.attestationsHash || !!expectedHashes.payloadDigest,
|
|
90
|
+
hasAttestationsHash: !!expectedHashes.attestationsHash,
|
|
91
|
+
hasPayloadDigest: !!expectedHashes.payloadDigest,
|
|
92
|
+
});
|
|
73
93
|
const tx = await this.publicClient.getTransaction({ hash: txHash });
|
|
74
94
|
const proposeCalldata = await this.getProposeCallData(tx, checkpointNumber);
|
|
75
|
-
return this.decodeAndBuildCheckpoint(proposeCalldata, tx.blockHash!, checkpointNumber);
|
|
95
|
+
return this.decodeAndBuildCheckpoint(proposeCalldata, tx.blockHash!, checkpointNumber, expectedHashes);
|
|
76
96
|
}
|
|
77
97
|
|
|
78
98
|
/** Gets rollup propose calldata from a transaction */
|
|
@@ -324,17 +344,59 @@ export class CalldataRetriever {
|
|
|
324
344
|
return calls[0].input;
|
|
325
345
|
}
|
|
326
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Extracts the CommitteeAttestations struct definition from RollupAbi.
|
|
349
|
+
* Finds the _attestations parameter by name in the propose function.
|
|
350
|
+
* Lazy-loaded to avoid issues during module initialization.
|
|
351
|
+
*/
|
|
352
|
+
private getCommitteeAttestationsStructDef(): AbiParameter {
|
|
353
|
+
const proposeFunction = RollupAbi.find(item => item.type === 'function' && item.name === 'propose') as
|
|
354
|
+
| { type: 'function'; name: string; inputs: readonly AbiParameter[] }
|
|
355
|
+
| undefined;
|
|
356
|
+
|
|
357
|
+
if (!proposeFunction) {
|
|
358
|
+
throw new Error('propose function not found in RollupAbi');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Find the _attestations parameter by name, not by index
|
|
362
|
+
const attestationsParam = proposeFunction.inputs.find(param => param.name === '_attestations');
|
|
363
|
+
|
|
364
|
+
if (!attestationsParam) {
|
|
365
|
+
throw new Error('_attestations parameter not found in propose function');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (attestationsParam.type !== 'tuple') {
|
|
369
|
+
throw new Error(`Expected _attestations parameter to be a tuple, got ${attestationsParam.type}`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Extract the tuple components (struct fields)
|
|
373
|
+
const tupleParam = attestationsParam as unknown as {
|
|
374
|
+
type: 'tuple';
|
|
375
|
+
components?: readonly AbiParameter[];
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
return {
|
|
379
|
+
type: 'tuple',
|
|
380
|
+
components: tupleParam.components || [],
|
|
381
|
+
} as AbiParameter;
|
|
382
|
+
}
|
|
383
|
+
|
|
327
384
|
/**
|
|
328
385
|
* Decodes propose calldata and builds the checkpoint header structure.
|
|
329
386
|
* @param proposeCalldata - The propose function calldata
|
|
330
387
|
* @param blockHash - The L1 block hash containing this transaction
|
|
331
388
|
* @param checkpointNumber - The checkpoint number
|
|
389
|
+
* @param expectedHashes - Optional expected hashes from the CheckpointProposed event for validation
|
|
332
390
|
* @returns The decoded checkpoint header and metadata
|
|
333
391
|
*/
|
|
334
392
|
protected decodeAndBuildCheckpoint(
|
|
335
393
|
proposeCalldata: Hex,
|
|
336
394
|
blockHash: Hex,
|
|
337
395
|
checkpointNumber: CheckpointNumber,
|
|
396
|
+
expectedHashes: {
|
|
397
|
+
attestationsHash?: Hex;
|
|
398
|
+
payloadDigest?: Hex;
|
|
399
|
+
},
|
|
338
400
|
): {
|
|
339
401
|
checkpointNumber: CheckpointNumber;
|
|
340
402
|
archiveRoot: Fr;
|
|
@@ -365,6 +427,57 @@ export class CalldataRetriever {
|
|
|
365
427
|
];
|
|
366
428
|
|
|
367
429
|
const attestations = CommitteeAttestation.fromPacked(packedAttestations, this.targetCommitteeSize);
|
|
430
|
+
const header = CheckpointHeader.fromViem(decodedArgs.header);
|
|
431
|
+
const archiveRoot = new Fr(Buffer.from(hexToBytes(decodedArgs.archive)));
|
|
432
|
+
|
|
433
|
+
// Validate attestationsHash if provided (skip for backwards compatibility with older events)
|
|
434
|
+
if (expectedHashes.attestationsHash) {
|
|
435
|
+
// Compute attestationsHash: keccak256(abi.encode(CommitteeAttestations))
|
|
436
|
+
const computedAttestationsHash = keccak256(
|
|
437
|
+
encodeAbiParameters([this.getCommitteeAttestationsStructDef()], [packedAttestations]),
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
// Compare as buffers to avoid case-sensitivity and string comparison issues
|
|
441
|
+
const computedBuffer = Buffer.from(hexToBytes(computedAttestationsHash));
|
|
442
|
+
const expectedBuffer = Buffer.from(hexToBytes(expectedHashes.attestationsHash));
|
|
443
|
+
|
|
444
|
+
if (!computedBuffer.equals(expectedBuffer)) {
|
|
445
|
+
throw new Error(
|
|
446
|
+
`Attestations hash mismatch for checkpoint ${checkpointNumber}: ` +
|
|
447
|
+
`computed=${computedAttestationsHash}, expected=${expectedHashes.attestationsHash}`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
this.logger.trace(`Validated attestationsHash for checkpoint ${checkpointNumber}`, {
|
|
452
|
+
computedAttestationsHash,
|
|
453
|
+
expectedAttestationsHash: expectedHashes.attestationsHash,
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Validate payloadDigest if provided (skip for backwards compatibility with older events)
|
|
458
|
+
if (expectedHashes.payloadDigest) {
|
|
459
|
+
// Use ConsensusPayload to compute the digest - this ensures we match the exact logic
|
|
460
|
+
// used by the network for signing and verification
|
|
461
|
+
const consensusPayload = new ConsensusPayload(header, archiveRoot);
|
|
462
|
+
const payloadToSign = consensusPayload.getPayloadToSign(SignatureDomainSeparator.checkpointAttestation);
|
|
463
|
+
const computedPayloadDigest = keccak256(payloadToSign);
|
|
464
|
+
|
|
465
|
+
// Compare as buffers to avoid case-sensitivity and string comparison issues
|
|
466
|
+
const computedBuffer = Buffer.from(hexToBytes(computedPayloadDigest));
|
|
467
|
+
const expectedBuffer = Buffer.from(hexToBytes(expectedHashes.payloadDigest));
|
|
468
|
+
|
|
469
|
+
if (!computedBuffer.equals(expectedBuffer)) {
|
|
470
|
+
throw new Error(
|
|
471
|
+
`Payload digest mismatch for checkpoint ${checkpointNumber}: ` +
|
|
472
|
+
`computed=${computedPayloadDigest}, expected=${expectedHashes.payloadDigest}`,
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
this.logger.trace(`Validated payloadDigest for checkpoint ${checkpointNumber}`, {
|
|
477
|
+
computedPayloadDigest,
|
|
478
|
+
expectedPayloadDigest: expectedHashes.payloadDigest,
|
|
479
|
+
});
|
|
480
|
+
}
|
|
368
481
|
|
|
369
482
|
this.logger.trace(`Decoded propose calldata`, {
|
|
370
483
|
checkpointNumber,
|
|
@@ -376,9 +489,6 @@ export class CalldataRetriever {
|
|
|
376
489
|
targetCommitteeSize: this.targetCommitteeSize,
|
|
377
490
|
});
|
|
378
491
|
|
|
379
|
-
const header = CheckpointHeader.fromViem(decodedArgs.header);
|
|
380
|
-
const archiveRoot = new Fr(Buffer.from(hexToBytes(decodedArgs.archive)));
|
|
381
|
-
|
|
382
492
|
return {
|
|
383
493
|
checkpointNumber,
|
|
384
494
|
archiveRoot,
|