From 46dcb985e98ca26ee2dd3d2ec98976f1d8f27ba7 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 6 Jun 2024 16:38:30 +0100 Subject: [PATCH] feat: Add ENFORCE_FEES sequencer config (#6949) Sequencer will reject all txs without a fee payer if set. --- yarn-project/circuit-types/src/interfaces/configs.ts | 2 ++ .../sequencer-client/src/client/sequencer-client.ts | 2 +- yarn-project/sequencer-client/src/config.ts | 2 ++ .../sequencer-client/src/sequencer/sequencer.test.ts | 2 +- .../src/tx_validator/gas_validator.test.ts | 10 ++++++++-- .../sequencer-client/src/tx_validator/gas_validator.ts | 8 ++++++-- .../src/tx_validator/tx_validator_factory.ts | 8 ++++++-- 7 files changed, 26 insertions(+), 8 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/configs.ts b/yarn-project/circuit-types/src/interfaces/configs.ts index c86fb093f55..a4074c862c0 100644 --- a/yarn-project/circuit-types/src/interfaces/configs.ts +++ b/yarn-project/circuit-types/src/interfaces/configs.ts @@ -39,4 +39,6 @@ export interface SequencerConfig { allowedFunctionsInTeardown?: AllowedFunction[]; /** Max block size */ maxBlockSizeInBytes?: number; + /** Whether to require every tx to have a fee payer */ + enforceFees?: boolean; } diff --git a/yarn-project/sequencer-client/src/client/sequencer-client.ts b/yarn-project/sequencer-client/src/client/sequencer-client.ts index a8b4f6c8247..dae754f04a4 100644 --- a/yarn-project/sequencer-client/src/client/sequencer-client.ts +++ b/yarn-project/sequencer-client/src/client/sequencer-client.ts @@ -54,7 +54,7 @@ export class SequencerClient { l2BlockSource, l1ToL2MessageSource, publicProcessorFactory, - new TxValidatorFactory(merkleTreeDb, contractDataSource), + new TxValidatorFactory(merkleTreeDb, contractDataSource, !!config.enforceFees), config, ); diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts index a30ff6177a2..c3de3aba519 100644 --- a/yarn-project/sequencer-client/src/config.ts +++ b/yarn-project/sequencer-client/src/config.ts @@ -62,6 +62,7 @@ export function getConfigEnvVars(): SequencerClientConfig { FEE_RECIPIENT, ACVM_WORKING_DIRECTORY, ACVM_BINARY_PATH, + ENFORCE_FEES = '', } = process.env; const publisherPrivateKey: Hex = SEQ_PUBLISHER_PRIVATE_KEY @@ -83,6 +84,7 @@ export function getConfigEnvVars(): SequencerClientConfig { }; return { + enforceFees: ['1', 'true'].includes(ENFORCE_FEES), rpcUrl: ETHEREUM_HOST ? ETHEREUM_HOST : '', chainId: CHAIN_ID ? +CHAIN_ID : 31337, // 31337 is the default chain id for anvil version: VERSION ? +VERSION : 1, // 1 is our default version diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index fbcec5e886c..4292e85e838 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -114,7 +114,7 @@ describe('sequencer', () => { l2BlockSource, l1ToL2MessageSource, publicProcessorFactory, - new TxValidatorFactory(merkleTreeOps, contractSource), + new TxValidatorFactory(merkleTreeOps, contractSource, false), ); }); diff --git a/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts b/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts index cb45cc2ddf3..5cc1219637c 100644 --- a/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts +++ b/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts @@ -20,7 +20,7 @@ describe('GasTxValidator', () => { storageRead: mockFn().mockImplementation((_address: AztecAddress, _slot: Fr) => Fr.ZERO), }); - validator = new GasTxValidator(publicStateSource, gasTokenAddress); + validator = new GasTxValidator(publicStateSource, gasTokenAddress, false); }); let tx: Tx; @@ -94,7 +94,13 @@ describe('GasTxValidator', () => { await expectValidateFail(tx); }); - it.skip('rejects txs with no fee payer', async () => { + it('allows txs with no fee payer if fees are not enforced', async () => { + tx.data.feePayer = AztecAddress.ZERO; + await expectValidateSuccess(tx); + }); + + it('rejects txs with no fee payer if fees are enforced', async () => { + validator.enforceFees = true; tx.data.feePayer = AztecAddress.ZERO; await expectValidateFail(tx); }); diff --git a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts index bcad5e7e343..2fbf9975058 100644 --- a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts @@ -14,7 +14,7 @@ export class GasTxValidator implements TxValidator { #publicDataSource: PublicStateSource; #gasTokenAddress: AztecAddress; - constructor(publicDataSource: PublicStateSource, gasTokenAddress: AztecAddress) { + constructor(publicDataSource: PublicStateSource, gasTokenAddress: AztecAddress, public enforceFees: boolean) { this.#publicDataSource = publicDataSource; this.#gasTokenAddress = gasTokenAddress; } @@ -38,7 +38,11 @@ export class GasTxValidator implements TxValidator { const feePayer = tx.data.feePayer; // TODO(@spalladino) Eventually remove the is_zero condition as we should always charge fees to every tx if (feePayer.isZero()) { - return true; + if (this.enforceFees) { + this.#log.warn(`Rejecting transaction ${tx.getTxHash()} due to missing fee payer`); + } else { + return true; + } } // Compute the maximum fee that this tx may pay, based on its gasLimits and maxFeePerGas diff --git a/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts b/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts index f31f2862680..f997aabaa41 100644 --- a/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts +++ b/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts @@ -12,14 +12,18 @@ import { MetadataTxValidator } from './metadata_validator.js'; import { PhasesTxValidator } from './phases_validator.js'; export class TxValidatorFactory { - constructor(private merkleTreeDb: MerkleTreeOperations, private contractDataSource: ContractDataSource) {} + constructor( + private merkleTreeDb: MerkleTreeOperations, + private contractDataSource: ContractDataSource, + private enforceFees: boolean, + ) {} validatorForNewTxs(globalVariables: GlobalVariables, setupAllowList: AllowedFunction[]): TxValidator { return new AggregateTxValidator( new MetadataTxValidator(globalVariables), new DoubleSpendTxValidator(new WorldStateDB(this.merkleTreeDb)), new PhasesTxValidator(this.contractDataSource, setupAllowList), - new GasTxValidator(new WorldStatePublicDB(this.merkleTreeDb), GasTokenAddress), + new GasTxValidator(new WorldStatePublicDB(this.merkleTreeDb), GasTokenAddress, this.enforceFees), ); }