diff --git a/crates/cfxcore/core/src/transaction_pool/mod.rs b/crates/cfxcore/core/src/transaction_pool/mod.rs index 52c661dbcd..1479e42bc2 100644 --- a/crates/cfxcore/core/src/transaction_pool/mod.rs +++ b/crates/cfxcore/core/src/transaction_pool/mod.rs @@ -16,7 +16,9 @@ use crate::{ block_data_manager::BlockDataManager, consensus::BestInformation, transaction_pool::{nonce_pool::TxWithReadyInfo, pool_metrics::*}, - verification::{VerificationConfig, VerifyTxLocalMode, VerifyTxMode}, + verification::{ + PackingCheckResult, VerificationConfig, VerifyTxLocalMode, VerifyTxMode, + }, }; use cfx_executor::{ machine::Machine, spec::TransitionsEpochHeight, state::State, @@ -718,6 +720,21 @@ impl TransactionPool { } } + fn check_validity( + &self, tx: &SignedTransaction, best_epoch_height: u64, + best_block_number: u64, + ) -> PackingCheckResult { + let spec = self.machine.spec(best_block_number, best_epoch_height); + let transitions = &self.machine.params().transition_heights; + + self.verification_config.fast_recheck( + tx, + best_epoch_height, + transitions, + &spec, + ) + } + pub fn pack_transactions<'a>( &self, num_txs: usize, block_gas_limit: U256, evm_gas_limit: U256, block_size_limit: usize, mut best_epoch_height: u64, @@ -727,15 +744,17 @@ impl TransactionPool { best_epoch_height += 1; // The best block number is not necessary an exact number. best_block_number += 1; + + let validity = |tx: &SignedTransaction| { + self.check_validity(tx, best_epoch_height, best_block_number) + }; + inner.pack_transactions( num_txs, block_gas_limit, evm_gas_limit, block_size_limit, - best_epoch_height, - best_block_number, - &self.verification_config, - &self.machine, + validity, ) } @@ -749,16 +768,8 @@ impl TransactionPool { // The best block number is not necessary an exact number. best_block_number += 1; - let spec = self.machine.spec(best_block_number, best_epoch_height); - let transitions = &self.machine.params().transition_heights; - let validity = |tx: &SignedTransaction| { - self.verification_config.fast_recheck( - tx, - best_epoch_height, - transitions, - &spec, - ) + self.check_validity(tx, best_epoch_height, best_block_number) }; inner.pack_transactions_1559( @@ -800,7 +811,7 @@ impl TransactionPool { for tx in txs { gas_used[tx.space()] += *tx.gas_limit(); min_gas_price[tx.space()] = - min_gas_price[tx.space()].min(*tx.gas_limit()); + min_gas_price[tx.space()].min(*tx.gas_price()); } let core_gas_limit = diff --git a/crates/cfxcore/core/src/transaction_pool/transaction_pool_inner.rs b/crates/cfxcore/core/src/transaction_pool/transaction_pool_inner.rs index 890f2c6a87..3f536ea609 100644 --- a/crates/cfxcore/core/src/transaction_pool/transaction_pool_inner.rs +++ b/crates/cfxcore/core/src/transaction_pool/transaction_pool_inner.rs @@ -7,11 +7,14 @@ use super::{ TransactionPoolError, }; -use crate::verification::{PackingCheckResult, VerificationConfig}; +use crate::verification::PackingCheckResult; use cfx_executor::machine::Machine; use cfx_packing_pool::PackingPoolConfig; use cfx_parameters::{ - block::cspace_block_gas_limit_after_cip1559, + block::{ + cspace_block_gas_limit_after_cip1559, + espace_block_gas_limit_of_enabled_block, + }, consensus_internal::ELASTICITY_MULTIPLIER, staking::DRIPS_PER_STORAGE_COLLATERAL_UNIT, }; @@ -643,27 +646,14 @@ impl TransactionPoolInner { /// pack at most num_txs transactions randomly pub fn pack_transactions<'a>( &mut self, num_txs: usize, block_gas_limit: U256, evm_gas_limit: U256, - block_size_limit: usize, best_epoch_height: u64, - best_block_number: u64, verification_config: &VerificationConfig, - machine: &Machine, + block_size_limit: usize, + validity: impl Fn(&SignedTransaction) -> PackingCheckResult, ) -> Vec> { let mut packed_transactions: Vec> = Vec::new(); if num_txs == 0 { return packed_transactions; } - let spec = machine.spec(best_block_number, best_epoch_height); - let transitions = &machine.params().transition_heights; - - let validity = |tx: &SignedTransaction| { - verification_config.fast_recheck( - tx, - best_epoch_height, - transitions, - &spec, - ) - }; - let (sampled_tx, used_gas, used_size) = self.deferred_pool.packing_sampler( Space::Ethereum, @@ -671,7 +661,7 @@ impl TransactionPoolInner { block_size_limit, num_txs, U256::zero(), - validity, + &validity, ); packed_transactions.extend_from_slice(&sampled_tx); @@ -681,7 +671,7 @@ impl TransactionPoolInner { block_size_limit - used_size, num_txs - sampled_tx.len(), U256::zero(), - validity, + &validity, ); packed_transactions.extend_from_slice(&sampled_tx); @@ -722,7 +712,9 @@ impl TransactionPoolInner { machine.params().can_pack_evm_transaction(best_epoch_height); let (evm_packed_tx_num, evm_used_size) = if can_pack_evm { - let gas_target = block_gas_limit * 5 / 10 / ELASTICITY_MULTIPLIER; + let gas_target = + espace_block_gas_limit_of_enabled_block(block_gas_limit) + / ELASTICITY_MULTIPLIER; let parent_base_price = parent_base_price[Space::Ethereum]; let min_base_price = machine.params().min_base_price()[Space::Ethereum]; diff --git a/crates/cfxcore/packing-pool/src/key_mng.rs b/crates/cfxcore/packing-pool/src/key_mng.rs index 8f3ab6c842..658d8ad211 100644 --- a/crates/cfxcore/packing-pool/src/key_mng.rs +++ b/crates/cfxcore/packing-pool/src/key_mng.rs @@ -37,7 +37,7 @@ impl KeyMngTrait> ) { match (value, old_value) { (Some(v), _) => { - self.insert(*key, v.first_gas_price()); + self.insert(*key, v.first_priority_gas_price()); } (None, Some(_)) => { self.remove(key); @@ -57,6 +57,6 @@ impl KeyMngTrait> fn make_sort_key( &self, _key: &TX::Sender, value: &PackingBatch, ) -> U256 { - value.first_gas_price() + value.first_priority_gas_price() } } diff --git a/crates/cfxcore/packing-pool/src/mock_tx.rs b/crates/cfxcore/packing-pool/src/mock_tx.rs index 697f436b82..8c04e093b1 100644 --- a/crates/cfxcore/packing-pool/src/mock_tx.rs +++ b/crates/cfxcore/packing-pool/src/mock_tx.rs @@ -1,4 +1,5 @@ use crate::transaction::PackingPoolTransaction; +use cfx_types::U256; #[derive(Default, Clone, Copy, PartialEq, Eq, Debug, Hash)] /// A minimal implementation of the [`PackingPoolTransaction`] trait for testing @@ -26,9 +27,13 @@ impl PackingPoolTransaction for MockTransaction { fn sender(&self) -> Self::Sender { self.sender } - fn nonce(&self) -> cfx_types::U256 { self.nonce.into() } + fn nonce(&self) -> U256 { self.nonce.into() } - fn gas_price(&self) -> cfx_types::U256 { self.gas_price.into() } + fn gas_price(&self) -> U256 { self.gas_price.into() } - fn gas_limit(&self) -> cfx_types::U256 { self.gas_limit.into() } + // mock tx is a eip155 like transaction, so we use gas_price as + // max_priority_gas_price + fn max_priority_gas_price(&self) -> U256 { self.gas_price.into() } + + fn gas_limit(&self) -> U256 { self.gas_limit.into() } } diff --git a/crates/cfxcore/packing-pool/src/packing_batch.rs b/crates/cfxcore/packing-pool/src/packing_batch.rs index 2ef33f53c7..6427597240 100644 --- a/crates/cfxcore/packing-pool/src/packing_batch.rs +++ b/crates/cfxcore/packing-pool/src/packing_batch.rs @@ -41,7 +41,7 @@ pub enum RemoveError { #[derive(Debug)] pub(crate) struct PackInfo { - pub first_gas_price: U256, + pub first_priority_gas_price: U256, pub total_gas_limit: U256, } @@ -60,6 +60,11 @@ impl PackingBatch { #[inline] pub fn start_nonce(&self) -> U256 { self.txs.first().unwrap().nonce() } + #[inline] + pub fn first_priority_gas_price(&self) -> U256 { + self.txs.first().unwrap().max_priority_gas_price() + } + #[inline] pub fn first_gas_price(&self) -> U256 { self.txs.first().unwrap().gas_price() @@ -71,7 +76,7 @@ impl PackingBatch { #[inline] pub(crate) fn pack_info(&self) -> PackInfo { PackInfo { - first_gas_price: self.first_gas_price(), + first_priority_gas_price: self.first_priority_gas_price(), total_gas_limit: self.total_gas_limit(), } } @@ -104,14 +109,16 @@ impl PackingBatch { let txs = &mut self.txs; if tx.nonce() + 1 < start_nonce || (tx.nonce() + 1 == start_nonce - && tx.gas_price() > txs[0].gas_price()) + && tx.max_priority_gas_price() + > txs[0].max_priority_gas_price()) { let old_txs = std::mem::take(txs); *self = Self::new(tx); return (old_txs, Ok(())); } - if tx.nonce() + 1 == start_nonce && tx.gas_price() <= txs[0].gas_price() + if tx.nonce() + 1 == start_nonce + && tx.max_priority_gas_price() <= txs[0].max_priority_gas_price() { txs.insert(0, tx); let (truncate_idx, addr_gas_limit) = @@ -131,7 +138,9 @@ impl PackingBatch { return (vec![], Err(ExceedAddrTxCount)); } - if txs.last().unwrap().gas_price() > tx.gas_price() { + if txs.last().unwrap().max_priority_gas_price() + > tx.max_priority_gas_price() + { return (vec![], Err(DecreasingGasPrice)); } if config.address_gas_limit @@ -148,7 +157,8 @@ impl PackingBatch { // Replace let to_replaced_idx = (tx.nonce() - start_nonce).as_usize(); if to_replaced_idx > 0 - && tx.gas_price() < txs[to_replaced_idx - 1].gas_price() + && tx.max_priority_gas_price() + < txs[to_replaced_idx - 1].max_priority_gas_price() { let old_txs = self.txs.split_off(to_replaced_idx); self.update_total_limit(); @@ -162,7 +172,7 @@ impl PackingBatch { self.update_total_limit(); return (old_txs, Err(ExceedAddrGasLimit)); } - let my_gas_price = tx.gas_price(); + let my_gas_price = tx.max_priority_gas_price(); std::mem::swap(&mut txs[to_replaced_idx], &mut tx); @@ -170,7 +180,7 @@ impl PackingBatch { let truncated_txs; if txs .get(to_replaced_idx + 1) - .map_or(false, |tx| tx.gas_price() < my_gas_price) + .map_or(false, |tx| tx.max_priority_gas_price() < my_gas_price) { truncated_txs = txs.split_off(to_replaced_idx + 1); self.update_total_limit(); @@ -262,7 +272,8 @@ impl PackingBatch { ) -> treap_map::Node> { let key = self.txs.first().unwrap().sender(); let gas_price = self.first_gas_price(); - let sort_key = gas_price; + let priority_gas_price = self.first_priority_gas_price(); + let sort_key = priority_gas_price; let loss_ratio = config.loss_ratio(sort_key); let weight = PackingPoolWeight { gas_limit: self.total_gas_limit, @@ -279,7 +290,10 @@ impl PackingBatch { for i in 0..(self.txs.len() - 1) { assert_eq!(self.txs[i].sender(), self.txs[i + 1].sender()); assert_eq!(self.txs[i].nonce() + 1, self.txs[i + 1].nonce()); - assert!(self.txs[i].gas_price() <= self.txs[i + 1].gas_price()); + assert!( + self.txs[i].max_priority_gas_price() + <= self.txs[i + 1].max_priority_gas_price() + ); } assert_eq!( self.total_gas_limit.as_u128(), diff --git a/crates/cfxcore/packing-pool/src/pool.rs b/crates/cfxcore/packing-pool/src/pool.rs index 26d20b010c..7ba71278f7 100644 --- a/crates/cfxcore/packing-pool/src/pool.rs +++ b/crates/cfxcore/packing-pool/src/pool.rs @@ -239,8 +239,9 @@ impl PackingPool { let weight = &node.weight; let packing_batch = &node.value; packing_batch.assert_constraints(); - let loss_ratio = - self.config.loss_ratio(packing_batch.first_gas_price()); + let loss_ratio = self + .config + .loss_ratio(packing_batch.first_priority_gas_price()); let gas_limit = packing_batch.total_gas_limit(); assert_eq!(gas_limit, weight.gas_limit); assert_eq!(loss_ratio, weight.max_loss_ratio); @@ -253,14 +254,15 @@ fn make_apply_outcome( old_info: PackInfo, new_info: PackInfo, node: &mut Node>, config: &PackingPoolConfig, out: T, ) -> ApplyOpOutcome { - let change_gas_price = old_info.first_gas_price != new_info.first_gas_price; + let change_gas_price = + old_info.first_priority_gas_price != new_info.first_priority_gas_price; let change_gas_limit = old_info.total_gas_limit != new_info.total_gas_limit; let mut update_weight = false; let mut update_key = false; if change_gas_price { - let gas_price = new_info.first_gas_price; + let gas_price = new_info.first_priority_gas_price; node.sort_key = gas_price; node.weight.max_loss_ratio = config.loss_ratio(gas_price); node.weight.gas_limit = new_info.total_gas_limit; diff --git a/crates/cfxcore/packing-pool/src/sample.rs b/crates/cfxcore/packing-pool/src/sample.rs index 3940a4afa6..c603bea75a 100644 --- a/crates/cfxcore/packing-pool/src/sample.rs +++ b/crates/cfxcore/packing-pool/src/sample.rs @@ -27,11 +27,11 @@ pub enum SampleTag { /// /// The iterator operates in three phases: /// 1. **Random Sampling Phase**: Based on the random packing algorithm, -/// addresses are selected from high to low gas prices of their first +/// addresses are selected from high to low gas prices of their first /// transaction. The probability of inclusion is determined by the algorithm. -/// Transactions not selected are placed in a candidate queue. +/// Transactions not selected are placed in a candidate queue. /// 2. **Candidate Queue Phase**: Transactions from the candidate queue are -/// output in a random order. Transactions with a higher probability in the +/// output in a random order. Transactions with a higher probability in the /// first phase have a greater chance of appearing earlier in this phase. /// 3. **Remaining Transactions Phase**: Remaining addresses are output in /// descending order of their first transaction gas prices. diff --git a/crates/cfxcore/packing-pool/src/transaction.rs b/crates/cfxcore/packing-pool/src/transaction.rs index 3ef099260e..27015a5fab 100644 --- a/crates/cfxcore/packing-pool/src/transaction.rs +++ b/crates/cfxcore/packing-pool/src/transaction.rs @@ -6,6 +6,7 @@ use primitives::SignedTransaction; /// Trait representing a transaction processed by the `PackingPool`. pub trait PackingPoolTransaction: Clone { type Sender: Default + Ord + Hash + Copy + Debug; + fn sender(&self) -> Self::Sender; fn nonce(&self) -> U256; @@ -13,6 +14,8 @@ pub trait PackingPoolTransaction: Clone { fn gas_price(&self) -> U256; fn gas_limit(&self) -> U256; + + fn max_priority_gas_price(&self) -> U256; } impl PackingPoolTransaction for Arc { @@ -27,6 +30,11 @@ impl PackingPoolTransaction for Arc { #[inline] fn gas_price(&self) -> U256 { *SignedTransaction::gas_price(&self) } + #[inline] + fn max_priority_gas_price(&self) -> U256 { + *SignedTransaction::max_priority_gas_price(&self) + } + #[inline] fn gas_limit(&self) -> U256 { *SignedTransaction::gas_limit(&self) } } diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 10f616e18a..3a28fb039c 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -1120,6 +1120,10 @@ impl SignedTransaction { pub fn gas_price(&self) -> &U256 { &self.transaction.gas_price() } + pub fn max_priority_gas_price(&self) -> &U256 { + &self.transaction.max_priority_gas_price() + } + pub fn gas_limit(&self) -> &U256 { &self.transaction.gas() } pub fn storage_limit(&self) -> Option { diff --git a/crates/rpc/rpc-eth-impl/src/eth.rs b/crates/rpc/rpc-eth-impl/src/eth.rs index 3fc2e5b563..8b97ccb913 100644 --- a/crates/rpc/rpc-eth-impl/src/eth.rs +++ b/crates/rpc/rpc-eth-impl/src/eth.rs @@ -1168,9 +1168,6 @@ impl EthApiServer for EthApi { } /// Returns the EIP-2718 encoded transaction if it exists. - /// - /// If this is a EIP-4844 transaction that is in the pool it will include - /// the sidecar. async fn raw_transaction_by_hash( &self, hash: H256, ) -> RpcResult> {