@aztec/sequencer-client 0.67.0 → 0.67.1-devnet
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.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.js +145 -35
- 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/sequencer.d.ts +0 -4
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +20 -50
- 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 +23 -20
- package/src/config.ts +5 -60
- package/src/index.ts +0 -1
- package/src/publisher/index.ts +0 -1
- package/src/publisher/l1-publisher.ts +183 -55
- package/src/sequencer/allowed.ts +36 -0
- package/src/sequencer/config.ts +1 -1
- package/src/sequencer/sequencer.ts +19 -66
- package/src/tx_validator/gas_validator.ts +32 -6
- package/src/tx_validator/tx_validator_factory.ts +11 -3
package/src/config.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type AllowedElement } from '@aztec/circuit-types';
|
|
2
|
-
import { AztecAddress, Fr, FunctionSelector
|
|
1
|
+
import { type AllowedElement, type SequencerConfig } from '@aztec/circuit-types/config';
|
|
2
|
+
import { AztecAddress, Fr, FunctionSelector } from '@aztec/circuits.js';
|
|
3
3
|
import {
|
|
4
4
|
type L1ContractsConfig,
|
|
5
5
|
type L1ReaderConfig,
|
|
@@ -14,9 +14,6 @@ import {
|
|
|
14
14
|
} from '@aztec/foundation/config';
|
|
15
15
|
import { pickConfigMappings } from '@aztec/foundation/config';
|
|
16
16
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
17
|
-
import { FPCContract } from '@aztec/noir-contracts.js/FPC';
|
|
18
|
-
import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
|
|
19
|
-
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
20
17
|
|
|
21
18
|
import {
|
|
22
19
|
type PublisherConfig,
|
|
@@ -24,7 +21,9 @@ import {
|
|
|
24
21
|
getPublisherConfigMappings,
|
|
25
22
|
getTxSenderConfigMappings,
|
|
26
23
|
} from './publisher/config.js';
|
|
27
|
-
|
|
24
|
+
|
|
25
|
+
export * from './publisher/config.js';
|
|
26
|
+
export { SequencerConfig };
|
|
28
27
|
|
|
29
28
|
/** Chain configuration. */
|
|
30
29
|
type ChainConfig = {
|
|
@@ -60,17 +59,6 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
|
|
|
60
59
|
description: 'The minimum number of txs to include in a block.',
|
|
61
60
|
...numberConfigHelper(1),
|
|
62
61
|
},
|
|
63
|
-
minSecondsBetweenBlocks: {
|
|
64
|
-
env: 'SEQ_MIN_SECONDS_BETWEEN_BLOCKS',
|
|
65
|
-
description: 'The minimum number of seconds in-between consecutive blocks.',
|
|
66
|
-
...numberConfigHelper(0),
|
|
67
|
-
},
|
|
68
|
-
maxSecondsBetweenBlocks: {
|
|
69
|
-
env: 'SEQ_MAX_SECONDS_BETWEEN_BLOCKS',
|
|
70
|
-
description:
|
|
71
|
-
'The maximum number of seconds in-between consecutive blocks. Sequencer will produce a block with less than minTxsPerBlock once this threshold is reached.',
|
|
72
|
-
...numberConfigHelper(0),
|
|
73
|
-
},
|
|
74
62
|
coinbase: {
|
|
75
63
|
env: 'COINBASE',
|
|
76
64
|
parseEnv: (val: string) => EthAddress.fromString(val),
|
|
@@ -92,18 +80,10 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
|
|
|
92
80
|
allowedInSetup: {
|
|
93
81
|
env: 'SEQ_ALLOWED_SETUP_FN',
|
|
94
82
|
parseEnv: (val: string) => parseSequencerAllowList(val),
|
|
95
|
-
defaultValue: getDefaultAllowedSetupFunctions(),
|
|
96
83
|
description: 'The list of functions calls allowed to run in setup',
|
|
97
84
|
printDefault: () =>
|
|
98
85
|
'AuthRegistry, FeeJuice.increase_public_balance, Token.increase_public_balance, FPC.prepare_fee',
|
|
99
86
|
},
|
|
100
|
-
allowedInTeardown: {
|
|
101
|
-
env: 'SEQ_ALLOWED_TEARDOWN_FN',
|
|
102
|
-
parseEnv: (val: string) => parseSequencerAllowList(val),
|
|
103
|
-
defaultValue: getDefaultAllowedTeardownFunctions(),
|
|
104
|
-
description: 'The list of functions calls allowed to run teardown',
|
|
105
|
-
printDefault: () => 'FPC.pay_refund',
|
|
106
|
-
},
|
|
107
87
|
maxBlockSizeInBytes: {
|
|
108
88
|
env: 'SEQ_MAX_BLOCK_SIZE_IN_BYTES',
|
|
109
89
|
description: 'Max block size',
|
|
@@ -202,38 +182,3 @@ export function parseSequencerAllowList(value: string): AllowedElement[] {
|
|
|
202
182
|
|
|
203
183
|
return entries;
|
|
204
184
|
}
|
|
205
|
-
|
|
206
|
-
function getDefaultAllowedSetupFunctions(): AllowedElement[] {
|
|
207
|
-
return [
|
|
208
|
-
// needed for authwit support
|
|
209
|
-
{
|
|
210
|
-
address: ProtocolContractAddress.AuthRegistry,
|
|
211
|
-
},
|
|
212
|
-
// needed for claiming on the same tx as a spend
|
|
213
|
-
{
|
|
214
|
-
address: ProtocolContractAddress.FeeJuice,
|
|
215
|
-
// We can't restrict the selector because public functions get routed via dispatch.
|
|
216
|
-
// selector: FunctionSelector.fromSignature('_increase_public_balance((Field),Field)'),
|
|
217
|
-
},
|
|
218
|
-
// needed for private transfers via FPC
|
|
219
|
-
{
|
|
220
|
-
classId: getContractClassFromArtifact(TokenContractArtifact).id,
|
|
221
|
-
// We can't restrict the selector because public functions get routed via dispatch.
|
|
222
|
-
// selector: FunctionSelector.fromSignature('_increase_public_balance((Field),Field)'),
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
classId: getContractClassFromArtifact(FPCContract.artifact).id,
|
|
226
|
-
// We can't restrict the selector because public functions get routed via dispatch.
|
|
227
|
-
// selector: FunctionSelector.fromSignature('prepare_fee((Field),Field,(Field),Field)'),
|
|
228
|
-
},
|
|
229
|
-
];
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function getDefaultAllowedTeardownFunctions(): AllowedElement[] {
|
|
233
|
-
return [
|
|
234
|
-
{
|
|
235
|
-
classId: getContractClassFromArtifact(FPCContract.artifact).id,
|
|
236
|
-
selector: FunctionSelector.fromSignature('pay_refund((Field),Field,(Field))'),
|
|
237
|
-
},
|
|
238
|
-
];
|
|
239
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './client/index.js';
|
|
2
2
|
export * from './config.js';
|
|
3
3
|
export * from './publisher/index.js';
|
|
4
|
-
export * from './sequencer/index.js';
|
|
5
4
|
|
|
6
5
|
// Used by the node to simulate public parts of transactions. Should these be moved to a shared library?
|
|
7
6
|
// ISSUE(#9832)
|
package/src/publisher/index.ts
CHANGED
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
createEthereumChain,
|
|
26
26
|
} from '@aztec/ethereum';
|
|
27
27
|
import { makeTuple } from '@aztec/foundation/array';
|
|
28
|
+
import { toHex } from '@aztec/foundation/bigint-buffer';
|
|
29
|
+
import { Blob } from '@aztec/foundation/blob';
|
|
28
30
|
import { areArraysEqual, compactArray, times } from '@aztec/foundation/collection';
|
|
29
31
|
import { type Signature } from '@aztec/foundation/eth-signature';
|
|
30
32
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -32,7 +34,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
32
34
|
import { type Tuple, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
33
35
|
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
34
36
|
import { Timer } from '@aztec/foundation/timer';
|
|
35
|
-
import { GovernanceProposerAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
37
|
+
import { ExtRollupLibAbi, GovernanceProposerAbi, LeonidasLibAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
36
38
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
37
39
|
|
|
38
40
|
import pick from 'lodash.pick';
|
|
@@ -41,7 +43,7 @@ import {
|
|
|
41
43
|
type BaseError,
|
|
42
44
|
type Chain,
|
|
43
45
|
type Client,
|
|
44
|
-
|
|
46
|
+
ContractFunctionExecutionError,
|
|
45
47
|
ContractFunctionRevertedError,
|
|
46
48
|
type GetContractReturnType,
|
|
47
49
|
type Hex,
|
|
@@ -60,6 +62,7 @@ import {
|
|
|
60
62
|
getAbiItem,
|
|
61
63
|
getAddress,
|
|
62
64
|
getContract,
|
|
65
|
+
getContractError,
|
|
63
66
|
hexToBytes,
|
|
64
67
|
http,
|
|
65
68
|
publicActions,
|
|
@@ -110,8 +113,10 @@ type L1ProcessArgs = {
|
|
|
110
113
|
archive: Buffer;
|
|
111
114
|
/** The L2 block's leaf in the archive tree. */
|
|
112
115
|
blockHash: Buffer;
|
|
113
|
-
/** L2 block body. */
|
|
116
|
+
/** L2 block body. TODO(#9101): Remove block body once we can extract blobs. */
|
|
114
117
|
body: Buffer;
|
|
118
|
+
/** L2 block blobs containing all tx effects. */
|
|
119
|
+
blobs: Blob[];
|
|
115
120
|
/** L2 block tx hashes */
|
|
116
121
|
txHashes: TxHash[];
|
|
117
122
|
/** Attestations */
|
|
@@ -166,6 +171,9 @@ export class L1Publisher {
|
|
|
166
171
|
protected account: PrivateKeyAccount;
|
|
167
172
|
protected ethereumSlotDuration: bigint;
|
|
168
173
|
|
|
174
|
+
// @note - with blobs, the below estimate seems too large.
|
|
175
|
+
// Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob)
|
|
176
|
+
// Total used for emptier block from above test: 429k (of which 84k is 1x blob)
|
|
169
177
|
public static PROPOSE_GAS_GUESS: bigint = 12_000_000n;
|
|
170
178
|
public static PROPOSE_AND_CLAIM_GAS_GUESS: bigint = this.PROPOSE_GAS_GUESS + 100_000n;
|
|
171
179
|
|
|
@@ -342,7 +350,10 @@ export class L1Publisher {
|
|
|
342
350
|
try {
|
|
343
351
|
await this.rollupContract.read.validateEpochProofRightClaimAtTime(args, { account: this.account });
|
|
344
352
|
} catch (err) {
|
|
345
|
-
|
|
353
|
+
let errorName = tryGetCustomErrorName(err);
|
|
354
|
+
if (!errorName) {
|
|
355
|
+
errorName = tryGetCustomErrorNameContractFunction(err as ContractFunctionExecutionError);
|
|
356
|
+
}
|
|
346
357
|
this.log.warn(`Proof quote validation failed: ${errorName}`, quote);
|
|
347
358
|
return undefined;
|
|
348
359
|
}
|
|
@@ -375,7 +386,7 @@ export class L1Publisher {
|
|
|
375
386
|
formattedSignatures,
|
|
376
387
|
`0x${attestationData.digest.toString('hex')}`,
|
|
377
388
|
ts,
|
|
378
|
-
`0x${header.contentCommitment.
|
|
389
|
+
`0x${header.contentCommitment.blobsHash.toString('hex')}`,
|
|
379
390
|
flags,
|
|
380
391
|
] as const;
|
|
381
392
|
|
|
@@ -386,6 +397,36 @@ export class L1Publisher {
|
|
|
386
397
|
if (error instanceof ContractFunctionRevertedError) {
|
|
387
398
|
const err = error as ContractFunctionRevertedError;
|
|
388
399
|
this.log.debug(`Validation failed: ${err.message}`, err.data);
|
|
400
|
+
} else if (error instanceof ContractFunctionExecutionError) {
|
|
401
|
+
let err = error as ContractFunctionRevertedError;
|
|
402
|
+
if (!tryGetCustomErrorName(err)) {
|
|
403
|
+
// If we get here, it's because the custom error no longer exists in Rollup.sol,
|
|
404
|
+
// but in another lib. The below reconstructs the error message.
|
|
405
|
+
try {
|
|
406
|
+
await this.publicClient.estimateGas({
|
|
407
|
+
data: encodeFunctionData({
|
|
408
|
+
abi: this.rollupContract.abi,
|
|
409
|
+
functionName: 'validateHeader',
|
|
410
|
+
args,
|
|
411
|
+
}),
|
|
412
|
+
account: this.account,
|
|
413
|
+
to: this.rollupContract.address,
|
|
414
|
+
});
|
|
415
|
+
} catch (estGasErr: unknown) {
|
|
416
|
+
const possibleAbis = [ExtRollupLibAbi, LeonidasLibAbi];
|
|
417
|
+
possibleAbis.forEach(abi => {
|
|
418
|
+
const possibleErr = getContractError(estGasErr as BaseError, {
|
|
419
|
+
args: [],
|
|
420
|
+
abi: abi,
|
|
421
|
+
functionName: 'validateHeader',
|
|
422
|
+
address: this.rollupContract.address,
|
|
423
|
+
sender: this.account.address,
|
|
424
|
+
});
|
|
425
|
+
err = tryGetCustomErrorName(possibleErr) ? possibleErr : err;
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
throw err;
|
|
429
|
+
}
|
|
389
430
|
} else {
|
|
390
431
|
this.log.debug(`Unexpected error during validation: ${error}`);
|
|
391
432
|
}
|
|
@@ -501,10 +542,10 @@ export class L1Publisher {
|
|
|
501
542
|
archive: block.archive.root.toBuffer(),
|
|
502
543
|
blockHash: block.header.hash().toBuffer(),
|
|
503
544
|
body: block.body.toBuffer(),
|
|
545
|
+
blobs: Blob.getBlobs(block.body.toBlobFields()),
|
|
504
546
|
attestations,
|
|
505
547
|
txHashes: txHashes ?? [],
|
|
506
548
|
};
|
|
507
|
-
|
|
508
549
|
// Publish body and propose block (if not already published)
|
|
509
550
|
if (this.interrupted) {
|
|
510
551
|
this.log.verbose('L2 block data syncing interrupted while processing blocks.', ctx);
|
|
@@ -532,7 +573,7 @@ export class L1Publisher {
|
|
|
532
573
|
return false;
|
|
533
574
|
}
|
|
534
575
|
|
|
535
|
-
const { receipt, args, functionName } = result;
|
|
576
|
+
const { receipt, args, functionName, data } = result;
|
|
536
577
|
|
|
537
578
|
// Tx was mined successfully
|
|
538
579
|
if (receipt.status === 'success') {
|
|
@@ -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,69 @@ export class L1Publisher {
|
|
|
567
615
|
return false;
|
|
568
616
|
}
|
|
569
617
|
|
|
570
|
-
private async tryGetErrorFromRevertedTx(
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
618
|
+
private async tryGetErrorFromRevertedTx(
|
|
619
|
+
data: Hex,
|
|
620
|
+
args: {
|
|
621
|
+
args: any[];
|
|
622
|
+
functionName: string;
|
|
623
|
+
abi: any;
|
|
624
|
+
address: Hex;
|
|
625
|
+
},
|
|
626
|
+
_blobInputs?: {
|
|
627
|
+
blobs: Uint8Array[];
|
|
628
|
+
kzg: any;
|
|
629
|
+
maxFeePerBlobGas: bigint;
|
|
630
|
+
},
|
|
631
|
+
) {
|
|
632
|
+
const blobInputs = _blobInputs || {};
|
|
577
633
|
try {
|
|
578
|
-
|
|
634
|
+
// NB: If this fn starts unexpectedly giving incorrect blob hash errors, it may be because the checkBlob
|
|
635
|
+
// bool is no longer at the slot below. To find the slot, run: forge inspect src/core/Rollup.sol:Rollup storage
|
|
636
|
+
const checkBlobSlot = 9n;
|
|
637
|
+
await this.publicClient.simulateContract({
|
|
638
|
+
...args,
|
|
639
|
+
account: this.walletClient.account,
|
|
640
|
+
stateOverride: [
|
|
641
|
+
{
|
|
642
|
+
address: args.address,
|
|
643
|
+
stateDiff: [
|
|
644
|
+
{
|
|
645
|
+
slot: toHex(checkBlobSlot, true),
|
|
646
|
+
value: toHex(0n, true),
|
|
647
|
+
},
|
|
648
|
+
],
|
|
649
|
+
},
|
|
650
|
+
],
|
|
651
|
+
});
|
|
652
|
+
// If the above passes, we have a blob error. We cannot simulate blob txs, and failed txs no longer throw errors,
|
|
653
|
+
// and viem provides no way to get the revert reason from a given tx.
|
|
654
|
+
// Strangely, the only way to throw the revert reason as an error and provide blobs is prepareTransactionRequest.
|
|
655
|
+
// See: https://github.com/wevm/viem/issues/2075
|
|
656
|
+
// This throws a EstimateGasExecutionError with the custom error information:
|
|
657
|
+
await this.walletClient.prepareTransactionRequest({
|
|
658
|
+
account: this.walletClient.account,
|
|
659
|
+
to: this.rollupContract.address,
|
|
660
|
+
data,
|
|
661
|
+
...blobInputs,
|
|
662
|
+
});
|
|
579
663
|
return undefined;
|
|
580
|
-
} catch (
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
664
|
+
} catch (simulationErr: any) {
|
|
665
|
+
// If we don't have a ContractFunctionExecutionError, we have a blob related error => use ExtRollupLibAbi to get the error msg.
|
|
666
|
+
const contractErr =
|
|
667
|
+
simulationErr.name === 'ContractFunctionExecutionError'
|
|
668
|
+
? simulationErr
|
|
669
|
+
: getContractError(simulationErr as BaseError, {
|
|
670
|
+
args: [],
|
|
671
|
+
abi: ExtRollupLibAbi,
|
|
672
|
+
functionName: args.functionName,
|
|
673
|
+
address: args.address,
|
|
674
|
+
sender: this.account.address,
|
|
675
|
+
});
|
|
676
|
+
if (contractErr.name === 'ContractFunctionExecutionError') {
|
|
677
|
+
const execErr = contractErr as ContractFunctionExecutionError;
|
|
678
|
+
return tryGetCustomErrorNameContractFunction(execErr);
|
|
587
679
|
}
|
|
588
|
-
this.log.error(`Error getting error from simulation`,
|
|
680
|
+
this.log.error(`Error getting error from simulation`, simulationErr);
|
|
589
681
|
}
|
|
590
682
|
}
|
|
591
683
|
|
|
@@ -726,7 +818,8 @@ export class L1Publisher {
|
|
|
726
818
|
epochSize: argsArray[0],
|
|
727
819
|
args: argsArray[1],
|
|
728
820
|
fees: argsArray[2],
|
|
729
|
-
|
|
821
|
+
blobPublicInputs: argsArray[3],
|
|
822
|
+
aggregationObject: argsArray[4],
|
|
730
823
|
proof: proofHex,
|
|
731
824
|
},
|
|
732
825
|
] as const;
|
|
@@ -750,22 +843,31 @@ export class L1Publisher {
|
|
|
750
843
|
}
|
|
751
844
|
|
|
752
845
|
private async prepareProposeTx(encodedData: L1ProcessArgs) {
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
846
|
+
const kzg = Blob.getViemKzgInstance();
|
|
847
|
+
const blobEvaluationGas = await this.l1TxUtils.estimateGas(
|
|
848
|
+
this.account,
|
|
849
|
+
{
|
|
850
|
+
to: this.rollupContract.address,
|
|
851
|
+
data: encodeFunctionData({
|
|
852
|
+
abi: this.rollupContract.abi,
|
|
853
|
+
functionName: 'validateBlobs',
|
|
854
|
+
args: [Blob.getEthBlobEvaluationInputs(encodedData.blobs)],
|
|
855
|
+
}),
|
|
856
|
+
},
|
|
857
|
+
{},
|
|
858
|
+
{
|
|
859
|
+
blobs: encodedData.blobs.map(b => b.data),
|
|
860
|
+
kzg,
|
|
861
|
+
maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS
|
|
862
|
+
},
|
|
863
|
+
);
|
|
761
864
|
|
|
762
865
|
// @note We perform this guesstimate instead of the usual `gasEstimate` since
|
|
763
866
|
// viem will use the current state to simulate against, which means that
|
|
764
867
|
// we will fail estimation in the case where we are simulating for the
|
|
765
868
|
// first ethereum block within our slot (as current time is not in the
|
|
766
869
|
// slot yet).
|
|
767
|
-
const gasGuesstimate =
|
|
768
|
-
|
|
870
|
+
const gasGuesstimate = blobEvaluationGas + L1Publisher.PROPOSE_GAS_GUESS;
|
|
769
871
|
const attestations = encodedData.attestations
|
|
770
872
|
? encodedData.attestations.map(attest => attest.toViemSignature())
|
|
771
873
|
: [];
|
|
@@ -783,7 +885,9 @@ export class L1Publisher {
|
|
|
783
885
|
txHashes,
|
|
784
886
|
},
|
|
785
887
|
attestations,
|
|
888
|
+
// TODO(#9101): Extract blobs from beacon chain => calldata will only contain what's needed to verify blob and body input can be removed
|
|
786
889
|
`0x${encodedData.body.toString('hex')}`,
|
|
890
|
+
Blob.getEthBlobEvaluationInputs(encodedData.blobs),
|
|
787
891
|
] as const;
|
|
788
892
|
|
|
789
893
|
return { args, gas: gasGuesstimate };
|
|
@@ -811,35 +915,47 @@ export class L1Publisher {
|
|
|
811
915
|
? args.publicInputs.fees[i / 2].recipient.toField().toString()
|
|
812
916
|
: args.publicInputs.fees[(i - 1) / 2].value.toString(),
|
|
813
917
|
),
|
|
918
|
+
`0x${args.publicInputs.blobPublicInputs
|
|
919
|
+
.filter((_, i) => i < args.toBlock - args.fromBlock + 1)
|
|
920
|
+
.map(b => b.toString())
|
|
921
|
+
.join(``)}`,
|
|
814
922
|
`0x${serializeToBuffer(args.proof.extractAggregationObject()).toString('hex')}`,
|
|
815
923
|
] as const;
|
|
816
924
|
}
|
|
817
925
|
|
|
818
926
|
private async sendProposeTx(
|
|
819
927
|
encodedData: L1ProcessArgs,
|
|
820
|
-
): Promise<{ receipt: TransactionReceipt; args: any; functionName: string } | undefined> {
|
|
928
|
+
): Promise<{ receipt: TransactionReceipt | undefined; args: any; functionName: string; data: Hex } | undefined> {
|
|
821
929
|
if (this.interrupted) {
|
|
822
930
|
return undefined;
|
|
823
931
|
}
|
|
824
932
|
try {
|
|
933
|
+
const kzg = Blob.getViemKzgInstance();
|
|
825
934
|
const { args, gas } = await this.prepareProposeTx(encodedData);
|
|
935
|
+
const data = encodeFunctionData({
|
|
936
|
+
abi: this.rollupContract.abi,
|
|
937
|
+
functionName: 'propose',
|
|
938
|
+
args,
|
|
939
|
+
});
|
|
826
940
|
const receipt = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
827
941
|
{
|
|
828
942
|
to: this.rollupContract.address,
|
|
829
|
-
data
|
|
830
|
-
abi: this.rollupContract.abi,
|
|
831
|
-
functionName: 'propose',
|
|
832
|
-
args,
|
|
833
|
-
}),
|
|
943
|
+
data,
|
|
834
944
|
},
|
|
835
945
|
{
|
|
836
946
|
fixedGas: gas,
|
|
837
947
|
},
|
|
948
|
+
{
|
|
949
|
+
blobs: encodedData.blobs.map(b => b.data),
|
|
950
|
+
kzg,
|
|
951
|
+
maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS
|
|
952
|
+
},
|
|
838
953
|
);
|
|
839
954
|
return {
|
|
840
955
|
receipt,
|
|
841
956
|
args,
|
|
842
957
|
functionName: 'propose',
|
|
958
|
+
data,
|
|
843
959
|
};
|
|
844
960
|
} catch (err) {
|
|
845
961
|
prettyLogViemError(err, this.log);
|
|
@@ -851,7 +967,7 @@ export class L1Publisher {
|
|
|
851
967
|
private async sendProposeAndClaimTx(
|
|
852
968
|
encodedData: L1ProcessArgs,
|
|
853
969
|
quote: EpochProofQuote,
|
|
854
|
-
): Promise<{ receipt: TransactionReceipt; args: any; functionName: string } | undefined> {
|
|
970
|
+
): Promise<{ receipt: TransactionReceipt | undefined; args: any; functionName: string; data: Hex } | undefined> {
|
|
855
971
|
if (this.interrupted) {
|
|
856
972
|
return undefined;
|
|
857
973
|
}
|
|
@@ -859,23 +975,31 @@ export class L1Publisher {
|
|
|
859
975
|
this.log.info(`ProposeAndClaim`);
|
|
860
976
|
this.log.info(inspect(quote.payload));
|
|
861
977
|
|
|
978
|
+
const kzg = Blob.getViemKzgInstance();
|
|
862
979
|
const { args, gas } = await this.prepareProposeTx(encodedData);
|
|
980
|
+
const data = encodeFunctionData({
|
|
981
|
+
abi: this.rollupContract.abi,
|
|
982
|
+
functionName: 'proposeAndClaim',
|
|
983
|
+
args: [...args, quote.toViemArgs()],
|
|
984
|
+
});
|
|
863
985
|
const receipt = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
864
986
|
{
|
|
865
987
|
to: this.rollupContract.address,
|
|
866
|
-
data
|
|
867
|
-
abi: this.rollupContract.abi,
|
|
868
|
-
functionName: 'proposeAndClaim',
|
|
869
|
-
args: [...args, quote.toViemArgs()],
|
|
870
|
-
}),
|
|
988
|
+
data,
|
|
871
989
|
},
|
|
872
990
|
{ fixedGas: gas },
|
|
991
|
+
{
|
|
992
|
+
blobs: encodedData.blobs.map(b => b.data),
|
|
993
|
+
kzg,
|
|
994
|
+
maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS
|
|
995
|
+
},
|
|
873
996
|
);
|
|
874
997
|
|
|
875
998
|
return {
|
|
876
999
|
receipt,
|
|
877
|
-
args,
|
|
1000
|
+
args: [...args, quote.toViemArgs()],
|
|
878
1001
|
functionName: 'proposeAndClaim',
|
|
1002
|
+
data,
|
|
879
1003
|
};
|
|
880
1004
|
} catch (err) {
|
|
881
1005
|
prettyLogViemError(err, this.log);
|
|
@@ -935,6 +1059,10 @@ function getCalldataGasUsage(data: Uint8Array) {
|
|
|
935
1059
|
return data.filter(byte => byte === 0).length * 4 + data.filter(byte => byte !== 0).length * 16;
|
|
936
1060
|
}
|
|
937
1061
|
|
|
1062
|
+
function tryGetCustomErrorNameContractFunction(err: ContractFunctionExecutionError) {
|
|
1063
|
+
return compactArray([err.shortMessage, ...(err.metaMessages ?? []).slice(0, 2).map(s => s.trim())]).join(' ');
|
|
1064
|
+
}
|
|
1065
|
+
|
|
938
1066
|
function tryGetCustomErrorName(err: any) {
|
|
939
1067
|
try {
|
|
940
1068
|
// See https://viem.sh/docs/contract/simulateContract#handling-custom-errors
|
|
@@ -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';
|