@aztec/sequencer-client 0.56.0 → 0.57.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 (38) hide show
  1. package/dest/block_builder/index.d.ts +2 -2
  2. package/dest/block_builder/index.d.ts.map +1 -1
  3. package/dest/block_builder/light.d.ts +7 -11
  4. package/dest/block_builder/light.d.ts.map +1 -1
  5. package/dest/block_builder/light.js +6 -11
  6. package/dest/block_builder/orchestrator.d.ts +7 -10
  7. package/dest/block_builder/orchestrator.d.ts.map +1 -1
  8. package/dest/block_builder/orchestrator.js +3 -10
  9. package/dest/config.js +8 -5
  10. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  11. package/dest/global_variable_builder/global_builder.js +2 -1
  12. package/dest/publisher/config.d.ts.map +1 -1
  13. package/dest/publisher/config.js +7 -2
  14. package/dest/publisher/index.d.ts +1 -1
  15. package/dest/publisher/index.d.ts.map +1 -1
  16. package/dest/publisher/index.js +1 -1
  17. package/dest/publisher/l1-publisher.d.ts +45 -34
  18. package/dest/publisher/l1-publisher.d.ts.map +1 -1
  19. package/dest/publisher/l1-publisher.js +257 -115
  20. package/dest/publisher/utils.d.ts +1 -1
  21. package/dest/publisher/utils.js +1 -1
  22. package/dest/sequencer/sequencer.d.ts +3 -2
  23. package/dest/sequencer/sequencer.d.ts.map +1 -1
  24. package/dest/sequencer/sequencer.js +54 -18
  25. package/dest/tx_validator/gas_validator.d.ts.map +1 -1
  26. package/dest/tx_validator/gas_validator.js +7 -5
  27. package/package.json +22 -19
  28. package/src/block_builder/index.ts +2 -2
  29. package/src/block_builder/light.ts +10 -19
  30. package/src/block_builder/orchestrator.ts +7 -20
  31. package/src/config.ts +7 -4
  32. package/src/global_variable_builder/global_builder.ts +1 -0
  33. package/src/publisher/config.ts +6 -1
  34. package/src/publisher/index.ts +1 -1
  35. package/src/publisher/l1-publisher.ts +369 -142
  36. package/src/publisher/utils.ts +1 -1
  37. package/src/sequencer/sequencer.ts +68 -20
  38. package/src/tx_validator/gas_validator.ts +6 -7
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  type BlockAttestation,
3
+ type EpochProofQuote,
3
4
  type L1ToL2MessageSource,
4
5
  type L2Block,
5
6
  type L2BlockSource,
@@ -10,7 +11,7 @@ import {
10
11
  type WorldStateStatus,
11
12
  type WorldStateSynchronizer,
12
13
  } from '@aztec/circuit-types';
13
- import { type AllowedElement, BlockProofError, PROVING_STATUS } from '@aztec/circuit-types/interfaces';
14
+ import { type AllowedElement, BlockProofError } from '@aztec/circuit-types/interfaces';
14
15
  import { type L2BlockBuiltStats } from '@aztec/circuit-types/stats';
15
16
  import {
16
17
  AppendOnlyTreeSnapshot,
@@ -31,10 +32,12 @@ import { type PublicProcessorFactory } from '@aztec/simulator';
31
32
  import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client';
32
33
  import { type ValidatorClient } from '@aztec/validator-client';
33
34
 
35
+ import { inspect } from 'util';
36
+
34
37
  import { type BlockBuilderFactory } from '../block_builder/index.js';
35
38
  import { type GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
36
39
  import { type L1Publisher } from '../publisher/l1-publisher.js';
37
- import { prettyLogVeimError } from '../publisher/utils.js';
40
+ import { prettyLogViemError } from '../publisher/utils.js';
38
41
  import { type TxValidatorFactory } from '../tx_validator/tx_validator_factory.js';
39
42
  import { type SequencerConfig } from './config.js';
40
43
  import { SequencerMetrics } from './metrics.js';
@@ -311,7 +314,7 @@ export class Sequencer {
311
314
  this.log.debug(`Can propose block ${proposalBlockNumber} at slot ${slot}`);
312
315
  return slot;
313
316
  } catch (err) {
314
- prettyLogVeimError(err, this.log);
317
+ prettyLogViemError(err, this.log);
315
318
  throw err;
316
319
  }
317
320
  }
@@ -424,7 +427,7 @@ export class Sequencer {
424
427
 
425
428
  const blockBuildingTimer = new Timer();
426
429
  const blockBuilder = this.blockBuilderFactory.create(this.worldState.getLatest());
427
- const blockTicket = await blockBuilder.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages);
430
+ await blockBuilder.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages);
428
431
 
