Skip to content

Commit

Permalink
fix orphan for rbf and adjust evict interval
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Oct 25, 2023
1 parent f0270ef commit 664898a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 15 deletions.
27 changes: 12 additions & 15 deletions tx-pool/src/component/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use ckb_types::{
packed::{OutPoint, ProposalShortId},
};
use ckb_util::shrink_to_fit;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

const SHRINK_THRESHOLD: usize = 100;
pub(crate) const ORPHAN_TX_EXPIRE_TIME: u64 = 2 * MAX_BLOCK_INTERVAL; // double block interval
pub(crate) const ORPHAN_TX_EXPIRE_TIME: u64 = 100 * MAX_BLOCK_INTERVAL; // double block interval
pub(crate) const DEFAULT_MAX_ORPHAN_TRANSACTIONS: usize = 100;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -39,7 +39,7 @@ impl Entry {
#[derive(Default, Debug, Clone)]
pub(crate) struct OrphanPool {
pub(crate) entries: HashMap<ProposalShortId, Entry>,
pub(crate) by_out_point: HashMap<OutPoint, ProposalShortId>,
pub(crate) by_out_point: HashMap<OutPoint, HashSet<ProposalShortId>>,
}

impl OrphanPool {
Expand All @@ -60,7 +60,7 @@ impl OrphanPool {
self.entries.contains_key(id)
}

pub fn shrink_to_fit(&mut self) {
fn shrink_to_fit(&mut self) {
shrink_to_fit!(self.entries, SHRINK_THRESHOLD);
shrink_to_fit!(self.by_out_point, SHRINK_THRESHOLD);
}
Expand All @@ -73,7 +73,9 @@ impl OrphanPool {
self.entries.remove(id).map(|entry| {
debug!("remove orphan tx {}", entry.tx.hash());
for out_point in entry.tx.input_pts_iter() {
self.by_out_point.remove(&out_point);
self.by_out_point
.get_mut(&out_point)
.map(|set| set.remove(id));
}
entry
})
Expand Down Expand Up @@ -134,23 +136,17 @@ impl OrphanPool {
return vec![];
}

// double spend checking
if tx
.input_pts_iter()
.any(|out_point| self.by_out_point.contains_key(&out_point))
{
return vec![];
}

debug!("add_orphan_tx {}", tx.hash());

self.entries.insert(
tx.proposal_short_id(),
Entry::new(tx.clone(), peer, declared_cycle),
);

for out_point in tx.input_pts_iter() {
self.by_out_point.insert(out_point, tx.proposal_short_id());
self.by_out_point
.entry(out_point)
.or_insert_with(HashSet::default)
.insert(tx.proposal_short_id());
}

self.limit_size()
Expand All @@ -160,6 +156,7 @@ impl OrphanPool {
tx.output_pts()
.iter()
.filter_map(|out_point| self.by_out_point.get(out_point).cloned())
.flatten()
.collect::<Vec<_>>()
}
}
1 change: 1 addition & 0 deletions tx-pool/src/component/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod chunk;
mod entry;
mod orphan;
mod pending;
mod proposed;
mod recent_reject;
Expand Down
58 changes: 58 additions & 0 deletions tx-pool/src/component/tests/orphan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::component::orphan::OrphanPool;
use crate::component::tests::util::build_tx;
use ckb_types::packed::Byte32;

#[test]
fn test_orphan() {
let tx1 = build_tx(vec![(&Byte32::zero(), 1), (&Byte32::zero(), 2)], 1);
let mut orphan = OrphanPool::new();
assert_eq!(orphan.len(), 0);
assert_eq!(orphan.contains_key(&tx1.proposal_short_id()), false);

orphan.add_orphan_tx(tx1.clone(), 0.into(), 0);
assert_eq!(orphan.len(), 1);

orphan.add_orphan_tx(tx1.clone(), 0.into(), 0);
assert_eq!(orphan.len(), 1);

let tx2 = build_tx(vec![(&tx1.hash(), 0)], 1);
orphan.add_orphan_tx(tx2.clone(), 0.into(), 0);
assert_eq!(orphan.len(), 2);

orphan.remove_orphan_tx(&tx1.proposal_short_id());
assert_eq!(orphan.len(), 1);
orphan.remove_orphan_tx(&tx2.proposal_short_id());
assert_eq!(orphan.len(), 0);
}

#[test]
fn test_orphan_duplicated() {
let tx1 = build_tx(vec![(&Byte32::zero(), 1), (&Byte32::zero(), 2)], 3);
let mut orphan = OrphanPool::new();

let tx2 = build_tx(vec![(&tx1.hash(), 0)], 1);
let tx3 = build_tx(vec![(&tx2.hash(), 0)], 1);
let tx4 = build_tx(vec![(&tx3.hash(), 0), (&tx1.hash(), 1)], 1);
let tx5 = build_tx(vec![(&tx1.hash(), 2)], 1);
orphan.add_orphan_tx(tx1.clone(), 0.into(), 0);
orphan.add_orphan_tx(tx2.clone(), 0.into(), 0);
orphan.add_orphan_tx(tx3.clone(), 0.into(), 0);
orphan.add_orphan_tx(tx4.clone(), 0.into(), 0);
orphan.add_orphan_tx(tx5.clone(), 0.into(), 0);
assert_eq!(orphan.len(), 5);

let txs = orphan.find_by_previous(&tx2);
assert_eq!(txs.len(), 1);

let txs = orphan.find_by_previous(&tx1);
assert_eq!(txs.len(), 3);
assert!(txs.contains(&tx2.proposal_short_id()));
assert!(txs.contains(&tx4.proposal_short_id()));
assert!(txs.contains(&tx5.proposal_short_id()));

orphan.remove_orphan_tx(&tx4.proposal_short_id());
let txs = orphan.find_by_previous(&tx1);
assert_eq!(txs.len(), 2);
assert!(txs.contains(&tx2.proposal_short_id()));
assert!(txs.contains(&tx5.proposal_short_id()));
}

0 comments on commit 664898a

Please sign in to comment.