@aztec/p2p 0.0.1-commit.9593d84 → 0.0.1-commit.96bb3f7
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.d.ts +2 -2
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +2 -3
- package/dest/client/interface.d.ts +18 -5
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +16 -19
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +460 -127
- package/dest/config.d.ts +4 -7
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +8 -11
- 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 +227 -264
- 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 +114 -109
- 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 +9 -8
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +10 -9
- package/dest/mem_pools/instrumentation.d.ts +7 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +30 -12
- package/dest/mem_pools/interface.d.ts +3 -4
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +30 -25
- 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 +262 -324
- 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 +11 -6
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +30 -24
- 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 +13 -11
- 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} +20 -22
- 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/archive_cache.d.ts +2 -2
- package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- 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/factory.d.ts +4 -3
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/test_utils.d.ts +2 -2
- package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
- 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 +5 -3
- 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 +30 -13
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +707 -153
- 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 +4 -12
- 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/interface.d.ts +2 -2
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +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/auth.d.ts +2 -2
- package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/auth.js +2 -2
- package/dest/services/reqresp/protocols/block.d.ts +1 -1
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.js +3 -2
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +2 -2
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +1 -1
- package/dest/services/reqresp/protocols/status.d.ts +5 -4
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +6 -3
- package/dest/services/reqresp/protocols/tx.d.ts +2 -3
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- 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/config.js +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -3
- package/dest/services/tx_collection/fast_tx_collection.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_collection/slow_tx_collection.d.ts +6 -5
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.d.ts +11 -10
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_provider.d.ts +6 -4
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +11 -2
- package/dest/services/tx_provider_instrumentation.d.ts +5 -2
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.js +13 -13
- package/dest/test-helpers/mock-tx-helpers.js +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -2
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- 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 +16 -16
- package/src/client/factory.ts +5 -10
- package/src/client/interface.ts +19 -4
- package/src/client/p2p_client.ts +104 -157
- package/src/config.ts +10 -16
- package/src/mem_pools/attestation_pool/attestation_pool.ts +68 -41
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +233 -289
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +163 -141
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -164
- package/src/mem_pools/attestation_pool/mocks.ts +15 -11
- package/src/mem_pools/instrumentation.ts +38 -14
- package/src/mem_pools/interface.ts +2 -4
- package/src/mem_pools/tx_pool/README.md +255 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +314 -373
- 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 +11 -5
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +23 -17
- package/src/msg_validators/attestation_validator/attestation_validator.ts +17 -14
- 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} +24 -29
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +206 -0
- package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/block_header_validator.ts +1 -1
- package/src/msg_validators/tx_validator/data_validator.ts +12 -4
- package/src/msg_validators/tx_validator/factory.ts +3 -2
- package/src/msg_validators/tx_validator/metadata_validator.ts +13 -5
- package/src/msg_validators/tx_validator/test_utils.ts +1 -1
- package/src/msg_validators/tx_validator/timestamp_validator.ts +5 -2
- package/src/services/dummy_service.ts +6 -0
- package/src/services/encoding.ts +4 -2
- package/src/services/libp2p/instrumentation.ts +14 -68
- package/src/services/libp2p/libp2p_service.ts +342 -123
- package/src/services/peer-manager/metrics.ts +22 -21
- package/src/services/peer-manager/peer_manager.ts +5 -4
- 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/interface.ts +1 -1
- package/src/services/reqresp/metrics.ts +7 -23
- package/src/services/reqresp/protocols/auth.ts +2 -2
- package/src/services/reqresp/protocols/block.ts +3 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +1 -1
- package/src/services/reqresp/protocols/status.ts +11 -9
- package/src/services/reqresp/protocols/tx.ts +1 -2
- package/src/services/service.ts +19 -4
- package/src/services/tx_collection/config.ts +1 -1
- package/src/services/tx_collection/fast_tx_collection.ts +3 -2
- package/src/services/tx_collection/instrumentation.ts +4 -21
- package/src/services/tx_collection/slow_tx_collection.ts +5 -5
- package/src/services/tx_collection/tx_collection.ts +10 -9
- package/src/services/tx_provider.ts +21 -5
- package/src/services/tx_provider_instrumentation.ts +18 -14
- package/src/test-helpers/mock-pubsub.ts +1 -1
- package/src/test-helpers/mock-tx-helpers.ts +1 -1
- package/src/test-helpers/reqresp-nodes.ts +1 -1
- package/src/testbench/p2p_client_testbench_worker.ts +36 -12
- package/src/testbench/worker_client_manager.ts +6 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -80
- 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 -238
- 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 -283
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { insertIntoSortedArray } from '@aztec/foundation/array';
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
4
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
5
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
6
|
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
5
|
-
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import type { MerkleTreeReadOperations, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
7
|
+
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
|
|
8
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
9
|
+
import type { MerkleTreeReadOperations, ReadonlyWorldStateAccess } from '@aztec/stdlib/interfaces/server';
|
|
9
10
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
10
11
|
import type { TxAddedToPoolStats } from '@aztec/stdlib/stats';
|
|
11
|
-
import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
|
|
12
12
|
import { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
|
|
13
13
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
14
14
|
|
|
@@ -16,49 +16,46 @@ import assert from 'assert';
|
|
|
16
16
|
import EventEmitter from 'node:events';
|
|
17
17
|
|
|
18
18
|
import { ArchiveCache } from '../../msg_validators/tx_validator/archive_cache.js';
|
|
19
|
-
import { GasTxValidator } from '../../msg_validators/tx_validator/gas_validator.js';
|
|
20
19
|
import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
|
|
20
|
+
import { EvictionManager } from './eviction/eviction_manager.js';
|
|
21
|
+
import type { PendingTxInfo, TxBlockReference, TxPoolOperations } from './eviction/eviction_strategy.js';
|
|
22
|
+
import { InsufficientFeePayerBalanceRule } from './eviction/insufficient_fee_payer_balance_rule.js';
|
|
23
|
+
import { InvalidTxsAfterMiningRule } from './eviction/invalid_txs_after_mining_rule.js';
|
|
24
|
+
import { InvalidTxsAfterReorgRule } from './eviction/invalid_txs_after_reorg_rule.js';
|
|
25
|
+
import { LowPriorityEvictionRule } from './eviction/low_priority_eviction_rule.js';
|
|
21
26
|
import { getPendingTxPriority } from './priority.js';
|
|
22
27
|
import type { TxPool, TxPoolEvents, TxPoolOptions } from './tx_pool.js';
|
|
23
28
|
|
|
24
29
|
/**
|
|
25
30
|
* KV implementation of the Transaction Pool.
|
|
26
31
|
*/
|
|
27
|
-
export class AztecKVTxPool
|
|
32
|
+
export class AztecKVTxPool
|
|
33
|
+
extends (EventEmitter as new () => TypedEventEmitter<TxPoolEvents>)
|
|
34
|
+
implements TxPool, TxPoolOperations
|
|
35
|
+
{
|
|
28
36
|
#store: AztecAsyncKVStore;
|
|
29
37
|
|
|
30
38
|
/** Our tx pool, stored as a Map, with K: tx hash and V: the transaction. */
|
|
31
39
|
#txs: AztecAsyncMap<string, Buffer>;
|
|
32
40
|
|
|
33
|
-
/**
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
/** The tx evicion logic will kick after pool size is greater than maxTxPoolSize * txPoolOverflowFactor */
|
|
37
|
-
txPoolOverflowFactor: number = 1;
|
|
41
|
+
/** Holds the historical block for each tx */
|
|
42
|
+
#pendingTxHashToHistoricalBlockHeaderHash: AztecAsyncMap<string, string>;
|
|
38
43
|
|
|
39
44
|
/** Index from tx hash to the block number in which they were mined, filtered by mined txs. */
|
|
40
|
-
#minedTxHashToBlock: AztecAsyncMap<string,
|
|
45
|
+
#minedTxHashToBlock: AztecAsyncMap<string, BlockNumber>;
|
|
41
46
|
|
|
42
47
|
/** Index from tx priority (stored as hex) to its tx hash, filtered by pending txs. */
|
|
43
48
|
#pendingTxPriorityToHash: AztecAsyncMultiMap<string, string>;
|
|
44
49
|
|
|
45
|
-
/** Index from tx hash to its tx size (in bytes), filtered by pending txs. */
|
|
46
|
-
#pendingTxHashToSize: AztecAsyncMap<string, number>;
|
|
47
|
-
|
|
48
|
-
/** Index from tx hash to its header hash, filtered by pending txs. */
|
|
49
|
-
#pendingTxHashToHeaderHash: AztecAsyncMap<string, string>;
|
|
50
|
-
|
|
51
50
|
/** Map from tx hash to the block number it was originally mined in (for soft-deleted txs). */
|
|
52
|
-
#deletedMinedTxHashes: AztecAsyncMap<string,
|
|
51
|
+
#deletedMinedTxHashes: AztecAsyncMap<string, BlockNumber>;
|
|
53
52
|
|
|
54
53
|
/** MultiMap from block number to deleted mined tx hashes for efficient cleanup. */
|
|
55
|
-
#blockToDeletedMinedTxHash: AztecAsyncMultiMap<
|
|
54
|
+
#blockToDeletedMinedTxHash: AztecAsyncMultiMap<BlockNumber, string>;
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
#pendingTxSize: AztecAsyncSingleton<number>;
|
|
56
|
+
#historicalHeaderToTxHash: AztecAsyncMultiMap<string, string>;
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
#pendingTxs: Map<string, Tx>;
|
|
58
|
+
#feePayerToTxHash: AztecAsyncMultiMap<string, string>;
|
|
62
59
|
|
|
63
60
|
/** In-memory set of txs that should not be evicted from the pool. */
|
|
64
61
|
#nonEvictableTxs: Set<string>;
|
|
@@ -75,8 +72,7 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
75
72
|
/** Number of txs to archive. */
|
|
76
73
|
#archivedTxLimit: number = 0;
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
75
|
+
#evictionManager: EvictionManager;
|
|
80
76
|
|
|
81
77
|
#log: Logger;
|
|
82
78
|
|
|
@@ -93,7 +89,7 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
93
89
|
constructor(
|
|
94
90
|
store: AztecAsyncKVStore,
|
|
95
91
|
archive: AztecAsyncKVStore,
|
|
96
|
-
|
|
92
|
+
worldState: ReadonlyWorldStateAccess,
|
|
97
93
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
98
94
|
config: TxPoolOptions = {},
|
|
99
95
|
log = createLogger('p2p:tx_pool'),
|
|
@@ -101,18 +97,30 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
101
97
|
super();
|
|
102
98
|
|
|
103
99
|
this.#log = log;
|
|
100
|
+
|
|
101
|
+
this.#evictionManager = new EvictionManager(this);
|
|
102
|
+
this.#evictionManager.registerRule(new InvalidTxsAfterMiningRule());
|
|
103
|
+
this.#evictionManager.registerRule(new InvalidTxsAfterReorgRule(worldState));
|
|
104
|
+
this.#evictionManager.registerRule(new InsufficientFeePayerBalanceRule(worldState));
|
|
105
|
+
this.#evictionManager.registerRule(
|
|
106
|
+
new LowPriorityEvictionRule({
|
|
107
|
+
//NOTE: 0 effectively disables low priority eviction
|
|
108
|
+
maxPoolSize: config.maxPendingTxCount ?? 0,
|
|
109
|
+
}),
|
|
110
|
+
);
|
|
111
|
+
|
|
104
112
|
this.updateConfig(config);
|
|
105
113
|
|
|
106
114
|
this.#txs = store.openMap('txs');
|
|
107
115
|
this.#minedTxHashToBlock = store.openMap('txHashToBlockMined');
|
|
108
116
|
this.#pendingTxPriorityToHash = store.openMultiMap('pendingTxFeeToHash');
|
|
109
|
-
this.#pendingTxHashToSize = store.openMap('pendingTxHashToSize');
|
|
110
|
-
this.#pendingTxHashToHeaderHash = store.openMap('pendingTxHashToHeaderHash');
|
|
111
|
-
this.#pendingTxSize = store.openSingleton('pendingTxSize');
|
|
112
117
|
this.#deletedMinedTxHashes = store.openMap('deletedMinedTxHashes');
|
|
113
118
|
this.#blockToDeletedMinedTxHash = store.openMultiMap('blockToDeletedMinedTxHash');
|
|
114
119
|
|
|
115
|
-
this.#
|
|
120
|
+
this.#pendingTxHashToHistoricalBlockHeaderHash = store.openMap('txHistoricalBlock');
|
|
121
|
+
this.#historicalHeaderToTxHash = store.openMultiMap('historicalHeaderToPendingTxHash');
|
|
122
|
+
this.#feePayerToTxHash = store.openMultiMap('feePayerToPendingTxHash');
|
|
123
|
+
|
|
116
124
|
this.#nonEvictableTxs = new Set<string>();
|
|
117
125
|
|
|
118
126
|
this.#archivedTxs = archive.openMap('archivedTxs');
|
|
@@ -120,7 +128,7 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
120
128
|
|
|
121
129
|
this.#store = store;
|
|
122
130
|
this.#archive = archive;
|
|
123
|
-
|
|
131
|
+
|
|
124
132
|
this.#metrics = new PoolInstrumentation(telemetry, PoolName.TX_POOL, this.countTxs, () => store.estimateSize());
|
|
125
133
|
}
|
|
126
134
|
|
|
@@ -141,6 +149,7 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
141
149
|
}
|
|
142
150
|
return true;
|
|
143
151
|
}
|
|
152
|
+
|
|
144
153
|
/**
|
|
145
154
|
* Marks transactions as mined in a block and updates the pool state accordingly.
|
|
146
155
|
* Removes the transactions from the pending set and adds them to the mined set.
|
|
@@ -153,68 +162,72 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
153
162
|
return Promise.resolve();
|
|
154
163
|
}
|
|
155
164
|
|
|
156
|
-
const
|
|
157
|
-
const
|
|
165
|
+
const uniqueMinedNullifiers: Fr[] = [];
|
|
166
|
+
const uniqueMinedFeePayers: AztecAddress[] = [];
|
|
158
167
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
try {
|
|
169
|
+
await this.#store.transactionAsync(async () => {
|
|
170
|
+
for (const hash of txHashes) {
|
|
171
|
+
const key = hash.toString();
|
|
172
|
+
await this.#minedTxHashToBlock.set(key, blockHeader.globalVariables.blockNumber);
|
|
173
|
+
|
|
174
|
+
const tx = await this.getPendingTxByHash(hash);
|
|
175
|
+
if (tx) {
|
|
176
|
+
const nullifiers = tx.data.getNonEmptyNullifiers();
|
|
177
|
+
|
|
178
|
+
nullifiers.forEach(nullifier => insertIntoSortedArray(uniqueMinedNullifiers, nullifier, Fr.cmp, false));
|
|
179
|
+
insertIntoSortedArray(
|
|
180
|
+
uniqueMinedFeePayers,
|
|
181
|
+
tx.data.feePayer,
|
|
182
|
+
(a, b) => a.toField().cmp(b.toField()),
|
|
183
|
+
false,
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
await this.removePendingTxIndicesInDbTx(tx, key);
|
|
187
|
+
}
|
|
163
188
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
// If this tx was previously soft-deleted, remove it from the deleted sets
|
|
190
|
+
if (await this.#deletedMinedTxHashes.hasAsync(key)) {
|
|
191
|
+
const originalBlock = await this.#deletedMinedTxHashes.getAsync(key);
|
|
192
|
+
await this.#deletedMinedTxHashes.delete(key);
|
|
193
|
+
// Remove from block-to-hash mapping
|
|
194
|
+
if (originalBlock !== undefined) {
|
|
195
|
+
await this.#blockToDeletedMinedTxHash.deleteValue(originalBlock, key);
|
|
196
|
+
}
|
|
171
197
|
}
|
|
172
198
|
}
|
|
199
|
+
});
|
|
173
200
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const tx = await this.getPendingTxByHash(hash);
|
|
177
|
-
if (tx) {
|
|
178
|
-
const nullifiers = tx.data.getNonEmptyNullifiers();
|
|
179
|
-
nullifiers.forEach(nullifier => minedNullifiers.add(nullifier.toString()));
|
|
180
|
-
minedFeePayers.add(tx.data.feePayer.toString());
|
|
181
|
-
pendingTxSize -= tx.getSize();
|
|
182
|
-
await this.removePendingTxIndices(tx, key);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
await this.#pendingTxSize.set(pendingTxSize);
|
|
201
|
+
await this.#evictionManager.evictAfterNewBlock(blockHeader, uniqueMinedNullifiers, uniqueMinedFeePayers);
|
|
186
202
|
|
|
187
|
-
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
// The non-evictable set is not considered when evicting transactions that are invalid after a block is mined.
|
|
192
|
-
this.#nonEvictableTxs.clear();
|
|
203
|
+
this.#metrics.transactionsRemoved(txHashes.map(hash => hash.toBigInt()));
|
|
204
|
+
} catch (err) {
|
|
205
|
+
this.#log.warn('Unexpected error when marking txs as mined', { err });
|
|
206
|
+
}
|
|
193
207
|
}
|
|
194
208
|
|
|
195
|
-
public async markMinedAsPending(txHashes: TxHash[]): Promise<void> {
|
|
209
|
+
public async markMinedAsPending(txHashes: TxHash[], latestBlock: BlockNumber): Promise<void> {
|
|
196
210
|
if (txHashes.length === 0) {
|
|
197
211
|
return Promise.resolve();
|
|
198
212
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
213
|
+
try {
|
|
214
|
+
await this.#store.transactionAsync(async () => {
|
|
215
|
+
for (const hash of txHashes) {
|
|
216
|
+
const key = hash.toString();
|
|
217
|
+
await this.#minedTxHashToBlock.delete(key);
|
|
218
|
+
|
|
219
|
+
// Rehydrate the tx in the in-memory pending txs mapping
|
|
220
|
+
const tx = await this.getPendingTxByHash(hash);
|
|
221
|
+
if (tx) {
|
|
222
|
+
await this.addPendingTxIndicesInDbTx(tx, key);
|
|
223
|
+
}
|
|
210
224
|
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
await this.#pendingTxSize.set(pendingTxSize);
|
|
214
|
-
});
|
|
225
|
+
});
|
|
215
226
|
|
|
216
|
-
|
|
217
|
-
|
|
227
|
+
await this.#evictionManager.evictAfterChainPrune(latestBlock);
|
|
228
|
+
} catch (err) {
|
|
229
|
+
this.#log.warn('Unexpected error when marking mined txs as pending', { err });
|
|
230
|
+
}
|
|
218
231
|
}
|
|
219
232
|
|
|
220
233
|
public async getPendingTxHashes(): Promise<TxHash[]> {
|
|
@@ -222,38 +235,6 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
222
235
|
return vals.map(TxHash.fromString);
|
|
223
236
|
}
|
|
224
237
|
|
|
225
|
-
public async getMinedTxHashes(): Promise<[TxHash, number][]> {
|
|
226
|
-
const vals = await toArray(this.#minedTxHashToBlock.entriesAsync());
|
|
227
|
-
return vals.map(([txHash, blockNumber]) => [TxHash.fromString(txHash), blockNumber]);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
public async getPendingTxCount(): Promise<number> {
|
|
231
|
-
return (await this.#pendingTxHashToHeaderHash.sizeAsync()) ?? 0;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
public async getMinedTxCount(): Promise<number> {
|
|
235
|
-
return (await this.#minedTxHashToBlock.sizeAsync()) ?? 0;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
public async getTxStatus(txHash: TxHash): Promise<'pending' | 'mined' | 'deleted' | undefined> {
|
|
239
|
-
const key = txHash.toString();
|
|
240
|
-
const [isMined, isKnown, isDeleted] = await Promise.all([
|
|
241
|
-
this.#minedTxHashToBlock.hasAsync(key),
|
|
242
|
-
this.#txs.hasAsync(key),
|
|
243
|
-
this.#deletedMinedTxHashes.hasAsync(key),
|
|
244
|
-
]);
|
|
245
|
-
|
|
246
|
-
if (isDeleted) {
|
|
247
|
-
return 'deleted';
|
|
248
|
-
} else if (isMined) {
|
|
249
|
-
return 'mined';
|
|
250
|
-
} else if (isKnown) {
|
|
251
|
-
return 'pending';
|
|
252
|
-
} else {
|
|
253
|
-
return undefined;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
238
|
/**
|
|
258
239
|
* Checks if a transaction exists in the pool and returns it.
|
|
259
240
|
* @param txHash - The generated tx hash.
|
|
@@ -291,43 +272,53 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
291
272
|
/**
|
|
292
273
|
* Adds a list of transactions to the pool. Duplicates are ignored.
|
|
293
274
|
* @param txs - An array of txs to be added to the pool.
|
|
294
|
-
* @returns
|
|
275
|
+
* @returns count of added transactions
|
|
295
276
|
*/
|
|
296
277
|
public async addTxs(txs: Tx[], opts: { source?: string } = {}): Promise<number> {
|
|
278
|
+
if (txs.length === 0) {
|
|
279
|
+
return Promise.resolve(0);
|
|
280
|
+
}
|
|
281
|
+
|
|
297
282
|
const addedTxs: Tx[] = [];
|
|
298
283
|
const hashesAndStats = txs.map(tx => ({ txHash: tx.getTxHash(), txStats: tx.getStats() }));
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
this.#log.verbose(`Adding tx ${txHash.toString()} to pool`, {
|
|
311
|
-
eventName: 'tx-added-to-pool',
|
|
312
|
-
...txStats,
|
|
313
|
-
} satisfies TxAddedToPoolStats);
|
|
314
|
-
|
|
315
|
-
await this.#txs.set(key, tx.toBuffer());
|
|
316
|
-
addedTxs.push(tx as Tx);
|
|
284
|
+
try {
|
|
285
|
+
await this.#store.transactionAsync(async () => {
|
|
286
|
+
await Promise.all(
|
|
287
|
+
txs.map(async (tx, i) => {
|
|
288
|
+
const { txHash, txStats } = hashesAndStats[i];
|
|
289
|
+
const key = txHash.toString();
|
|
290
|
+
if (await this.#txs.hasAsync(key)) {
|
|
291
|
+
this.#log.debug(`Tx ${txHash.toString()} already exists in the pool`);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
317
294
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
295
|
+
this.#log.verbose(`Adding tx ${txHash.toString()} to pool`, {
|
|
296
|
+
eventName: 'tx-added-to-pool',
|
|
297
|
+
...txStats,
|
|
298
|
+
} satisfies TxAddedToPoolStats);
|
|
299
|
+
|
|
300
|
+
await this.#txs.set(key, tx.toBuffer());
|
|
301
|
+
addedTxs.push(tx as Tx);
|
|
302
|
+
await this.#pendingTxHashToHistoricalBlockHeaderHash.set(
|
|
303
|
+
key,
|
|
304
|
+
(await tx.data.constants.anchorBlockHeader.hash()).toString(),
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
if (!(await this.#minedTxHashToBlock.hasAsync(key))) {
|
|
308
|
+
await this.addPendingTxIndicesInDbTx(tx, key);
|
|
309
|
+
this.#metrics.recordSize(tx);
|
|
310
|
+
}
|
|
311
|
+
}),
|
|
312
|
+
);
|
|
313
|
+
});
|
|
325
314
|
|
|
326
|
-
await this.#
|
|
327
|
-
|
|
328
|
-
|
|
315
|
+
await this.#evictionManager.evictAfterNewTxs(addedTxs.map(({ txHash }) => txHash));
|
|
316
|
+
} catch (err) {
|
|
317
|
+
this.#log.warn('Unexpected error when adding txs', { err });
|
|
318
|
+
}
|
|
329
319
|
|
|
330
320
|
if (addedTxs.length > 0) {
|
|
321
|
+
this.#metrics.transactionsAdded(addedTxs);
|
|
331
322
|
this.emit('txs-added', { ...opts, txs: addedTxs });
|
|
332
323
|
}
|
|
333
324
|
return addedTxs.length;
|
|
@@ -339,54 +330,62 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
339
330
|
* @param txHashes - An array of tx hashes to be deleted from the tx pool.
|
|
340
331
|
* @returns Empty promise.
|
|
341
332
|
*/
|
|
342
|
-
public deleteTxs(txHashes: TxHash[], opts
|
|
333
|
+
public deleteTxs(txHashes: TxHash[], opts?: { permanently?: boolean }): Promise<void> {
|
|
343
334
|
if (txHashes.length === 0) {
|
|
344
335
|
return Promise.resolve();
|
|
345
336
|
}
|
|
337
|
+
|
|
346
338
|
const deletedTxs: Tx[] = [];
|
|
347
339
|
const poolDbTx = this.#store.transactionAsync(async () => {
|
|
348
|
-
let pendingTxSize = (await this.#pendingTxSize.getAsync()) ?? 0;
|
|
349
340
|
for (const hash of txHashes) {
|
|
350
341
|
const key = hash.toString();
|
|
351
342
|
const tx = await this.getTxByHash(hash);
|
|
343
|
+
if (!tx) {
|
|
344
|
+
this.#log.trace(`Skipping deletion of missing tx ${key} from pool`);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
352
347
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
await this.#txs.delete(key);
|
|
362
|
-
} else {
|
|
363
|
-
// Soft-delete mined transactions: remove from mined set but keep in storage
|
|
364
|
-
this.#log.trace(`Soft-deleting mined tx ${key} from pool`);
|
|
365
|
-
await this.#deletedMinedTxHashes.set(key, minedBlockNumber);
|
|
366
|
-
await this.#blockToDeletedMinedTxHash.set(minedBlockNumber, key);
|
|
367
|
-
}
|
|
368
|
-
} else {
|
|
369
|
-
// Permanently delete pending transactions
|
|
370
|
-
this.#log.trace(`Deleting pending tx ${key} from pool`);
|
|
371
|
-
pendingTxSize -= tx.getSize();
|
|
372
|
-
await this.removePendingTxIndices(tx, key);
|
|
373
|
-
await this.#txs.delete(key);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (!opts.eviction && this.#archivedTxLimit) {
|
|
348
|
+
const minedBlockNumber = await this.#minedTxHashToBlock.getAsync(key);
|
|
349
|
+
const txIsPending = minedBlockNumber === undefined;
|
|
350
|
+
if (txIsPending) {
|
|
351
|
+
await this.deletePendingTx(tx, key);
|
|
352
|
+
} else {
|
|
353
|
+
await this.deleteMinedTx(key, minedBlockNumber!, opts?.permanently ?? false);
|
|
354
|
+
const shouldArchiveTx = this.#archivedTxLimit && !opts?.permanently;
|
|
355
|
+
if (shouldArchiveTx) {
|
|
377
356
|
deletedTxs.push(tx);
|
|
378
357
|
}
|
|
379
|
-
} else {
|
|
380
|
-
this.#log.trace(`Skipping deletion of missing tx ${key} from pool`);
|
|
381
358
|
}
|
|
382
359
|
}
|
|
383
|
-
|
|
384
|
-
await this.#pendingTxSize.set(pendingTxSize);
|
|
385
360
|
});
|
|
361
|
+
this.#metrics.transactionsRemoved(txHashes.map(hash => hash.toBigInt()));
|
|
386
362
|
this.#log.debug(`Deleted ${txHashes.length} txs from pool`, { txHashes });
|
|
363
|
+
|
|
387
364
|
return this.#archivedTxLimit ? poolDbTx.then(() => this.archiveTxs(deletedTxs)) : poolDbTx;
|
|
388
365
|
}
|
|
389
366
|
|
|
367
|
+
private async deleteMinedTx(txHash: `0x${string}`, minedBlockNumber: BlockNumber, permanently: boolean) {
|
|
368
|
+
await this.#minedTxHashToBlock.delete(txHash);
|
|
369
|
+
if (permanently) {
|
|
370
|
+
this.#log.trace(`Deleting mined tx ${txHash} from pool`);
|
|
371
|
+
await this.#txs.delete(txHash);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Soft-delete mined transactions: remove from mined set but keep in storage
|
|
376
|
+
this.#log.trace(`Soft-deleting mined tx ${txHash} from pool`);
|
|
377
|
+
await this.#deletedMinedTxHashes.set(txHash, minedBlockNumber);
|
|
378
|
+
await this.#blockToDeletedMinedTxHash.set(minedBlockNumber, txHash);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
private async deletePendingTx(tx: Tx, txHash: `0x${string}`) {
|
|
382
|
+
// We always permanently delete pending transactions
|
|
383
|
+
this.#log.trace(`Deleting pending tx ${txHash} from pool`);
|
|
384
|
+
await this.removePendingTxIndices(tx, txHash);
|
|
385
|
+
await this.#txs.delete(txHash);
|
|
386
|
+
await this.#pendingTxHashToHistoricalBlockHeaderHash.delete(txHash);
|
|
387
|
+
}
|
|
388
|
+
|
|
390
389
|
/**
|
|
391
390
|
* Gets all the transactions stored in the pool.
|
|
392
391
|
* @returns Array of tx objects in the order they were added to the pool.
|
|
@@ -405,30 +404,101 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
405
404
|
return vals.map(x => TxHash.fromString(x));
|
|
406
405
|
}
|
|
407
406
|
|
|
408
|
-
public
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
407
|
+
public async getPendingTxInfos(): Promise<PendingTxInfo[]> {
|
|
408
|
+
const vals = await toArray(this.#pendingTxPriorityToHash.valuesAsync());
|
|
409
|
+
const results = await Promise.all(vals.map(val => this.getPendingTxInfo(TxHash.fromString(val))));
|
|
410
|
+
return results.filter((info): info is PendingTxInfo => info !== undefined);
|
|
411
|
+
}
|
|
412
412
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
413
|
+
private async getPendingTxInfo(txHash: TxHash): Promise<PendingTxInfo | undefined> {
|
|
414
|
+
let historicalBlockHash = await this.#pendingTxHashToHistoricalBlockHeaderHash.getAsync(txHash.toString());
|
|
415
|
+
// Not all tx might have this index created.
|
|
416
|
+
if (!historicalBlockHash) {
|
|
417
|
+
const tx = await this.getPendingTxByHash(txHash);
|
|
418
|
+
if (!tx) {
|
|
419
|
+
this.#log.warn(`PendingTxInfo:tx ${txHash} not found`);
|
|
420
|
+
return undefined;
|
|
417
421
|
}
|
|
422
|
+
|
|
423
|
+
historicalBlockHash = (await tx.data.constants.anchorBlockHeader.hash()).toString();
|
|
424
|
+
await this.#pendingTxHashToHistoricalBlockHeaderHash.set(txHash.toString(), historicalBlockHash);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return {
|
|
428
|
+
txHash,
|
|
429
|
+
blockHash: Fr.fromString(historicalBlockHash),
|
|
430
|
+
isEvictable: !this.#nonEvictableTxs.has(txHash.toString()),
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
public async getPendingTxsReferencingBlocks(blockHashes: Fr[]): Promise<TxBlockReference[]> {
|
|
435
|
+
const result: TxBlockReference[] = [];
|
|
436
|
+
for (const blockHash of blockHashes) {
|
|
437
|
+
const chunk = await toArray(this.#historicalHeaderToTxHash.getValuesAsync(blockHash.toString()));
|
|
438
|
+
result.push(
|
|
439
|
+
...chunk.map(txHash => ({
|
|
440
|
+
txHash: TxHash.fromString(txHash),
|
|
441
|
+
blockHash,
|
|
442
|
+
isEvictable: !this.#nonEvictableTxs.has(txHash),
|
|
443
|
+
})),
|
|
444
|
+
);
|
|
418
445
|
}
|
|
419
446
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
447
|
+
return result;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
public async getPendingTxsWithFeePayer(feePayers: AztecAddress[]): Promise<PendingTxInfo[]> {
|
|
451
|
+
const result: PendingTxInfo[] = [];
|
|
452
|
+
for (const feePayer of feePayers) {
|
|
453
|
+
const chunk = await toArray(this.#feePayerToTxHash.getValuesAsync(feePayer.toString()));
|
|
454
|
+
const infos = await Promise.all(chunk.map(txHash => this.getPendingTxInfo(TxHash.fromString(txHash))));
|
|
455
|
+
result.push(...infos.filter((info): info is PendingTxInfo => info !== undefined));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return result;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
public async getMinedTxHashes(): Promise<[TxHash, BlockNumber][]> {
|
|
462
|
+
const vals = await toArray(this.#minedTxHashToBlock.entriesAsync());
|
|
463
|
+
return vals.map(([txHash, blockNumber]) => [TxHash.fromString(txHash), blockNumber]);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
public async getPendingTxCount(): Promise<number> {
|
|
467
|
+
return (await this.#pendingTxPriorityToHash.sizeAsync()) ?? 0;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
public async getMinedTxCount(): Promise<number> {
|
|
471
|
+
return (await this.#minedTxHashToBlock.sizeAsync()) ?? 0;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
public async getTxStatus(txHash: TxHash): Promise<'pending' | 'mined' | 'deleted' | undefined> {
|
|
475
|
+
const key = txHash.toString();
|
|
476
|
+
const [isMined, isKnown, isDeleted] = await Promise.all([
|
|
477
|
+
this.#minedTxHashToBlock.hasAsync(key),
|
|
478
|
+
this.#txs.hasAsync(key),
|
|
479
|
+
this.#deletedMinedTxHashes.hasAsync(key),
|
|
480
|
+
]);
|
|
481
|
+
|
|
482
|
+
if (isDeleted) {
|
|
483
|
+
return 'deleted';
|
|
484
|
+
} else if (isMined) {
|
|
485
|
+
return 'mined';
|
|
486
|
+
} else if (isKnown) {
|
|
487
|
+
return 'pending';
|
|
488
|
+
} else {
|
|
489
|
+
return undefined;
|
|
424
490
|
}
|
|
491
|
+
}
|
|
425
492
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
493
|
+
public updateConfig(cfg: TxPoolOptions): void {
|
|
494
|
+
if (typeof cfg.archivedTxLimit === 'number') {
|
|
495
|
+
assert(cfg.archivedTxLimit >= 0, 'archivedTxLimit must be greater or equal to 0');
|
|
496
|
+
this.#archivedTxLimit = cfg.archivedTxLimit;
|
|
429
497
|
}
|
|
430
498
|
|
|
431
|
-
|
|
499
|
+
if (this.#evictionManager) {
|
|
500
|
+
this.#evictionManager.updateConfig(cfg);
|
|
501
|
+
}
|
|
432
502
|
}
|
|
433
503
|
|
|
434
504
|
public markTxsAsNonEvictable(txHashes: TxHash[]): Promise<void> {
|
|
@@ -436,17 +506,26 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
436
506
|
return Promise.resolve();
|
|
437
507
|
}
|
|
438
508
|
|
|
509
|
+
public clearNonEvictableTxs(): Promise<void> {
|
|
510
|
+
// Clear the non-evictable set after completing the DB updates above.
|
|
511
|
+
// This ensures pinned (non-evictable) txs are protected while we mark mined txs,
|
|
512
|
+
// but they won't remain pinned indefinitely across blocks. Note that eviction rules
|
|
513
|
+
// (including post-mining invalidation) respect the non-evictable flag while it is set.
|
|
514
|
+
this.#nonEvictableTxs.clear();
|
|
515
|
+
return Promise.resolve();
|
|
516
|
+
}
|
|
517
|
+
|
|
439
518
|
/**
|
|
440
519
|
* Permanently deletes deleted mined transactions from blocks up to and including the specified block number.
|
|
441
520
|
* @param blockNumber - Block number threshold. Deleted mined txs from this block or earlier will be permanently deleted.
|
|
442
521
|
* @returns The number of transactions permanently deleted.
|
|
443
522
|
*/
|
|
444
|
-
public async cleanupDeletedMinedTxs(blockNumber:
|
|
523
|
+
public async cleanupDeletedMinedTxs(blockNumber: BlockNumber): Promise<number> {
|
|
445
524
|
let deletedCount = 0;
|
|
446
|
-
const txHashesToDelete: string[] = [];
|
|
447
|
-
const blocksToDelete: number[] = [];
|
|
448
|
-
|
|
449
525
|
await this.#store.transactionAsync(async () => {
|
|
526
|
+
const txHashesToDelete: string[] = [];
|
|
527
|
+
const blocksToDelete: BlockNumber[] = [];
|
|
528
|
+
|
|
450
529
|
// Iterate through all entries and check block numbers
|
|
451
530
|
for await (const [block, txHash] of this.#blockToDeletedMinedTxHash.entriesAsync()) {
|
|
452
531
|
if (block <= blockNumber) {
|
|
@@ -460,6 +539,7 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
460
539
|
deletedCount++;
|
|
461
540
|
}
|
|
462
541
|
}
|
|
542
|
+
this.#metrics.transactionsRemoved(txHashesToDelete);
|
|
463
543
|
|
|
464
544
|
// Clean up block-to-hash mapping - delete all values for each block
|
|
465
545
|
for (const block of blocksToDelete) {
|
|
@@ -476,15 +556,6 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
476
556
|
return deletedCount;
|
|
477
557
|
}
|
|
478
558
|
|
|
479
|
-
/**
|
|
480
|
-
* Creates a GasTxValidator instance.
|
|
481
|
-
* @param db - DB for the validator to use
|
|
482
|
-
* @returns A GasTxValidator instance
|
|
483
|
-
*/
|
|
484
|
-
protected createGasTxValidator(db: MerkleTreeReadOperations): GasTxValidator {
|
|
485
|
-
return new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, GasFees.empty());
|
|
486
|
-
}
|
|
487
|
-
|
|
488
559
|
/**
|
|
489
560
|
* Creates an ArchiveCache instance.
|
|
490
561
|
* @param db - DB for the cache to use
|
|
@@ -501,20 +572,12 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
501
572
|
* @returns The transaction, if found, 'undefined' otherwise.
|
|
502
573
|
*/
|
|
503
574
|
private async getPendingTxByHash(txHash: TxHash | string): Promise<Tx | undefined> {
|
|
504
|
-
let key;
|
|
505
575
|
if (typeof txHash === 'string') {
|
|
506
|
-
key = txHash;
|
|
507
576
|
txHash = TxHash.fromString(txHash);
|
|
508
|
-
} else {
|
|
509
|
-
key = txHash.toString();
|
|
510
577
|
}
|
|
511
578
|
|
|
512
|
-
if (this.#pendingTxs.has(key)) {
|
|
513
|
-
return this.#pendingTxs.get(key);
|
|
514
|
-
}
|
|
515
579
|
const tx = await this.getTxByHash(txHash);
|
|
516
580
|
if (tx) {
|
|
517
|
-
this.#pendingTxs.set(key, tx);
|
|
518
581
|
return tx;
|
|
519
582
|
}
|
|
520
583
|
return undefined;
|
|
@@ -522,6 +585,7 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
522
585
|
|
|
523
586
|
/**
|
|
524
587
|
* Archives a list of txs for future reference. The number of archived txs is limited by the specified archivedTxLimit.
|
|
588
|
+
* Note: Pending txs should not be archived, only finalized txs
|
|
525
589
|
* @param txs - The list of transactions to archive.
|
|
526
590
|
* @returns Empty promise.
|
|
527
591
|
*/
|
|
@@ -529,6 +593,10 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
529
593
|
if (txs.length === 0) {
|
|
530
594
|
return;
|
|
531
595
|
}
|
|
596
|
+
if (this.#archivedTxLimit === 0) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
532
600
|
try {
|
|
533
601
|
const txHashes = await Promise.all(txs.map(tx => tx.getTxHash()));
|
|
534
602
|
await this.#archive.transactionAsync(async () => {
|
|
@@ -568,183 +636,56 @@ export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<
|
|
|
568
636
|
}
|
|
569
637
|
}
|
|
570
638
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
* @returns The total number of txs evicted from the pool and the number of new txs that were evicted.
|
|
577
|
-
*/
|
|
578
|
-
private async evictLowPriorityTxs(
|
|
579
|
-
newTxHashes: TxHash[],
|
|
580
|
-
): Promise<{ numLowPriorityTxsEvicted: number; numNewTxsEvicted: number }> {
|
|
581
|
-
if (this.#maxTxPoolSize === undefined || this.#maxTxPoolSize === 0) {
|
|
582
|
-
return { numLowPriorityTxsEvicted: 0, numNewTxsEvicted: 0 };
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
let numNewTxsEvicted = 0;
|
|
586
|
-
const txsToEvict: TxHash[] = [];
|
|
587
|
-
|
|
588
|
-
let pendingTxsSize = (await this.#pendingTxSize.getAsync()) ?? 0;
|
|
589
|
-
if (pendingTxsSize > this.#maxTxPoolSize * this.txPoolOverflowFactor) {
|
|
590
|
-
for await (const txHash of this.#pendingTxPriorityToHash.valuesAsync()) {
|
|
591
|
-
if (this.#nonEvictableTxs.has(txHash.toString())) {
|
|
592
|
-
continue;
|
|
593
|
-
}
|
|
594
|
-
const txSize =
|
|
595
|
-
(await this.#pendingTxHashToSize.getAsync(txHash.toString())) ??
|
|
596
|
-
(await this.getPendingTxByHash(txHash))?.getSize();
|
|
597
|
-
|
|
598
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to low priority to satisfy max tx size limit`, {
|
|
599
|
-
txHash,
|
|
600
|
-
txSize,
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
604
|
-
|
|
605
|
-
if (txSize) {
|
|
606
|
-
pendingTxsSize -= txSize;
|
|
607
|
-
if (pendingTxsSize <= this.#maxTxPoolSize) {
|
|
608
|
-
break;
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
numNewTxsEvicted += newTxHashes.filter(txHash => txsToEvict.includes(txHash)).length;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
if (txsToEvict.length > 0) {
|
|
616
|
-
await this.deleteTxs(txsToEvict, { eviction: true });
|
|
617
|
-
}
|
|
618
|
-
return {
|
|
619
|
-
numLowPriorityTxsEvicted: txsToEvict.length,
|
|
620
|
-
numNewTxsEvicted,
|
|
621
|
-
};
|
|
639
|
+
// Assumes being called within a DB transaction
|
|
640
|
+
private async addPendingTxIndicesInDbTx(tx: Tx, txHash: string): Promise<void> {
|
|
641
|
+
await this.#pendingTxPriorityToHash.set(getPendingTxPriority(tx), txHash);
|
|
642
|
+
await this.#historicalHeaderToTxHash.set((await tx.data.constants.anchorBlockHeader.hash()).toString(), txHash);
|
|
643
|
+
await this.#feePayerToTxHash.set(tx.data.feePayer.toString(), txHash);
|
|
622
644
|
}
|
|
623
645
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
* - txs with an expiration timestamp lower than that of the mined block
|
|
630
|
-
*
|
|
631
|
-
* @param minedTxHashes - The tx hashes of the txs mined in the block.
|
|
632
|
-
* @param blockHeader - The header of the mined block.
|
|
633
|
-
* @returns The total number of txs evicted from the pool.
|
|
634
|
-
*/
|
|
635
|
-
private async evictInvalidTxsAfterMining(
|
|
636
|
-
minedTxHashes: TxHash[],
|
|
637
|
-
blockHeader: BlockHeader,
|
|
638
|
-
minedNullifiers: Set<string>,
|
|
639
|
-
minedFeePayers: Set<string>,
|
|
640
|
-
): Promise<number> {
|
|
641
|
-
if (minedTxHashes.length === 0) {
|
|
642
|
-
return 0;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
const { blockNumber, timestamp } = blockHeader.globalVariables;
|
|
646
|
-
|
|
647
|
-
// Wait for world state to be synced to at least the mined block number
|
|
648
|
-
await this.#worldStateSynchronizer.syncImmediate(blockNumber);
|
|
649
|
-
|
|
650
|
-
const db = this.#worldStateSynchronizer.getCommitted();
|
|
651
|
-
const gasTxValidator = this.createGasTxValidator(db);
|
|
652
|
-
|
|
653
|
-
const txsToEvict: TxHash[] = [];
|
|
654
|
-
for await (const txHash of this.#pendingTxPriorityToHash.valuesAsync()) {
|
|
655
|
-
const tx = await this.getPendingTxByHash(txHash);
|
|
656
|
-
if (!tx) {
|
|
657
|
-
continue;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
// Evict pending txs that share nullifiers with mined txs
|
|
661
|
-
const txNullifiers = tx.data.getNonEmptyNullifiers();
|
|
662
|
-
if (txNullifiers.some(nullifier => minedNullifiers.has(nullifier.toString()))) {
|
|
663
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to a duplicate nullifier with a mined tx`);
|
|
664
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// Evict pending txs with an insufficient fee payer balance
|
|
669
|
-
if (
|
|
670
|
-
minedFeePayers.has(tx.data.feePayer.toString()) &&
|
|
671
|
-
(await gasTxValidator.validateTxFee(tx)).result === 'invalid'
|
|
672
|
-
) {
|
|
673
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to an insufficient fee payer balance`);
|
|
674
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
675
|
-
continue;
|
|
676
|
-
}
|
|
646
|
+
private async addPendingTxIndices(tx: Tx, txHash: string): Promise<void> {
|
|
647
|
+
return await this.#store.transactionAsync(async () => {
|
|
648
|
+
await this.addPendingTxIndicesInDbTx(tx, txHash);
|
|
649
|
+
});
|
|
650
|
+
}
|
|
677
651
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
}
|
|
652
|
+
// Assumes being called within a DB transaction
|
|
653
|
+
private async removePendingTxIndicesInDbTx(tx: Tx, txHash: string): Promise<void> {
|
|
654
|
+
await this.#pendingTxPriorityToHash.deleteValue(getPendingTxPriority(tx), txHash);
|
|
655
|
+
await this.#historicalHeaderToTxHash.deleteValue(
|
|
656
|
+
(await tx.data.constants.anchorBlockHeader.hash()).toString(),
|
|
657
|
+
txHash,
|
|
658
|
+
);
|
|
659
|
+
await this.#feePayerToTxHash.deleteValue(tx.data.feePayer.toString(), txHash);
|
|
660
|
+
}
|
|
688
661
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
662
|
+
private async removePendingTxIndices(tx: Tx, txHash: string): Promise<void> {
|
|
663
|
+
return await this.#store.transactionAsync(async () => {
|
|
664
|
+
await this.removePendingTxIndicesInDbTx(tx, txHash);
|
|
665
|
+
});
|
|
693
666
|
}
|
|
694
667
|
|
|
695
668
|
/**
|
|
696
|
-
*
|
|
697
|
-
*
|
|
698
|
-
* @param txHashes - The tx hashes of the txs that were moved from mined to pending.
|
|
699
|
-
* @returns The total number of txs evicted from the pool.
|
|
669
|
+
* Returns up to `limit` lowest-priority evictable pending tx hashes without hydrating transactions.
|
|
670
|
+
* Iterates the priority index in ascending order and skips non-evictable txs.
|
|
700
671
|
*/
|
|
701
|
-
|
|
702
|
-
if (txHashes.length === 0) {
|
|
703
|
-
return 0;
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
await this.#worldStateSynchronizer.syncImmediate();
|
|
707
|
-
const db = this.#worldStateSynchronizer.getCommitted();
|
|
708
|
-
const archiveCache = this.createArchiveCache(db);
|
|
709
|
-
const gasTxValidator = this.createGasTxValidator(db);
|
|
710
|
-
|
|
672
|
+
public async getLowestPriorityEvictable(limit: number): Promise<TxHash[]> {
|
|
711
673
|
const txsToEvict: TxHash[] = [];
|
|
674
|
+
if (limit <= 0) {
|
|
675
|
+
return txsToEvict;
|
|
676
|
+
}
|
|
712
677
|
|
|
713
|
-
for await (const
|
|
714
|
-
|
|
715
|
-
if (!tx) {
|
|
716
|
-
continue;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
const [index] = await archiveCache.getArchiveIndices([Fr.fromString(headerHash)]);
|
|
720
|
-
if (index === undefined) {
|
|
721
|
-
this.#log.verbose(`Evicting tx ${txHash} from pool due to an invalid archive root`);
|
|
722
|
-
txsToEvict.push(TxHash.fromString(txHash));
|
|
678
|
+
for await (const txHashStr of this.#pendingTxPriorityToHash.valuesAsync()) {
|
|
679
|
+
if (this.#nonEvictableTxs.has(txHashStr)) {
|
|
723
680
|
continue;
|
|
724
681
|
}
|
|
725
682
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
683
|
+
txsToEvict.push(TxHash.fromString(txHashStr));
|
|
684
|
+
if (txsToEvict.length >= limit) {
|
|
685
|
+
break;
|
|
729
686
|
}
|
|
730
687
|
}
|
|
731
688
|
|
|
732
|
-
|
|
733
|
-
await this.deleteTxs(txsToEvict, { eviction: true });
|
|
734
|
-
}
|
|
735
|
-
return txsToEvict.length;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
private async addPendingTxIndices(tx: Tx, txHash: string): Promise<void> {
|
|
739
|
-
await this.#pendingTxPriorityToHash.set(getPendingTxPriority(tx), txHash);
|
|
740
|
-
await this.#pendingTxHashToSize.set(txHash, tx.getSize());
|
|
741
|
-
await this.#pendingTxHashToHeaderHash.set(txHash, (await tx.data.constants.anchorBlockHeader.hash()).toString());
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
private async removePendingTxIndices(tx: Tx, txHash: string): Promise<void> {
|
|
745
|
-
await this.#pendingTxPriorityToHash.deleteValue(getPendingTxPriority(tx), txHash);
|
|
746
|
-
await this.#pendingTxHashToSize.delete(txHash);
|
|
747
|
-
await this.#pendingTxHashToHeaderHash.delete(txHash);
|
|
748
|
-
this.#pendingTxs.delete(txHash);
|
|
689
|
+
return txsToEvict;
|
|
749
690
|
}
|
|
750
691
|
}
|