429
432
  const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() =>
430
433
  processor.process(validTxs, blockSize, blockBuilder, this.txValidatorFactory.validatorForProcessedTxs()),
@@ -443,23 +446,15 @@ export class Sequencer {
443
446
  processedTxsCount: processedTxs.length,
444
447
  })
445
448
  ) {
446
- blockBuilder.cancel();
449
+ // TODO: Roll back changes to world state
447
450
  throw new Error('Should not propose the block');
448
451
  }
449
452
 
450
453
  // All real transactions have been added, set the block as full and complete the proving.
451
- await blockBuilder.setBlockCompleted();
454
+ const block = await blockBuilder.setBlockCompleted();
452
455
 
453
- // Here we are now waiting for the block to be proven (using simulated[fake] proofs).
454
456
  // TODO(@PhilWindle) We should probably periodically check for things like another
455
457
  // block being published before ours instead of just waiting on our block
456
- const result = await blockTicket.provingPromise;
457
- if (result.status === PROVING_STATUS.FAILURE) {
458
- throw new Error(`Block proving failed, reason: ${result.reason}`);
459
- }
460
-
461
- // Block is ready, now finalise
462
- const { block } = await blockBuilder.finaliseBlock();
463
458
 
464
459
  await this.publisher.validateBlockForSubmission(block.header);
465
460
 
