@aztec/archiver 0.0.1-commit.d431d1c → 0.0.1-commit.d939eb5aa
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 +21 -6
- package/dest/archiver.d.ts +17 -12
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +108 -127
- package/dest/config.d.ts +3 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +3 -2
- package/dest/errors.d.ts +39 -10
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +52 -15
- package/dest/factory.d.ts +4 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +29 -23
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/l1/bin/retrieve-calldata.js +35 -32
- package/dest/l1/calldata_retriever.d.ts +73 -50
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +191 -259
- package/dest/l1/data_retrieval.d.ts +11 -11
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +38 -37
- package/dest/l1/spire_proposer.d.ts +5 -5
- package/dest/l1/spire_proposer.d.ts.map +1 -1
- package/dest/l1/spire_proposer.js +9 -17
- package/dest/l1/validate_trace.d.ts +6 -3
- package/dest/l1/validate_trace.d.ts.map +1 -1
- package/dest/l1/validate_trace.js +13 -9
- package/dest/modules/data_source_base.d.ts +29 -23
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +55 -124
- package/dest/modules/data_store_updater.d.ts +43 -26
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +158 -129
- package/dest/modules/instrumentation.d.ts +19 -4
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +53 -18
- package/dest/modules/l1_synchronizer.d.ts +7 -9
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +186 -145
- 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 +86 -34
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +414 -152
- 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 +16 -72
- 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 +80 -39
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +86 -35
- package/dest/store/l2_tips_cache.d.ts +20 -0
- package/dest/store/l2_tips_cache.d.ts.map +1 -0
- package/dest/store/l2_tips_cache.js +109 -0
- package/dest/store/log_store.d.ts +9 -6
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +151 -56
- 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 +24 -4
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +133 -26
- package/dest/test/index.js +3 -1
- package/dest/test/mock_archiver.d.ts +1 -1
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +3 -2
- 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 +44 -23
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +185 -115
- package/dest/test/mock_structs.d.ts +6 -2
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +24 -10
- package/dest/test/noop_l1_archiver.d.ts +26 -0
- package/dest/test/noop_l1_archiver.d.ts.map +1 -0
- package/dest/test/noop_l1_archiver.js +71 -0
- package/package.json +14 -13
- package/src/archiver.ts +144 -159
- package/src/config.ts +9 -2
- package/src/errors.ts +82 -26
- package/src/factory.ts +46 -22
- package/src/index.ts +1 -0
- package/src/l1/README.md +25 -68
- package/src/l1/bin/retrieve-calldata.ts +45 -33
- package/src/l1/calldata_retriever.ts +250 -379
- package/src/l1/data_retrieval.ts +35 -41
- package/src/l1/spire_proposer.ts +7 -15
- package/src/l1/validate_trace.ts +24 -6
- package/src/modules/data_source_base.ts +98 -169
- package/src/modules/data_store_updater.ts +178 -160
- package/src/modules/instrumentation.ts +64 -20
- package/src/modules/l1_synchronizer.ts +212 -182
- package/src/modules/validation.ts +2 -2
- package/src/store/block_store.ts +533 -207
- package/src/store/contract_class_store.ts +16 -110
- package/src/store/contract_instance_store.ts +8 -5
- package/src/store/kv_archiver_store.ts +141 -59
- package/src/store/l2_tips_cache.ts +134 -0
- package/src/store/log_store.ts +232 -74
- package/src/store/message_store.ts +27 -10
- package/src/structs/inbox_message.ts +1 -1
- package/src/test/fake_l1_state.ts +180 -32
- package/src/test/index.ts +3 -0
- package/src/test/mock_archiver.ts +3 -2
- package/src/test/mock_l1_to_l2_message_source.ts +1 -0
- package/src/test/mock_l2_block_source.ts +247 -130
- package/src/test/mock_structs.ts +45 -15
- package/src/test/noop_l1_archiver.ts +114 -0
|
@@ -8,48 +8,97 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
8
8
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
9
9
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
10
10
|
import {
|
|
11
|
+
type BlockData,
|
|
12
|
+
BlockHash,
|
|
11
13
|
CheckpointedL2Block,
|
|
12
|
-
|
|
13
|
-
L2BlockNew,
|
|
14
|
+
L2Block,
|
|
14
15
|
type L2BlockSource,
|
|
15
16
|
type L2Tips,
|
|
16
17
|
type ValidateCheckpointResult,
|
|
17
18
|
} from '@aztec/stdlib/block';
|
|
18
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
Checkpoint,
|
|
21
|
+
type CheckpointData,
|
|
22
|
+
L1PublishedData,
|
|
23
|
+
type ProposedCheckpointData,
|
|
24
|
+
PublishedCheckpoint,
|
|
25
|
+
} from '@aztec/stdlib/checkpoint';
|
|
19
26
|
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
20
|
-
import {
|
|
21
|
-
|
|
27
|
+
import {
|
|
28
|
+
EmptyL1RollupConstants,
|
|
29
|
+
type L1RollupConstants,
|
|
30
|
+
getEpochAtSlot,
|
|
31
|
+
getSlotRangeForEpoch,
|
|
32
|
+
} from '@aztec/stdlib/epoch-helpers';
|
|
33
|
+
import { computeCheckpointOutHash } from '@aztec/stdlib/messaging';
|
|
34
|
+
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
35
|
+
import { type BlockHeader, TxExecutionResult, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
|
|
22
36
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
23
37
|
|
|
24
38
|
/**
|
|
25
39
|
* A mocked implementation of L2BlockSource to be used in tests.
|
|
26
40
|
*/
|
|
27
41
|
export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
28
|
-
protected l2Blocks:
|
|
42
|
+
protected l2Blocks: L2Block[] = [];
|
|
43
|
+
protected checkpointList: Checkpoint[] = [];
|
|
29
44
|
|
|
30
45
|
private provenBlockNumber: number = 0;
|
|
31
46
|
private finalizedBlockNumber: number = 0;
|
|
32
47
|
private checkpointedBlockNumber: number = 0;
|
|
48
|
+
private proposedCheckpointBlockNumber: number = 0;
|
|
33
49
|
|
|
34
50
|
private log = createLogger('archiver:mock_l2_block_source');
|
|
35
51
|
|
|
52
|
+
/** Creates blocks grouped into single-block checkpoints. */
|
|
36
53
|
public async createBlocks(numBlocks: number) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
54
|
+
await this.createCheckpoints(numBlocks, 1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public getCheckpointNumber(): Promise<CheckpointNumber> {
|
|
58
|
+
return Promise.resolve(
|
|
59
|
+
this.checkpointList.length === 0 ? CheckpointNumber.ZERO : CheckpointNumber(this.checkpointList.length),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Creates checkpoints, each containing `blocksPerCheckpoint` blocks. */
|
|
64
|
+
public async createCheckpoints(numCheckpoints: number, blocksPerCheckpoint: number = 1) {
|
|
65
|
+
for (let c = 0; c < numCheckpoints; c++) {
|
|
66
|
+
const checkpointNum = CheckpointNumber(this.checkpointList.length + 1);
|
|
67
|
+
const startBlockNum = this.l2Blocks.length + 1;
|
|
68
|
+
const slotNumber = SlotNumber(Number(checkpointNum));
|
|
69
|
+
const checkpoint = await Checkpoint.random(checkpointNum, {
|
|
70
|
+
numBlocks: blocksPerCheckpoint,
|
|
71
|
+
startBlockNumber: startBlockNum,
|
|
72
|
+
slotNumber,
|
|
73
|
+
checkpointNumber: checkpointNum,
|
|
74
|
+
});
|
|
75
|
+
this.checkpointList.push(checkpoint);
|
|
76
|
+
this.l2Blocks.push(...checkpoint.blocks);
|
|
41
77
|
}
|
|
42
78
|
|
|
43
|
-
this.log.verbose(
|
|
79
|
+
this.log.verbose(
|
|
80
|
+
`Created ${numCheckpoints} checkpoints with ${blocksPerCheckpoint} blocks each in the mock L2 block source`,
|
|
81
|
+
);
|
|
44
82
|
}
|
|
45
83
|
|
|
46
|
-
public
|
|
84
|
+
public addProposedBlocks(blocks: L2Block[]) {
|
|
47
85
|
this.l2Blocks.push(...blocks);
|
|
48
|
-
this.log.verbose(`Added ${blocks.length} blocks to the mock L2 block source`);
|
|
86
|
+
this.log.verbose(`Added ${blocks.length} proposed blocks to the mock L2 block source`);
|
|
49
87
|
}
|
|
50
88
|
|
|
51
89
|
public removeBlocks(numBlocks: number) {
|
|
52
90
|
this.l2Blocks = this.l2Blocks.slice(0, -numBlocks);
|
|
91
|
+
const maxBlockNum = this.l2Blocks.length;
|
|
92
|
+
// Remove any checkpoint whose last block is beyond the remaining blocks.
|
|
93
|
+
this.checkpointList = this.checkpointList.filter(c => {
|
|
94
|
+
const lastBlockNum = c.blocks[0].number + c.blocks.length - 1;
|
|
95
|
+
return lastBlockNum <= maxBlockNum;
|
|
96
|
+
});
|
|
97
|
+
// Keep tip numbers consistent with remaining blocks.
|
|
98
|
+
this.checkpointedBlockNumber = Math.min(this.checkpointedBlockNumber, maxBlockNum);
|
|
99
|
+
this.proposedCheckpointBlockNumber = Math.min(this.proposedCheckpointBlockNumber, maxBlockNum);
|
|
100
|
+
this.provenBlockNumber = Math.min(this.provenBlockNumber, maxBlockNum);
|
|
101
|
+
this.finalizedBlockNumber = Math.min(this.finalizedBlockNumber, maxBlockNum);
|
|
53
102
|
this.log.verbose(`Removed ${numBlocks} blocks from the mock L2 block source`);
|
|
54
103
|
}
|
|
55
104
|
|
|
@@ -64,8 +113,42 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
64
113
|
this.finalizedBlockNumber = finalizedBlockNumber;
|
|
65
114
|
}
|
|
66
115
|
|
|
116
|
+
public setProposedCheckpointBlockNumber(blockNumber: number) {
|
|
117
|
+
this.proposedCheckpointBlockNumber = blockNumber;
|
|
118
|
+
}
|
|
119
|
+
|
|
67
120
|
public setCheckpointedBlockNumber(checkpointedBlockNumber: number) {
|
|
121
|
+
const prevCheckpointed = this.checkpointedBlockNumber;
|
|
68
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
|
+
}
|
|
127
|
+
// Auto-create single-block checkpoints for newly checkpointed blocks that don't have one yet.
|
|
128
|
+
// This handles blocks added via addProposedBlocks that are now being marked as checkpointed.
|
|
129
|
+
const newCheckpoints: Checkpoint[] = [];
|
|
130
|
+
for (let blockNum = prevCheckpointed + 1; blockNum <= checkpointedBlockNumber; blockNum++) {
|
|
131
|
+
const block = this.l2Blocks[blockNum - 1];
|
|
132
|
+
if (!block) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (this.checkpointList.some(c => c.blocks.some(b => b.number === block.number))) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const checkpointNum = CheckpointNumber(this.checkpointList.length + newCheckpoints.length + 1);
|
|
139
|
+
const checkpoint = new Checkpoint(
|
|
140
|
+
block.archive,
|
|
141
|
+
CheckpointHeader.random({ slotNumber: block.header.globalVariables.slotNumber }),
|
|
142
|
+
[block],
|
|
143
|
+
checkpointNum,
|
|
144
|
+
);
|
|
145
|
+
newCheckpoints.push(checkpoint);
|
|
146
|
+
}
|
|
147
|
+
// Insert new checkpoints in order by number.
|
|
148
|
+
if (newCheckpoints.length > 0) {
|
|
149
|
+
this.checkpointList.push(...newCheckpoints);
|
|
150
|
+
this.checkpointList.sort((a, b) => a.number - b.number);
|
|
151
|
+
}
|
|
69
152
|
}
|
|
70
153
|
|
|
71
154
|
/**
|
|
@@ -96,6 +179,18 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
96
179
|
return Promise.resolve(BlockNumber(this.provenBlockNumber));
|
|
97
180
|
}
|
|
98
181
|
|
|
182
|
+
public getCheckpointedL2BlockNumber() {
|
|
183
|
+
return Promise.resolve(BlockNumber(this.checkpointedBlockNumber));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public getFinalizedL2BlockNumber() {
|
|
187
|
+
return Promise.resolve(BlockNumber(this.finalizedBlockNumber));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public getProposedCheckpointL2BlockNumber() {
|
|
191
|
+
return Promise.resolve(BlockNumber(this.proposedCheckpointBlockNumber));
|
|
192
|
+
}
|
|
193
|
+
|
|
99
194
|
public getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
|
|
100
195
|
if (number > this.checkpointedBlockNumber) {
|
|
101
196
|
return Promise.resolve(undefined);
|
|
@@ -104,20 +199,10 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
104
199
|
if (!block) {
|
|
105
200
|
return Promise.resolve(undefined);
|
|
106
201
|
}
|
|
107
|
-
|
|
108
|
-
CheckpointNumber(number),
|
|
109
|
-
block,
|
|
110
|
-
new L1PublishedData(BigInt(number), BigInt(number), `0x${number.toString(16).padStart(64, '0')}`),
|
|
111
|
-
[],
|
|
112
|
-
);
|
|
113
|
-
return Promise.resolve(checkpointedBlock);
|
|
202
|
+
return Promise.resolve(this.toCheckpointedBlock(block));
|
|
114
203
|
}
|
|
115
204
|
|
|
116
|
-
public async getCheckpointedBlocks(
|
|
117
|
-
from: BlockNumber,
|
|
118
|
-
limit: number,
|
|
119
|
-
_proven?: boolean,
|
|
120
|
-
): Promise<CheckpointedL2Block[]> {
|
|
205
|
+
public async getCheckpointedBlocks(from: BlockNumber, limit: number): Promise<CheckpointedL2Block[]> {
|
|
121
206
|
const result: CheckpointedL2Block[] = [];
|
|
122
207
|
for (let i = 0; i < limit; i++) {
|
|
123
208
|
const blockNum = from + i;
|
|
@@ -137,7 +222,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
137
222
|
* @param number - The block number to return (inclusive).
|
|
138
223
|
* @returns The requested L2 block.
|
|
139
224
|
*/
|
|
140
|
-
public getBlock(number: number): Promise<
|
|
225
|
+
public getBlock(number: number): Promise<L2Block | undefined> {
|
|
141
226
|
const block = this.l2Blocks[number - 1];
|
|
142
227
|
return Promise.resolve(block);
|
|
143
228
|
}
|
|
@@ -147,7 +232,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
147
232
|
* @param number - The block number to return.
|
|
148
233
|
* @returns The requested L2 block.
|
|
149
234
|
*/
|
|
150
|
-
public
|
|
235
|
+
public getL2Block(number: BlockNumber): Promise<L2Block | undefined> {
|
|
151
236
|
const block = this.l2Blocks[number - 1];
|
|
152
237
|
return Promise.resolve(block);
|
|
153
238
|
}
|
|
@@ -158,95 +243,41 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
158
243
|
* @param limit - The maximum number of blocks to return.
|
|
159
244
|
* @returns The requested mocked L2 blocks.
|
|
160
245
|
*/
|
|
161
|
-
public getBlocks(from: number, limit: number
|
|
162
|
-
return Promise.resolve(
|
|
163
|
-
this.l2Blocks
|
|
164
|
-
.slice(from - 1, from - 1 + limit)
|
|
165
|
-
.filter(b => !proven || this.provenBlockNumber === undefined || b.number <= this.provenBlockNumber),
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
public getPublishedCheckpoints(from: CheckpointNumber, limit: number) {
|
|
170
|
-
// TODO(mbps): Implement this properly. This only works when we have one block per checkpoint.
|
|
171
|
-
const blocks = this.l2Blocks.slice(from - 1, from - 1 + limit);
|
|
172
|
-
return Promise.all(
|
|
173
|
-
blocks.map(async block => {
|
|
174
|
-
// Create a checkpoint from the block - manually construct since L2BlockNew doesn't have toCheckpoint()
|
|
175
|
-
const checkpoint = await Checkpoint.random(block.checkpointNumber, { numBlocks: 1 });
|
|
176
|
-
checkpoint.blocks = [block];
|
|
177
|
-
return new PublishedCheckpoint(
|
|
178
|
-
checkpoint,
|
|
179
|
-
new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
180
|
-
[],
|
|
181
|
-
);
|
|
182
|
-
}),
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
public async getCheckpointByArchive(archive: Fr): Promise<Checkpoint | undefined> {
|
|
187
|
-
// TODO(mbps): Implement this properly. This only works when we have one block per checkpoint.
|
|
188
|
-
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
|
|
189
|
-
if (!block) {
|
|
190
|
-
return undefined;
|
|
191
|
-
}
|
|
192
|
-
// Create a checkpoint from the block - manually construct since L2BlockNew doesn't have toCheckpoint()
|
|
193
|
-
const checkpoint = await Checkpoint.random(block.checkpointNumber, { numBlocks: 1 });
|
|
194
|
-
checkpoint.blocks = [block];
|
|
195
|
-
return checkpoint;
|
|
246
|
+
public getBlocks(from: number, limit: number): Promise<L2Block[]> {
|
|
247
|
+
return Promise.resolve(this.l2Blocks.slice(from - 1, from - 1 + limit));
|
|
196
248
|
}
|
|
197
249
|
|
|
198
|
-
public
|
|
199
|
-
const
|
|
200
|
-
.slice(from - 1, from - 1 + limit)
|
|
201
|
-
.filter(b => !proven || this.provenBlockNumber === undefined || b.number <= this.provenBlockNumber);
|
|
250
|
+
public getCheckpoints(from: CheckpointNumber, limit: number) {
|
|
251
|
+
const checkpoints = this.checkpointList.slice(from - 1, from - 1 + limit);
|
|
202
252
|
return Promise.resolve(
|
|
203
|
-
|
|
204
|
-
CheckpointedL2Block.fromFields({
|
|
205
|
-
checkpointNumber: CheckpointNumber(block.number),
|
|
206
|
-
block,
|
|
207
|
-
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
208
|
-
attestations: [],
|
|
209
|
-
}),
|
|
210
|
-
),
|
|
253
|
+
checkpoints.map(checkpoint => new PublishedCheckpoint(checkpoint, this.mockL1DataForCheckpoint(checkpoint), [])),
|
|
211
254
|
);
|
|
212
255
|
}
|
|
213
256
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return
|
|
257
|
+
public getCheckpointByArchive(archive: Fr): Promise<Checkpoint | undefined> {
|
|
258
|
+
const checkpoint = this.checkpointList.find(c => c.archive.root.equals(archive));
|
|
259
|
+
return Promise.resolve(checkpoint);
|
|
217
260
|
}
|
|
218
261
|
|
|
219
|
-
public async
|
|
262
|
+
public async getCheckpointedBlockByHash(blockHash: BlockHash): Promise<CheckpointedL2Block | undefined> {
|
|
220
263
|
for (const block of this.l2Blocks) {
|
|
221
264
|
const hash = await block.hash();
|
|
222
265
|
if (hash.equals(blockHash)) {
|
|
223
|
-
return
|
|
224
|
-
checkpointNumber: CheckpointNumber(block.number),
|
|
225
|
-
block,
|
|
226
|
-
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
227
|
-
attestations: [],
|
|
228
|
-
});
|
|
266
|
+
return this.toCheckpointedBlock(block);
|
|
229
267
|
}
|
|
230
268
|
}
|
|
231
269
|
return undefined;
|
|
232
270
|
}
|
|
233
271
|
|
|
234
|
-
public
|
|
272
|
+
public getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
235
273
|
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
|
|
236
274
|
if (!block) {
|
|
237
275
|
return Promise.resolve(undefined);
|
|
238
276
|
}
|
|
239
|
-
return Promise.resolve(
|
|
240
|
-
CheckpointedL2Block.fromFields({
|
|
241
|
-
checkpointNumber: CheckpointNumber(block.number),
|
|
242
|
-
block,
|
|
243
|
-
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
244
|
-
attestations: [],
|
|
245
|
-
}),
|
|
246
|
-
);
|
|
277
|
+
return Promise.resolve(this.toCheckpointedBlock(block));
|
|
247
278
|
}
|
|
248
279
|
|
|
249
|
-
public async
|
|
280
|
+
public async getL2BlockByHash(blockHash: BlockHash): Promise<L2Block | undefined> {
|
|
250
281
|
for (const block of this.l2Blocks) {
|
|
251
282
|
const hash = await block.hash();
|
|
252
283
|
if (hash.equals(blockHash)) {
|
|
@@ -256,12 +287,12 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
256
287
|
return undefined;
|
|
257
288
|
}
|
|
258
289
|
|
|
259
|
-
public
|
|
290
|
+
public getL2BlockByArchive(archive: Fr): Promise<L2Block | undefined> {
|
|
260
291
|
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
|
|
261
292
|
return Promise.resolve(block);
|
|
262
293
|
}
|
|
263
294
|
|
|
264
|
-
public async getBlockHeaderByHash(blockHash:
|
|
295
|
+
public async getBlockHeaderByHash(blockHash: BlockHash): Promise<BlockHeader | undefined> {
|
|
265
296
|
for (const block of this.l2Blocks) {
|
|
266
297
|
const hash = await block.hash();
|
|
267
298
|
if (hash.equals(blockHash)) {
|
|
@@ -276,46 +307,77 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
276
307
|
return Promise.resolve(block?.header);
|
|
277
308
|
}
|
|
278
309
|
|
|
310
|
+
public async getBlockData(number: BlockNumber): Promise<BlockData | undefined> {
|
|
311
|
+
const block = this.l2Blocks[number - 1];
|
|
312
|
+
if (!block) {
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
header: block.header,
|
|
317
|
+
archive: block.archive,
|
|
318
|
+
blockHash: await block.hash(),
|
|
319
|
+
checkpointNumber: block.checkpointNumber,
|
|
320
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
public async getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
|
|
325
|
+
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
|
|
326
|
+
if (!block) {
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
header: block.header,
|
|
331
|
+
archive: block.archive,
|
|
332
|
+
blockHash: await block.hash(),
|
|
333
|
+
checkpointNumber: block.checkpointNumber,
|
|
334
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
279
338
|
getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
|
|
280
339
|
return Promise.resolve(this.l2Blocks.at(typeof number === 'number' ? number - 1 : -1)?.header);
|
|
281
340
|
}
|
|
282
341
|
|
|
283
342
|
getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
343
|
+
return Promise.resolve(this.getCheckpointsInEpoch(epochNumber));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
getCheckpointsDataForEpoch(epochNumber: EpochNumber): Promise<CheckpointData[]> {
|
|
347
|
+
const checkpoints = this.getCheckpointsInEpoch(epochNumber);
|
|
348
|
+
return Promise.resolve(
|
|
349
|
+
checkpoints.map(
|
|
350
|
+
(checkpoint): CheckpointData => ({
|
|
351
|
+
checkpointNumber: checkpoint.number,
|
|
352
|
+
header: checkpoint.header,
|
|
353
|
+
archive: checkpoint.archive,
|
|
354
|
+
checkpointOutHash: computeCheckpointOutHash(
|
|
355
|
+
checkpoint.blocks.map(b => b.body.txEffects.map(tx => tx.l2ToL1Msgs)),
|
|
356
|
+
),
|
|
357
|
+
startBlock: checkpoint.blocks[0].number,
|
|
358
|
+
blockCount: checkpoint.blocks.length,
|
|
359
|
+
attestations: [],
|
|
360
|
+
l1: this.mockL1DataForCheckpoint(checkpoint),
|
|
361
|
+
}),
|
|
362
|
+
),
|
|
298
363
|
);
|
|
299
364
|
}
|
|
300
365
|
|
|
301
|
-
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
return slot >= start && slot <= end;
|
|
307
|
-
});
|
|
308
|
-
return Promise.resolve(blocks);
|
|
366
|
+
getCheckpointedBlocksForEpoch(epochNumber: EpochNumber): Promise<CheckpointedL2Block[]> {
|
|
367
|
+
const checkpoints = this.getCheckpointsInEpoch(epochNumber);
|
|
368
|
+
return Promise.resolve(
|
|
369
|
+
checkpoints.flatMap(checkpoint => checkpoint.blocks.map(block => this.toCheckpointedBlock(block))),
|
|
370
|
+
);
|
|
309
371
|
}
|
|
310
372
|
|
|
311
|
-
getBlocksForSlot(slotNumber: SlotNumber): Promise<
|
|
373
|
+
getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
|
|
312
374
|
const blocks = this.l2Blocks.filter(b => b.header.globalVariables.slotNumber === slotNumber);
|
|
313
375
|
return Promise.resolve(blocks);
|
|
314
376
|
}
|
|
315
377
|
|
|
316
|
-
async
|
|
317
|
-
const
|
|
318
|
-
return
|
|
378
|
+
async getCheckpointedBlockHeadersForEpoch(epochNumber: EpochNumber): Promise<BlockHeader[]> {
|
|
379
|
+
const checkpointedBlocks = await this.getCheckpointedBlocksForEpoch(epochNumber);
|
|
380
|
+
return checkpointedBlocks.map(b => b.block.header);
|
|
319
381
|
}
|
|
320
382
|
|
|
321
383
|
/**
|
|
@@ -334,7 +396,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
334
396
|
return {
|
|
335
397
|
data: txEffect,
|
|
336
398
|
l2BlockNumber: block.number,
|
|
337
|
-
l2BlockHash:
|
|
399
|
+
l2BlockHash: await block.hash(),
|
|
338
400
|
txIndexInBlock: block.body.txEffects.indexOf(txEffect),
|
|
339
401
|
};
|
|
340
402
|
}
|
|
@@ -348,13 +410,16 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
348
410
|
for (const block of this.l2Blocks) {
|
|
349
411
|
for (const txEffect of block.body.txEffects) {
|
|
350
412
|
if (txEffect.txHash.equals(txHash)) {
|
|
413
|
+
// In mock, assume all txs are checkpointed with successful execution
|
|
351
414
|
return new TxReceipt(
|
|
352
415
|
txHash,
|
|
353
|
-
TxStatus.
|
|
354
|
-
|
|
416
|
+
TxStatus.CHECKPOINTED,
|
|
417
|
+
TxExecutionResult.SUCCESS,
|
|
418
|
+
undefined,
|
|
355
419
|
txEffect.transactionFee.toBigInt(),
|
|
356
|
-
|
|
420
|
+
await block.hash(),
|
|
357
421
|
block.number,
|
|
422
|
+
getEpochAtSlot(block.slot, EmptyL1RollupConstants),
|
|
358
423
|
);
|
|
359
424
|
}
|
|
360
425
|
}
|
|
@@ -363,17 +428,19 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
363
428
|
}
|
|
364
429
|
|
|
365
430
|
async getL2Tips(): Promise<L2Tips> {
|
|
366
|
-
const [latest, proven, finalized, checkpointed] = [
|
|
431
|
+
const [latest, proven, finalized, checkpointed, proposedCheckpoint] = [
|
|
367
432
|
await this.getBlockNumber(),
|
|
368
433
|
await this.getProvenBlockNumber(),
|
|
369
434
|
this.finalizedBlockNumber,
|
|
370
435
|
this.checkpointedBlockNumber,
|
|
436
|
+
await this.getProposedCheckpointL2BlockNumber(),
|
|
371
437
|
] as const;
|
|
372
438
|
|
|
373
439
|
const latestBlock = this.l2Blocks[latest - 1];
|
|
374
440
|
const provenBlock = this.l2Blocks[proven - 1];
|
|
375
441
|
const finalizedBlock = this.l2Blocks[finalized - 1];
|
|
376
442
|
const checkpointedBlock = this.l2Blocks[checkpointed - 1];
|
|
443
|
+
const proposedCheckpointBlock = this.l2Blocks[proposedCheckpoint - 1];
|
|
377
444
|
|
|
378
445
|
const latestBlockId = {
|
|
379
446
|
number: BlockNumber(latest),
|
|
@@ -391,10 +458,17 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
391
458
|
number: BlockNumber(checkpointed),
|
|
392
459
|
hash: (await checkpointedBlock?.hash())?.toString(),
|
|
393
460
|
};
|
|
461
|
+
const proposedCheckpointBlockId = {
|
|
462
|
+
number: BlockNumber(proposedCheckpoint),
|
|
463
|
+
hash: (await proposedCheckpointBlock?.hash())?.toString(),
|
|
464
|
+
};
|
|
394
465
|
|
|
395
466
|
const makeTipId = (blockId: typeof latestBlockId) => ({
|
|
396
467
|
block: blockId,
|
|
397
|
-
checkpoint: {
|
|
468
|
+
checkpoint: {
|
|
469
|
+
number: this.findCheckpointNumberForBlock(blockId.number) ?? CheckpointNumber(0),
|
|
470
|
+
hash: blockId.hash,
|
|
471
|
+
},
|
|
398
472
|
});
|
|
399
473
|
|
|
400
474
|
return {
|
|
@@ -402,14 +476,15 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
402
476
|
checkpointed: makeTipId(checkpointedBlockId),
|
|
403
477
|
proven: makeTipId(provenBlockId),
|
|
404
478
|
finalized: makeTipId(finalizedBlockId),
|
|
479
|
+
proposedCheckpoint: makeTipId(proposedCheckpointBlockId),
|
|
405
480
|
};
|
|
406
481
|
}
|
|
407
482
|
|
|
408
|
-
|
|
483
|
+
getSyncedL2EpochNumber(): Promise<EpochNumber> {
|
|
409
484
|
throw new Error('Method not implemented.');
|
|
410
485
|
}
|
|
411
486
|
|
|
412
|
-
|
|
487
|
+
getSyncedL2SlotNumber(): Promise<SlotNumber> {
|
|
413
488
|
throw new Error('Method not implemented.');
|
|
414
489
|
}
|
|
415
490
|
|
|
@@ -482,4 +557,46 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
482
557
|
getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
|
|
483
558
|
return Promise.resolve({ valid: true });
|
|
484
559
|
}
|
|
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
|
+
|
|
569
|
+
/** Returns checkpoints whose slot falls within the given epoch. */
|
|
570
|
+
private getCheckpointsInEpoch(epochNumber: EpochNumber): Checkpoint[] {
|
|
571
|
+
const epochDuration = DefaultL1ContractsConfig.aztecEpochDuration;
|
|
572
|
+
const [start, end] = getSlotRangeForEpoch(epochNumber, { epochDuration });
|
|
573
|
+
return this.checkpointList.filter(c => c.header.slotNumber >= start && c.header.slotNumber <= end);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** Creates a mock L1PublishedData for a checkpoint. */
|
|
577
|
+
private mockL1DataForCheckpoint(checkpoint: Checkpoint): L1PublishedData {
|
|
578
|
+
return new L1PublishedData(BigInt(checkpoint.number), BigInt(checkpoint.number), Buffer32.random().toString());
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/** Creates a CheckpointedL2Block from a block using stored checkpoint info. */
|
|
582
|
+
private toCheckpointedBlock(block: L2Block): CheckpointedL2Block {
|
|
583
|
+
const checkpoint = this.checkpointList.find(c => c.blocks.some(b => b.number === block.number));
|
|
584
|
+
const checkpointNumber = checkpoint?.number ?? block.checkpointNumber;
|
|
585
|
+
return new CheckpointedL2Block(
|
|
586
|
+
checkpointNumber,
|
|
587
|
+
block,
|
|
588
|
+
new L1PublishedData(
|
|
589
|
+
BigInt(block.number),
|
|
590
|
+
BigInt(block.number),
|
|
591
|
+
`0x${block.number.toString(16).padStart(64, '0')}`,
|
|
592
|
+
),
|
|
593
|
+
[],
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/** Finds the checkpoint number for a block, or undefined if the block is not in any checkpoint. */
|
|
598
|
+
private findCheckpointNumberForBlock(blockNumber: BlockNumber): CheckpointNumber | undefined {
|
|
599
|
+
const checkpoint = this.checkpointList.find(c => c.blocks.some(b => b.number === blockNumber));
|
|
600
|
+
return checkpoint?.number;
|
|
601
|
+
}
|
|
485
602
|
}
|
package/src/test/mock_structs.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { Secp256k1Signer } from '@aztec/foundation/crypto/secp256k1-signer'
|
|
|
12
12
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
13
13
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
14
14
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
15
|
-
import { CommitteeAttestation,
|
|
15
|
+
import { CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
|
|
16
16
|
import { Checkpoint, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
17
17
|
import { PrivateLog, PublicLog, SiloedTag, Tag } from '@aztec/stdlib/logs';
|
|
18
18
|
import { InboxLeaf } from '@aztec/stdlib/messaging';
|
|
@@ -46,24 +46,40 @@ export function makeInboxMessage(
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export function makeInboxMessages(
|
|
49
|
-
|
|
49
|
+
totalCount: number,
|
|
50
50
|
opts: {
|
|
51
51
|
initialHash?: Buffer16;
|
|
52
52
|
initialCheckpointNumber?: CheckpointNumber;
|
|
53
|
+
messagesPerCheckpoint?: number;
|
|
53
54
|
overrideFn?: (msg: InboxMessage, index: number) => InboxMessage;
|
|
54
55
|
} = {},
|
|
55
56
|
): InboxMessage[] {
|
|
56
|
-
const {
|
|
57
|
+
const {
|
|
58
|
+
initialHash = Buffer16.ZERO,
|
|
59
|
+
overrideFn = msg => msg,
|
|
60
|
+
initialCheckpointNumber = CheckpointNumber(1),
|
|
61
|
+
messagesPerCheckpoint = 1,
|
|
62
|
+
} = opts;
|
|
63
|
+
|
|
57
64
|
const messages: InboxMessage[] = [];
|
|
58
65
|
let rollingHash = initialHash;
|
|
59
|
-
for (let i = 0; i <
|
|
66
|
+
for (let i = 0; i < totalCount; i++) {
|
|
67
|
+
const msgIndex = i % messagesPerCheckpoint;
|
|
68
|
+
const checkpointNumber = CheckpointNumber.fromBigInt(
|
|
69
|
+
BigInt(initialCheckpointNumber) + BigInt(i) / BigInt(messagesPerCheckpoint),
|
|
70
|
+
);
|
|
60
71
|
const leaf = Fr.random();
|
|
61
|
-
const
|
|
62
|
-
|
|
72
|
+
const message = overrideFn(
|
|
73
|
+
makeInboxMessage(rollingHash, {
|
|
74
|
+
leaf,
|
|
75
|
+
checkpointNumber,
|
|
76
|
+
index: InboxLeaf.smallestIndexForCheckpoint(checkpointNumber) + BigInt(msgIndex),
|
|
77
|
+
}),
|
|
78
|
+
i,
|
|
79
|
+
);
|
|
63
80
|
rollingHash = message.rollingHash;
|
|
64
81
|
messages.push(message);
|
|
65
82
|
}
|
|
66
|
-
|
|
67
83
|
return messages;
|
|
68
84
|
}
|
|
69
85
|
|
|
@@ -111,6 +127,25 @@ export function makeL1PublishedData(l1BlockNumber: number): L1PublishedData {
|
|
|
111
127
|
return new L1PublishedData(BigInt(l1BlockNumber), BigInt(l1BlockNumber * 1000), makeBlockHash(l1BlockNumber));
|
|
112
128
|
}
|
|
113
129
|
|
|
130
|
+
/** Creates a Checkpoint from a list of blocks with a header that matches the blocks' structure. */
|
|
131
|
+
export function makeCheckpoint(blocks: L2Block[], checkpointNumber = CheckpointNumber(1)): Checkpoint {
|
|
132
|
+
const firstBlock = blocks[0];
|
|
133
|
+
const { slotNumber, timestamp, coinbase, feeRecipient, gasFees } = firstBlock.header.globalVariables;
|
|
134
|
+
return new Checkpoint(
|
|
135
|
+
blocks.at(-1)!.archive,
|
|
136
|
+
CheckpointHeader.random({
|
|
137
|
+
lastArchiveRoot: firstBlock.header.lastArchive.root,
|
|
138
|
+
slotNumber,
|
|
139
|
+
timestamp,
|
|
140
|
+
coinbase,
|
|
141
|
+
feeRecipient,
|
|
142
|
+
gasFees,
|
|
143
|
+
}),
|
|
144
|
+
blocks,
|
|
145
|
+
checkpointNumber,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
114
149
|
/** Wraps a Checkpoint with L1 published data and random attestations. */
|
|
115
150
|
export function makePublishedCheckpoint(
|
|
116
151
|
checkpoint: Checkpoint,
|
|
@@ -268,8 +303,8 @@ export async function makeCheckpointWithLogs(
|
|
|
268
303
|
): Promise<PublishedCheckpoint> {
|
|
269
304
|
const { previousArchive, numTxsPerBlock = 4, privateLogs, publicLogs } = options;
|
|
270
305
|
|
|
271
|
-
const block = await
|
|
272
|
-
checkpointNumber: CheckpointNumber(blockNumber),
|
|
306
|
+
const block = await L2Block.random(BlockNumber(blockNumber), {
|
|
307
|
+
checkpointNumber: CheckpointNumber.fromBlockNumber(BlockNumber(blockNumber)),
|
|
273
308
|
indexWithinCheckpoint: IndexWithinCheckpoint(0),
|
|
274
309
|
state: makeStateForBlock(blockNumber, numTxsPerBlock),
|
|
275
310
|
...(previousArchive ? { lastArchive: previousArchive } : {}),
|
|
@@ -285,11 +320,6 @@ export async function makeCheckpointWithLogs(
|
|
|
285
320
|
return txEffect;
|
|
286
321
|
});
|
|
287
322
|
|
|
288
|
-
const checkpoint =
|
|
289
|
-
AppendOnlyTreeSnapshot.random(),
|
|
290
|
-
CheckpointHeader.random(),
|
|
291
|
-
[block],
|
|
292
|
-
CheckpointNumber(blockNumber),
|
|
293
|
-
);
|
|
323
|
+
const checkpoint = makeCheckpoint([block], CheckpointNumber.fromBlockNumber(BlockNumber(blockNumber)));
|
|
294
324
|
return makePublishedCheckpoint(checkpoint, blockNumber);
|
|
295
325
|
}
|