@aztec/archiver 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a
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 +7 -5
- package/dest/archiver.d.ts +49 -14
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +216 -68
- package/dest/config.d.ts +4 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +11 -16
- package/dest/errors.d.ts +19 -13
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +32 -16
- package/dest/factory.d.ts +12 -6
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +31 -21
- package/dest/index.d.ts +9 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +8 -1
- package/dest/l1/calldata_retriever.d.ts +2 -1
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +13 -4
- package/dest/l1/trace_tx.d.ts +12 -66
- package/dest/l1/trace_tx.d.ts.map +1 -1
- package/dest/modules/contract_data_source_adapter.d.ts +25 -0
- package/dest/modules/contract_data_source_adapter.d.ts.map +1 -0
- package/dest/modules/contract_data_source_adapter.js +40 -0
- package/dest/modules/data_source_base.d.ts +71 -49
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +269 -143
- package/dest/modules/data_store_updater.d.ts +18 -6
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +108 -59
- package/dest/modules/instrumentation.js +3 -1
- package/dest/modules/l1_synchronizer.d.ts +6 -5
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +203 -100
- package/dest/modules/outbox_trees_resolver.d.ts +62 -0
- package/dest/modules/outbox_trees_resolver.d.ts.map +1 -0
- package/dest/modules/outbox_trees_resolver.js +162 -0
- package/dest/modules/validation.d.ts +4 -3
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +4 -4
- package/dest/store/block_store.d.ts +155 -98
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +473 -265
- package/dest/store/contract_class_store.d.ts +17 -3
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +17 -1
- package/dest/store/contract_instance_store.d.ts +28 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +31 -0
- package/dest/store/data_stores.d.ts +68 -0
- package/dest/store/data_stores.d.ts.map +1 -0
- package/dest/store/data_stores.js +54 -0
- package/dest/store/function_names_cache.d.ts +17 -0
- package/dest/store/function_names_cache.d.ts.map +1 -0
- package/dest/store/function_names_cache.js +30 -0
- package/dest/store/l2_tips_cache.d.ts +13 -8
- package/dest/store/l2_tips_cache.d.ts.map +1 -1
- package/dest/store/l2_tips_cache.js +13 -96
- package/dest/store/log_store.d.ts +42 -40
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +257 -478
- package/dest/store/log_store_codec.d.ts +70 -0
- package/dest/store/log_store_codec.d.ts.map +1 -0
- package/dest/store/log_store_codec.js +101 -0
- package/dest/store/message_store.d.ts +9 -3
- package/dest/store/message_store.d.ts.map +1 -1
- package/dest/store/message_store.js +31 -1
- package/dest/test/fake_l1_state.d.ts +2 -1
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +25 -8
- package/dest/test/mock_l2_block_source.d.ts +47 -51
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +223 -185
- package/dest/test/noop_l1_archiver.d.ts +10 -6
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +19 -8
- package/package.json +14 -14
- package/src/archiver.ts +265 -72
- package/src/config.ts +12 -19
- package/src/errors.ts +46 -23
- package/src/factory.ts +38 -20
- package/src/index.ts +16 -1
- package/src/l1/calldata_retriever.ts +14 -4
- package/src/modules/contract_data_source_adapter.ts +55 -0
- package/src/modules/data_source_base.ts +335 -187
- package/src/modules/data_store_updater.ts +118 -61
- package/src/modules/instrumentation.ts +1 -1
- package/src/modules/l1_synchronizer.ts +278 -120
- package/src/modules/outbox_trees_resolver.ts +199 -0
- package/src/modules/validation.ts +8 -7
- package/src/store/block_store.ts +566 -323
- package/src/store/contract_class_store.ts +28 -2
- package/src/store/contract_instance_store.ts +43 -0
- package/src/store/data_stores.ts +104 -0
- package/src/store/function_names_cache.ts +37 -0
- package/src/store/l2_tips_cache.ts +16 -115
- package/src/store/log_store.ts +296 -650
- package/src/store/log_store_codec.ts +132 -0
- package/src/store/message_store.ts +35 -2
- package/src/test/fake_l1_state.ts +24 -14
- package/src/test/mock_l2_block_source.ts +271 -239
- package/src/test/noop_l1_archiver.ts +39 -8
- package/dest/store/kv_archiver_store.d.ts +0 -383
- package/dest/store/kv_archiver_store.d.ts.map +0 -1
- package/dest/store/kv_archiver_store.js +0 -501
- package/src/store/kv_archiver_store.ts +0 -728
|
@@ -1,44 +1,133 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
|
+
import {
|
|
3
|
+
BlockNumber,
|
|
4
|
+
CheckpointNumber,
|
|
5
|
+
type EpochNumber,
|
|
6
|
+
IndexWithinCheckpoint,
|
|
7
|
+
type SlotNumber,
|
|
8
|
+
} from '@aztec/foundation/branded-types';
|
|
3
9
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
10
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
-
import { isDefined } from '@aztec/foundation/types';
|
|
6
11
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
7
12
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
type BlockData,
|
|
15
|
+
type BlockHash,
|
|
16
|
+
type BlockQuery,
|
|
17
|
+
type BlockTag,
|
|
18
|
+
type BlocksQuery,
|
|
19
|
+
Body,
|
|
20
|
+
type CheckpointQuery,
|
|
21
|
+
type CheckpointsQuery,
|
|
22
|
+
L2Block,
|
|
23
|
+
type L2Tips,
|
|
24
|
+
type ProposedCheckpointQuery,
|
|
25
|
+
} from '@aztec/stdlib/block';
|
|
9
26
|
import {
|
|
10
27
|
Checkpoint,
|
|
11
28
|
type CheckpointData,
|
|
12
|
-
type CommonCheckpointData,
|
|
13
29
|
type ProposedCheckpointData,
|
|
14
30
|
PublishedCheckpoint,
|
|
15
31
|
} from '@aztec/stdlib/checkpoint';
|
|
16
32
|
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
17
|
-
import {
|
|
18
|
-
|
|
33
|
+
import {
|
|
34
|
+
type L1RollupConstants,
|
|
35
|
+
getEpochAtSlot,
|
|
36
|
+
getEpochNumberAtTimestamp,
|
|
37
|
+
getLastL1SlotTimestampForL2Slot,
|
|
38
|
+
getProofSubmissionDeadlineEpoch,
|
|
39
|
+
getSlotRangeForEpoch,
|
|
40
|
+
} from '@aztec/stdlib/epoch-helpers';
|
|
19
41
|
import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
|
|
20
|
-
import type {
|
|
21
|
-
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
22
|
-
import
|
|
23
|
-
import type { BlockHeader, IndexedTxEffect, TxHash
|
|
42
|
+
import type { LogResult, PrivateLogsQuery, PublicLogsQuery } from '@aztec/stdlib/logs';
|
|
43
|
+
import type { L1ToL2MessageSource, L2ToL1MembershipWitness } from '@aztec/stdlib/messaging';
|
|
44
|
+
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
45
|
+
import type { BlockHeader, IndexedTxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
24
46
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
25
47
|
|
|
26
48
|
import type { ArchiverDataSource } from '../interfaces.js';
|
|
27
|
-
import type {
|
|
49
|
+
import type { ResolvedBlockQuery, ResolvedBlocksQuery } from '../store/block_store.js';
|
|
50
|
+
import type { ArchiverDataStores } from '../store/data_stores.js';
|
|
28
51
|
import type { ValidateCheckpointResult } from './validation.js';
|
|
29
52
|
|
|
30
53
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
54
|
+
* Sentinel returned by {@link ArchiverDataSourceBase#resolveBlockQuery} when a query resolves
|
|
55
|
+
* to the genesis block. Forces single-block lookup methods to take the genesis branch
|
|
56
|
+
* explicitly rather than silently falling through to the BlockStore (which never has a block 0).
|
|
57
|
+
*/
|
|
58
|
+
type GenesisBlockQuery = { genesis: true };
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Abstract base class implementing ArchiverDataSource using a bundle of archiver substores.
|
|
62
|
+
* Provides implementations for all read-side methods and declares abstract methods for
|
|
63
|
+
* L1-dependent functionality that subclasses must implement.
|
|
34
64
|
*/
|
|
35
65
|
export abstract class ArchiverDataSourceBase
|
|
36
66
|
implements ArchiverDataSource, L2LogsSource, ContractDataSource, L1ToL2MessageSource
|
|
37
67
|
{
|
|
68
|
+
/** The injected genesis block header. */
|
|
69
|
+
protected readonly initialHeader: BlockHeader;
|
|
70
|
+
/** Precomputed hash of the initial header, exposed via {@link getGenesisBlockHash}. */
|
|
71
|
+
protected readonly initialBlockHash: BlockHash;
|
|
72
|
+
/** Archive root after block 0 was appended — read from L1 (`Rollup.getGenesisArchiveTreeRoot`). */
|
|
73
|
+
protected readonly genesisArchiveRoot: Fr;
|
|
74
|
+
|
|
75
|
+
/** Memoized synthetic genesis block — callers rely on referential identity for caching. */
|
|
76
|
+
private readonly genesisBlock: L2Block;
|
|
77
|
+
/** Memoized synthetic genesis block data — kept consistent with {@link genesisBlock}. */
|
|
78
|
+
private readonly genesisBlockData: BlockData;
|
|
79
|
+
|
|
38
80
|
constructor(
|
|
39
|
-
protected readonly
|
|
40
|
-
protected readonly l1Constants
|
|
41
|
-
|
|
81
|
+
protected readonly stores: ArchiverDataStores,
|
|
82
|
+
protected readonly l1Constants: L1RollupConstants | undefined,
|
|
83
|
+
initialHeader: BlockHeader,
|
|
84
|
+
initialBlockHash: BlockHash,
|
|
85
|
+
genesisArchiveRoot: Fr,
|
|
86
|
+
) {
|
|
87
|
+
this.initialHeader = initialHeader;
|
|
88
|
+
this.initialBlockHash = initialBlockHash;
|
|
89
|
+
this.genesisArchiveRoot = genesisArchiveRoot;
|
|
90
|
+
|
|
91
|
+
const genesisArchive = new AppendOnlyTreeSnapshot(genesisArchiveRoot, 1);
|
|
92
|
+
this.genesisBlock = new L2Block(
|
|
93
|
+
genesisArchive,
|
|
94
|
+
initialHeader,
|
|
95
|
+
Body.empty(),
|
|
96
|
+
CheckpointNumber.ZERO,
|
|
97
|
+
IndexWithinCheckpoint(0),
|
|
98
|
+
);
|
|
99
|
+
this.genesisBlockData = {
|
|
100
|
+
header: initialHeader,
|
|
101
|
+
archive: genesisArchive,
|
|
102
|
+
blockHash: initialBlockHash,
|
|
103
|
+
checkpointNumber: CheckpointNumber.ZERO,
|
|
104
|
+
indexWithinCheckpoint: IndexWithinCheckpoint(0),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Returns the precomputed hash of the genesis block header. */
|
|
109
|
+
public getGenesisBlockHash(): BlockHash {
|
|
110
|
+
return this.initialBlockHash;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Returns the synthetic genesis L2Block (memoized — same instance across calls). */
|
|
114
|
+
private getGenesisBlock(): L2Block {
|
|
115
|
+
return this.genesisBlock;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Returns genesis block data (memoized — same instance across calls). */
|
|
119
|
+
private getGenesisBlockData(): BlockData {
|
|
120
|
+
return this.genesisBlockData;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Type guard distinguishing the genesis sentinel from a {@link ResolvedBlockQuery}.
|
|
125
|
+
* `resolveBlockQuery` already rewrites every genesis-matching shape to the sentinel,
|
|
126
|
+
* so callers only need this single sync check.
|
|
127
|
+
*/
|
|
128
|
+
private isGenesisBlockQuery(query: ResolvedBlockQuery | GenesisBlockQuery): query is GenesisBlockQuery {
|
|
129
|
+
return 'genesis' in query;
|
|
130
|
+
}
|
|
42
131
|
|
|
43
132
|
abstract getRollupAddress(): Promise<EthAddress>;
|
|
44
133
|
|
|
@@ -60,115 +149,147 @@ export abstract class ArchiverDataSourceBase
|
|
|
60
149
|
|
|
61
150
|
abstract syncImmediate(): Promise<void>;
|
|
62
151
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return this.store.getSynchedCheckpointNumber();
|
|
69
|
-
}
|
|
152
|
+
abstract getL2ToL1MembershipWitness(
|
|
153
|
+
txHash: TxHash,
|
|
154
|
+
message: Fr,
|
|
155
|
+
messageIndexInTx?: number,
|
|
156
|
+
): Promise<L2ToL1MembershipWitness | undefined>;
|
|
70
157
|
|
|
71
|
-
public
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
158
|
+
public async isPruneDueAtSlot(slot: SlotNumber): Promise<boolean> {
|
|
159
|
+
if (!this.l1Constants) {
|
|
160
|
+
throw new Error('isPruneDueAtSlot requires l1Constants');
|
|
161
|
+
}
|
|
162
|
+
const tips = await this.getL2Tips();
|
|
163
|
+
const proven = tips.proven.checkpoint.number;
|
|
164
|
+
const pending = tips.checkpointed.checkpoint.number;
|
|
165
|
+
if (pending === proven) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
82
168
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return undefined;
|
|
169
|
+
const oldestUnproven = await this.getCheckpointData({ number: CheckpointNumber(Number(proven) + 1) });
|
|
170
|
+
if (!oldestUnproven) {
|
|
171
|
+
return false;
|
|
87
172
|
}
|
|
88
|
-
const headers = await this.store.getBlockHeaders(blockNumber, 1);
|
|
89
|
-
return headers.length === 0 ? undefined : headers[0];
|
|
90
|
-
}
|
|
91
173
|
|
|
92
|
-
|
|
93
|
-
|
|
174
|
+
const slotTs = getLastL1SlotTimestampForL2Slot(slot, this.l1Constants);
|
|
175
|
+
const slotEpoch = getEpochNumberAtTimestamp(slotTs, this.l1Constants);
|
|
176
|
+
const oldestUnprovenEpoch = getEpochAtSlot(oldestUnproven.header.slotNumber, this.l1Constants);
|
|
177
|
+
const deadlineEpoch = getProofSubmissionDeadlineEpoch(oldestUnprovenEpoch, this.l1Constants);
|
|
178
|
+
return slotEpoch >= deadlineEpoch;
|
|
94
179
|
}
|
|
95
180
|
|
|
96
|
-
public
|
|
97
|
-
return this.
|
|
181
|
+
public getCheckpointNumber(): Promise<CheckpointNumber> {
|
|
182
|
+
return this.stores.blocks.getLatestCheckpointNumber();
|
|
98
183
|
}
|
|
99
184
|
|
|
100
|
-
public
|
|
101
|
-
return this.
|
|
185
|
+
public getProvenCheckpointNumber(): Promise<CheckpointNumber> {
|
|
186
|
+
return this.stores.blocks.getProvenCheckpointNumber();
|
|
102
187
|
}
|
|
103
188
|
|
|
104
|
-
public
|
|
105
|
-
|
|
106
|
-
|
|
189
|
+
public getBlockNumber(): Promise<BlockNumber>;
|
|
190
|
+
public getBlockNumber(query: BlockQuery): Promise<BlockNumber | undefined>;
|
|
191
|
+
public async getBlockNumber(query?: BlockQuery): Promise<BlockNumber | undefined> {
|
|
192
|
+
if (!query) {
|
|
193
|
+
return this.stores.blocks.getLatestL2BlockNumber();
|
|
107
194
|
}
|
|
108
|
-
|
|
195
|
+
const resolved = await this.resolveBlockQuery(query);
|
|
196
|
+
if (resolved === undefined) {
|
|
109
197
|
return undefined;
|
|
110
198
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return undefined;
|
|
199
|
+
if (this.isGenesisBlockQuery(resolved)) {
|
|
200
|
+
return BlockNumber.ZERO;
|
|
114
201
|
}
|
|
115
|
-
return
|
|
202
|
+
return this.stores.blocks.getBlockNumber(resolved);
|
|
116
203
|
}
|
|
117
204
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Resolves a {@link CheckpointQuery} to a concrete `CheckpointNumber`, or undefined when the
|
|
207
|
+
* query refers to a position that has no checkpoint yet (e.g. `{ slot }` not found).
|
|
208
|
+
*/
|
|
209
|
+
private resolveCheckpointQuery(query: CheckpointQuery): Promise<CheckpointNumber | undefined> {
|
|
210
|
+
if ('number' in query) {
|
|
211
|
+
return Promise.resolve(query.number);
|
|
212
|
+
}
|
|
213
|
+
if ('slot' in query) {
|
|
214
|
+
return this.stores.blocks.getCheckpointNumberBySlot(query.slot);
|
|
215
|
+
}
|
|
216
|
+
// tag variant
|
|
217
|
+
switch (query.tag) {
|
|
218
|
+
case 'checkpointed':
|
|
219
|
+
return this.stores.blocks.getLatestCheckpointNumber();
|
|
220
|
+
case 'proven':
|
|
221
|
+
return this.stores.blocks.getProvenCheckpointNumber();
|
|
222
|
+
case 'finalized':
|
|
223
|
+
return this.stores.blocks.getFinalizedCheckpointNumber();
|
|
122
224
|
}
|
|
123
|
-
return BlockNumber(checkpointData.startBlock + checkpointData.blockCount - 1);
|
|
124
225
|
}
|
|
125
226
|
|
|
126
|
-
|
|
127
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Resolves a {@link CheckpointsQuery} to a concrete `{from, limit}` pair used by BlockStore,
|
|
229
|
+
* or undefined when the epoch has no checkpoints.
|
|
230
|
+
*/
|
|
231
|
+
private async resolveCheckpointsQuery(
|
|
232
|
+
query: CheckpointsQuery,
|
|
233
|
+
): Promise<{ from: CheckpointNumber; limit: number } | undefined> {
|
|
234
|
+
if ('from' in query) {
|
|
235
|
+
return query;
|
|
236
|
+
}
|
|
237
|
+
const numbers = await this.getCheckpointNumbersForEpoch(query.epoch);
|
|
238
|
+
if (numbers.length === 0) {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
return { from: numbers[0], limit: numbers.length };
|
|
128
242
|
}
|
|
129
243
|
|
|
130
|
-
public
|
|
131
|
-
|
|
244
|
+
public async getCheckpoint(query: CheckpointQuery): Promise<PublishedCheckpoint | undefined> {
|
|
245
|
+
const number = await this.resolveCheckpointQuery(query);
|
|
246
|
+
if (number === undefined || number === 0) {
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
const data = await this.stores.blocks.getCheckpointData(number);
|
|
250
|
+
if (!data) {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
return this.getPublishedCheckpointFromCheckpointData(data);
|
|
132
254
|
}
|
|
133
255
|
|
|
134
|
-
public
|
|
135
|
-
|
|
256
|
+
public async getCheckpoints(query: CheckpointsQuery): Promise<PublishedCheckpoint[]> {
|
|
257
|
+
const resolved = await this.resolveCheckpointsQuery(query);
|
|
258
|
+
if (!resolved) {
|
|
259
|
+
return [];
|
|
260
|
+
}
|
|
261
|
+
const checkpoints = await this.stores.blocks.getRangeOfCheckpoints(resolved.from, resolved.limit);
|
|
262
|
+
return Promise.all(checkpoints.map(ch => this.getPublishedCheckpointFromCheckpointData(ch)));
|
|
136
263
|
}
|
|
137
264
|
|
|
138
|
-
public
|
|
139
|
-
|
|
265
|
+
public async getCheckpointData(query: CheckpointQuery): Promise<CheckpointData | undefined> {
|
|
266
|
+
const number = await this.resolveCheckpointQuery(query);
|
|
267
|
+
if (number === undefined || number === 0) {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
return this.stores.blocks.getCheckpointData(number);
|
|
140
271
|
}
|
|
141
272
|
|
|
142
|
-
public
|
|
143
|
-
|
|
273
|
+
public async getCheckpointsData(query: CheckpointsQuery): Promise<CheckpointData[]> {
|
|
274
|
+
const resolved = await this.resolveCheckpointsQuery(query);
|
|
275
|
+
if (!resolved) {
|
|
276
|
+
return [];
|
|
277
|
+
}
|
|
278
|
+
return this.stores.blocks.getRangeOfCheckpoints(resolved.from, resolved.limit);
|
|
144
279
|
}
|
|
145
280
|
|
|
146
|
-
public
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
number = await this.store.getLatestBlockNumber();
|
|
281
|
+
public getProposedCheckpointData(query?: ProposedCheckpointQuery): Promise<ProposedCheckpointData | undefined> {
|
|
282
|
+
if (!query || 'tag' in query) {
|
|
283
|
+
return this.stores.blocks.getLastProposedCheckpoint();
|
|
150
284
|
}
|
|
151
|
-
if (number
|
|
152
|
-
return
|
|
285
|
+
if ('number' in query) {
|
|
286
|
+
return this.stores.blocks.getProposedCheckpointByNumber(query.number);
|
|
153
287
|
}
|
|
154
|
-
|
|
155
|
-
return publishedBlock;
|
|
288
|
+
return this.stores.blocks.getProposedCheckpointBySlot(query.slot);
|
|
156
289
|
}
|
|
157
290
|
|
|
158
291
|
public getTxEffect(txHash: TxHash): Promise<IndexedTxEffect | undefined> {
|
|
159
|
-
return this.
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
|
|
163
|
-
return this.store.getSettledTxReceipt(txHash, this.l1Constants);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public getProposedCheckpoint(): Promise<CommonCheckpointData | undefined> {
|
|
167
|
-
return this.store.getProposedCheckpoint();
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
public getProposedCheckpointOnly(): Promise<ProposedCheckpointData | undefined> {
|
|
171
|
-
return this.store.getProposedCheckpointOnly();
|
|
292
|
+
return this.stores.blocks.getTxEffect(txHash);
|
|
172
293
|
}
|
|
173
294
|
|
|
174
295
|
public isPendingChainInvalid(): Promise<boolean> {
|
|
@@ -176,40 +297,23 @@ export abstract class ArchiverDataSourceBase
|
|
|
176
297
|
}
|
|
177
298
|
|
|
178
299
|
public async getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
|
|
179
|
-
return (await this.
|
|
300
|
+
return (await this.stores.blocks.getPendingChainValidationStatus()) ?? { valid: true };
|
|
180
301
|
}
|
|
181
302
|
|
|
182
|
-
public getPrivateLogsByTags(
|
|
183
|
-
|
|
184
|
-
page?: number,
|
|
185
|
-
upToBlockNumber?: BlockNumber,
|
|
186
|
-
): Promise<TxScopedL2Log[][]> {
|
|
187
|
-
return this.store.getPrivateLogsByTags(tags, page, upToBlockNumber);
|
|
303
|
+
public getPrivateLogsByTags(query: PrivateLogsQuery): Promise<LogResult[][]> {
|
|
304
|
+
return this.stores.logs.getPrivateLogsByTags(query);
|
|
188
305
|
}
|
|
189
306
|
|
|
190
|
-
public
|
|
191
|
-
|
|
192
|
-
tags: Tag[],
|
|
193
|
-
page?: number,
|
|
194
|
-
upToBlockNumber?: BlockNumber,
|
|
195
|
-
): Promise<TxScopedL2Log[][]> {
|
|
196
|
-
return this.store.getPublicLogsByTagsFromContract(contractAddress, tags, page, upToBlockNumber);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
public getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
|
|
200
|
-
return this.store.getPublicLogs(filter);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
public getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
|
|
204
|
-
return this.store.getContractClassLogs(filter);
|
|
307
|
+
public getPublicLogsByTags(query: PublicLogsQuery): Promise<LogResult[][]> {
|
|
308
|
+
return this.stores.logs.getPublicLogsByTags(query);
|
|
205
309
|
}
|
|
206
310
|
|
|
207
311
|
public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
208
|
-
return this.
|
|
312
|
+
return this.stores.contractClasses.getContractClass(id);
|
|
209
313
|
}
|
|
210
314
|
|
|
211
315
|
public getBytecodeCommitment(id: Fr): Promise<Fr | undefined> {
|
|
212
|
-
return this.
|
|
316
|
+
return this.stores.contractClasses.getBytecodeCommitment(id);
|
|
213
317
|
}
|
|
214
318
|
|
|
215
319
|
public async getContract(
|
|
@@ -218,43 +322,39 @@ export abstract class ArchiverDataSourceBase
|
|
|
218
322
|
): Promise<ContractInstanceWithAddress | undefined> {
|
|
219
323
|
let timestamp;
|
|
220
324
|
if (maybeTimestamp === undefined) {
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
timestamp = latestBlockHeader ? latestBlockHeader.globalVariables.timestamp : 0n;
|
|
325
|
+
const latestBlockData = await this.getBlockData({ tag: 'proposed' });
|
|
326
|
+
timestamp = latestBlockData ? latestBlockData.header.globalVariables.timestamp : 0n;
|
|
224
327
|
} else {
|
|
225
328
|
timestamp = maybeTimestamp;
|
|
226
329
|
}
|
|
227
330
|
|
|
228
|
-
return this.
|
|
331
|
+
return this.stores.contractInstances.getContractInstance(address, timestamp);
|
|
229
332
|
}
|
|
230
333
|
|
|
231
334
|
public getContractClassIds(): Promise<Fr[]> {
|
|
232
|
-
return this.
|
|
335
|
+
return this.stores.contractClasses.getContractClassIds();
|
|
233
336
|
}
|
|
234
337
|
|
|
235
|
-
|
|
236
|
-
|
|
338
|
+
/** Looks up a public function name given a selector. */
|
|
339
|
+
public getDebugFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
|
|
340
|
+
return Promise.resolve(this.stores.functionNames.get(selector));
|
|
237
341
|
}
|
|
238
342
|
|
|
343
|
+
/** Register public function signatures so they can be looked up by selector. */
|
|
239
344
|
public registerContractFunctionSignatures(signatures: string[]): Promise<void> {
|
|
240
|
-
return this.
|
|
345
|
+
return this.stores.functionNames.register(signatures);
|
|
241
346
|
}
|
|
242
347
|
|
|
243
348
|
public getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|
|
244
|
-
return this.
|
|
349
|
+
return this.stores.messages.getL1ToL2Messages(checkpointNumber);
|
|
245
350
|
}
|
|
246
351
|
|
|
247
352
|
public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
|
|
248
|
-
return this.
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
public async getCheckpoints(checkpointNumber: CheckpointNumber, limit: number): Promise<PublishedCheckpoint[]> {
|
|
252
|
-
const checkpoints = await this.store.getRangeOfCheckpoints(checkpointNumber, limit);
|
|
253
|
-
return Promise.all(checkpoints.map(ch => this.getPublishedCheckpointFromCheckpointData(ch)));
|
|
353
|
+
return this.stores.messages.getL1ToL2MessageIndex(l1ToL2Message);
|
|
254
354
|
}
|
|
255
355
|
|
|
256
356
|
private async getPublishedCheckpointFromCheckpointData(checkpoint: CheckpointData): Promise<PublishedCheckpoint> {
|
|
257
|
-
const blocksForCheckpoint = await this.
|
|
357
|
+
const blocksForCheckpoint = await this.stores.blocks.getBlocksForCheckpoint(checkpoint.checkpointNumber);
|
|
258
358
|
if (!blocksForCheckpoint) {
|
|
259
359
|
throw new Error(`Blocks for checkpoint ${checkpoint.checkpointNumber} not found`);
|
|
260
360
|
}
|
|
@@ -263,85 +363,133 @@ export abstract class ArchiverDataSourceBase
|
|
|
263
363
|
checkpoint.header,
|
|
264
364
|
blocksForCheckpoint,
|
|
265
365
|
checkpoint.checkpointNumber,
|
|
366
|
+
checkpoint.feeAssetPriceModifier,
|
|
266
367
|
);
|
|
267
368
|
return new PublishedCheckpoint(fullCheckpoint, checkpoint.l1, checkpoint.attestations);
|
|
268
369
|
}
|
|
269
370
|
|
|
270
371
|
public getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
|
|
271
|
-
return this.
|
|
372
|
+
return this.stores.blocks.getBlocksForSlot(slotNumber);
|
|
272
373
|
}
|
|
273
374
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const blocks = await Promise.all(
|
|
277
|
-
checkpointsData.flatMap(checkpoint =>
|
|
278
|
-
range(checkpoint.blockCount, checkpoint.startBlock).map(blockNumber =>
|
|
279
|
-
this.getCheckpointedBlock(BlockNumber(blockNumber)),
|
|
280
|
-
),
|
|
281
|
-
),
|
|
282
|
-
);
|
|
283
|
-
return blocks.filter(isDefined);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
public async getCheckpointedBlockHeadersForEpoch(epochNumber: EpochNumber): Promise<BlockHeader[]> {
|
|
287
|
-
const checkpointsData = await this.getCheckpointsDataForEpoch(epochNumber);
|
|
288
|
-
const blocks = await Promise.all(
|
|
289
|
-
checkpointsData.flatMap(checkpoint =>
|
|
290
|
-
range(checkpoint.blockCount, checkpoint.startBlock).map(blockNumber =>
|
|
291
|
-
this.getBlockHeader(BlockNumber(blockNumber)),
|
|
292
|
-
),
|
|
293
|
-
),
|
|
294
|
-
);
|
|
295
|
-
return blocks.filter(isDefined);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
public async getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
|
|
299
|
-
const checkpointsData = await this.getCheckpointsDataForEpoch(epochNumber);
|
|
300
|
-
return Promise.all(
|
|
301
|
-
checkpointsData.map(data => this.getPublishedCheckpointFromCheckpointData(data).then(p => p.checkpoint)),
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/** Returns checkpoint data for all checkpoints whose slot falls within the given epoch. */
|
|
306
|
-
public getCheckpointsDataForEpoch(epochNumber: EpochNumber): Promise<CheckpointData[]> {
|
|
375
|
+
/** Returns just the checkpoint numbers for all checkpoints whose slot falls within the given epoch. */
|
|
376
|
+
private getCheckpointNumbersForEpoch(epochNumber: EpochNumber): Promise<CheckpointNumber[]> {
|
|
307
377
|
if (!this.l1Constants) {
|
|
308
378
|
throw new Error('L1 constants not set');
|
|
309
379
|
}
|
|
310
380
|
|
|
311
381
|
const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1Constants);
|
|
312
|
-
return this.
|
|
382
|
+
return this.stores.blocks.getCheckpointNumbersForSlotRange(start, end);
|
|
313
383
|
}
|
|
314
384
|
|
|
315
|
-
public async getBlock(
|
|
316
|
-
|
|
317
|
-
if (
|
|
318
|
-
number = await this.store.getLatestBlockNumber();
|
|
319
|
-
}
|
|
320
|
-
if (number === 0) {
|
|
385
|
+
public async getBlock(query: BlockQuery): Promise<L2Block | undefined> {
|
|
386
|
+
const resolved = await this.resolveBlockQuery(query);
|
|
387
|
+
if (resolved === undefined) {
|
|
321
388
|
return undefined;
|
|
322
389
|
}
|
|
323
|
-
|
|
390
|
+
if (this.isGenesisBlockQuery(resolved)) {
|
|
391
|
+
return this.getGenesisBlock();
|
|
392
|
+
}
|
|
393
|
+
return this.stores.blocks.getBlock(resolved);
|
|
324
394
|
}
|
|
325
395
|
|
|
326
|
-
|
|
327
|
-
|
|
396
|
+
/**
|
|
397
|
+
* Range queries iterate physical blocks only; the genesis block is NOT prepended.
|
|
398
|
+
* `L2BlockStream` consumers (`world-state.handleL2Blocks`, etc.) emit `blocks-added` events for
|
|
399
|
+
* real blocks and would be surprised by a synthetic block 0. Use {@link getBlock} or
|
|
400
|
+
* {@link getBlockData} for genesis-aware single-block lookups.
|
|
401
|
+
*/
|
|
402
|
+
public async getBlocks(query: BlocksQuery): Promise<L2Block[]> {
|
|
403
|
+
const resolved = await this.resolveBlocksQuery(query);
|
|
404
|
+
return resolved ? this.stores.blocks.getBlocks(resolved) : [];
|
|
328
405
|
}
|
|
329
406
|
|
|
330
|
-
public
|
|
331
|
-
|
|
407
|
+
public async getBlockData(query: BlockQuery): Promise<BlockData | undefined> {
|
|
408
|
+
const resolved = await this.resolveBlockQuery(query);
|
|
409
|
+
if (resolved === undefined) {
|
|
410
|
+
return undefined;
|
|
411
|
+
}
|
|
412
|
+
if (this.isGenesisBlockQuery(resolved)) {
|
|
413
|
+
return this.getGenesisBlockData();
|
|
414
|
+
}
|
|
415
|
+
return this.stores.blocks.getBlockData(resolved);
|
|
332
416
|
}
|
|
333
417
|
|
|
334
|
-
|
|
335
|
-
|
|
418
|
+
/** See {@link getBlocks} — range queries do not prepend the genesis block. */
|
|
419
|
+
public async getBlocksData(query: BlocksQuery): Promise<BlockData[]> {
|
|
420
|
+
const resolved = await this.resolveBlocksQuery(query);
|
|
421
|
+
return resolved ? this.stores.blocks.getBlocksData(resolved) : [];
|
|
336
422
|
}
|
|
337
423
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
424
|
+
/**
|
|
425
|
+
* Resolves a {@link BlockQuery} to either the genesis sentinel or a {@link ResolvedBlockQuery}
|
|
426
|
+
* understood by BlockStore. Detects every shape that points at block 0 — `{number:0}`,
|
|
427
|
+
* `{hash}` matching the initial header, `{archive}` matching the post-genesis archive root,
|
|
428
|
+
* and `{tag}` resolving to 0 — and rewrites them to the sentinel so callers branch once.
|
|
429
|
+
*/
|
|
430
|
+
private async resolveBlockQuery(query: BlockQuery): Promise<ResolvedBlockQuery | GenesisBlockQuery | undefined> {
|
|
431
|
+
if ('number' in query) {
|
|
432
|
+
return query.number === BlockNumber.ZERO ? { genesis: true } : query;
|
|
433
|
+
}
|
|
434
|
+
if ('hash' in query) {
|
|
435
|
+
return query.hash.equals(this.initialBlockHash) ? { genesis: true } : query;
|
|
436
|
+
}
|
|
437
|
+
if ('archive' in query) {
|
|
438
|
+
return query.archive.equals(this.genesisArchiveRoot) ? { genesis: true } : query;
|
|
439
|
+
}
|
|
440
|
+
const number = await this.resolveBlockTag(query.tag);
|
|
441
|
+
if (number === BlockNumber.ZERO) {
|
|
442
|
+
return { genesis: true };
|
|
443
|
+
}
|
|
444
|
+
return { number };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** Maps a {@link BlockTag} to the matching block number for the current chain state. */
|
|
448
|
+
private resolveBlockTag(tag: BlockTag): Promise<BlockNumber> {
|
|
449
|
+
switch (tag) {
|
|
450
|
+
case 'latest':
|
|
451
|
+
case 'proposed':
|
|
452
|
+
return this.stores.blocks.getLatestL2BlockNumber();
|
|
453
|
+
case 'checkpointed':
|
|
454
|
+
return this.stores.blocks.getCheckpointedL2BlockNumber();
|
|
455
|
+
case 'proven':
|
|
456
|
+
return this.stores.blocks.getProvenBlockNumber();
|
|
457
|
+
case 'finalized':
|
|
458
|
+
return this.stores.blocks.getFinalizedL2BlockNumber();
|
|
459
|
+
}
|
|
341
460
|
}
|
|
342
461
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
462
|
+
/**
|
|
463
|
+
* Converts an epoch-based BlocksQuery to a from/limit query using l1Constants.
|
|
464
|
+
* Returns undefined when the epoch has no checkpoints, so callers can return [] without
|
|
465
|
+
* entering BlockStore. Reads only the two endpoint checkpoints rather than the whole epoch.
|
|
466
|
+
*/
|
|
467
|
+
private async resolveBlocksQuery(query: BlocksQuery): Promise<ResolvedBlocksQuery | undefined> {
|
|
468
|
+
if (!('epoch' in query)) {
|
|
469
|
+
if (query.from < INITIAL_L2_BLOCK_NUM) {
|
|
470
|
+
throw new Error(
|
|
471
|
+
`getBlocks/getBlocksData: 'from' must be >= ${INITIAL_L2_BLOCK_NUM}, got ${query.from}. ` +
|
|
472
|
+
`Use getBlock({number:0})/getBlockData({number:0}) for genesis-aware single-block lookups.`,
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
return query;
|
|
476
|
+
}
|
|
477
|
+
const checkpointNumbers = await this.getCheckpointNumbersForEpoch(query.epoch);
|
|
478
|
+
if (checkpointNumbers.length === 0) {
|
|
479
|
+
return undefined;
|
|
480
|
+
}
|
|
481
|
+
const firstNumber = checkpointNumbers[0];
|
|
482
|
+
const lastNumber = checkpointNumbers[checkpointNumbers.length - 1];
|
|
483
|
+
const first = await this.stores.blocks.getCheckpointData(firstNumber);
|
|
484
|
+
if (!first) {
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
const last = firstNumber === lastNumber ? first : await this.stores.blocks.getCheckpointData(lastNumber);
|
|
488
|
+
if (!last) {
|
|
489
|
+
return undefined;
|
|
490
|
+
}
|
|
491
|
+
const from = BlockNumber(first.startBlock);
|
|
492
|
+
const limit = last.startBlock + last.blockCount - first.startBlock;
|
|
493
|
+
return { from, limit, onlyCheckpointed: true };
|
|
346
494
|
}
|
|
347
495
|
}
|