@aztec/archiver 0.0.1-commit.86469d5 → 0.0.1-commit.8655d4a
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 +19 -11
- package/dest/archiver.d.ts +39 -17
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +260 -160
- package/dest/config.d.ts +6 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +23 -15
- package/dest/errors.d.ts +55 -9
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +81 -14
- package/dest/factory.d.ts +13 -9
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +51 -37
- package/dest/index.d.ts +12 -3
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +11 -2
- package/dest/l1/bin/retrieve-calldata.js +36 -33
- package/dest/l1/calldata_retriever.d.ts +74 -50
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +201 -260
- package/dest/l1/data_retrieval.d.ts +26 -17
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +42 -47
- 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/trace_tx.d.ts +12 -66
- package/dest/l1/trace_tx.d.ts.map +1 -1
- 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/contract_data_source_adapter.d.ts +25 -0
- package/dest/modules/contract_data_source_adapter.d.ts.map +1 -0
- package/dest/modules/contract_data_source_adapter.js +40 -0
- package/dest/modules/data_source_base.d.ts +71 -42
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +270 -179
- package/dest/modules/data_store_updater.d.ts +49 -17
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +211 -121
- package/dest/modules/instrumentation.d.ts +21 -3
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +44 -9
- package/dest/modules/l1_synchronizer.d.ts +14 -12
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +443 -211
- 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 +174 -66
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +743 -245
- package/dest/store/contract_class_store.d.ts +17 -4
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +24 -68
- package/dest/store/contract_instance_store.d.ts +28 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +37 -2
- package/dest/store/data_stores.d.ts +68 -0
- package/dest/store/data_stores.d.ts.map +1 -0
- package/dest/store/data_stores.js +54 -0
- package/dest/store/function_names_cache.d.ts +17 -0
- package/dest/store/function_names_cache.d.ts.map +1 -0
- package/dest/store/function_names_cache.js +30 -0
- package/dest/store/l2_tips_cache.d.ts +25 -0
- package/dest/store/l2_tips_cache.d.ts.map +1 -0
- package/dest/store/l2_tips_cache.js +26 -0
- package/dest/store/log_store.d.ts +42 -37
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +262 -388
- package/dest/store/log_store_codec.d.ts +70 -0
- package/dest/store/log_store_codec.d.ts.map +1 -0
- package/dest/store/log_store_codec.js +101 -0
- package/dest/store/message_store.d.ts +11 -1
- package/dest/store/message_store.d.ts.map +1 -1
- package/dest/store/message_store.js +51 -9
- package/dest/test/fake_l1_state.d.ts +25 -1
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +166 -32
- 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 +62 -41
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +321 -202
- package/dest/test/mock_structs.d.ts +4 -1
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +13 -1
- package/dest/test/noop_l1_archiver.d.ts +12 -6
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +26 -9
- package/package.json +14 -14
- package/src/archiver.ts +319 -181
- package/src/config.ts +32 -12
- package/src/errors.ts +122 -21
- package/src/factory.ts +75 -36
- package/src/index.ts +19 -2
- package/src/l1/README.md +25 -68
- package/src/l1/bin/retrieve-calldata.ts +46 -39
- package/src/l1/calldata_retriever.ts +260 -379
- package/src/l1/data_retrieval.ts +58 -69
- package/src/l1/spire_proposer.ts +7 -15
- package/src/l1/validate_historical_logs.ts +140 -0
- package/src/modules/contract_data_source_adapter.ts +55 -0
- package/src/modules/data_source_base.ts +347 -221
- package/src/modules/data_store_updater.ts +248 -153
- package/src/modules/instrumentation.ts +56 -9
- package/src/modules/l1_synchronizer.ts +585 -258
- package/src/modules/validation.ts +10 -9
- package/src/store/block_store.ts +924 -300
- package/src/store/contract_class_store.ts +31 -103
- package/src/store/contract_instance_store.ts +51 -5
- package/src/store/data_stores.ts +104 -0
- package/src/store/function_names_cache.ts +37 -0
- package/src/store/l2_tips_cache.ts +35 -0
- package/src/store/log_store.ts +303 -499
- package/src/store/log_store_codec.ts +132 -0
- package/src/store/message_store.ts +60 -10
- package/src/structs/inbox_message.ts +1 -1
- package/src/test/fake_l1_state.ts +213 -42
- 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 +394 -210
- package/src/test/mock_structs.ts +20 -6
- package/src/test/noop_l1_archiver.ts +39 -9
- package/dest/store/kv_archiver_store.d.ts +0 -340
- package/dest/store/kv_archiver_store.d.ts.map +0 -1
- package/dest/store/kv_archiver_store.js +0 -446
- package/src/store/kv_archiver_store.ts +0 -639
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
2
2
|
import { DefaultL1ContractsConfig } from '@aztec/ethereum/config';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
BlockNumber,
|
|
5
|
+
CheckpointNumber,
|
|
6
|
+
EpochNumber,
|
|
7
|
+
IndexWithinCheckpoint,
|
|
8
|
+
SlotNumber,
|
|
9
|
+
} from '@aztec/foundation/branded-types';
|
|
4
10
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
5
11
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
6
12
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -8,17 +14,40 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
8
14
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
9
15
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
10
16
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
type BlockData,
|
|
18
|
+
type BlockHash,
|
|
19
|
+
type BlockQuery,
|
|
20
|
+
type BlockTag,
|
|
21
|
+
type BlocksQuery,
|
|
22
|
+
Body,
|
|
23
|
+
type CheckpointQuery,
|
|
24
|
+
type CheckpointsQuery,
|
|
25
|
+
GENESIS_BLOCK_HEADER_HASH,
|
|
26
|
+
GENESIS_CHECKPOINT_HEADER_HASH,
|
|
13
27
|
L2Block,
|
|
14
28
|
type L2BlockSource,
|
|
15
29
|
type L2Tips,
|
|
30
|
+
type ProposedCheckpointQuery,
|
|
16
31
|
type ValidateCheckpointResult,
|
|
17
32
|
} from '@aztec/stdlib/block';
|
|
18
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
Checkpoint,
|
|
35
|
+
type CheckpointData,
|
|
36
|
+
L1PublishedData,
|
|
37
|
+
type ProposedCheckpointData,
|
|
38
|
+
PublishedCheckpoint,
|
|
39
|
+
} from '@aztec/stdlib/checkpoint';
|
|
19
40
|
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
20
|
-
import {
|
|
21
|
-
|
|
41
|
+
import {
|
|
42
|
+
EmptyL1RollupConstants,
|
|
43
|
+
type L1RollupConstants,
|
|
44
|
+
getEpochAtSlot,
|
|
45
|
+
getSlotRangeForEpoch,
|
|
46
|
+
} from '@aztec/stdlib/epoch-helpers';
|
|
47
|
+
import { computeCheckpointOutHash } from '@aztec/stdlib/messaging';
|
|
48
|
+
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
49
|
+
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
50
|
+
import { BlockHeader, TxExecutionResult, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
|
|
22
51
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
23
52
|
|
|
24
53
|
/**
|
|
@@ -26,21 +55,103 @@ import type { UInt64 } from '@aztec/stdlib/types';
|
|
|
26
55
|
*/
|
|
27
56
|
export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
28
57
|
protected l2Blocks: L2Block[] = [];
|
|
58
|
+
protected checkpointList: Checkpoint[] = [];
|
|
29
59
|
|
|
30
60
|
private provenBlockNumber: number = 0;
|
|
31
61
|
private finalizedBlockNumber: number = 0;
|
|
32
62
|
private checkpointedBlockNumber: number = 0;
|
|
63
|
+
private proposedCheckpointBlockNumber: number = 0;
|
|
64
|
+
|
|
65
|
+
private initialHeader: BlockHeader = BlockHeader.empty();
|
|
66
|
+
private initialHeaderHash: BlockHash = GENESIS_BLOCK_HEADER_HASH;
|
|
67
|
+
private genesisArchiveRoot?: Fr;
|
|
68
|
+
private genesisBlock?: L2Block;
|
|
33
69
|
|
|
34
70
|
private log = createLogger('archiver:mock_l2_block_source');
|
|
35
71
|
|
|
72
|
+
/** Returns the initial header used to synthesize block 0. */
|
|
73
|
+
public getInitialHeader(): BlockHeader {
|
|
74
|
+
return this.initialHeader;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Sets the initial header used to synthesize block 0. Tests that wire up a real
|
|
79
|
+
* world-state should call this with `worldState.getInitialHeader()` so the L2BlockStream
|
|
80
|
+
* agrees on the genesis hash on both sides. Precomputes and caches the header hash so
|
|
81
|
+
* `getGenesisBlockHash()` can return synchronously.
|
|
82
|
+
*/
|
|
83
|
+
public async setInitialHeader(header: BlockHeader): Promise<void> {
|
|
84
|
+
this.initialHeader = header;
|
|
85
|
+
this.initialHeaderHash = await header.hash();
|
|
86
|
+
this.genesisBlock = undefined;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Returns the precomputed hash of the genesis block header. Defaults to the static
|
|
91
|
+
* {@link GENESIS_BLOCK_HEADER_HASH} unless {@link setInitialHeader} has been called with a
|
|
92
|
+
* custom header.
|
|
93
|
+
*/
|
|
94
|
+
public getGenesisBlockHash(): BlockHash {
|
|
95
|
+
return this.initialHeaderHash;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Sets the post-genesis archive root used to synthesize block 0. Mirrors the real archiver,
|
|
100
|
+
* whose synthetic block 0 carries `new AppendOnlyTreeSnapshot(genesisArchiveRoot, 1)` rather
|
|
101
|
+
* than `AppendOnlyTreeSnapshot.empty()`. Tests wiring up a real world-state should set this so
|
|
102
|
+
* archive-based block lookups against the mock match production semantics.
|
|
103
|
+
*/
|
|
104
|
+
public setGenesisArchiveRoot(root: Fr): void {
|
|
105
|
+
this.genesisArchiveRoot = root;
|
|
106
|
+
this.genesisBlock = undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private getGenesisBlock(): L2Block {
|
|
110
|
+
if (this.genesisBlock) {
|
|
111
|
+
return this.genesisBlock;
|
|
112
|
+
}
|
|
113
|
+
const archive = this.genesisArchiveRoot
|
|
114
|
+
? new AppendOnlyTreeSnapshot(this.genesisArchiveRoot, 1)
|
|
115
|
+
: AppendOnlyTreeSnapshot.empty();
|
|
116
|
+
return (this.genesisBlock = new L2Block(
|
|
117
|
+
archive,
|
|
118
|
+
this.initialHeader,
|
|
119
|
+
Body.empty(),
|
|
120
|
+
CheckpointNumber.ZERO,
|
|
121
|
+
IndexWithinCheckpoint(0),
|
|
122
|
+
));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Creates blocks grouped into single-block checkpoints. */
|
|
36
126
|
public async createBlocks(numBlocks: number) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
127
|
+
await this.createCheckpoints(numBlocks, 1);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public getCheckpointNumber(): Promise<CheckpointNumber> {
|
|
131
|
+
return Promise.resolve(
|
|
132
|
+
this.checkpointList.length === 0 ? CheckpointNumber.ZERO : CheckpointNumber(this.checkpointList.length),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Creates checkpoints, each containing `blocksPerCheckpoint` blocks. */
|
|
137
|
+
public async createCheckpoints(numCheckpoints: number, blocksPerCheckpoint: number = 1) {
|
|
138
|
+
for (let c = 0; c < numCheckpoints; c++) {
|
|
139
|
+
const checkpointNum = CheckpointNumber(this.checkpointList.length + 1);
|
|
140
|
+
const startBlockNum = this.l2Blocks.length + 1;
|
|
141
|
+
const slotNumber = SlotNumber(Number(checkpointNum));
|
|
142
|
+
const checkpoint = await Checkpoint.random(checkpointNum, {
|
|
143
|
+
numBlocks: blocksPerCheckpoint,
|
|
144
|
+
startBlockNumber: startBlockNum,
|
|
145
|
+
slotNumber,
|
|
146
|
+
checkpointNumber: checkpointNum,
|
|
147
|
+
});
|
|
148
|
+
this.checkpointList.push(checkpoint);
|
|
149
|
+
this.l2Blocks.push(...checkpoint.blocks);
|
|
41
150
|
}
|
|
42
151
|
|
|
43
|
-
this.log.verbose(
|
|
152
|
+
this.log.verbose(
|
|
153
|
+
`Created ${numCheckpoints} checkpoints with ${blocksPerCheckpoint} blocks each in the mock L2 block source`,
|
|
154
|
+
);
|
|
44
155
|
}
|
|
45
156
|
|
|
46
157
|
public addProposedBlocks(blocks: L2Block[]) {
|
|
@@ -50,6 +161,17 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
50
161
|
|
|
51
162
|
public removeBlocks(numBlocks: number) {
|
|
52
163
|
this.l2Blocks = this.l2Blocks.slice(0, -numBlocks);
|
|
164
|
+
const maxBlockNum = this.l2Blocks.length;
|
|
165
|
+
// Remove any checkpoint whose last block is beyond the remaining blocks.
|
|
166
|
+
this.checkpointList = this.checkpointList.filter(c => {
|
|
167
|
+
const lastBlockNum = c.blocks[0].number + c.blocks.length - 1;
|
|
168
|
+
return lastBlockNum <= maxBlockNum;
|
|
169
|
+
});
|
|
170
|
+
// Keep tip numbers consistent with remaining blocks.
|
|
171
|
+
this.checkpointedBlockNumber = Math.min(this.checkpointedBlockNumber, maxBlockNum);
|
|
172
|
+
this.proposedCheckpointBlockNumber = Math.min(this.proposedCheckpointBlockNumber, maxBlockNum);
|
|
173
|
+
this.provenBlockNumber = Math.min(this.provenBlockNumber, maxBlockNum);
|
|
174
|
+
this.finalizedBlockNumber = Math.min(this.finalizedBlockNumber, maxBlockNum);
|
|
53
175
|
this.log.verbose(`Removed ${numBlocks} blocks from the mock L2 block source`);
|
|
54
176
|
}
|
|
55
177
|
|
|
@@ -64,8 +186,42 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
64
186
|
this.finalizedBlockNumber = finalizedBlockNumber;
|
|
65
187
|
}
|
|
66
188
|
|
|
189
|
+
public setProposedCheckpointBlockNumber(blockNumber: number) {
|
|
190
|
+
this.proposedCheckpointBlockNumber = blockNumber;
|
|
191
|
+
}
|
|
192
|
+
|
|
67
193
|
public setCheckpointedBlockNumber(checkpointedBlockNumber: number) {
|
|
194
|
+
const prevCheckpointed = this.checkpointedBlockNumber;
|
|
68
195
|
this.checkpointedBlockNumber = checkpointedBlockNumber;
|
|
196
|
+
// Proposed checkpoint is always at least as advanced as checkpointed
|
|
197
|
+
if (this.proposedCheckpointBlockNumber < checkpointedBlockNumber) {
|
|
198
|
+
this.proposedCheckpointBlockNumber = checkpointedBlockNumber;
|
|
199
|
+
}
|
|
200
|
+
// Auto-create single-block checkpoints for newly checkpointed blocks that don't have one yet.
|
|
201
|
+
// This handles blocks added via addProposedBlocks that are now being marked as checkpointed.
|
|
202
|
+
const newCheckpoints: Checkpoint[] = [];
|
|
203
|
+
for (let blockNum = prevCheckpointed + 1; blockNum <= checkpointedBlockNumber; blockNum++) {
|
|
204
|
+
const block = this.l2Blocks[blockNum - 1];
|
|
205
|
+
if (!block) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (this.checkpointList.some(c => c.blocks.some(b => b.number === block.number))) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const checkpointNum = CheckpointNumber(this.checkpointList.length + newCheckpoints.length + 1);
|
|
212
|
+
const checkpoint = new Checkpoint(
|
|
213
|
+
block.archive,
|
|
214
|
+
CheckpointHeader.random({ slotNumber: block.header.globalVariables.slotNumber }),
|
|
215
|
+
[block],
|
|
216
|
+
checkpointNum,
|
|
217
|
+
);
|
|
218
|
+
newCheckpoints.push(checkpoint);
|
|
219
|
+
}
|
|
220
|
+
// Insert new checkpoints in order by number.
|
|
221
|
+
if (newCheckpoints.length > 0) {
|
|
222
|
+
this.checkpointList.push(...newCheckpoints);
|
|
223
|
+
this.checkpointList.sort((a, b) => a.number - b.number);
|
|
224
|
+
}
|
|
69
225
|
}
|
|
70
226
|
|
|
71
227
|
/**
|
|
@@ -88,212 +244,105 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
88
244
|
* Gets the number of the latest L2 block processed by the block source implementation.
|
|
89
245
|
* @returns In this mock instance, returns the number of L2 blocks that we've mocked.
|
|
90
246
|
*/
|
|
91
|
-
public getBlockNumber()
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return Promise.resolve(BlockNumber(this.provenBlockNumber));
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
public getCheckpointedL2BlockNumber() {
|
|
100
|
-
return Promise.resolve(BlockNumber(this.checkpointedBlockNumber));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
public getFinalizedL2BlockNumber() {
|
|
104
|
-
return Promise.resolve(BlockNumber(this.finalizedBlockNumber));
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
public getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
|
|
108
|
-
if (number > this.checkpointedBlockNumber) {
|
|
109
|
-
return Promise.resolve(undefined);
|
|
247
|
+
public getBlockNumber(): Promise<BlockNumber>;
|
|
248
|
+
public getBlockNumber(query: BlockQuery): Promise<BlockNumber | undefined>;
|
|
249
|
+
public async getBlockNumber(query?: BlockQuery): Promise<BlockNumber | undefined> {
|
|
250
|
+
if (!query) {
|
|
251
|
+
return BlockNumber(this.l2Blocks.length);
|
|
110
252
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return Promise.resolve(undefined);
|
|
253
|
+
if ('number' in query) {
|
|
254
|
+
return query.number;
|
|
114
255
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
block,
|
|
118
|
-
new L1PublishedData(BigInt(number), BigInt(number), `0x${number.toString(16).padStart(64, '0')}`),
|
|
119
|
-
[],
|
|
120
|
-
);
|
|
121
|
-
return Promise.resolve(checkpointedBlock);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
public async getCheckpointedBlocks(from: BlockNumber, limit: number): Promise<CheckpointedL2Block[]> {
|
|
125
|
-
const result: CheckpointedL2Block[] = [];
|
|
126
|
-
for (let i = 0; i < limit; i++) {
|
|
127
|
-
const blockNum = from + i;
|
|
128
|
-
if (blockNum > this.checkpointedBlockNumber) {
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
const block = await this.getCheckpointedBlock(BlockNumber(blockNum));
|
|
132
|
-
if (block) {
|
|
133
|
-
result.push(block);
|
|
134
|
-
}
|
|
256
|
+
if ('tag' in query) {
|
|
257
|
+
return BlockNumber(this.resolveBlockTag(query.tag));
|
|
135
258
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Gets an l2 block.
|
|
141
|
-
* @param number - The block number to return (inclusive).
|
|
142
|
-
* @returns The requested L2 block.
|
|
143
|
-
*/
|
|
144
|
-
public getBlock(number: number): Promise<L2Block | undefined> {
|
|
145
|
-
const block = this.l2Blocks[number - 1];
|
|
146
|
-
return Promise.resolve(block);
|
|
259
|
+
const block = await this.getBlock(query);
|
|
260
|
+
return block ? block.header.globalVariables.blockNumber : undefined;
|
|
147
261
|
}
|
|
148
262
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
* @param number - The block number to return.
|
|
152
|
-
* @returns The requested L2 block.
|
|
153
|
-
*/
|
|
154
|
-
public getL2Block(number: BlockNumber): Promise<L2Block | undefined> {
|
|
155
|
-
const block = this.l2Blocks[number - 1];
|
|
156
|
-
return Promise.resolve(block);
|
|
263
|
+
public getProposedCheckpointL2BlockNumber() {
|
|
264
|
+
return Promise.resolve(BlockNumber(this.proposedCheckpointBlockNumber));
|
|
157
265
|
}
|
|
158
266
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
public getBlocks(from: number, limit: number): Promise<L2Block[]> {
|
|
166
|
-
return Promise.resolve(this.l2Blocks.slice(from - 1, from - 1 + limit));
|
|
267
|
+
public getCheckpoint(query: CheckpointQuery): Promise<PublishedCheckpoint | undefined> {
|
|
268
|
+
const checkpoint = this.resolveCheckpointQuery(query);
|
|
269
|
+
if (!checkpoint) {
|
|
270
|
+
return Promise.resolve(undefined);
|
|
271
|
+
}
|
|
272
|
+
return Promise.resolve(new PublishedCheckpoint(checkpoint, this.mockL1DataForCheckpoint(checkpoint), []));
|
|
167
273
|
}
|
|
168
274
|
|
|
169
|
-
public getCheckpoints(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
blocks.map(async block => {
|
|
174
|
-
// Create a checkpoint from the block - manually construct since L2Block 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
|
-
}),
|
|
275
|
+
public getCheckpoints(query: CheckpointsQuery): Promise<PublishedCheckpoint[]> {
|
|
276
|
+
const checkpoints = this.resolveCheckpointsQuery(query);
|
|
277
|
+
return Promise.resolve(
|
|
278
|
+
checkpoints.map(checkpoint => new PublishedCheckpoint(checkpoint, this.mockL1DataForCheckpoint(checkpoint), [])),
|
|
183
279
|
);
|
|
184
280
|
}
|
|
185
281
|
|
|
186
|
-
public
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (!block) {
|
|
190
|
-
return undefined;
|
|
191
|
-
}
|
|
192
|
-
// Create a checkpoint from the block - manually construct since L2Block doesn't have toCheckpoint()
|
|
193
|
-
const checkpoint = await Checkpoint.random(block.checkpointNumber, { numBlocks: 1 });
|
|
194
|
-
checkpoint.blocks = [block];
|
|
195
|
-
return checkpoint;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
public async getCheckpointedBlockByHash(blockHash: BlockHash): Promise<CheckpointedL2Block | undefined> {
|
|
199
|
-
for (const block of this.l2Blocks) {
|
|
200
|
-
const hash = await block.hash();
|
|
201
|
-
if (hash.equals(blockHash)) {
|
|
202
|
-
return CheckpointedL2Block.fromFields({
|
|
203
|
-
checkpointNumber: CheckpointNumber.fromBlockNumber(block.number),
|
|
204
|
-
block,
|
|
205
|
-
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
206
|
-
attestations: [],
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return undefined;
|
|
282
|
+
public getCheckpointByArchive(archive: Fr): Promise<Checkpoint | undefined> {
|
|
283
|
+
const checkpoint = this.checkpointList.find(c => c.archive.root.equals(archive));
|
|
284
|
+
return Promise.resolve(checkpoint);
|
|
211
285
|
}
|
|
212
286
|
|
|
213
|
-
public
|
|
214
|
-
const
|
|
215
|
-
if (!
|
|
287
|
+
public getCheckpointData(query: CheckpointQuery): Promise<CheckpointData | undefined> {
|
|
288
|
+
const checkpoint = this.resolveCheckpointQuery(query);
|
|
289
|
+
if (!checkpoint) {
|
|
216
290
|
return Promise.resolve(undefined);
|
|
217
291
|
}
|
|
218
|
-
return Promise.resolve(
|
|
219
|
-
CheckpointedL2Block.fromFields({
|
|
220
|
-
checkpointNumber: CheckpointNumber.fromBlockNumber(block.number),
|
|
221
|
-
block,
|
|
222
|
-
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
223
|
-
attestations: [],
|
|
224
|
-
}),
|
|
225
|
-
);
|
|
292
|
+
return Promise.resolve(this.checkpointToData(checkpoint));
|
|
226
293
|
}
|
|
227
294
|
|
|
228
|
-
public
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (hash.equals(blockHash)) {
|
|
232
|
-
return block;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return undefined;
|
|
295
|
+
public getCheckpointsData(query: CheckpointsQuery): Promise<CheckpointData[]> {
|
|
296
|
+
const checkpoints = this.resolveCheckpointsQuery(query);
|
|
297
|
+
return Promise.resolve(checkpoints.map(c => this.checkpointToData(c)));
|
|
236
298
|
}
|
|
237
299
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
300
|
+
private checkpointToData(checkpoint: Checkpoint): CheckpointData {
|
|
301
|
+
return {
|
|
302
|
+
checkpointNumber: checkpoint.number,
|
|
303
|
+
header: checkpoint.header,
|
|
304
|
+
archive: checkpoint.archive,
|
|
305
|
+
checkpointOutHash: computeCheckpointOutHash(
|
|
306
|
+
checkpoint.blocks.map(b => b.body.txEffects.map(tx => tx.l2ToL1Msgs)),
|
|
307
|
+
),
|
|
308
|
+
startBlock: checkpoint.blocks[0].number,
|
|
309
|
+
blockCount: checkpoint.blocks.length,
|
|
310
|
+
feeAssetPriceModifier: checkpoint.feeAssetPriceModifier,
|
|
311
|
+
attestations: [],
|
|
312
|
+
l1: this.mockL1DataForCheckpoint(checkpoint),
|
|
313
|
+
};
|
|
241
314
|
}
|
|
242
315
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
316
|
+
private resolveCheckpointQuery(query: CheckpointQuery): Checkpoint | undefined {
|
|
317
|
+
if ('number' in query) {
|
|
318
|
+
return this.checkpointList[query.number - 1];
|
|
319
|
+
}
|
|
320
|
+
if ('slot' in query) {
|
|
321
|
+
return this.checkpointList.find(c => c.header.slotNumber === query.slot);
|
|
322
|
+
}
|
|
323
|
+
switch (query.tag) {
|
|
324
|
+
case 'checkpointed':
|
|
325
|
+
return this.checkpointList[this.checkpointList.length - 1];
|
|
326
|
+
case 'proven': {
|
|
327
|
+
const provenCheckpoint = this.checkpointList.filter(c =>
|
|
328
|
+
c.blocks.some(b => b.number <= this.provenBlockNumber),
|
|
329
|
+
);
|
|
330
|
+
return provenCheckpoint.at(-1);
|
|
331
|
+
}
|
|
332
|
+
case 'finalized': {
|
|
333
|
+
const finalizedCheckpoint = this.checkpointList.filter(c =>
|
|
334
|
+
c.blocks.some(b => b.number <= this.finalizedBlockNumber),
|
|
335
|
+
);
|
|
336
|
+
return finalizedCheckpoint.at(-1);
|
|
248
337
|
}
|
|
249
338
|
}
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
public getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined> {
|
|
254
|
-
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
|
|
255
|
-
return Promise.resolve(block?.header);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
|
|
259
|
-
return Promise.resolve(this.l2Blocks.at(typeof number === 'number' ? number - 1 : -1)?.header);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
|
|
263
|
-
// TODO(mbps): Implement this properly. This only works when we have one block per checkpoint.
|
|
264
|
-
const epochDuration = DefaultL1ContractsConfig.aztecEpochDuration;
|
|
265
|
-
const [start, end] = getSlotRangeForEpoch(epochNumber, { epochDuration });
|
|
266
|
-
const blocks = this.l2Blocks.filter(b => {
|
|
267
|
-
const slot = b.header.globalVariables.slotNumber;
|
|
268
|
-
return slot >= start && slot <= end;
|
|
269
|
-
});
|
|
270
|
-
// Create checkpoints from blocks - manually construct since L2Block doesn't have toCheckpoint()
|
|
271
|
-
return Promise.all(
|
|
272
|
-
blocks.map(async block => {
|
|
273
|
-
const checkpoint = await Checkpoint.random(block.checkpointNumber, { numBlocks: 1 });
|
|
274
|
-
checkpoint.blocks = [block];
|
|
275
|
-
return checkpoint;
|
|
276
|
-
}),
|
|
277
|
-
);
|
|
278
339
|
}
|
|
279
340
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
return slot >= start && slot <= end;
|
|
286
|
-
});
|
|
287
|
-
return Promise.resolve(
|
|
288
|
-
blocks.map(block =>
|
|
289
|
-
CheckpointedL2Block.fromFields({
|
|
290
|
-
checkpointNumber: CheckpointNumber.fromBlockNumber(block.number),
|
|
291
|
-
block,
|
|
292
|
-
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
293
|
-
attestations: [],
|
|
294
|
-
}),
|
|
295
|
-
),
|
|
296
|
-
);
|
|
341
|
+
private resolveCheckpointsQuery(query: CheckpointsQuery): Checkpoint[] {
|
|
342
|
+
if ('from' in query) {
|
|
343
|
+
return this.checkpointList.slice(query.from - 1, query.from - 1 + query.limit);
|
|
344
|
+
}
|
|
345
|
+
return this.getCheckpointsInEpoch(query.epoch);
|
|
297
346
|
}
|
|
298
347
|
|
|
299
348
|
getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
|
|
@@ -301,11 +350,6 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
301
350
|
return Promise.resolve(blocks);
|
|
302
351
|
}
|
|
303
352
|
|
|
304
|
-
async getCheckpointedBlockHeadersForEpoch(epochNumber: EpochNumber): Promise<BlockHeader[]> {
|
|
305
|
-
const checkpointedBlocks = await this.getCheckpointedBlocksForEpoch(epochNumber);
|
|
306
|
-
return checkpointedBlocks.map(b => b.block.header);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
353
|
/**
|
|
310
354
|
* Gets a tx effect.
|
|
311
355
|
* @param txHash - The hash of the tx corresponding to the tx effect.
|
|
@@ -323,7 +367,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
323
367
|
data: txEffect,
|
|
324
368
|
l2BlockNumber: block.number,
|
|
325
369
|
l2BlockHash: await block.hash(),
|
|
326
|
-
txIndexInBlock: block.body.txEffects.
|
|
370
|
+
txIndexInBlock: block.body.txEffects.findIndex(t => t.txHash.equals(txHash)),
|
|
327
371
|
};
|
|
328
372
|
}
|
|
329
373
|
|
|
@@ -345,6 +389,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
345
389
|
txEffect.transactionFee.toBigInt(),
|
|
346
390
|
await block.hash(),
|
|
347
391
|
block.number,
|
|
392
|
+
getEpochAtSlot(block.slot, EmptyL1RollupConstants),
|
|
348
393
|
);
|
|
349
394
|
}
|
|
350
395
|
}
|
|
@@ -353,53 +398,77 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
353
398
|
}
|
|
354
399
|
|
|
355
400
|
async getL2Tips(): Promise<L2Tips> {
|
|
356
|
-
const [latest, proven, finalized, checkpointed] = [
|
|
401
|
+
const [latest, proven, finalized, checkpointed, proposedCheckpoint] = [
|
|
357
402
|
await this.getBlockNumber(),
|
|
358
|
-
|
|
403
|
+
this.provenBlockNumber,
|
|
359
404
|
this.finalizedBlockNumber,
|
|
360
405
|
this.checkpointedBlockNumber,
|
|
406
|
+
await this.getProposedCheckpointL2BlockNumber(),
|
|
361
407
|
] as const;
|
|
362
408
|
|
|
363
409
|
const latestBlock = this.l2Blocks[latest - 1];
|
|
364
410
|
const provenBlock = this.l2Blocks[proven - 1];
|
|
365
411
|
const finalizedBlock = this.l2Blocks[finalized - 1];
|
|
366
412
|
const checkpointedBlock = this.l2Blocks[checkpointed - 1];
|
|
413
|
+
const proposedCheckpointBlock = this.l2Blocks[proposedCheckpoint - 1];
|
|
414
|
+
|
|
415
|
+
// For genesis tips (block number 0) report the dynamic initial header hash so consumers
|
|
416
|
+
// running L2BlockStream against this mock agree at block 0 with their local tip store.
|
|
417
|
+
const genesisHash = (await this.initialHeader.hash()).toString();
|
|
418
|
+
const tipHash = async (block: L2Block | undefined, number: number): Promise<string> => {
|
|
419
|
+
if (block) {
|
|
420
|
+
return (await block.hash()).toString();
|
|
421
|
+
}
|
|
422
|
+
return number === 0 ? genesisHash : '';
|
|
423
|
+
};
|
|
367
424
|
|
|
368
425
|
const latestBlockId = {
|
|
369
426
|
number: BlockNumber(latest),
|
|
370
|
-
hash:
|
|
427
|
+
hash: await tipHash(latestBlock, latest),
|
|
371
428
|
};
|
|
372
429
|
const provenBlockId = {
|
|
373
430
|
number: BlockNumber(proven),
|
|
374
|
-
hash:
|
|
431
|
+
hash: await tipHash(provenBlock, proven),
|
|
375
432
|
};
|
|
376
433
|
const finalizedBlockId = {
|
|
377
434
|
number: BlockNumber(finalized),
|
|
378
|
-
hash:
|
|
435
|
+
hash: await tipHash(finalizedBlock, finalized),
|
|
379
436
|
};
|
|
380
437
|
const checkpointedBlockId = {
|
|
381
438
|
number: BlockNumber(checkpointed),
|
|
382
|
-
hash:
|
|
439
|
+
hash: await tipHash(checkpointedBlock, checkpointed),
|
|
440
|
+
};
|
|
441
|
+
const proposedCheckpointBlockId = {
|
|
442
|
+
number: BlockNumber(proposedCheckpoint),
|
|
443
|
+
hash: await tipHash(proposedCheckpointBlock, proposedCheckpoint),
|
|
383
444
|
};
|
|
384
445
|
|
|
385
|
-
const makeTipId = (blockId: typeof latestBlockId) =>
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
446
|
+
const makeTipId = (blockId: typeof latestBlockId) => {
|
|
447
|
+
const checkpointNumber = this.findCheckpointNumberForBlock(blockId.number) ?? CheckpointNumber(0);
|
|
448
|
+
// Match production semantics: checkpoint 0 is fully synthetic (no real checkpoint header
|
|
449
|
+
// exists at 0), so its hash stays at the protocol constant `GENESIS_CHECKPOINT_HEADER_HASH`
|
|
450
|
+
// even though the block-0 hash is dynamic. See L2TipsCache for the production path.
|
|
451
|
+
const hash = checkpointNumber === 0 ? GENESIS_CHECKPOINT_HEADER_HASH.toString() : blockId.hash;
|
|
452
|
+
return {
|
|
453
|
+
block: blockId,
|
|
454
|
+
checkpoint: { number: checkpointNumber, hash },
|
|
455
|
+
};
|
|
456
|
+
};
|
|
389
457
|
|
|
390
458
|
return {
|
|
391
459
|
proposed: latestBlockId,
|
|
392
460
|
checkpointed: makeTipId(checkpointedBlockId),
|
|
393
461
|
proven: makeTipId(provenBlockId),
|
|
394
462
|
finalized: makeTipId(finalizedBlockId),
|
|
463
|
+
proposedCheckpoint: makeTipId(proposedCheckpointBlockId),
|
|
395
464
|
};
|
|
396
465
|
}
|
|
397
466
|
|
|
398
|
-
|
|
467
|
+
getSyncedL2EpochNumber(): Promise<EpochNumber> {
|
|
399
468
|
throw new Error('Method not implemented.');
|
|
400
469
|
}
|
|
401
470
|
|
|
402
|
-
|
|
471
|
+
getSyncedL2SlotNumber(): Promise<SlotNumber> {
|
|
403
472
|
throw new Error('Method not implemented.');
|
|
404
473
|
}
|
|
405
474
|
|
|
@@ -411,8 +480,12 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
411
480
|
return Promise.resolve(EmptyL1RollupConstants);
|
|
412
481
|
}
|
|
413
482
|
|
|
483
|
+
isPruneDueAtSlot(_slot: SlotNumber): Promise<boolean> {
|
|
484
|
+
return Promise.resolve(false);
|
|
485
|
+
}
|
|
486
|
+
|
|
414
487
|
getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
415
|
-
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
488
|
+
return Promise.resolve({ genesisArchiveRoot: this.genesisArchiveRoot ?? new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
416
489
|
}
|
|
417
490
|
|
|
418
491
|
getL1Timestamp(): Promise<bigint> {
|
|
@@ -465,6 +538,95 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
465
538
|
return Promise.resolve();
|
|
466
539
|
}
|
|
467
540
|
|
|
541
|
+
async getBlock(query: BlockQuery): Promise<L2Block | undefined> {
|
|
542
|
+
if ('number' in query) {
|
|
543
|
+
if (query.number === 0) {
|
|
544
|
+
return this.getGenesisBlock();
|
|
545
|
+
}
|
|
546
|
+
return this.l2Blocks[query.number - 1];
|
|
547
|
+
}
|
|
548
|
+
if ('hash' in query) {
|
|
549
|
+
const genesis = this.getGenesisBlock();
|
|
550
|
+
if ((await genesis.hash()).equals(query.hash)) {
|
|
551
|
+
return genesis;
|
|
552
|
+
}
|
|
553
|
+
for (const b of this.l2Blocks) {
|
|
554
|
+
const hash = await b.hash();
|
|
555
|
+
if (hash.equals(query.hash)) {
|
|
556
|
+
return b;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
if ('archive' in query) {
|
|
562
|
+
const genesis = this.getGenesisBlock();
|
|
563
|
+
if (genesis.archive.root.equals(query.archive)) {
|
|
564
|
+
return genesis;
|
|
565
|
+
}
|
|
566
|
+
return this.l2Blocks.find(b => b.archive.root.equals(query.archive));
|
|
567
|
+
}
|
|
568
|
+
const number = this.resolveBlockTag(query.tag);
|
|
569
|
+
if (number === 0) {
|
|
570
|
+
return this.getGenesisBlock();
|
|
571
|
+
}
|
|
572
|
+
return this.l2Blocks[number - 1];
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
private resolveBlockTag(tag: BlockTag): number {
|
|
576
|
+
switch (tag) {
|
|
577
|
+
case 'latest':
|
|
578
|
+
case 'proposed':
|
|
579
|
+
return this.l2Blocks.length;
|
|
580
|
+
case 'checkpointed':
|
|
581
|
+
return this.checkpointedBlockNumber;
|
|
582
|
+
case 'proven':
|
|
583
|
+
return this.provenBlockNumber;
|
|
584
|
+
case 'finalized':
|
|
585
|
+
return this.finalizedBlockNumber;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
getBlocks(query: BlocksQuery): Promise<L2Block[]> {
|
|
590
|
+
let blocks: L2Block[];
|
|
591
|
+
if ('from' in query) {
|
|
592
|
+
blocks = this.l2Blocks.slice(query.from - 1, query.from - 1 + query.limit);
|
|
593
|
+
} else {
|
|
594
|
+
const epochCheckpoints = this.getCheckpointsInEpoch(query.epoch);
|
|
595
|
+
blocks = epochCheckpoints.flatMap(c => c.blocks);
|
|
596
|
+
}
|
|
597
|
+
if (query.onlyCheckpointed) {
|
|
598
|
+
blocks = blocks.filter(b => b.header.globalVariables.blockNumber <= this.checkpointedBlockNumber);
|
|
599
|
+
}
|
|
600
|
+
return Promise.resolve(blocks);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
async getBlockData(query: BlockQuery): Promise<BlockData | undefined> {
|
|
604
|
+
const block = await this.getBlock(query);
|
|
605
|
+
if (!block) {
|
|
606
|
+
return undefined;
|
|
607
|
+
}
|
|
608
|
+
return {
|
|
609
|
+
header: block.header,
|
|
610
|
+
archive: block.archive,
|
|
611
|
+
blockHash: await block.hash(),
|
|
612
|
+
checkpointNumber: block.checkpointNumber,
|
|
613
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
async getBlocksData(query: BlocksQuery): Promise<BlockData[]> {
|
|
618
|
+
const blocks = await this.getBlocks(query);
|
|
619
|
+
return Promise.all(
|
|
620
|
+
blocks.map(async block => ({
|
|
621
|
+
header: block.header,
|
|
622
|
+
archive: block.archive,
|
|
623
|
+
blockHash: await block.hash(),
|
|
624
|
+
checkpointNumber: block.checkpointNumber,
|
|
625
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
626
|
+
})),
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
|
|
468
630
|
isPendingChainInvalid(): Promise<boolean> {
|
|
469
631
|
return Promise.resolve(false);
|
|
470
632
|
}
|
|
@@ -472,4 +634,26 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
472
634
|
getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
|
|
473
635
|
return Promise.resolve({ valid: true });
|
|
474
636
|
}
|
|
637
|
+
|
|
638
|
+
getProposedCheckpointData(_query?: ProposedCheckpointQuery): Promise<ProposedCheckpointData | undefined> {
|
|
639
|
+
return Promise.resolve(undefined);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** Returns checkpoints whose slot falls within the given epoch. */
|
|
643
|
+
private getCheckpointsInEpoch(epochNumber: EpochNumber): Checkpoint[] {
|
|
644
|
+
const epochDuration = DefaultL1ContractsConfig.aztecEpochDuration;
|
|
645
|
+
const [start, end] = getSlotRangeForEpoch(epochNumber, { epochDuration });
|
|
646
|
+
return this.checkpointList.filter(c => c.header.slotNumber >= start && c.header.slotNumber <= end);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/** Creates a mock L1PublishedData for a checkpoint. */
|
|
650
|
+
private mockL1DataForCheckpoint(checkpoint: Checkpoint): L1PublishedData {
|
|
651
|
+
return new L1PublishedData(BigInt(checkpoint.number), BigInt(checkpoint.number), Buffer32.random().toString());
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/** Finds the checkpoint number for a block, or undefined if the block is not in any checkpoint. */
|
|
655
|
+
private findCheckpointNumberForBlock(blockNumber: BlockNumber): CheckpointNumber | undefined {
|
|
656
|
+
const checkpoint = this.checkpointList.find(c => c.blocks.some(b => b.number === blockNumber));
|
|
657
|
+
return checkpoint?.number;
|
|
658
|
+
}
|
|
475
659
|
}
|