@aztec/sequencer-client 0.0.1-commit.358457c → 0.0.1-commit.381b1a9
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/client/sequencer-client.d.ts +12 -1
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +85 -13
- package/dest/config.d.ts +23 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +23 -16
- package/dest/publisher/config.d.ts +1 -5
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +1 -6
- package/dest/publisher/index.d.ts +1 -2
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.d.ts +2 -8
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +8 -217
- package/dest/sequencer/checkpoint_proposal_job.d.ts +2 -4
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +60 -44
- package/dest/sequencer/sequencer.d.ts +10 -7
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +12 -14
- package/dest/sequencer/timetable.d.ts +4 -3
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +6 -7
- package/dest/sequencer/types.d.ts +2 -2
- package/dest/sequencer/types.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.d.ts +10 -8
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.js +41 -30
- package/package.json +28 -28
- package/src/client/sequencer-client.ts +111 -12
- package/src/config.ts +28 -19
- package/src/publisher/config.ts +0 -9
- package/src/publisher/index.ts +0 -3
- package/src/publisher/sequencer-publisher.ts +8 -178
- package/src/sequencer/checkpoint_proposal_job.ts +90 -55
- package/src/sequencer/sequencer.ts +13 -15
- package/src/sequencer/timetable.ts +7 -7
- package/src/sequencer/types.ts +1 -1
- package/src/test/mock_checkpoint_builder.ts +52 -47
- package/dest/publisher/l1_tx_failed_store/factory.d.ts +0 -11
- package/dest/publisher/l1_tx_failed_store/factory.d.ts.map +0 -1
- package/dest/publisher/l1_tx_failed_store/factory.js +0 -22
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +0 -59
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +0 -1
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.js +0 -1
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts +0 -15
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts.map +0 -1
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.js +0 -34
- package/dest/publisher/l1_tx_failed_store/index.d.ts +0 -4
- package/dest/publisher/l1_tx_failed_store/index.d.ts.map +0 -1
- package/dest/publisher/l1_tx_failed_store/index.js +0 -2
- package/src/publisher/l1_tx_failed_store/factory.ts +0 -32
- package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +0 -55
- package/src/publisher/l1_tx_failed_store/file_store_failed_tx_store.ts +0 -46
- package/src/publisher/l1_tx_failed_store/index.ts +0 -3
|
@@ -390,8 +390,7 @@ import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
|
390
390
|
import { encodeSlashConsensusVotes } from '@aztec/slasher';
|
|
391
391
|
import { CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
392
392
|
import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
393
|
-
import { encodeFunctionData,
|
|
394
|
-
import { createL1TxFailedStore } from './l1_tx_failed_store/index.js';
|
|
393
|
+
import { encodeFunctionData, toHex } from 'viem';
|
|
395
394
|
import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js';
|
|
396
395
|
export const Actions = [
|
|
397
396
|
'invalidate-by-invalid-attestation',
|
|
@@ -431,7 +430,6 @@ export class SequencerPublisher {
|
|
|
431
430
|
interrupted;
|
|
432
431
|
metrics;
|
|
433
432
|
epochCache;
|
|
434
|
-
failedTxStore;
|
|
435
433
|
governanceLog;
|
|
436
434
|
slashingLog;
|
|
437
435
|
lastActions;
|
|
@@ -487,24 +485,6 @@ export class SequencerPublisher {
|
|
|
487
485
|
}
|
|
488
486
|
// Initialize fee asset price oracle
|
|
489
487
|
this.feeAssetPriceOracle = new FeeAssetPriceOracle(this.l1TxUtils.client, this.rollupContract, createLogger('sequencer:publisher:price-oracle'));
|
|
490
|
-
// Initialize failed L1 tx store (optional, for test networks)
|
|
491
|
-
this.failedTxStore = createL1TxFailedStore(config.l1TxFailedStore, this.log);
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Backs up a failed L1 transaction to the configured store for debugging.
|
|
495
|
-
* Does nothing if no store is configured.
|
|
496
|
-
*/ backupFailedTx(failedTx) {
|
|
497
|
-
if (!this.failedTxStore) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
const tx = {
|
|
501
|
-
...failedTx,
|
|
502
|
-
timestamp: Date.now()
|
|
503
|
-
};
|
|
504
|
-
// Fire and forget - don't block on backup
|
|
505
|
-
void this.failedTxStore.then((store)=>store?.saveFailedTx(tx)).catch((err)=>{
|
|
506
|
-
this.log.warn(`Failed to backup failed L1 tx to store`, err);
|
|
507
|
-
});
|
|
508
488
|
}
|
|
509
489
|
getRollupContract() {
|
|
510
490
|
return this.rollupContract;
|
|
@@ -650,31 +630,12 @@ export class SequencerPublisher {
|
|
|
650
630
|
// This ensures the committee gets precomputed correctly
|
|
651
631
|
validRequests.sort((a, b)=>compareActions(a.action, b.action));
|
|
652
632
|
try {
|
|
653
|
-
// Capture context for failed tx backup before sending
|
|
654
|
-
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
655
|
-
const multicallData = encodeFunctionData({
|
|
656
|
-
abi: multicall3Abi,
|
|
657
|
-
functionName: 'aggregate3',
|
|
658
|
-
args: [
|
|
659
|
-
validRequests.map((r)=>({
|
|
660
|
-
target: r.request.to,
|
|
661
|
-
callData: r.request.data,
|
|
662
|
-
allowFailure: true
|
|
663
|
-
}))
|
|
664
|
-
]
|
|
665
|
-
});
|
|
666
|
-
const blobDataHex = blobConfig?.blobs?.map((b)=>toHex(b));
|
|
667
633
|
this.log.debug('Forwarding transactions', {
|
|
668
634
|
validRequests: validRequests.map((request)=>request.action),
|
|
669
635
|
txConfig
|
|
670
636
|
});
|
|
671
637
|
const result = await Multicall3.forward(validRequests.map((request)=>request.request), this.l1TxUtils, txConfig, blobConfig, this.rollupContract.address, this.log);
|
|
672
|
-
const
|
|
673
|
-
multicallData,
|
|
674
|
-
blobData: blobDataHex,
|
|
675
|
-
l1BlockNumber
|
|
676
|
-
};
|
|
677
|
-
const { successfulActions = [], failedActions = [] } = this.callbackBundledTransactions(validRequests, result, txContext);
|
|
638
|
+
const { successfulActions = [], failedActions = [] } = this.callbackBundledTransactions(validRequests, result);
|
|
678
639
|
return {
|
|
679
640
|
result,
|
|
680
641
|
expiredActions,
|
|
@@ -694,33 +655,10 @@ export class SequencerPublisher {
|
|
|
694
655
|
}
|
|
695
656
|
}
|
|
696
657
|
}
|
|
697
|
-
callbackBundledTransactions(requests, result
|
|
658
|
+
callbackBundledTransactions(requests, result) {
|
|
698
659
|
const actionsListStr = requests.map((r)=>r.action).join(', ');
|
|
699
660
|
if (result instanceof FormattedViemError) {
|
|
700
661
|
this.log.error(`Failed to publish bundled transactions (${actionsListStr})`, result);
|
|
701
|
-
this.backupFailedTx({
|
|
702
|
-
id: keccak256(txContext.multicallData),
|
|
703
|
-
failureType: 'send-error',
|
|
704
|
-
request: {
|
|
705
|
-
to: MULTI_CALL_3_ADDRESS,
|
|
706
|
-
data: txContext.multicallData
|
|
707
|
-
},
|
|
708
|
-
blobData: txContext.blobData,
|
|
709
|
-
l1BlockNumber: txContext.l1BlockNumber.toString(),
|
|
710
|
-
error: {
|
|
711
|
-
message: result.message,
|
|
712
|
-
name: result.name
|
|
713
|
-
},
|
|
714
|
-
context: {
|
|
715
|
-
actions: requests.map((r)=>r.action),
|
|
716
|
-
requests: requests.map((r)=>({
|
|
717
|
-
action: r.action,
|
|
718
|
-
to: r.request.to,
|
|
719
|
-
data: r.request.data
|
|
720
|
-
})),
|
|
721
|
-
sender: this.getSenderAddress().toString()
|
|
722
|
-
}
|
|
723
|
-
});
|
|
724
662
|
return {
|
|
725
663
|
failedActions: requests.map((r)=>r.action)
|
|
726
664
|
};
|
|
@@ -738,37 +676,6 @@ export class SequencerPublisher {
|
|
|
738
676
|
failedActions.push(request.action);
|
|
739
677
|
}
|
|
740
678
|
}
|
|
741
|
-
// Single backup for the whole reverted tx
|
|
742
|
-
if (failedActions.length > 0 && result?.receipt?.status === 'reverted') {
|
|
743
|
-
this.backupFailedTx({
|
|
744
|
-
id: result.receipt.transactionHash,
|
|
745
|
-
failureType: 'revert',
|
|
746
|
-
request: {
|
|
747
|
-
to: MULTI_CALL_3_ADDRESS,
|
|
748
|
-
data: txContext.multicallData
|
|
749
|
-
},
|
|
750
|
-
blobData: txContext.blobData,
|
|
751
|
-
l1BlockNumber: result.receipt.blockNumber.toString(),
|
|
752
|
-
receipt: {
|
|
753
|
-
transactionHash: result.receipt.transactionHash,
|
|
754
|
-
blockNumber: result.receipt.blockNumber.toString(),
|
|
755
|
-
gasUsed: (result.receipt.gasUsed ?? 0n).toString(),
|
|
756
|
-
status: 'reverted'
|
|
757
|
-
},
|
|
758
|
-
error: {
|
|
759
|
-
message: result.errorMsg ?? 'Transaction reverted'
|
|
760
|
-
},
|
|
761
|
-
context: {
|
|
762
|
-
actions: failedActions,
|
|
763
|
-
requests: requests.filter((r)=>failedActions.includes(r.action)).map((r)=>({
|
|
764
|
-
action: r.action,
|
|
765
|
-
to: r.request.to,
|
|
766
|
-
data: r.request.data
|
|
767
|
-
})),
|
|
768
|
-
sender: this.getSenderAddress().toString()
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
679
|
return {
|
|
773
680
|
successfulActions,
|
|
774
681
|
failedActions
|
|
@@ -871,7 +778,6 @@ export class SequencerPublisher {
|
|
|
871
778
|
...logData,
|
|
872
779
|
request
|
|
873
780
|
});
|
|
874
|
-
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
875
781
|
try {
|
|
876
782
|
const { gasUsed } = await this.l1TxUtils.simulate(request, undefined, undefined, mergeAbis([
|
|
877
783
|
request.abi ?? [],
|
|
@@ -914,27 +820,6 @@ export class SequencerPublisher {
|
|
|
914
820
|
}
|
|
915
821
|
// Otherwise, throw. We cannot build the next checkpoint if we cannot invalidate the previous one.
|
|
916
822
|
this.log.error(`Simulation for invalidate checkpoint ${checkpointNumber} failed`, viemError, logData);
|
|
917
|
-
this.backupFailedTx({
|
|
918
|
-
id: keccak256(request.data),
|
|
919
|
-
failureType: 'simulation',
|
|
920
|
-
request: {
|
|
921
|
-
to: request.to,
|
|
922
|
-
data: request.data,
|
|
923
|
-
value: request.value?.toString()
|
|
924
|
-
},
|
|
925
|
-
l1BlockNumber: l1BlockNumber.toString(),
|
|
926
|
-
error: {
|
|
927
|
-
message: viemError.message,
|
|
928
|
-
name: viemError.name
|
|
929
|
-
},
|
|
930
|
-
context: {
|
|
931
|
-
actions: [
|
|
932
|
-
`invalidate-${reason}`
|
|
933
|
-
],
|
|
934
|
-
checkpointNumber,
|
|
935
|
-
sender: this.getSenderAddress().toString()
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
823
|
throw new Error(`Failed to simulate invalidate checkpoint ${checkpointNumber}`, {
|
|
939
824
|
cause: viemError
|
|
940
825
|
});
|
|
@@ -1037,7 +922,6 @@ export class SequencerPublisher {
|
|
|
1037
922
|
signer: this.l1TxUtils.client.account?.address,
|
|
1038
923
|
lastValidL2Slot: slotNumber
|
|
1039
924
|
});
|
|
1040
|
-
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1041
925
|
try {
|
|
1042
926
|
await this.l1TxUtils.simulate(request, {
|
|
1043
927
|
time: timestamp
|
|
@@ -1049,29 +933,7 @@ export class SequencerPublisher {
|
|
|
1049
933
|
request
|
|
1050
934
|
});
|
|
1051
935
|
} catch (err) {
|
|
1052
|
-
|
|
1053
|
-
this.log.error(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, viemError);
|
|
1054
|
-
this.backupFailedTx({
|
|
1055
|
-
id: keccak256(request.data),
|
|
1056
|
-
failureType: 'simulation',
|
|
1057
|
-
request: {
|
|
1058
|
-
to: request.to,
|
|
1059
|
-
data: request.data,
|
|
1060
|
-
value: request.value?.toString()
|
|
1061
|
-
},
|
|
1062
|
-
l1BlockNumber: l1BlockNumber.toString(),
|
|
1063
|
-
error: {
|
|
1064
|
-
message: viemError.message,
|
|
1065
|
-
name: viemError.name
|
|
1066
|
-
},
|
|
1067
|
-
context: {
|
|
1068
|
-
actions: [
|
|
1069
|
-
action
|
|
1070
|
-
],
|
|
1071
|
-
slot: slotNumber,
|
|
1072
|
-
sender: this.getSenderAddress().toString()
|
|
1073
|
-
}
|
|
1074
|
-
});
|
|
936
|
+
this.log.error(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, err);
|
|
1075
937
|
// Yes, we enqueue the request anyway, in case there was a bug with the simulation itself
|
|
1076
938
|
}
|
|
1077
939
|
// TODO(palla/slash): All votes (governance and slashing) should txTimeoutAt at the end of the slot.
|
|
@@ -1293,7 +1155,6 @@ export class SequencerPublisher {
|
|
|
1293
1155
|
const cachedLastActionSlot = this.lastActions[action];
|
|
1294
1156
|
this.lastActions[action] = slotNumber;
|
|
1295
1157
|
this.log.debug(`Simulating ${action} for slot ${slotNumber}`, logData);
|
|
1296
|
-
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1297
1158
|
let gasUsed;
|
|
1298
1159
|
const simulateAbi = mergeAbis([
|
|
1299
1160
|
request.abi ?? [],
|
|
@@ -1311,27 +1172,6 @@ export class SequencerPublisher {
|
|
|
1311
1172
|
} catch (err) {
|
|
1312
1173
|
const viemError = formatViemError(err, simulateAbi);
|
|
1313
1174
|
this.log.error(`Simulation for ${action} at ${slotNumber} failed`, viemError, logData);
|
|
1314
|
-
this.backupFailedTx({
|
|
1315
|
-
id: keccak256(request.data),
|
|
1316
|
-
failureType: 'simulation',
|
|
1317
|
-
request: {
|
|
1318
|
-
to: request.to,
|
|
1319
|
-
data: request.data,
|
|
1320
|
-
value: request.value?.toString()
|
|
1321
|
-
},
|
|
1322
|
-
l1BlockNumber: l1BlockNumber.toString(),
|
|
1323
|
-
error: {
|
|
1324
|
-
message: viemError.message,
|
|
1325
|
-
name: viemError.name
|
|
1326
|
-
},
|
|
1327
|
-
context: {
|
|
1328
|
-
actions: [
|
|
1329
|
-
action
|
|
1330
|
-
],
|
|
1331
|
-
slot: slotNumber,
|
|
1332
|
-
sender: this.getSenderAddress().toString()
|
|
1333
|
-
}
|
|
1334
|
-
});
|
|
1335
1175
|
return false;
|
|
1336
1176
|
}
|
|
1337
1177
|
// We issued the simulation against the rollup contract, so we need to account for the overhead of the multicall3
|
|
@@ -1410,38 +1250,10 @@ export class SequencerPublisher {
|
|
|
1410
1250
|
}, {}, {
|
|
1411
1251
|
blobs: encodedData.blobs.map((b)=>b.data),
|
|
1412
1252
|
kzg
|
|
1413
|
-
}).catch(
|
|
1414
|
-
const
|
|
1415
|
-
this.log.error(`Failed to validate blobs`,
|
|
1416
|
-
metaMessages
|
|
1417
|
-
});
|
|
1418
|
-
const validateBlobsData = encodeFunctionData({
|
|
1419
|
-
abi: RollupAbi,
|
|
1420
|
-
functionName: 'validateBlobs',
|
|
1421
|
-
args: [
|
|
1422
|
-
blobInput
|
|
1423
|
-
]
|
|
1424
|
-
});
|
|
1425
|
-
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1426
|
-
this.backupFailedTx({
|
|
1427
|
-
id: keccak256(validateBlobsData),
|
|
1428
|
-
failureType: 'simulation',
|
|
1429
|
-
request: {
|
|
1430
|
-
to: this.rollupContract.address,
|
|
1431
|
-
data: validateBlobsData
|
|
1432
|
-
},
|
|
1433
|
-
blobData: encodedData.blobs.map((b)=>toHex(b.data)),
|
|
1434
|
-
l1BlockNumber: l1BlockNumber.toString(),
|
|
1435
|
-
error: {
|
|
1436
|
-
message: viemError.message,
|
|
1437
|
-
name: viemError.name
|
|
1438
|
-
},
|
|
1439
|
-
context: {
|
|
1440
|
-
actions: [
|
|
1441
|
-
'validate-blobs'
|
|
1442
|
-
],
|
|
1443
|
-
sender: this.getSenderAddress().toString()
|
|
1444
|
-
}
|
|
1253
|
+
}).catch((err)=>{
|
|
1254
|
+
const { message, metaMessages } = formatViemError(err);
|
|
1255
|
+
this.log.error(`Failed to validate blobs`, message, {
|
|
1256
|
+
metaMessages
|
|
1445
1257
|
});
|
|
1446
1258
|
throw new Error('Failed to validate blobs');
|
|
1447
1259
|
});
|
|
@@ -1501,7 +1313,6 @@ export class SequencerPublisher {
|
|
|
1501
1313
|
balance: 10n * WEI_CONST * WEI_CONST
|
|
1502
1314
|
});
|
|
1503
1315
|
}
|
|
1504
|
-
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1505
1316
|
const simulationResult = await this.l1TxUtils.simulate({
|
|
1506
1317
|
to: this.rollupContract.address,
|
|
1507
1318
|
data: rollupData,
|
|
@@ -1529,26 +1340,6 @@ export class SequencerPublisher {
|
|
|
1529
1340
|
};
|
|
1530
1341
|
}
|
|
1531
1342
|
this.log.error(`Failed to simulate propose tx`, viemError);
|
|
1532
|
-
this.backupFailedTx({
|
|
1533
|
-
id: keccak256(rollupData),
|
|
1534
|
-
failureType: 'simulation',
|
|
1535
|
-
request: {
|
|
1536
|
-
to: this.rollupContract.address,
|
|
1537
|
-
data: rollupData
|
|
1538
|
-
},
|
|
1539
|
-
l1BlockNumber: l1BlockNumber.toString(),
|
|
1540
|
-
error: {
|
|
1541
|
-
message: viemError.message,
|
|
1542
|
-
name: viemError.name
|
|
1543
|
-
},
|
|
1544
|
-
context: {
|
|
1545
|
-
actions: [
|
|
1546
|
-
'propose'
|
|
1547
|
-
],
|
|
1548
|
-
slot: Number(args[0].header.slotNumber),
|
|
1549
|
-
sender: this.getSenderAddress().toString()
|
|
1550
|
-
}
|
|
1551
|
-
});
|
|
1552
1343
|
throw err;
|
|
1553
1344
|
});
|
|
1554
1345
|
return {
|
|
@@ -7,7 +7,7 @@ import { type TypedEventEmitter } from '@aztec/foundation/types';
|
|
|
7
7
|
import type { P2P } from '@aztec/p2p';
|
|
8
8
|
import type { SlasherClientInterface } from '@aztec/slasher';
|
|
9
9
|
import { L2Block, type L2BlockSink, type L2BlockSource } from '@aztec/stdlib/block';
|
|
10
|
-
import type
|
|
10
|
+
import { type Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
11
11
|
import { type ResolvedSequencerConfig, type WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
12
12
|
import { type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
13
13
|
import { Tx } from '@aztec/stdlib/tx';
|
|
@@ -71,11 +71,9 @@ export declare class CheckpointProposalJob implements Traceable {
|
|
|
71
71
|
indexWithinCheckpoint: IndexWithinCheckpoint;
|
|
72
72
|
buildDeadline: Date | undefined;
|
|
73
73
|
txHashesAlreadyIncluded: Set<string>;
|
|
74
|
-
remainingBlobFields: number;
|
|
75
74
|
}): Promise<{
|
|
76
75
|
block: L2Block;
|
|
77
76
|
usedTxs: Tx[];
|
|
78
|
-
remainingBlobFields: number;
|
|
79
77
|
} | {
|
|
80
78
|
error: Error;
|
|
81
79
|
} | undefined>;
|
|
@@ -99,4 +97,4 @@ export declare class CheckpointProposalJob implements Traceable {
|
|
|
99
97
|
private getSecondsIntoSlot;
|
|
100
98
|
getPublisher(): SequencerPublisher;
|
|
101
99
|
}
|
|
102
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF9wcm9wb3NhbF9qb2IuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXF1ZW5jZXIvY2hlY2twb2ludF9wcm9wb3NhbF9qb2IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUNMLFdBQVcsRUFDWCxnQkFBZ0IsRUFDaEIsV0FBVyxFQUNYLHFCQUFxQixFQUNyQixVQUFVLEVBQ1gsTUFBTSxpQ0FBaUMsQ0FBQztBQVF6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFHM0QsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFFLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sRUFBRSxLQUFLLFlBQVksRUFBUyxNQUFNLHlCQUF5QixDQUFDO0FBQ25FLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUEwQixNQUFNLHlCQUF5QixDQUFDO0FBQ3pGLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN0QyxPQUFPLEtBQUssRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdELE9BQU8sRUFHTCxPQUFPLEVBQ1AsS0FBSyxXQUFXLEVBQ2hCLEtBQUssYUFBYSxFQUVuQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxLQUFLLFVBQVUsRUFBc0IsTUFBTSwwQkFBMEIsQ0FBQztBQUcvRSxPQUFPLEVBR0wsS0FBSyx1QkFBdUIsRUFDNUIsS0FBSyxzQkFBc0IsRUFDNUIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsS0FBSyxtQkFBbUIsRUFBbUMsTUFBTSx5QkFBeUIsQ0FBQztBQUlwRyxPQUFPLEVBQWlCLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXJELE9BQU8sRUFBYyxLQUFLLFNB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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint_proposal_job.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_proposal_job.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkpoint_proposal_job.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_proposal_job.ts"],"names":[],"mappings":"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"}
|
|
@@ -436,20 +436,19 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
436
436
|
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
437
437
|
}
|
|
438
438
|
var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _initProto;
|
|
439
|
-
import { NUM_CHECKPOINT_END_MARKER_FIELDS, getNumBlockEndBlobFields } from '@aztec/blob-lib/encoding';
|
|
440
|
-
import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB } from '@aztec/constants';
|
|
441
439
|
import { BlockNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
|
|
442
440
|
import { randomInt } from '@aztec/foundation/crypto/random';
|
|
443
|
-
import {
|
|
441
|
+
import { flipSignature, generateRecoverableSignature, generateUnrecoverableSignature } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
444
442
|
import { filter } from '@aztec/foundation/iterator';
|
|
445
443
|
import { createLogger } from '@aztec/foundation/log';
|
|
446
444
|
import { sleep, sleepUntil } from '@aztec/foundation/sleep';
|
|
447
445
|
import { Timer } from '@aztec/foundation/timer';
|
|
448
446
|
import { isErrorClass, unfreeze } from '@aztec/foundation/types';
|
|
449
447
|
import { CommitteeAttestationsAndSigners, MaliciousCommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
448
|
+
import { validateCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
450
449
|
import { getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
451
450
|
import { Gas } from '@aztec/stdlib/gas';
|
|
452
|
-
import {
|
|
451
|
+
import { InsufficientValidTxsError } from '@aztec/stdlib/interfaces/server';
|
|
453
452
|
import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
454
453
|
import { orderAttestations, trimAttestations } from '@aztec/stdlib/p2p';
|
|
455
454
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
@@ -696,6 +695,21 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
696
695
|
// broadcasted yet, and wait to collect the committee attestations.
|
|
697
696
|
this.setStateFn(SequencerState.ASSEMBLING_CHECKPOINT, this.slot);
|
|
698
697
|
const checkpoint = await checkpointBuilder.completeCheckpoint();
|
|
698
|
+
// Final validation round for the checkpoint before we propose it, just for safety
|
|
699
|
+
try {
|
|
700
|
+
validateCheckpoint(checkpoint, {
|
|
701
|
+
rollupManaLimit: this.l1Constants.rollupManaLimit,
|
|
702
|
+
maxL2BlockGas: this.config.maxL2BlockGas,
|
|
703
|
+
maxDABlockGas: this.config.maxDABlockGas,
|
|
704
|
+
maxTxsPerBlock: this.config.maxTxsPerBlock,
|
|
705
|
+
maxTxsPerCheckpoint: this.config.maxTxsPerCheckpoint
|
|
706
|
+
});
|
|
707
|
+
} catch (err) {
|
|
708
|
+
this.log.error(`Built an invalid checkpoint at slot ${this.slot} (skipping proposal)`, err, {
|
|
709
|
+
checkpoint: checkpoint.header.toInspect()
|
|
710
|
+
});
|
|
711
|
+
return undefined;
|
|
712
|
+
}
|
|
699
713
|
// Record checkpoint-level build metrics
|
|
700
714
|
this.metrics.recordCheckpointBuild(checkpointBuildTimer.ms(), blocksInCheckpoint.length, checkpoint.getStats().txCount, Number(checkpoint.header.totalManaUsed.toBigInt()));
|
|
701
715
|
// Do not collect attestations nor publish to L1 in fisherman mode
|
|
@@ -775,8 +789,6 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
775
789
|
const blocksInCheckpoint = [];
|
|
776
790
|
const txHashesAlreadyIncluded = new Set();
|
|
777
791
|
const initialBlockNumber = BlockNumber(this.syncedToBlockNumber + 1);
|
|
778
|
-
// Remaining blob fields available for blocks (checkpoint end marker already subtracted)
|
|
779
|
-
let remainingBlobFields = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB - NUM_CHECKPOINT_END_MARKER_FIELDS;
|
|
780
792
|
// Last block in the checkpoint will usually be flagged as pending broadcast, so we send it along with the checkpoint proposal
|
|
781
793
|
let blockPendingBroadcast = undefined;
|
|
782
794
|
while(true){
|
|
@@ -802,8 +814,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
802
814
|
buildDeadline: timingInfo.deadline ? new Date((this.getSlotStartBuildTimestamp() + timingInfo.deadline) * 1000) : undefined,
|
|
803
815
|
blockNumber,
|
|
804
816
|
indexWithinCheckpoint,
|
|
805
|
-
txHashesAlreadyIncluded
|
|
806
|
-
remainingBlobFields
|
|
817
|
+
txHashesAlreadyIncluded
|
|
807
818
|
});
|
|
808
819
|
// TODO(palla/mbps): Review these conditions. We may want to keep trying in some scenarios.
|
|
809
820
|
if (!buildResult && timingInfo.isLastBlock) {
|
|
@@ -825,10 +836,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
825
836
|
}
|
|
826
837
|
break;
|
|
827
838
|
}
|
|
828
|
-
const { block, usedTxs
|
|
839
|
+
const { block, usedTxs } = buildResult;
|
|
829
840
|
blocksInCheckpoint.push(block);
|
|
830
|
-
// Update remaining blob fields for the next block
|
|
831
|
-
remainingBlobFields = newRemainingBlobFields;
|
|
832
841
|
// Sync the proposed block to the archiver to make it available
|
|
833
842
|
// Note that the checkpoint builder uses its own fork so it should not need to wait for this syncing
|
|
834
843
|
// Eventually we should refactor the checkpoint builder to not need a separate long-lived fork
|
|
@@ -879,15 +888,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
879
888
|
await this.waitUntilTimeInSlot(nextSubslotStart);
|
|
880
889
|
}
|
|
881
890
|
/** Builds a single block. Called from the main block building loop. */ async buildSingleBlock(checkpointBuilder, opts) {
|
|
882
|
-
const { blockTimestamp, forceCreate, blockNumber, indexWithinCheckpoint, buildDeadline, txHashesAlreadyIncluded
|
|
891
|
+
const { blockTimestamp, forceCreate, blockNumber, indexWithinCheckpoint, buildDeadline, txHashesAlreadyIncluded } = opts;
|
|
883
892
|
this.log.verbose(`Preparing block ${blockNumber} index ${indexWithinCheckpoint} at checkpoint ${this.checkpointNumber} for slot ${this.slot}`, {
|
|
884
893
|
...checkpointBuilder.getConstantData(),
|
|
885
894
|
...opts
|
|
886
895
|
});
|
|
887
896
|
try {
|
|
888
897
|
// Wait until we have enough txs to build the block
|
|
889
|
-
const minTxs = this.
|
|
890
|
-
const { availableTxs, canStartBuilding } = await this.waitForMinTxs(opts);
|
|
898
|
+
const { availableTxs, canStartBuilding, minTxs } = await this.waitForMinTxs(opts);
|
|
891
899
|
if (!canStartBuilding) {
|
|
892
900
|
this.log.warn(`Not enough txs to build block ${blockNumber} at index ${indexWithinCheckpoint} in slot ${this.slot} (got ${availableTxs} txs but needs ${minTxs})`, {
|
|
893
901
|
blockNumber,
|
|
@@ -911,32 +919,30 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
911
919
|
indexWithinCheckpoint
|
|
912
920
|
});
|
|
913
921
|
this.setStateFn(SequencerState.CREATING_BLOCK, this.slot);
|
|
914
|
-
//
|
|
915
|
-
|
|
916
|
-
|
|
922
|
+
// Per-block limits derived at startup by computeBlockLimits(), further capped
|
|
923
|
+
// by remaining checkpoint-level budgets inside CheckpointBuilder before each block is built.
|
|
924
|
+
// minValidTxs is passed into the builder so it can reject the block *before* updating state.
|
|
925
|
+
const minValidTxs = forceCreate ? 0 : this.config.minValidTxsPerBlock ?? minTxs;
|
|
917
926
|
const blockBuilderOptions = {
|
|
918
927
|
maxTransactions: this.config.maxTxsPerBlock,
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
928
|
+
maxBlockGas: this.config.maxL2BlockGas !== undefined || this.config.maxDABlockGas !== undefined ? new Gas(this.config.maxDABlockGas ?? Infinity, this.config.maxL2BlockGas ?? Infinity) : undefined,
|
|
929
|
+
deadline: buildDeadline,
|
|
930
|
+
isBuildingProposal: true,
|
|
931
|
+
minValidTxs
|
|
923
932
|
};
|
|
924
|
-
// Actually build the block by executing txs
|
|
933
|
+
// Actually build the block by executing txs. The builder throws InsufficientValidTxsError
|
|
934
|
+
// if the number of successfully processed txs is below minValidTxs, ensuring state is not
|
|
935
|
+
// updated for blocks that will be discarded.
|
|
925
936
|
const buildResult = await this.buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
|
|
926
937
|
// If any txs failed during execution, drop them from the mempool so we don't pick them up again
|
|
927
938
|
await this.dropFailedTxsFromP2P(buildResult.failedTxs);
|
|
928
|
-
|
|
929
|
-
// too long, then we may not get to minTxsPerBlock after executing public functions.
|
|
930
|
-
const minValidTxs = this.config.minValidTxsPerBlock ?? minTxs;
|
|
931
|
-
const numTxs = buildResult.status === 'no-valid-txs' ? 0 : buildResult.numTxs;
|
|
932
|
-
if (buildResult.status === 'no-valid-txs' || !forceCreate && numTxs < minValidTxs) {
|
|
939
|
+
if (buildResult.status === 'insufficient-valid-txs') {
|
|
933
940
|
this.log.warn(`Block ${blockNumber} at index ${indexWithinCheckpoint} on slot ${this.slot} has too few valid txs to be proposed`, {
|
|
934
941
|
slot: this.slot,
|
|
935
942
|
blockNumber,
|
|
936
|
-
numTxs,
|
|
943
|
+
numTxs: buildResult.processedCount,
|
|
937
944
|
indexWithinCheckpoint,
|
|
938
|
-
minValidTxs
|
|
939
|
-
buildResult: buildResult.status
|
|
945
|
+
minValidTxs
|
|
940
946
|
});
|
|
941
947
|
this.eventEmitter.emit('block-build-failed', {
|
|
942
948
|
reason: `Insufficient valid txs`,
|
|
@@ -946,7 +952,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
946
952
|
return undefined;
|
|
947
953
|
}
|
|
948
954
|
// Block creation succeeded, emit stats and metrics
|
|
949
|
-
const {
|
|
955
|
+
const { block, publicProcessorDuration, usedTxs, blockBuildDuration, numTxs } = buildResult;
|
|
950
956
|
const blockStats = {
|
|
951
957
|
eventName: 'l2-block-built',
|
|
952
958
|
duration: blockBuildDuration,
|
|
@@ -955,7 +961,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
955
961
|
};
|
|
956
962
|
const blockHash = await block.hash();
|
|
957
963
|
const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
|
|
958
|
-
const manaPerSec =
|
|
964
|
+
const manaPerSec = block.header.totalManaUsed.toNumberUnsafe() / (blockBuildDuration / 1000);
|
|
959
965
|
this.log.info(`Built block ${block.number} at checkpoint ${this.checkpointNumber} for slot ${this.slot} with ${numTxs} txs`, {
|
|
960
966
|
blockHash,
|
|
961
967
|
txHashes,
|
|
@@ -966,11 +972,10 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
966
972
|
blockNumber: block.number,
|
|
967
973
|
slot: this.slot
|
|
968
974
|
});
|
|
969
|
-
this.metrics.recordBuiltBlock(blockBuildDuration,
|
|
975
|
+
this.metrics.recordBuiltBlock(blockBuildDuration, block.header.totalManaUsed.toNumberUnsafe());
|
|
970
976
|
return {
|
|
971
977
|
block,
|
|
972
|
-
usedTxs
|
|
973
|
-
remainingBlobFields: maxBlobFieldsForTxs - usedTxBlobFields
|
|
978
|
+
usedTxs
|
|
974
979
|
};
|
|
975
980
|
} catch (err) {
|
|
976
981
|
this.eventEmitter.emit('block-build-failed', {
|
|
@@ -988,7 +993,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
988
993
|
};
|
|
989
994
|
}
|
|
990
995
|
}
|
|
991
|
-
/** Uses the checkpoint builder to build a block, catching
|
|
996
|
+
/** Uses the checkpoint builder to build a block, catching InsufficientValidTxsError. */ async buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions) {
|
|
992
997
|
try {
|
|
993
998
|
const workTimer = new Timer();
|
|
994
999
|
const result = await checkpointBuilder.buildBlock(pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
|
|
@@ -999,10 +1004,11 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
999
1004
|
status: 'success'
|
|
1000
1005
|
};
|
|
1001
1006
|
} catch (err) {
|
|
1002
|
-
if (isErrorClass(err,
|
|
1007
|
+
if (isErrorClass(err, InsufficientValidTxsError)) {
|
|
1003
1008
|
return {
|
|
1004
1009
|
failedTxs: err.failedTxs,
|
|
1005
|
-
|
|
1010
|
+
processedCount: err.processedCount,
|
|
1011
|
+
status: 'insufficient-valid-txs'
|
|
1006
1012
|
};
|
|
1007
1013
|
}
|
|
1008
1014
|
throw err;
|
|
@@ -1021,7 +1027,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1021
1027
|
if (startBuildingDeadline === undefined || now >= startBuildingDeadline) {
|
|
1022
1028
|
return {
|
|
1023
1029
|
canStartBuilding: false,
|
|
1024
|
-
availableTxs
|
|
1030
|
+
availableTxs,
|
|
1031
|
+
minTxs
|
|
1025
1032
|
};
|
|
1026
1033
|
}
|
|
1027
1034
|
// Wait a bit before checking again
|
|
@@ -1036,7 +1043,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1036
1043
|
}
|
|
1037
1044
|
return {
|
|
1038
1045
|
canStartBuilding: true,
|
|
1039
|
-
availableTxs
|
|
1046
|
+
availableTxs,
|
|
1047
|
+
minTxs
|
|
1040
1048
|
};
|
|
1041
1049
|
}
|
|
1042
1050
|
/**
|
|
@@ -1082,7 +1090,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1082
1090
|
// Rollup contract requires that the signatures are provided in the order of the committee
|
|
1083
1091
|
const sorted = orderAttestations(trimmed, committee);
|
|
1084
1092
|
// Manipulate the attestations if we've been configured to do so
|
|
1085
|
-
if (this.config.injectFakeAttestation || this.config.shuffleAttestationOrdering) {
|
|
1093
|
+
if (this.config.injectFakeAttestation || this.config.injectHighSValueAttestation || this.config.injectUnrecoverableSignatureAttestation || this.config.shuffleAttestationOrdering) {
|
|
1086
1094
|
return this.manipulateAttestations(proposal.slotNumber, epoch, seed, committee, sorted);
|
|
1087
1095
|
}
|
|
1088
1096
|
return new CommitteeAttestationsAndSigners(sorted);
|
|
@@ -1099,7 +1107,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1099
1107
|
// Compute the proposer index in the committee, since we dont want to tweak it.
|
|
1100
1108
|
// Otherwise, the L1 rollup contract will reject the block outright.
|
|
1101
1109
|
const proposerIndex = Number(this.epochCache.computeProposerIndex(slotNumber, epoch, seed, BigInt(committee.length)));
|
|
1102
|
-
if (this.config.injectFakeAttestation) {
|
|
1110
|
+
if (this.config.injectFakeAttestation || this.config.injectHighSValueAttestation || this.config.injectUnrecoverableSignatureAttestation) {
|
|
1103
1111
|
// Find non-empty attestations that are not from the proposer
|
|
1104
1112
|
const nonProposerIndices = [];
|
|
1105
1113
|
for(let i = 0; i < attestations.length; i++){
|
|
@@ -1109,8 +1117,16 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1109
1117
|
}
|
|
1110
1118
|
if (nonProposerIndices.length > 0) {
|
|
1111
1119
|
const targetIndex = nonProposerIndices[randomInt(nonProposerIndices.length)];
|
|
1112
|
-
this.
|
|
1113
|
-
|
|
1120
|
+
if (this.config.injectHighSValueAttestation) {
|
|
1121
|
+
this.log.warn(`Injecting high-s value attestation in checkpoint for slot ${slotNumber} at index ${targetIndex}`);
|
|
1122
|
+
unfreeze(attestations[targetIndex]).signature = flipSignature(attestations[targetIndex].signature);
|
|
1123
|
+
} else if (this.config.injectUnrecoverableSignatureAttestation) {
|
|
1124
|
+
this.log.warn(`Injecting unrecoverable signature attestation in checkpoint for slot ${slotNumber} at index ${targetIndex}`);
|
|
1125
|
+
unfreeze(attestations[targetIndex]).signature = generateUnrecoverableSignature();
|
|
1126
|
+
} else {
|
|
1127
|
+
this.log.warn(`Injecting fake attestation in checkpoint for slot ${slotNumber} at index ${targetIndex}`);
|
|
1128
|
+
unfreeze(attestations[targetIndex]).signature = generateRecoverableSignature();
|
|
1129
|
+
}
|
|
1114
1130
|
}
|
|
1115
1131
|
return new CommitteeAttestationsAndSigners(attestations);
|
|
1116
1132
|
}
|