@aztec/archiver 0.0.1-commit.7035c9bd6 → 0.0.1-commit.71324e566
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 +6 -4
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +32 -14
- package/dest/config.js +1 -1
- package/dest/errors.d.ts +14 -2
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +18 -2
- package/dest/factory.d.ts +2 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +7 -6
- package/dest/l1/calldata_retriever.d.ts +1 -1
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +2 -1
- package/dest/l1/data_retrieval.d.ts +3 -3
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +14 -15
- package/dest/modules/data_source_base.d.ts +4 -2
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +6 -0
- package/dest/modules/data_store_updater.d.ts +5 -7
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +56 -65
- package/dest/modules/instrumentation.d.ts +4 -2
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +17 -6
- package/dest/modules/l1_synchronizer.d.ts +3 -2
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +131 -124
- package/dest/modules/validation.d.ts +1 -1
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +2 -2
- package/dest/store/block_store.d.ts +39 -4
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +232 -63
- 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 +26 -16
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +29 -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 +9 -1
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +41 -6
- 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 +7 -2
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +28 -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 +0 -1
- package/package.json +13 -13
- package/src/archiver.ts +43 -19
- package/src/config.ts +1 -1
- package/src/errors.ts +30 -2
- package/src/factory.ts +12 -7
- package/src/l1/calldata_retriever.ts +2 -1
- package/src/l1/data_retrieval.ts +8 -12
- package/src/modules/data_source_base.ts +15 -1
- package/src/modules/data_store_updater.ts +68 -95
- package/src/modules/instrumentation.ts +19 -7
- package/src/modules/l1_synchronizer.ts +145 -151
- package/src/modules/validation.ts +2 -2
- package/src/store/block_store.ts +301 -74
- 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 +48 -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 +56 -7
- package/src/test/mock_l1_to_l2_message_source.ts +1 -0
- package/src/test/mock_l2_block_source.ts +37 -2
- package/src/test/noop_l1_archiver.ts +0 -1
|
@@ -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
|
|
|
@@ -13,14 +13,19 @@ import {
|
|
|
13
13
|
L2Block,
|
|
14
14
|
type ValidateCheckpointResult,
|
|
15
15
|
} from '@aztec/stdlib/block';
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
CheckpointData,
|
|
18
|
+
CommonCheckpointData,
|
|
19
|
+
ProposedCheckpointData,
|
|
20
|
+
ProposedCheckpointInput,
|
|
21
|
+
PublishedCheckpoint,
|
|
22
|
+
} from '@aztec/stdlib/checkpoint';
|
|
17
23
|
import type {
|
|
18
24
|
ContractClassPublic,
|
|
25
|
+
ContractClassPublicWithCommitment,
|
|
19
26
|
ContractDataSource,
|
|
20
27
|
ContractInstanceUpdateWithAddress,
|
|
21
28
|
ContractInstanceWithAddress,
|
|
22
|
-
ExecutablePrivateFunctionWithMembershipProof,
|
|
23
|
-
UtilityFunctionWithMembershipProof,
|
|
24
29
|
} from '@aztec/stdlib/contract';
|
|
25
30
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
26
31
|
import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
|
|
@@ -37,7 +42,7 @@ import { ContractInstanceStore } from './contract_instance_store.js';
|
|
|
37
42
|
import { LogStore } from './log_store.js';
|
|
38
43
|
import { MessageStore } from './message_store.js';
|
|
39
44
|
|
|
40
|
-
export const ARCHIVER_DB_VERSION =
|
|
45
|
+
export const ARCHIVER_DB_VERSION = 6;
|
|
41
46
|
export const MAX_FUNCTION_SIGNATURES = 1000;
|
|
42
47
|
export const MAX_FUNCTION_NAME_LEN = 256;
|
|
43
48
|
|
|
@@ -167,19 +172,14 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
167
172
|
|
|
168
173
|
/**
|
|
169
174
|
* 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.
|
|
175
|
+
* @param data - List of contract classes (with bytecode commitments) to be added.
|
|
172
176
|
* @param blockNumber - Number of the L2 block the contracts were registered in.
|
|
173
177
|
* @returns True if the operation is successful.
|
|
174
178
|
*/
|
|
175
|
-
async addContractClasses(
|
|
176
|
-
data: ContractClassPublic[],
|
|
177
|
-
bytecodeCommitments: Fr[],
|
|
178
|
-
blockNumber: BlockNumber,
|
|
179
|
-
): Promise<boolean> {
|
|
179
|
+
async addContractClasses(data: ContractClassPublicWithCommitment[], blockNumber: BlockNumber): Promise<boolean> {
|
|
180
180
|
return (
|
|
181
181
|
await Promise.all(
|
|
182
|
-
data.map(
|
|
182
|
+
data.map(c => this.#contractClassStore.addContractClass(c, c.publicBytecodeCommitment, blockNumber)),
|
|
183
183
|
)
|
|
184
184
|
).every(Boolean);
|
|
185
185
|
}
|
|
@@ -194,15 +194,6 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
194
194
|
return this.#contractClassStore.getBytecodeCommitment(contractClassId);
|
|
195
195
|
}
|
|
196
196
|
|
|
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
197
|
/**
|
|
207
198
|
* Add new contract instances from an L2 block to the store's list.
|
|
208
199
|
* @param data - List of contract instances to be added.
|
|
@@ -269,7 +260,7 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
269
260
|
* @returns The number of the latest block
|
|
270
261
|
*/
|
|
271
262
|
getLatestBlockNumber(): Promise<BlockNumber> {
|
|
272
|
-
return this.#blockStore.
|
|
263
|
+
return this.#blockStore.getLatestL2BlockNumber();
|
|
273
264
|
}
|
|
274
265
|
|
|
275
266
|
/**
|
|
@@ -567,13 +558,6 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
567
558
|
await this.#blockStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
568
559
|
}
|
|
569
560
|
|
|
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
561
|
/**
|
|
578
562
|
* Returns the number of the most recent proven block
|
|
579
563
|
* @returns The number of the most recent proven block
|
|
@@ -606,9 +590,9 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
606
590
|
return this.#messageStore.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
|
|
607
591
|
}
|
|
608
592
|
|
|
609
|
-
/**
|
|
610
|
-
public
|
|
611
|
-
return this.#messageStore.
|
|
593
|
+
/** Atomically updates the message sync state: the L1 sync point and the inbox tree-in-progress marker. */
|
|
594
|
+
public setMessageSyncState(l1Block: L1BlockId, treeInProgress: bigint | undefined): Promise<void> {
|
|
595
|
+
return this.#messageStore.setMessageSyncState(l1Block, treeInProgress);
|
|
612
596
|
}
|
|
613
597
|
|
|
614
598
|
/** Returns an async iterator to all L1 to L2 messages on the range. */
|
|
@@ -631,6 +615,38 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
631
615
|
return this.#blockStore.setPendingChainValidationStatus(status);
|
|
632
616
|
}
|
|
633
617
|
|
|
618
|
+
/**
|
|
619
|
+
* Gets the L2 block number of the proposed checkpoint.
|
|
620
|
+
* @returns The block number of the proposed checkpoint, or the checkpointed block number if none.
|
|
621
|
+
*/
|
|
622
|
+
public getProposedCheckpointL2BlockNumber(): Promise<BlockNumber> {
|
|
623
|
+
return this.#blockStore.getProposedCheckpointL2BlockNumber();
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/** Returns the checkpoint data at the proposed tip */
|
|
627
|
+
public getProposedCheckpoint(): Promise<CommonCheckpointData | undefined> {
|
|
628
|
+
return this.#blockStore.getProposedCheckpoint();
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/** Returns the proposed checkpoint data, or undefined if no proposed checkpoint exists. No fallback to confirmed. */
|
|
632
|
+
public getProposedCheckpointOnly(): Promise<ProposedCheckpointData | undefined> {
|
|
633
|
+
return this.#blockStore.getProposedCheckpointOnly();
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Set proposed checkpoint
|
|
638
|
+
* @param proposedCheckpoint
|
|
639
|
+
* @returns
|
|
640
|
+
*/
|
|
641
|
+
public setProposedCheckpoint(proposedCheckpoint: ProposedCheckpointInput): Promise<void> {
|
|
642
|
+
return this.#blockStore.setProposedCheckpoint(proposedCheckpoint);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/** Deletes the proposed checkpoint from storage. */
|
|
646
|
+
public deleteProposedCheckpoint(): Promise<void> {
|
|
647
|
+
return this.#blockStore.deleteProposedCheckpoint();
|
|
648
|
+
}
|
|
649
|
+
|
|
634
650
|
/**
|
|
635
651
|
* Gets the number of the latest L2 block processed.
|
|
636
652
|
* @returns The number of the latest L2 block processed.
|
|
@@ -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.getProposedCheckpointOnly();
|
|
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[]> {
|
|
@@ -332,6 +332,21 @@ export class FakeL1State {
|
|
|
332
332
|
this.updatePendingCheckpointNumber();
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Moves a checkpoint to a different L1 block number (simulates L1 reorg that
|
|
337
|
+
* re-includes the same checkpoint transaction in a different block).
|
|
338
|
+
* The checkpoint content stays the same — only the L1 metadata changes.
|
|
339
|
+
* Auto-updates pending status.
|
|
340
|
+
*/
|
|
341
|
+
moveCheckpointToL1Block(checkpointNumber: CheckpointNumber, newL1BlockNumber: bigint): void {
|
|
342
|
+
for (const cpData of this.checkpoints) {
|
|
343
|
+
if (cpData.checkpointNumber === checkpointNumber) {
|
|
344
|
+
cpData.l1BlockNumber = newL1BlockNumber;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
this.updatePendingCheckpointNumber();
|
|
348
|
+
}
|
|
349
|
+
|
|
335
350
|
/**
|
|
336
351
|
* Removes messages after a given total index (simulates L1 reorg).
|
|
337
352
|
* Auto-updates rolling hash.
|
|
@@ -451,19 +466,33 @@ export class FakeL1State {
|
|
|
451
466
|
createMockInboxContract(_publicClient: MockProxy<ViemPublicClient>): MockProxy<InboxContract> {
|
|
452
467
|
const mockInbox = mock<InboxContract>();
|
|
453
468
|
|
|
454
|
-
mockInbox.getState.mockImplementation(() => {
|
|
469
|
+
mockInbox.getState.mockImplementation((opts: { blockTag?: string; blockNumber?: bigint } = {}) => {
|
|
470
|
+
// Filter messages visible at the given block number (or all if not specified)
|
|
471
|
+
const blockNumber = opts.blockNumber ?? this.l1BlockNumber;
|
|
472
|
+
const visibleMessages = this.messages.filter(m => m.l1BlockNumber <= blockNumber);
|
|
473
|
+
|
|
455
474
|
// treeInProgress must be > any sealed checkpoint. On L1, a checkpoint can only be proposed
|
|
456
475
|
// after its messages are sealed, so treeInProgress > checkpointNumber for all published checkpoints.
|
|
457
476
|
const maxFromMessages =
|
|
458
|
-
|
|
477
|
+
visibleMessages.length > 0 ? Math.max(...visibleMessages.map(m => Number(m.checkpointNumber))) + 1 : 0;
|
|
459
478
|
const maxFromCheckpoints =
|
|
460
479
|
this.checkpoints.length > 0
|
|
461
|
-
? Math.max(
|
|
480
|
+
? Math.max(
|
|
481
|
+
...this.checkpoints
|
|
482
|
+
.filter(cp => !cp.pruned && cp.l1BlockNumber <= blockNumber)
|
|
483
|
+
.map(cp => Number(cp.checkpointNumber)),
|
|
484
|
+
0,
|
|
485
|
+
) + 1
|
|
462
486
|
: 0;
|
|
463
487
|
const treeInProgress = Math.max(maxFromMessages, maxFromCheckpoints, INITIAL_CHECKPOINT_NUMBER);
|
|
488
|
+
|
|
489
|
+
// Compute rolling hash only for visible messages
|
|
490
|
+
const rollingHash =
|
|
491
|
+
visibleMessages.length > 0 ? visibleMessages[visibleMessages.length - 1].rollingHash : Buffer16.ZERO;
|
|
492
|
+
|
|
464
493
|
return Promise.resolve({
|
|
465
|
-
messagesRollingHash:
|
|
466
|
-
totalMessagesInserted: BigInt(
|
|
494
|
+
messagesRollingHash: rollingHash,
|
|
495
|
+
totalMessagesInserted: BigInt(visibleMessages.length),
|
|
467
496
|
treeInProgress: BigInt(treeInProgress),
|
|
468
497
|
});
|
|
469
498
|
});
|
|
@@ -473,8 +502,8 @@ export class FakeL1State {
|
|
|
473
502
|
Promise.resolve(this.getMessageSentLogs(fromBlock, toBlock)),
|
|
474
503
|
);
|
|
475
504
|
|
|
476
|
-
mockInbox.getMessageSentEventByHash.mockImplementation((
|
|
477
|
-
Promise.resolve(this.
|
|
505
|
+
mockInbox.getMessageSentEventByHash.mockImplementation((msgHash: string, l1BlockHash: string) =>
|
|
506
|
+
Promise.resolve(this.getMessageSentLogByHash(msgHash, l1BlockHash) as MessageSentLog),
|
|
478
507
|
);
|
|
479
508
|
|
|
480
509
|
return mockInbox;
|
|
@@ -594,6 +623,26 @@ export class FakeL1State {
|
|
|
594
623
|
}));
|
|
595
624
|
}
|
|
596
625
|
|
|
626
|
+
private getMessageSentLogByHash(msgHash: string, l1BlockHash: string): MessageSentLog | undefined {
|
|
627
|
+
const msg = this.messages.find(
|
|
628
|
+
msg => msg.leaf.toString() === msgHash && Buffer32.fromBigInt(msg.l1BlockNumber).toString() === l1BlockHash,
|
|
629
|
+
);
|
|
630
|
+
if (!msg) {
|
|
631
|
+
return undefined;
|
|
632
|
+
}
|
|
633
|
+
return {
|
|
634
|
+
l1BlockNumber: msg.l1BlockNumber,
|
|
635
|
+
l1BlockHash: Buffer32.fromBigInt(msg.l1BlockNumber),
|
|
636
|
+
l1TransactionHash: `0x${msg.l1BlockNumber.toString(16)}` as `0x${string}`,
|
|
637
|
+
args: {
|
|
638
|
+
checkpointNumber: msg.checkpointNumber,
|
|
639
|
+
index: msg.index,
|
|
640
|
+
leaf: msg.leaf,
|
|
641
|
+
rollingHash: msg.rollingHash,
|
|
642
|
+
},
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
|
|
597
646
|
private async makeRollupTx(
|
|
598
647
|
checkpoint: Checkpoint,
|
|
599
648
|
signers: Secp256k1Signer[],
|
|
@@ -16,7 +16,13 @@ import {
|
|
|
16
16
|
type L2Tips,
|
|
17
17
|
type ValidateCheckpointResult,
|
|
18
18
|
} from '@aztec/stdlib/block';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
Checkpoint,
|
|
21
|
+
type CheckpointData,
|
|
22
|
+
L1PublishedData,
|
|
23
|
+
type ProposedCheckpointData,
|
|
24
|
+
PublishedCheckpoint,
|
|
25
|
+
} from '@aztec/stdlib/checkpoint';
|
|
20
26
|
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
21
27
|
import {
|
|
22
28
|
EmptyL1RollupConstants,
|
|
@@ -39,6 +45,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
39
45
|
private provenBlockNumber: number = 0;
|
|
40
46
|
private finalizedBlockNumber: number = 0;
|
|
41
47
|
private checkpointedBlockNumber: number = 0;
|
|
48
|
+
private proposedCheckpointBlockNumber: number = 0;
|
|
42
49
|
|
|
43
50
|
private log = createLogger('archiver:mock_l2_block_source');
|
|
44
51
|
|
|
@@ -89,6 +96,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
89
96
|
});
|
|
90
97
|
// Keep tip numbers consistent with remaining blocks.
|
|
91
98
|
this.checkpointedBlockNumber = Math.min(this.checkpointedBlockNumber, maxBlockNum);
|
|
99
|
+
this.proposedCheckpointBlockNumber = Math.min(this.proposedCheckpointBlockNumber, maxBlockNum);
|
|
92
100
|
this.provenBlockNumber = Math.min(this.provenBlockNumber, maxBlockNum);
|
|
93
101
|
this.finalizedBlockNumber = Math.min(this.finalizedBlockNumber, maxBlockNum);
|
|
94
102
|
this.log.verbose(`Removed ${numBlocks} blocks from the mock L2 block source`);
|
|
@@ -105,9 +113,17 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
105
113
|
this.finalizedBlockNumber = finalizedBlockNumber;
|
|
106
114
|
}
|
|
107
115
|
|
|
116
|
+
public setProposedCheckpointBlockNumber(blockNumber: number) {
|
|
117
|
+
this.proposedCheckpointBlockNumber = blockNumber;
|
|
118
|
+
}
|
|
119
|
+
|
|
108
120
|
public setCheckpointedBlockNumber(checkpointedBlockNumber: number) {
|
|
109
121
|
const prevCheckpointed = this.checkpointedBlockNumber;
|
|
110
122
|
this.checkpointedBlockNumber = checkpointedBlockNumber;
|
|
123
|
+
// Proposed checkpoint is always at least as advanced as checkpointed
|
|
124
|
+
if (this.proposedCheckpointBlockNumber < checkpointedBlockNumber) {
|
|
125
|
+
this.proposedCheckpointBlockNumber = checkpointedBlockNumber;
|
|
126
|
+
}
|
|
111
127
|
// Auto-create single-block checkpoints for newly checkpointed blocks that don't have one yet.
|
|
112
128
|
// This handles blocks added via addProposedBlocks that are now being marked as checkpointed.
|
|
113
129
|
const newCheckpoints: Checkpoint[] = [];
|
|
@@ -171,6 +187,10 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
171
187
|
return Promise.resolve(BlockNumber(this.finalizedBlockNumber));
|
|
172
188
|
}
|
|
173
189
|
|
|
190
|
+
public getProposedCheckpointL2BlockNumber() {
|
|
191
|
+
return Promise.resolve(BlockNumber(this.proposedCheckpointBlockNumber));
|
|
192
|
+
}
|
|
193
|
+
|
|
174
194
|
public getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
|
|
175
195
|
if (number > this.checkpointedBlockNumber) {
|
|
176
196
|
return Promise.resolve(undefined);
|
|
@@ -408,17 +428,19 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
408
428
|
}
|
|
409
429
|
|
|
410
430
|
async getL2Tips(): Promise<L2Tips> {
|
|
411
|
-
const [latest, proven, finalized, checkpointed] = [
|
|
431
|
+
const [latest, proven, finalized, checkpointed, proposedCheckpoint] = [
|
|
412
432
|
await this.getBlockNumber(),
|
|
413
433
|
await this.getProvenBlockNumber(),
|
|
414
434
|
this.finalizedBlockNumber,
|
|
415
435
|
this.checkpointedBlockNumber,
|
|
436
|
+
await this.getProposedCheckpointL2BlockNumber(),
|
|
416
437
|
] as const;
|
|
417
438
|
|
|
418
439
|
const latestBlock = this.l2Blocks[latest - 1];
|
|
419
440
|
const provenBlock = this.l2Blocks[proven - 1];
|
|
420
441
|
const finalizedBlock = this.l2Blocks[finalized - 1];
|
|
421
442
|
const checkpointedBlock = this.l2Blocks[checkpointed - 1];
|
|
443
|
+
const proposedCheckpointBlock = this.l2Blocks[proposedCheckpoint - 1];
|
|
422
444
|
|
|
423
445
|
const latestBlockId = {
|
|
424
446
|
number: BlockNumber(latest),
|
|
@@ -436,6 +458,10 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
436
458
|
number: BlockNumber(checkpointed),
|
|
437
459
|
hash: (await checkpointedBlock?.hash())?.toString(),
|
|
438
460
|
};
|
|
461
|
+
const proposedCheckpointBlockId = {
|
|
462
|
+
number: BlockNumber(proposedCheckpoint),
|
|
463
|
+
hash: (await proposedCheckpointBlock?.hash())?.toString(),
|
|
464
|
+
};
|
|
439
465
|
|
|
440
466
|
const makeTipId = (blockId: typeof latestBlockId) => ({
|
|
441
467
|
block: blockId,
|
|
@@ -450,6 +476,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
450
476
|
checkpointed: makeTipId(checkpointedBlockId),
|
|
451
477
|
proven: makeTipId(provenBlockId),
|
|
452
478
|
finalized: makeTipId(finalizedBlockId),
|
|
479
|
+
proposedCheckpoint: makeTipId(proposedCheckpointBlockId),
|
|
453
480
|
};
|
|
454
481
|
}
|
|
455
482
|
|
|
@@ -531,6 +558,14 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
531
558
|
return Promise.resolve({ valid: true });
|
|
532
559
|
}
|
|
533
560
|
|
|
561
|
+
getProposedCheckpoint(): Promise<ProposedCheckpointData | undefined> {
|
|
562
|
+
return Promise.resolve(undefined);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
getProposedCheckpointOnly(): Promise<ProposedCheckpointData | undefined> {
|
|
566
|
+
return Promise.resolve(undefined);
|
|
567
|
+
}
|
|
568
|
+
|
|
534
569
|
/** Returns checkpoints whose slot falls within the given epoch. */
|
|
535
570
|
private getCheckpointsInEpoch(epochNumber: EpochNumber): Checkpoint[] {
|
|
536
571
|
const epochDuration = DefaultL1ContractsConfig.aztecEpochDuration;
|