diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts index ec51c50d1a1..f4d5610890a 100644 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts @@ -201,6 +201,9 @@ export class AztecRPCServer implements AztecRPC { public async sendTx(tx: Tx): Promise { const txHash = await tx.getTxHash(); + if (await this.node.getTx(txHash)) { + throw new Error(`A settled tx with equal hash ${txHash.toString()} exists.`); + } this.log.info(`Sending transaction ${txHash}`); await this.node.sendTx(tx); return txHash; diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts index 0faa498d573..99adad75081 100644 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_server.test.ts @@ -1,8 +1,8 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { TestKeyStore } from '@aztec/key-store'; -import { AztecNode, AztecRPC } from '@aztec/types'; +import { AztecNode, AztecRPC, L2Tx, mockTx } from '@aztec/types'; -import { mock } from 'jest-mock-extended'; +import { MockProxy, mock } from 'jest-mock-extended'; import { MemoryDB } from '../../database/memory_db.js'; import { EthAddress, RpcServerConfig } from '../../index.js'; @@ -27,3 +27,29 @@ async function createAztecRpcServer(): Promise { } aztecRpcTestSuite('AztecRPCServer', createAztecRpcServer); + +describe('AztecRPCServer', () => { + let keyStore: TestKeyStore; + let node: MockProxy; + let db: MemoryDB; + let config: RpcServerConfig; + + beforeEach(async () => { + keyStore = new TestKeyStore(await Grumpkin.new()); + node = mock(); + db = new MemoryDB(); + config = { + l2BlockPollingIntervalMS: 100, + }; + }); + + it('throws when submitting a tx with a nullifier of already settled tx', async () => { + const settledTx = L2Tx.random(); + const duplicateTx = mockTx(); + + node.getTx.mockResolvedValue(settledTx); + + const rpc = new AztecRPCServer(keyStore, node, db, config); + await expect(rpc.sendTx(duplicateTx)).rejects.toThrowError(/A settled tx with equal hash/); + }); +}); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts index 81216417fdd..ef827094871 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts @@ -79,9 +79,8 @@ describe('e2e_deploy_contract', () => { /** * Milestone 1.2. * https://hackmd.io/-a5DjEfHTLaMBR49qy6QkA - * Task to repair this test: https://github.com/AztecProtocol/aztec-packages/issues/1810 */ - it.skip('should not deploy a contract with the same salt twice', async () => { + it('should not deploy a contract with the same salt twice', async () => { const contractAddressSalt = Fr.random(); const deployer = new ContractDeployer(TestContractAbi, aztecRpcServer); @@ -97,13 +96,9 @@ describe('e2e_deploy_contract', () => { } { - const tx = deployer.deploy().send({ contractAddressSalt }); - const isMined = await tx.isMined({ interval: 0.1 }); - expect(isMined).toBe(false); - const receipt = await tx.getReceipt(); - - expect(receipt.status).toBe(TxStatus.DROPPED); - expect(receipt.error).toBe('Tx dropped by P2P node.'); + await expect(deployer.deploy().send({ contractAddressSalt }).wait()).rejects.toThrowError( + /A settled tx with equal hash/, + ); } }, 30_000); });