From da5a2821babf87732f34ab3a76e4ffa6e15bdb4d Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 27 Aug 2024 11:28:35 +0000 Subject: [PATCH] init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: fixing private voting by correctly throwing an error if simulation fails (#7840) This PR makes a simulation of a tx fail, if the tx cannot be included in a block and added to the state. e.g. If a simulation produces duplicate nullifiers, or nullifiers that already exist in a state tree, the results of this simulation should not be returned, but should warn users that the transaction simulated is impossible to actually be added to a block due to being an invalid transaction. The method for achieving the above is that a new API on the node was created, used for validating the correctness of the metadata and side-effects produced by a transaction. A transaction is deemed valid if and only if the transaction can be added to a block that can be used to advance state. Note: this update does not make this validation necessary, and defaults to offline simulation. Offline simulation is previous non-validated behavior, and is potentially useful if we ever move to a model where a node is optional to a pxe. Another note just for reference: there is weirdness in e2e_prover, that fails the proof validation. Resolves #4781. Apply suggestions from code review Co-authored-by: Nicolás Venturo --- .../aztec-node/src/aztec-node/server.ts | 51 ++++++++++++------- .../tx_metadata_validator.test.ts | 29 ----------- .../tx_validator/tx_metadata_validator.ts | 40 --------------- yarn-project/sequencer-client/src/index.ts | 2 + 4 files changed, 35 insertions(+), 87 deletions(-) delete mode 100644 yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts delete mode 100644 yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index fd53a10894e..27d0cbc032f 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -2,6 +2,7 @@ import { createArchiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; import { type AztecNode, + type ClientProtocolCircuitVerifier, type FromLogType, type GetUnencryptedLogsResponse, type L1ToL2MessageSource, @@ -24,7 +25,6 @@ import { type TxHash, TxReceipt, TxStatus, - type TxValidator, partitionReverts, } from '@aztec/circuit-types'; import { @@ -57,8 +57,15 @@ import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice'; import { getCanonicalInstanceDeployer } from '@aztec/protocol-contracts/instance-deployer'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; import { getCanonicalMultiCallEntrypointAddress } from '@aztec/protocol-contracts/multi-call-entrypoint'; -import { AggregateTxValidator, DataTxValidator, GlobalVariableBuilder, SequencerClient } from '@aztec/sequencer-client'; -import { PublicProcessorFactory, WASMSimulator, createSimulationProvider } from '@aztec/simulator'; +import { + AggregateTxValidator, + DataTxValidator, + DoubleSpendTxValidator, + GlobalVariableBuilder, + MetadataTxValidator, + SequencerClient, +} from '@aztec/sequencer-client'; +import { PublicProcessorFactory, WASMSimulator, WorldStateDB, createSimulationProvider } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { @@ -72,7 +79,6 @@ import { MerkleTrees, type WorldStateSynchronizer, createWorldStateSynchronizer import { type AztecNodeConfig, getPackageInfo } from './config.js'; import { NodeMetrics } from './node_metrics.js'; -import { MetadataTxValidator } from './tx_validator/tx_metadata_validator.js'; import { TxProofValidator } from './tx_validator/tx_proof_validator.js'; /** @@ -97,7 +103,7 @@ export class AztecNodeService implements AztecNode { protected readonly version: number, protected readonly globalVariableBuilder: GlobalVariableBuilder, protected readonly merkleTreesDb: AztecKVStore, - private txValidator: TxValidator, + private proofVerifier: ClientProtocolCircuitVerifier, private telemetry: TelemetryClient, private log = createDebugLogger('aztec:node'), ) { @@ -158,11 +164,6 @@ export class AztecNodeService implements AztecNode { await Promise.all([p2pClient.start(), worldStateSynchronizer.start()]); const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); - const txValidator = new AggregateTxValidator( - new DataTxValidator(), - new MetadataTxValidator(config.l1ChainId), - new TxProofValidator(proofVerifier), - ); const simulationProvider = await createSimulationProvider(config, log); @@ -197,7 +198,7 @@ export class AztecNodeService implements AztecNode { config.version, new GlobalVariableBuilder(config), store, - txValidator, + proofVerifier, telemetry, log, ); @@ -762,7 +763,26 @@ export class AztecNodeService implements AztecNode { } public async isValidTx(tx: Tx): Promise { - const [_, invalidTxs] = await this.txValidator.validateTxs([tx]); + const blockNumber = (await this.blockSource.getBlockNumber()) + 1; + + const newGlobalVariables = await this.globalVariableBuilder.buildGlobalVariables( + new Fr(blockNumber), + // We only need chainId and block number, thus coinbase and fee recipient can be set to 0. + EthAddress.ZERO, + AztecAddress.ZERO, + ); + + // These validators are taken from the sequencer, and should match. + // The reason why `phases` and `gas` tx validator is in the sequencer and not here is because + // those tx validators are customizable by the sequencer. + const txValidator = new AggregateTxValidator( + new DataTxValidator(), + new MetadataTxValidator(newGlobalVariables), + new DoubleSpendTxValidator(new WorldStateDB(this.worldStateSynchronizer.getLatest())), + new TxProofValidator(this.proofVerifier), + ); + + const [_, invalidTxs] = await txValidator.validateTxs([tx]); if (invalidTxs.length > 0) { this.log.warn(`Rejecting tx ${tx.getTxHash()} because of validation errors`); @@ -777,12 +797,7 @@ export class AztecNodeService implements AztecNode { this.sequencer?.updateSequencerConfig(config); if (newConfig.realProofs !== this.config.realProofs) { - const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(newConfig) : new TestCircuitVerifier(); - - this.txValidator = new AggregateTxValidator( - new MetadataTxValidator(this.l1ChainId), - new TxProofValidator(proofVerifier), - ); + this.proofVerifier = config.realProofs ? await BBCircuitVerifier.new(newConfig) : new TestCircuitVerifier(); } this.config = newConfig; diff --git a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts b/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts deleted file mode 100644 index 58f40185eff..00000000000 --- a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { mockTx, mockTxForRollup } from '@aztec/circuit-types'; -import { Fr } from '@aztec/circuits.js'; - -import { MetadataTxValidator } from './tx_metadata_validator.js'; - -describe('MetadataTxValidator', () => { - let l1ChainId: Fr; - let validator: MetadataTxValidator; - - beforeEach(() => { - l1ChainId = new Fr(123); - validator = new MetadataTxValidator(l1ChainId); - }); - - it('allows only transactions for the right chain', async () => { - const goodTxs = [mockTx(1), mockTxForRollup(2)]; - const badTxs = [mockTx(3), mockTxForRollup(4)]; - - goodTxs.forEach(tx => { - tx.data.constants.txContext.chainId = l1ChainId; - }); - - badTxs.forEach(tx => { - tx.data.constants.txContext.chainId = l1ChainId.add(new Fr(1)); - }); - - await expect(validator.validateTxs([...goodTxs, ...badTxs])).resolves.toEqual([goodTxs, badTxs]); - }); -}); diff --git a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts b/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts deleted file mode 100644 index d6b5795722e..00000000000 --- a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Tx, type TxValidator } from '@aztec/circuit-types'; -import { Fr } from '@aztec/circuits.js'; -import { createDebugLogger } from '@aztec/foundation/log'; - -export class MetadataTxValidator implements TxValidator { - #log = createDebugLogger('aztec:sequencer:tx_validator:tx_metadata'); - #l1ChainId: Fr; - - constructor(l1ChainId: number | Fr) { - this.#l1ChainId = new Fr(l1ChainId); - } - - validateTxs(txs: Tx[]): Promise<[validTxs: Tx[], invalidTxs: Tx[]]> { - const validTxs: Tx[] = []; - const invalidTxs: Tx[] = []; - for (const tx of txs) { - if (!this.#hasCorrectChainId(tx)) { - invalidTxs.push(tx); - continue; - } - - validTxs.push(tx); - } - - return Promise.resolve([validTxs, invalidTxs]); - } - - #hasCorrectChainId(tx: Tx): boolean { - if (!tx.data.constants.txContext.chainId.equals(this.#l1ChainId)) { - this.#log.warn( - `Rejecting tx ${Tx.getHash( - tx, - )} because of incorrect chain ${tx.data.constants.txContext.chainId.toNumber()} != ${this.#l1ChainId.toNumber()}`, - ); - return false; - } else { - return true; - } - } -} diff --git a/yarn-project/sequencer-client/src/index.ts b/yarn-project/sequencer-client/src/index.ts index 8dd0cf23889..155263344d6 100644 --- a/yarn-project/sequencer-client/src/index.ts +++ b/yarn-project/sequencer-client/src/index.ts @@ -4,6 +4,8 @@ export * from './publisher/index.js'; export * from './sequencer/index.js'; export * from './tx_validator/aggregate_tx_validator.js'; export * from './tx_validator/data_validator.js'; +export * from './tx_validator/double_spend_validator.js'; +export * from './tx_validator/metadata_validator.js'; // Used by the node to simulate public parts of transactions. Should these be moved to a shared library? export * from './global_variable_builder/index.js';