@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.
- package/dest/block_builder/index.d.ts +2 -2
- package/dest/block_builder/index.d.ts.map +1 -1
- package/dest/block_builder/light.d.ts +7 -11
- package/dest/block_builder/light.d.ts.map +1 -1
- package/dest/block_builder/light.js +6 -11
- package/dest/block_builder/orchestrator.d.ts +7 -10
- package/dest/block_builder/orchestrator.d.ts.map +1 -1
- package/dest/block_builder/orchestrator.js +3 -10
- package/dest/config.js +8 -5
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +2 -1
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +7 -2
- package/dest/publisher/index.d.ts +1 -1
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/index.js +1 -1
- package/dest/publisher/l1-publisher.d.ts +45 -34
- package/dest/publisher/l1-publisher.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.js +257 -115
- package/dest/publisher/utils.d.ts +1 -1
- package/dest/publisher/utils.js +1 -1
- package/dest/sequencer/sequencer.d.ts +3 -2
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +54 -18
- package/dest/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/tx_validator/gas_validator.js +7 -5
- package/package.json +22 -19
- package/src/block_builder/index.ts +2 -2
- package/src/block_builder/light.ts +10 -19
- package/src/block_builder/orchestrator.ts +7 -20
- package/src/config.ts +7 -4
- package/src/global_variable_builder/global_builder.ts +1 -0
- package/src/publisher/config.ts +6 -1
- package/src/publisher/index.ts +1 -1
- package/src/publisher/l1-publisher.ts +369 -142
- package/src/publisher/utils.ts +1 -1
- package/src/sequencer/sequencer.ts +68 -20
- 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
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
497
|
-
}
|
|
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(
|
|
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.
|
|
68
|
-
|
|
69
|
-
) &&
|
|
70
|
-
fn.args[
|
|
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[
|
|
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;
|