1mod deferred_pool;
6mod error;
7mod garbage_collector;
8mod nonce_pool;
9mod pool_metrics;
10mod state_provider;
11mod transaction_pool_inner;
12
13pub use error::TransactionPoolError;
14
15use crate::{
16 block_data_manager::BlockDataManager,
17 consensus::BestInformation,
18 transaction_pool::{nonce_pool::TxWithReadyInfo, pool_metrics::*},
19 verification::{VerificationConfig, VerifyTxLocalMode, VerifyTxMode},
20};
21use cfx_executor::{
22 machine::Machine, spec::TransitionsEpochHeight, state::State,
23};
24use cfx_parameters::{
25 block::{
26 cspace_block_gas_limit_after_cip1559, espace_block_gas_limit,
27 espace_block_gas_limit_of_enabled_block,
28 DEFAULT_TARGET_BLOCK_GAS_LIMIT,
29 },
30 consensus_internal::ELASTICITY_MULTIPLIER,
31};
32use cfx_rpc_cfx_types::{PendingReason, TransactionStatus};
33use cfx_statedb::{Result as StateDbResult, StateDb};
34use cfx_storage::{StateIndex, StorageManagerTrait};
35use cfx_types::{
36 AddressWithSpace as Address, AllChainID, Space, SpaceMap, H256, U256,
37};
38use cfx_vm_types::Spec;
39
40use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
41use metrics::{MeterTimer, RwLockExtensions};
42use parking_lot::{Mutex, RwLock};
43use primitives::{
44 block::BlockHeight,
45 block_header::{compute_next_price, compute_next_price_tuple},
46 Account, SignedTransaction, Transaction, TransactionWithSignature,
47};
48use state_provider::StateProvider;
49use std::{
50 cmp::{max, min},
51 collections::{hash_map::HashMap, BTreeMap, BTreeSet},
52 mem,
53 ops::DerefMut,
54 sync::{
55 atomic::{AtomicBool, Ordering},
56 Arc,
57 },
58};
59use transaction_pool_inner::TransactionPoolInner;
60
61pub struct TxPoolConfig {
62 pub capacity: usize,
63 pub min_native_tx_price: u64,
64 pub min_eth_tx_price: u64,
65 pub half_block_gas_limit: RwLock<U256>,
66 pub allow_gas_over_half_block: bool,
67 pub target_block_gas_limit: u64,
68 pub max_packing_batch_gas_limit: u64,
69 pub max_packing_batch_size: usize,
70 pub packing_pool_degree: u8,
71}
72
73impl MallocSizeOf for TxPoolConfig {
74 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { 0 }
75}
76
77impl Default for TxPoolConfig {
78 fn default() -> Self {
79 TxPoolConfig {
80 capacity: 500_000,
81 min_native_tx_price: 1,
82 min_eth_tx_price: 1,
83 half_block_gas_limit: RwLock::new(U256::from(
84 DEFAULT_TARGET_BLOCK_GAS_LIMIT,
85 )),
86 allow_gas_over_half_block: true,
87 max_packing_batch_size: 20,
88 max_packing_batch_gas_limit: DEFAULT_TARGET_BLOCK_GAS_LIMIT / 10,
89 packing_pool_degree: 4,
90 target_block_gas_limit: DEFAULT_TARGET_BLOCK_GAS_LIMIT,
91 }
92 }
93}
94
95impl TxPoolConfig {
96 pub fn check_gas_price_and_limit(
97 &self, tx: &TransactionWithSignature,
98 ) -> Result<(), TransactionPoolError> {
99 let half_block_gas_limit = std::cmp::min(
105 *self.half_block_gas_limit.read(),
106 U256::from(self.target_block_gas_limit),
107 );
108
109 let block_gas_target = half_block_gas_limit;
114
115 let min_tx_price = match tx.space() {
116 Space::Native => self.min_native_tx_price,
117 Space::Ethereum => self.min_eth_tx_price,
118 };
119
120 let space_gas_target: U256 = match tx.space() {
121 Space::Native => {
122 cspace_block_gas_limit_after_cip1559(block_gas_target)
123 }
124 Space::Ethereum => {
125 espace_block_gas_limit_of_enabled_block(block_gas_target)
126 }
127 };
128
129 let space_gas_limit = space_gas_target * 2;
130 let max_tx_gas = if self.allow_gas_over_half_block {
131 space_gas_limit
132 } else {
133 space_gas_limit / 2
134 };
135
136 let tx_gas = *tx.gas();
137 let tx_gas_price = *tx.gas_price();
138
139 if tx_gas > max_tx_gas {
140 warn!(
141 "Transaction discarded due to above gas limit: {} > {:?}",
142 tx.gas(),
143 max_tx_gas
144 );
145 return Err(TransactionPoolError::GasLimitExceeded {
146 max: max_tx_gas,
147 have: tx_gas,
148 });
149 }
150
151 let minimum_price = compute_next_price(
152 space_gas_target,
153 tx_gas,
154 min_tx_price.into(),
155 min_tx_price.into(),
156 );
157
158 if tx_gas_price < minimum_price {
160 trace!("Transaction {} discarded due to below minimal gas price: price {}", tx.hash(), tx_gas_price);
161 return Err(TransactionPoolError::GasPriceLessThanMinimum {
162 min: minimum_price,
163 have: tx_gas_price,
164 });
165 }
166
167 Ok(())
168 }
169}
170
171pub struct TransactionPool {
172 pub config: TxPoolConfig,
173 verification_config: VerificationConfig,
174 inner: RwLock<TransactionPoolInner>,
175 to_propagate_trans: Arc<RwLock<HashMap<H256, Arc<SignedTransaction>>>>,
176 pub data_man: Arc<BlockDataManager>,
177 best_executed_state: Mutex<Arc<State>>,
178 consensus_best_info: Mutex<Arc<BestInformation>>,
179 set_tx_requests: Mutex<Vec<Arc<SignedTransaction>>>,
180 recycle_tx_requests: Mutex<Vec<Arc<SignedTransaction>>>,
181 machine: Arc<Machine>,
182
183 ready_for_mining: AtomicBool,
186}
187
188impl MallocSizeOf for TransactionPool {
189 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
190 let inner_size = self.inner.read().size_of(ops);
191 let to_propagate_trans_size =
192 self.to_propagate_trans.read().size_of(ops);
193 let consensus_best_info_size =
194 self.consensus_best_info.lock().size_of(ops);
195 let set_tx_requests_size = self.set_tx_requests.lock().size_of(ops);
196 let recycle_tx_requests_size =
197 self.recycle_tx_requests.lock().size_of(ops);
198 self.config.size_of(ops)
199 + inner_size
200 + to_propagate_trans_size
201 + self.data_man.size_of(ops)
202 + consensus_best_info_size
203 + set_tx_requests_size
204 + recycle_tx_requests_size
205 }
207}
208
209pub type SharedTransactionPool = Arc<TransactionPool>;
210
211impl TransactionPool {
212 pub fn new(
213 config: TxPoolConfig, verification_config: VerificationConfig,
214 data_man: Arc<BlockDataManager>, machine: Arc<Machine>,
215 ) -> Self {
216 let genesis_hash = data_man.true_genesis.hash();
217 let inner = TransactionPoolInner::new(
218 config.capacity,
219 config.max_packing_batch_gas_limit as usize,
220 config.max_packing_batch_size,
221 config.packing_pool_degree,
222 );
223 let best_executed_state = Mutex::new(
224 Self::get_best_executed_state_by_epoch(
225 &data_man,
226 StateIndex::new_for_readonly(
227 &genesis_hash,
228 &data_man.true_genesis_state_root(),
229 ),
230 )
231 .expect("The genesis state is guaranteed to exist."),
232 );
233 TransactionPool {
234 config,
235 verification_config,
236 inner: RwLock::new(inner),
237 to_propagate_trans: Arc::new(RwLock::new(HashMap::new())),
238 data_man: data_man.clone(),
239 best_executed_state,
240 consensus_best_info: Mutex::new(Arc::new(Default::default())),
241 set_tx_requests: Mutex::new(Default::default()),
242 recycle_tx_requests: Mutex::new(Default::default()),
243 machine,
244 ready_for_mining: AtomicBool::new(false),
245 }
246 }
247
248 pub fn machine(&self) -> Arc<Machine> { self.machine.clone() }
249
250 pub fn get_transaction(
251 &self, tx_hash: &H256,
252 ) -> Option<Arc<SignedTransaction>> {
253 self.inner.read().get(tx_hash)
254 }
255
256 pub fn get_transaction_by_address2nonce(
257 &self, address: Address, nonce: U256,
258 ) -> Option<Arc<SignedTransaction>> {
259 self.inner.read().get_by_address2nonce(address, nonce)
260 }
261
262 pub fn check_tx_packed_in_deferred_pool(&self, tx_hash: &H256) -> bool {
263 self.inner.read().check_tx_packed_in_deferred_pool(tx_hash)
264 }
265
266 pub fn get_local_account_info(&self, address: &Address) -> (U256, U256) {
267 self.inner
268 .read()
269 .get_local_nonce_and_balance(address)
270 .unwrap_or((0.into(), 0.into()))
271 }
272
273 pub fn get_next_nonce(&self, address: &Address) -> U256 {
274 let (state_nonce, _) = self
275 .get_state_account_info(address)
276 .unwrap_or((0.into(), 0.into()));
277 self.inner.read().get_next_nonce(address, state_nonce)
278 }
279
280 pub fn get_account_pending_info(
281 &self, address: &Address,
282 ) -> Option<(U256, U256, U256, H256)> {
283 self.inner.read().get_account_pending_info(address)
284 }
285
286 pub fn get_account_pending_transactions(
288 &self, address: &Address, maybe_start_nonce: Option<U256>,
289 maybe_limit: Option<usize>, best_height: BlockHeight,
290 ) -> StateDbResult<(
291 Vec<Arc<SignedTransaction>>,
292 Option<TransactionStatus>,
293 usize,
294 )> {
295 use TransactionStatus::{Pending, Ready};
296
297 let inner = self.inner.read();
298 let (txs, mut first_tx_status, pending_count) = inner
299 .get_account_pending_transactions(
300 address,
301 maybe_start_nonce,
302 maybe_limit,
303 );
304
305 let first_tx = if let Some(first) = txs.first() {
306 first
307 } else {
308 return Ok((txs, first_tx_status, pending_count));
309 };
310
311 if let Transaction::Native(tx) = &first_tx.unsigned {
312 if VerificationConfig::check_transaction_epoch_bound(
313 tx,
314 best_height,
315 self.verification_config.transaction_epoch_bound,
316 ) == -1
317 {
318 first_tx_status = Some(Pending(PendingReason::OldEpochHeight));
321 }
322 }
323
324 if !matches!(
325 first_tx_status,
326 Some(Ready | Pending(PendingReason::NotEnoughCash))
327 ) {
328 return Ok((txs, first_tx_status, pending_count));
329 }
330
331 let state = self.get_best_state_provider();
335
336 let (sponsored_gas, sponsored_storage) =
337 inner.get_sponsored_gas_and_storage(&state, &first_tx)?;
338 let (_, balance) = state.get_nonce_and_balance(&first_tx.sender())?;
339 let tx_cost = TxWithReadyInfo::new(
340 first_tx.clone(),
341 false,
342 sponsored_gas,
343 sponsored_storage,
344 )
345 .get_tx_cost();
346
347 let outdated = match (tx_cost <= balance, &first_tx_status) {
348 (true, Some(Pending(PendingReason::NotEnoughCash)))
349 | (false, Some(Ready)) => true,
350 _ => false,
351 };
352 if outdated {
353 first_tx_status = Some(Pending(PendingReason::OutdatedStatus));
354 }
355
356 return Ok((txs, first_tx_status, pending_count));
357 }
358
359 pub fn get_pending_transaction_hashes_in_evm_pool(&self) -> BTreeSet<H256> {
360 self.inner.read().ready_transacton_hashes_in_evm_pool()
361 }
362
363 pub fn get_pending_transaction_hashes_in_native_pool(
364 &self,
365 ) -> BTreeSet<H256> {
366 self.inner.read().ready_transacton_hashes_in_native_pool()
367 }
368
369 pub fn get_state_account_info(
370 &self, address: &Address,
371 ) -> StateDbResult<(U256, U256)> {
372 let state = self.get_best_state_provider();
373 state.get_nonce_and_balance(address)
374 }
375
376 pub fn calc_half_block_gas_limit(&self) -> Option<U256> {
377 let current_best_info = self.consensus_best_info.lock().clone();
378 self.data_man
379 .block_from_db(¤t_best_info.best_block_hash)
380 .map(|pivot_block| pivot_block.block_header.gas_limit() / 2)
381 }
382
383 pub fn insert_new_transactions(
390 &self, mut transactions: Vec<TransactionWithSignature>,
391 ) -> (
392 Vec<Arc<SignedTransaction>>,
393 HashMap<H256, TransactionPoolError>,
394 ) {
395 INSERT_TPS.mark(1);
396 INSERT_TXS_TPS.mark(transactions.len());
397 let _timer = MeterTimer::time_func(TX_POOL_INSERT_TIMER.as_ref());
398
399 let mut passed_transactions = Vec::new();
400 let mut failure = HashMap::new();
401 let current_best_info = self.consensus_best_info.lock().clone();
402
403 let (chain_id, best_height, best_block_number) = {
404 (
405 current_best_info.best_chain_id(),
406 current_best_info.best_epoch_number,
407 current_best_info.best_block_number,
408 )
409 };
410 let vm_spec = self.machine.spec(best_block_number, best_height);
414 let transitions = &self.machine.params().transition_heights;
415
416 let mut index = 0;
418 while let Some(tx) = transactions.get(index) {
419 match self.verify_transaction_tx_pool(
420 tx,
421 true,
422 chain_id,
423 best_height,
424 transitions,
425 &vm_spec,
426 ) {
427 Ok(_) => index += 1,
428 Err(e) => {
429 let removed = transactions.swap_remove(index);
430 debug!("failed to insert tx into pool (validation failed), hash = {:?}, error = {:?}", removed.hash, e);
431 failure.insert(removed.hash, e);
432 }
433 }
434 }
435
436 if transactions.is_empty() {
437 INSERT_TXS_SUCCESS_TPS.mark(passed_transactions.len());
438 INSERT_TXS_FAILURE_TPS.mark(failure.len());
439 return (passed_transactions, failure);
440 }
441
442 match self.data_man.recover_unsigned_tx(&transactions) {
447 Ok(signed_trans) => {
448 let state = self.get_best_state_provider();
449 let mut inner =
450 self.inner.write_with_metric(&INSERT_TXS_ENQUEUE_LOCK);
451 let mut to_prop = self.to_propagate_trans.write();
452
453 for tx in signed_trans {
454 if inner.get(&tx.hash).is_some() {
455 continue;
456 }
457
458 if let Err(e) = self.add_transaction_with_readiness_check(
459 &mut *inner,
460 &state,
461 tx.clone(),
462 false,
463 false,
464 ) {
465 debug!(
466 "tx {:?} fails to be inserted to pool, err={:?}",
467 &tx.hash, e
468 );
469 failure.insert(tx.hash(), e);
470 continue;
471 }
472
473 passed_transactions.push(tx.clone());
474 if to_prop.len() < inner.capacity() {
475 to_prop.entry(tx.hash).or_insert(tx);
476 }
477 }
478 }
479 Err(e) => {
480 for tx in transactions {
481 failure.insert(
482 tx.hash(),
483 TransactionPoolError::RlpDecodeError(format!(
484 "{:?}",
485 e
486 )),
487 );
488 }
489 }
490 }
491
492 TX_POOL_DEFERRED_GAUGE.update(self.total_deferred(None));
493 TX_POOL_UNPACKED_GAUGE.update(self.total_unpacked());
494 TX_POOL_READY_GAUGE.update(self.total_ready_accounts());
495
496 INSERT_TXS_SUCCESS_TPS.mark(passed_transactions.len());
497 INSERT_TXS_FAILURE_TPS.mark(failure.len());
498
499 (passed_transactions, failure)
500 }
501
502 pub fn insert_new_signed_transactions(
509 &self, mut signed_transactions: Vec<Arc<SignedTransaction>>,
510 ) -> (
511 Vec<Arc<SignedTransaction>>,
512 HashMap<H256, TransactionPoolError>,
513 ) {
514 INSERT_TPS.mark(1);
515 INSERT_TXS_TPS.mark(signed_transactions.len());
516 let _timer = MeterTimer::time_func(TX_POOL_INSERT_TIMER.as_ref());
517
518 let mut passed_transactions = Vec::new();
519 let mut failure = HashMap::new();
520 let current_best_info = { self.consensus_best_info.lock().clone() };
521
522 let mut index = 0;
524
525 let (chain_id, best_height, best_block_number) = {
526 (
527 current_best_info.best_chain_id(),
528 current_best_info.best_epoch_number,
529 current_best_info.best_block_number,
530 )
531 };
532 let vm_spec = self.machine.spec(best_block_number, best_height);
535 let transitions = &self.machine.params().transition_heights;
536
537 while let Some(tx) = signed_transactions.get(index) {
538 match self.verify_transaction_tx_pool(
539 &tx.transaction,
540 true, chain_id,
542 best_height,
543 transitions,
544 &vm_spec,
545 ) {
546 Ok(_) => index += 1,
547 Err(e) => {
548 let removed = signed_transactions.swap_remove(index);
549 debug!("failed to insert tx into pool (validation failed), hash = {:?}, error = {:?}", removed.hash, e);
550 failure.insert(removed.hash, e);
551 }
552 }
553 }
554
555 let quota = self
557 .inner
558 .write_with_metric(&INSERT_TXS_QUOTA_LOCK)
559 .remaining_quota();
560 if quota < signed_transactions.len() {
561 for tx in signed_transactions.split_off(quota) {
562 trace!("failed to insert tx into pool (quota not enough), hash = {:?}", tx.hash);
563 failure.insert(tx.hash, TransactionPoolError::TxPoolFull);
564 }
565 }
566
567 if signed_transactions.is_empty() {
568 INSERT_TXS_SUCCESS_TPS.mark(passed_transactions.len());
569 INSERT_TXS_FAILURE_TPS.mark(failure.len());
570 return (passed_transactions, failure);
571 }
572
573 {
578 let state = self.get_best_state_provider();
579 let mut inner =
580 self.inner.write_with_metric(&INSERT_TXS_ENQUEUE_LOCK);
581 let mut to_prop = self.to_propagate_trans.write();
582
583 for tx in signed_transactions {
584 if let Err(e) = self.add_transaction_with_readiness_check(
585 &mut *inner,
586 &state,
587 tx.clone(),
588 false,
589 false,
590 ) {
591 debug!(
592 "tx {:?} fails to be inserted to pool, err={:?}",
593 &tx.hash, e
594 );
595 failure.insert(tx.hash(), e);
596 continue;
597 }
598 passed_transactions.push(tx.clone());
599 if !to_prop.contains_key(&tx.hash) {
600 to_prop.insert(tx.hash, tx);
601 }
602 }
603 }
605
606 TX_POOL_DEFERRED_GAUGE.update(self.total_deferred(None));
607 TX_POOL_UNPACKED_GAUGE.update(self.total_unpacked());
608 TX_POOL_READY_GAUGE.update(self.total_ready_accounts());
609
610 INSERT_TXS_SUCCESS_TPS.mark(passed_transactions.len());
611 INSERT_TXS_FAILURE_TPS.mark(failure.len());
612
613 (passed_transactions, failure)
614 }
615
616 fn verify_transaction_tx_pool(
619 &self, transaction: &TransactionWithSignature, basic_check: bool,
620 chain_id: AllChainID, best_height: u64,
621 transitions: &TransitionsEpochHeight, spec: &Spec,
622 ) -> Result<(), TransactionPoolError> {
623 let _timer = MeterTimer::time_func(TX_POOL_VERIFY_TIMER.as_ref());
624 let mode = VerifyTxMode::Local(VerifyTxLocalMode::MaybeLater, spec);
625
626 if basic_check {
627 self.verification_config
628 .check_tx_size(transaction)
629 .map_err(|e| TransactionPoolError::TransactionError(e))?;
630 if let Err(e) = self.verification_config.verify_transaction_common(
631 transaction,
632 chain_id,
633 best_height,
634 transitions,
635 mode,
636 ) {
637 warn!("Transaction {:?} discarded due to not passing basic verification.", transaction.hash());
638 return Err(TransactionPoolError::TransactionError(e));
639 }
640 }
641
642 self.config.check_gas_price_and_limit(transaction)?;
649
650 Ok(())
651 }
652
653 pub fn add_transaction_with_readiness_check(
657 &self, inner: &mut TransactionPoolInner, state: &StateProvider,
658 transaction: Arc<SignedTransaction>, packed: bool, force: bool,
659 ) -> Result<(), TransactionPoolError> {
660 if !transaction.is_canonical_rlp() {
666 return Err(TransactionPoolError::RlpDecodeError(
667 "non-canonical transaction RLP encoding".into(),
668 ));
669 }
670 inner.insert_transaction_with_readiness_check(
671 state,
672 transaction,
673 packed,
674 force,
675 )
676 }
677
678 pub fn get_to_be_propagated_transactions(
679 &self,
680 ) -> HashMap<H256, Arc<SignedTransaction>> {
681 let mut to_prop = self.to_propagate_trans.write();
682 let mut res = HashMap::new();
683 mem::swap(&mut *to_prop, &mut res);
684 res
685 }
686
687 pub fn set_to_be_propagated_transactions(
688 &self, transactions: HashMap<H256, Arc<SignedTransaction>>,
689 ) {
690 let mut to_prop = self.to_propagate_trans.write();
691 to_prop.extend(transactions);
692 }
693
694 pub fn remove_to_be_propagated_transactions(&self, tx_hash: &H256) {
695 self.to_propagate_trans.write().remove(tx_hash);
696 }
697
698 pub fn recycle_transactions(
702 &self, transactions: Vec<Arc<SignedTransaction>>,
703 ) {
704 trace!(
705 "To re-add transactions to transaction pool. \
706 transactions={:?}",
707 &transactions
708 );
709 if transactions.is_empty() || !self.ready_for_mining() {
710 return;
712 }
713
714 let mut recycle_req_buffer = self.recycle_tx_requests.lock();
715 for tx in transactions {
716 recycle_req_buffer.push(tx);
717 }
718 }
719
720 pub fn set_tx_packed(&self, transactions: &Vec<Arc<SignedTransaction>>) {
721 if transactions.is_empty() || !self.ready_for_mining() {
722 return;
724 }
725 let mut tx_req_buffer = self.set_tx_requests.lock();
726 for tx in transactions {
727 tx_req_buffer.push(tx.clone());
728 }
729 }
730
731 pub fn pack_transactions<'a>(
732 &self, num_txs: usize, block_gas_limit: U256, evm_gas_limit: U256,
733 block_size_limit: usize, mut best_epoch_height: u64,
734 mut best_block_number: u64,
735 ) -> Vec<Arc<SignedTransaction>> {
736 let mut inner = self.inner.write_with_metric(&PACK_TRANSACTION_LOCK);
737 best_epoch_height += 1;
738 best_block_number += 1;
740 inner.pack_transactions(
741 num_txs,
742 block_gas_limit,
743 evm_gas_limit,
744 block_size_limit,
745 best_epoch_height,
746 best_block_number,
747 &self.verification_config,
748 &self.machine,
749 )
750 }
751
752 pub fn pack_transactions_1559<'a>(
753 &self, num_txs: usize, block_gas_limit: U256,
754 parent_base_price: SpaceMap<U256>, block_size_limit: usize,
755 mut best_epoch_height: u64, mut best_block_number: u64,
756 ) -> (Vec<Arc<SignedTransaction>>, SpaceMap<U256>) {
757 let mut inner = self.inner.write_with_metric(&PACK_TRANSACTION_LOCK);
758 best_epoch_height += 1;
759 best_block_number += 1;
761
762 let spec = self.machine.spec(best_block_number, best_epoch_height);
763 let transitions = &self.machine.params().transition_heights;
764
765 let validity = |tx: &SignedTransaction| {
766 self.verification_config.fast_recheck(
767 tx,
768 best_epoch_height,
769 transitions,
770 &spec,
771 )
772 };
773
774 inner.pack_transactions_1559(
775 num_txs,
776 block_gas_limit,
777 parent_base_price,
778 block_size_limit,
779 best_epoch_height,
780 &self.machine,
781 validity,
782 )
783 }
784
785 pub fn compute_1559_base_price<'a, I>(
792 &self, parent_hash: &H256, block_gas_limit: U256, txs: I,
793 ) -> Result<Option<SpaceMap<U256>>, String>
794 where I: Iterator<Item = &'a SignedTransaction> + 'a {
795 let parent = self
796 .data_man
797 .block_header_by_hash(parent_hash)
798 .ok_or("Cannot find parent block")?;
799 let current_height = parent.height() + 1;
800
801 let params = self.machine.params();
802 let cip_1559_height = params.transition_heights.cip1559;
803 if current_height < cip_1559_height {
804 return Ok(None);
805 }
806
807 let mut gas_used = SpaceMap::default();
808 let mut min_gas_price =
809 SpaceMap::new(U256::max_value(), U256::max_value());
810 for tx in txs {
811 gas_used[tx.space()] += *tx.gas_limit();
812 min_gas_price[tx.space()] =
813 min_gas_price[tx.space()].min(*tx.gas_price());
814 }
815
816 let core_gas_limit =
817 cspace_block_gas_limit_after_cip1559(block_gas_limit);
818 let eth_gas_limit = espace_block_gas_limit(
819 params.can_pack_evm_transaction(current_height),
820 block_gas_limit,
821 );
822
823 let gas_target =
824 SpaceMap::new(core_gas_limit, eth_gas_limit).map_all(|x| x / 2);
825
826 let parent_base_price = if current_height == cip_1559_height {
827 params.init_base_price()
828 } else {
829 parent.base_price().unwrap()
830 };
831
832 let min_base_price = params.min_base_price();
833
834 let base_price = SpaceMap::zip4(
835 gas_target,
836 gas_used,
837 parent_base_price,
838 min_base_price,
839 )
840 .map_all(compute_next_price_tuple);
841
842 for space in [Space::Native, Space::Ethereum] {
843 if base_price[space] > min_gas_price[space] {
844 return Err(format!("Not sufficient min price in space {:?}, expected {:?}, actual {:?}", space, base_price[space], min_gas_price[space]));
845 }
846 }
847
848 Ok(Some(base_price))
849 }
850
851 pub fn notify_modified_accounts(
852 &self, accounts_from_execution: Vec<Account>,
853 ) {
854 let mut inner = self.inner.write_with_metric(&NOTIFY_MODIFIED_LOCK);
855 inner.notify_modified_accounts(accounts_from_execution)
856 }
857
858 pub fn clear_tx_pool(&self) {
859 let mut inner = self.inner.write();
860 inner.clear()
861 }
862
863 pub fn total_deferred(&self, space: Option<Space>) -> usize {
864 let inner = self.inner.read();
865 inner.total_deferred(space)
866 }
867
868 pub fn total_ready_accounts(&self) -> usize {
869 let inner = self.inner.read();
870 inner.total_ready_accounts()
871 }
872
873 pub fn total_received(&self) -> usize {
874 let inner = self.inner.read();
875 inner.total_received()
876 }
877
878 pub fn total_unpacked(&self) -> usize {
879 let inner = self.inner.read();
880 inner.total_unpacked(None)
881 }
882
883 pub fn total_pending(&self, space: Option<Space>) -> u64 {
886 let inner = self.inner.read();
887 inner.total_pending(space)
888 }
889
890 pub fn total_queued(&self, space: Option<Space>) -> u64 {
894 let inner = self.inner.read();
895 inner.total_queued(space)
896 }
897
898 pub fn stats(&self) -> (usize, usize, usize, usize) {
900 let inner = self.inner.read();
901 (
902 inner.total_ready_accounts(),
903 inner.total_deferred(None),
904 inner.total_received(),
905 inner.total_unpacked(None),
906 )
907 }
908
909 pub fn eth_content(
910 &self, space: Option<Space>,
911 ) -> (
912 BTreeMap<Address, BTreeMap<U256, Arc<SignedTransaction>>>,
913 BTreeMap<Address, BTreeMap<U256, Arc<SignedTransaction>>>,
914 ) {
915 let inner = self.inner.read();
916 inner.eth_content(space)
917 }
918
919 pub fn eth_content_from(
920 &self, from: Address,
921 ) -> (
922 BTreeMap<U256, Arc<SignedTransaction>>,
923 BTreeMap<U256, Arc<SignedTransaction>>,
924 ) {
925 let inner = self.inner.read();
926 inner.eth_content_from(from)
927 }
928
929 pub fn content(
932 &self, address: Option<Address>,
933 ) -> (Vec<Arc<SignedTransaction>>, Vec<Arc<SignedTransaction>>) {
934 let inner = self.inner.read();
935 inner.content(address)
936 }
937
938 pub fn notify_new_best_info(
939 &self, best_info: Arc<BestInformation>,
940 ) -> StateDbResult<()> {
941 let mut set_tx_buffer = self.set_tx_requests.lock();
942 let mut recycle_tx_buffer = self.recycle_tx_requests.lock();
943 {
944 let mut consensus_best_info = self.consensus_best_info.lock();
945 *consensus_best_info = best_info.clone();
946 }
947 if let Some(half_block_gas_limit) = self.calc_half_block_gas_limit() {
948 *self.config.half_block_gas_limit.write() = half_block_gas_limit;
949 }
950
951 let state = self.get_best_state_provider();
952 let mut inner = self.inner.write_with_metric(&NOTIFY_BEST_INFO_LOCK);
953 let inner = inner.deref_mut();
954
955 while let Some(tx) = set_tx_buffer.pop() {
956 let tx_hash = tx.hash();
957 if let Err(e) = self.add_transaction_with_readiness_check(
958 inner, &state, tx, true, false,
959 ) {
960 trace!("set tx err: tx={}, e={:?}", tx_hash, e);
963 }
964 }
965
966 let (chain_id, best_height, best_block_number) = {
967 (
968 best_info.best_chain_id(),
969 best_info.best_epoch_number,
970 best_info.best_block_number,
971 )
972 };
973 let vm_spec = self.machine.spec(best_block_number, best_height);
976 let transitions = &self.machine.params().transition_heights;
977
978 while let Some(tx) = recycle_tx_buffer.pop() {
979 info!(
980 "should not trigger recycle transaction, nonce = {}, sender = {:?}, \
981 account nonce = {}, hash = {:?} .",
982 &tx.nonce(), &tx.sender(),
983 state.get_nonce(&tx.sender())?, tx.hash);
984
985 if let Err(e) = self.verify_transaction_tx_pool(
986 &tx,
987 false,
988 chain_id,
989 best_height,
990 transitions,
991 &vm_spec,
992 ) {
993 warn!(
994 "Recycled transaction {:?} discarded due to not passing verification {}.",
995 tx.hash(), e
996 );
997 }
998 if let Err(e) = self.add_transaction_with_readiness_check(
999 inner, &state, tx, false, true,
1000 ) {
1001 warn!("recycle tx err: e={:?}", e);
1002 }
1003 }
1004 debug!(
1005 "notify_new_best_info: {:?}",
1006 self.consensus_best_info.lock()
1007 );
1008
1009 Ok(())
1010 }
1011
1012 pub fn get_best_info_with_parent_base_price(
1014 &self,
1015 ) -> (Arc<BestInformation>, Option<SpaceMap<U256>>) {
1016 let consensus_best_info_clone = self.consensus_best_info.lock().clone();
1017 debug!(
1018 "get_best_info_with_base_price: {:?}",
1019 consensus_best_info_clone
1020 );
1021
1022 let params = self.machine.params();
1023 let parent_block = self
1024 .data_man
1025 .block_header_by_hash(&consensus_best_info_clone.best_block_hash)
1026 .expect(&concat!(file!(), ":", line!(), ":", column!()));
1028
1029 let cip1559_height = params.transition_heights.cip1559;
1030 let pack_height = consensus_best_info_clone.best_epoch_number + 1;
1031
1032 (
1033 consensus_best_info_clone,
1034 if pack_height <= cip1559_height {
1035 None
1036 } else {
1037 Some(parent_block.base_price().unwrap())
1039 },
1040 )
1041 }
1042
1043 pub fn get_best_info_with_packed_transactions(
1044 &self, num_txs: usize, block_size_limit: usize,
1045 additional_transactions: Vec<Arc<SignedTransaction>>,
1046 ) -> (
1047 Arc<BestInformation>,
1048 U256,
1049 Vec<Arc<SignedTransaction>>,
1050 Option<SpaceMap<U256>>,
1051 ) {
1052 let consensus_best_info_clone = self.consensus_best_info.lock().clone();
1056 debug!(
1057 "get_best_info_with_packed_transactions: {:?}",
1058 consensus_best_info_clone
1059 );
1060
1061 let params = self.machine.params();
1062
1063 let cip1559_height = params.transition_heights.cip1559;
1064 let pack_height = consensus_best_info_clone.best_epoch_number + 1;
1065
1066 let parent_block = self
1067 .data_man
1068 .block_header_by_hash(&consensus_best_info_clone.best_block_hash)
1069 .expect(&concat!(file!(), ":", line!(), ":", column!()));
1071 let parent_block_gas_limit = *parent_block.gas_limit()
1072 * if cip1559_height == pack_height {
1073 ELASTICITY_MULTIPLIER
1074 } else {
1075 1
1076 };
1077
1078 let gas_limit_divisor = params.gas_limit_bound_divisor;
1079 let min_gas_limit = params.min_gas_limit;
1080 assert!(parent_block_gas_limit >= min_gas_limit);
1081 let gas_lower = max(
1082 parent_block_gas_limit - parent_block_gas_limit / gas_limit_divisor
1083 + 1,
1084 min_gas_limit,
1085 );
1086 let gas_upper = parent_block_gas_limit
1087 + parent_block_gas_limit / gas_limit_divisor
1088 - 1;
1089
1090 let target_gas_limit = self.config.target_block_gas_limit
1091 * if pack_height >= cip1559_height {
1092 ELASTICITY_MULTIPLIER as u64
1093 } else {
1094 1
1095 };
1096
1097 let self_gas_limit =
1098 min(max(target_gas_limit.into(), gas_lower), gas_upper);
1099
1100 let (transactions_from_pool, maybe_base_price) = if pack_height
1101 < cip1559_height
1102 {
1103 let evm_gas_limit = if self
1104 .machine
1105 .params()
1106 .can_pack_evm_transaction(pack_height)
1107 {
1108 self_gas_limit / params.evm_transaction_gas_ratio
1109 } else {
1110 U256::zero()
1111 };
1112
1113 let txs = self.pack_transactions(
1114 num_txs,
1115 self_gas_limit.clone(),
1116 evm_gas_limit,
1117 block_size_limit,
1118 consensus_best_info_clone.best_epoch_number,
1119 consensus_best_info_clone.best_block_number,
1120 );
1121 (txs, None)
1122 } else {
1123 let parent_base_price = if pack_height == cip1559_height {
1124 params.init_base_price()
1125 } else {
1126 parent_block.base_price().unwrap()
1127 };
1128
1129 let (txs, packing_base_price) = self.pack_transactions_1559(
1130 num_txs,
1131 self_gas_limit.clone(),
1132 parent_base_price,
1133 block_size_limit,
1134 consensus_best_info_clone.best_epoch_number,
1135 consensus_best_info_clone.best_block_number,
1136 );
1137
1138 let mut base_price = packing_base_price;
1139
1140 if !additional_transactions.is_empty() {
1142 let iter = additional_transactions
1143 .iter()
1144 .chain(txs.iter())
1145 .map(|x| &**x);
1146 match self.compute_1559_base_price(
1147 &parent_block.hash(),
1148 self_gas_limit,
1149 iter,
1150 ) {
1151 Ok(Some(p)) => {
1152 base_price = p;
1153 }
1154 Ok(None) => {
1155 warn!("Should not happen");
1156 }
1157 Err(e) => {
1158 error!("Cannot compute base price with additional transactions: {}", e);
1159 }
1160 }
1161 }
1162 (txs, Some(base_price))
1163 };
1164
1165 let transactions = [
1166 additional_transactions.as_slice(),
1167 transactions_from_pool.as_slice(),
1168 ]
1169 .concat();
1170
1171 (
1172 consensus_best_info_clone,
1173 self_gas_limit,
1174 transactions,
1175 maybe_base_price,
1176 )
1177 }
1178
1179 fn get_best_executed_state_by_epoch(
1180 data_man: &BlockDataManager, best_executed_epoch: StateIndex,
1181 ) -> StateDbResult<Arc<State>> {
1182 let storage = data_man
1183 .storage_manager
1184 .get_state_no_commit(
1185 best_executed_epoch,
1186 false,
1187 None,
1188 )?
1189 .unwrap();
1191 let state_db = StateDb::new(storage);
1192 let state = State::new(state_db)?;
1193 Ok(Arc::new(state))
1194 }
1195
1196 pub fn set_best_executed_state_by_epoch(
1197 &self, best_executed_epoch: StateIndex,
1198 ) -> StateDbResult<()> {
1199 *self.best_executed_state.lock() =
1200 Self::get_best_executed_state_by_epoch(
1201 &self.data_man,
1202 best_executed_epoch,
1203 )?;
1204
1205 Ok(())
1206 }
1207
1208 fn get_best_state_provider(&self) -> StateProvider {
1209 let _timer = MeterTimer::time_func(TX_POOL_GET_STATE_TIMER.as_ref());
1210 StateProvider::new((self.best_executed_state.lock()).clone())
1211 }
1212
1213 pub fn ready_for_mining(&self) -> bool {
1214 self.ready_for_mining.load(Ordering::SeqCst)
1215 }
1216
1217 pub fn set_ready_for_mining(&self) {
1218 self.ready_for_mining.store(true, Ordering::SeqCst);
1219 }
1220}