@aztec/sequencer-client 0.0.1-commit.5de5ca79e → 0.0.1-commit.6201a7b05
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 +6 -1
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +11 -17
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +13 -12
- package/dest/global_variable_builder/fee_predictor.d.ts +37 -0
- package/dest/global_variable_builder/fee_predictor.d.ts.map +1 -0
- package/dest/global_variable_builder/fee_predictor.js +128 -0
- package/dest/global_variable_builder/fee_provider.d.ts +21 -0
- package/dest/global_variable_builder/fee_provider.d.ts.map +1 -0
- package/dest/global_variable_builder/fee_provider.js +58 -0
- package/dest/global_variable_builder/global_builder.d.ts +15 -14
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +16 -51
- package/dest/global_variable_builder/index.d.ts +4 -2
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/global_variable_builder/index.js +2 -0
- package/dest/publisher/config.d.ts +13 -1
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +19 -4
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +3 -4
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.d.ts +3 -5
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +2 -3
- package/dest/publisher/sequencer-publisher.d.ts +48 -42
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +119 -111
- package/dest/sequencer/chain_state_overrides.d.ts +25 -0
- package/dest/sequencer/chain_state_overrides.d.ts.map +1 -0
- package/dest/sequencer/chain_state_overrides.js +39 -0
- package/dest/sequencer/checkpoint_proposal_job.d.ts +41 -11
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +525 -149
- package/dest/sequencer/checkpoint_proposal_job_metrics.d.ts +34 -0
- package/dest/sequencer/checkpoint_proposal_job_metrics.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_proposal_job_metrics.js +72 -0
- package/dest/sequencer/checkpoint_voter.d.ts +1 -2
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_voter.js +2 -5
- package/dest/sequencer/events.d.ts +6 -1
- package/dest/sequencer/events.d.ts.map +1 -1
- package/dest/sequencer/metrics.d.ts +9 -10
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +34 -20
- package/dest/sequencer/sequencer.d.ts +27 -7
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +106 -28
- package/dest/sequencer/timetable.d.ts +14 -1
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +45 -36
- package/dest/test/utils.d.ts +1 -1
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +7 -6
- package/package.json +27 -27
- package/src/client/sequencer-client.ts +16 -24
- package/src/config.ts +13 -11
- package/src/global_variable_builder/README.md +44 -0
- package/src/global_variable_builder/fee_predictor.ts +172 -0
- package/src/global_variable_builder/fee_provider.ts +75 -0
- package/src/global_variable_builder/global_builder.ts +26 -63
- package/src/global_variable_builder/index.ts +3 -1
- package/src/publisher/config.ts +38 -4
- package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +3 -1
- package/src/publisher/sequencer-publisher-factory.ts +3 -6
- package/src/publisher/sequencer-publisher.ts +183 -159
- package/src/sequencer/README.md +82 -13
- package/src/sequencer/chain_state_overrides.ts +87 -0
- package/src/sequencer/checkpoint_proposal_job.ts +616 -167
- package/src/sequencer/checkpoint_proposal_job_metrics.ts +128 -0
- package/src/sequencer/checkpoint_voter.ts +1 -12
- package/src/sequencer/events.ts +5 -0
- package/src/sequencer/metrics.ts +43 -24
- package/src/sequencer/sequencer.ts +148 -32
- package/src/sequencer/timetable.ts +57 -45
- package/src/test/utils.ts +28 -10
|
@@ -372,12 +372,11 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
372
372
|
}
|
|
373
373
|
var _dec, _dec1, _dec2, _initProto;
|
|
374
374
|
import { Blob, getBlobsPerL1Block, getPrefixedEthBlobCommitments } from '@aztec/blob-lib';
|
|
375
|
-
import { FeeAssetPriceOracle, MULTI_CALL_3_ADDRESS, Multicall3,
|
|
375
|
+
import { FeeAssetPriceOracle, MULTI_CALL_3_ADDRESS, Multicall3, SimulationOverridesBuilder, buildSimulationOverridesStateOverride } from '@aztec/ethereum/contracts';
|
|
376
376
|
import { L1FeeAnalyzer } from '@aztec/ethereum/l1-fee-analysis';
|
|
377
377
|
import { MAX_L1_TX_LIMIT, WEI_CONST } from '@aztec/ethereum/l1-tx-utils';
|
|
378
378
|
import { FormattedViemError, formatViemError, mergeAbis, tryExtractEvent } from '@aztec/ethereum/utils';
|
|
379
379
|
import { sumBigint } from '@aztec/foundation/bigint';
|
|
380
|
-
import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
|
|
381
380
|
import { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
382
381
|
import { trimmedBytesLength } from '@aztec/foundation/buffer';
|
|
383
382
|
import { pick } from '@aztec/foundation/collection';
|
|
@@ -386,11 +385,13 @@ import { EthAddress } from '@aztec/foundation/eth-address';
|
|
|
386
385
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
387
386
|
import { createLogger } from '@aztec/foundation/log';
|
|
388
387
|
import { makeBackoff, retry } from '@aztec/foundation/retry';
|
|
388
|
+
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
389
389
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
390
390
|
import { Timer } from '@aztec/foundation/timer';
|
|
391
391
|
import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
392
392
|
import { encodeSlashConsensusVotes } from '@aztec/slasher';
|
|
393
393
|
import { CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
394
|
+
import { getLastL1SlotTimestampForL2Slot, getNextL1SlotTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
394
395
|
import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
395
396
|
import { encodeFunctionData, keccak256, multicall3Abi, toHex } from 'viem';
|
|
396
397
|
import { createL1TxFailedStore } from './l1_tx_failed_store/index.js';
|
|
@@ -400,9 +401,6 @@ export const Actions = [
|
|
|
400
401
|
'invalidate-by-insufficient-attestations',
|
|
401
402
|
'propose',
|
|
402
403
|
'governance-signal',
|
|
403
|
-
'empire-slashing-signal',
|
|
404
|
-
'create-empire-payload',
|
|
405
|
-
'execute-empire-payload',
|
|
406
404
|
'vote-offenses',
|
|
407
405
|
'execute-slash'
|
|
408
406
|
];
|
|
@@ -442,11 +440,13 @@ export class SequencerPublisher {
|
|
|
442
440
|
log;
|
|
443
441
|
ethereumSlotDuration;
|
|
444
442
|
aztecSlotDuration;
|
|
443
|
+
/** Date provider for wall-clock time. */ dateProvider;
|
|
445
444
|
blobClient;
|
|
446
445
|
/** Address to use for simulations in fisherman mode (actual proposer's address) */ proposerAddressForSimulation;
|
|
447
446
|
/** Optional callback to obtain a replacement publisher when the current one fails to send. */ getNextPublisher;
|
|
448
447
|
/** L1 fee analyzer for fisherman mode */ l1FeeAnalyzer;
|
|
449
448
|
/** Fee asset price oracle for computing price modifiers from Uniswap V4 */ feeAssetPriceOracle;
|
|
449
|
+
/** Interruptible sleep used by sendRequestsAt to wait until a target timestamp. */ interruptibleSleep;
|
|
450
450
|
// A CALL to a cold address is 2700 gas
|
|
451
451
|
static MULTICALL_OVERHEAD_GAS_GUESS = 5000n;
|
|
452
452
|
// Gas report for VotingWithSigTest shows a max gas of 100k, but we've seen it cost 700k+ in testnet
|
|
@@ -455,7 +455,6 @@ export class SequencerPublisher {
|
|
|
455
455
|
rollupContract;
|
|
456
456
|
govProposerContract;
|
|
457
457
|
slashingProposerContract;
|
|
458
|
-
slashFactoryContract;
|
|
459
458
|
tracer;
|
|
460
459
|
requests;
|
|
461
460
|
constructor(config, deps){
|
|
@@ -466,13 +465,16 @@ export class SequencerPublisher {
|
|
|
466
465
|
this.lastActions = {};
|
|
467
466
|
this.isPayloadEmptyCache = new Map();
|
|
468
467
|
this.payloadProposedCache = new Set();
|
|
468
|
+
this.interruptibleSleep = new InterruptibleSleep();
|
|
469
469
|
this.requests = [];
|
|
470
470
|
this.log = deps.log ?? createLogger('sequencer:publisher');
|
|
471
471
|
this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
|
|
472
472
|
this.aztecSlotDuration = BigInt(config.aztecSlotDuration);
|
|
473
|
+
this.dateProvider = deps.dateProvider;
|
|
473
474
|
this.epochCache = deps.epochCache;
|
|
474
475
|
this.lastActions = deps.lastActions;
|
|
475
476
|
this.blobClient = deps.blobClient;
|
|
477
|
+
this.dateProvider = deps.dateProvider;
|
|
476
478
|
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
477
479
|
this.metrics = deps.metrics ?? new SequencerPublisherMetrics(telemetry, 'SequencerPublisher');
|
|
478
480
|
this.tracer = telemetry.getTracer('SequencerPublisher');
|
|
@@ -486,7 +488,6 @@ export class SequencerPublisher {
|
|
|
486
488
|
const newSlashingProposer = await this.rollupContract.getSlashingProposer();
|
|
487
489
|
this.slashingProposerContract = newSlashingProposer;
|
|
488
490
|
});
|
|
489
|
-
this.slashFactoryContract = deps.slashFactoryContract;
|
|
490
491
|
// Initialize L1 fee analyzer for fisherman mode
|
|
491
492
|
if (config.fishermanMode) {
|
|
492
493
|
this.l1FeeAnalyzer = new L1FeeAnalyzer(this.l1TxUtils.client, deps.dateProvider, createLogger('sequencer:publisher:fee-analyzer'));
|
|
@@ -737,6 +738,41 @@ export class SequencerPublisher {
|
|
|
737
738
|
}
|
|
738
739
|
}
|
|
739
740
|
}
|
|
741
|
+
/*
|
|
742
|
+
* Schedules sending all enqueued requests at (or after) the given timestamp.
|
|
743
|
+
* Uses InterruptibleSleep so it can be cancelled via interrupt().
|
|
744
|
+
* Returns the promise for the L1 response (caller should NOT await this in the work loop).
|
|
745
|
+
*/ async sendRequestsAt(submitAfter) {
|
|
746
|
+
const ms = submitAfter.getTime() - this.dateProvider.now();
|
|
747
|
+
if (ms > 0) {
|
|
748
|
+
this.log.debug(`Sleeping ${ms}ms before sending requests`, {
|
|
749
|
+
submitAfter
|
|
750
|
+
});
|
|
751
|
+
await this.interruptibleSleep.sleep(ms);
|
|
752
|
+
}
|
|
753
|
+
if (this.interrupted) {
|
|
754
|
+
return undefined;
|
|
755
|
+
}
|
|
756
|
+
// Re-validate enqueued requests after the sleep (state may have changed, e.g. prune or L1 reorg)
|
|
757
|
+
const validRequests = [];
|
|
758
|
+
for (const request of this.requests){
|
|
759
|
+
if (!request.preCheck) {
|
|
760
|
+
validRequests.push(request);
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
try {
|
|
764
|
+
await request.preCheck();
|
|
765
|
+
validRequests.push(request);
|
|
766
|
+
} catch (err) {
|
|
767
|
+
this.log.warn(`Pre-send validation failed for ${request.action}, discarding request`, err);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
this.requests = validRequests;
|
|
771
|
+
if (this.requests.length === 0) {
|
|
772
|
+
return undefined;
|
|
773
|
+
}
|
|
774
|
+
return this.sendRequests();
|
|
775
|
+
}
|
|
740
776
|
callbackBundledTransactions(requests, result, txContext) {
|
|
741
777
|
const actionsListStr = requests.map((r)=>r.action).join(', ');
|
|
742
778
|
if (result instanceof FormattedViemError) {
|
|
@@ -831,18 +867,17 @@ export class SequencerPublisher {
|
|
|
831
867
|
* @notice Will call `canProposeAt` to make sure that it is possible to propose
|
|
832
868
|
* @param tipArchive - The archive to check
|
|
833
869
|
* @returns The slot and block number if it is possible to propose, undefined otherwise
|
|
834
|
-
*/ canProposeAt(tipArchive, msgSender,
|
|
870
|
+
*/ async canProposeAt(tipArchive, msgSender, simulationOverridesPlan) {
|
|
835
871
|
// TODO: #14291 - should loop through multiple keys to check if any of them can propose
|
|
836
872
|
const ignoredErrors = [
|
|
837
873
|
'SlotAlreadyInChain',
|
|
838
874
|
'InvalidProposer',
|
|
839
875
|
'InvalidArchive'
|
|
840
876
|
];
|
|
841
|
-
const pipelined =
|
|
877
|
+
const pipelined = this.epochCache.isProposerPipeliningEnabled();
|
|
842
878
|
const slotOffset = pipelined ? this.aztecSlotDuration : 0n;
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}).catch((err)=>{
|
|
879
|
+
const nextL1SlotTs = this.getNextL1SlotTimestamp() + slotOffset;
|
|
880
|
+
return this.rollupContract.canProposeAt(tipArchive.toBuffer(), msgSender.toString(), nextL1SlotTs, await buildSimulationOverridesStateOverride(this.rollupContract, simulationOverridesPlan)).catch((err)=>{
|
|
846
881
|
if (err instanceof FormattedViemError && ignoredErrors.find((e)=>err.message.includes(e))) {
|
|
847
882
|
this.log.warn(`Failed canProposeAtTime check with ${ignoredErrors.find((e)=>err.message.includes(e))}`, {
|
|
848
883
|
error: err.message
|
|
@@ -858,22 +893,22 @@ export class SequencerPublisher {
|
|
|
858
893
|
* @dev This is a convenience function that can be used by the sequencer to validate a "partial" header.
|
|
859
894
|
* It will throw if the block header is invalid.
|
|
860
895
|
* @param header - The block header to validate
|
|
861
|
-
*/ async validateBlockHeader(header,
|
|
896
|
+
*/ async validateBlockHeader(header, simulationOverridesPlan) {
|
|
862
897
|
const flags = {
|
|
863
898
|
ignoreDA: true,
|
|
864
899
|
ignoreSignatures: true
|
|
865
900
|
};
|
|
866
901
|
const args = [
|
|
867
902
|
header.toViem(),
|
|
868
|
-
CommitteeAttestationsAndSigners.
|
|
903
|
+
CommitteeAttestationsAndSigners.packAttestations([]),
|
|
869
904
|
[],
|
|
870
905
|
Signature.empty().toViemSignature(),
|
|
871
906
|
`0x${'0'.repeat(64)}`,
|
|
872
907
|
header.blobsHash.toString(),
|
|
873
908
|
flags
|
|
874
909
|
];
|
|
875
|
-
const ts =
|
|
876
|
-
const stateOverrides = await this.rollupContract
|
|
910
|
+
const ts = this.getSimulationTimestamp(header.slotNumber);
|
|
911
|
+
const stateOverrides = await buildSimulationOverridesStateOverride(this.rollupContract, simulationOverridesPlan);
|
|
877
912
|
let balance = 0n;
|
|
878
913
|
if (this.config.fishermanMode) {
|
|
879
914
|
// In fisherman mode, we can't know where the proposer is publishing from
|
|
@@ -895,7 +930,7 @@ export class SequencerPublisher {
|
|
|
895
930
|
}),
|
|
896
931
|
from: MULTI_CALL_3_ADDRESS
|
|
897
932
|
}, {
|
|
898
|
-
time: ts
|
|
933
|
+
time: ts
|
|
899
934
|
}, stateOverrides);
|
|
900
935
|
this.log.debug(`Simulated validateHeader`);
|
|
901
936
|
}
|
|
@@ -941,6 +976,7 @@ export class SequencerPublisher {
|
|
|
941
976
|
gasUsed,
|
|
942
977
|
checkpointNumber,
|
|
943
978
|
forcePendingCheckpointNumber: CheckpointNumber(checkpointNumber - 1),
|
|
979
|
+
lastArchive: validationResult.checkpoint.lastArchive,
|
|
944
980
|
reason
|
|
945
981
|
};
|
|
946
982
|
} catch (err) {
|
|
@@ -953,8 +989,8 @@ export class SequencerPublisher {
|
|
|
953
989
|
request,
|
|
954
990
|
error: viemError.message
|
|
955
991
|
});
|
|
956
|
-
const
|
|
957
|
-
if (
|
|
992
|
+
const latestProposedCheckpointNumber = await this.rollupContract.getCheckpointNumber();
|
|
993
|
+
if (latestProposedCheckpointNumber < checkpointNumber) {
|
|
958
994
|
this.log.verbose(`Checkpoint ${checkpointNumber} has already been invalidated`, {
|
|
959
995
|
...logData
|
|
960
996
|
});
|
|
@@ -1004,7 +1040,7 @@ export class SequencerPublisher {
|
|
|
1004
1040
|
reason
|
|
1005
1041
|
};
|
|
1006
1042
|
this.log.debug(`Building invalidate checkpoint ${checkpoint.checkpointNumber} request`, logData);
|
|
1007
|
-
const attestationsAndSigners =
|
|
1043
|
+
const attestationsAndSigners = CommitteeAttestationsAndSigners.packAttestations(validationResult.attestations);
|
|
1008
1044
|
if (reason === 'invalid-attestation') {
|
|
1009
1045
|
return this.rollupContract.buildInvalidateBadAttestationRequest(checkpoint.checkpointNumber, attestationsAndSigners, committee, validationResult.invalidIndex);
|
|
1010
1046
|
} else if (reason === 'insufficient-attestations') {
|
|
@@ -1014,10 +1050,7 @@ export class SequencerPublisher {
|
|
|
1014
1050
|
throw new Error(`Unknown reason for invalidation`);
|
|
1015
1051
|
}
|
|
1016
1052
|
}
|
|
1017
|
-
/** Simulates `propose` to make sure that the checkpoint is valid for submission */ async validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature,
|
|
1018
|
-
// Anchor the simulation timestamp to the checkpoint's own slot start time
|
|
1019
|
-
// rather than the current L1 block timestamp, which may overshoot into the next slot if the build ran late.
|
|
1020
|
-
const ts = checkpoint.header.timestamp;
|
|
1053
|
+
/** Simulates `propose` to make sure that the checkpoint is valid for submission */ async validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, simulationOverridesPlan) {
|
|
1021
1054
|
const blobFields = checkpoint.toBlobFields();
|
|
1022
1055
|
const blobs = await getBlobsPerL1Block(blobFields);
|
|
1023
1056
|
const blobInput = getPrefixedEthBlobCommitments(blobs);
|
|
@@ -1034,10 +1067,9 @@ export class SequencerPublisher {
|
|
|
1034
1067
|
attestationsAndSignersSignature.toViemSignature(),
|
|
1035
1068
|
blobInput
|
|
1036
1069
|
];
|
|
1037
|
-
await this.simulateProposeTx(args,
|
|
1038
|
-
return ts;
|
|
1070
|
+
await this.simulateProposeTx(args, simulationOverridesPlan);
|
|
1039
1071
|
}
|
|
1040
|
-
async enqueueCastSignalHelper(slotNumber,
|
|
1072
|
+
async enqueueCastSignalHelper(slotNumber, signalType, payload, base, signerAddress, signer) {
|
|
1041
1073
|
if (this.lastActions[signalType] && this.lastActions[signalType] === slotNumber) {
|
|
1042
1074
|
this.log.debug(`Skipping duplicate vote cast signal ${signalType} for slot ${slotNumber}`);
|
|
1043
1075
|
return false;
|
|
@@ -1094,6 +1126,7 @@ export class SequencerPublisher {
|
|
|
1094
1126
|
lastValidL2Slot: slotNumber
|
|
1095
1127
|
});
|
|
1096
1128
|
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1129
|
+
const timestamp = this.getSimulationTimestamp(slotNumber);
|
|
1097
1130
|
try {
|
|
1098
1131
|
await this.l1TxUtils.simulate(request, {
|
|
1099
1132
|
time: timestamp
|
|
@@ -1106,7 +1139,10 @@ export class SequencerPublisher {
|
|
|
1106
1139
|
});
|
|
1107
1140
|
} catch (err) {
|
|
1108
1141
|
const viemError = formatViemError(err);
|
|
1109
|
-
this.log.error(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, viemError
|
|
1142
|
+
this.log.error(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, viemError, {
|
|
1143
|
+
simulationTimestamp: timestamp,
|
|
1144
|
+
l1BlockNumber
|
|
1145
|
+
});
|
|
1110
1146
|
this.backupFailedTx({
|
|
1111
1147
|
id: keccak256(request.data),
|
|
1112
1148
|
failureType: 'simulation',
|
|
@@ -1171,55 +1207,17 @@ export class SequencerPublisher {
|
|
|
1171
1207
|
/**
|
|
1172
1208
|
* Enqueues a governance castSignal transaction to cast a signal for a given slot number.
|
|
1173
1209
|
* @param slotNumber - The slot number to cast a signal for.
|
|
1174
|
-
* @param timestamp - The timestamp of the slot to cast a signal for.
|
|
1175
1210
|
* @returns True if the signal was successfully enqueued, false otherwise.
|
|
1176
|
-
*/ enqueueGovernanceCastSignal(governancePayload, slotNumber,
|
|
1177
|
-
return this.enqueueCastSignalHelper(slotNumber,
|
|
1211
|
+
*/ enqueueGovernanceCastSignal(governancePayload, slotNumber, signerAddress, signer) {
|
|
1212
|
+
return this.enqueueCastSignalHelper(slotNumber, 'governance-signal', governancePayload, this.govProposerContract, signerAddress, signer);
|
|
1178
1213
|
}
|
|
1179
|
-
/** Enqueues all slashing actions as returned by the slasher client. */ async enqueueSlashingActions(actions, slotNumber,
|
|
1214
|
+
/** Enqueues all slashing actions as returned by the slasher client. */ async enqueueSlashingActions(actions, slotNumber, signerAddress, signer) {
|
|
1180
1215
|
if (actions.length === 0) {
|
|
1181
1216
|
this.log.debug(`No slashing actions to enqueue for slot ${slotNumber}`);
|
|
1182
1217
|
return false;
|
|
1183
1218
|
}
|
|
1184
1219
|
for (const action of actions){
|
|
1185
1220
|
switch(action.type){
|
|
1186
|
-
case 'vote-empire-payload':
|
|
1187
|
-
{
|
|
1188
|
-
if (this.slashingProposerContract?.type !== 'empire') {
|
|
1189
|
-
this.log.error('Cannot vote for empire payload on non-empire slashing contract');
|
|
1190
|
-
break;
|
|
1191
|
-
}
|
|
1192
|
-
this.log.debug(`Enqueuing slashing vote for payload ${action.payload} at slot ${slotNumber}`, {
|
|
1193
|
-
signerAddress
|
|
1194
|
-
});
|
|
1195
|
-
await this.enqueueCastSignalHelper(slotNumber, timestamp, 'empire-slashing-signal', action.payload, this.slashingProposerContract, signerAddress, signer);
|
|
1196
|
-
break;
|
|
1197
|
-
}
|
|
1198
|
-
case 'create-empire-payload':
|
|
1199
|
-
{
|
|
1200
|
-
this.log.debug(`Enqueuing slashing create payload at slot ${slotNumber}`, {
|
|
1201
|
-
slotNumber,
|
|
1202
|
-
signerAddress
|
|
1203
|
-
});
|
|
1204
|
-
const request = this.slashFactoryContract.buildCreatePayloadRequest(action.data);
|
|
1205
|
-
await this.simulateAndEnqueueRequest('create-empire-payload', request, (receipt)=>!!this.slashFactoryContract.tryExtractSlashPayloadCreatedEvent(receipt.logs), slotNumber, timestamp);
|
|
1206
|
-
break;
|
|
1207
|
-
}
|
|
1208
|
-
case 'execute-empire-payload':
|
|
1209
|
-
{
|
|
1210
|
-
this.log.debug(`Enqueuing slashing execute payload at slot ${slotNumber}`, {
|
|
1211
|
-
slotNumber,
|
|
1212
|
-
signerAddress
|
|
1213
|
-
});
|
|
1214
|
-
if (this.slashingProposerContract?.type !== 'empire') {
|
|
1215
|
-
this.log.error('Cannot execute slashing payload on non-empire slashing contract');
|
|
1216
|
-
return false;
|
|
1217
|
-
}
|
|
1218
|
-
const empireSlashingProposer = this.slashingProposerContract;
|
|
1219
|
-
const request = empireSlashingProposer.buildExecuteRoundRequest(action.round);
|
|
1220
|
-
await this.simulateAndEnqueueRequest('execute-empire-payload', request, (receipt)=>!!empireSlashingProposer.tryExtractPayloadSubmittedEvent(receipt.logs), slotNumber, timestamp);
|
|
1221
|
-
break;
|
|
1222
|
-
}
|
|
1223
1221
|
case 'vote-offenses':
|
|
1224
1222
|
{
|
|
1225
1223
|
this.log.debug(`Enqueuing slashing vote for ${action.votes.length} votes at slot ${slotNumber}`, {
|
|
@@ -1228,14 +1226,13 @@ export class SequencerPublisher {
|
|
|
1228
1226
|
votesCount: action.votes.length,
|
|
1229
1227
|
signerAddress
|
|
1230
1228
|
});
|
|
1231
|
-
if (this.slashingProposerContract
|
|
1232
|
-
this.log.error('
|
|
1229
|
+
if (!this.slashingProposerContract) {
|
|
1230
|
+
this.log.error('No slashing proposer contract available');
|
|
1233
1231
|
return false;
|
|
1234
1232
|
}
|
|
1235
|
-
const tallySlashingProposer = this.slashingProposerContract;
|
|
1236
1233
|
const votes = bufferToHex(encodeSlashConsensusVotes(action.votes));
|
|
1237
|
-
const request = await
|
|
1238
|
-
await this.simulateAndEnqueueRequest('vote-offenses', request, (receipt)=>!!
|
|
1234
|
+
const request = await this.slashingProposerContract.buildVoteRequestFromSigner(votes, slotNumber, signer);
|
|
1235
|
+
await this.simulateAndEnqueueRequest('vote-offenses', request, (receipt)=>!!this.slashingProposerContract.tryExtractVoteCastEvent(receipt.logs), slotNumber);
|
|
1239
1236
|
break;
|
|
1240
1237
|
}
|
|
1241
1238
|
case 'execute-slash':
|
|
@@ -1245,13 +1242,12 @@ export class SequencerPublisher {
|
|
|
1245
1242
|
round: action.round,
|
|
1246
1243
|
signerAddress
|
|
1247
1244
|
});
|
|
1248
|
-
if (this.slashingProposerContract
|
|
1249
|
-
this.log.error('
|
|
1245
|
+
if (!this.slashingProposerContract) {
|
|
1246
|
+
this.log.error('No slashing proposer contract available');
|
|
1250
1247
|
return false;
|
|
1251
1248
|
}
|
|
1252
|
-
const
|
|
1253
|
-
|
|
1254
|
-
await this.simulateAndEnqueueRequest('execute-slash', request, (receipt)=>!!tallySlashingProposer.tryExtractRoundExecutedEvent(receipt.logs), slotNumber, timestamp);
|
|
1249
|
+
const executeRequest = this.slashingProposerContract.buildExecuteRoundRequest(action.round, action.committees);
|
|
1250
|
+
await this.simulateAndEnqueueRequest('execute-slash', executeRequest, (receipt)=>!!this.slashingProposerContract.tryExtractRoundExecutedEvent(receipt.logs), slotNumber);
|
|
1255
1251
|
break;
|
|
1256
1252
|
}
|
|
1257
1253
|
default:
|
|
@@ -1275,27 +1271,40 @@ export class SequencerPublisher {
|
|
|
1275
1271
|
attestationsAndSignersSignature,
|
|
1276
1272
|
feeAssetPriceModifier: checkpoint.feeAssetPriceModifier
|
|
1277
1273
|
};
|
|
1278
|
-
|
|
1274
|
+
const simulationOverridesPlan = SimulationOverridesBuilder.from(opts.simulationOverridesPlan).withoutBlobCheck().build();
|
|
1279
1275
|
try {
|
|
1280
1276
|
// @note This will make sure that we are passing the checks for our header ASSUMING that the data is also made available
|
|
1281
1277
|
// This means that we can avoid the simulation issues in later checks.
|
|
1282
1278
|
// By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which
|
|
1283
1279
|
// make time consistency checks break.
|
|
1284
1280
|
// TODO(palla): Check whether we're validating twice, once here and once within addProposeTx, since we call simulateProposeTx in both places.
|
|
1285
|
-
|
|
1281
|
+
await this.validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, simulationOverridesPlan);
|
|
1286
1282
|
} catch (err) {
|
|
1287
1283
|
this.log.error(`Checkpoint validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
|
|
1288
1284
|
...checkpoint.getStats(),
|
|
1289
1285
|
slotNumber: checkpoint.header.slotNumber,
|
|
1290
|
-
|
|
1286
|
+
simulationOverridesPlan
|
|
1291
1287
|
});
|
|
1292
1288
|
throw err;
|
|
1293
1289
|
}
|
|
1290
|
+
// Build a pre-check callback that re-validates the checkpoint before L1 submission.
|
|
1291
|
+
// During pipelining this catches stale proposals due to prunes or L1 reorgs that occur during the pipeline sleep.
|
|
1292
|
+
let preCheck = undefined;
|
|
1293
|
+
if (this.epochCache.isProposerPipeliningEnabled()) {
|
|
1294
|
+
preCheck = async ()=>{
|
|
1295
|
+
this.log.debug(`Re-validating checkpoint ${checkpoint.number} before L1 submission`);
|
|
1296
|
+
await this.validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, simulationOverridesPlan);
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1294
1299
|
this.log.verbose(`Enqueuing checkpoint propose transaction`, {
|
|
1295
1300
|
...checkpoint.toCheckpointInfo(),
|
|
1296
|
-
|
|
1301
|
+
txTimeoutAt: opts.txTimeoutAt,
|
|
1302
|
+
simulationOverridesPlan
|
|
1297
1303
|
});
|
|
1298
|
-
await this.addProposeTx(checkpoint, proposeTxArgs,
|
|
1304
|
+
await this.addProposeTx(checkpoint, proposeTxArgs, {
|
|
1305
|
+
txTimeoutAt: opts.txTimeoutAt,
|
|
1306
|
+
simulationOverridesPlan
|
|
1307
|
+
}, preCheck);
|
|
1299
1308
|
}
|
|
1300
1309
|
enqueueInvalidateCheckpoint(request, opts = {}) {
|
|
1301
1310
|
if (!request) {
|
|
@@ -1336,7 +1345,8 @@ export class SequencerPublisher {
|
|
|
1336
1345
|
}
|
|
1337
1346
|
});
|
|
1338
1347
|
}
|
|
1339
|
-
async simulateAndEnqueueRequest(action, request, checkSuccess, slotNumber
|
|
1348
|
+
async simulateAndEnqueueRequest(action, request, checkSuccess, slotNumber) {
|
|
1349
|
+
const timestamp = this.getSimulationTimestamp(slotNumber);
|
|
1340
1350
|
const logData = {
|
|
1341
1351
|
slotNumber,
|
|
1342
1352
|
timestamp,
|
|
@@ -1358,7 +1368,7 @@ export class SequencerPublisher {
|
|
|
1358
1368
|
try {
|
|
1359
1369
|
({ gasUsed } = await this.l1TxUtils.simulate(request, {
|
|
1360
1370
|
time: timestamp
|
|
1361
|
-
}, [], simulateAbi));
|
|
1371
|
+
}, [], simulateAbi));
|
|
1362
1372
|
this.log.verbose(`Simulation for ${action} succeeded`, {
|
|
1363
1373
|
...logData,
|
|
1364
1374
|
request,
|
|
@@ -1433,13 +1443,14 @@ export class SequencerPublisher {
|
|
|
1433
1443
|
* A call to `restart` is required before you can continue publishing.
|
|
1434
1444
|
*/ interrupt() {
|
|
1435
1445
|
this.interrupted = true;
|
|
1446
|
+
this.interruptibleSleep.interrupt();
|
|
1436
1447
|
this.l1TxUtils.interrupt();
|
|
1437
1448
|
}
|
|
1438
1449
|
/** Restarts the publisher after calling `interrupt`. */ restart() {
|
|
1439
1450
|
this.interrupted = false;
|
|
1440
1451
|
this.l1TxUtils.restart();
|
|
1441
1452
|
}
|
|
1442
|
-
async prepareProposeTx(encodedData,
|
|
1453
|
+
async prepareProposeTx(encodedData, simulationOverridesPlan) {
|
|
1443
1454
|
const kzg = Blob.getViemKzgInstance();
|
|
1444
1455
|
const blobInput = getPrefixedEthBlobCommitments(encodedData.blobs);
|
|
1445
1456
|
this.log.debug('Validating blob input', {
|
|
@@ -1516,7 +1527,7 @@ export class SequencerPublisher {
|
|
|
1516
1527
|
encodedData.attestationsAndSignersSignature.toViemSignature(),
|
|
1517
1528
|
blobInput
|
|
1518
1529
|
];
|
|
1519
|
-
const { rollupData, simulationResult } = await this.simulateProposeTx(args,
|
|
1530
|
+
const { rollupData, simulationResult } = await this.simulateProposeTx(args, simulationOverridesPlan);
|
|
1520
1531
|
return {
|
|
1521
1532
|
args,
|
|
1522
1533
|
blobEvaluationGas,
|
|
@@ -1527,29 +1538,14 @@ export class SequencerPublisher {
|
|
|
1527
1538
|
/**
|
|
1528
1539
|
* Simulates the propose tx with eth_simulateV1
|
|
1529
1540
|
* @param args - The propose tx args
|
|
1530
|
-
* @param timestamp - The timestamp to simulate proposal at
|
|
1531
1541
|
* @returns The simulation result
|
|
1532
|
-
*/ async simulateProposeTx(args,
|
|
1542
|
+
*/ async simulateProposeTx(args, simulationOverridesPlan) {
|
|
1533
1543
|
const rollupData = encodeFunctionData({
|
|
1534
1544
|
abi: RollupAbi,
|
|
1535
1545
|
functionName: 'propose',
|
|
1536
1546
|
args
|
|
1537
1547
|
});
|
|
1538
|
-
|
|
1539
|
-
const forcePendingCheckpointNumberStateDiff = (options.forcePendingCheckpointNumber !== undefined ? await this.rollupContract.makePendingCheckpointNumberOverride(options.forcePendingCheckpointNumber) : []).flatMap((override)=>override.stateDiff ?? []);
|
|
1540
|
-
const stateOverrides = [
|
|
1541
|
-
{
|
|
1542
|
-
address: this.rollupContract.address,
|
|
1543
|
-
// @note we override checkBlob to false since blobs are not part simulate()
|
|
1544
|
-
stateDiff: [
|
|
1545
|
-
{
|
|
1546
|
-
slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true),
|
|
1547
|
-
value: toPaddedHex(0n, true)
|
|
1548
|
-
},
|
|
1549
|
-
...forcePendingCheckpointNumberStateDiff
|
|
1550
|
-
]
|
|
1551
|
-
}
|
|
1552
|
-
];
|
|
1548
|
+
const stateOverrides = await buildSimulationOverridesStateOverride(this.rollupContract, simulationOverridesPlan);
|
|
1553
1549
|
// In fisherman mode, simulate as the proposer but with sufficient balance
|
|
1554
1550
|
if (this.proposerAddressForSimulation) {
|
|
1555
1551
|
stateOverrides.push({
|
|
@@ -1558,6 +1554,7 @@ export class SequencerPublisher {
|
|
|
1558
1554
|
});
|
|
1559
1555
|
}
|
|
1560
1556
|
const l1BlockNumber = await this.l1TxUtils.getBlockNumber();
|
|
1557
|
+
const simTs = this.getSimulationTimestamp(SlotNumber.fromBigInt(args[0].header.slotNumber));
|
|
1561
1558
|
const simulationResult = await this.l1TxUtils.simulate({
|
|
1562
1559
|
to: this.rollupContract.address,
|
|
1563
1560
|
data: rollupData,
|
|
@@ -1566,8 +1563,7 @@ export class SequencerPublisher {
|
|
|
1566
1563
|
from: this.proposerAddressForSimulation.toString()
|
|
1567
1564
|
}
|
|
1568
1565
|
}, {
|
|
1569
|
-
|
|
1570
|
-
time: timestamp + 1n,
|
|
1566
|
+
time: simTs,
|
|
1571
1567
|
// @note reth should have a 30m gas limit per block but throws errors that this tx is beyond limit so we increase here
|
|
1572
1568
|
gasLimit: MAX_L1_TX_LIMIT * 2n
|
|
1573
1569
|
}, stateOverrides, RollupAbi, {
|
|
@@ -1584,7 +1580,9 @@ export class SequencerPublisher {
|
|
|
1584
1580
|
logs: []
|
|
1585
1581
|
};
|
|
1586
1582
|
}
|
|
1587
|
-
this.log.error(`Failed to simulate propose tx`, viemError
|
|
1583
|
+
this.log.error(`Failed to simulate propose tx`, viemError, {
|
|
1584
|
+
simulationTimestamp: simTs
|
|
1585
|
+
});
|
|
1588
1586
|
this.backupFailedTx({
|
|
1589
1587
|
id: keccak256(rollupData),
|
|
1590
1588
|
failureType: 'simulation',
|
|
@@ -1612,11 +1610,11 @@ export class SequencerPublisher {
|
|
|
1612
1610
|
simulationResult
|
|
1613
1611
|
};
|
|
1614
1612
|
}
|
|
1615
|
-
async addProposeTx(checkpoint, encodedData, opts = {},
|
|
1613
|
+
async addProposeTx(checkpoint, encodedData, opts = {}, preCheck) {
|
|
1616
1614
|
const slot = checkpoint.header.slotNumber;
|
|
1617
1615
|
const timer = new Timer();
|
|
1618
1616
|
const kzg = Blob.getViemKzgInstance();
|
|
1619
|
-
const { rollupData, simulationResult, blobEvaluationGas } = await this.prepareProposeTx(encodedData,
|
|
1617
|
+
const { rollupData, simulationResult, blobEvaluationGas } = await this.prepareProposeTx(encodedData, opts.simulationOverridesPlan);
|
|
1620
1618
|
const startBlock = await this.l1TxUtils.getBlockNumber();
|
|
1621
1619
|
const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(simulationResult.gasUsed) * 64 / 63)) + blobEvaluationGas + SequencerPublisher.MULTICALL_OVERHEAD_GAS_GUESS);
|
|
1622
1620
|
// Send the blobs to the blob client preemptively. This helps in tests where the sequencer mistakingly thinks that the propose
|
|
@@ -1632,9 +1630,10 @@ export class SequencerPublisher {
|
|
|
1632
1630
|
},
|
|
1633
1631
|
lastValidL2Slot: checkpoint.header.slotNumber,
|
|
1634
1632
|
gasConfig: {
|
|
1635
|
-
|
|
1633
|
+
txTimeoutAt: opts.txTimeoutAt,
|
|
1636
1634
|
gasLimit
|
|
1637
1635
|
},
|
|
1636
|
+
preCheck,
|
|
1638
1637
|
blobConfig: {
|
|
1639
1638
|
blobs: encodedData.blobs.map((b)=>b.data),
|
|
1640
1639
|
kzg
|
|
@@ -1681,4 +1680,13 @@ export class SequencerPublisher {
|
|
|
1681
1680
|
}
|
|
1682
1681
|
});
|
|
1683
1682
|
}
|
|
1683
|
+
/** Returns the timestamp of the last L1 slot within a given L2 slot. Used as the simulation timestamp
|
|
1684
|
+
* for eth_simulateV1 calls, since it's guaranteed to be greater than any L1 block produced during the slot. */ getSimulationTimestamp(slot) {
|
|
1685
|
+
const l1Constants = this.epochCache.getL1Constants();
|
|
1686
|
+
return getLastL1SlotTimestampForL2Slot(slot, l1Constants);
|
|
1687
|
+
}
|
|
1688
|
+
/** Returns the timestamp of the next L1 slot boundary after now. */ getNextL1SlotTimestamp() {
|
|
1689
|
+
const l1Constants = this.epochCache.getL1Constants();
|
|
1690
|
+
return getNextL1SlotTimestamp(this.dateProvider.nowInSeconds(), l1Constants);
|
|
1691
|
+
}
|
|
1684
1692
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RollupContract, type SimulationOverridesPlan } from '@aztec/ethereum/contracts';
|
|
2
|
+
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
5
|
+
import type { ProposedCheckpointData } from '@aztec/stdlib/checkpoint';
|
|
6
|
+
type PipelinedParentSimulationOverridesPlanInput = {
|
|
7
|
+
checkpointNumber: CheckpointNumber;
|
|
8
|
+
proposedCheckpointData?: ProposedCheckpointData;
|
|
9
|
+
rollup: RollupContract;
|
|
10
|
+
log: Logger;
|
|
11
|
+
};
|
|
12
|
+
type SubmissionSimulationOverridesPlanInput = {
|
|
13
|
+
pipelinedParentPlan?: SimulationOverridesPlan;
|
|
14
|
+
invalidateToPendingCheckpointNumber?: CheckpointNumber;
|
|
15
|
+
lastArchiveRoot: Fr;
|
|
16
|
+
pipeliningEnabled: boolean;
|
|
17
|
+
};
|
|
18
|
+
/** Builds the simulated parent checkpoint view used while constructing a pipelined proposal. */
|
|
19
|
+
export declare function buildPipelinedParentSimulationOverridesPlan(input: PipelinedParentSimulationOverridesPlanInput): Promise<SimulationOverridesPlan | undefined>;
|
|
20
|
+
/** Builds the simulated chain view used when validating and enqueueing checkpoint submission. */
|
|
21
|
+
export declare function buildSubmissionSimulationOverridesPlan(input: SubmissionSimulationOverridesPlanInput): SimulationOverridesPlan | undefined;
|
|
22
|
+
/** Derives the pending parent fee header used during pipelined proposal simulation. */
|
|
23
|
+
export declare function computePipelinedParentFeeHeader(input: PipelinedParentSimulationOverridesPlanInput): Promise<import("@aztec/ethereum/contracts").FeeHeader | undefined>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhaW5fc3RhdGVfb3ZlcnJpZGVzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VxdWVuY2VyL2NoYWluX3N0YXRlX292ZXJyaWRlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUE4QixLQUFLLHVCQUF1QixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckgsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDekQsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxLQUFLLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RSxLQUFLLDJDQUEyQyxHQUFHO0lBQ2pELGdCQUFnQixFQUFFLGdCQUFnQixDQUFDO0lBQ25DLHNCQUFzQixDQUFDLEVBQUUsc0JBQXNCLENBQUM7SUFDaEQsTUFBTSxFQUFFLGNBQWMsQ0FBQztJQUN2QixHQUFHLEVBQUUsTUFBTSxDQUFDO0NBQ2IsQ0FBQztBQUVGLEtBQUssc0NBQXNDLEdBQUc7SUFDNUMsbUJBQW1CLENBQUMsRUFBRSx1QkFBdUIsQ0FBQztJQUM5QyxtQ0FBbUMsQ0FBQyxFQUFFLGdCQUFnQixDQUFDO0lBQ3ZELGVBQWUsRUFBRSxFQUFFLENBQUM7SUFDcEIsaUJBQWlCLEVBQUUsT0FBTyxDQUFDO0NBQzVCLENBQUM7QUFFRixnR0FBZ0c7QUFDaEcsd0JBQXNCLDJDQUEyQyxDQUMvRCxLQUFLLEVBQUUsMkNBQTJDLEdBQ2pELE9BQU8sQ0FBQyx1QkFBdUIsR0FBRyxTQUFTLENBQUMsQ0FVOUM7QUFFRCxpR0FBaUc7QUFDakcsd0JBQWdCLHNDQUFzQyxDQUNwRCxLQUFLLEVBQUUsc0NBQXNDLEdBQzVDLHVCQUF1QixHQUFHLFNBQVMsQ0FhckM7QUFFRCx1RkFBdUY7QUFDdkYsd0JBQXNCLCtCQUErQixDQUFDLEtBQUssRUFBRSwyQ0FBMkMsc0VBZ0N2RyJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain_state_overrides.d.ts","sourceRoot":"","sources":["../../src/sequencer/chain_state_overrides.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA8B,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACrH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE,KAAK,2CAA2C,GAAG;IACjD,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD,MAAM,EAAE,cAAc,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,KAAK,sCAAsC,GAAG;IAC5C,mBAAmB,CAAC,EAAE,uBAAuB,CAAC;IAC9C,mCAAmC,CAAC,EAAE,gBAAgB,CAAC;IACvD,eAAe,EAAE,EAAE,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,gGAAgG;AAChG,wBAAsB,2CAA2C,CAC/D,KAAK,EAAE,2CAA2C,GACjD,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAU9C;AAED,iGAAiG;AACjG,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,sCAAsC,GAC5C,uBAAuB,GAAG,SAAS,CAarC;AAED,uFAAuF;AACvF,wBAAsB,+BAA+B,CAAC,KAAK,EAAE,2CAA2C,sEAgCvG"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RollupContract, SimulationOverridesBuilder } from '@aztec/ethereum/contracts';
|
|
2
|
+
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
/** Builds the simulated parent checkpoint view used while constructing a pipelined proposal. */ export async function buildPipelinedParentSimulationOverridesPlan(input) {
|
|
4
|
+
const parentCheckpointNumber = CheckpointNumber(input.checkpointNumber - 1);
|
|
5
|
+
const builder = new SimulationOverridesBuilder().forPendingCheckpoint(parentCheckpointNumber);
|
|
6
|
+
const pendingFeeHeader = await computePipelinedParentFeeHeader(input);
|
|
7
|
+
if (pendingFeeHeader) {
|
|
8
|
+
builder.withPendingFeeHeader(pendingFeeHeader);
|
|
9
|
+
}
|
|
10
|
+
return builder.build();
|
|
11
|
+
}
|
|
12
|
+
/** Builds the simulated chain view used when validating and enqueueing checkpoint submission. */ export function buildSubmissionSimulationOverridesPlan(input) {
|
|
13
|
+
const pendingCheckpointNumber = input.invalidateToPendingCheckpointNumber ?? input.pipelinedParentPlan?.pendingCheckpointNumber;
|
|
14
|
+
const builder = SimulationOverridesBuilder.from(input.pipelinedParentPlan).forPendingCheckpoint(pendingCheckpointNumber);
|
|
15
|
+
if (input.pipeliningEnabled && pendingCheckpointNumber !== undefined) {
|
|
16
|
+
builder.withPendingArchive(input.lastArchiveRoot);
|
|
17
|
+
}
|
|
18
|
+
return builder.build();
|
|
19
|
+
}
|
|
20
|
+
/** Derives the pending parent fee header used during pipelined proposal simulation. */ export async function computePipelinedParentFeeHeader(input) {
|
|
21
|
+
if (!input.proposedCheckpointData || input.checkpointNumber < 2) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const grandparentCheckpointNumber = CheckpointNumber(input.checkpointNumber - 2);
|
|
25
|
+
try {
|
|
26
|
+
const [grandparentCheckpoint, manaTarget] = await Promise.all([
|
|
27
|
+
input.rollup.getCheckpoint(grandparentCheckpointNumber),
|
|
28
|
+
input.rollup.getManaTarget()
|
|
29
|
+
]);
|
|
30
|
+
if (!grandparentCheckpoint?.feeHeader) {
|
|
31
|
+
input.log.error(`Grandparent checkpoint or feeHeader missing for checkpoint ${grandparentCheckpointNumber.toString()}`);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return RollupContract.computeChildFeeHeader(grandparentCheckpoint.feeHeader, input.proposedCheckpointData.totalManaUsed, input.proposedCheckpointData.feeAssetPriceModifier, manaTarget);
|
|
35
|
+
} catch (err) {
|
|
36
|
+
input.log.error(`Failed to derive pipelined parent fee header for checkpoint ${grandparentCheckpointNumber.toString()}: ${err}`);
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|