Skip to content

Commit

Permalink
feat(hardfork): reset scripts caches when a new feature enabled which…
Browse files Browse the repository at this point in the history
… mays change the script results
  • Loading branch information
chaoticlonghair committed Jun 15, 2021
1 parent fa40d1c commit e4dac8a
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 10 deletions.
17 changes: 16 additions & 1 deletion tx-pool/src/component/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::{component::entry::TxEntry, error::Reject};
use ckb_types::{
core::Capacity,
core::{Capacity, TransactionView},
packed::{OutPoint, ProposalShortId},
};
use std::borrow::Cow;
Expand Down Expand Up @@ -184,6 +184,10 @@ impl TxLinksMap {
.get_mut(short_id)
.map(|links| links.children.insert(child))
}

fn clear(&mut self) {
self.inner.clear();
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -395,6 +399,17 @@ impl SortedTxMap {
.rev()
.map(move |key| self.entries.get(&key.id).expect("consistent"))
}

/// Clear and return all transactions.
pub(crate) fn drain(&mut self) -> Vec<TransactionView> {
self.sorted_index.clear();
self.deps.clear();
self.links.clear();
self.entries
.drain()
.map(|(_, entry)| entry.transaction().to_owned())
.collect()
}
}

#[cfg(test)]
Expand Down
7 changes: 7 additions & 0 deletions tx-pool/src/component/pending.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ impl PendingQueue {
}
}
}

pub(crate) fn drain(&mut self) -> Vec<TransactionView> {
self.inner
.values()
.map(|entry| entry.transaction().clone())
.collect()
}
}

impl CellProvider for PendingQueue {
Expand Down
11 changes: 11 additions & 0 deletions tx-pool/src/component/proposed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ impl Edges {
self.deps.remove(out_point);
}
}

pub(crate) fn clear(&mut self) {
self.outputs.clear();
self.inputs.clear();
self.deps.clear();
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -307,6 +313,11 @@ impl ProposedPool {
pub fn calc_descendants(&self, tx_short_id: &ProposalShortId) -> HashSet<ProposalShortId> {
self.inner.calc_descendants(&tx_short_id)
}

pub(crate) fn drain(&mut self) -> Vec<TransactionView> {
self.edges.clear();
self.inner.drain()
}
}

#[cfg(test)]
Expand Down
7 changes: 7 additions & 0 deletions tx-pool/src/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,4 +451,11 @@ impl TxPool {

TxPoolEntryInfo { pending, proposed }
}

pub(crate) fn drain_all_transactions(&mut self) -> Vec<TransactionView> {
let mut txs = self.proposed.drain();
txs.append(&mut self.gap.drain());
txs.append(&mut self.pending.drain());
txs
}
}
86 changes: 77 additions & 9 deletions tx-pool/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use ckb_types::{
get_related_dep_out_points, OverlayCellChecker, ResolvedTransaction,
TransactionsChecker,
},
hardfork::HardForkSwitch,
BlockView, Capacity, Cycle, EpochExt, HeaderView, ScriptHashType, TransactionView,
UncleBlockView, Version,
},
Expand Down Expand Up @@ -611,6 +612,11 @@ impl TxPoolService {
) {
let mut detached = LinkedHashSet::default();
let mut attached = LinkedHashSet::default();
let hardfork_switch = snapshot.consensus().hardfork_switch();
let hardfork_during_detach =
check_if_hardfork_during_blocks(&hardfork_switch, &detached_blocks);
let hardfork_during_attach =
check_if_hardfork_during_blocks(&hardfork_switch, &attached_blocks);

for blk in detached_blocks {
detached.extend(blk.transactions().into_iter().skip(1))
Expand All @@ -624,16 +630,33 @@ impl TxPoolService {
let fetched_cache = self.fetch_txs_verify_cache(retain.iter()).await;

{
let mut tx_pool = self.tx_pool.write().await;
_update_tx_pool_for_reorg(
&mut tx_pool,
&attached,
detached_proposal_id,
snapshot,
&self.callbacks,
);
let txs_opt = {
// This closure is used to limit the lifetime of mutable tx_pool.
let mut tx_pool = self.tx_pool.write().await;

let txs_opt = if hardfork_during_detach || hardfork_during_attach {
// The tx_pool is locked, remove all caches if has any hardfork.
self.txs_verify_cache.write().await.clear();
Some(tx_pool.drain_all_transactions())
} else {
None
};

_update_tx_pool_for_reorg(
&mut tx_pool,
&attached,
detached_proposal_id,
snapshot,
&self.callbacks,
);
self.readd_dettached_tx(&mut tx_pool, retain, fetched_cache);

txs_opt
};

self.readd_dettached_tx(&mut tx_pool, retain, fetched_cache)
if let Some(txs) = txs_opt {
self.try_process_txs(txs).await;
}
}

{
Expand Down Expand Up @@ -671,6 +694,23 @@ impl TxPoolService {
}
}

// # Notice
//
// This method assumes that the inputs transactions are sorted.
async fn try_process_txs(&self, txs: Vec<TransactionView>) {
if txs.is_empty() {
return;
}
let total = txs.len();
let mut count = 0usize;
for tx in txs {
if self._process_tx(tx, None).await.is_err() {
count += 1;
}
}
info!("{}/{} transactions are failed to process", count, total);
}

pub(crate) async fn clear_pool(&mut self, new_snapshot: Arc<Snapshot>) {
let mut tx_pool = self.tx_pool.write().await;
let config = tx_pool.config;
Expand Down Expand Up @@ -833,3 +873,31 @@ fn _update_tx_pool_for_reorg(
}
}
}

// # Notice
//
// This method assumes that the inputs blocks are sorted.
fn check_if_hardfork_during_blocks(
hardfork_switch: &HardForkSwitch,
blocks: &VecDeque<BlockView>,
) -> bool {
if blocks.is_empty() {
false
} else {
// This method assumes that the hardfork epochs are sorted and unique.
let hardfork_epochs = hardfork_switch.script_result_changed_at();
if hardfork_epochs.is_empty() {
false
} else {
let epoch_first = blocks.front().unwrap().epoch().number();
let epoch_next = blocks
.back()
.unwrap()
.epoch()
.minimum_epoch_number_after_n_blocks(1);
hardfork_epochs
.into_iter()
.any(|hardfork_epoch| epoch_first < hardfork_epoch && hardfork_epoch <= epoch_next)
}
}
}
12 changes: 12 additions & 0 deletions util/types/src/core/hardfork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ impl HardForkSwitch {
.build()
.unwrap()
}

/// Returns a vector of epoch numbers, and there are new features which
/// require refrese tx-pool caches will be enabled at those epochs.
pub fn script_result_changed_at(&self) -> Vec<EpochNumber> {
let mut epochs = vec![self.rfc_pr_0237()];
// In future, there could be more than one epoch,
// we should merge the same epochs and sort all epochs.
//epochs.sort_unstable();
//epochs.dedup();
epochs.retain(|&x| x != 0);
epochs
}
}

define_methods!(
Expand Down

0 comments on commit e4dac8a

Please sign in to comment.