Skip to content

Commit 7022ca5

Browse files
committed
chore: Add config to evict txs after reorg
1 parent 3bf6083 commit 7022ca5

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

yarn-project/foundation/src/config/env_var.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ export type EnvVar =
134134
| 'P2P_SEEN_MSG_CACHE_SIZE'
135135
| 'P2P_DROP_TX'
136136
| 'P2P_DROP_TX_CHANCE'
137+
| 'P2P_TX_POOL_DELETE_TXS_AFTER_REORG'
137138
| 'PEER_ID_PRIVATE_KEY'
138139
| 'PEER_ID_PRIVATE_KEY_PATH'
139140
| 'PROVER_AGENT_COUNT'

yarn-project/p2p/src/client/p2p_client.test.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { TxArray, TxHash, TxHashArray } from '@aztec/stdlib/tx';
1212
import { expect, jest } from '@jest/globals';
1313
import { type MockProxy, mock } from 'jest-mock-extended';
1414

15+
import type { P2PConfig } from '../config.js';
1516
import { InMemoryAttestationPool, type P2PService } from '../index.js';
1617
import type { AttestationPool } from '../mem_pools/attestation_pool/attestation_pool.js';
1718
import type { MemPools } from '../mem_pools/interface.js';
@@ -57,8 +58,8 @@ describe('P2P Client', () => {
5758
client = createClient();
5859
});
5960

60-
const createClient = () =>
61-
new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, txCollection);
61+
const createClient = (config: Partial<P2PConfig> = {}) =>
62+
new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, txCollection, config);
6263

6364
const advanceToProvenBlock = async (blockNumber: number) => {
6465
blockSource.setProvenBlockNumber(blockNumber);
@@ -277,6 +278,34 @@ describe('P2P Client', () => {
277278
});
278279

279280
describe('Chain prunes', () => {
281+
it('deletes transactions mined in pruned blocks when flag is enabled', async () => {
282+
client = createClient({ txPoolDeleteTxsAfterReorg: true });
283+
blockSource.setProvenBlockNumber(0);
284+
await client.start();
285+
286+
// Create two transactions:
287+
// 1. A transaction mined in block 95 (which will be pruned)
288+
// 2. A transaction mined in block 90 (which will remain)
289+
const txMinedInPrunedBlock = await mockTx();
290+
const txMinedInKeptBlock = await mockTx();
291+
292+
// Mock the mined transactions
293+
txPool.getMinedTxHashes.mockResolvedValue([
294+
[txMinedInPrunedBlock.getTxHash(), 95],
295+
[txMinedInKeptBlock.getTxHash(), 90],
296+
]);
297+
298+
txPool.getAllTxs.mockResolvedValue([txMinedInPrunedBlock, txMinedInKeptBlock]);
299+
300+
// Prune the chain back to block 90
301+
blockSource.removeBlocks(10);
302+
await client.sync();
303+
304+
// Verify only the transaction mined in the pruned block is deleted
305+
expect(txPool.deleteTxs).toHaveBeenCalledWith([txMinedInPrunedBlock.getTxHash()]);
306+
await client.stop();
307+
});
308+
280309
it('moves the tips on a chain reorg', async () => {
281310
blockSource.setProvenBlockNumber(0);
282311
await client.start();

yarn-project/p2p/src/client/p2p_client.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -799,29 +799,33 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
799799
}
800800
}
801801

802-
this.log.info(
803-
`Detected chain prune. Removing invalid txs count=${
804-
txsToDelete.size
805-
} newLatestBlock=${latestBlock} previousLatestBlock=${await this.getSyncedLatestBlockNum()}`,
806-
);
802+
this.log.info(`Detected chain prune. Removing ${txsToDelete.size} txs built against pruned blocks.`, {
803+
newLatestBlock: latestBlock,
804+
previousLatestBlock: await this.getSyncedLatestBlockNum(),
805+
});
807806

808807
// delete invalid txs (both pending and mined)
809808
await this.txPool.deleteTxs(Array.from(txsToDelete.values()));
810809

811810
// everything left in the mined set was built against a block on the proven chain so its still valid
812-
// move back to pending the txs that were reorged out of the chain
811+
// move back to pending the txs that were reorged out of the chain, unless txPoolDeleteTxsAfterReorg is set,
812+
// in which case we clean them up to avoid potential reorg loops
813813
// NOTE: we can't move _all_ txs back to pending because the tx pool could keep hold of mined txs for longer
814814
// (see this.keepProvenTxsFor)
815-
816-
const txsToMoveToPending: TxHash[] = [];
815+
const minedTxsFromReorg: TxHash[] = [];
817816
for (const [txHash, blockNumber] of minedTxs) {
818817
if (blockNumber > latestBlock) {
819-
txsToMoveToPending.push(txHash);
818+
minedTxsFromReorg.push(txHash);
820819
}
821820
}
822821

823-
this.log.info(`Moving ${txsToMoveToPending.length} mined txs back to pending`);
824-
await this.txPool.markMinedAsPending(txsToMoveToPending);
822+
if (this.config.txPoolDeleteTxsAfterReorg) {
823+
this.log.info(`Deleting ${minedTxsFromReorg.length} mined txs from reorg`);
824+
await this.txPool.deleteTxs(minedTxsFromReorg);
825+
} else {
826+
this.log.info(`Moving ${minedTxsFromReorg.length} mined txs from reorg back to pending`);
827+
await this.txPool.markMinedAsPending(minedTxsFromReorg);
828+
}
825829

826830
await this.synchedLatestBlockNumber.set(latestBlock);
827831
// no need to update block hashes, as they will be updated as new blocks are added

yarn-project/p2p/src/config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ export interface P2PConfig extends P2PReqRespConfig, ChainConfig, TxCollectionCo
161161

162162
/** The probability that a transaction is discarded. - For testing purposes only */
163163
dropTransactionsProbability: number;
164+
165+
/** Whether to delete transactions from the pool after a reorg instead of moving them back to pending. */
166+
txPoolDeleteTxsAfterReorg: boolean;
164167
}
165168

166169
export const DEFAULT_P2P_PORT = 40400;
@@ -412,6 +415,11 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
412415
'Whether transactions are disabled for this node. This means transactions will be rejected at the RPC and P2P layers.',
413416
...booleanConfigHelper(false),
414417
},
418+
txPoolDeleteTxsAfterReorg: {
419+
env: 'P2P_TX_POOL_DELETE_TXS_AFTER_REORG',
420+
description: 'Whether to delete transactions from the pool after a reorg instead of moving them back to pending.',
421+
...booleanConfigHelper(false),
422+
},
415423
...p2pReqRespConfigMappings,
416424
...chainConfigMappings,
417425
...txCollectionConfigMappings,

0 commit comments

Comments
 (0)