@aztec/p2p 0.0.1-commit.03f7ef2 → 0.0.1-commit.1142ef1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/client/factory.js +1 -1
- package/dest/client/interface.d.ts +18 -5
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +10 -13
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +450 -119
- package/dest/config.d.ts +4 -7
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +6 -9
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +61 -42
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +225 -262
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +21 -18
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +113 -108
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -16
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +89 -128
- package/dest/mem_pools/attestation_pool/mocks.d.ts +7 -6
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +9 -8
- package/dest/mem_pools/instrumentation.d.ts +3 -3
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +10 -17
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +28 -24
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +260 -325
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +18 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +56 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +83 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +5 -0
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +88 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +76 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
- package/dest/mem_pools/tx_pool/index.d.ts +1 -2
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/index.js +0 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +6 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +8 -4
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +7 -7
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -4
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +12 -10
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -5
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +7 -10
- package/dest/msg_validators/index.d.ts +2 -2
- package/dest/msg_validators/index.d.ts.map +1 -1
- package/dest/msg_validators/index.js +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
- package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/index.js +3 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/{block_proposal_validator/block_proposal_validator.js → proposal_validator/proposal_validator.js} +19 -21
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +183 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/services/dummy_service.d.ts +6 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +3 -0
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +4 -2
- package/dest/services/libp2p/instrumentation.d.ts +1 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +15 -68
- package/dest/services/libp2p/libp2p_service.d.ts +27 -10
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +696 -137
- package/dest/services/peer-manager/metrics.d.ts +6 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +18 -21
- package/dest/services/peer-manager/peer_manager.d.ts +2 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +2 -10
- package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +2 -5
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +5 -21
- package/dest/services/reqresp/protocols/status.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +2 -0
- package/dest/services/reqresp/reqresp.js +402 -24
- package/dest/services/service.d.ts +16 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +4 -14
- package/dest/services/tx_provider.d.ts +1 -1
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +3 -1
- package/dest/services/tx_provider_instrumentation.d.ts +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.js +6 -19
- package/dest/testbench/p2p_client_testbench_worker.js +26 -11
- package/dest/testbench/worker_client_manager.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +6 -1
- package/package.json +14 -14
- package/src/client/factory.ts +1 -1
- package/src/client/interface.ts +19 -4
- package/src/client/p2p_client.ts +79 -129
- package/src/config.ts +8 -14
- package/src/mem_pools/attestation_pool/attestation_pool.ts +68 -41
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +231 -287
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +162 -140
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -164
- package/src/mem_pools/attestation_pool/mocks.ts +13 -9
- package/src/mem_pools/instrumentation.ts +18 -25
- package/src/mem_pools/tx_pool/README.md +255 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +307 -370
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +71 -0
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +93 -0
- package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +108 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +91 -0
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
- package/src/mem_pools/tx_pool/index.ts +0 -1
- package/src/mem_pools/tx_pool/priority.ts +8 -1
- package/src/mem_pools/tx_pool/tx_pool.ts +8 -3
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +7 -7
- package/src/msg_validators/attestation_validator/attestation_validator.ts +16 -13
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +9 -12
- package/src/msg_validators/index.ts +1 -1
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
- package/src/msg_validators/proposal_validator/index.ts +3 -0
- package/src/msg_validators/{block_proposal_validator/block_proposal_validator.ts → proposal_validator/proposal_validator.ts} +23 -28
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +206 -0
- package/src/msg_validators/tx_validator/data_validator.ts +12 -4
- package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
- package/src/msg_validators/tx_validator/timestamp_validator.ts +3 -1
- package/src/services/dummy_service.ts +6 -0
- package/src/services/encoding.ts +3 -1
- package/src/services/libp2p/instrumentation.ts +14 -68
- package/src/services/libp2p/libp2p_service.ts +324 -100
- package/src/services/peer-manager/metrics.ts +22 -21
- package/src/services/peer-manager/peer_manager.ts +3 -2
- package/src/services/peer-manager/peer_scoring.ts +1 -5
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +3 -1
- package/src/services/reqresp/metrics.ts +7 -23
- package/src/services/reqresp/protocols/status.ts +2 -1
- package/src/services/service.ts +19 -4
- package/src/services/tx_collection/instrumentation.ts +4 -21
- package/src/services/tx_provider.ts +4 -1
- package/src/services/tx_provider_instrumentation.ts +11 -24
- package/src/testbench/p2p_client_testbench_worker.ts +35 -11
- package/src/testbench/worker_client_manager.ts +6 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -81
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -242
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.js +0 -1
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -288
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,39 +1,38 @@
|
|
|
1
|
+
import { insertIntoSortedArray } from '@aztec/foundation/array';
|
|
1
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
3
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
-
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
|
-
import { GasFees } from '@aztec/stdlib/gas';
|
|
6
5
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
7
|
-
import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
|
|
8
6
|
import { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
9
7
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
10
8
|
import assert from 'assert';
|
|
11
9
|
import EventEmitter from 'node:events';
|
|
12
10
|
import { ArchiveCache } from '../../msg_validators/tx_validator/archive_cache.js';
|
|
13
|
-
import { GasTxValidator } from '../../msg_validators/tx_validator/gas_validator.js';
|
|
14
11
|
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
12
|
+
import { EvictionManager } from './eviction/eviction_manager.js';
|
|
13
|
+
import { InsufficientFeePayerBalanceRule } from './eviction/insufficient_fee_payer_balance_rule.js';
|
|
14
|
+
import { InvalidTxsAfterMiningRule } from './eviction/invalid_txs_after_mining_rule.js';
|
|
15
|
+
import { InvalidTxsAfterReorgRule } from './eviction/invalid_txs_after_reorg_rule.js';
|
|
16
|
+
import { LowPriorityEvictionRule } from './eviction/low_priority_eviction_rule.js';
|
|
15
17
|
import { getPendingTxPriority } from './priority.js';
|
|
16
18
|
/**
|
|
17
19
|
* KV implementation of the Transaction Pool.
|
|
18
20
|
*/ export class AztecKVTxPool extends EventEmitter {
|
|
19
21
|
#store;
|
|
20
22
|
/** Our tx pool, stored as a Map, with K: tx hash and V: the transaction. */ #txs;
|
|
21
|
-
/**
|
|
22
|
-
/** The tx evicion logic will kick after pool size is greater than maxTxPoolSize * txPoolOverflowFactor */ txPoolOverflowFactor = 1;
|
|
23
|
+
/** Holds the historical block for each tx */ #pendingTxHashToHistoricalBlockHeaderHash;
|
|
23
24
|
/** Index from tx hash to the block number in which they were mined, filtered by mined txs. */ #minedTxHashToBlock;
|
|
24
25
|
/** Index from tx priority (stored as hex) to its tx hash, filtered by pending txs. */ #pendingTxPriorityToHash;
|
|
25
|
-
/** Index from tx hash to its tx size (in bytes), filtered by pending txs. */ #pendingTxHashToSize;
|
|
26
|
-
/** Index from tx hash to its header hash, filtered by pending txs. */ #pendingTxHashToHeaderHash;
|
|
27
26
|
/** Map from tx hash to the block number it was originally mined in (for soft-deleted txs). */ #deletedMinedTxHashes;
|
|
28
27
|
/** MultiMap from block number to deleted mined tx hashes for efficient cleanup. */ #blockToDeletedMinedTxHash;
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
#historicalHeaderToTxHash;
|
|
29
|
+
#feePayerToTxHash;
|
|
31
30
|
/** In-memory set of txs that should not be evicted from the pool. */ #nonEvictableTxs;
|
|
32
31
|
/** KV store for archived txs. */ #archive;
|
|
33
32
|
/** Archived txs map for future lookup. */ #archivedTxs;
|
|
34
33
|
/** Indexes of the archived txs by insertion order. */ #archivedTxIndices;
|
|
35
34
|
/** Number of txs to archive. */ #archivedTxLimit = 0;
|
|
36
|
-
|
|
35
|
+
#evictionManager;
|
|
37
36
|
#log;
|
|
38
37
|
#metrics;
|
|
39
38
|
/**
|
|
@@ -43,25 +42,31 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
43
42
|
* @param telemetry - A telemetry client.
|
|
44
43
|
* @param archivedTxLimit - The number of txs to archive.
|
|
45
44
|
* @param log - A logger.
|
|
46
|
-
*/ constructor(store, archive,
|
|
45
|
+
*/ constructor(store, archive, worldState, telemetry = getTelemetryClient(), config = {}, log = createLogger('p2p:tx_pool')){
|
|
47
46
|
super();
|
|
48
47
|
this.#log = log;
|
|
48
|
+
this.#evictionManager = new EvictionManager(this);
|
|
49
|
+
this.#evictionManager.registerRule(new InvalidTxsAfterMiningRule());
|
|
50
|
+
this.#evictionManager.registerRule(new InvalidTxsAfterReorgRule(worldState));
|
|
51
|
+
this.#evictionManager.registerRule(new InsufficientFeePayerBalanceRule(worldState));
|
|
52
|
+
this.#evictionManager.registerRule(new LowPriorityEvictionRule({
|
|
53
|
+
//NOTE: 0 effectively disables low priority eviction
|
|
54
|
+
maxPoolSize: config.maxPendingTxCount ?? 0
|
|
55
|
+
}));
|
|
49
56
|
this.updateConfig(config);
|
|
50
57
|
this.#txs = store.openMap('txs');
|
|
51
58
|
this.#minedTxHashToBlock = store.openMap('txHashToBlockMined');
|
|
52
59
|
this.#pendingTxPriorityToHash = store.openMultiMap('pendingTxFeeToHash');
|
|
53
|
-
this.#pendingTxHashToSize = store.openMap('pendingTxHashToSize');
|
|
54
|
-
this.#pendingTxHashToHeaderHash = store.openMap('pendingTxHashToHeaderHash');
|
|
55
|
-
this.#pendingTxSize = store.openSingleton('pendingTxSize');
|
|
56
60
|
this.#deletedMinedTxHashes = store.openMap('deletedMinedTxHashes');
|
|
57
61
|
this.#blockToDeletedMinedTxHash = store.openMultiMap('blockToDeletedMinedTxHash');
|
|
58
|
-
this.#
|
|
62
|
+
this.#pendingTxHashToHistoricalBlockHeaderHash = store.openMap('txHistoricalBlock');
|
|
63
|
+
this.#historicalHeaderToTxHash = store.openMultiMap('historicalHeaderToPendingTxHash');
|
|
64
|
+
this.#feePayerToTxHash = store.openMultiMap('feePayerToPendingTxHash');
|
|
59
65
|
this.#nonEvictableTxs = new Set();
|
|
60
66
|
this.#archivedTxs = archive.openMap('archivedTxs');
|
|
61
67
|
this.#archivedTxIndices = archive.openMap('archivedTxIndices');
|
|
62
68
|
this.#store = store;
|
|
63
69
|
this.#archive = archive;
|
|
64
|
-
this.#worldStateSynchronizer = worldStateSynchronizer;
|
|
65
70
|
this.#metrics = new PoolInstrumentation(telemetry, PoolName.TX_POOL, this.countTxs, ()=>store.estimateSize());
|
|
66
71
|
}
|
|
67
72
|
countTxs = async ()=>{
|
|
@@ -92,60 +97,61 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
92
97
|
if (txHashes.length === 0) {
|
|
93
98
|
return Promise.resolve();
|
|
94
99
|
}
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
await this
|
|
100
|
+
const uniqueMinedNullifiers = [];
|
|
101
|
+
const uniqueMinedFeePayers = [];
|
|
102
|
+
try {
|
|
103
|
+
await this.#store.transactionAsync(async ()=>{
|
|
104
|
+
for (const hash of txHashes){
|
|
105
|
+
const key = hash.toString();
|
|
106
|
+
await this.#minedTxHashToBlock.set(key, blockHeader.globalVariables.blockNumber);
|
|
107
|
+
const tx = await this.getPendingTxByHash(hash);
|
|
108
|
+
if (tx) {
|
|
109
|
+
const nullifiers = tx.data.getNonEmptyNullifiers();
|
|
110
|
+
nullifiers.forEach((nullifier)=>insertIntoSortedArray(uniqueMinedNullifiers, nullifier, Fr.cmp, false));
|
|
111
|
+
insertIntoSortedArray(uniqueMinedFeePayers, tx.data.feePayer, (a, b)=>a.toField().cmp(b.toField()), false);
|
|
112
|
+
await this.removePendingTxIndicesInDbTx(tx, key);
|
|
113
|
+
}
|
|
114
|
+
// If this tx was previously soft-deleted, remove it from the deleted sets
|
|
115
|
+
if (await this.#deletedMinedTxHashes.hasAsync(key)) {
|
|
116
|
+
const originalBlock = await this.#deletedMinedTxHashes.getAsync(key);
|
|
117
|
+
await this.#deletedMinedTxHashes.delete(key);
|
|
118
|
+
// Remove from block-to-hash mapping
|
|
119
|
+
if (originalBlock !== undefined) {
|
|
120
|
+
await this.#blockToDeletedMinedTxHash.deleteValue(originalBlock, key);
|
|
121
|
+
}
|
|
108
122
|
}
|
|
109
123
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
await this.#pendingTxSize.set(pendingTxSize);
|
|
121
|
-
await this.evictInvalidTxsAfterMining(txHashes, blockHeader, minedNullifiers, minedFeePayers);
|
|
122
|
-
});
|
|
123
|
-
this.#metrics.transactionsRemoved(txHashes);
|
|
124
|
-
// We update this after the transaction above. This ensures that the non-evictable transactions are not evicted
|
|
125
|
-
// until any that have been mined are marked as such.
|
|
126
|
-
// The non-evictable set is not considered when evicting transactions that are invalid after a block is mined.
|
|
127
|
-
this.#nonEvictableTxs.clear();
|
|
124
|
+
});
|
|
125
|
+
await this.#evictionManager.evictAfterNewBlock(blockHeader, uniqueMinedNullifiers, uniqueMinedFeePayers);
|
|
126
|
+
this.#metrics.transactionsRemoved(txHashes.map((hash)=>hash.toBigInt()));
|
|
127
|
+
} catch (err) {
|
|
128
|
+
this.#log.warn('Unexpected error when marking txs as mined', {
|
|
129
|
+
err
|
|
130
|
+
});
|
|
131
|
+
}
|
|
128
132
|
}
|
|
129
|
-
async markMinedAsPending(txHashes) {
|
|
133
|
+
async markMinedAsPending(txHashes, latestBlock) {
|
|
130
134
|
if (txHashes.length === 0) {
|
|
131
135
|
return Promise.resolve();
|
|
132
136
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
try {
|
|
138
|
+
await this.#store.transactionAsync(async ()=>{
|
|
139
|
+
for (const hash of txHashes){
|
|
140
|
+
const key = hash.toString();
|
|
141
|
+
await this.#minedTxHashToBlock.delete(key);
|
|
142
|
+
// Rehydrate the tx in the in-memory pending txs mapping
|
|
143
|
+
const tx = await this.getPendingTxByHash(hash);
|
|
144
|
+
if (tx) {
|
|
145
|
+
await this.addPendingTxIndicesInDbTx(tx, key);
|
|
146
|
+
}
|
|
143
147
|
}
|
|
144
|
-
}
|
|
145
|
-
await this.#
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
});
|
|
149
|
+
await this.#evictionManager.evictAfterChainPrune(latestBlock);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
this.#log.warn('Unexpected error when marking mined txs as pending', {
|
|
152
|
+
err
|
|
153
|
+
});
|
|
154
|
+
}
|
|
149
155
|
}
|
|
150
156
|
async getPendingTxHashes() {
|
|
151
157
|
const vals = await toArray(this.#pendingTxPriorityToHash.valuesAsync({
|
|
@@ -153,36 +159,6 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
153
159
|
}));
|
|
154
160
|
return vals.map(TxHash.fromString);
|
|
155
161
|
}
|
|
156
|
-
async getMinedTxHashes() {
|
|
157
|
-
const vals = await toArray(this.#minedTxHashToBlock.entriesAsync());
|
|
158
|
-
return vals.map(([txHash, blockNumber])=>[
|
|
159
|
-
TxHash.fromString(txHash),
|
|
160
|
-
blockNumber
|
|
161
|
-
]);
|
|
162
|
-
}
|
|
163
|
-
async getPendingTxCount() {
|
|
164
|
-
return await this.#pendingTxHashToHeaderHash.sizeAsync() ?? 0;
|
|
165
|
-
}
|
|
166
|
-
async getMinedTxCount() {
|
|
167
|
-
return await this.#minedTxHashToBlock.sizeAsync() ?? 0;
|
|
168
|
-
}
|
|
169
|
-
async getTxStatus(txHash) {
|
|
170
|
-
const key = txHash.toString();
|
|
171
|
-
const [isMined, isKnown, isDeleted] = await Promise.all([
|
|
172
|
-
this.#minedTxHashToBlock.hasAsync(key),
|
|
173
|
-
this.#txs.hasAsync(key),
|
|
174
|
-
this.#deletedMinedTxHashes.hasAsync(key)
|
|
175
|
-
]);
|
|
176
|
-
if (isDeleted) {
|
|
177
|
-
return 'deleted';
|
|
178
|
-
} else if (isMined) {
|
|
179
|
-
return 'mined';
|
|
180
|
-
} else if (isKnown) {
|
|
181
|
-
return 'pending';
|
|
182
|
-
} else {
|
|
183
|
-
return undefined;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
162
|
/**
|
|
187
163
|
* Checks if a transaction exists in the pool and returns it.
|
|
188
164
|
* @param txHash - The generated tx hash.
|
|
@@ -215,37 +191,44 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
215
191
|
/**
|
|
216
192
|
* Adds a list of transactions to the pool. Duplicates are ignored.
|
|
217
193
|
* @param txs - An array of txs to be added to the pool.
|
|
218
|
-
* @returns
|
|
194
|
+
* @returns count of added transactions
|
|
219
195
|
*/ async addTxs(txs, opts = {}) {
|
|
196
|
+
if (txs.length === 0) {
|
|
197
|
+
return Promise.resolve(0);
|
|
198
|
+
}
|
|
220
199
|
const addedTxs = [];
|
|
221
200
|
const hashesAndStats = txs.map((tx)=>({
|
|
222
201
|
txHash: tx.getTxHash(),
|
|
223
202
|
txStats: tx.getStats()
|
|
224
203
|
}));
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
await this.
|
|
248
|
-
})
|
|
204
|
+
try {
|
|
205
|
+
await this.#store.transactionAsync(async ()=>{
|
|
206
|
+
await Promise.all(txs.map(async (tx, i)=>{
|
|
207
|
+
const { txHash, txStats } = hashesAndStats[i];
|
|
208
|
+
const key = txHash.toString();
|
|
209
|
+
if (await this.#txs.hasAsync(key)) {
|
|
210
|
+
this.#log.debug(`Tx ${txHash.toString()} already exists in the pool`);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
this.#log.verbose(`Adding tx ${txHash.toString()} to pool`, {
|
|
214
|
+
eventName: 'tx-added-to-pool',
|
|
215
|
+
...txStats
|
|
216
|
+
});
|
|
217
|
+
await this.#txs.set(key, tx.toBuffer());
|
|
218
|
+
addedTxs.push(tx);
|
|
219
|
+
await this.#pendingTxHashToHistoricalBlockHeaderHash.set(key, (await tx.data.constants.anchorBlockHeader.hash()).toString());
|
|
220
|
+
if (!await this.#minedTxHashToBlock.hasAsync(key)) {
|
|
221
|
+
await this.addPendingTxIndicesInDbTx(tx, key);
|
|
222
|
+
this.#metrics.recordSize(tx);
|
|
223
|
+
}
|
|
224
|
+
}));
|
|
225
|
+
});
|
|
226
|
+
await this.#evictionManager.evictAfterNewTxs(addedTxs.map(({ txHash })=>txHash));
|
|
227
|
+
} catch (err) {
|
|
228
|
+
this.#log.warn('Unexpected error when adding txs', {
|
|
229
|
+
err
|
|
230
|
+
});
|
|
231
|
+
}
|
|
249
232
|
if (addedTxs.length > 0) {
|
|
250
233
|
this.#metrics.transactionsAdded(addedTxs);
|
|
251
234
|
this.emit('txs-added', {
|
|
@@ -260,52 +243,57 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
260
243
|
* Mined transactions are soft-deleted with a timestamp, pending transactions are permanently deleted.
|
|
261
244
|
* @param txHashes - An array of tx hashes to be deleted from the tx pool.
|
|
262
245
|
* @returns Empty promise.
|
|
263
|
-
*/ deleteTxs(txHashes, opts
|
|
246
|
+
*/ deleteTxs(txHashes, opts) {
|
|
264
247
|
if (txHashes.length === 0) {
|
|
265
248
|
return Promise.resolve();
|
|
266
249
|
}
|
|
267
250
|
const deletedTxs = [];
|
|
268
251
|
const poolDbTx = this.#store.transactionAsync(async ()=>{
|
|
269
|
-
let pendingTxSize = await this.#pendingTxSize.getAsync() ?? 0;
|
|
270
252
|
for (const hash of txHashes){
|
|
271
253
|
const key = hash.toString();
|
|
272
254
|
const tx = await this.getTxByHash(hash);
|
|
273
|
-
if (tx) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
await this.#blockToDeletedMinedTxHash.set(minedBlockNumber, key);
|
|
286
|
-
}
|
|
287
|
-
} else {
|
|
288
|
-
// Permanently delete pending transactions
|
|
289
|
-
this.#log.trace(`Deleting pending tx ${key} from pool`);
|
|
290
|
-
pendingTxSize -= tx.getSize();
|
|
291
|
-
await this.removePendingTxIndices(tx, key);
|
|
292
|
-
await this.#txs.delete(key);
|
|
293
|
-
}
|
|
294
|
-
if (!opts.eviction && this.#archivedTxLimit) {
|
|
255
|
+
if (!tx) {
|
|
256
|
+
this.#log.trace(`Skipping deletion of missing tx ${key} from pool`);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const minedBlockNumber = await this.#minedTxHashToBlock.getAsync(key);
|
|
260
|
+
const txIsPending = minedBlockNumber === undefined;
|
|
261
|
+
if (txIsPending) {
|
|
262
|
+
await this.deletePendingTx(tx, key);
|
|
263
|
+
} else {
|
|
264
|
+
await this.deleteMinedTx(key, minedBlockNumber, opts?.permanently ?? false);
|
|
265
|
+
const shouldArchiveTx = this.#archivedTxLimit && !opts?.permanently;
|
|
266
|
+
if (shouldArchiveTx) {
|
|
295
267
|
deletedTxs.push(tx);
|
|
296
268
|
}
|
|
297
|
-
} else {
|
|
298
|
-
this.#log.trace(`Skipping deletion of missing tx ${key} from pool`);
|
|
299
269
|
}
|
|
300
270
|
}
|
|
301
|
-
await this.#pendingTxSize.set(pendingTxSize);
|
|
302
271
|
});
|
|
303
|
-
this.#metrics.transactionsRemoved(txHashes);
|
|
272
|
+
this.#metrics.transactionsRemoved(txHashes.map((hash)=>hash.toBigInt()));
|
|
304
273
|
this.#log.debug(`Deleted ${txHashes.length} txs from pool`, {
|
|
305
274
|
txHashes
|
|
306
275
|
});
|
|
307
276
|
return this.#archivedTxLimit ? poolDbTx.then(()=>this.archiveTxs(deletedTxs)) : poolDbTx;
|
|
308
277
|
}
|
|
278
|
+
async deleteMinedTx(txHash, minedBlockNumber, permanently) {
|
|
279
|
+
await this.#minedTxHashToBlock.delete(txHash);
|
|
280
|
+
if (permanently) {
|
|
281
|
+
this.#log.trace(`Deleting mined tx ${txHash} from pool`);
|
|
282
|
+
await this.#txs.delete(txHash);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
// Soft-delete mined transactions: remove from mined set but keep in storage
|
|
286
|
+
this.#log.trace(`Soft-deleting mined tx ${txHash} from pool`);
|
|
287
|
+
await this.#deletedMinedTxHashes.set(txHash, minedBlockNumber);
|
|
288
|
+
await this.#blockToDeletedMinedTxHash.set(minedBlockNumber, txHash);
|
|
289
|
+
}
|
|
290
|
+
async deletePendingTx(tx, txHash) {
|
|
291
|
+
// We always permanently delete pending transactions
|
|
292
|
+
this.#log.trace(`Deleting pending tx ${txHash} from pool`);
|
|
293
|
+
await this.removePendingTxIndices(tx, txHash);
|
|
294
|
+
await this.#txs.delete(txHash);
|
|
295
|
+
await this.#pendingTxHashToHistoricalBlockHeaderHash.delete(txHash);
|
|
296
|
+
}
|
|
309
297
|
/**
|
|
310
298
|
* Gets all the transactions stored in the pool.
|
|
311
299
|
* @returns Array of tx objects in the order they were added to the pool.
|
|
@@ -320,45 +308,110 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
320
308
|
const vals = await toArray(this.#txs.keysAsync());
|
|
321
309
|
return vals.map((x)=>TxHash.fromString(x));
|
|
322
310
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
311
|
+
async getPendingTxInfos() {
|
|
312
|
+
const vals = await toArray(this.#pendingTxPriorityToHash.valuesAsync());
|
|
313
|
+
const results = await Promise.all(vals.map((val)=>this.getPendingTxInfo(TxHash.fromString(val))));
|
|
314
|
+
return results.filter((info)=>info !== undefined);
|
|
315
|
+
}
|
|
316
|
+
async getPendingTxInfo(txHash) {
|
|
317
|
+
let historicalBlockHash = await this.#pendingTxHashToHistoricalBlockHeaderHash.getAsync(txHash.toString());
|
|
318
|
+
// Not all tx might have this index created.
|
|
319
|
+
if (!historicalBlockHash) {
|
|
320
|
+
const tx = await this.getPendingTxByHash(txHash);
|
|
321
|
+
if (!tx) {
|
|
322
|
+
this.#log.warn(`PendingTxInfo:tx ${txHash} not found`);
|
|
323
|
+
return undefined;
|
|
333
324
|
}
|
|
325
|
+
historicalBlockHash = (await tx.data.constants.anchorBlockHeader.hash()).toString();
|
|
326
|
+
await this.#pendingTxHashToHistoricalBlockHeaderHash.set(txHash.toString(), historicalBlockHash);
|
|
334
327
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
this.#
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
328
|
+
return {
|
|
329
|
+
txHash,
|
|
330
|
+
blockHash: Fr.fromString(historicalBlockHash),
|
|
331
|
+
isEvictable: !this.#nonEvictableTxs.has(txHash.toString())
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
async getPendingTxsReferencingBlocks(blockHashes) {
|
|
335
|
+
const result = [];
|
|
336
|
+
for (const blockHash of blockHashes){
|
|
337
|
+
const chunk = await toArray(this.#historicalHeaderToTxHash.getValuesAsync(blockHash.toString()));
|
|
338
|
+
result.push(...chunk.map((txHash)=>({
|
|
339
|
+
txHash: TxHash.fromString(txHash),
|
|
340
|
+
blockHash,
|
|
341
|
+
isEvictable: !this.#nonEvictableTxs.has(txHash)
|
|
342
|
+
})));
|
|
343
|
+
}
|
|
344
|
+
return result;
|
|
345
|
+
}
|
|
346
|
+
async getPendingTxsWithFeePayer(feePayers) {
|
|
347
|
+
const result = [];
|
|
348
|
+
for (const feePayer of feePayers){
|
|
349
|
+
const chunk = await toArray(this.#feePayerToTxHash.getValuesAsync(feePayer.toString()));
|
|
350
|
+
const infos = await Promise.all(chunk.map((txHash)=>this.getPendingTxInfo(TxHash.fromString(txHash))));
|
|
351
|
+
result.push(...infos.filter((info)=>info !== undefined));
|
|
352
|
+
}
|
|
353
|
+
return result;
|
|
354
|
+
}
|
|
355
|
+
async getMinedTxHashes() {
|
|
356
|
+
const vals = await toArray(this.#minedTxHashToBlock.entriesAsync());
|
|
357
|
+
return vals.map(([txHash, blockNumber])=>[
|
|
358
|
+
TxHash.fromString(txHash),
|
|
359
|
+
blockNumber
|
|
360
|
+
]);
|
|
361
|
+
}
|
|
362
|
+
async getPendingTxCount() {
|
|
363
|
+
return await this.#pendingTxPriorityToHash.sizeAsync() ?? 0;
|
|
364
|
+
}
|
|
365
|
+
async getMinedTxCount() {
|
|
366
|
+
return await this.#minedTxHashToBlock.sizeAsync() ?? 0;
|
|
367
|
+
}
|
|
368
|
+
async getTxStatus(txHash) {
|
|
369
|
+
const key = txHash.toString();
|
|
370
|
+
const [isMined, isKnown, isDeleted] = await Promise.all([
|
|
371
|
+
this.#minedTxHashToBlock.hasAsync(key),
|
|
372
|
+
this.#txs.hasAsync(key),
|
|
373
|
+
this.#deletedMinedTxHashes.hasAsync(key)
|
|
374
|
+
]);
|
|
375
|
+
if (isDeleted) {
|
|
376
|
+
return 'deleted';
|
|
377
|
+
} else if (isMined) {
|
|
378
|
+
return 'mined';
|
|
379
|
+
} else if (isKnown) {
|
|
380
|
+
return 'pending';
|
|
381
|
+
} else {
|
|
382
|
+
return undefined;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
updateConfig(cfg) {
|
|
386
|
+
if (typeof cfg.archivedTxLimit === 'number') {
|
|
387
|
+
assert(cfg.archivedTxLimit >= 0, 'archivedTxLimit must be greater or equal to 0');
|
|
388
|
+
this.#archivedTxLimit = cfg.archivedTxLimit;
|
|
342
389
|
}
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
this.#archivedTxLimit = archivedTxLimit;
|
|
390
|
+
if (this.#evictionManager) {
|
|
391
|
+
this.#evictionManager.updateConfig(cfg);
|
|
346
392
|
}
|
|
347
|
-
// deletedMinedCleanupThresholdMs is no longer used in block-based cleanup
|
|
348
393
|
}
|
|
349
394
|
markTxsAsNonEvictable(txHashes) {
|
|
350
395
|
txHashes.forEach((txHash)=>this.#nonEvictableTxs.add(txHash.toString()));
|
|
351
396
|
return Promise.resolve();
|
|
352
397
|
}
|
|
398
|
+
clearNonEvictableTxs() {
|
|
399
|
+
// Clear the non-evictable set after completing the DB updates above.
|
|
400
|
+
// This ensures pinned (non-evictable) txs are protected while we mark mined txs,
|
|
401
|
+
// but they won't remain pinned indefinitely across blocks. Note that eviction rules
|
|
402
|
+
// (including post-mining invalidation) respect the non-evictable flag while it is set.
|
|
403
|
+
this.#nonEvictableTxs.clear();
|
|
404
|
+
return Promise.resolve();
|
|
405
|
+
}
|
|
353
406
|
/**
|
|
354
407
|
* Permanently deletes deleted mined transactions from blocks up to and including the specified block number.
|
|
355
408
|
* @param blockNumber - Block number threshold. Deleted mined txs from this block or earlier will be permanently deleted.
|
|
356
409
|
* @returns The number of transactions permanently deleted.
|
|
357
410
|
*/ async cleanupDeletedMinedTxs(blockNumber) {
|
|
358
411
|
let deletedCount = 0;
|
|
359
|
-
const txHashesToDelete = [];
|
|
360
|
-
const blocksToDelete = [];
|
|
361
412
|
await this.#store.transactionAsync(async ()=>{
|
|
413
|
+
const txHashesToDelete = [];
|
|
414
|
+
const blocksToDelete = [];
|
|
362
415
|
// Iterate through all entries and check block numbers
|
|
363
416
|
for await (const [block, txHash] of this.#blockToDeletedMinedTxHash.entriesAsync()){
|
|
364
417
|
if (block <= blockNumber) {
|
|
@@ -372,6 +425,7 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
372
425
|
deletedCount++;
|
|
373
426
|
}
|
|
374
427
|
}
|
|
428
|
+
this.#metrics.transactionsRemoved(txHashesToDelete);
|
|
375
429
|
// Clean up block-to-hash mapping - delete all values for each block
|
|
376
430
|
for (const block of blocksToDelete){
|
|
377
431
|
const txHashesForBlock = await toArray(this.#blockToDeletedMinedTxHash.getValuesAsync(block));
|
|
@@ -386,13 +440,6 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
386
440
|
return deletedCount;
|
|
387
441
|
}
|
|
388
442
|
/**
|
|
389
|
-
* Creates a GasTxValidator instance.
|
|
390
|
-
* @param db - DB for the validator to use
|
|
391
|
-
* @returns A GasTxValidator instance
|
|
392
|
-
*/ createGasTxValidator(db) {
|
|
393
|
-
return new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, GasFees.empty());
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
443
|
* Creates an ArchiveCache instance.
|
|
397
444
|
* @param db - DB for the cache to use
|
|
398
445
|
* @returns An ArchiveCache instance
|
|
@@ -405,31 +452,27 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
405
452
|
* @param txHash - The generated tx hash.
|
|
406
453
|
* @returns The transaction, if found, 'undefined' otherwise.
|
|
407
454
|
*/ async getPendingTxByHash(txHash) {
|
|
408
|
-
let key;
|
|
409
455
|
if (typeof txHash === 'string') {
|
|
410
|
-
key = txHash;
|
|
411
456
|
txHash = TxHash.fromString(txHash);
|
|
412
|
-
} else {
|
|
413
|
-
key = txHash.toString();
|
|
414
|
-
}
|
|
415
|
-
if (this.#pendingTxs.has(key)) {
|
|
416
|
-
return this.#pendingTxs.get(key);
|
|
417
457
|
}
|
|
418
458
|
const tx = await this.getTxByHash(txHash);
|
|
419
459
|
if (tx) {
|
|
420
|
-
this.#pendingTxs.set(key, tx);
|
|
421
460
|
return tx;
|
|
422
461
|
}
|
|
423
462
|
return undefined;
|
|
424
463
|
}
|
|
425
464
|
/**
|
|
426
465
|
* Archives a list of txs for future reference. The number of archived txs is limited by the specified archivedTxLimit.
|
|
466
|
+
* Note: Pending txs should not be archived, only finalized txs
|
|
427
467
|
* @param txs - The list of transactions to archive.
|
|
428
468
|
* @returns Empty promise.
|
|
429
469
|
*/ async archiveTxs(txs) {
|
|
430
470
|
if (txs.length === 0) {
|
|
431
471
|
return;
|
|
432
472
|
}
|
|
473
|
+
if (this.#archivedTxLimit === 0) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
433
476
|
try {
|
|
434
477
|
const txHashes = await Promise.all(txs.map((tx)=>tx.getTxHash()));
|
|
435
478
|
await this.#archive.transactionAsync(async ()=>{
|
|
@@ -468,153 +511,45 @@ import { getPendingTxPriority } from './priority.js';
|
|
|
468
511
|
});
|
|
469
512
|
}
|
|
470
513
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
* @returns The total number of txs evicted from the pool and the number of new txs that were evicted.
|
|
477
|
-
*/ async evictLowPriorityTxs(newTxHashes) {
|
|
478
|
-
if (this.#maxTxPoolSize === undefined || this.#maxTxPoolSize === 0) {
|
|
479
|
-
return {
|
|
480
|
-
numLowPriorityTxsEvicted: 0,
|
|
481
|
-
numNewTxsEvicted: 0
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
let numNewTxsEvicted = 0;
|
|
485
|
-
const txsToEvict = [];
|
|
486
|
-
let pendingTxsSize = await this.#pendingTxSize.getAsync() ?? 0;
|
|
487
|
-
if (pendingTxsSize > this.#maxTxPoolSize * this.txPoolOverflowFactor) {
|
|
488
|
-
for await (const txHash of this.#pendingTxPriorityToHash.valuesAsync()){
|
|
489
|
-
if (this.#nonEvictableTxs.has(txHash.toString())) {
|
|
490
|
-
continue;
|
|
491
|
-
}
|
|
492
|
-
const txSize = await this.#pendingTxHashToSize.getAsync(txHash.toString()) ?? (await this.getPendingTxByHash(txHash))?.getSize();
|
|
493
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to low priority to satisfy max tx size limit`, {
|
|
494
|
-
txHash,
|
|
495
|
-
txSize
|
|
496
|
-
});
|
|
497
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
498
|
-
if (txSize) {
|
|
499
|
-
pendingTxsSize -= txSize;
|
|
500
|
-
if (pendingTxsSize <= this.#maxTxPoolSize) {
|
|
501
|
-
break;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
numNewTxsEvicted += newTxHashes.filter((txHash)=>txsToEvict.includes(txHash)).length;
|
|
506
|
-
}
|
|
507
|
-
if (txsToEvict.length > 0) {
|
|
508
|
-
await this.deleteTxs(txsToEvict, {
|
|
509
|
-
eviction: true
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
return {
|
|
513
|
-
numLowPriorityTxsEvicted: txsToEvict.length,
|
|
514
|
-
numNewTxsEvicted
|
|
515
|
-
};
|
|
514
|
+
// Assumes being called within a DB transaction
|
|
515
|
+
async addPendingTxIndicesInDbTx(tx, txHash) {
|
|
516
|
+
await this.#pendingTxPriorityToHash.set(getPendingTxPriority(tx), txHash);
|
|
517
|
+
await this.#historicalHeaderToTxHash.set((await tx.data.constants.anchorBlockHeader.hash()).toString(), txHash);
|
|
518
|
+
await this.#feePayerToTxHash.set(tx.data.feePayer.toString(), txHash);
|
|
516
519
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
// Wait for world state to be synced to at least the mined block number
|
|
533
|
-
await this.#worldStateSynchronizer.syncImmediate(blockNumber);
|
|
534
|
-
const db = this.#worldStateSynchronizer.getCommitted();
|
|
535
|
-
const gasTxValidator = this.createGasTxValidator(db);
|
|
536
|
-
const txsToEvict = [];
|
|
537
|
-
for await (const txHash of this.#pendingTxPriorityToHash.valuesAsync()){
|
|
538
|
-
const tx = await this.getPendingTxByHash(txHash);
|
|
539
|
-
if (!tx) {
|
|
540
|
-
continue;
|
|
541
|
-
}
|
|
542
|
-
// Evict pending txs that share nullifiers with mined txs
|
|
543
|
-
const txNullifiers = tx.data.getNonEmptyNullifiers();
|
|
544
|
-
if (txNullifiers.some((nullifier)=>minedNullifiers.has(nullifier.toString()))) {
|
|
545
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to a duplicate nullifier with a mined tx`);
|
|
546
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
547
|
-
continue;
|
|
548
|
-
}
|
|
549
|
-
// Evict pending txs with an insufficient fee payer balance
|
|
550
|
-
if (minedFeePayers.has(tx.data.feePayer.toString()) && (await gasTxValidator.validateTxFee(tx)).result === 'invalid') {
|
|
551
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to an insufficient fee payer balance`);
|
|
552
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
// Evict pending txs with an expiration timestamp less than or equal to the mined block timestamp
|
|
556
|
-
const includeByTimestamp = tx.data.includeByTimestamp;
|
|
557
|
-
if (includeByTimestamp <= timestamp) {
|
|
558
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to the tx being expired (includeByTimestamp: ${includeByTimestamp}, mined block timestamp: ${timestamp})`);
|
|
559
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
560
|
-
continue;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
if (txsToEvict.length > 0) {
|
|
564
|
-
await this.deleteTxs(txsToEvict, {
|
|
565
|
-
eviction: true
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
return txsToEvict.length;
|
|
520
|
+
async addPendingTxIndices(tx, txHash) {
|
|
521
|
+
return await this.#store.transactionAsync(async ()=>{
|
|
522
|
+
await this.addPendingTxIndicesInDbTx(tx, txHash);
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
// Assumes being called within a DB transaction
|
|
526
|
+
async removePendingTxIndicesInDbTx(tx, txHash) {
|
|
527
|
+
await this.#pendingTxPriorityToHash.deleteValue(getPendingTxPriority(tx), txHash);
|
|
528
|
+
await this.#historicalHeaderToTxHash.deleteValue((await tx.data.constants.anchorBlockHeader.hash()).toString(), txHash);
|
|
529
|
+
await this.#feePayerToTxHash.deleteValue(tx.data.feePayer.toString(), txHash);
|
|
530
|
+
}
|
|
531
|
+
async removePendingTxIndices(tx, txHash) {
|
|
532
|
+
return await this.#store.transactionAsync(async ()=>{
|
|
533
|
+
await this.removePendingTxIndicesInDbTx(tx, txHash);
|
|
534
|
+
});
|
|
569
535
|
}
|
|
570
536
|
/**
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
|
|
574
|
-
* @returns The total number of txs evicted from the pool.
|
|
575
|
-
*/ async evictInvalidTxsAfterReorg(txHashes) {
|
|
576
|
-
if (txHashes.length === 0) {
|
|
577
|
-
return 0;
|
|
578
|
-
}
|
|
579
|
-
await this.#worldStateSynchronizer.syncImmediate();
|
|
580
|
-
const db = this.#worldStateSynchronizer.getCommitted();
|
|
581
|
-
const archiveCache = this.createArchiveCache(db);
|
|
582
|
-
const gasTxValidator = this.createGasTxValidator(db);
|
|
537
|
+
* Returns up to `limit` lowest-priority evictable pending tx hashes without hydrating transactions.
|
|
538
|
+
* Iterates the priority index in ascending order and skips non-evictable txs.
|
|
539
|
+
*/ async getLowestPriorityEvictable(limit) {
|
|
583
540
|
const txsToEvict = [];
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const [index] = await archiveCache.getArchiveIndices([
|
|
590
|
-
Fr.fromString(headerHash)
|
|
591
|
-
]);
|
|
592
|
-
if (index === undefined) {
|
|
593
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to an invalid archive root`);
|
|
594
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
541
|
+
if (limit <= 0) {
|
|
542
|
+
return txsToEvict;
|
|
543
|
+
}
|
|
544
|
+
for await (const txHashStr of this.#pendingTxPriorityToHash.valuesAsync()){
|
|
545
|
+
if (this.#nonEvictableTxs.has(txHashStr)) {
|
|
595
546
|
continue;
|
|
596
547
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
548
|
+
txsToEvict.push(TxHash.fromString(txHashStr));
|
|
549
|
+
if (txsToEvict.length >= limit) {
|
|
550
|
+
break;
|
|
600
551
|
}
|
|
601
552
|
}
|
|
602
|
-
|
|
603
|
-
await this.deleteTxs(txsToEvict, {
|
|
604
|
-
eviction: true
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
return txsToEvict.length;
|
|
608
|
-
}
|
|
609
|
-
async addPendingTxIndices(tx, txHash) {
|
|
610
|
-
await this.#pendingTxPriorityToHash.set(getPendingTxPriority(tx), txHash);
|
|
611
|
-
await this.#pendingTxHashToSize.set(txHash, tx.getSize());
|
|
612
|
-
await this.#pendingTxHashToHeaderHash.set(txHash, (await tx.data.constants.anchorBlockHeader.hash()).toString());
|
|
613
|
-
}
|
|
614
|
-
async removePendingTxIndices(tx, txHash) {
|
|
615
|
-
await this.#pendingTxPriorityToHash.deleteValue(getPendingTxPriority(tx), txHash);
|
|
616
|
-
await this.#pendingTxHashToSize.delete(txHash);
|
|
617
|
-
await this.#pendingTxHashToHeaderHash.delete(txHash);
|
|
618
|
-
this.#pendingTxs.delete(txHash);
|
|
553
|
+
return txsToEvict;
|
|
619
554
|
}
|
|
620
555
|
}
|