reth_network/transactions/
constants.rs

1/* ==================== BROADCAST ==================== */
2
3/// Soft limit for the number of hashes in a
4/// [`NewPooledTransactionHashes`](reth_eth_wire::NewPooledTransactionHashes) broadcast message.
5///
6/// Spec'd at 4096 hashes.
7///
8/// <https://github.com/ethereum/devp2p/blob/master/caps/eth.md#newpooledtransactionhashes-0x08>
9pub const SOFT_LIMIT_COUNT_HASHES_IN_NEW_POOLED_TRANSACTIONS_BROADCAST_MESSAGE: usize = 4096;
10
11/// Default soft limit for the byte size of a [`Transactions`](reth_eth_wire::Transactions)
12/// broadcast message.
13///
14/// Default is 128 KiB.
15pub const DEFAULT_SOFT_LIMIT_BYTE_SIZE_TRANSACTIONS_BROADCAST_MESSAGE: usize = 128 * 1024;
16
17/* ================ REQUEST-RESPONSE ================ */
18
19/// Recommended soft limit for the number of hashes in a
20/// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) request.
21///
22/// Spec'd at 256 hashes (8 KiB).
23///
24/// <https://github.com/ethereum/devp2p/blob/master/caps/eth.md#getpooledtransactions-0x09>
25pub const SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST: usize = 256;
26
27/// Soft limit for the byte size of a [`PooledTransactions`](reth_eth_wire::PooledTransactions)
28/// response on assembling a [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions)
29/// request.
30///
31/// Spec'd at 2 MiB.
32///
33/// <https://github.com/ethereum/devp2p/blob/master/caps/eth.md#protocol-messages>.
34pub const SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE: usize = 2 * 1024 * 1024;
35
36/// Constants used by [`TransactionsManager`](super::TransactionsManager).
37pub mod tx_manager {
38    use super::SOFT_LIMIT_COUNT_HASHES_IN_NEW_POOLED_TRANSACTIONS_BROADCAST_MESSAGE;
39
40    /// Default limit for number of transactions to keep track of for a single peer.
41    ///
42    /// Default is 320 transaction hashes.
43    pub const DEFAULT_MAX_COUNT_TRANSACTIONS_SEEN_BY_PEER: u32 = 10 * 1024 / 32;
44
45    /// Default maximum pending pool imports to tolerate.
46    ///
47    /// Default is equivalent to the number of hashes in one full announcement, which is spec'd at
48    /// 4096 hashes, so 4096 pending pool imports.
49    pub const DEFAULT_MAX_COUNT_PENDING_POOL_IMPORTS: usize =
50        SOFT_LIMIT_COUNT_HASHES_IN_NEW_POOLED_TRANSACTIONS_BROADCAST_MESSAGE;
51
52    /// Default limit for number of bad imports to keep track of.
53    ///
54    /// Default is 100 KiB, i.e. 3 200 transaction hashes.
55    pub const DEFAULT_MAX_COUNT_BAD_IMPORTS: u32 = 100 * 1024 / 32;
56}
57
58/// Constants used by [`TransactionFetcher`](super::TransactionFetcher).
59pub mod tx_fetcher {
60    use crate::transactions::fetcher::TransactionFetcherInfo;
61    use reth_network_types::peers::config::{
62        DEFAULT_MAX_COUNT_PEERS_INBOUND, DEFAULT_MAX_COUNT_PEERS_OUTBOUND,
63    };
64
65    use super::{
66        SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE,
67        SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST,
68        SOFT_LIMIT_COUNT_HASHES_IN_NEW_POOLED_TRANSACTIONS_BROADCAST_MESSAGE,
69    };
70
71    /* ============== SCALARS OF MESSAGES ============== */
72
73    /// Default soft limit for the byte size of a
74    /// [`PooledTransactions`](reth_eth_wire::PooledTransactions) response on assembling a
75    /// [`GetPooledTransactions`](reth_eth_wire::PooledTransactions) request. This defaults to less
76    /// than the [`SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE`], at 2 MiB, used when
77    /// assembling a [`PooledTransactions`](reth_eth_wire::PooledTransactions) response.
78    ///
79    /// Default is 128 KiB.
80    pub const DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ: usize = 128 * 1024;
81
82    /* ==================== RETRIES ==================== */
83
84    /// Default maximum request retires per [`TxHash`](alloy_primitives::TxHash). Note, this is
85    /// reset should the [`TxHash`](alloy_primitives::TxHash) re-appear in an announcement after it
86    /// has been evicted from the hashes pending fetch cache, i.e. the counter is restarted. If
87    /// this happens, it is likely a very popular transaction, that should and can indeed be
88    /// fetched hence this behaviour is favourable.
89    ///
90    /// Default is 2 retries.
91    pub const DEFAULT_MAX_RETRIES: u8 = 2;
92
93    /// Default number of alternative peers to keep track of for each transaction pending fetch. At
94    /// most [`DEFAULT_MAX_RETRIES`], which defaults to 2 peers, can ever be needed per peer.
95    ///
96    /// Default is the sum of [`DEFAULT_MAX_RETRIES`] an
97    /// [`DEFAULT_MARGINAL_COUNT_FALLBACK_PEERS`], which defaults to 1 peer, so 3 peers.
98    pub const DEFAULT_MAX_COUNT_FALLBACK_PEERS: u8 =
99        DEFAULT_MAX_RETRIES + DEFAULT_MARGINAL_COUNT_FALLBACK_PEERS;
100
101    /// Default marginal on fallback peers. This is the case, since a transaction is only requested
102    /// once from each individual peer.
103    ///
104    /// Default is 1 peer.
105    pub const DEFAULT_MARGINAL_COUNT_FALLBACK_PEERS: u8 = 1;
106
107    /* ==================== CONCURRENCY ==================== */
108
109    /// Default maximum concurrent [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions)
110    /// requests.
111    ///
112    /// Default is the product of [`DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS_PER_PEER`], which
113    /// defaults to 1 request, and the sum of [`DEFAULT_MAX_COUNT_PEERS_INBOUND`] and
114    /// [`DEFAULT_MAX_COUNT_PEERS_OUTBOUND`], which default to 30 and 100 peers respectively, so
115    /// 130 requests.
116    pub const DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS: u32 =
117        DEFAULT_MAX_COUNT_PEERS_INBOUND + DEFAULT_MAX_COUNT_PEERS_OUTBOUND;
118
119    /// Default maximum number of concurrent
120    /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions)s to allow per peer. This
121    /// number reflects concurrent requests for different hashes.
122    ///
123    /// Default is 1 request.
124    pub const DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS_PER_PEER: u8 = 1;
125
126    /* =============== HASHES PENDING FETCH ================ */
127
128    /// Default limit for number of transactions waiting for an idle peer to be fetched from.
129    ///
130    /// Default is 100 times the [`SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST`],
131    /// which defaults to 256 hashes, so 25 600 hashes.
132    pub const DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH: u32 =
133        100 * SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST as u32;
134
135    /// Default max size for cache of inflight and pending transactions fetch.
136    ///
137    /// Default is [`DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH`] +
138    /// [`DEFAULT_MAX_COUNT_INFLIGHT_REQUESTS_ON_FETCH_PENDING_HASHES`], which is 25600 hashes and
139    /// 65 requests, so it is 25665 hashes.
140    pub const DEFAULT_MAX_CAPACITY_CACHE_INFLIGHT_AND_PENDING_FETCH: u32 =
141        DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH +
142            DEFAULT_MAX_COUNT_INFLIGHT_REQUESTS_ON_FETCH_PENDING_HASHES as u32;
143
144    /// Default maximum number of hashes pending fetch to tolerate at any time.
145    ///
146    /// Default is half of [`DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH`], which defaults to 25 600
147    /// hashes, so 12 800 hashes.
148    pub const DEFAULT_MAX_COUNT_PENDING_FETCH: usize =
149        DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH as usize / 2;
150
151    /* ====== LIMITED CAPACITY ON FETCH PENDING HASHES ====== */
152
153    /// Default budget for finding an idle fallback peer for any hash pending fetch, when said
154    /// search is budget constrained.
155    ///
156    /// Default is a sixth of [`DEFAULT_MAX_COUNT_PENDING_FETCH`], which defaults to 12 800 hashes
157    /// (the ideal max number of hashes pending fetch), divided by
158    /// [`DEFAULT_MAX_COUNT_FALLBACK_PEERS`], which defaults to 3 peers (the depth of the search),
159    /// so a search breadth of 711 lru hashes in the pending hashes cache.
160    pub const DEFAULT_BUDGET_FIND_IDLE_FALLBACK_PEER: usize =
161        DEFAULT_MAX_COUNT_PENDING_FETCH / 6 / DEFAULT_MAX_COUNT_FALLBACK_PEERS as usize;
162
163    /// Default budget for finding hashes in the intersection of transactions announced by a peer
164    /// and in the cache of hashes pending fetch, when said search is budget constrained.
165    ///
166    /// Default is an eight of [`DEFAULT_MAX_COUNT_PENDING_FETCH`], which defaults to 12 800 hashes
167    /// (the ideal max number of hashes pending fetch), so a search breadth of 1 600 lru hashes in
168    /// the pending hashes cache.
169    pub const DEFAULT_BUDGET_FIND_INTERSECTION_ANNOUNCED_BY_PEER_AND_PENDING_FETCH: usize =
170        DEFAULT_MAX_COUNT_PENDING_FETCH / 8;
171
172    /* ====== SCALARS FOR USE ON FETCH PENDING HASHES ====== */
173
174    /// Default soft limit for the number of hashes in a
175    /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) request, when it is filled
176    /// from hashes pending fetch.
177    ///
178    /// Default is half of the [`SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST`]
179    /// which by spec is 256 hashes, so 128 hashes.
180    pub const DEFAULT_SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST_ON_FETCH_PENDING_HASHES:
181    usize = SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST / 2;
182
183    /// Default soft limit for a [`PooledTransactions`](reth_eth_wire::PooledTransactions) response
184    /// when it's used as expected response in calibrating the filling of a
185    /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) request, when the request
186    /// is filled from hashes pending fetch.
187    ///
188    /// Default is half of
189    /// [`DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ`],
190    /// which defaults to 128 KiB, so 64 KiB.
191    pub const DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE_ON_FETCH_PENDING_HASHES:
192        usize =
193        DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ /
194            2;
195
196    /// Default max inflight request when fetching pending hashes.
197    ///
198    /// Default is half of [`DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS`], which defaults to 130
199    /// requests, so 65 requests.
200    pub const DEFAULT_MAX_COUNT_INFLIGHT_REQUESTS_ON_FETCH_PENDING_HASHES: usize =
201        DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS as usize / 2;
202
203    /// Default divisor of the max inflight request when calculating search breadth of the search
204    /// for any idle peer to which to send a request filled with hashes pending fetch. The max
205    /// inflight requests is configured in [`TransactionFetcherInfo`].
206    ///
207    /// Default is 3 requests.
208    pub const DEFAULT_DIVISOR_MAX_COUNT_INFLIGHT_REQUESTS_ON_FIND_IDLE_PEER: usize = 3;
209
210    /// Default divisor of the max inflight request when calculating search breadth of the search
211    /// for the intersection of hashes announced by a peer and hashes pending fetch. The max
212    /// inflight requests is configured in [`TransactionFetcherInfo`].
213    ///
214    /// Default is 3 requests.
215    pub const DEFAULT_DIVISOR_MAX_COUNT_INFLIGHT_REQUESTS_ON_FIND_INTERSECTION: usize = 3;
216
217    // Default divisor to the max pending pool imports when calculating search breadth of the
218    /// search for any idle peer to which to send a request filled with hashes pending fetch.
219    /// The max pending pool imports is configured in
220    /// [`PendingPoolImportsInfo`](crate::transactions::PendingPoolImportsInfo).
221    ///
222    /// Default is 4 requests.
223    pub const DEFAULT_DIVISOR_MAX_COUNT_PENDING_POOL_IMPORTS_ON_FIND_IDLE_PEER: usize = 4;
224
225    /// Default divisor to the max pending pool imports when calculating search breadth of the
226    /// search for any idle peer to which to send a request filled with hashes pending fetch.
227    /// The max pending pool imports is configured in
228    /// [`PendingPoolImportsInfo`](crate::transactions::PendingPoolImportsInfo).
229    ///
230    /// Default is 4 requests.
231    pub const DEFAULT_DIVISOR_MAX_COUNT_PENDING_POOL_IMPORTS_ON_FIND_INTERSECTION: usize = 4;
232
233    /* ================== ROUGH MEASURES ================== */
234
235    /// Average byte size of an encoded transaction.
236    ///
237    /// Default is [`SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE`], which defaults to 2 MiB,
238    /// divided by [`SOFT_LIMIT_COUNT_HASHES_IN_NEW_POOLED_TRANSACTIONS_BROADCAST_MESSAGE`], which
239    /// is spec'd at 4096 hashes, so 521 bytes.
240    pub const AVERAGE_BYTE_SIZE_TX_ENCODED: usize =
241        SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE /
242            SOFT_LIMIT_COUNT_HASHES_IN_NEW_POOLED_TRANSACTIONS_BROADCAST_MESSAGE;
243
244    /// Median observed size in bytes of a small encoded legacy transaction.
245    ///
246    /// Default is 120 bytes.
247    pub const MEDIAN_BYTE_SIZE_SMALL_LEGACY_TX_ENCODED: usize = 120;
248
249    /// Marginal on the number of hashes to preallocate memory for in a
250    /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) request, when packed
251    /// according to the [`Eth68`](reth_eth_wire::EthVersion::Eth68) protocol version. To make
252    /// sure enough memory is preallocated in most cases, it's sensible to use a margin. This,
253    /// since the capacity is calculated based on median value
254    /// [`MEDIAN_BYTE_SIZE_SMALL_LEGACY_TX_ENCODED`]. There may otherwise be a noteworthy number of
255    /// cases where just 1 or 2 bytes too little memory is preallocated.
256    ///
257    /// Default is 8 hashes.
258    pub const DEFAULT_MARGINAL_COUNT_HASHES_GET_POOLED_TRANSACTIONS_REQUEST: usize = 8;
259
260    /// Returns the approx number of transaction hashes that a
261    /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) request will have capacity
262    /// for w.r.t. the [`Eth68`](reth_eth_wire::EthVersion::Eth68) protocol version. This is useful
263    /// for preallocating memory.
264    pub const fn approx_capacity_get_pooled_transactions_req_eth68(
265        info: &TransactionFetcherInfo,
266    ) -> usize {
267        let max_size_expected_response =
268            info.soft_limit_byte_size_pooled_transactions_response_on_pack_request;
269
270        max_size_expected_response / MEDIAN_BYTE_SIZE_SMALL_LEGACY_TX_ENCODED +
271            DEFAULT_MARGINAL_COUNT_HASHES_GET_POOLED_TRANSACTIONS_REQUEST
272    }
273
274    /// Returns the approx number of transactions that a
275    /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) request will
276    /// have capacity for w.r.t. the [`Eth66`](reth_eth_wire::EthVersion::Eth66) protocol version.
277    /// This is useful for preallocating memory.
278    pub const fn approx_capacity_get_pooled_transactions_req_eth66() -> usize {
279        SOFT_LIMIT_COUNT_HASHES_IN_GET_POOLED_TRANSACTIONS_REQUEST
280    }
281}