@@ -488,13 +483,17 @@ export class Sequencer {
488
483
  const attestations = await this.collectAttestations(block, txHashes);
489
484
  this.log.verbose('Attestations collected');
490
485
 
486
+ this.log.verbose('Collecting proof quotes');
487
+ const proofQuote = await this.createProofClaimForPreviousEpoch(newGlobalVariables.slotNumber.toBigInt());
488
+ this.log.verbose(proofQuote ? `Using proof quote ${inspect(proofQuote.payload)}` : 'No proof quote available');
489
+
491
490
  try {
492
- await this.publishL2Block(block, attestations, txHashes);
491
+ await this.publishL2Block(block, attestations, txHashes, proofQuote);
493
492
  this.metrics.recordPublishedBlock(workDuration);
494
493
  this.log.info(
495
- `Submitted rollup block ${block.number} with ${
496
- processedTxs.length
497
- } transactions duration=${workDuration}ms (Submitter: ${await this.publisher.getSenderAddress()})`,
494
+ `Submitted rollup block ${block.number} with ${processedTxs.length} transactions duration=${Math.ceil(
495
+ workDuration,
496
+ )}ms (Submitter: ${this.publisher.getSenderAddress()})`,
498
497
  );
499
498
  } catch (err) {
500
499
  this.metrics.recordFailedBlock();
@@ -540,6 +539,50 @@ export class Sequencer {
540
539
  return orderAttestations(attestations, committee);
541
540
  }
542
541
 
542
+ protected async createProofClaimForPreviousEpoch(slotNumber: bigint): Promise<EpochProofQuote | undefined> {
543
+ try {
544
+ // Find out which epoch we are currently in
545
+ const epochForBlock = await this.publisher.getEpochForSlotNumber(slotNumber);
546
+ if (epochForBlock < 1n) {
547
+ // It's the 0th epoch, nothing to be proven yet
548
+ this.log.verbose(`First epoch has no claim`);
549
+ return undefined;
550
+ }
551
+ const epochToProve = epochForBlock - 1n;
552
+ // Find out the next epoch that can be claimed
553
+ const canClaim = await this.publisher.nextEpochToClaim();
554
+ if (canClaim != epochToProve) {
555
+ // It's not the one we are looking to claim
556
+ this.log.verbose(`Unable to claim previous epoch (${canClaim} != ${epochToProve})`);
557
+ return undefined;
558
+ }
559
+ // Get quotes for the epoch to be proven
560
+ const quotes = await this.p2pClient.getEpochProofQuotes(epochToProve);
561
+ this.log.verbose(`Retrieved ${quotes.length} quotes, slot: ${slotNumber}, epoch to prove: ${epochToProve}`);
562
+ for (const quote of quotes) {
563
+ this.log.verbose(inspect(quote.payload));
564
+ }
565
+ // ensure these quotes are still valid for the slot and have the contract validate them
566
+ const validQuotesPromise = Promise.all(
567
+ quotes.filter(x => x.payload.validUntilSlot >= slotNumber).map(x => this.publisher.validateProofQuote(x)),
568
+ );
569
+
570
+ const validQuotes = (await validQuotesPromise).filter((q): q is EpochProofQuote => !!q);
571
+ if (!validQuotes.length) {
572
+ this.log.verbose(`Failed to find any valid proof quotes`);
573
+ return undefined;
574
+ }
575
+ // pick the quote with the lowest fee
576
+ const sortedQuotes = validQuotes.sort(
577
+ (a: EpochProofQuote, b: EpochProofQuote) => a.payload.basisPointFee - b.payload.basisPointFee,
578
+ );
579
+ return sortedQuotes[0];
580
+ } catch (err) {
581
+ this.log.error(`Failed to create proof claim for previous epoch: ${err}`);
582
+ return undefined;
583
+ }
584
+ }
585
+
543
586
  /**
544
587
  * Publishes the L2Block to the rollup contract.
545
588
  * @param block - The L2Block to be published.
@@ -547,11 +590,16 @@ export class Sequencer {
547
590
  @trackSpan('Sequencer.publishL2Block', block => ({
548
591
  [Attributes.BLOCK_NUMBER]: block.number,
549
592
  }))
550
- protected async publishL2Block(block: L2Block, attestations?: Signature[], txHashes?: TxHash[]) {
593
+ protected async publishL2Block(
594
+ block: L2Block,
595
+ attestations?: Signature[],
596
+ txHashes?: TxHash[],
597
+ proofQuote?: EpochProofQuote,
598
+ ) {
551
599
  // Publishes new block to the network and awaits the tx to be mined
552
600
  this.state = SequencerState.PUBLISHING_BLOCK;
553
601
 
554
- const publishedL2Block = await this.publisher.proposeL2Block(block, attestations, txHashes);
602
+ const publishedL2Block = await this.publisher.proposeL2Block(block, attestations, txHashes, proofQuote);
555
603
  if (publishedL2Block) {
556
604
  this.lastPublishedBlock = block.number;
557
605
  } else {
@@ -1,7 +1,6 @@
1
1
  import { PublicKernelPhase, type Tx, type TxValidator } from '@aztec/circuit-types';
2
- import { type AztecAddress, type Fr } from '@aztec/circuits.js';
2
+ import { type AztecAddress, type Fr, FunctionSelector } from '@aztec/circuits.js';
3
3
  import { createDebugLogger } from '@aztec/foundation/log';
4
- import { FeeJuiceArtifact } from '@aztec/protocol-contracts/fee-juice';
5
4
  import { EnqueuedCallsProcessor, computeFeePayerBalanceStorageSlot } from '@aztec/simulator';
6
5
 
7
6
  /** Provides a view into public contract state */
@@ -64,15 +63,15 @@ export class GasTxValidator implements TxValidator<Tx> {
64
63
  fn =>
65
64
  fn.contractAddress.equals(this.#feeJuiceAddress) &&
66
65
  fn.callContext.msgSender.equals(this.#feeJuiceAddress) &&
67
- fn.callContext.functionSelector.equals(
68
- FeeJuiceArtifact.functions.find(f => f.name === '_increase_public_balance')!,
69
- ) &&
70
- fn.args[0].equals(feePayer) &&
66
+ fn.args.length > 2 &&
67
+ // Public functions get routed through the dispatch function, whose first argument is the target function selector.
68
+ fn.args[0].equals(FunctionSelector.fromSignature('_increase_public_balance((Field),Field)').toField()) &&
69
+ fn.args[1].equals(feePayer) &&
71
70
  !fn.callContext.isStaticCall &&
72
71
  !fn.callContext.isDelegateCall,
73
72
  );
74
73
 
75
- const balance = claimFunctionCall ? initialBalance.add(claimFunctionCall.args[1]) : initialBalance;
74
+ const balance = claimFunctionCall ? initialBalance.add(claimFunctionCall.args[2]) : initialBalance;
76
75
  if (balance.lt(feeLimit)) {
77
76
  this.#log.info(`Rejecting transaction due to not enough fee payer balance`, { feePayer, balance, feeLimit });
78
77
  return false;