@aztec/sequencer-client 0.67.1 → 0.68.0
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/config.d.ts +3 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +3 -56
- package/dest/index.d.ts +0 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -2
- package/dest/publisher/index.d.ts +0 -1
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/index.js +1 -2
- package/dest/publisher/l1-publisher-metrics.d.ts +5 -2
- package/dest/publisher/l1-publisher-metrics.d.ts.map +1 -1
- package/dest/publisher/l1-publisher-metrics.js +16 -1
- package/dest/publisher/l1-publisher.d.ts +4 -1
- package/dest/publisher/l1-publisher.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.js +200 -44
- package/dest/publisher/utils.d.ts +1 -3
- package/dest/publisher/utils.d.ts.map +1 -1
- package/dest/publisher/utils.js +2 -8
- package/dest/sequencer/allowed.d.ts +3 -0
- package/dest/sequencer/allowed.d.ts.map +1 -0
- package/dest/sequencer/allowed.js +34 -0
- package/dest/sequencer/config.d.ts +1 -1
- package/dest/sequencer/config.d.ts.map +1 -1
- package/dest/sequencer/metrics.d.ts +2 -0
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +13 -2
- package/dest/sequencer/sequencer.d.ts +1 -4
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +51 -54
- package/dest/tx_validator/gas_validator.d.ts +3 -4
- package/dest/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/tx_validator/gas_validator.js +25 -8
- package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.js +6 -4
- package/package.json +26 -23
- package/src/config.ts +5 -60
- package/src/index.ts +0 -1
- package/src/publisher/index.ts +0 -1
- package/src/publisher/l1-publisher-metrics.ts +24 -3
- package/src/publisher/l1-publisher.ts +241 -68
- package/src/publisher/utils.ts +1 -10
- package/src/sequencer/allowed.ts +36 -0
- package/src/sequencer/config.ts +1 -1
- package/src/sequencer/metrics.ts +15 -1
- package/src/sequencer/sequencer.ts +61 -70
- package/src/tx_validator/gas_validator.ts +32 -6
- package/src/tx_validator/tx_validator_factory.ts +11 -3
|
@@ -7,16 +7,15 @@ import {
|
|
|
7
7
|
type TxHash,
|
|
8
8
|
getHashedSignaturePayload,
|
|
9
9
|
} from '@aztec/circuit-types';
|
|
10
|
-
import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats';
|
|
10
|
+
import { type L1PublishBlockStats, type L1PublishProofStats, type L1PublishStats } from '@aztec/circuit-types/stats';
|
|
11
11
|
import {
|
|
12
12
|
AGGREGATION_OBJECT_LENGTH,
|
|
13
13
|
AZTEC_MAX_EPOCH_DURATION,
|
|
14
14
|
type BlockHeader,
|
|
15
15
|
EthAddress,
|
|
16
|
-
type FeeRecipient,
|
|
17
16
|
type Proof,
|
|
18
|
-
type RootRollupPublicInputs,
|
|
19
17
|
} from '@aztec/circuits.js';
|
|
18
|
+
import { type FeeRecipient, type RootRollupPublicInputs } from '@aztec/circuits.js/rollup';
|
|
20
19
|
import {
|
|
21
20
|
type EthereumChain,
|
|
22
21
|
type L1ContractsConfig,
|
|
@@ -25,6 +24,8 @@ import {
|
|
|
25
24
|
createEthereumChain,
|
|
26
25
|
} from '@aztec/ethereum';
|
|
27
26
|
import { makeTuple } from '@aztec/foundation/array';
|
|
27
|
+
import { toHex } from '@aztec/foundation/bigint-buffer';
|
|
28
|
+
import { Blob } from '@aztec/foundation/blob';
|
|
28
29
|
import { areArraysEqual, compactArray, times } from '@aztec/foundation/collection';
|
|
29
30
|
import { type Signature } from '@aztec/foundation/eth-signature';
|
|
30
31
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -32,16 +33,15 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
32
33
|
import { type Tuple, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
33
34
|
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
34
35
|
import { Timer } from '@aztec/foundation/timer';
|
|
35
|
-
import { GovernanceProposerAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
36
|
+
import { ExtRollupLibAbi, GovernanceProposerAbi, LeonidasLibAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
36
37
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
37
38
|
|
|
38
39
|
import pick from 'lodash.pick';
|
|
39
|
-
import { inspect } from 'util';
|
|
40
40
|
import {
|
|
41
41
|
type BaseError,
|
|
42
42
|
type Chain,
|
|
43
43
|
type Client,
|
|
44
|
-
|
|
44
|
+
ContractFunctionExecutionError,
|
|
45
45
|
ContractFunctionRevertedError,
|
|
46
46
|
type GetContractReturnType,
|
|
47
47
|
type Hex,
|
|
@@ -60,6 +60,7 @@ import {
|
|
|
60
60
|
getAbiItem,
|
|
61
61
|
getAddress,
|
|
62
62
|
getContract,
|
|
63
|
+
getContractError,
|
|
63
64
|
hexToBytes,
|
|
64
65
|
http,
|
|
65
66
|
publicActions,
|
|
@@ -68,7 +69,7 @@ import { privateKeyToAccount } from 'viem/accounts';
|
|
|
68
69
|
|
|
69
70
|
import { type PublisherConfig, type TxSenderConfig } from './config.js';
|
|
70
71
|
import { L1PublisherMetrics } from './l1-publisher-metrics.js';
|
|
71
|
-
import {
|
|
72
|
+
import { prettyLogViemErrorMsg } from './utils.js';
|
|
72
73
|
|
|
73
74
|
/**
|
|
74
75
|
* Stats for a sent transaction.
|
|
@@ -110,8 +111,10 @@ type L1ProcessArgs = {
|
|
|
110
111
|
archive: Buffer;
|
|
111
112
|
/** The L2 block's leaf in the archive tree. */
|
|
112
113
|
blockHash: Buffer;
|
|
113
|
-
/** L2 block body. */
|
|
114
|
+
/** L2 block body. TODO(#9101): Remove block body once we can extract blobs. */
|
|
114
115
|
body: Buffer;
|
|
116
|
+
/** L2 block blobs containing all tx effects. */
|
|
117
|
+
blobs: Blob[];
|
|
115
118
|
/** L2 block tx hashes */
|
|
116
119
|
txHashes: TxHash[];
|
|
117
120
|
/** Attestations */
|
|
@@ -166,6 +169,9 @@ export class L1Publisher {
|
|
|
166
169
|
protected account: PrivateKeyAccount;
|
|
167
170
|
protected ethereumSlotDuration: bigint;
|
|
168
171
|
|
|
172
|
+
// @note - with blobs, the below estimate seems too large.
|
|
173
|
+
// Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob)
|
|
174
|
+
// Total used for emptier block from above test: 429k (of which 84k is 1x blob)
|
|
169
175
|
public static PROPOSE_GAS_GUESS: bigint = 12_000_000n;
|
|
170
176
|
public static PROPOSE_AND_CLAIM_GAS_GUESS: bigint = this.PROPOSE_GAS_GUESS + 100_000n;
|
|
171
177
|
|
|
@@ -342,7 +348,10 @@ export class L1Publisher {
|
|
|
342
348
|
try {
|
|
343
349
|
await this.rollupContract.read.validateEpochProofRightClaimAtTime(args, { account: this.account });
|
|
344
350
|
} catch (err) {
|
|
345
|
-
|
|
351
|
+
let errorName = tryGetCustomErrorName(err);
|
|
352
|
+
if (!errorName) {
|
|
353
|
+
errorName = tryGetCustomErrorNameContractFunction(err as ContractFunctionExecutionError);
|
|
354
|
+
}
|
|
346
355
|
this.log.warn(`Proof quote validation failed: ${errorName}`, quote);
|
|
347
356
|
return undefined;
|
|
348
357
|
}
|
|
@@ -375,7 +384,7 @@ export class L1Publisher {
|
|
|
375
384
|
formattedSignatures,
|
|
376
385
|
`0x${attestationData.digest.toString('hex')}`,
|
|
377
386
|
ts,
|
|
378
|
-
`0x${header.contentCommitment.
|
|
387
|
+
`0x${header.contentCommitment.blobsHash.toString('hex')}`,
|
|
379
388
|
flags,
|
|
380
389
|
] as const;
|
|
381
390
|
|
|
@@ -386,6 +395,36 @@ export class L1Publisher {
|
|
|
386
395
|
if (error instanceof ContractFunctionRevertedError) {
|
|
387
396
|
const err = error as ContractFunctionRevertedError;
|
|
388
397
|
this.log.debug(`Validation failed: ${err.message}`, err.data);
|
|
398
|
+
} else if (error instanceof ContractFunctionExecutionError) {
|
|
399
|
+
let err = error as ContractFunctionRevertedError;
|
|
400
|
+
if (!tryGetCustomErrorName(err)) {
|
|
401
|
+
// If we get here, it's because the custom error no longer exists in Rollup.sol,
|
|
402
|
+
// but in another lib. The below reconstructs the error message.
|
|
403
|
+
try {
|
|
404
|
+
await this.publicClient.estimateGas({
|
|
405
|
+
data: encodeFunctionData({
|
|
406
|
+
abi: this.rollupContract.abi,
|
|
407
|
+
functionName: 'validateHeader',
|
|
408
|
+
args,
|
|
409
|
+
}),
|
|
410
|
+
account: this.account,
|
|
411
|
+
to: this.rollupContract.address,
|
|
412
|
+
});
|
|
413
|
+
} catch (estGasErr: unknown) {
|
|
414
|
+
const possibleAbis = [ExtRollupLibAbi, LeonidasLibAbi];
|
|
415
|
+
possibleAbis.forEach(abi => {
|
|
416
|
+
const possibleErr = getContractError(estGasErr as BaseError, {
|
|
417
|
+
args: [],
|
|
418
|
+
abi: abi,
|
|
419
|
+
functionName: 'validateHeader',
|
|
420
|
+
address: this.rollupContract.address,
|
|
421
|
+
sender: this.account.address,
|
|
422
|
+
});
|
|
423
|
+
err = tryGetCustomErrorName(possibleErr) ? possibleErr : err;
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
throw err;
|
|
427
|
+
}
|
|
389
428
|
} else {
|
|
390
429
|
this.log.debug(`Unexpected error during validation: ${error}`);
|
|
391
430
|
}
|
|
@@ -501,10 +540,10 @@ export class L1Publisher {
|
|
|
501
540
|
archive: block.archive.root.toBuffer(),
|
|
502
541
|
blockHash: block.header.hash().toBuffer(),
|
|
503
542
|
body: block.body.toBuffer(),
|
|
543
|
+
blobs: Blob.getBlobs(block.body.toBlobFields()),
|
|
504
544
|
attestations,
|
|
505
545
|
txHashes: txHashes ?? [],
|
|
506
546
|
};
|
|
507
|
-
|
|
508
547
|
// Publish body and propose block (if not already published)
|
|
509
548
|
if (this.interrupted) {
|
|
510
549
|
this.log.verbose('L2 block data syncing interrupted while processing blocks.', ctx);
|
|
@@ -532,7 +571,7 @@ export class L1Publisher {
|
|
|
532
571
|
return false;
|
|
533
572
|
}
|
|
534
573
|
|
|
535
|
-
const { receipt, args, functionName } = result;
|
|
574
|
+
const { receipt, args, functionName, data } = result;
|
|
536
575
|
|
|
537
576
|
// Tx was mined successfully
|
|
538
577
|
if (receipt.status === 'success') {
|
|
@@ -540,6 +579,8 @@ export class L1Publisher {
|
|
|
540
579
|
const stats: L1PublishBlockStats = {
|
|
541
580
|
gasPrice: receipt.effectiveGasPrice,
|
|
542
581
|
gasUsed: receipt.gasUsed,
|
|
582
|
+
blobGasUsed: receipt.blobGasUsed ?? 0n,
|
|
583
|
+
blobDataGas: receipt.blobGasPrice ?? 0n,
|
|
543
584
|
transactionHash: receipt.transactionHash,
|
|
544
585
|
...pick(tx!, 'calldataGas', 'calldataSize', 'sender'),
|
|
545
586
|
...block.getStats(),
|
|
@@ -551,14 +592,21 @@ export class L1Publisher {
|
|
|
551
592
|
}
|
|
552
593
|
|
|
553
594
|
this.metrics.recordFailedTx('process');
|
|
554
|
-
|
|
555
|
-
const errorMsg = await this.tryGetErrorFromRevertedTx(
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
595
|
+
const kzg = Blob.getViemKzgInstance();
|
|
596
|
+
const errorMsg = await this.tryGetErrorFromRevertedTx(
|
|
597
|
+
data,
|
|
598
|
+
{
|
|
599
|
+
args,
|
|
600
|
+
functionName,
|
|
601
|
+
abi: RollupAbi,
|
|
602
|
+
address: this.rollupContract.address,
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
blobs: proposeTxArgs.blobs.map(b => b.data),
|
|
606
|
+
kzg,
|
|
607
|
+
maxFeePerBlobGas: 10000000000n,
|
|
608
|
+
},
|
|
609
|
+
);
|
|
562
610
|
this.log.error(`Rollup process tx reverted. ${errorMsg}`, undefined, {
|
|
563
611
|
...ctx,
|
|
564
612
|
txHash: receipt.transactionHash,
|
|
@@ -567,25 +615,118 @@ export class L1Publisher {
|
|
|
567
615
|
return false;
|
|
568
616
|
}
|
|
569
617
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
blockNumber: bigint | undefined;
|
|
576
|
-
}) {
|
|
618
|
+
/** Calls claimEpochProofRight in the Rollup contract to submit a chosen prover quote for the previous epoch. */
|
|
619
|
+
public async claimEpochProofRight(proofQuote: EpochProofQuote) {
|
|
620
|
+
const timer = new Timer();
|
|
621
|
+
|
|
622
|
+
let receipt;
|
|
577
623
|
try {
|
|
578
|
-
|
|
624
|
+
this.log.debug(`Submitting claimEpochProofRight transaction`);
|
|
625
|
+
receipt = await this.l1TxUtils.sendAndMonitorTransaction({
|
|
626
|
+
to: this.rollupContract.address,
|
|
627
|
+
data: encodeFunctionData({
|
|
628
|
+
abi: RollupAbi,
|
|
629
|
+
functionName: 'claimEpochProofRight',
|
|
630
|
+
args: [proofQuote.toViemArgs()],
|
|
631
|
+
}),
|
|
632
|
+
});
|
|
633
|
+
} catch (err) {
|
|
634
|
+
this.log.error(`Failed to claim epoch proof right: ${prettyLogViemErrorMsg(err)}`, err, {
|
|
635
|
+
proofQuote: proofQuote.toInspect(),
|
|
636
|
+
});
|
|
637
|
+
return false;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (receipt.status === 'success') {
|
|
641
|
+
const tx = await this.getTransactionStats(receipt.transactionHash);
|
|
642
|
+
const stats: L1PublishStats = {
|
|
643
|
+
gasPrice: receipt.effectiveGasPrice,
|
|
644
|
+
gasUsed: receipt.gasUsed,
|
|
645
|
+
transactionHash: receipt.transactionHash,
|
|
646
|
+
blobDataGas: 0n,
|
|
647
|
+
blobGasUsed: 0n,
|
|
648
|
+
...pick(tx!, 'calldataGas', 'calldataSize', 'sender'),
|
|
649
|
+
};
|
|
650
|
+
this.log.verbose(`Submitted claim epoch proof right to L1 rollup contract`, {
|
|
651
|
+
...stats,
|
|
652
|
+
...proofQuote.toInspect(),
|
|
653
|
+
});
|
|
654
|
+
this.metrics.recordClaimEpochProofRightTx(timer.ms(), stats);
|
|
655
|
+
return true;
|
|
656
|
+
} else {
|
|
657
|
+
this.metrics.recordFailedTx('claimEpochProofRight');
|
|
658
|
+
// TODO: Get the error message from the reverted tx
|
|
659
|
+
this.log.error(`Claim epoch proof right tx reverted`, {
|
|
660
|
+
txHash: receipt.transactionHash,
|
|
661
|
+
...proofQuote.toInspect(),
|
|
662
|
+
});
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
private async tryGetErrorFromRevertedTx(
|
|
668
|
+
data: Hex,
|
|
669
|
+
args: {
|
|
670
|
+
args: any[];
|
|
671
|
+
functionName: string;
|
|
672
|
+
abi: any;
|
|
673
|
+
address: Hex;
|
|
674
|
+
},
|
|
675
|
+
_blobInputs?: {
|
|
676
|
+
blobs: Uint8Array[];
|
|
677
|
+
kzg: any;
|
|
678
|
+
maxFeePerBlobGas: bigint;
|
|
679
|
+
},
|
|
680
|
+
) {
|
|
681
|
+
const blobInputs = _blobInputs || {};
|
|
682
|
+
try {
|
|
683
|
+
// NB: If this fn starts unexpectedly giving incorrect blob hash errors, it may be because the checkBlob
|
|
684
|
+
// bool is no longer at the slot below. To find the slot, run: forge inspect src/core/Rollup.sol:Rollup storage
|
|
685
|
+
const checkBlobSlot = 9n;
|
|
686
|
+
await this.publicClient.simulateContract({
|
|
687
|
+
...args,
|
|
688
|
+
account: this.walletClient.account,
|
|
689
|
+
stateOverride: [
|
|
690
|
+
{
|
|
691
|
+
address: args.address,
|
|
692
|
+
stateDiff: [
|
|
693
|
+
{
|
|
694
|
+
slot: toHex(checkBlobSlot, true),
|
|
695
|
+
value: toHex(0n, true),
|
|
696
|
+
},
|
|
697
|
+
],
|
|
698
|
+
},
|
|
699
|
+
],
|
|
700
|
+
});
|
|
701
|
+
// If the above passes, we have a blob error. We cannot simulate blob txs, and failed txs no longer throw errors,
|
|
702
|
+
// and viem provides no way to get the revert reason from a given tx.
|
|
703
|
+
// Strangely, the only way to throw the revert reason as an error and provide blobs is prepareTransactionRequest.
|
|
704
|
+
// See: https://github.com/wevm/viem/issues/2075
|
|
705
|
+
// This throws a EstimateGasExecutionError with the custom error information:
|
|
706
|
+
await this.walletClient.prepareTransactionRequest({
|
|
707
|
+
account: this.walletClient.account,
|
|
708
|
+
to: this.rollupContract.address,
|
|
709
|
+
data,
|
|
710
|
+
...blobInputs,
|
|
711
|
+
});
|
|
579
712
|
return undefined;
|
|
580
|
-
} catch (
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
713
|
+
} catch (simulationErr: any) {
|
|
714
|
+
// If we don't have a ContractFunctionExecutionError, we have a blob related error => use ExtRollupLibAbi to get the error msg.
|
|
715
|
+
const contractErr =
|
|
716
|
+
simulationErr.name === 'ContractFunctionExecutionError'
|
|
717
|
+
? simulationErr
|
|
718
|
+
: getContractError(simulationErr as BaseError, {
|
|
719
|
+
args: [],
|
|
720
|
+
abi: ExtRollupLibAbi,
|
|
721
|
+
functionName: args.functionName,
|
|
722
|
+
address: args.address,
|
|
723
|
+
sender: this.account.address,
|
|
724
|
+
});
|
|
725
|
+
if (contractErr.name === 'ContractFunctionExecutionError') {
|
|
726
|
+
const execErr = contractErr as ContractFunctionExecutionError;
|
|
727
|
+
return tryGetCustomErrorNameContractFunction(execErr);
|
|
587
728
|
}
|
|
588
|
-
this.log.error(`Error getting error from simulation`,
|
|
729
|
+
this.log.error(`Error getting error from simulation`, simulationErr);
|
|
589
730
|
}
|
|
590
731
|
}
|
|
591
732
|
|
|
@@ -620,6 +761,8 @@ export class L1Publisher {
|
|
|
620
761
|
const stats: L1PublishProofStats = {
|
|
621
762
|
...pick(receipt, 'gasPrice', 'gasUsed', 'transactionHash'),
|
|
622
763
|
...pick(tx!, 'calldataGas', 'calldataSize', 'sender'),
|
|
764
|
+
blobDataGas: 0n,
|
|
765
|
+
blobGasUsed: 0n,
|
|
623
766
|
eventName: 'proof-published-to-l1',
|
|
624
767
|
};
|
|
625
768
|
this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
|
|
@@ -726,7 +869,8 @@ export class L1Publisher {
|
|
|
726
869
|
epochSize: argsArray[0],
|
|
727
870
|
args: argsArray[1],
|
|
728
871
|
fees: argsArray[2],
|
|
729
|
-
|
|
872
|
+
blobPublicInputs: argsArray[3],
|
|
873
|
+
aggregationObject: argsArray[4],
|
|
730
874
|
proof: proofHex,
|
|
731
875
|
},
|
|
732
876
|
] as const;
|
|
@@ -750,22 +894,31 @@ export class L1Publisher {
|
|
|
750
894
|
}
|
|
751
895
|
|
|
752
896
|
private async prepareProposeTx(encodedData: L1ProcessArgs) {
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
897
|
+
const kzg = Blob.getViemKzgInstance();
|
|
898
|
+
const blobEvaluationGas = await this.l1TxUtils.estimateGas(
|
|
899
|
+
this.account,
|
|
900
|
+
{
|
|
901
|
+
to: this.rollupContract.address,
|
|
902
|
+
data: encodeFunctionData({
|
|
903
|
+
abi: this.rollupContract.abi,
|
|
904
|
+
functionName: 'validateBlobs',
|
|
905
|
+
args: [Blob.getEthBlobEvaluationInputs(encodedData.blobs)],
|
|
906
|
+
}),
|
|
907
|
+
},
|
|
908
|
+
{},
|
|
909
|
+
{
|
|
910
|
+
blobs: encodedData.blobs.map(b => b.data),
|
|
911
|
+
kzg,
|
|
912
|
+
maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS
|
|
913
|
+
},
|
|
914
|
+
);
|
|
761
915
|
|
|
762
916
|
// @note We perform this guesstimate instead of the usual `gasEstimate` since
|
|
763
917
|
// viem will use the current state to simulate against, which means that
|
|
764
918
|
// we will fail estimation in the case where we are simulating for the
|
|
765
919
|
// first ethereum block within our slot (as current time is not in the
|
|
766
920
|
// slot yet).
|
|
767
|
-
const gasGuesstimate =
|
|
768
|
-
|
|
921
|
+
const gasGuesstimate = blobEvaluationGas + L1Publisher.PROPOSE_GAS_GUESS;
|
|
769
922
|
const attestations = encodedData.attestations
|
|
770
923
|
? encodedData.attestations.map(attest => attest.toViemSignature())
|
|
771
924
|
: [];
|
|
@@ -783,7 +936,9 @@ export class L1Publisher {
|
|
|
783
936
|
txHashes,
|
|
784
937
|
},
|
|
785
938
|
attestations,
|
|
939
|
+
// TODO(#9101): Extract blobs from beacon chain => calldata will only contain what's needed to verify blob and body input can be removed
|
|
786
940
|
`0x${encodedData.body.toString('hex')}`,
|
|
941
|
+
Blob.getEthBlobEvaluationInputs(encodedData.blobs),
|
|
787
942
|
] as const;
|
|
788
943
|
|
|
789
944
|
return { args, gas: gasGuesstimate };
|
|
@@ -811,39 +966,50 @@ export class L1Publisher {
|
|
|
811
966
|
? args.publicInputs.fees[i / 2].recipient.toField().toString()
|
|
812
967
|
: args.publicInputs.fees[(i - 1) / 2].value.toString(),
|
|
813
968
|
),
|
|
969
|
+
`0x${args.publicInputs.blobPublicInputs
|
|
970
|
+
.filter((_, i) => i < args.toBlock - args.fromBlock + 1)
|
|
971
|
+
.map(b => b.toString())
|
|
972
|
+
.join(``)}`,
|
|
814
973
|
`0x${serializeToBuffer(args.proof.extractAggregationObject()).toString('hex')}`,
|
|
815
974
|
] as const;
|
|
816
975
|
}
|
|
817
976
|
|
|
818
977
|
private async sendProposeTx(
|
|
819
978
|
encodedData: L1ProcessArgs,
|
|
820
|
-
): Promise<{ receipt: TransactionReceipt; args: any; functionName: string } | undefined> {
|
|
979
|
+
): Promise<{ receipt: TransactionReceipt | undefined; args: any; functionName: string; data: Hex } | undefined> {
|
|
821
980
|
if (this.interrupted) {
|
|
822
981
|
return undefined;
|
|
823
982
|
}
|
|
824
983
|
try {
|
|
984
|
+
const kzg = Blob.getViemKzgInstance();
|
|
825
985
|
const { args, gas } = await this.prepareProposeTx(encodedData);
|
|
986
|
+
const data = encodeFunctionData({
|
|
987
|
+
abi: this.rollupContract.abi,
|
|
988
|
+
functionName: 'propose',
|
|
989
|
+
args,
|
|
990
|
+
});
|
|
826
991
|
const receipt = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
827
992
|
{
|
|
828
993
|
to: this.rollupContract.address,
|
|
829
|
-
data
|
|
830
|
-
abi: this.rollupContract.abi,
|
|
831
|
-
functionName: 'propose',
|
|
832
|
-
args,
|
|
833
|
-
}),
|
|
994
|
+
data,
|
|
834
995
|
},
|
|
835
996
|
{
|
|
836
997
|
fixedGas: gas,
|
|
837
998
|
},
|
|
999
|
+
{
|
|
1000
|
+
blobs: encodedData.blobs.map(b => b.data),
|
|
1001
|
+
kzg,
|
|
1002
|
+
maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS
|
|
1003
|
+
},
|
|
838
1004
|
);
|
|
839
1005
|
return {
|
|
840
1006
|
receipt,
|
|
841
1007
|
args,
|
|
842
1008
|
functionName: 'propose',
|
|
1009
|
+
data,
|
|
843
1010
|
};
|
|
844
1011
|
} catch (err) {
|
|
845
|
-
|
|
846
|
-
this.log.error(`Rollup publish failed`, err);
|
|
1012
|
+
this.log.error(`Rollup publish failed: ${prettyLogViemErrorMsg(err)}`, err);
|
|
847
1013
|
return undefined;
|
|
848
1014
|
}
|
|
849
1015
|
}
|
|
@@ -851,36 +1017,39 @@ export class L1Publisher {
|
|
|
851
1017
|
private async sendProposeAndClaimTx(
|
|
852
1018
|
encodedData: L1ProcessArgs,
|
|
853
1019
|
quote: EpochProofQuote,
|
|
854
|
-
): Promise<{ receipt: TransactionReceipt; args: any; functionName: string } | undefined> {
|
|
1020
|
+
): Promise<{ receipt: TransactionReceipt | undefined; args: any; functionName: string; data: Hex } | undefined> {
|
|
855
1021
|
if (this.interrupted) {
|
|
856
1022
|
return undefined;
|
|
857
1023
|
}
|
|
858
1024
|
try {
|
|
859
|
-
|
|
860
|
-
this.log.info(inspect(quote.payload));
|
|
861
|
-
|
|
1025
|
+
const kzg = Blob.getViemKzgInstance();
|
|
862
1026
|
const { args, gas } = await this.prepareProposeTx(encodedData);
|
|
1027
|
+
const data = encodeFunctionData({
|
|
1028
|
+
abi: this.rollupContract.abi,
|
|
1029
|
+
functionName: 'proposeAndClaim',
|
|
1030
|
+
args: [...args, quote.toViemArgs()],
|
|
1031
|
+
});
|
|
863
1032
|
const receipt = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
864
1033
|
{
|
|
865
1034
|
to: this.rollupContract.address,
|
|
866
|
-
data
|
|
867
|
-
abi: this.rollupContract.abi,
|
|
868
|
-
functionName: 'proposeAndClaim',
|
|
869
|
-
args: [...args, quote.toViemArgs()],
|
|
870
|
-
}),
|
|
1035
|
+
data,
|
|
871
1036
|
},
|
|
872
1037
|
{ fixedGas: gas },
|
|
1038
|
+
{
|
|
1039
|
+
blobs: encodedData.blobs.map(b => b.data),
|
|
1040
|
+
kzg,
|
|
1041
|
+
maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS
|
|
1042
|
+
},
|
|
873
1043
|
);
|
|
874
1044
|
|
|
875
1045
|
return {
|
|
876
1046
|
receipt,
|
|
877
|
-
args,
|
|
1047
|
+
args: [...args, quote.toViemArgs()],
|
|
878
1048
|
functionName: 'proposeAndClaim',
|
|
1049
|
+
data,
|
|
879
1050
|
};
|
|
880
1051
|
} catch (err) {
|
|
881
|
-
|
|
882
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
883
|
-
this.log.error(`Rollup publish failed`, errorMessage);
|
|
1052
|
+
this.log.error(`Rollup publish failed: ${prettyLogViemErrorMsg(err)}`, err);
|
|
884
1053
|
return undefined;
|
|
885
1054
|
}
|
|
886
1055
|
}
|
|
@@ -935,6 +1104,10 @@ function getCalldataGasUsage(data: Uint8Array) {
|
|
|
935
1104
|
return data.filter(byte => byte === 0).length * 4 + data.filter(byte => byte !== 0).length * 16;
|
|
936
1105
|
}
|
|
937
1106
|
|
|
1107
|
+
function tryGetCustomErrorNameContractFunction(err: ContractFunctionExecutionError) {
|
|
1108
|
+
return compactArray([err.shortMessage, ...(err.metaMessages ?? []).slice(0, 2).map(s => s.trim())]).join(' ');
|
|
1109
|
+
}
|
|
1110
|
+
|
|
938
1111
|
function tryGetCustomErrorName(err: any) {
|
|
939
1112
|
try {
|
|
940
1113
|
// See https://viem.sh/docs/contract/simulateContract#handling-custom-errors
|
package/src/publisher/utils.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { type Logger } from '@aztec/foundation/log';
|
|
2
|
-
|
|
3
1
|
import { BaseError, ContractFunctionRevertedError } from 'viem';
|
|
4
2
|
|
|
5
3
|
export function prettyLogViemErrorMsg(err: any) {
|
|
@@ -12,12 +10,5 @@ export function prettyLogViemErrorMsg(err: any) {
|
|
|
12
10
|
return `${errorName}${args}`;
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// TODO(palla/log): Review this method
|
|
18
|
-
export function prettyLogViemError(err: any, logger: Logger) {
|
|
19
|
-
const msg = prettyLogViemErrorMsg(err);
|
|
20
|
-
if (msg) {
|
|
21
|
-
logger.debug(`canProposeAtTime failed with "${msg}"`);
|
|
22
|
-
}
|
|
13
|
+
return err?.message ?? err;
|
|
23
14
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type AllowedElement } from '@aztec/circuit-types';
|
|
2
|
+
import { getContractClassFromArtifact } from '@aztec/circuits.js';
|
|
3
|
+
import { FPCContract } from '@aztec/noir-contracts.js/FPC';
|
|
4
|
+
import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
|
|
5
|
+
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
6
|
+
|
|
7
|
+
let defaultAllowedSetupFunctions: AllowedElement[] | undefined = undefined;
|
|
8
|
+
|
|
9
|
+
export function getDefaultAllowedSetupFunctions(): AllowedElement[] {
|
|
10
|
+
if (defaultAllowedSetupFunctions === undefined) {
|
|
11
|
+
defaultAllowedSetupFunctions = [
|
|
12
|
+
// needed for authwit support
|
|
13
|
+
{
|
|
14
|
+
address: ProtocolContractAddress.AuthRegistry,
|
|
15
|
+
},
|
|
16
|
+
// needed for claiming on the same tx as a spend
|
|
17
|
+
{
|
|
18
|
+
address: ProtocolContractAddress.FeeJuice,
|
|
19
|
+
// We can't restrict the selector because public functions get routed via dispatch.
|
|
20
|
+
// selector: FunctionSelector.fromSignature('_increase_public_balance((Field),Field)'),
|
|
21
|
+
},
|
|
22
|
+
// needed for private transfers via FPC
|
|
23
|
+
{
|
|
24
|
+
classId: getContractClassFromArtifact(TokenContractArtifact).id,
|
|
25
|
+
// We can't restrict the selector because public functions get routed via dispatch.
|
|
26
|
+
// selector: FunctionSelector.fromSignature('_increase_public_balance((Field),Field)'),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
classId: getContractClassFromArtifact(FPCContract.artifact).id,
|
|
30
|
+
// We can't restrict the selector because public functions get routed via dispatch.
|
|
31
|
+
// selector: FunctionSelector.fromSignature('prepare_fee((Field),Field,(Field),Field)'),
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
return defaultAllowedSetupFunctions;
|
|
36
|
+
}
|
package/src/sequencer/config.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { SequencerConfig } from '@aztec/circuit-types';
|
|
1
|
+
export { type SequencerConfig } from '@aztec/circuit-types/config';
|
package/src/sequencer/metrics.ts
CHANGED
|
@@ -19,6 +19,7 @@ export class SequencerMetrics {
|
|
|
19
19
|
private stateTransitionBufferDuration: Histogram;
|
|
20
20
|
private currentBlockNumber: Gauge;
|
|
21
21
|
private currentBlockSize: Gauge;
|
|
22
|
+
private blockBuilderInsertions: Histogram;
|
|
22
23
|
|
|
23
24
|
private timeToCollectAttestations: Gauge;
|
|
24
25
|
|
|
@@ -49,14 +50,23 @@ export class SequencerMetrics {
|
|
|
49
50
|
|
|
50
51
|
this.currentBlockNumber = meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_NUMBER, {
|
|
51
52
|
description: 'Current block number',
|
|
53
|
+
valueType: ValueType.INT,
|
|
52
54
|
});
|
|
53
55
|
|
|
54
56
|
this.currentBlockSize = meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_SIZE, {
|
|
55
|
-
description: 'Current block
|
|
57
|
+
description: 'Current block size',
|
|
58
|
+
valueType: ValueType.INT,
|
|
56
59
|
});
|
|
57
60
|
|
|
58
61
|
this.timeToCollectAttestations = meter.createGauge(Metrics.SEQUENCER_TIME_TO_COLLECT_ATTESTATIONS, {
|
|
59
62
|
description: 'The time spent collecting attestations from committee members',
|
|
63
|
+
valueType: ValueType.INT,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.blockBuilderInsertions = meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_INSERTION_TIME, {
|
|
67
|
+
description: 'Timer for tree insertions performed by the block builder',
|
|
68
|
+
unit: 'us',
|
|
69
|
+
valueType: ValueType.INT,
|
|
60
70
|
});
|
|
61
71
|
|
|
62
72
|
this.setCurrentBlock(0, 0);
|
|
@@ -75,6 +85,10 @@ export class SequencerMetrics {
|
|
|
75
85
|
this.timeToCollectAttestations.record(time);
|
|
76
86
|
}
|
|
77
87
|
|
|
88
|
+
recordBlockBuilderTreeInsertions(timeUs: number) {
|
|
89
|
+
this.blockBuilderInsertions.record(Math.ceil(timeUs));
|
|
90
|
+
}
|
|
91
|
+
|
|
78
92
|
recordCancelledBlock() {
|
|
79
93
|
this.blockCounter.add(1, {
|
|
80
94
|
[Attributes.STATUS]: 'cancelled',
|