@aztec/sequencer-client 0.0.1-commit.7ac86ea28 → 0.0.1-commit.7b86788
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/publisher/config.d.ts +5 -1
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +6 -1
- package/dest/publisher/index.d.ts +2 -1
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/l1_tx_failed_store/factory.d.ts +11 -0
- package/dest/publisher/l1_tx_failed_store/factory.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/factory.js +22 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +59 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.js +1 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts +15 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.js +34 -0
- package/dest/publisher/l1_tx_failed_store/index.d.ts +4 -0
- package/dest/publisher/l1_tx_failed_store/index.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/index.js +2 -0
- package/dest/publisher/sequencer-publisher.d.ts +8 -2
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +217 -8
- package/dest/sequencer/checkpoint_proposal_job.d.ts +1 -1
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +8 -2
- package/dest/sequencer/timetable.js +1 -1
- package/package.json +28 -28
- package/src/publisher/config.ts +9 -0
- package/src/publisher/index.ts +3 -0
- package/src/publisher/l1_tx_failed_store/factory.ts +32 -0
- package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +55 -0
- package/src/publisher/l1_tx_failed_store/file_store_failed_tx_store.ts +46 -0
- package/src/publisher/l1_tx_failed_store/index.ts +3 -0
- package/src/publisher/sequencer-publisher.ts +178 -8
- package/src/sequencer/checkpoint_proposal_job.ts +14 -2
- package/src/sequencer/timetable.ts +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import type { FileStore } from '@aztec/stdlib/file-store';
|
|
3
|
+
|
|
4
|
+
import type { FailedL1Tx, FailedL1TxUri, L1TxFailedStore } from './failed_tx_store.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* L1TxFailedStore implementation using the FileStore abstraction.
|
|
8
|
+
* Supports any backend that FileStore supports (GCS, S3, R2, local filesystem).
|
|
9
|
+
*/
|
|
10
|
+
export class FileStoreL1TxFailedStore implements L1TxFailedStore {
|
|
11
|
+
private readonly log: Logger;
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
private readonly fileStore: FileStore,
|
|
15
|
+
logger?: Logger,
|
|
16
|
+
) {
|
|
17
|
+
this.log = logger ?? createLogger('sequencer:l1-tx-failed-store');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public async saveFailedTx(tx: FailedL1Tx): Promise<FailedL1TxUri> {
|
|
21
|
+
const prefix = tx.receipt ? 'tx' : 'data';
|
|
22
|
+
const path = `${tx.failureType}/${prefix}-${tx.id}.json`;
|
|
23
|
+
const json = JSON.stringify(tx, null, 2);
|
|
24
|
+
|
|
25
|
+
const uri = await this.fileStore.save(path, Buffer.from(json), {
|
|
26
|
+
metadata: {
|
|
27
|
+
'content-type': 'application/json',
|
|
28
|
+
actions: tx.context.actions.join(','),
|
|
29
|
+
'failure-type': tx.failureType,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
this.log.info(`Saved failed L1 tx to ${uri}`, {
|
|
34
|
+
id: tx.id,
|
|
35
|
+
failureType: tx.failureType,
|
|
36
|
+
actions: tx.context.actions.join(','),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return uri as FailedL1TxUri;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public async getFailedTx(uri: FailedL1TxUri): Promise<FailedL1Tx> {
|
|
43
|
+
const data = await this.fileStore.read(uri);
|
|
44
|
+
return JSON.parse(data.toString()) as FailedL1Tx;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -45,9 +45,19 @@ import type { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
|
45
45
|
import type { L1PublishCheckpointStats } from '@aztec/stdlib/stats';
|
|
46
46
|
import { type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
47
47
|
|
|
48
|
-
import {
|
|
48
|
+
import {
|
|
49
|
+
type Hex,
|
|
50
|
+
type StateOverride,
|
|
51
|
+
type TransactionReceipt,
|
|
52
|
+
type TypedDataDefinition,
|
|
53
|
+
encodeFunctionData,
|
|
54
|
+
keccak256,
|
|
55
|
+
multicall3Abi,
|
|
56
|
+
toHex,
|
|
57
|
+
} from 'viem';
|
|
49
58
|
|
|
50
59
|
import type { SequencerPublisherConfig } from './config.js';
|
|
60
|
+
import { type FailedL1Tx, type L1TxFailedStore, createL1TxFailedStore } from './l1_tx_failed_store/index.js';
|
|
51
61
|
import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js';
|
|
52
62
|
|
|
53
63
|
/** Arguments to the process method of the rollup contract */
|
|
@@ -109,6 +119,7 @@ export class SequencerPublisher {
|
|
|
109
119
|
private interrupted = false;
|
|
110
120
|
private metrics: SequencerPublisherMetrics;
|
|
111
121
|
public epochCache: EpochCache;
|
|
122
|
+
private failedTxStore?: Promise<L1TxFailedStore | undefined>;
|
|
112
123
|
|
|
113
124
|
protected governanceLog = createLogger('sequencer:publisher:governance');
|
|
114
125
|
protected slashingLog = createLogger('sequencer:publisher:slashing');
|
|
@@ -149,7 +160,7 @@ export class SequencerPublisher {
|
|
|
149
160
|
protected requests: RequestWithExpiry[] = [];
|
|
150
161
|
|
|
151
162
|
constructor(
|
|
152
|
-
private config: Pick<SequencerPublisherConfig, 'fishermanMode'> &
|
|
163
|
+
private config: Pick<SequencerPublisherConfig, 'fishermanMode' | 'l1TxFailedStore'> &
|
|
153
164
|
Pick<L1ContractsConfig, 'ethereumSlotDuration'> & { l1ChainId: number },
|
|
154
165
|
deps: {
|
|
155
166
|
telemetry?: TelemetryClient;
|
|
@@ -205,6 +216,31 @@ export class SequencerPublisher {
|
|
|
205
216
|
this.rollupContract,
|
|
206
217
|
createLogger('sequencer:publisher:price-oracle'),
|
|
207
218
|
);
|
|
219
|
+
|
|
220
|
+
// Initialize failed L1 tx store (optional, for test networks)
|
|
221
|
+
this.failedTxStore = createL1TxFailedStore(config.l1TxFailedStore, this.log);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Backs up a failed L1 transaction to the configured store for debugging.
|
|
226
|
+
* Does nothing if no store is configured.
|
|
227
|
+
*/
|
|
228
|
+
private backupFailedTx(failedTx: Omit<FailedL1Tx, 'timestamp'>): void {
|
|
229
|
+
if (!this.failedTxStore) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const tx: FailedL1Tx = {
|
|
234
|
+
...failedTx,
|
|
235
|
+
timestamp: Date.now(),
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// Fire and forget - don't block on backup
|
|
239
|
+
void this.failedTxStore
|
|
240
|
+
.then(store => store?.saveFailedTx(tx))
|
|
241
|
+
.catch(err => {
|
|
242
|
+
this.log.warn(`Failed to backup failed L1 tx to store`, err);
|
|
243
|
+
});
|
|
208
244
|
}
|
|
209
245
|
|
|
210
246
|
public getRollupContract(): RollupContract {
|
|
@@ -386,6 +422,21 @@ export class SequencerPublisher {
|
|
|
386
422
|
validRequests.sort((a, b) => compareActions(a.action, b.action));
|
|
387
423
|
|
|
388
424
|
try {
|
|
425
|
+
// Capture context for failed tx backup before sending
|
|
426
|
+
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
427
|
+
const multicallData = encodeFunctionData({
|
|
428
|
+
abi: multicall3Abi,
|
|
429
|
+
functionName: 'aggregate3',
|
|
430
|
+
args: [
|
|
431
|
+
validRequests.map(r => ({
|
|
432
|
+
target: r.request.to!,
|
|
433
|
+
callData: r.request.data!,
|
|
434
|
+
allowFailure: true,
|
|
435
|
+
})),
|
|
436
|
+
],
|
|
437
|
+
});
|
|
438
|
+
const blobDataHex = blobConfig?.blobs?.map(b => toHex(b)) as Hex[] | undefined;
|
|
439
|
+
|
|
389
440
|
this.log.debug('Forwarding transactions', {
|
|
390
441
|
validRequests: validRequests.map(request => request.action),
|
|
391
442
|
txConfig,
|
|
@@ -398,7 +449,12 @@ export class SequencerPublisher {
|
|
|
398
449
|
this.rollupContract.address,
|
|
399
450
|
this.log,
|
|
400
451
|
);
|
|
401
|
-
const
|
|
452
|
+
const txContext = { multicallData, blobData: blobDataHex, l1BlockNumber };
|
|
453
|
+
const { successfulActions = [], failedActions = [] } = this.callbackBundledTransactions(
|
|
454
|
+
validRequests,
|
|
455
|
+
result,
|
|
456
|
+
txContext,
|
|
457
|
+
);
|
|
402
458
|
return { result, expiredActions, sentActions: validActions, successfulActions, failedActions };
|
|
403
459
|
} catch (err) {
|
|
404
460
|
const viemError = formatViemError(err);
|
|
@@ -418,11 +474,25 @@ export class SequencerPublisher {
|
|
|
418
474
|
|
|
419
475
|
private callbackBundledTransactions(
|
|
420
476
|
requests: RequestWithExpiry[],
|
|
421
|
-
result
|
|
477
|
+
result: { receipt: TransactionReceipt; errorMsg?: string } | FormattedViemError | undefined,
|
|
478
|
+
txContext: { multicallData: Hex; blobData?: Hex[]; l1BlockNumber: bigint },
|
|
422
479
|
) {
|
|
423
480
|
const actionsListStr = requests.map(r => r.action).join(', ');
|
|
424
481
|
if (result instanceof FormattedViemError) {
|
|
425
482
|
this.log.error(`Failed to publish bundled transactions (${actionsListStr})`, result);
|
|
483
|
+
this.backupFailedTx({
|
|
484
|
+
id: keccak256(txContext.multicallData),
|
|
485
|
+
failureType: 'send-error',
|
|
486
|
+
request: { to: MULTI_CALL_3_ADDRESS, data: txContext.multicallData },
|
|
487
|
+
blobData: txContext.blobData,
|
|
488
|
+
l1BlockNumber: txContext.l1BlockNumber.toString(),
|
|
489
|
+
error: { message: result.message, name: result.name },
|
|
490
|
+
context: {
|
|
491
|
+
actions: requests.map(r => r.action),
|
|
492
|
+
requests: requests.map(r => ({ action: r.action, to: r.request.to! as Hex, data: r.request.data! })),
|
|
493
|
+
sender: this.getSenderAddress().toString(),
|
|
494
|
+
},
|
|
495
|
+
});
|
|
426
496
|
return { failedActions: requests.map(r => r.action) };
|
|
427
497
|
} else {
|
|
428
498
|
this.log.verbose(`Published bundled transactions (${actionsListStr})`, { result, requests });
|
|
@@ -435,6 +505,30 @@ export class SequencerPublisher {
|
|
|
435
505
|
failedActions.push(request.action);
|
|
436
506
|
}
|
|
437
507
|
}
|
|
508
|
+
// Single backup for the whole reverted tx
|
|
509
|
+
if (failedActions.length > 0 && result?.receipt?.status === 'reverted') {
|
|
510
|
+
this.backupFailedTx({
|
|
511
|
+
id: result.receipt.transactionHash,
|
|
512
|
+
failureType: 'revert',
|
|
513
|
+
request: { to: MULTI_CALL_3_ADDRESS, data: txContext.multicallData },
|
|
514
|
+
blobData: txContext.blobData,
|
|
515
|
+
l1BlockNumber: result.receipt.blockNumber.toString(),
|
|
516
|
+
receipt: {
|
|
517
|
+
transactionHash: result.receipt.transactionHash,
|
|
518
|
+
blockNumber: result.receipt.blockNumber.toString(),
|
|
519
|
+
gasUsed: (result.receipt.gasUsed ?? 0n).toString(),
|
|
520
|
+
status: 'reverted',
|
|
521
|
+
},
|
|
522
|
+
error: { message: result.errorMsg ?? 'Transaction reverted' },
|
|
523
|
+
context: {
|
|
524
|
+
actions: failedActions,
|
|
525
|
+
requests: requests
|
|
526
|
+
.filter(r => failedActions.includes(r.action))
|
|
527
|
+
.map(r => ({ action: r.action, to: r.request.to! as Hex, data: r.request.data! })),
|
|
528
|
+
sender: this.getSenderAddress().toString(),
|
|
529
|
+
},
|
|
530
|
+
});
|
|
531
|
+
}
|
|
438
532
|
return { successfulActions, failedActions };
|
|
439
533
|
}
|
|
440
534
|
}
|
|
@@ -546,6 +640,8 @@ export class SequencerPublisher {
|
|
|
546
640
|
const request = this.buildInvalidateCheckpointRequest(validationResult);
|
|
547
641
|
this.log.debug(`Simulating invalidate checkpoint ${checkpointNumber}`, { ...logData, request });
|
|
548
642
|
|
|
643
|
+
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
644
|
+
|
|
549
645
|
try {
|
|
550
646
|
const { gasUsed } = await this.l1TxUtils.simulate(
|
|
551
647
|
request,
|
|
@@ -597,6 +693,18 @@ export class SequencerPublisher {
|
|
|
597
693
|
|
|
598
694
|
// Otherwise, throw. We cannot build the next checkpoint if we cannot invalidate the previous one.
|
|
599
695
|
this.log.error(`Simulation for invalidate checkpoint ${checkpointNumber} failed`, viemError, logData);
|
|
696
|
+
this.backupFailedTx({
|
|
697
|
+
id: keccak256(request.data!),
|
|
698
|
+
failureType: 'simulation',
|
|
699
|
+
request: { to: request.to!, data: request.data!, value: request.value?.toString() },
|
|
700
|
+
l1BlockNumber: l1BlockNumber.toString(),
|
|
701
|
+
error: { message: viemError.message, name: viemError.name },
|
|
702
|
+
context: {
|
|
703
|
+
actions: [`invalidate-${reason}`],
|
|
704
|
+
checkpointNumber,
|
|
705
|
+
sender: this.getSenderAddress().toString(),
|
|
706
|
+
},
|
|
707
|
+
});
|
|
600
708
|
throw new Error(`Failed to simulate invalidate checkpoint ${checkpointNumber}`, { cause: viemError });
|
|
601
709
|
}
|
|
602
710
|
}
|
|
@@ -744,11 +852,26 @@ export class SequencerPublisher {
|
|
|
744
852
|
lastValidL2Slot: slotNumber,
|
|
745
853
|
});
|
|
746
854
|
|
|
855
|
+
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
856
|
+
|
|
747
857
|
try {
|
|
748
858
|
await this.l1TxUtils.simulate(request, { time: timestamp }, [], mergeAbis([request.abi ?? [], ErrorsAbi]));
|
|
749
859
|
this.log.debug(`Simulation for ${action} at slot ${slotNumber} succeeded`, { request });
|
|
750
860
|
} catch (err) {
|
|
751
|
-
|
|
861
|
+
const viemError = formatViemError(err);
|
|
862
|
+
this.log.error(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, viemError);
|
|
863
|
+
this.backupFailedTx({
|
|
864
|
+
id: keccak256(request.data!),
|
|
865
|
+
failureType: 'simulation',
|
|
866
|
+
request: { to: request.to!, data: request.data!, value: request.value?.toString() },
|
|
867
|
+
l1BlockNumber: l1BlockNumber.toString(),
|
|
868
|
+
error: { message: viemError.message, name: viemError.name },
|
|
869
|
+
context: {
|
|
870
|
+
actions: [action],
|
|
871
|
+
slot: slotNumber,
|
|
872
|
+
sender: this.getSenderAddress().toString(),
|
|
873
|
+
},
|
|
874
|
+
});
|
|
752
875
|
// Yes, we enqueue the request anyway, in case there was a bug with the simulation itself
|
|
753
876
|
}
|
|
754
877
|
|
|
@@ -1044,6 +1167,8 @@ export class SequencerPublisher {
|
|
|
1044
1167
|
|
|
1045
1168
|
this.log.debug(`Simulating ${action} for slot ${slotNumber}`, logData);
|
|
1046
1169
|
|
|
1170
|
+
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1171
|
+
|
|
1047
1172
|
let gasUsed: bigint;
|
|
1048
1173
|
const simulateAbi = mergeAbis([request.abi ?? [], ErrorsAbi]);
|
|
1049
1174
|
try {
|
|
@@ -1053,6 +1178,19 @@ export class SequencerPublisher {
|
|
|
1053
1178
|
const viemError = formatViemError(err, simulateAbi);
|
|
1054
1179
|
this.log.error(`Simulation for ${action} at ${slotNumber} failed`, viemError, logData);
|
|
1055
1180
|
|
|
1181
|
+
this.backupFailedTx({
|
|
1182
|
+
id: keccak256(request.data!),
|
|
1183
|
+
failureType: 'simulation',
|
|
1184
|
+
request: { to: request.to!, data: request.data!, value: request.value?.toString() },
|
|
1185
|
+
l1BlockNumber: l1BlockNumber.toString(),
|
|
1186
|
+
error: { message: viemError.message, name: viemError.name },
|
|
1187
|
+
context: {
|
|
1188
|
+
actions: [action],
|
|
1189
|
+
slot: slotNumber,
|
|
1190
|
+
sender: this.getSenderAddress().toString(),
|
|
1191
|
+
},
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1056
1194
|
return false;
|
|
1057
1195
|
}
|
|
1058
1196
|
|
|
@@ -1136,9 +1274,27 @@ export class SequencerPublisher {
|
|
|
1136
1274
|
kzg,
|
|
1137
1275
|
},
|
|
1138
1276
|
)
|
|
1139
|
-
.catch(err => {
|
|
1140
|
-
const
|
|
1141
|
-
this.log.error(`Failed to validate blobs`, message, { metaMessages });
|
|
1277
|
+
.catch(async err => {
|
|
1278
|
+
const viemError = formatViemError(err);
|
|
1279
|
+
this.log.error(`Failed to validate blobs`, viemError.message, { metaMessages: viemError.metaMessages });
|
|
1280
|
+
const validateBlobsData = encodeFunctionData({
|
|
1281
|
+
abi: RollupAbi,
|
|
1282
|
+
functionName: 'validateBlobs',
|
|
1283
|
+
args: [blobInput],
|
|
1284
|
+
});
|
|
1285
|
+
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1286
|
+
this.backupFailedTx({
|
|
1287
|
+
id: keccak256(validateBlobsData),
|
|
1288
|
+
failureType: 'simulation',
|
|
1289
|
+
request: { to: this.rollupContract.address as Hex, data: validateBlobsData },
|
|
1290
|
+
blobData: encodedData.blobs.map(b => toHex(b.data)) as Hex[],
|
|
1291
|
+
l1BlockNumber: l1BlockNumber.toString(),
|
|
1292
|
+
error: { message: viemError.message, name: viemError.name },
|
|
1293
|
+
context: {
|
|
1294
|
+
actions: ['validate-blobs'],
|
|
1295
|
+
sender: this.getSenderAddress().toString(),
|
|
1296
|
+
},
|
|
1297
|
+
});
|
|
1142
1298
|
throw new Error('Failed to validate blobs');
|
|
1143
1299
|
});
|
|
1144
1300
|
}
|
|
@@ -1217,6 +1373,8 @@ export class SequencerPublisher {
|
|
|
1217
1373
|
});
|
|
1218
1374
|
}
|
|
1219
1375
|
|
|
1376
|
+
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1377
|
+
|
|
1220
1378
|
const simulationResult = await this.l1TxUtils
|
|
1221
1379
|
.simulate(
|
|
1222
1380
|
{
|
|
@@ -1250,6 +1408,18 @@ export class SequencerPublisher {
|
|
|
1250
1408
|
};
|
|
1251
1409
|
}
|
|
1252
1410
|
this.log.error(`Failed to simulate propose tx`, viemError);
|
|
1411
|
+
this.backupFailedTx({
|
|
1412
|
+
id: keccak256(rollupData),
|
|
1413
|
+
failureType: 'simulation',
|
|
1414
|
+
request: { to: this.rollupContract.address, data: rollupData },
|
|
1415
|
+
l1BlockNumber: l1BlockNumber.toString(),
|
|
1416
|
+
error: { message: viemError.message, name: viemError.name },
|
|
1417
|
+
context: {
|
|
1418
|
+
actions: ['propose'],
|
|
1419
|
+
slot: Number(args[0].header.slotNumber),
|
|
1420
|
+
sender: this.getSenderAddress().toString(),
|
|
1421
|
+
},
|
|
1422
|
+
});
|
|
1253
1423
|
throw err;
|
|
1254
1424
|
});
|
|
1255
1425
|
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
} from '@aztec/stdlib/interfaces/server';
|
|
39
39
|
import { type L1ToL2MessageSource, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
40
40
|
import type { BlockProposalOptions, CheckpointProposal, CheckpointProposalOptions } from '@aztec/stdlib/p2p';
|
|
41
|
-
import { orderAttestations } from '@aztec/stdlib/p2p';
|
|
41
|
+
import { orderAttestations, trimAttestations } from '@aztec/stdlib/p2p';
|
|
42
42
|
import type { L2BlockBuiltStats } from '@aztec/stdlib/stats';
|
|
43
43
|
import { type FailedTx, Tx } from '@aztec/stdlib/tx';
|
|
44
44
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
@@ -743,8 +743,20 @@ export class CheckpointProposalJob implements Traceable {
|
|
|
743
743
|
|
|
744
744
|
collectedAttestationsCount = attestations.length;
|
|
745
745
|
|
|
746
|
+
// Trim attestations to minimum required to save L1 calldata gas
|
|
747
|
+
const localAddresses = this.validatorClient.getValidatorAddresses();
|
|
748
|
+
const trimmed = trimAttestations(
|
|
749
|
+
attestations,
|
|
750
|
+
numberOfRequiredAttestations,
|
|
751
|
+
this.attestorAddress,
|
|
752
|
+
localAddresses,
|
|
753
|
+
);
|
|
754
|
+
if (trimmed.length < attestations.length) {
|
|
755
|
+
this.log.debug(`Trimmed attestations from ${attestations.length} to ${trimmed.length} for L1 submission`);
|
|
756
|
+
}
|
|
757
|
+
|
|
746
758
|
// Rollup contract requires that the signatures are provided in the order of the committee
|
|
747
|
-
const sorted = orderAttestations(
|
|
759
|
+
const sorted = orderAttestations(trimmed, committee);
|
|
748
760
|
|
|
749
761
|
// Manipulate the attestations if we've been configured to do so
|
|
750
762
|
if (this.config.injectFakeAttestation || this.config.shuffleAttestationOrdering) {
|
|
@@ -132,7 +132,7 @@ export class SequencerTimetable {
|
|
|
132
132
|
const initializeDeadline = this.aztecSlotDuration - minWorkToDo;
|
|
133
133
|
this.initializeDeadline = initializeDeadline;
|
|
134
134
|
|
|
135
|
-
this.log.
|
|
135
|
+
this.log.info(
|
|
136
136
|
`Sequencer timetable initialized with ${this.maxNumberOfBlocks} blocks per slot (${this.enforce ? 'enforced' : 'not enforced'})`,
|
|
137
137
|
{
|
|
138
138
|
ethereumSlotDuration: this.ethereumSlotDuration,
|