Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 26 additions & 15 deletions crates/cfxcore/core/src/transaction_pool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
)
}

Expand All @@ -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(
Expand Down Expand Up @@ -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 =
Expand Down
32 changes: 12 additions & 20 deletions crates/cfxcore/core/src/transaction_pool/transaction_pool_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -643,35 +646,22 @@ 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<Arc<SignedTransaction>> {
let mut packed_transactions: Vec<Arc<SignedTransaction>> = 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,
std::cmp::min(block_gas_limit, evm_gas_limit),
block_size_limit,
num_txs,
U256::zero(),
validity,
&validity,
);
packed_transactions.extend_from_slice(&sampled_tx);

Expand All @@ -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);

Expand Down Expand Up @@ -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];
Expand Down
4 changes: 2 additions & 2 deletions crates/cfxcore/packing-pool/src/key_mng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl<TX: PackingPoolTransaction> KeyMngTrait<PackingPoolMap<TX>>
) {
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);
Expand All @@ -57,6 +57,6 @@ impl<TX: PackingPoolTransaction> KeyMngTrait<PackingPoolMap<TX>>
fn make_sort_key(
&self, _key: &TX::Sender, value: &PackingBatch<TX>,
) -> U256 {
value.first_gas_price()
value.first_priority_gas_price()
}
}
11 changes: 8 additions & 3 deletions crates/cfxcore/packing-pool/src/mock_tx.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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() }
}
34 changes: 24 additions & 10 deletions crates/cfxcore/packing-pool/src/packing_batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand All @@ -60,6 +60,11 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
#[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()
Expand All @@ -71,7 +76,7 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
#[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(),
}
}
Expand Down Expand Up @@ -104,14 +109,16 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
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) =
Expand All @@ -131,7 +138,9 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
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
Expand All @@ -148,7 +157,8 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
// 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();
Expand All @@ -162,15 +172,15 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
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);

let mut res = vec![tx];
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();
Expand Down Expand Up @@ -262,7 +272,8 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
) -> treap_map::Node<PackingPoolMap<TX>> {
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,
Expand All @@ -279,7 +290,10 @@ impl<TX: PackingPoolTransaction> PackingBatch<TX> {
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(),
Expand Down
10 changes: 6 additions & 4 deletions crates/cfxcore/packing-pool/src/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,9 @@ impl<TX: PackingPoolTransaction> PackingPool<TX> {
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);
Expand All @@ -253,14 +254,15 @@ fn make_apply_outcome<TX: PackingPoolTransaction, T>(
old_info: PackInfo, new_info: PackInfo,
node: &mut Node<PackingPoolMap<TX>>, config: &PackingPoolConfig, out: T,
) -> ApplyOpOutcome<T> {
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;
Expand Down
6 changes: 3 additions & 3 deletions crates/cfxcore/packing-pool/src/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions crates/cfxcore/packing-pool/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ 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;

fn gas_price(&self) -> U256;

fn gas_limit(&self) -> U256;

fn max_priority_gas_price(&self) -> U256;
}

impl PackingPoolTransaction for Arc<SignedTransaction> {
Expand All @@ -27,6 +30,11 @@ impl PackingPoolTransaction for Arc<SignedTransaction> {
#[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) }
}
4 changes: 4 additions & 0 deletions crates/primitives/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u64> {
Expand Down
Loading
Loading