@aztec/archiver 0.0.1-commit.5de5ca79e → 0.0.1-commit.6201a7b05
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 +16 -7
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +104 -48
- package/dest/config.d.ts +3 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +14 -3
- package/dest/errors.d.ts +41 -2
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +62 -1
- package/dest/factory.d.ts +2 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +9 -7
- 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 +19 -10
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +25 -32
- 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 +8 -2
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +19 -1
- package/dest/modules/data_store_updater.d.ts +15 -10
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +71 -68
- 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 +7 -2
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +261 -143
- 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 +72 -5
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +341 -66
- 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 +51 -17
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +60 -16
- 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 +1 -1
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +2 -4
- package/dest/store/message_store.d.ts +3 -3
- package/dest/store/message_store.d.ts.map +1 -1
- package/dest/store/message_store.js +9 -10
- package/dest/test/fake_l1_state.d.ts +15 -3
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +80 -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 +16 -2
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +50 -3
- package/dest/test/noop_l1_archiver.d.ts +1 -1
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +4 -2
- package/package.json +13 -13
- package/src/archiver.ts +126 -46
- package/src/config.ts +15 -1
- package/src/errors.ts +97 -2
- package/src/factory.ts +13 -7
- package/src/index.ts +2 -1
- package/src/l1/calldata_retriever.ts +17 -5
- package/src/l1/data_retrieval.ts +36 -45
- package/src/l1/validate_historical_logs.ts +140 -0
- package/src/modules/data_source_base.ts +32 -1
- package/src/modules/data_store_updater.ts +98 -97
- package/src/modules/instrumentation.ts +27 -7
- package/src/modules/l1_synchronizer.ts +328 -169
- package/src/modules/validation.ts +10 -9
- package/src/store/block_store.ts +419 -76
- 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 +100 -32
- package/src/store/l2_tips_cache.ts +58 -13
- package/src/store/log_store.ts +2 -5
- package/src/store/message_store.ts +10 -12
- package/src/structs/inbox_message.ts +1 -1
- package/src/test/fake_l1_state.ts +99 -27
- package/src/test/mock_l1_to_l2_message_source.ts +1 -0
- package/src/test/mock_l2_block_source.ts +58 -2
- package/src/test/noop_l1_archiver.ts +3 -1
|
@@ -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
|
|
|
@@ -167,19 +174,14 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
167
174
|
|
|
168
175
|
/**
|
|
169
176
|
* Add new contract classes from an L2 block to the store's list.
|
|
170
|
-
* @param data - List of contract classes to be added.
|
|
171
|
-
* @param bytecodeCommitments - Bytecode commitments for the contract classes.
|
|
177
|
+
* @param data - List of contract classes (with bytecode commitments) to be added.
|
|
172
178
|
* @param blockNumber - Number of the L2 block the contracts were registered in.
|
|
173
179
|
* @returns True if the operation is successful.
|
|
174
180
|
*/
|
|
175
|
-
async addContractClasses(
|
|
176
|
-
data: ContractClassPublic[],
|
|
177
|
-
bytecodeCommitments: Fr[],
|
|
178
|
-
blockNumber: BlockNumber,
|
|
179
|
-
): Promise<boolean> {
|
|
181
|
+
async addContractClasses(data: ContractClassPublicWithCommitment[], blockNumber: BlockNumber): Promise<boolean> {
|
|
180
182
|
return (
|
|
181
183
|
await Promise.all(
|
|
182
|
-
data.map(
|
|
184
|
+
data.map(c => this.#contractClassStore.addContractClass(c, c.publicBytecodeCommitment, blockNumber)),
|
|
183
185
|
)
|
|
184
186
|
).every(Boolean);
|
|
185
187
|
}
|
|
@@ -194,15 +196,6 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
194
196
|
return this.#contractClassStore.getBytecodeCommitment(contractClassId);
|
|
195
197
|
}
|
|
196
198
|
|
|
197
|
-
/** Adds private functions to a contract class. */
|
|
198
|
-
addFunctions(
|
|
199
|
-
contractClassId: Fr,
|
|
200
|
-
privateFunctions: ExecutablePrivateFunctionWithMembershipProof[],
|
|
201
|
-
utilityFunctions: UtilityFunctionWithMembershipProof[],
|
|
202
|
-
): Promise<boolean> {
|
|
203
|
-
return this.#contractClassStore.addFunctions(contractClassId, privateFunctions, utilityFunctions);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
199
|
/**
|
|
207
200
|
* Add new contract instances from an L2 block to the store's list.
|
|
208
201
|
* @param data - List of contract instances to be added.
|
|
@@ -269,7 +262,7 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
269
262
|
* @returns The number of the latest block
|
|
270
263
|
*/
|
|
271
264
|
getLatestBlockNumber(): Promise<BlockNumber> {
|
|
272
|
-
return this.#blockStore.
|
|
265
|
+
return this.#blockStore.getLatestL2BlockNumber();
|
|
273
266
|
}
|
|
274
267
|
|
|
275
268
|
/**
|
|
@@ -567,13 +560,6 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
567
560
|
await this.#blockStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
568
561
|
}
|
|
569
562
|
|
|
570
|
-
/**
|
|
571
|
-
* Stores the l1 block that messages have been synched until
|
|
572
|
-
*/
|
|
573
|
-
async setMessageSynchedL1Block(l1Block: L1BlockId) {
|
|
574
|
-
await this.#messageStore.setSynchedL1Block(l1Block);
|
|
575
|
-
}
|
|
576
|
-
|
|
577
563
|
/**
|
|
578
564
|
* Returns the number of the most recent proven block
|
|
579
565
|
* @returns The number of the most recent proven block
|
|
@@ -606,9 +592,9 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
606
592
|
return this.#messageStore.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
|
|
607
593
|
}
|
|
608
594
|
|
|
609
|
-
/**
|
|
610
|
-
public
|
|
611
|
-
return this.#messageStore.
|
|
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);
|
|
612
598
|
}
|
|
613
599
|
|
|
614
600
|
/** Returns an async iterator to all L1 to L2 messages on the range. */
|
|
@@ -631,6 +617,73 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
631
617
|
return this.#blockStore.setPendingChainValidationStatus(status);
|
|
632
618
|
}
|
|
633
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
|
+
|
|
634
687
|
/**
|
|
635
688
|
* Gets the number of the latest L2 block processed.
|
|
636
689
|
* @returns The number of the latest L2 block processed.
|
|
@@ -676,6 +729,21 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
676
729
|
return this.#blockStore.getCheckpointDataForSlotRange(startSlot, endSlot);
|
|
677
730
|
}
|
|
678
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
|
+
|
|
679
747
|
/**
|
|
680
748
|
* Gets all blocks that have the given slot number.
|
|
681
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) {
|
package/src/store/log_store.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
2
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { compactArray, filterAsync } from '@aztec/foundation/collection';
|
|
4
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
5
|
import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
|
|
7
6
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
@@ -302,13 +301,11 @@ export class LogStore {
|
|
|
302
301
|
}
|
|
303
302
|
|
|
304
303
|
#unpackBlockHash(reader: BufferReader): BlockHash {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (!blockHash) {
|
|
304
|
+
if (reader.remainingBytes() === 0) {
|
|
308
305
|
throw new Error('Failed to read block hash from log entry buffer');
|
|
309
306
|
}
|
|
310
307
|
|
|
311
|
-
return
|
|
308
|
+
return BlockHash.fromBuffer(reader);
|
|
312
309
|
}
|
|
313
310
|
|
|
314
311
|
deleteLogs(blocks: L2Block[]): Promise<boolean> {
|
|
@@ -161,15 +161,6 @@ export class MessageStore {
|
|
|
161
161
|
lastMessage = message;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
// Update the L1 sync point to that of the last message added.
|
|
165
|
-
const currentSyncPoint = await this.getSynchedL1Block();
|
|
166
|
-
if (!currentSyncPoint || currentSyncPoint.l1BlockNumber < lastMessage!.l1BlockNumber) {
|
|
167
|
-
await this.setSynchedL1Block({
|
|
168
|
-
l1BlockNumber: lastMessage!.l1BlockNumber,
|
|
169
|
-
l1BlockHash: lastMessage!.l1BlockHash,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
164
|
// Update total message count with the number of inserted messages.
|
|
174
165
|
await this.increaseTotalMessageCount(messageCount);
|
|
175
166
|
});
|
|
@@ -194,9 +185,16 @@ export class MessageStore {
|
|
|
194
185
|
return this.#inboxTreeInProgress.getAsync();
|
|
195
186
|
}
|
|
196
187
|
|
|
197
|
-
/**
|
|
198
|
-
public
|
|
199
|
-
|
|
188
|
+
/** Atomically updates the message sync state: the L1 sync point and the inbox tree-in-progress marker. */
|
|
189
|
+
public setMessageSyncState(l1Block: L1BlockId, treeInProgress: bigint | undefined): Promise<void> {
|
|
190
|
+
return this.db.transactionAsync(async () => {
|
|
191
|
+
await this.setSynchedL1Block(l1Block);
|
|
192
|
+
if (treeInProgress !== undefined) {
|
|
193
|
+
await this.#inboxTreeInProgress.set(treeInProgress);
|
|
194
|
+
} else {
|
|
195
|
+
await this.#inboxTreeInProgress.delete();
|
|
196
|
+
}
|
|
197
|
+
});
|
|
200
198
|
}
|
|
201
199
|
|
|
202
200
|
public async getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|