@aztec/sequencer-client 0.0.1-commit.b655e406 → 0.0.1-commit.c7c42ec
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/index.d.ts +1 -1
- package/dest/client/sequencer-client.d.ts +10 -9
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +32 -24
- package/dest/config.d.ts +12 -5
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +75 -28
- package/dest/global_variable_builder/global_builder.d.ts +19 -13
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +41 -28
- package/dest/global_variable_builder/index.d.ts +1 -1
- package/dest/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/publisher/config.d.ts +9 -4
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +14 -3
- package/dest/publisher/index.d.ts +1 -1
- package/dest/publisher/sequencer-publisher-factory.d.ts +5 -4
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +1 -1
- package/dest/publisher/sequencer-publisher-metrics.d.ts +3 -3
- package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.d.ts +66 -53
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +230 -120
- package/dest/sequencer/block_builder.d.ts +4 -5
- package/dest/sequencer/block_builder.d.ts.map +1 -1
- package/dest/sequencer/block_builder.js +9 -10
- package/dest/sequencer/checkpoint_builder.d.ts +63 -0
- package/dest/sequencer/checkpoint_builder.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_builder.js +131 -0
- package/dest/sequencer/checkpoint_proposal_job.d.ts +74 -0
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_proposal_job.js +642 -0
- package/dest/sequencer/checkpoint_voter.d.ts +34 -0
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_voter.js +85 -0
- package/dest/sequencer/config.d.ts +3 -2
- package/dest/sequencer/config.d.ts.map +1 -1
- package/dest/sequencer/errors.d.ts +1 -1
- package/dest/sequencer/errors.d.ts.map +1 -1
- package/dest/sequencer/events.d.ts +46 -0
- package/dest/sequencer/events.d.ts.map +1 -0
- package/dest/sequencer/events.js +1 -0
- package/dest/sequencer/index.d.ts +5 -1
- package/dest/sequencer/index.d.ts.map +1 -1
- package/dest/sequencer/index.js +4 -0
- package/dest/sequencer/metrics.d.ts +32 -3
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +192 -0
- package/dest/sequencer/sequencer.d.ts +96 -138
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +247 -479
- package/dest/sequencer/timetable.d.ts +54 -14
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +148 -59
- package/dest/sequencer/types.d.ts +3 -0
- package/dest/sequencer/types.d.ts.map +1 -0
- package/dest/sequencer/types.js +1 -0
- package/dest/sequencer/utils.d.ts +14 -8
- package/dest/sequencer/utils.d.ts.map +1 -1
- package/dest/sequencer/utils.js +7 -4
- package/dest/test/index.d.ts +4 -2
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.d.ts +83 -0
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -0
- package/dest/test/mock_checkpoint_builder.js +179 -0
- package/dest/test/utils.d.ts +49 -0
- package/dest/test/utils.d.ts.map +1 -0
- package/dest/test/utils.js +94 -0
- package/dest/tx_validator/nullifier_cache.d.ts +1 -1
- package/dest/tx_validator/nullifier_cache.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.d.ts +4 -3
- package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.js +1 -1
- package/package.json +31 -30
- package/src/client/sequencer-client.ts +28 -38
- package/src/config.ts +81 -32
- package/src/global_variable_builder/global_builder.ts +56 -48
- package/src/index.ts +2 -0
- package/src/publisher/config.ts +20 -9
- package/src/publisher/sequencer-publisher-factory.ts +7 -5
- package/src/publisher/sequencer-publisher-metrics.ts +2 -2
- package/src/publisher/sequencer-publisher.ts +328 -161
- package/src/sequencer/README.md +531 -0
- package/src/sequencer/block_builder.ts +12 -13
- package/src/sequencer/checkpoint_builder.ts +217 -0
- package/src/sequencer/checkpoint_proposal_job.ts +706 -0
- package/src/sequencer/checkpoint_voter.ts +105 -0
- package/src/sequencer/config.ts +2 -1
- package/src/sequencer/events.ts +27 -0
- package/src/sequencer/index.ts +4 -0
- package/src/sequencer/metrics.ts +254 -3
- package/src/sequencer/sequencer.ts +360 -674
- package/src/sequencer/timetable.ts +173 -79
- package/src/sequencer/types.ts +6 -0
- package/src/sequencer/utils.ts +18 -9
- package/src/test/index.ts +3 -1
- package/src/test/mock_checkpoint_builder.ts +247 -0
- package/src/test/utils.ts +137 -0
- package/src/tx_validator/tx_validator_factory.ts +3 -2
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { Blob, getBlobsPerL1Block, getPrefixedEthBlobCommitments } from '@aztec/blob-lib';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { MULTI_CALL_3_ADDRESS, Multicall3, RollupContract } from '@aztec/ethereum/contracts';
|
|
3
|
+
import { L1FeeAnalyzer } from '@aztec/ethereum/l1-fee-analysis';
|
|
4
|
+
import { WEI_CONST } from '@aztec/ethereum/l1-tx-utils';
|
|
5
|
+
import { FormattedViemError, formatViemError, tryExtractEvent } from '@aztec/ethereum/utils';
|
|
4
6
|
import { sumBigint } from '@aztec/foundation/bigint';
|
|
5
7
|
import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
|
|
8
|
+
import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
9
|
+
import { pick } from '@aztec/foundation/collection';
|
|
6
10
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
7
11
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
8
12
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -10,7 +14,7 @@ import { bufferToHex } from '@aztec/foundation/string';
|
|
|
10
14
|
import { Timer } from '@aztec/foundation/timer';
|
|
11
15
|
import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
12
16
|
import { encodeSlashConsensusVotes } from '@aztec/slasher';
|
|
13
|
-
import {
|
|
17
|
+
import { CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
14
18
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
15
19
|
import { encodeFunctionData, toHex } from 'viem';
|
|
16
20
|
import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js';
|
|
@@ -35,9 +39,12 @@ export class SequencerPublisher {
|
|
|
35
39
|
governanceLog;
|
|
36
40
|
slashingLog;
|
|
37
41
|
lastActions;
|
|
42
|
+
isPayloadEmptyCache;
|
|
38
43
|
log;
|
|
39
44
|
ethereumSlotDuration;
|
|
40
|
-
|
|
45
|
+
blobClient;
|
|
46
|
+
/** Address to use for simulations in fisherman mode (actual proposer's address) */ proposerAddressForSimulation;
|
|
47
|
+
/** L1 fee analyzer for fisherman mode */ l1FeeAnalyzer;
|
|
41
48
|
// @note - with blobs, the below estimate seems too large.
|
|
42
49
|
// Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob)
|
|
43
50
|
// Total used for emptier block from above test: 429k (of which 84k is 1x blob)
|
|
@@ -58,14 +65,13 @@ export class SequencerPublisher {
|
|
|
58
65
|
this.governanceLog = createLogger('sequencer:publisher:governance');
|
|
59
66
|
this.slashingLog = createLogger('sequencer:publisher:slashing');
|
|
60
67
|
this.lastActions = {};
|
|
68
|
+
this.isPayloadEmptyCache = new Map();
|
|
61
69
|
this.requests = [];
|
|
62
70
|
this.log = deps.log ?? createLogger('sequencer:publisher');
|
|
63
71
|
this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
|
|
64
72
|
this.epochCache = deps.epochCache;
|
|
65
73
|
this.lastActions = deps.lastActions;
|
|
66
|
-
this.
|
|
67
|
-
logger: createLogger('sequencer:blob-sink:client')
|
|
68
|
-
});
|
|
74
|
+
this.blobClient = deps.blobClient;
|
|
69
75
|
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
70
76
|
this.metrics = deps.metrics ?? new SequencerPublisherMetrics(telemetry, 'SequencerPublisher');
|
|
71
77
|
this.l1TxUtils = deps.l1TxUtils;
|
|
@@ -78,6 +84,10 @@ export class SequencerPublisher {
|
|
|
78
84
|
this.slashingProposerContract = newSlashingProposer;
|
|
79
85
|
});
|
|
80
86
|
this.slashFactoryContract = deps.slashFactoryContract;
|
|
87
|
+
// Initialize L1 fee analyzer for fisherman mode
|
|
88
|
+
if (config.fishermanMode) {
|
|
89
|
+
this.l1FeeAnalyzer = new L1FeeAnalyzer(this.l1TxUtils.client, deps.dateProvider, createLogger('sequencer:publisher:fee-analyzer'));
|
|
90
|
+
}
|
|
81
91
|
}
|
|
82
92
|
getRollupContract() {
|
|
83
93
|
return this.rollupContract;
|
|
@@ -85,6 +95,17 @@ export class SequencerPublisher {
|
|
|
85
95
|
getSenderAddress() {
|
|
86
96
|
return this.l1TxUtils.getSenderAddress();
|
|
87
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Gets the L1 fee analyzer instance (only available in fisherman mode)
|
|
100
|
+
*/ getL1FeeAnalyzer() {
|
|
101
|
+
return this.l1FeeAnalyzer;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Sets the proposer address to use for simulations in fisherman mode.
|
|
105
|
+
* @param proposerAddress - The actual proposer's address to use for balance lookups in simulations
|
|
106
|
+
*/ setProposerAddressForSimulation(proposerAddress) {
|
|
107
|
+
this.proposerAddressForSimulation = proposerAddress;
|
|
108
|
+
}
|
|
88
109
|
addRequest(request) {
|
|
89
110
|
this.requests.push(request);
|
|
90
111
|
}
|
|
@@ -92,6 +113,55 @@ export class SequencerPublisher {
|
|
|
92
113
|
return this.epochCache.getEpochAndSlotNow().slot;
|
|
93
114
|
}
|
|
94
115
|
/**
|
|
116
|
+
* Clears all pending requests without sending them.
|
|
117
|
+
*/ clearPendingRequests() {
|
|
118
|
+
const count = this.requests.length;
|
|
119
|
+
this.requests = [];
|
|
120
|
+
if (count > 0) {
|
|
121
|
+
this.log.debug(`Cleared ${count} pending request(s)`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Analyzes L1 fees for the pending requests without sending them.
|
|
126
|
+
* This is used in fisherman mode to validate fee calculations.
|
|
127
|
+
* @param l2SlotNumber - The L2 slot number for this analysis
|
|
128
|
+
* @param onComplete - Optional callback to invoke when analysis completes (after block is mined)
|
|
129
|
+
* @returns The analysis result (incomplete until block mines), or undefined if no requests
|
|
130
|
+
*/ async analyzeL1Fees(l2SlotNumber, onComplete) {
|
|
131
|
+
if (!this.l1FeeAnalyzer) {
|
|
132
|
+
this.log.warn('L1 fee analyzer not available (not in fisherman mode)');
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
const requestsToAnalyze = [
|
|
136
|
+
...this.requests
|
|
137
|
+
];
|
|
138
|
+
if (requestsToAnalyze.length === 0) {
|
|
139
|
+
this.log.debug('No requests to analyze for L1 fees');
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
// Extract blob config from requests (if any)
|
|
143
|
+
const blobConfigs = requestsToAnalyze.filter((request)=>request.blobConfig).map((request)=>request.blobConfig);
|
|
144
|
+
const blobConfig = blobConfigs[0];
|
|
145
|
+
// Get gas configs
|
|
146
|
+
const gasConfigs = requestsToAnalyze.filter((request)=>request.gasConfig).map((request)=>request.gasConfig);
|
|
147
|
+
const gasLimits = gasConfigs.map((g)=>g?.gasLimit).filter((g)=>g !== undefined);
|
|
148
|
+
const gasLimit = gasLimits.length > 0 ? gasLimits.reduce((sum, g)=>sum + g, 0n) : 0n;
|
|
149
|
+
// Get the transaction requests
|
|
150
|
+
const l1Requests = requestsToAnalyze.map((r)=>r.request);
|
|
151
|
+
// Start the analysis
|
|
152
|
+
const analysisId = await this.l1FeeAnalyzer.startAnalysis(l2SlotNumber, gasLimit > 0n ? gasLimit : SequencerPublisher.PROPOSE_GAS_GUESS, l1Requests, blobConfig, onComplete);
|
|
153
|
+
this.log.info('Started L1 fee analysis', {
|
|
154
|
+
analysisId,
|
|
155
|
+
l2SlotNumber: l2SlotNumber.toString(),
|
|
156
|
+
requestCount: requestsToAnalyze.length,
|
|
157
|
+
hasBlobConfig: !!blobConfig,
|
|
158
|
+
gasLimit: gasLimit.toString(),
|
|
159
|
+
actions: requestsToAnalyze.map((r)=>r.action)
|
|
160
|
+
});
|
|
161
|
+
// Return the analysis result (will be incomplete until block mines)
|
|
162
|
+
return this.l1FeeAnalyzer.getAnalysis(analysisId);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
95
165
|
* Sends all requests that are still valid.
|
|
96
166
|
* @returns one of:
|
|
97
167
|
* - A receipt and stats if the tx succeeded
|
|
@@ -102,7 +172,7 @@ export class SequencerPublisher {
|
|
|
102
172
|
...this.requests
|
|
103
173
|
];
|
|
104
174
|
this.requests = [];
|
|
105
|
-
if (this.interrupted) {
|
|
175
|
+
if (this.interrupted || requestsToProcess.length === 0) {
|
|
106
176
|
return undefined;
|
|
107
177
|
}
|
|
108
178
|
const currentL2Slot = this.getCurrentL2Slot();
|
|
@@ -211,7 +281,9 @@ export class SequencerPublisher {
|
|
|
211
281
|
'InvalidProposer',
|
|
212
282
|
'InvalidArchive'
|
|
213
283
|
];
|
|
214
|
-
return this.rollupContract.canProposeAtNextEthBlock(tipArchive.toBuffer(), msgSender.toString(), this.ethereumSlotDuration,
|
|
284
|
+
return this.rollupContract.canProposeAtNextEthBlock(tipArchive.toBuffer(), msgSender.toString(), Number(this.ethereumSlotDuration), {
|
|
285
|
+
forcePendingCheckpointNumber: opts.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(opts.forcePendingBlockNumber) : undefined
|
|
286
|
+
}).catch((err)=>{
|
|
215
287
|
if (err instanceof FormattedViemError && ignoredErrors.find((e)=>err.message.includes(e))) {
|
|
216
288
|
this.log.warn(`Failed canProposeAtTime check with ${ignoredErrors.find((e)=>err.message.includes(e))}`, {
|
|
217
289
|
error: err.message
|
|
@@ -242,9 +314,20 @@ export class SequencerPublisher {
|
|
|
242
314
|
flags
|
|
243
315
|
];
|
|
244
316
|
const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
|
|
317
|
+
const optsForcePendingCheckpointNumber = opts?.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(opts.forcePendingBlockNumber) : undefined;
|
|
318
|
+
const stateOverrides = await this.rollupContract.makePendingCheckpointNumberOverride(optsForcePendingCheckpointNumber);
|
|
319
|
+
let balance = 0n;
|
|
320
|
+
if (this.config.fishermanMode) {
|
|
321
|
+
// In fisherman mode, we can't know where the proposer is publishing from
|
|
322
|
+
// so we just add sufficient balance to the multicall3 address
|
|
323
|
+
balance = 10n * WEI_CONST * WEI_CONST; // 10 ETH
|
|
324
|
+
} else {
|
|
325
|
+
balance = await this.l1TxUtils.getSenderBalance();
|
|
326
|
+
}
|
|
327
|
+
stateOverrides.push({
|
|
328
|
+
address: MULTI_CALL_3_ADDRESS,
|
|
329
|
+
balance
|
|
330
|
+
});
|
|
248
331
|
await this.l1TxUtils.simulate({
|
|
249
332
|
to: this.rollupContract.address,
|
|
250
333
|
data: encodeFunctionData({
|
|
@@ -255,13 +338,7 @@ export class SequencerPublisher {
|
|
|
255
338
|
from: MULTI_CALL_3_ADDRESS
|
|
256
339
|
}, {
|
|
257
340
|
time: ts + 1n
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
address: MULTI_CALL_3_ADDRESS,
|
|
261
|
-
balance
|
|
262
|
-
},
|
|
263
|
-
...await this.rollupContract.makePendingBlockNumberOverride(opts?.forcePendingBlockNumber)
|
|
264
|
-
]);
|
|
341
|
+
}, stateOverrides);
|
|
265
342
|
this.log.debug(`Simulated validateHeader`);
|
|
266
343
|
}
|
|
267
344
|
/**
|
|
@@ -277,7 +354,7 @@ export class SequencerPublisher {
|
|
|
277
354
|
...block,
|
|
278
355
|
reason
|
|
279
356
|
};
|
|
280
|
-
const currentBlockNumber = await this.rollupContract.
|
|
357
|
+
const currentBlockNumber = await this.rollupContract.getCheckpointNumber();
|
|
281
358
|
if (currentBlockNumber < validationResult.block.blockNumber) {
|
|
282
359
|
this.log.verbose(`Skipping block ${blockNumber} invalidation since it has already been removed from the pending chain`, {
|
|
283
360
|
currentBlockNumber,
|
|
@@ -301,7 +378,7 @@ export class SequencerPublisher {
|
|
|
301
378
|
request,
|
|
302
379
|
gasUsed,
|
|
303
380
|
blockNumber,
|
|
304
|
-
forcePendingBlockNumber: blockNumber - 1,
|
|
381
|
+
forcePendingBlockNumber: BlockNumber(blockNumber - 1),
|
|
305
382
|
reason
|
|
306
383
|
};
|
|
307
384
|
} catch (err) {
|
|
@@ -314,7 +391,7 @@ export class SequencerPublisher {
|
|
|
314
391
|
request,
|
|
315
392
|
error: viemError.message
|
|
316
393
|
});
|
|
317
|
-
const latestPendingBlockNumber = await this.rollupContract.
|
|
394
|
+
const latestPendingBlockNumber = await this.rollupContract.getCheckpointNumber();
|
|
318
395
|
if (latestPendingBlockNumber < blockNumber) {
|
|
319
396
|
this.log.verbose(`Block number ${blockNumber} has already been invalidated`, {
|
|
320
397
|
...logData
|
|
@@ -346,43 +423,37 @@ export class SequencerPublisher {
|
|
|
346
423
|
this.log.debug(`Simulating invalidate block ${block.blockNumber}`, logData);
|
|
347
424
|
const attestationsAndSigners = new CommitteeAttestationsAndSigners(validationResult.attestations).getPackedAttestations();
|
|
348
425
|
if (reason === 'invalid-attestation') {
|
|
349
|
-
return this.rollupContract.buildInvalidateBadAttestationRequest(block.blockNumber, attestationsAndSigners, committee, validationResult.invalidIndex);
|
|
426
|
+
return this.rollupContract.buildInvalidateBadAttestationRequest(CheckpointNumber.fromBlockNumber(block.blockNumber), attestationsAndSigners, committee, validationResult.invalidIndex);
|
|
350
427
|
} else if (reason === 'insufficient-attestations') {
|
|
351
|
-
return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(block.blockNumber, attestationsAndSigners, committee);
|
|
428
|
+
return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(CheckpointNumber.fromBlockNumber(block.blockNumber), attestationsAndSigners, committee);
|
|
352
429
|
} else {
|
|
353
430
|
const _ = reason;
|
|
354
431
|
throw new Error(`Unknown reason for invalidation`);
|
|
355
432
|
}
|
|
356
433
|
}
|
|
357
|
-
/**
|
|
358
|
-
* @notice Will simulate `propose` to make sure that the block is valid for submission
|
|
359
|
-
*
|
|
360
|
-
* @dev Throws if unable to propose
|
|
361
|
-
*
|
|
362
|
-
* @param block - The block to propose
|
|
363
|
-
* @param attestationData - The block's attestation data
|
|
364
|
-
*
|
|
365
|
-
*/ async validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, options) {
|
|
434
|
+
/** Simulates `propose` to make sure that the checkpoint is valid for submission */ async validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, options) {
|
|
366
435
|
const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
|
|
436
|
+
// TODO(palla/mbps): This should not be needed, there's no flow where we propose with zero attestations. Or is there?
|
|
367
437
|
// If we have no attestations, we still need to provide the empty attestations
|
|
368
438
|
// so that the committee is recalculated correctly
|
|
369
|
-
const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
|
|
370
|
-
if (ignoreSignatures) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
439
|
+
// const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
|
|
440
|
+
// if (ignoreSignatures) {
|
|
441
|
+
// const { committee } = await this.epochCache.getCommittee(block.header.globalVariables.slotNumber);
|
|
442
|
+
// if (!committee) {
|
|
443
|
+
// this.log.warn(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
|
|
444
|
+
// throw new Error(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
|
|
445
|
+
// }
|
|
446
|
+
// attestationsAndSigners.attestations = committee.map(committeeMember =>
|
|
447
|
+
// CommitteeAttestation.fromAddress(committeeMember),
|
|
448
|
+
// );
|
|
449
|
+
// }
|
|
450
|
+
const blobFields = checkpoint.toBlobFields();
|
|
379
451
|
const blobs = getBlobsPerL1Block(blobFields);
|
|
380
452
|
const blobInput = getPrefixedEthBlobCommitments(blobs);
|
|
381
453
|
const args = [
|
|
382
454
|
{
|
|
383
|
-
header:
|
|
384
|
-
archive: toHex(
|
|
385
|
-
stateReference: block.header.state.toViem(),
|
|
455
|
+
header: checkpoint.header.toViem(),
|
|
456
|
+
archive: toHex(checkpoint.archive.root.toBuffer()),
|
|
386
457
|
oracleInput: {
|
|
387
458
|
feeAssetPriceModifier: 0n
|
|
388
459
|
}
|
|
@@ -409,9 +480,16 @@ export class SequencerPublisher {
|
|
|
409
480
|
}
|
|
410
481
|
const round = await base.computeRound(slotNumber);
|
|
411
482
|
const roundInfo = await base.getRoundInfo(this.rollupContract.address, round);
|
|
483
|
+
if (roundInfo.quorumReached) {
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
412
486
|
if (roundInfo.lastSignalSlot >= slotNumber) {
|
|
413
487
|
return false;
|
|
414
488
|
}
|
|
489
|
+
if (await this.isPayloadEmpty(payload)) {
|
|
490
|
+
this.log.warn(`Skipping vote cast for payload with empty code`);
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
415
493
|
const cachedLastVote = this.lastActions[signalType];
|
|
416
494
|
this.lastActions[signalType] = slotNumber;
|
|
417
495
|
const action = signalType;
|
|
@@ -450,17 +528,27 @@ export class SequencerPublisher {
|
|
|
450
528
|
payload: payload.toString()
|
|
451
529
|
};
|
|
452
530
|
if (!success) {
|
|
453
|
-
this.log.error(`Signaling in
|
|
531
|
+
this.log.error(`Signaling in ${action} for ${payload} at slot ${slotNumber} in round ${round} failed`, logData);
|
|
454
532
|
this.lastActions[signalType] = cachedLastVote;
|
|
455
533
|
return false;
|
|
456
534
|
} else {
|
|
457
|
-
this.log.info(`Signaling in
|
|
535
|
+
this.log.info(`Signaling in ${action} for ${payload} at slot ${slotNumber} in round ${round} succeeded`, logData);
|
|
458
536
|
return true;
|
|
459
537
|
}
|
|
460
538
|
}
|
|
461
539
|
});
|
|
462
540
|
return true;
|
|
463
541
|
}
|
|
542
|
+
async isPayloadEmpty(payload) {
|
|
543
|
+
const key = payload.toString();
|
|
544
|
+
const cached = this.isPayloadEmptyCache.get(key);
|
|
545
|
+
if (cached) {
|
|
546
|
+
return cached;
|
|
547
|
+
}
|
|
548
|
+
const isEmpty = !await this.l1TxUtils.getCode(payload);
|
|
549
|
+
this.isPayloadEmptyCache.set(key, isEmpty);
|
|
550
|
+
return isEmpty;
|
|
551
|
+
}
|
|
464
552
|
/**
|
|
465
553
|
* Enqueues a governance castSignal transaction to cast a signal for a given slot number.
|
|
466
554
|
* @param slotNumber - The slot number to cast a signal for.
|
|
@@ -556,20 +644,13 @@ export class SequencerPublisher {
|
|
|
556
644
|
}
|
|
557
645
|
return true;
|
|
558
646
|
}
|
|
559
|
-
/**
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
* @param block - L2 block to propose.
|
|
563
|
-
* @returns True if the tx has been enqueued, throws otherwise. See #9315
|
|
564
|
-
*/ async enqueueProposeL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
|
|
565
|
-
const checkpointHeader = block.getCheckpointHeader();
|
|
566
|
-
const blobFields = block.getCheckpointBlobFields();
|
|
647
|
+
/** Simulates and enqueues a proposal for a checkpoint on L1 */ async enqueueProposeCheckpoint(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
|
|
648
|
+
const checkpointHeader = checkpoint.header;
|
|
649
|
+
const blobFields = checkpoint.toBlobFields();
|
|
567
650
|
const blobs = getBlobsPerL1Block(blobFields);
|
|
568
651
|
const proposeTxArgs = {
|
|
569
652
|
header: checkpointHeader,
|
|
570
|
-
archive:
|
|
571
|
-
stateReference: block.header.state,
|
|
572
|
-
body: block.body.toBuffer(),
|
|
653
|
+
archive: checkpoint.archive.root.toBuffer(),
|
|
573
654
|
blobs,
|
|
574
655
|
attestationsAndSigners,
|
|
575
656
|
attestationsAndSignersSignature
|
|
@@ -581,21 +662,20 @@ export class SequencerPublisher {
|
|
|
581
662
|
// By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which
|
|
582
663
|
// make time consistency checks break.
|
|
583
664
|
// TODO(palla): Check whether we're validating twice, once here and once within addProposeTx, since we call simulateProposeTx in both places.
|
|
584
|
-
ts = await this.
|
|
665
|
+
ts = await this.validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, opts);
|
|
585
666
|
} catch (err) {
|
|
586
|
-
this.log.error(`
|
|
587
|
-
...
|
|
588
|
-
slotNumber:
|
|
667
|
+
this.log.error(`Checkpoint validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
|
|
668
|
+
...checkpoint.getStats(),
|
|
669
|
+
slotNumber: checkpoint.header.slotNumber,
|
|
589
670
|
forcePendingBlockNumber: opts.forcePendingBlockNumber
|
|
590
671
|
});
|
|
591
672
|
throw err;
|
|
592
673
|
}
|
|
593
|
-
this.log.verbose(`Enqueuing
|
|
594
|
-
...
|
|
674
|
+
this.log.verbose(`Enqueuing checkpoint propose transaction`, {
|
|
675
|
+
...checkpoint.toCheckpointInfo(),
|
|
595
676
|
...opts
|
|
596
677
|
});
|
|
597
|
-
await this.addProposeTx(
|
|
598
|
-
return true;
|
|
678
|
+
await this.addProposeTx(checkpoint, proposeTxArgs, opts, ts);
|
|
599
679
|
}
|
|
600
680
|
enqueueInvalidateBlock(request, opts = {}) {
|
|
601
681
|
if (!request) {
|
|
@@ -618,9 +698,9 @@ export class SequencerPublisher {
|
|
|
618
698
|
gasLimit,
|
|
619
699
|
txTimeoutAt: opts.txTimeoutAt
|
|
620
700
|
},
|
|
621
|
-
lastValidL2Slot: this.getCurrentL2Slot() +
|
|
701
|
+
lastValidL2Slot: SlotNumber(this.getCurrentL2Slot() + 2),
|
|
622
702
|
checkSuccess: (_req, result)=>{
|
|
623
|
-
const success = result && result.receipt && result.receipt.status === 'success' && tryExtractEvent(result.receipt.logs, this.rollupContract.address, RollupAbi, '
|
|
703
|
+
const success = result && result.receipt && result.receipt.status === 'success' && tryExtractEvent(result.receipt.logs, this.rollupContract.address, RollupAbi, 'CheckpointInvalidated');
|
|
624
704
|
if (!success) {
|
|
625
705
|
this.log.warn(`Invalidate block ${request.blockNumber} failed`, {
|
|
626
706
|
...result,
|
|
@@ -713,31 +793,40 @@ export class SequencerPublisher {
|
|
|
713
793
|
this.log.debug('Validating blob input', {
|
|
714
794
|
blobInput
|
|
715
795
|
});
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
796
|
+
// Get blob evaluation gas
|
|
797
|
+
let blobEvaluationGas;
|
|
798
|
+
if (this.config.fishermanMode) {
|
|
799
|
+
// In fisherman mode, we can't estimate blob gas because estimateGas doesn't support state overrides
|
|
800
|
+
// Use a fixed estimate.
|
|
801
|
+
blobEvaluationGas = BigInt(encodedData.blobs.length) * 21_000n;
|
|
802
|
+
this.log.debug(`Using fixed blob evaluation gas estimate in fisherman mode: ${blobEvaluationGas}`);
|
|
803
|
+
} else {
|
|
804
|
+
// Normal mode - use estimateGas with blob inputs
|
|
805
|
+
blobEvaluationGas = await this.l1TxUtils.estimateGas(this.getSenderAddress().toString(), {
|
|
806
|
+
to: this.rollupContract.address,
|
|
807
|
+
data: encodeFunctionData({
|
|
808
|
+
abi: RollupAbi,
|
|
809
|
+
functionName: 'validateBlobs',
|
|
810
|
+
args: [
|
|
811
|
+
blobInput
|
|
812
|
+
]
|
|
813
|
+
})
|
|
814
|
+
}, {}, {
|
|
815
|
+
blobs: encodedData.blobs.map((b)=>b.data),
|
|
816
|
+
kzg
|
|
817
|
+
}).catch((err)=>{
|
|
818
|
+
const { message, metaMessages } = formatViemError(err);
|
|
819
|
+
this.log.error(`Failed to validate blobs`, message, {
|
|
820
|
+
metaMessages
|
|
821
|
+
});
|
|
822
|
+
throw new Error('Failed to validate blobs');
|
|
732
823
|
});
|
|
733
|
-
|
|
734
|
-
});
|
|
824
|
+
}
|
|
735
825
|
const signers = encodedData.attestationsAndSigners.getSigners().map((signer)=>signer.toString());
|
|
736
826
|
const args = [
|
|
737
827
|
{
|
|
738
828
|
header: encodedData.header.toViem(),
|
|
739
829
|
archive: toHex(encodedData.archive),
|
|
740
|
-
stateReference: encodedData.stateReference.toViem(),
|
|
741
830
|
oracleInput: {
|
|
742
831
|
// We are currently not modifying these. See #9963
|
|
743
832
|
feeAssetPriceModifier: 0n
|
|
@@ -767,18 +856,10 @@ export class SequencerPublisher {
|
|
|
767
856
|
functionName: 'propose',
|
|
768
857
|
args
|
|
769
858
|
});
|
|
770
|
-
// override the pending
|
|
771
|
-
const
|
|
772
|
-
const
|
|
773
|
-
|
|
774
|
-
data: rollupData,
|
|
775
|
-
gas: SequencerPublisher.PROPOSE_GAS_GUESS
|
|
776
|
-
}, {
|
|
777
|
-
// @note we add 1n to the timestamp because geth implementation doesn't like simulation timestamp to be equal to the current block timestamp
|
|
778
|
-
time: timestamp + 1n,
|
|
779
|
-
// @note reth should have a 30m gas limit per block but throws errors that this tx is beyond limit so we increase here
|
|
780
|
-
gasLimit: SequencerPublisher.PROPOSE_GAS_GUESS * 2n
|
|
781
|
-
}, [
|
|
859
|
+
// override the pending checkpoint number if requested
|
|
860
|
+
const optsForcePendingCheckpointNumber = options.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(options.forcePendingBlockNumber) : undefined;
|
|
861
|
+
const forcePendingCheckpointNumberStateDiff = (optsForcePendingCheckpointNumber !== undefined ? await this.rollupContract.makePendingCheckpointNumberOverride(optsForcePendingCheckpointNumber) : []).flatMap((override)=>override.stateDiff ?? []);
|
|
862
|
+
const stateOverrides = [
|
|
782
863
|
{
|
|
783
864
|
address: this.rollupContract.address,
|
|
784
865
|
// @note we override checkBlob to false since blobs are not part simulate()
|
|
@@ -787,14 +868,44 @@ export class SequencerPublisher {
|
|
|
787
868
|
slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true),
|
|
788
869
|
value: toPaddedHex(0n, true)
|
|
789
870
|
},
|
|
790
|
-
...
|
|
871
|
+
...forcePendingCheckpointNumberStateDiff
|
|
791
872
|
]
|
|
792
873
|
}
|
|
793
|
-
]
|
|
874
|
+
];
|
|
875
|
+
// In fisherman mode, simulate as the proposer but with sufficient balance
|
|
876
|
+
if (this.proposerAddressForSimulation) {
|
|
877
|
+
stateOverrides.push({
|
|
878
|
+
address: this.proposerAddressForSimulation.toString(),
|
|
879
|
+
balance: 10n * WEI_CONST * WEI_CONST
|
|
880
|
+
});
|
|
881
|
+
}
|
|
882
|
+
const simulationResult = await this.l1TxUtils.simulate({
|
|
883
|
+
to: this.rollupContract.address,
|
|
884
|
+
data: rollupData,
|
|
885
|
+
gas: SequencerPublisher.PROPOSE_GAS_GUESS,
|
|
886
|
+
...this.proposerAddressForSimulation && {
|
|
887
|
+
from: this.proposerAddressForSimulation.toString()
|
|
888
|
+
}
|
|
889
|
+
}, {
|
|
890
|
+
// @note we add 1n to the timestamp because geth implementation doesn't like simulation timestamp to be equal to the current block timestamp
|
|
891
|
+
time: timestamp + 1n,
|
|
892
|
+
// @note reth should have a 30m gas limit per block but throws errors that this tx is beyond limit so we increase here
|
|
893
|
+
gasLimit: SequencerPublisher.PROPOSE_GAS_GUESS * 2n
|
|
894
|
+
}, stateOverrides, RollupAbi, {
|
|
794
895
|
// @note fallback gas estimate to use if the node doesn't support simulation API
|
|
795
896
|
fallbackGasEstimate: SequencerPublisher.PROPOSE_GAS_GUESS
|
|
796
897
|
}).catch((err)=>{
|
|
797
|
-
|
|
898
|
+
// In fisherman mode, we expect ValidatorSelection__MissingProposerSignature since fisherman doesn't have proposer signature
|
|
899
|
+
const viemError = formatViemError(err);
|
|
900
|
+
if (this.config.fishermanMode && viemError.message?.includes('ValidatorSelection__MissingProposerSignature')) {
|
|
901
|
+
this.log.debug(`Ignoring expected ValidatorSelection__MissingProposerSignature error in fisherman mode`);
|
|
902
|
+
// Return a minimal simulation result with the fallback gas estimate
|
|
903
|
+
return {
|
|
904
|
+
gasUsed: SequencerPublisher.PROPOSE_GAS_GUESS,
|
|
905
|
+
logs: []
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
this.log.error(`Failed to simulate propose tx`, viemError);
|
|
798
909
|
throw err;
|
|
799
910
|
});
|
|
800
911
|
return {
|
|
@@ -802,24 +913,25 @@ export class SequencerPublisher {
|
|
|
802
913
|
simulationResult
|
|
803
914
|
};
|
|
804
915
|
}
|
|
805
|
-
async addProposeTx(
|
|
916
|
+
async addProposeTx(checkpoint, encodedData, opts = {}, timestamp) {
|
|
917
|
+
const slot = checkpoint.header.slotNumber;
|
|
806
918
|
const timer = new Timer();
|
|
807
919
|
const kzg = Blob.getViemKzgInstance();
|
|
808
920
|
const { rollupData, simulationResult, blobEvaluationGas } = await this.prepareProposeTx(encodedData, timestamp, opts);
|
|
809
921
|
const startBlock = await this.l1TxUtils.getBlockNumber();
|
|
810
922
|
const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(simulationResult.gasUsed) * 64 / 63)) + blobEvaluationGas + SequencerPublisher.MULTICALL_OVERHEAD_GAS_GUESS);
|
|
811
|
-
// Send the blobs to the blob
|
|
812
|
-
// tx fails but it does get mined. We make sure that the blobs are sent to the blob
|
|
813
|
-
void this.
|
|
814
|
-
|
|
815
|
-
|
|
923
|
+
// Send the blobs to the blob client preemptively. This helps in tests where the sequencer mistakingly thinks that the propose
|
|
924
|
+
// tx fails but it does get mined. We make sure that the blobs are sent to the blob client regardless of the tx outcome.
|
|
925
|
+
void Promise.resolve().then(()=>this.blobClient.sendBlobsToFilestore(encodedData.blobs).catch((_err)=>{
|
|
926
|
+
this.log.error('Failed to send blobs to blob client');
|
|
927
|
+
}));
|
|
816
928
|
return this.addRequest({
|
|
817
929
|
action: 'propose',
|
|
818
930
|
request: {
|
|
819
931
|
to: this.rollupContract.address,
|
|
820
932
|
data: rollupData
|
|
821
933
|
},
|
|
822
|
-
lastValidL2Slot:
|
|
934
|
+
lastValidL2Slot: checkpoint.header.slotNumber,
|
|
823
935
|
gasConfig: {
|
|
824
936
|
...opts,
|
|
825
937
|
gasLimit
|
|
@@ -833,7 +945,7 @@ export class SequencerPublisher {
|
|
|
833
945
|
return false;
|
|
834
946
|
}
|
|
835
947
|
const { receipt, stats, errorMsg } = result;
|
|
836
|
-
const success = receipt && receipt.status === 'success' && tryExtractEvent(receipt.logs, this.rollupContract.address, RollupAbi, '
|
|
948
|
+
const success = receipt && receipt.status === 'success' && tryExtractEvent(receipt.logs, this.rollupContract.address, RollupAbi, 'CheckpointProposed');
|
|
837
949
|
if (success) {
|
|
838
950
|
const endBlock = receipt.blockNumber;
|
|
839
951
|
const inclusionBlocks = Number(endBlock - startBlock);
|
|
@@ -847,25 +959,23 @@ export class SequencerPublisher {
|
|
|
847
959
|
calldataGas,
|
|
848
960
|
calldataSize,
|
|
849
961
|
sender,
|
|
850
|
-
...
|
|
962
|
+
...checkpoint.getStats(),
|
|
851
963
|
eventName: 'rollup-published-to-l1',
|
|
852
964
|
blobCount: encodedData.blobs.length,
|
|
853
965
|
inclusionBlocks
|
|
854
966
|
};
|
|
855
|
-
this.log.info(`Published
|
|
967
|
+
this.log.info(`Published checkpoint ${checkpoint.number} at slot ${slot} to rollup contract`, {
|
|
856
968
|
...stats,
|
|
857
|
-
...
|
|
858
|
-
...receipt
|
|
969
|
+
...checkpoint.getStats(),
|
|
970
|
+
...pick(receipt, 'transactionHash', 'blockHash')
|
|
859
971
|
});
|
|
860
972
|
this.metrics.recordProcessBlockTx(timer.ms(), publishStats);
|
|
861
973
|
return true;
|
|
862
974
|
} else {
|
|
863
975
|
this.metrics.recordFailedTx('process');
|
|
864
|
-
this.log.error(`
|
|
865
|
-
...
|
|
866
|
-
receipt
|
|
867
|
-
txHash: receipt.transactionHash,
|
|
868
|
-
slotNumber: block.header.globalVariables.slotNumber.toBigInt()
|
|
976
|
+
this.log.error(`Publishing checkpoint at slot ${slot} failed with ${errorMsg ?? 'no error message'}`, undefined, {
|
|
977
|
+
...checkpoint.getStats(),
|
|
978
|
+
...receipt
|
|
869
979
|
});
|
|
870
980
|
return false;
|
|
871
981
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
3
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
3
4
|
import { PublicProcessor } from '@aztec/simulator/server';
|
|
4
5
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
5
|
-
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
6
6
|
import type { BuildBlockResult, FullNodeBlockBuilderConfig, IFullNodeBlockBuilder, MerkleTreeWriteOperations, PublicProcessorLimits, PublicProcessorValidator, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
7
7
|
import { GlobalVariables, Tx } from '@aztec/stdlib/tx';
|
|
8
8
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
9
|
-
export declare function buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], newGlobalVariables: GlobalVariables, opts: PublicProcessorLimits | undefined, worldStateFork: MerkleTreeWriteOperations, processor: PublicProcessor, validator: PublicProcessorValidator, l1Constants: Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>, dateProvider: DateProvider, telemetryClient?: TelemetryClient): Promise<BuildBlockResult>;
|
|
10
9
|
export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
|
|
11
10
|
private config;
|
|
12
11
|
private worldState;
|
|
@@ -22,6 +21,6 @@ export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
|
|
|
22
21
|
}>;
|
|
23
22
|
private syncToPreviousBlock;
|
|
24
23
|
buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], globalVariables: GlobalVariables, opts: PublicProcessorLimits, suppliedFork?: MerkleTreeWriteOperations): Promise<BuildBlockResult>;
|
|
25
|
-
getFork(blockNumber:
|
|
24
|
+
getFork(blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations>;
|
|
26
25
|
}
|
|
27
|
-
//# sourceMappingURL=
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfYnVpbGRlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9ibG9ja19idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU5RCxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUl6RCxPQUFPLEVBQUUsWUFBWSxFQUFrQixNQUFNLHlCQUF5QixDQUFDO0FBR3ZFLE9BQU8sRUFHTCxlQUFlLEVBRWhCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUdqRSxPQUFPLEtBQUssRUFDVixnQkFBZ0IsRUFDaEIsMEJBQTBCLEVBQzFCLHFCQUFxQixFQUNyQix5QkFBeUIsRUFDekIscUJBQXFCLEVBQ3JCLHdCQUF3QixFQUN4QixzQkFBc0IsRUFDdkIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBc0IsTUFBTSx5QkFBeUIsQ0FBQztBQTJFbkYscUJBQWEsb0JBQXFCLFlBQVcscUJBQXFCO0lBRTlELE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLFVBQVU7SUFDbEIsT0FBTyxDQUFDLGtCQUFrQjtJQUMxQixPQUFPLENBQUMsWUFBWTtJQUNwQixPQUFPLENBQUMsZUFBZTtJQUx6QixZQUNVLE1BQU0sRUFBRSwwQkFBMEIsRUFDbEMsVUFBVSxFQUFFLHNCQUFzQixFQUNsQyxrQkFBa0IsRUFBRSxrQkFBa0IsRUFDdEMsWUFBWSxFQUFFLFlBQVksRUFDMUIsZUFBZSxHQUFFLGVBQXNDLEVBQzdEO0lBRUcsU0FBUyxJQUFJLDBCQUEwQixDQUU3QztJQUVNLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLDBCQUEwQixDQUFDLFFBRTlEO0lBRVksb0JBQW9CLENBQUMsZUFBZSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUseUJBQXlCOzs7T0FrQ2xHO1lBRWEsbUJBQW1CO0lBVTNCLFVBQVUsQ0FDZCxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxFQUFFLENBQUMsRUFDNUMsY0FBYyxFQUFFLEVBQUUsRUFBRSxFQUNwQixlQUFlLEVBQUUsZUFBZSxFQUNoQyxJQUFJLEVBQUUscUJBQXFCLEVBQzNCLFlBQVksQ0FBQyxFQUFFLHlCQUF5QixHQUN2QyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FzQzNCO0lBRUQsT0FBTyxDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBRXBFO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/block_builder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"block_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/block_builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAIzD,OAAO,EAAE,YAAY,EAAkB,MAAM,yBAAyB,CAAC;AAGvE,OAAO,EAGL,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,KAAK,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AA2EnF,qBAAa,oBAAqB,YAAW,qBAAqB;IAE9D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IALzB,YACU,MAAM,EAAE,0BAA0B,EAClC,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,EAC7D;IAEG,SAAS,IAAI,0BAA0B,CAE7C;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC,QAE9D;IAEY,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;OAkClG;YAEa,mBAAmB;IAU3B,UAAU,CACd,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,cAAc,EAAE,EAAE,EAAE,EACpB,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,qBAAqB,EAC3B,YAAY,CAAC,EAAE,yBAAyB,GACvC,OAAO,CAAC,gBAAgB,CAAC,CAsC3B;IAED,OAAO,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAEpE;CACF"}
|