@aztec/archiver 0.0.1-commit.fffb133c → 0.0.1-dev
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/dest/archiver.d.ts +9 -5
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +87 -111
- package/dest/errors.d.ts +7 -9
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +9 -14
- package/dest/factory.d.ts +4 -3
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +32 -26
- 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 +36 -33
- 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 +190 -259
- package/dest/l1/data_retrieval.d.ts +4 -7
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +10 -14
- 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 +13 -8
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +29 -73
- package/dest/modules/data_store_updater.d.ts +22 -7
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +114 -40
- package/dest/modules/instrumentation.d.ts +4 -2
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +26 -12
- package/dest/modules/l1_synchronizer.d.ts +5 -8
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +42 -13
- package/dest/store/block_store.d.ts +38 -29
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +294 -85
- package/dest/store/contract_class_store.d.ts +1 -1
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +27 -7
- 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 +17 -2
- package/dest/store/kv_archiver_store.d.ts +40 -18
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +44 -16
- package/dest/store/l2_tips_cache.d.ts +18 -0
- package/dest/store/l2_tips_cache.d.ts.map +1 -0
- package/dest/store/l2_tips_cache.js +20 -0
- 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 +125 -56
- package/dest/store/message_store.js +1 -1
- package/dest/test/fake_l1_state.d.ts +20 -1
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +97 -20
- 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_l2_block_source.d.ts +25 -9
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +133 -87
- 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 +20 -6
- 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 +72 -0
- package/package.json +14 -13
- package/src/archiver.ts +110 -132
- package/src/errors.ts +10 -24
- package/src/factory.ts +47 -23
- package/src/index.ts +1 -0
- package/src/l1/README.md +25 -68
- package/src/l1/bin/retrieve-calldata.ts +46 -39
- package/src/l1/calldata_retriever.ts +249 -379
- package/src/l1/data_retrieval.ts +7 -17
- package/src/l1/spire_proposer.ts +7 -15
- package/src/l1/validate_trace.ts +24 -6
- package/src/modules/data_source_base.ts +59 -98
- package/src/modules/data_store_updater.ts +124 -43
- package/src/modules/instrumentation.ts +24 -12
- package/src/modules/l1_synchronizer.ts +49 -17
- package/src/store/block_store.ts +359 -115
- package/src/store/contract_class_store.ts +27 -7
- package/src/store/contract_instance_store.ts +19 -5
- package/src/store/kv_archiver_store.ts +71 -25
- package/src/store/l2_tips_cache.ts +27 -0
- package/src/store/log_store.ts +186 -57
- package/src/store/message_store.ts +1 -1
- package/src/test/fake_l1_state.ts +125 -21
- package/src/test/index.ts +3 -0
- package/src/test/mock_archiver.ts +3 -2
- package/src/test/mock_l2_block_source.ts +179 -87
- package/src/test/mock_structs.ts +42 -12
- package/src/test/noop_l1_archiver.ts +115 -0
package/dest/store/log_store.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
2
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import { filterAsync } from '@aztec/foundation/collection';
|
|
3
|
+
import { compactArray, filterAsync } from '@aztec/foundation/collection';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
6
|
import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
|
|
7
|
-
import {
|
|
7
|
+
import { BlockHash } from '@aztec/stdlib/block';
|
|
8
8
|
import { MAX_LOGS_PER_TAG } from '@aztec/stdlib/interfaces/api-limit';
|
|
9
9
|
import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
10
|
+
import { TxHash } from '@aztec/stdlib/tx';
|
|
11
|
+
/**
|
|
12
|
+
* Tag key for a log: the string form of its first field, or the empty string when the log carries no
|
|
13
|
+
* fields. A protocol-valid public log can carry zero fields (e.g. a raw AVM `EMITPUBLICLOG` with
|
|
14
|
+
* `logSize = 0`), which has no tag to index by. Keying it under the empty tag keeps it retrievable via
|
|
15
|
+
* the per-block read (and droppable on reorg) while never matching a real tag query — instead of reading
|
|
16
|
+
* `fields[0]` off an empty array and aborting the whole block-ingestion transaction.
|
|
17
|
+
*/ function tagKeyForLog(fields) {
|
|
18
|
+
return fields.length > 0 ? fields[0].toString() : '';
|
|
19
|
+
}
|
|
10
20
|
/**
|
|
11
21
|
* A store for logs
|
|
12
22
|
*/ export class LogStore {
|
|
@@ -47,19 +57,21 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
47
57
|
block.body.txEffects.forEach((txEffect)=>{
|
|
48
58
|
const txHash = txEffect.txHash;
|
|
49
59
|
txEffect.privateLogs.forEach((log)=>{
|
|
50
|
-
// Private logs use SiloedTag (already siloed by kernel)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
// Private logs use SiloedTag (already siloed by kernel). A zero-field log has no tag and is keyed
|
|
61
|
+
// under the empty tag rather than throwing on log.fields[0].
|
|
62
|
+
const tagKey = tagKeyForLog(log.fields);
|
|
63
|
+
this.#log.debug(`Found private log with tag ${tagKey} in block ${block.number}`);
|
|
64
|
+
const currentLogs = privateTaggedLogs.get(tagKey) ?? [];
|
|
54
65
|
currentLogs.push(new TxScopedL2Log(txHash, block.number, block.timestamp, log.getEmittedFields(), txEffect.noteHashes, txEffect.nullifiers[0]).toBuffer());
|
|
55
|
-
privateTaggedLogs.set(
|
|
66
|
+
privateTaggedLogs.set(tagKey, currentLogs);
|
|
56
67
|
});
|
|
57
68
|
txEffect.publicLogs.forEach((log)=>{
|
|
58
|
-
// Public logs use Tag directly (not siloed) and are stored with contract address
|
|
59
|
-
|
|
69
|
+
// Public logs use Tag directly (not siloed) and are stored with contract address. A zero-field
|
|
70
|
+
// log has no tag and is keyed under the empty tag rather than throwing on log.fields[0].
|
|
71
|
+
const tagKey = tagKeyForLog(log.fields);
|
|
60
72
|
const contractAddress = log.contractAddress;
|
|
61
|
-
const key = `${contractAddress.toString()}_${
|
|
62
|
-
this.#log.debug(`Found public log with tag ${
|
|
73
|
+
const key = `${contractAddress.toString()}_${tagKey}`;
|
|
74
|
+
this.#log.debug(`Found public log with tag ${tagKey} from contract ${contractAddress.toString()} in block ${block.number}`);
|
|
63
75
|
const currentLogs = publicTaggedLogs.get(key) ?? [];
|
|
64
76
|
currentLogs.push(new TxScopedL2Log(txHash, block.number, block.timestamp, log.getEmittedFields(), txEffect.noteHashes, txEffect.nullifiers[0]).toBuffer());
|
|
65
77
|
publicTaggedLogs.set(key, currentLogs);
|
|
@@ -142,6 +154,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
142
154
|
await this.#publicLogKeysByBlock.set(block.number, publicTagsInBlock);
|
|
143
155
|
const publicLogsInBlock = block.body.txEffects.map((txEffect, txIndex)=>[
|
|
144
156
|
numToUInt32BE(txIndex),
|
|
157
|
+
txEffect.txHash.toBuffer(),
|
|
145
158
|
numToUInt32BE(txEffect.publicLogs.length),
|
|
146
159
|
txEffect.publicLogs.map((log)=>log.toBuffer())
|
|
147
160
|
].flat()).flat();
|
|
@@ -154,6 +167,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
154
167
|
const blockHash = await block.hash();
|
|
155
168
|
const contractClassLogsInBlock = block.body.txEffects.map((txEffect, txIndex)=>[
|
|
156
169
|
numToUInt32BE(txIndex),
|
|
170
|
+
txEffect.txHash.toBuffer(),
|
|
157
171
|
numToUInt32BE(txEffect.contractClassLogs.length),
|
|
158
172
|
txEffect.contractClassLogs.map((log)=>log.toBuffer())
|
|
159
173
|
].flat()).flat();
|
|
@@ -185,18 +199,38 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
185
199
|
if (!blockHash) {
|
|
186
200
|
throw new Error('Failed to read block hash from log entry buffer');
|
|
187
201
|
}
|
|
188
|
-
return
|
|
202
|
+
return new BlockHash(blockHash);
|
|
189
203
|
}
|
|
190
204
|
deleteLogs(blocks) {
|
|
191
205
|
return this.db.transactionAsync(async ()=>{
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
const blockNumbers = new Set(blocks.map((block)=>block.number));
|
|
207
|
+
const firstBlockToDelete = Math.min(...blockNumbers);
|
|
208
|
+
// Collect all unique private tags across all blocks being deleted
|
|
209
|
+
const allPrivateTags = new Set(compactArray(await Promise.all(blocks.map((block)=>this.#privateLogKeysByBlock.getAsync(block.number)))).flat());
|
|
210
|
+
// Trim private logs: for each tag, delete all instances including and after the first block being deleted.
|
|
211
|
+
// This hinges on the invariant that logs for a given tag are always inserted in order of block number, which is enforced in #addPrivateLogs.
|
|
212
|
+
for (const tag of allPrivateTags){
|
|
213
|
+
const existing = await this.#privateLogsByTag.getAsync(tag);
|
|
214
|
+
if (existing === undefined || existing.length === 0) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const lastIndexToKeep = existing.findLastIndex((buf)=>TxScopedL2Log.getBlockNumberFromBuffer(buf) < firstBlockToDelete);
|
|
218
|
+
const remaining = existing.slice(0, lastIndexToKeep + 1);
|
|
219
|
+
await (remaining.length > 0 ? this.#privateLogsByTag.set(tag, remaining) : this.#privateLogsByTag.delete(tag));
|
|
220
|
+
}
|
|
221
|
+
// Collect all unique public keys across all blocks being deleted
|
|
222
|
+
const allPublicKeys = new Set(compactArray(await Promise.all(blocks.map((block)=>this.#publicLogKeysByBlock.getAsync(block.number)))).flat());
|
|
223
|
+
// And do the same as we did with private logs
|
|
224
|
+
for (const key of allPublicKeys){
|
|
225
|
+
const existing = await this.#publicLogsByContractAndTag.getAsync(key);
|
|
226
|
+
if (existing === undefined || existing.length === 0) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const lastIndexToKeep = existing.findLastIndex((buf)=>TxScopedL2Log.getBlockNumberFromBuffer(buf) < firstBlockToDelete);
|
|
230
|
+
const remaining = existing.slice(0, lastIndexToKeep + 1);
|
|
231
|
+
await (remaining.length > 0 ? this.#publicLogsByContractAndTag.set(key, remaining) : this.#publicLogsByContractAndTag.delete(key));
|
|
232
|
+
}
|
|
233
|
+
// After trimming the tagged logs, we can delete the block-level keys that track which tags are in which blocks.
|
|
200
234
|
await Promise.all(blocks.map((block)=>Promise.all([
|
|
201
235
|
this.#publicLogsByBlock.delete(block.number),
|
|
202
236
|
this.#privateLogKeysByBlock.delete(block.number),
|
|
@@ -261,22 +295,24 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
261
295
|
};
|
|
262
296
|
}
|
|
263
297
|
const buffer = await this.#publicLogsByBlock.getAsync(blockNumber) ?? Buffer.alloc(0);
|
|
264
|
-
const publicLogsInBlock = [
|
|
265
|
-
[]
|
|
266
|
-
];
|
|
298
|
+
const publicLogsInBlock = [];
|
|
267
299
|
const reader = new BufferReader(buffer);
|
|
268
300
|
const blockHash = this.#unpackBlockHash(reader);
|
|
269
301
|
while(reader.remainingBytes() > 0){
|
|
270
302
|
const indexOfTx = reader.readNumber();
|
|
303
|
+
const txHash = reader.readObject(TxHash);
|
|
271
304
|
const numLogsInTx = reader.readNumber();
|
|
272
|
-
publicLogsInBlock[indexOfTx] =
|
|
305
|
+
publicLogsInBlock[indexOfTx] = {
|
|
306
|
+
txHash,
|
|
307
|
+
logs: []
|
|
308
|
+
};
|
|
273
309
|
for(let i = 0; i < numLogsInTx; i++){
|
|
274
|
-
publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
|
|
310
|
+
publicLogsInBlock[indexOfTx].logs.push(reader.readObject(PublicLog));
|
|
275
311
|
}
|
|
276
312
|
}
|
|
277
|
-
const
|
|
313
|
+
const txData = publicLogsInBlock[txIndex];
|
|
278
314
|
const logs = [];
|
|
279
|
-
const maxLogsHit = this.#
|
|
315
|
+
const maxLogsHit = this.#accumulatePublicLogs(logs, blockNumber, blockHash, txIndex, txData.txHash, txData.logs, filter);
|
|
280
316
|
return {
|
|
281
317
|
logs,
|
|
282
318
|
maxLogsHit
|
|
@@ -297,22 +333,24 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
297
333
|
start,
|
|
298
334
|
end
|
|
299
335
|
})){
|
|
300
|
-
const publicLogsInBlock = [
|
|
301
|
-
[]
|
|
302
|
-
];
|
|
336
|
+
const publicLogsInBlock = [];
|
|
303
337
|
const reader = new BufferReader(logBuffer);
|
|
304
338
|
const blockHash = this.#unpackBlockHash(reader);
|
|
305
339
|
while(reader.remainingBytes() > 0){
|
|
306
340
|
const indexOfTx = reader.readNumber();
|
|
341
|
+
const txHash = reader.readObject(TxHash);
|
|
307
342
|
const numLogsInTx = reader.readNumber();
|
|
308
|
-
publicLogsInBlock[indexOfTx] =
|
|
343
|
+
publicLogsInBlock[indexOfTx] = {
|
|
344
|
+
txHash,
|
|
345
|
+
logs: []
|
|
346
|
+
};
|
|
309
347
|
for(let i = 0; i < numLogsInTx; i++){
|
|
310
|
-
publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
|
|
348
|
+
publicLogsInBlock[indexOfTx].logs.push(reader.readObject(PublicLog));
|
|
311
349
|
}
|
|
312
350
|
}
|
|
313
351
|
for(let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < publicLogsInBlock.length; txIndex++){
|
|
314
|
-
const
|
|
315
|
-
maxLogsHit = this.#
|
|
352
|
+
const txData = publicLogsInBlock[txIndex];
|
|
353
|
+
maxLogsHit = this.#accumulatePublicLogs(logs, blockNumber, blockHash, txIndex, txData.txHash, txData.logs, filter);
|
|
316
354
|
if (maxLogsHit) {
|
|
317
355
|
this.#log.debug(`Max logs hit at block ${blockNumber}`);
|
|
318
356
|
break loopOverBlocks;
|
|
@@ -349,22 +387,24 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
349
387
|
};
|
|
350
388
|
}
|
|
351
389
|
const contractClassLogsBuffer = await this.#contractClassLogsByBlock.getAsync(blockNumber) ?? Buffer.alloc(0);
|
|
352
|
-
const contractClassLogsInBlock = [
|
|
353
|
-
[]
|
|
354
|
-
];
|
|
390
|
+
const contractClassLogsInBlock = [];
|
|
355
391
|
const reader = new BufferReader(contractClassLogsBuffer);
|
|
356
392
|
const blockHash = this.#unpackBlockHash(reader);
|
|
357
393
|
while(reader.remainingBytes() > 0){
|
|
358
394
|
const indexOfTx = reader.readNumber();
|
|
395
|
+
const txHash = reader.readObject(TxHash);
|
|
359
396
|
const numLogsInTx = reader.readNumber();
|
|
360
|
-
contractClassLogsInBlock[indexOfTx] =
|
|
397
|
+
contractClassLogsInBlock[indexOfTx] = {
|
|
398
|
+
txHash,
|
|
399
|
+
logs: []
|
|
400
|
+
};
|
|
361
401
|
for(let i = 0; i < numLogsInTx; i++){
|
|
362
|
-
contractClassLogsInBlock[indexOfTx].push(reader.readObject(ContractClassLog));
|
|
402
|
+
contractClassLogsInBlock[indexOfTx].logs.push(reader.readObject(ContractClassLog));
|
|
363
403
|
}
|
|
364
404
|
}
|
|
365
|
-
const
|
|
405
|
+
const txData = contractClassLogsInBlock[txIndex];
|
|
366
406
|
const logs = [];
|
|
367
|
-
const maxLogsHit = this.#
|
|
407
|
+
const maxLogsHit = this.#accumulateContractClassLogs(logs, blockNumber, blockHash, txIndex, txData.txHash, txData.logs, filter);
|
|
368
408
|
return {
|
|
369
409
|
logs,
|
|
370
410
|
maxLogsHit
|
|
@@ -385,22 +425,24 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
385
425
|
start,
|
|
386
426
|
end
|
|
387
427
|
})){
|
|
388
|
-
const contractClassLogsInBlock = [
|
|
389
|
-
[]
|
|
390
|
-
];
|
|
428
|
+
const contractClassLogsInBlock = [];
|
|
391
429
|
const reader = new BufferReader(logBuffer);
|
|
392
430
|
const blockHash = this.#unpackBlockHash(reader);
|
|
393
431
|
while(reader.remainingBytes() > 0){
|
|
394
432
|
const indexOfTx = reader.readNumber();
|
|
433
|
+
const txHash = reader.readObject(TxHash);
|
|
395
434
|
const numLogsInTx = reader.readNumber();
|
|
396
|
-
contractClassLogsInBlock[indexOfTx] =
|
|
435
|
+
contractClassLogsInBlock[indexOfTx] = {
|
|
436
|
+
txHash,
|
|
437
|
+
logs: []
|
|
438
|
+
};
|
|
397
439
|
for(let i = 0; i < numLogsInTx; i++){
|
|
398
|
-
contractClassLogsInBlock[indexOfTx].push(reader.readObject(ContractClassLog));
|
|
440
|
+
contractClassLogsInBlock[indexOfTx].logs.push(reader.readObject(ContractClassLog));
|
|
399
441
|
}
|
|
400
442
|
}
|
|
401
443
|
for(let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < contractClassLogsInBlock.length; txIndex++){
|
|
402
|
-
const
|
|
403
|
-
maxLogsHit = this.#
|
|
444
|
+
const txData = contractClassLogsInBlock[txIndex];
|
|
445
|
+
maxLogsHit = this.#accumulateContractClassLogs(logs, blockNumber, blockHash, txIndex, txData.txHash, txData.logs, filter);
|
|
404
446
|
if (maxLogsHit) {
|
|
405
447
|
this.#log.debug(`Max logs hit at block ${blockNumber}`);
|
|
406
448
|
break loopOverBlocks;
|
|
@@ -412,19 +454,46 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
|
|
|
412
454
|
maxLogsHit
|
|
413
455
|
};
|
|
414
456
|
}
|
|
415
|
-
#
|
|
457
|
+
#accumulatePublicLogs(results, blockNumber, blockHash, txIndex, txHash, txLogs, filter = {}) {
|
|
458
|
+
if (filter.fromBlock && blockNumber < filter.fromBlock) {
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
if (filter.toBlock && blockNumber >= filter.toBlock) {
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
if (filter.txHash && !txHash.equals(filter.txHash)) {
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
416
467
|
let maxLogsHit = false;
|
|
417
468
|
let logIndex = typeof filter.afterLog?.logIndex === 'number' ? filter.afterLog.logIndex + 1 : 0;
|
|
418
469
|
for(; logIndex < txLogs.length; logIndex++){
|
|
419
470
|
const log = txLogs[logIndex];
|
|
420
|
-
if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
} else {
|
|
426
|
-
throw new Error('Unknown log type');
|
|
471
|
+
if ((!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) && (!filter.tag || log.fields[0]?.equals(filter.tag))) {
|
|
472
|
+
results.push(new ExtendedPublicLog(new LogId(BlockNumber(blockNumber), blockHash, txHash, txIndex, logIndex), log));
|
|
473
|
+
if (results.length >= this.#logsMaxPageSize) {
|
|
474
|
+
maxLogsHit = true;
|
|
475
|
+
break;
|
|
427
476
|
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return maxLogsHit;
|
|
480
|
+
}
|
|
481
|
+
#accumulateContractClassLogs(results, blockNumber, blockHash, txIndex, txHash, txLogs, filter = {}) {
|
|
482
|
+
if (filter.fromBlock && blockNumber < filter.fromBlock) {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
if (filter.toBlock && blockNumber >= filter.toBlock) {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
if (filter.txHash && !txHash.equals(filter.txHash)) {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
let maxLogsHit = false;
|
|
492
|
+
let logIndex = typeof filter.afterLog?.logIndex === 'number' ? filter.afterLog.logIndex + 1 : 0;
|
|
493
|
+
for(; logIndex < txLogs.length; logIndex++){
|
|
494
|
+
const log = txLogs[logIndex];
|
|
495
|
+
if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
|
|
496
|
+
results.push(new ExtendedContractClassLog(new LogId(BlockNumber(blockNumber), blockHash, txHash, txIndex, logIndex), log));
|
|
428
497
|
if (results.length >= this.#logsMaxPageSize) {
|
|
429
498
|
maxLogsHit = true;
|
|
430
499
|
break;
|
|
@@ -87,7 +87,7 @@ export class MessageStore {
|
|
|
87
87
|
if (lastMessage && message.checkpointNumber === lastMessage.checkpointNumber && message.index !== lastMessage.index + 1n) {
|
|
88
88
|
throw new MessageStoreError(`Missing prior message for incoming L1 to L2 message ${message.leaf.toString()} ` + `with index ${message.index}`, message);
|
|
89
89
|
}
|
|
90
|
-
// Check the first message in a
|
|
90
|
+
// Check the first message in a checkpoint has the correct index.
|
|
91
91
|
if ((!lastMessage || message.checkpointNumber > lastMessage.checkpointNumber) && message.index !== expectedStart) {
|
|
92
92
|
throw new MessageStoreError(`Message ${message.leaf.toString()} for checkpoint ${message.checkpointNumber} has wrong index ` + `${message.index} (expected ${expectedStart})`, message);
|
|
93
93
|
}
|
|
@@ -91,7 +91,9 @@ export declare class FakeL1State {
|
|
|
91
91
|
private provenCheckpointNumber;
|
|
92
92
|
private targetCommitteeSize;
|
|
93
93
|
private version;
|
|
94
|
+
private canPruneResult;
|
|
94
95
|
private pendingCheckpointNumber;
|
|
96
|
+
private finalizedL1BlockNumber;
|
|
95
97
|
constructor(config: FakeL1StateConfig);
|
|
96
98
|
/**
|
|
97
99
|
* Adds messages for a checkpoint. Returns the message leaves.
|
|
@@ -124,16 +126,31 @@ export declare class FakeL1State {
|
|
|
124
126
|
* Auto-updates pending checkpoint number based on visible checkpoints.
|
|
125
127
|
*/
|
|
126
128
|
setL1BlockNumber(blockNumber: bigint): void;
|
|
129
|
+
/** Sets the L1 block number that will be reported as "finalized". */
|
|
130
|
+
setFinalizedL1BlockNumber(blockNumber: bigint): void;
|
|
127
131
|
/** Marks a checkpoint as proven. Updates provenCheckpointNumber. */
|
|
128
132
|
markCheckpointAsProven(checkpointNumber: CheckpointNumber): void;
|
|
133
|
+
/**
|
|
134
|
+
* Simulates what `rollup.getProvenCheckpointNumber({ blockNumber: atL1Block })` would return.
|
|
135
|
+
*/
|
|
136
|
+
getProvenCheckpointNumberAtL1Block(atL1Block: bigint): CheckpointNumber;
|
|
129
137
|
/** Sets the target committee size for attestation validation. */
|
|
130
138
|
setTargetCommitteeSize(size: number): void;
|
|
139
|
+
/** Sets whether the rollup contract would allow pruning at the next block. */
|
|
140
|
+
setCanPrune(value: boolean): void;
|
|
131
141
|
/**
|
|
132
142
|
* Removes all entries for a checkpoint number (simulates L1 reorg or prune).
|
|
133
143
|
* Note: Does NOT remove messages for this checkpoint (use numL1ToL2Messages: 0 when re-adding).
|
|
134
144
|
* Auto-updates pending status.
|
|
135
145
|
*/
|
|
136
146
|
removeCheckpoint(checkpointNumber: CheckpointNumber): void;
|
|
147
|
+
/**
|
|
148
|
+
* Moves a checkpoint to a different L1 block number (simulates L1 reorg that
|
|
149
|
+
* re-includes the same checkpoint transaction in a different block).
|
|
150
|
+
* The checkpoint content stays the same — only the L1 metadata changes.
|
|
151
|
+
* Auto-updates pending status.
|
|
152
|
+
*/
|
|
153
|
+
moveCheckpointToL1Block(checkpointNumber: CheckpointNumber, newL1BlockNumber: bigint): void;
|
|
137
154
|
/**
|
|
138
155
|
* Removes messages after a given total index (simulates L1 reorg).
|
|
139
156
|
* Auto-updates rolling hash.
|
|
@@ -183,8 +200,10 @@ export declare class FakeL1State {
|
|
|
183
200
|
private getCheckpointProposedLogs;
|
|
184
201
|
private getMessageSentLogs;
|
|
185
202
|
private makeRollupTx;
|
|
203
|
+
/** Extracts the CommitteeAttestations struct definition from RollupAbi for hash computation. */
|
|
204
|
+
private getCommitteeAttestationsStructDef;
|
|
186
205
|
private makeVersionedBlobHashes;
|
|
187
206
|
private makeBlobsFromCheckpoint;
|
|
188
207
|
}
|
|
189
208
|
export {};
|
|
190
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
209
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFrZV9sMV9zdGF0ZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvZmFrZV9sMV9zdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBcUQsTUFBTSxpQkFBaUIsQ0FBQztBQUMvRixPQUFPLEtBQUssRUFBeUIsYUFBYSxFQUFrQixjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUV0SCxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzlELE9BQU8sRUFBb0IsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFakcsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJDQUEyQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFHM0QsT0FBTyxFQUF5RCxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFTdEQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFN0QsT0FBTyxFQUFFLEtBQUssU0FBUyxFQUFRLE1BQU0sb0JBQW9CLENBQUM7QUFjMUQsMkNBQTJDO0FBQzNDLE1BQU0sTUFBTSxpQkFBaUIsR0FBRztJQUM5Qiw0QkFBNEI7SUFDNUIsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO0lBQ3ZCLDZCQUE2QjtJQUM3QixZQUFZLEVBQUUsTUFBTSxDQUFDO0lBQ3JCLGtDQUFrQztJQUNsQyxhQUFhLEVBQUUsTUFBTSxDQUFDO0lBQ3RCLHlDQUF5QztJQUN6QyxvQkFBb0IsRUFBRSxNQUFNLENBQUM7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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake_l1_state.d.ts","sourceRoot":"","sources":["../../src/test/fake_l1_state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,KAAK,IAAI,EAAqD,MAAM,iBAAiB,CAAC;AAC/F,OAAO,KAAK,EAAyB,aAAa,EAAkB,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEtH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAoB,gBAAgB,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAEjG,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAG3D,OAAO,EAAyD,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACrG,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"fake_l1_state.d.ts","sourceRoot":"","sources":["../../src/test/fake_l1_state.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,10 +7,11 @@ import { RollupAbi } from '@aztec/l1-artifacts';
|
|
|
7
7
|
import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
8
8
|
import { getSlotAtTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
9
9
|
import { InboxLeaf } from '@aztec/stdlib/messaging';
|
|
10
|
+
import { ConsensusPayload, SignatureDomainSeparator } from '@aztec/stdlib/p2p';
|
|
10
11
|
import { makeAndSignCommitteeAttestationsAndSigners, makeCheckpointAttestationFromCheckpoint, mockCheckpointAndMessages } from '@aztec/stdlib/testing';
|
|
11
12
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
12
13
|
import { mock } from 'jest-mock-extended';
|
|
13
|
-
import { encodeFunctionData, multicall3Abi, toHex } from 'viem';
|
|
14
|
+
import { encodeAbiParameters, encodeFunctionData, keccak256, multicall3Abi, toHex } from 'viem';
|
|
14
15
|
import { updateRollingHash } from '../structs/inbox_message.js';
|
|
15
16
|
/**
|
|
16
17
|
* Stateful fake for L1 data used by the archiver.
|
|
@@ -43,8 +44,11 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
43
44
|
provenCheckpointNumber;
|
|
44
45
|
targetCommitteeSize;
|
|
45
46
|
version;
|
|
47
|
+
canPruneResult;
|
|
46
48
|
// Computed from checkpoints based on L1 block visibility
|
|
47
49
|
pendingCheckpointNumber;
|
|
50
|
+
// The L1 block number reported as "finalized" (defaults to the start block)
|
|
51
|
+
finalizedL1BlockNumber;
|
|
48
52
|
constructor(config){
|
|
49
53
|
this.config = config;
|
|
50
54
|
this.log = createLogger('archiver:test:fake-l1');
|
|
@@ -54,8 +58,10 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
54
58
|
this.provenCheckpointNumber = CheckpointNumber(0);
|
|
55
59
|
this.targetCommitteeSize = 0;
|
|
56
60
|
this.version = 1n;
|
|
61
|
+
this.canPruneResult = false;
|
|
57
62
|
this.pendingCheckpointNumber = CheckpointNumber(0);
|
|
58
63
|
this.l1BlockNumber = config.l1StartBlock;
|
|
64
|
+
this.finalizedL1BlockNumber = config.l1StartBlock;
|
|
59
65
|
this.lastArchive = new AppendOnlyTreeSnapshot(config.genesisArchiveRoot, 1);
|
|
60
66
|
}
|
|
61
67
|
/**
|
|
@@ -98,10 +104,10 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
98
104
|
});
|
|
99
105
|
// Store the messages internally so they match the checkpoint's inHash
|
|
100
106
|
this.addMessages(checkpointNumber, messagesL1BlockNumber, messages);
|
|
101
|
-
// Create the transaction and
|
|
102
|
-
const tx = this.makeRollupTx(checkpoint, signers);
|
|
103
|
-
const blobHashes = this.makeVersionedBlobHashes(checkpoint);
|
|
104
|
-
const blobs = this.makeBlobsFromCheckpoint(checkpoint);
|
|
107
|
+
// Create the transaction, blobs, and event hashes
|
|
108
|
+
const { tx, attestationsHash, payloadDigest } = await this.makeRollupTx(checkpoint, signers);
|
|
109
|
+
const blobHashes = await this.makeVersionedBlobHashes(checkpoint);
|
|
110
|
+
const blobs = await this.makeBlobsFromCheckpoint(checkpoint);
|
|
105
111
|
// Store the checkpoint data
|
|
106
112
|
this.checkpoints.push({
|
|
107
113
|
checkpointNumber,
|
|
@@ -110,7 +116,9 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
110
116
|
tx,
|
|
111
117
|
blobHashes,
|
|
112
118
|
blobs,
|
|
113
|
-
signers
|
|
119
|
+
signers,
|
|
120
|
+
attestationsHash,
|
|
121
|
+
payloadDigest
|
|
114
122
|
});
|
|
115
123
|
// Update last archive for auto-chaining
|
|
116
124
|
this.lastArchive = lastArchive ?? checkpoint.blocks.at(-1).archive;
|
|
@@ -152,12 +160,30 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
152
160
|
this.l1BlockNumber = blockNumber;
|
|
153
161
|
this.updatePendingCheckpointNumber();
|
|
154
162
|
}
|
|
163
|
+
/** Sets the L1 block number that will be reported as "finalized". */ setFinalizedL1BlockNumber(blockNumber) {
|
|
164
|
+
this.finalizedL1BlockNumber = blockNumber;
|
|
165
|
+
}
|
|
155
166
|
/** Marks a checkpoint as proven. Updates provenCheckpointNumber. */ markCheckpointAsProven(checkpointNumber) {
|
|
156
167
|
this.provenCheckpointNumber = checkpointNumber;
|
|
157
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Simulates what `rollup.getProvenCheckpointNumber({ blockNumber: atL1Block })` would return.
|
|
171
|
+
*/ getProvenCheckpointNumberAtL1Block(atL1Block) {
|
|
172
|
+
if (this.provenCheckpointNumber === 0) {
|
|
173
|
+
return CheckpointNumber(0);
|
|
174
|
+
}
|
|
175
|
+
const checkpoint = this.checkpoints.find((cp)=>cp.checkpointNumber === this.provenCheckpointNumber);
|
|
176
|
+
if (checkpoint && checkpoint.l1BlockNumber <= atL1Block) {
|
|
177
|
+
return this.provenCheckpointNumber;
|
|
178
|
+
}
|
|
179
|
+
return CheckpointNumber(0);
|
|
180
|
+
}
|
|
158
181
|
/** Sets the target committee size for attestation validation. */ setTargetCommitteeSize(size) {
|
|
159
182
|
this.targetCommitteeSize = size;
|
|
160
183
|
}
|
|
184
|
+
/** Sets whether the rollup contract would allow pruning at the next block. */ setCanPrune(value) {
|
|
185
|
+
this.canPruneResult = value;
|
|
186
|
+
}
|
|
161
187
|
/**
|
|
162
188
|
* Removes all entries for a checkpoint number (simulates L1 reorg or prune).
|
|
163
189
|
* Note: Does NOT remove messages for this checkpoint (use numL1ToL2Messages: 0 when re-adding).
|
|
@@ -167,6 +193,19 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
167
193
|
this.updatePendingCheckpointNumber();
|
|
168
194
|
}
|
|
169
195
|
/**
|
|
196
|
+
* Moves a checkpoint to a different L1 block number (simulates L1 reorg that
|
|
197
|
+
* re-includes the same checkpoint transaction in a different block).
|
|
198
|
+
* The checkpoint content stays the same — only the L1 metadata changes.
|
|
199
|
+
* Auto-updates pending status.
|
|
200
|
+
*/ moveCheckpointToL1Block(checkpointNumber, newL1BlockNumber) {
|
|
201
|
+
for (const cpData of this.checkpoints){
|
|
202
|
+
if (cpData.checkpointNumber === checkpointNumber) {
|
|
203
|
+
cpData.l1BlockNumber = newL1BlockNumber;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
this.updatePendingCheckpointNumber();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
170
209
|
* Removes messages after a given total index (simulates L1 reorg).
|
|
171
210
|
* Auto-updates rolling hash.
|
|
172
211
|
*/ removeMessagesAfter(totalIndex) {
|
|
@@ -238,6 +277,11 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
238
277
|
archiveOfMyCheckpoint: this.getArchiveAt(localCheckpointNum)
|
|
239
278
|
});
|
|
240
279
|
});
|
|
280
|
+
mockRollup.getProvenCheckpointNumber.mockImplementation((options)=>{
|
|
281
|
+
const atBlock = options?.blockNumber ?? this.l1BlockNumber;
|
|
282
|
+
return Promise.resolve(this.getProvenCheckpointNumberAtL1Block(atBlock));
|
|
283
|
+
});
|
|
284
|
+
mockRollup.canPruneAtTime.mockImplementation(()=>Promise.resolve(this.canPruneResult));
|
|
241
285
|
// Mock the wrapper method for fetching checkpoint events
|
|
242
286
|
mockRollup.getCheckpointProposedEvents.mockImplementation((fromBlock, toBlock)=>Promise.resolve(this.getCheckpointProposedLogs(fromBlock, toBlock)));
|
|
243
287
|
Object.defineProperty(mockRollup, 'address', {
|
|
@@ -261,9 +305,13 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
261
305
|
const publicClient = mock();
|
|
262
306
|
publicClient.getChainId.mockResolvedValue(1);
|
|
263
307
|
publicClient.getBlockNumber.mockImplementation(()=>Promise.resolve(this.l1BlockNumber));
|
|
264
|
-
// Use async function pattern that existing test uses for getBlock
|
|
265
308
|
publicClient.getBlock.mockImplementation(async (args = {})=>{
|
|
266
|
-
|
|
309
|
+
let blockNum;
|
|
310
|
+
if (args.blockTag === 'finalized') {
|
|
311
|
+
blockNum = this.finalizedL1BlockNumber;
|
|
312
|
+
} else {
|
|
313
|
+
blockNum = args.blockNumber ?? await publicClient.getBlockNumber();
|
|
314
|
+
}
|
|
267
315
|
return {
|
|
268
316
|
number: blockNum,
|
|
269
317
|
timestamp: BigInt(blockNum) * BigInt(this.config.ethereumSlotDuration) + this.config.l1GenesisTime,
|
|
@@ -310,10 +358,8 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
310
358
|
checkpointNumber: cpData.checkpointNumber,
|
|
311
359
|
archive: cpData.checkpoint.archive.root,
|
|
312
360
|
versionedBlobHashes: cpData.blobHashes.map((h)=>Buffer.from(h.slice(2), 'hex')),
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
payloadDigest: undefined,
|
|
316
|
-
attestationsHash: undefined
|
|
361
|
+
attestationsHash: cpData.attestationsHash,
|
|
362
|
+
payloadDigest: cpData.payloadDigest
|
|
317
363
|
}
|
|
318
364
|
}));
|
|
319
365
|
}
|
|
@@ -330,13 +376,14 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
330
376
|
}
|
|
331
377
|
}));
|
|
332
378
|
}
|
|
333
|
-
makeRollupTx(checkpoint, signers) {
|
|
379
|
+
async makeRollupTx(checkpoint, signers) {
|
|
334
380
|
const attestations = signers.map((signer)=>makeCheckpointAttestationFromCheckpoint(checkpoint, signer)).map((attestation)=>CommitteeAttestation.fromSignature(attestation.signature)).map((committeeAttestation)=>committeeAttestation.toViem());
|
|
335
381
|
const header = checkpoint.header.toViem();
|
|
336
|
-
const blobInput = getPrefixedEthBlobCommitments(getBlobsPerL1Block(checkpoint.toBlobFields()));
|
|
382
|
+
const blobInput = getPrefixedEthBlobCommitments(await getBlobsPerL1Block(checkpoint.toBlobFields()));
|
|
337
383
|
const archive = toHex(checkpoint.archive.root.toBuffer());
|
|
338
384
|
const attestationsAndSigners = new CommitteeAttestationsAndSigners(attestations.map((attestation)=>CommitteeAttestation.fromViem(attestation)));
|
|
339
385
|
const attestationsAndSignersSignature = makeAndSignCommitteeAttestationsAndSigners(attestationsAndSigners, signers[0]);
|
|
386
|
+
const packedAttestations = attestationsAndSigners.getPackedAttestations();
|
|
340
387
|
const rollupInput = encodeFunctionData({
|
|
341
388
|
abi: RollupAbi,
|
|
342
389
|
functionName: 'propose',
|
|
@@ -348,7 +395,7 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
348
395
|
feeAssetPriceModifier: 0n
|
|
349
396
|
}
|
|
350
397
|
},
|
|
351
|
-
|
|
398
|
+
packedAttestations,
|
|
352
399
|
attestationsAndSigners.getSigners().map((signer)=>signer.toString()),
|
|
353
400
|
attestationsAndSignersSignature.toViemSignature(),
|
|
354
401
|
blobInput
|
|
@@ -367,17 +414,47 @@ import { updateRollingHash } from '../structs/inbox_message.js';
|
|
|
367
414
|
]
|
|
368
415
|
]
|
|
369
416
|
});
|
|
370
|
-
|
|
417
|
+
// Compute attestationsHash (same logic as CalldataRetriever)
|
|
418
|
+
const attestationsHash = Buffer32.fromString(keccak256(encodeAbiParameters([
|
|
419
|
+
this.getCommitteeAttestationsStructDef()
|
|
420
|
+
], [
|
|
421
|
+
packedAttestations
|
|
422
|
+
])));
|
|
423
|
+
// Compute payloadDigest (same logic as CalldataRetriever)
|
|
424
|
+
const consensusPayload = ConsensusPayload.fromCheckpoint(checkpoint);
|
|
425
|
+
const payloadToSign = consensusPayload.getPayloadToSign(SignatureDomainSeparator.checkpointAttestation);
|
|
426
|
+
const payloadDigest = Buffer32.fromString(keccak256(payloadToSign));
|
|
427
|
+
const tx = {
|
|
371
428
|
input: multiCallInput,
|
|
372
429
|
hash: archive,
|
|
373
430
|
blockHash: archive,
|
|
374
431
|
to: MULTI_CALL_3_ADDRESS
|
|
375
432
|
};
|
|
433
|
+
return {
|
|
434
|
+
tx,
|
|
435
|
+
attestationsHash,
|
|
436
|
+
payloadDigest
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
/** Extracts the CommitteeAttestations struct definition from RollupAbi for hash computation. */ getCommitteeAttestationsStructDef() {
|
|
440
|
+
const proposeFunction = RollupAbi.find((item)=>item.type === 'function' && item.name === 'propose');
|
|
441
|
+
if (!proposeFunction) {
|
|
442
|
+
throw new Error('propose function not found in RollupAbi');
|
|
443
|
+
}
|
|
444
|
+
const attestationsParam = proposeFunction.inputs.find((param)=>param.name === '_attestations');
|
|
445
|
+
if (!attestationsParam) {
|
|
446
|
+
throw new Error('_attestations parameter not found in propose function');
|
|
447
|
+
}
|
|
448
|
+
const tupleParam = attestationsParam;
|
|
449
|
+
return {
|
|
450
|
+
type: 'tuple',
|
|
451
|
+
components: tupleParam.components || []
|
|
452
|
+
};
|
|
376
453
|
}
|
|
377
|
-
makeVersionedBlobHashes(checkpoint) {
|
|
378
|
-
return getBlobsPerL1Block(checkpoint.toBlobFields()).map((b)=>`0x${b.getEthVersionedBlobHash().toString('hex')}`);
|
|
454
|
+
async makeVersionedBlobHashes(checkpoint) {
|
|
455
|
+
return (await getBlobsPerL1Block(checkpoint.toBlobFields())).map((b)=>`0x${b.getEthVersionedBlobHash().toString('hex')}`);
|
|
379
456
|
}
|
|
380
|
-
makeBlobsFromCheckpoint(checkpoint) {
|
|
381
|
-
return getBlobsPerL1Block(checkpoint.toBlobFields());
|
|
457
|
+
async makeBlobsFromCheckpoint(checkpoint) {
|
|
458
|
+
return await getBlobsPerL1Block(checkpoint.toBlobFields());
|
|
382
459
|
}
|
|
383
460
|
}
|