@aztec/archiver 0.0.1-commit.934299a21 → 0.0.1-commit.949a33fd8
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 +12 -6
- package/dest/archiver.d.ts +18 -10
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +146 -57
- package/dest/config.d.ts +5 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +16 -4
- package/dest/errors.d.ts +61 -10
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +88 -14
- package/dest/factory.d.ts +4 -5
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +26 -22
- package/dest/index.d.ts +3 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -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 +11 -5
- package/dest/l1/data_retrieval.d.ts +24 -12
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +36 -37
- package/dest/l1/validate_historical_logs.d.ts +23 -0
- package/dest/l1/validate_historical_logs.d.ts.map +1 -0
- package/dest/l1/validate_historical_logs.js +108 -0
- package/dest/modules/data_source_base.d.ts +12 -6
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +24 -6
- package/dest/modules/data_store_updater.d.ts +28 -15
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +102 -80
- package/dest/modules/instrumentation.d.ts +7 -2
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +22 -6
- package/dest/modules/l1_synchronizer.d.ts +8 -2
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +292 -144
- package/dest/modules/validation.d.ts +4 -3
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +6 -6
- package/dest/store/block_store.d.ts +83 -17
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +399 -124
- package/dest/store/contract_class_store.d.ts +2 -3
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +7 -67
- package/dest/store/contract_instance_store.d.ts +1 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +6 -2
- package/dest/store/kv_archiver_store.d.ts +70 -23
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +88 -27
- package/dest/store/l2_tips_cache.d.ts +2 -1
- package/dest/store/l2_tips_cache.d.ts.map +1 -1
- package/dest/store/l2_tips_cache.js +27 -7
- package/dest/store/log_store.d.ts +6 -3
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +95 -20
- package/dest/store/message_store.d.ts +5 -1
- package/dest/store/message_store.d.ts.map +1 -1
- package/dest/store/message_store.js +21 -9
- package/dest/test/fake_l1_state.d.ts +20 -1
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +114 -18
- package/dest/test/mock_l1_to_l2_message_source.d.ts +1 -1
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +2 -1
- package/dest/test/mock_l2_block_source.d.ts +19 -4
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +57 -7
- package/dest/test/mock_structs.d.ts +4 -1
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +13 -1
- package/dest/test/noop_l1_archiver.d.ts +4 -1
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +9 -3
- package/package.json +13 -13
- package/src/archiver.ts +179 -56
- package/src/config.ts +23 -2
- package/src/errors.ts +133 -22
- package/src/factory.ts +24 -15
- package/src/index.ts +2 -1
- package/src/l1/calldata_retriever.ts +17 -5
- package/src/l1/data_retrieval.ts +52 -53
- package/src/l1/validate_historical_logs.ts +140 -0
- package/src/modules/data_source_base.ts +43 -7
- package/src/modules/data_store_updater.ts +126 -109
- package/src/modules/instrumentation.ts +27 -7
- package/src/modules/l1_synchronizer.ts +371 -178
- package/src/modules/validation.ts +10 -9
- package/src/store/block_store.ts +489 -143
- package/src/store/contract_class_store.ts +8 -106
- package/src/store/contract_instance_store.ts +8 -5
- package/src/store/kv_archiver_store.ts +133 -39
- package/src/store/l2_tips_cache.ts +58 -13
- package/src/store/log_store.ts +128 -32
- package/src/store/message_store.ts +27 -10
- package/src/structs/inbox_message.ts +1 -1
- package/src/test/fake_l1_state.ts +142 -29
- package/src/test/mock_l1_to_l2_message_source.ts +1 -0
- package/src/test/mock_l2_block_source.ts +73 -5
- package/src/test/mock_structs.ts +20 -6
- package/src/test/noop_l1_archiver.ts +10 -2
|
@@ -2,14 +2,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
2
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
3
|
import { BufferReader, numToUInt8, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
4
4
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
5
|
-
import {
|
|
6
|
-
import type {
|
|
7
|
-
ContractClassPublic,
|
|
8
|
-
ContractClassPublicWithBlockNumber,
|
|
9
|
-
ExecutablePrivateFunctionWithMembershipProof,
|
|
10
|
-
UtilityFunctionWithMembershipProof,
|
|
11
|
-
} from '@aztec/stdlib/contract';
|
|
12
|
-
import { Vector } from '@aztec/stdlib/types';
|
|
5
|
+
import type { ContractClassPublic, ContractClassPublicWithBlockNumber } from '@aztec/stdlib/contract';
|
|
13
6
|
|
|
14
7
|
/**
|
|
15
8
|
* LMDB-based contract class storage for the archiver.
|
|
@@ -29,11 +22,15 @@ export class ContractClassStore {
|
|
|
29
22
|
blockNumber: number,
|
|
30
23
|
): Promise<void> {
|
|
31
24
|
await this.db.transactionAsync(async () => {
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
const key = contractClass.id.toString();
|
|
26
|
+
if (await this.#contractClasses.hasAsync(key)) {
|
|
27
|
+
throw new Error(`Contract class ${key} already exists, cannot add again at block ${blockNumber}`);
|
|
28
|
+
}
|
|
29
|
+
await this.#contractClasses.set(
|
|
30
|
+
key,
|
|
34
31
|
serializeContractClassPublic({ ...contractClass, l2BlockNumber: blockNumber }),
|
|
35
32
|
);
|
|
36
|
-
await this.#bytecodeCommitments.
|
|
33
|
+
await this.#bytecodeCommitments.set(key, bytecodeCommitment.toBuffer());
|
|
37
34
|
});
|
|
38
35
|
}
|
|
39
36
|
|
|
@@ -60,37 +57,6 @@ export class ContractClassStore {
|
|
|
60
57
|
async getContractClassIds(): Promise<Fr[]> {
|
|
61
58
|
return (await toArray(this.#contractClasses.keysAsync())).map(key => Fr.fromHexString(key));
|
|
62
59
|
}
|
|
63
|
-
|
|
64
|
-
async addFunctions(
|
|
65
|
-
contractClassId: Fr,
|
|
66
|
-
newPrivateFunctions: ExecutablePrivateFunctionWithMembershipProof[],
|
|
67
|
-
newUtilityFunctions: UtilityFunctionWithMembershipProof[],
|
|
68
|
-
): Promise<boolean> {
|
|
69
|
-
await this.db.transactionAsync(async () => {
|
|
70
|
-
const existingClassBuffer = await this.#contractClasses.getAsync(contractClassId.toString());
|
|
71
|
-
if (!existingClassBuffer) {
|
|
72
|
-
throw new Error(`Unknown contract class ${contractClassId} when adding private functions to store`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const existingClass = deserializeContractClassPublic(existingClassBuffer);
|
|
76
|
-
const { privateFunctions: existingPrivateFns, utilityFunctions: existingUtilityFns } = existingClass;
|
|
77
|
-
|
|
78
|
-
const updatedClass: Omit<ContractClassPublicWithBlockNumber, 'id'> = {
|
|
79
|
-
...existingClass,
|
|
80
|
-
privateFunctions: [
|
|
81
|
-
...existingPrivateFns,
|
|
82
|
-
...newPrivateFunctions.filter(newFn => !existingPrivateFns.some(f => f.selector.equals(newFn.selector))),
|
|
83
|
-
],
|
|
84
|
-
utilityFunctions: [
|
|
85
|
-
...existingUtilityFns,
|
|
86
|
-
...newUtilityFunctions.filter(newFn => !existingUtilityFns.some(f => f.selector.equals(newFn.selector))),
|
|
87
|
-
],
|
|
88
|
-
};
|
|
89
|
-
await this.#contractClasses.set(contractClassId.toString(), serializeContractClassPublic(updatedClass));
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
60
|
}
|
|
95
61
|
|
|
96
62
|
function serializeContractClassPublic(contractClass: Omit<ContractClassPublicWithBlockNumber, 'id'>): Buffer {
|
|
@@ -98,83 +64,19 @@ function serializeContractClassPublic(contractClass: Omit<ContractClassPublicWit
|
|
|
98
64
|
contractClass.l2BlockNumber,
|
|
99
65
|
numToUInt8(contractClass.version),
|
|
100
66
|
contractClass.artifactHash,
|
|
101
|
-
contractClass.privateFunctions.length,
|
|
102
|
-
contractClass.privateFunctions.map(serializePrivateFunction),
|
|
103
|
-
contractClass.utilityFunctions.length,
|
|
104
|
-
contractClass.utilityFunctions.map(serializeUtilityFunction),
|
|
105
67
|
contractClass.packedBytecode.length,
|
|
106
68
|
contractClass.packedBytecode,
|
|
107
69
|
contractClass.privateFunctionsRoot,
|
|
108
70
|
);
|
|
109
71
|
}
|
|
110
72
|
|
|
111
|
-
function serializePrivateFunction(fn: ExecutablePrivateFunctionWithMembershipProof): Buffer {
|
|
112
|
-
return serializeToBuffer(
|
|
113
|
-
fn.selector,
|
|
114
|
-
fn.vkHash,
|
|
115
|
-
fn.bytecode.length,
|
|
116
|
-
fn.bytecode,
|
|
117
|
-
fn.functionMetadataHash,
|
|
118
|
-
fn.artifactMetadataHash,
|
|
119
|
-
fn.utilityFunctionsTreeRoot,
|
|
120
|
-
new Vector(fn.privateFunctionTreeSiblingPath),
|
|
121
|
-
fn.privateFunctionTreeLeafIndex,
|
|
122
|
-
new Vector(fn.artifactTreeSiblingPath),
|
|
123
|
-
fn.artifactTreeLeafIndex,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function serializeUtilityFunction(fn: UtilityFunctionWithMembershipProof): Buffer {
|
|
128
|
-
return serializeToBuffer(
|
|
129
|
-
fn.selector,
|
|
130
|
-
fn.bytecode.length,
|
|
131
|
-
fn.bytecode,
|
|
132
|
-
fn.functionMetadataHash,
|
|
133
|
-
fn.artifactMetadataHash,
|
|
134
|
-
fn.privateFunctionsArtifactTreeRoot,
|
|
135
|
-
new Vector(fn.artifactTreeSiblingPath),
|
|
136
|
-
fn.artifactTreeLeafIndex,
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
73
|
function deserializeContractClassPublic(buffer: Buffer): Omit<ContractClassPublicWithBlockNumber, 'id'> {
|
|
141
74
|
const reader = BufferReader.asReader(buffer);
|
|
142
75
|
return {
|
|
143
76
|
l2BlockNumber: reader.readNumber(),
|
|
144
77
|
version: reader.readUInt8() as 1,
|
|
145
78
|
artifactHash: reader.readObject(Fr),
|
|
146
|
-
privateFunctions: reader.readVector({ fromBuffer: deserializePrivateFunction }),
|
|
147
|
-
utilityFunctions: reader.readVector({ fromBuffer: deserializeUtilityFunction }),
|
|
148
79
|
packedBytecode: reader.readBuffer(),
|
|
149
80
|
privateFunctionsRoot: reader.readObject(Fr),
|
|
150
81
|
};
|
|
151
82
|
}
|
|
152
|
-
|
|
153
|
-
function deserializePrivateFunction(buffer: Buffer | BufferReader): ExecutablePrivateFunctionWithMembershipProof {
|
|
154
|
-
const reader = BufferReader.asReader(buffer);
|
|
155
|
-
return {
|
|
156
|
-
selector: reader.readObject(FunctionSelector),
|
|
157
|
-
vkHash: reader.readObject(Fr),
|
|
158
|
-
bytecode: reader.readBuffer(),
|
|
159
|
-
functionMetadataHash: reader.readObject(Fr),
|
|
160
|
-
artifactMetadataHash: reader.readObject(Fr),
|
|
161
|
-
utilityFunctionsTreeRoot: reader.readObject(Fr),
|
|
162
|
-
privateFunctionTreeSiblingPath: reader.readVector(Fr),
|
|
163
|
-
privateFunctionTreeLeafIndex: reader.readNumber(),
|
|
164
|
-
artifactTreeSiblingPath: reader.readVector(Fr),
|
|
165
|
-
artifactTreeLeafIndex: reader.readNumber(),
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function deserializeUtilityFunction(buffer: Buffer | BufferReader): UtilityFunctionWithMembershipProof {
|
|
170
|
-
const reader = BufferReader.asReader(buffer);
|
|
171
|
-
return {
|
|
172
|
-
selector: reader.readObject(FunctionSelector),
|
|
173
|
-
bytecode: reader.readBuffer(),
|
|
174
|
-
functionMetadataHash: reader.readObject(Fr),
|
|
175
|
-
artifactMetadataHash: reader.readObject(Fr),
|
|
176
|
-
privateFunctionsArtifactTreeRoot: reader.readObject(Fr),
|
|
177
|
-
artifactTreeSiblingPath: reader.readVector(Fr),
|
|
178
|
-
artifactTreeLeafIndex: reader.readNumber(),
|
|
179
|
-
};
|
|
180
|
-
}
|
|
@@ -27,11 +27,14 @@ export class ContractInstanceStore {
|
|
|
27
27
|
|
|
28
28
|
addContractInstance(contractInstance: ContractInstanceWithAddress, blockNumber: number): Promise<void> {
|
|
29
29
|
return this.db.transactionAsync(async () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
new
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
const key = contractInstance.address.toString();
|
|
31
|
+
if (await this.#contractInstances.hasAsync(key)) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Contract instance at ${key} already exists (deployed at block ${await this.#contractInstancePublishedAt.getAsync(key)}), cannot add again at block ${blockNumber}`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
await this.#contractInstances.set(key, new SerializableContractInstance(contractInstance).toBuffer());
|
|
37
|
+
await this.#contractInstancePublishedAt.set(key, blockNumber);
|
|
35
38
|
});
|
|
36
39
|
}
|
|
37
40
|
|
|
@@ -10,17 +10,24 @@ import {
|
|
|
10
10
|
type BlockData,
|
|
11
11
|
BlockHash,
|
|
12
12
|
CheckpointedL2Block,
|
|
13
|
+
type CommitteeAttestation,
|
|
13
14
|
L2Block,
|
|
14
15
|
type ValidateCheckpointResult,
|
|
15
16
|
} from '@aztec/stdlib/block';
|
|
16
|
-
import type {
|
|
17
|
+
import type {
|
|
18
|
+
CheckpointData,
|
|
19
|
+
CommonCheckpointData,
|
|
20
|
+
L1PublishedData,
|
|
21
|
+
ProposedCheckpointData,
|
|
22
|
+
ProposedCheckpointInput,
|
|
23
|
+
PublishedCheckpoint,
|
|
24
|
+
} from '@aztec/stdlib/checkpoint';
|
|
17
25
|
import type {
|
|
18
26
|
ContractClassPublic,
|
|
27
|
+
ContractClassPublicWithCommitment,
|
|
19
28
|
ContractDataSource,
|
|
20
29
|
ContractInstanceUpdateWithAddress,
|
|
21
30
|
ContractInstanceWithAddress,
|
|
22
|
-
ExecutablePrivateFunctionWithMembershipProof,
|
|
23
|
-
UtilityFunctionWithMembershipProof,
|
|
24
31
|
} from '@aztec/stdlib/contract';
|
|
25
32
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
26
33
|
import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
|
|
@@ -37,7 +44,7 @@ import { ContractInstanceStore } from './contract_instance_store.js';
|
|
|
37
44
|
import { LogStore } from './log_store.js';
|
|
38
45
|
import { MessageStore } from './message_store.js';
|
|
39
46
|
|
|
40
|
-
export const ARCHIVER_DB_VERSION =
|
|
47
|
+
export const ARCHIVER_DB_VERSION = 6;
|
|
41
48
|
export const MAX_FUNCTION_SIGNATURES = 1000;
|
|
42
49
|
export const MAX_FUNCTION_NAME_LEN = 256;
|
|
43
50
|
|
|
@@ -71,9 +78,8 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
71
78
|
constructor(
|
|
72
79
|
private db: AztecAsyncKVStore,
|
|
73
80
|
logsMaxPageSize: number = 1000,
|
|
74
|
-
l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
75
81
|
) {
|
|
76
|
-
this.#blockStore = new BlockStore(db
|
|
82
|
+
this.#blockStore = new BlockStore(db);
|
|
77
83
|
this.#logStore = new LogStore(db, this.#blockStore, logsMaxPageSize);
|
|
78
84
|
this.#messageStore = new MessageStore(db);
|
|
79
85
|
this.#contractClassStore = new ContractClassStore(db);
|
|
@@ -168,19 +174,14 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
168
174
|
|
|
169
175
|
/**
|
|
170
176
|
* Add new contract classes from an L2 block to the store's list.
|
|
171
|
-
* @param data - List of contract classes to be added.
|
|
172
|
-
* @param bytecodeCommitments - Bytecode commitments for the contract classes.
|
|
177
|
+
* @param data - List of contract classes (with bytecode commitments) to be added.
|
|
173
178
|
* @param blockNumber - Number of the L2 block the contracts were registered in.
|
|
174
179
|
* @returns True if the operation is successful.
|
|
175
180
|
*/
|
|
176
|
-
async addContractClasses(
|
|
177
|
-
data: ContractClassPublic[],
|
|
178
|
-
bytecodeCommitments: Fr[],
|
|
179
|
-
blockNumber: BlockNumber,
|
|
180
|
-
): Promise<boolean> {
|
|
181
|
+
async addContractClasses(data: ContractClassPublicWithCommitment[], blockNumber: BlockNumber): Promise<boolean> {
|
|
181
182
|
return (
|
|
182
183
|
await Promise.all(
|
|
183
|
-
data.map(
|
|
184
|
+
data.map(c => this.#contractClassStore.addContractClass(c, c.publicBytecodeCommitment, blockNumber)),
|
|
184
185
|
)
|
|
185
186
|
).every(Boolean);
|
|
186
187
|
}
|
|
@@ -195,15 +196,6 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
195
196
|
return this.#contractClassStore.getBytecodeCommitment(contractClassId);
|
|
196
197
|
}
|
|
197
198
|
|
|
198
|
-
/** Adds private functions to a contract class. */
|
|
199
|
-
addFunctions(
|
|
200
|
-
contractClassId: Fr,
|
|
201
|
-
privateFunctions: ExecutablePrivateFunctionWithMembershipProof[],
|
|
202
|
-
utilityFunctions: UtilityFunctionWithMembershipProof[],
|
|
203
|
-
): Promise<boolean> {
|
|
204
|
-
return this.#contractClassStore.addFunctions(contractClassId, privateFunctions, utilityFunctions);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
199
|
/**
|
|
208
200
|
* Add new contract instances from an L2 block to the store's list.
|
|
209
201
|
* @param data - List of contract instances to be added.
|
|
@@ -246,14 +238,14 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
246
238
|
}
|
|
247
239
|
|
|
248
240
|
/**
|
|
249
|
-
* Append new proposed
|
|
250
|
-
*
|
|
241
|
+
* Append a new proposed block to the store.
|
|
242
|
+
* This is an uncheckpointed block that has been proposed by the sequencer but not yet included in a checkpoint on L1.
|
|
251
243
|
* For checkpointed blocks (already published to L1), use addCheckpoints() instead.
|
|
252
|
-
* @param
|
|
244
|
+
* @param block - The proposed L2 block to be added to the store.
|
|
253
245
|
* @returns True if the operation is successful.
|
|
254
246
|
*/
|
|
255
|
-
|
|
256
|
-
return this.#blockStore.
|
|
247
|
+
addProposedBlock(block: L2Block, opts: { force?: boolean } = {}): Promise<boolean> {
|
|
248
|
+
return this.#blockStore.addProposedBlock(block, opts);
|
|
257
249
|
}
|
|
258
250
|
|
|
259
251
|
/**
|
|
@@ -270,7 +262,7 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
270
262
|
* @returns The number of the latest block
|
|
271
263
|
*/
|
|
272
264
|
getLatestBlockNumber(): Promise<BlockNumber> {
|
|
273
|
-
return this.#blockStore.
|
|
265
|
+
return this.#blockStore.getLatestL2BlockNumber();
|
|
274
266
|
}
|
|
275
267
|
|
|
276
268
|
/**
|
|
@@ -410,8 +402,11 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
410
402
|
* @param txHash - The hash of a tx we try to get the receipt for.
|
|
411
403
|
* @returns The requested tx receipt (or undefined if not found).
|
|
412
404
|
*/
|
|
413
|
-
getSettledTxReceipt(
|
|
414
|
-
|
|
405
|
+
getSettledTxReceipt(
|
|
406
|
+
txHash: TxHash,
|
|
407
|
+
l1Constants?: Pick<L1RollupConstants, 'epochDuration'>,
|
|
408
|
+
): Promise<TxReceipt | undefined> {
|
|
409
|
+
return this.#blockStore.getSettledTxReceipt(txHash, l1Constants);
|
|
415
410
|
}
|
|
416
411
|
|
|
417
412
|
/**
|
|
@@ -472,10 +467,11 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
472
467
|
* array implies no logs match that tag.
|
|
473
468
|
* @param tags - The tags to search for.
|
|
474
469
|
* @param page - The page number (0-indexed) for pagination. Returns at most 10 logs per tag per page.
|
|
470
|
+
* @param upToBlockNumber - If set, only return logs from blocks up to and including this block number.
|
|
475
471
|
*/
|
|
476
|
-
getPrivateLogsByTags(tags: SiloedTag[], page?: number): Promise<TxScopedL2Log[][]> {
|
|
472
|
+
getPrivateLogsByTags(tags: SiloedTag[], page?: number, upToBlockNumber?: BlockNumber): Promise<TxScopedL2Log[][]> {
|
|
477
473
|
try {
|
|
478
|
-
return this.#logStore.getPrivateLogsByTags(tags, page);
|
|
474
|
+
return this.#logStore.getPrivateLogsByTags(tags, page, upToBlockNumber);
|
|
479
475
|
} catch (err) {
|
|
480
476
|
return Promise.reject(err);
|
|
481
477
|
}
|
|
@@ -487,14 +483,16 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
487
483
|
* @param contractAddress - The contract address to search logs for.
|
|
488
484
|
* @param tags - The tags to search for.
|
|
489
485
|
* @param page - The page number (0-indexed) for pagination. Returns at most 10 logs per tag per page.
|
|
486
|
+
* @param upToBlockNumber - If set, only return logs from blocks up to and including this block number.
|
|
490
487
|
*/
|
|
491
488
|
getPublicLogsByTagsFromContract(
|
|
492
489
|
contractAddress: AztecAddress,
|
|
493
490
|
tags: Tag[],
|
|
494
491
|
page?: number,
|
|
492
|
+
upToBlockNumber?: BlockNumber,
|
|
495
493
|
): Promise<TxScopedL2Log[][]> {
|
|
496
494
|
try {
|
|
497
|
-
return this.#logStore.getPublicLogsByTagsFromContract(contractAddress, tags, page);
|
|
495
|
+
return this.#logStore.getPublicLogsByTagsFromContract(contractAddress, tags, page, upToBlockNumber);
|
|
498
496
|
} catch (err) {
|
|
499
497
|
return Promise.reject(err);
|
|
500
498
|
}
|
|
@@ -542,15 +540,24 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
542
540
|
await this.#blockStore.setProvenCheckpointNumber(checkpointNumber);
|
|
543
541
|
}
|
|
544
542
|
|
|
545
|
-
|
|
546
|
-
|
|
543
|
+
/**
|
|
544
|
+
* Gets the number of the latest finalized checkpoint processed.
|
|
545
|
+
* @returns The number of the latest finalized checkpoint processed.
|
|
546
|
+
*/
|
|
547
|
+
getFinalizedCheckpointNumber(): Promise<CheckpointNumber> {
|
|
548
|
+
return this.#blockStore.getFinalizedCheckpointNumber();
|
|
547
549
|
}
|
|
548
550
|
|
|
549
551
|
/**
|
|
550
|
-
* Stores the
|
|
552
|
+
* Stores the number of the latest finalized checkpoint processed.
|
|
553
|
+
* @param checkpointNumber - The number of the latest finalized checkpoint processed.
|
|
551
554
|
*/
|
|
552
|
-
async
|
|
553
|
-
await this.#
|
|
555
|
+
async setFinalizedCheckpointNumber(checkpointNumber: CheckpointNumber) {
|
|
556
|
+
await this.#blockStore.setFinalizedCheckpointNumber(checkpointNumber);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
async setBlockSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
560
|
+
await this.#blockStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
554
561
|
}
|
|
555
562
|
|
|
556
563
|
/**
|
|
@@ -585,6 +592,11 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
585
592
|
return this.#messageStore.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
|
|
586
593
|
}
|
|
587
594
|
|
|
595
|
+
/** Atomically updates the message sync state: the L1 sync point and the inbox tree-in-progress marker. */
|
|
596
|
+
public setMessageSyncState(l1Block: L1BlockId, treeInProgress: bigint | undefined): Promise<void> {
|
|
597
|
+
return this.#messageStore.setMessageSyncState(l1Block, treeInProgress);
|
|
598
|
+
}
|
|
599
|
+
|
|
588
600
|
/** Returns an async iterator to all L1 to L2 messages on the range. */
|
|
589
601
|
public iterateL1ToL2Messages(range: CustomRange<bigint> = {}): AsyncIterableIterator<InboxMessage> {
|
|
590
602
|
return this.#messageStore.iterateL1ToL2Messages(range);
|
|
@@ -605,6 +617,73 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
605
617
|
return this.#blockStore.setPendingChainValidationStatus(status);
|
|
606
618
|
}
|
|
607
619
|
|
|
620
|
+
/**
|
|
621
|
+
* Gets the L2 block number of the proposed checkpoint.
|
|
622
|
+
* @returns The block number of the proposed checkpoint, or the checkpointed block number if none.
|
|
623
|
+
*/
|
|
624
|
+
public getProposedCheckpointL2BlockNumber(): Promise<BlockNumber> {
|
|
625
|
+
return this.#blockStore.getProposedCheckpointL2BlockNumber();
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/** Returns the checkpoint data at the proposed tip */
|
|
629
|
+
public getLastCheckpoint(): Promise<CommonCheckpointData | undefined> {
|
|
630
|
+
return this.#blockStore.getLastCheckpoint();
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/** Returns the proposed checkpoint data, or undefined if no proposed checkpoint exists. No fallback to confirmed. */
|
|
634
|
+
public getLastProposedCheckpoint(): Promise<ProposedCheckpointData | undefined> {
|
|
635
|
+
return this.#blockStore.getLastProposedCheckpoint();
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Set proposed checkpoint
|
|
640
|
+
* @param proposedCheckpoint
|
|
641
|
+
* @returns
|
|
642
|
+
*/
|
|
643
|
+
public addProposedCheckpoint(proposedCheckpoint: ProposedCheckpointInput): Promise<void> {
|
|
644
|
+
return this.#blockStore.addProposedCheckpoint(proposedCheckpoint);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/** Deletes all pending proposed checkpoints from storage. */
|
|
648
|
+
public deleteProposedCheckpoints(): Promise<void> {
|
|
649
|
+
return this.#blockStore.deleteProposedCheckpoints();
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/** Returns the pending checkpoint for a specific checkpoint number, or undefined if not found. */
|
|
653
|
+
public getProposedCheckpointByNumber(n: CheckpointNumber): Promise<ProposedCheckpointData | undefined> {
|
|
654
|
+
return this.#blockStore.getProposedCheckpointByNumber(n);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/** Returns all pending checkpoints in ascending checkpoint-number order. */
|
|
658
|
+
public getProposedCheckpoints(): Promise<ProposedCheckpointData[]> {
|
|
659
|
+
return this.#blockStore.getProposedCheckpoints();
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Evicts all pending checkpoints with checkpoint number >= fromNumber.
|
|
664
|
+
* Used for divergent-mined-checkpoint cleanup.
|
|
665
|
+
*/
|
|
666
|
+
public evictProposedCheckpointsFrom(fromNumber: CheckpointNumber): Promise<void> {
|
|
667
|
+
return this.#blockStore.evictProposedCheckpointsFrom(fromNumber);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Promotes a specific pending checkpoint to a confirmed checkpoint entry.
|
|
672
|
+
* Should only be called after the checkpoint has been validated.
|
|
673
|
+
* @param checkpointNumber - The checkpoint number to promote.
|
|
674
|
+
* @param l1 - L1 published data for the checkpoint.
|
|
675
|
+
* @param attestations - Committee attestations.
|
|
676
|
+
* @param expectedArchiveRoot - The archive root to match against the proposed checkpoint, to guard against races.
|
|
677
|
+
*/
|
|
678
|
+
public promoteProposedToCheckpointed(
|
|
679
|
+
checkpointNumber: CheckpointNumber,
|
|
680
|
+
l1: L1PublishedData,
|
|
681
|
+
attestations: CommitteeAttestation[],
|
|
682
|
+
expectedArchiveRoot: Fr,
|
|
683
|
+
): Promise<void> {
|
|
684
|
+
return this.#blockStore.promoteProposedToCheckpointed(checkpointNumber, l1, attestations, expectedArchiveRoot);
|
|
685
|
+
}
|
|
686
|
+
|
|
608
687
|
/**
|
|
609
688
|
* Gets the number of the latest L2 block processed.
|
|
610
689
|
* @returns The number of the latest L2 block processed.
|
|
@@ -650,6 +729,21 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
650
729
|
return this.#blockStore.getCheckpointDataForSlotRange(startSlot, endSlot);
|
|
651
730
|
}
|
|
652
731
|
|
|
732
|
+
/** Returns lightweight checkpoint metadata for a range of checkpoints. */
|
|
733
|
+
getCheckpointDataRange(from: CheckpointNumber, limit: number): Promise<CheckpointData[]> {
|
|
734
|
+
return this.#blockStore.getRangeOfCheckpoints(from, limit);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/** Returns the checkpoint number for a given slot, if one exists. */
|
|
738
|
+
getCheckpointNumberBySlot(slot: SlotNumber): Promise<CheckpointNumber | undefined> {
|
|
739
|
+
return this.#blockStore.getCheckpointNumberBySlot(slot);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/** Returns block metadata plus checkpoint-derived context (L1 publish info, attestations). */
|
|
743
|
+
getBlockDataWithCheckpointContext(blockNumber: BlockNumber) {
|
|
744
|
+
return this.#blockStore.getBlockDataWithCheckpointContext(blockNumber);
|
|
745
|
+
}
|
|
746
|
+
|
|
653
747
|
/**
|
|
654
748
|
* Gets all blocks that have the given slot number.
|
|
655
749
|
* @param slotNumber - The slot number to search for.
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
2
|
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type BlockData,
|
|
5
|
+
type CheckpointId,
|
|
6
|
+
GENESIS_BLOCK_HEADER_HASH,
|
|
7
|
+
GENESIS_CHECKPOINT_HEADER_HASH,
|
|
8
|
+
type L2Tips,
|
|
9
|
+
} from '@aztec/stdlib/block';
|
|
4
10
|
|
|
5
11
|
import type { BlockStore } from './block_store.js';
|
|
6
12
|
|
|
@@ -26,9 +32,16 @@ export class L2TipsCache {
|
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
private async loadFromStore(): Promise<L2Tips> {
|
|
29
|
-
const [
|
|
30
|
-
|
|
35
|
+
const [
|
|
36
|
+
latestBlockNumber,
|
|
37
|
+
provenBlockNumber,
|
|
38
|
+
proposedCheckpointBlockNumber,
|
|
39
|
+
checkpointedBlockNumber,
|
|
40
|
+
finalizedBlockNumber,
|
|
41
|
+
] = await Promise.all([
|
|
42
|
+
this.blockStore.getLatestL2BlockNumber(),
|
|
31
43
|
this.blockStore.getProvenBlockNumber(),
|
|
44
|
+
this.blockStore.getProposedCheckpointL2BlockNumber(),
|
|
32
45
|
this.blockStore.getCheckpointedL2BlockNumber(),
|
|
33
46
|
this.blockStore.getFinalizedL2BlockNumber(),
|
|
34
47
|
]);
|
|
@@ -42,19 +55,34 @@ export class L2TipsCache {
|
|
|
42
55
|
const getBlockData = (blockNumber: BlockNumber) =>
|
|
43
56
|
blockNumber > beforeInitialBlockNumber ? this.blockStore.getBlockData(blockNumber) : genesisBlockHeader;
|
|
44
57
|
|
|
45
|
-
const [latestBlockData, provenBlockData, checkpointedBlockData, finalizedBlockData] =
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
const [latestBlockData, provenBlockData, proposedCheckpointBlockData, checkpointedBlockData, finalizedBlockData] =
|
|
59
|
+
await Promise.all(
|
|
60
|
+
[
|
|
61
|
+
latestBlockNumber,
|
|
62
|
+
provenBlockNumber,
|
|
63
|
+
proposedCheckpointBlockNumber,
|
|
64
|
+
checkpointedBlockNumber,
|
|
65
|
+
finalizedBlockNumber,
|
|
66
|
+
].map(getBlockData),
|
|
67
|
+
);
|
|
48
68
|
|
|
49
|
-
if (
|
|
69
|
+
if (
|
|
70
|
+
!latestBlockData ||
|
|
71
|
+
!provenBlockData ||
|
|
72
|
+
!finalizedBlockData ||
|
|
73
|
+
!checkpointedBlockData ||
|
|
74
|
+
!proposedCheckpointBlockData
|
|
75
|
+
) {
|
|
50
76
|
throw new Error('Failed to load block data for L2 tips');
|
|
51
77
|
}
|
|
52
78
|
|
|
53
|
-
const [provenCheckpointId, finalizedCheckpointId, checkpointedCheckpointId] =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
const [provenCheckpointId, finalizedCheckpointId, proposedCheckpointId, checkpointedCheckpointId] =
|
|
80
|
+
await Promise.all([
|
|
81
|
+
this.getCheckpointIdForBlock(provenBlockData),
|
|
82
|
+
this.getCheckpointIdForBlock(finalizedBlockData),
|
|
83
|
+
this.getCheckpointIdForProposedCheckpoint(checkpointedBlockData),
|
|
84
|
+
this.getCheckpointIdForBlock(checkpointedBlockData),
|
|
85
|
+
]);
|
|
58
86
|
|
|
59
87
|
return {
|
|
60
88
|
proposed: { number: latestBlockNumber, hash: latestBlockData.blockHash.toString() },
|
|
@@ -62,6 +90,10 @@ export class L2TipsCache {
|
|
|
62
90
|
block: { number: provenBlockNumber, hash: provenBlockData.blockHash.toString() },
|
|
63
91
|
checkpoint: provenCheckpointId,
|
|
64
92
|
},
|
|
93
|
+
proposedCheckpoint: {
|
|
94
|
+
block: { number: proposedCheckpointBlockNumber, hash: proposedCheckpointBlockData.blockHash.toString() },
|
|
95
|
+
checkpoint: proposedCheckpointId,
|
|
96
|
+
},
|
|
65
97
|
finalized: {
|
|
66
98
|
block: { number: finalizedBlockNumber, hash: finalizedBlockData.blockHash.toString() },
|
|
67
99
|
checkpoint: finalizedCheckpointId,
|
|
@@ -73,6 +105,19 @@ export class L2TipsCache {
|
|
|
73
105
|
};
|
|
74
106
|
}
|
|
75
107
|
|
|
108
|
+
private async getCheckpointIdForProposedCheckpoint(
|
|
109
|
+
checkpointedBlockData: Pick<BlockData, 'checkpointNumber'>,
|
|
110
|
+
): Promise<CheckpointId> {
|
|
111
|
+
const checkpointData = await this.blockStore.getLastProposedCheckpoint();
|
|
112
|
+
if (!checkpointData) {
|
|
113
|
+
return this.getCheckpointIdForBlock(checkpointedBlockData);
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
number: checkpointData.checkpointNumber,
|
|
117
|
+
hash: checkpointData.header.hash().toString(),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
76
121
|
private async getCheckpointIdForBlock(blockData: Pick<BlockData, 'checkpointNumber'>): Promise<CheckpointId> {
|
|
77
122
|
const checkpointData = await this.blockStore.getCheckpointData(blockData.checkpointNumber);
|
|
78
123
|
if (!checkpointData) {
|