@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.
Files changed (47) hide show
  1. package/dest/config.d.ts +3 -3
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +3 -56
  4. package/dest/index.d.ts +0 -1
  5. package/dest/index.d.ts.map +1 -1
  6. package/dest/index.js +1 -2
  7. package/dest/publisher/index.d.ts +0 -1
  8. package/dest/publisher/index.d.ts.map +1 -1
  9. package/dest/publisher/index.js +1 -2
  10. package/dest/publisher/l1-publisher-metrics.d.ts +5 -2
  11. package/dest/publisher/l1-publisher-metrics.d.ts.map +1 -1
  12. package/dest/publisher/l1-publisher-metrics.js +16 -1
  13. package/dest/publisher/l1-publisher.d.ts +4 -1
  14. package/dest/publisher/l1-publisher.d.ts.map +1 -1
  15. package/dest/publisher/l1-publisher.js +200 -44
  16. package/dest/publisher/utils.d.ts +1 -3
  17. package/dest/publisher/utils.d.ts.map +1 -1
  18. package/dest/publisher/utils.js +2 -8
  19. package/dest/sequencer/allowed.d.ts +3 -0
  20. package/dest/sequencer/allowed.d.ts.map +1 -0
  21. package/dest/sequencer/allowed.js +34 -0
  22. package/dest/sequencer/config.d.ts +1 -1
  23. package/dest/sequencer/config.d.ts.map +1 -1
  24. package/dest/sequencer/metrics.d.ts +2 -0
  25. package/dest/sequencer/metrics.d.ts.map +1 -1
  26. package/dest/sequencer/metrics.js +13 -2
  27. package/dest/sequencer/sequencer.d.ts +1 -4
  28. package/dest/sequencer/sequencer.d.ts.map +1 -1
  29. package/dest/sequencer/sequencer.js +51 -54
  30. package/dest/tx_validator/gas_validator.d.ts +3 -4
  31. package/dest/tx_validator/gas_validator.d.ts.map +1 -1
  32. package/dest/tx_validator/gas_validator.js +25 -8
  33. package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
  34. package/dest/tx_validator/tx_validator_factory.js +6 -4
  35. package/package.json +26 -23
  36. package/src/config.ts +5 -60
  37. package/src/index.ts +0 -1
  38. package/src/publisher/index.ts +0 -1
  39. package/src/publisher/l1-publisher-metrics.ts +24 -3
  40. package/src/publisher/l1-publisher.ts +241 -68
  41. package/src/publisher/utils.ts +1 -10
  42. package/src/sequencer/allowed.ts +36 -0
  43. package/src/sequencer/config.ts +1 -1
  44. package/src/sequencer/metrics.ts +15 -1
  45. package/src/sequencer/sequencer.ts +61 -70
  46. package/src/tx_validator/gas_validator.ts +32 -6
  47. 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
- type ContractFunctionExecutionError,
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 { prettyLogViemError, prettyLogViemErrorMsg } from './utils.js';
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
- const errorName = tryGetCustomErrorName(err);
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.txsEffectsHash.toString('hex')}`,
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
- args,
557
- functionName,
558
- abi: RollupAbi,
559
- address: this.rollupContract.address,
560
- blockNumber: receipt.blockNumber,
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
- private async tryGetErrorFromRevertedTx(args: {
571
- args: any[];
572
- functionName: string;
573
- abi: any;
574
- address: Hex;
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
- await this.publicClient.simulateContract({ ...args, account: this.walletClient.account });
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 (err: any) {
581
- if (err.name === 'ContractFunctionExecutionError') {
582
- const execErr = err as ContractFunctionExecutionError;
583
- return compactArray([
584
- execErr.shortMessage,
585
- ...(execErr.metaMessages ?? []).slice(0, 2).map(s => s.trim()),
586
- ]).join(' ');
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`, err);
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
- aggregationObject: argsArray[3],
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 computeTxsEffectsHashGas = await this.l1TxUtils.estimateGas(this.account, {
754
- to: this.rollupContract.address,
755
- data: encodeFunctionData({
756
- abi: this.rollupContract.abi,
757
- functionName: 'computeTxsEffectsHash',
758
- args: [`0x${encodedData.body.toString('hex')}`],
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 = computeTxsEffectsHashGas + L1Publisher.PROPOSE_GAS_GUESS;
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: encodeFunctionData({
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
- prettyLogViemError(err, this.log);
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
- this.log.info(`ProposeAndClaim`);
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: encodeFunctionData({
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
- prettyLogViemError(err, this.log);
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
@@ -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
+ }
@@ -1 +1 @@
1
- export { SequencerConfig } from '@aztec/circuit-types';
1
+ export { type SequencerConfig } from '@aztec/circuit-types/config';
@@ -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 number',
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',