From c2497e04637cf2bad08901aaedd7d44a864182d1 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Tue, 16 Jan 2024 17:34:11 +0000 Subject: [PATCH] fix: do not publish empty contract data (#4022) This PR fixes the sequencer publishing contract for every transaction. Fix #2970 --- .../src/sequencer/sequencer.test.ts | 50 ++++++++++++++++++- .../src/sequencer/sequencer.ts | 25 ++++++---- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 799ec870bd9..1bc34c9dc69 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -1,4 +1,13 @@ -import { L1ToL2MessageSource, L2Block, L2BlockSource, MerkleTreeId, Tx, TxHash, mockTx } from '@aztec/circuit-types'; +import { + ExtendedContractData, + L1ToL2MessageSource, + L2Block, + L2BlockSource, + MerkleTreeId, + Tx, + TxHash, + mockTx, +} from '@aztec/circuit-types'; import { BlockHeader, Fr, @@ -209,6 +218,45 @@ describe('sequencer', () => { expect(publisher.processL2Block).not.toHaveBeenCalled(); }); + + it('publishes contract data', async () => { + const txWithContract = mockTx(0x10000); + (txWithContract.newContracts as Array) = [ExtendedContractData.random()]; + txWithContract.data.constants.txContext.chainId = chainId; + + const txWithEmptyContract = mockTx(0x20000); + (txWithEmptyContract.newContracts as Array) = [ExtendedContractData.empty()]; + txWithEmptyContract.data.constants.txContext.chainId = chainId; + + const block = L2Block.random(lastBlockNumber + 1); + const proof = makeEmptyProof(); + + p2p.getTxs.mockResolvedValueOnce([txWithContract, txWithEmptyContract]); + blockBuilder.buildL2Block.mockResolvedValueOnce([block, proof]); + publisher.processL2Block.mockResolvedValueOnce(true); + publisher.processNewContractData.mockResolvedValueOnce(true); + globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( + new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO), + ); + + await sequencer.initialSync(); + await sequencer.work(); + + // check that the block was built with both transactions + expect(blockBuilder.buildL2Block).toHaveBeenCalledWith( + expect.anything(), + expect.arrayContaining([ + expect.objectContaining({ hash: await txWithContract.getTxHash() }), + expect.objectContaining({ hash: await txWithEmptyContract.getTxHash() }), + ]), + expect.any(Array), + ); + + // check that the empty contract did not get published + expect(publisher.processNewContractData).toHaveBeenCalledWith(block.number, block.getCalldataHash(), [ + txWithContract.newContracts[0], + ]); + }); }); class TestSubject extends Sequencer { diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index bbb9a6af75c..f23c8c9a9df 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -235,20 +235,25 @@ export class Sequencer { protected async publishExtendedContractData(validTxs: ProcessedTx[], block: L2Block) { // Publishes contract data for txs to the network and awaits the tx to be mined this.state = SequencerState.PUBLISHING_CONTRACT_DATA; - const newContractData = validTxs - .map(tx => { - // Currently can only have 1 new contract per tx - return tx.newContracts[0]; - }) - .filter((cd): cd is Exclude => cd !== undefined); + const newContracts = validTxs.flatMap(tx => tx.newContracts).filter(cd => !cd.isEmpty()); - const blockHash = block.getCalldataHash(); - this.log(`Publishing extended contract data with block hash ${blockHash.toString('hex')}`); + if (newContracts.length === 0) { + this.log.debug(`No new contracts to publish in block ${block.number}`); + return; + } + + const blockCalldataHash = block.getCalldataHash(); + this.log.info(`Publishing ${newContracts.length} contracts in block ${block.number}`); + + const publishedContractData = await this.publisher.processNewContractData( + block.number, + blockCalldataHash, + newContracts, + ); - const publishedContractData = await this.publisher.processNewContractData(block.number, blockHash, newContractData); if (publishedContractData) { this.log(`Successfully published new contract data for block ${block.number}`); - } else if (!publishedContractData && newContractData.length) { + } else if (!publishedContractData && newContracts.length) { this.log(`Failed to publish new contract data for block ${block.number}`); } }