Skip to content

Commit

Permalink
add double spend checking for orphan tx
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Oct 23, 2023
1 parent 0f0993f commit b4c38ad
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ fn all_specs() -> Vec<Box<dyn Spec>> {
Box::new(TxPoolOrphanNormal),
Box::new(TxPoolOrphanReverse),
Box::new(TxPoolOrphanUnordered),
Box::new(TxPoolOrphanDoubleSpend),
Box::new(OrphanTxRejected),
Box::new(GetRawTxPool),
Box::new(PoolReconcile),
Expand Down
46 changes: 46 additions & 0 deletions test/src/specs/tx_pool/orphan_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,49 @@ impl Spec for TxPoolOrphanUnordered {
);
}
}

pub struct TxPoolOrphanDoubleSpend;
impl Spec for TxPoolOrphanDoubleSpend {
fn run(&self, nodes: &mut Vec<Node>) {
let node0 = &nodes[0];
node0.mine_until_out_bootstrap_period();
let parent = node0.new_transaction_with_capacity(capacity_bytes!(800));

let script = node0.always_success_script();
let new_output1 = CellOutputBuilder::default()
.capacity(capacity_bytes!(200).pack())
.lock(script.clone())
.build();
let new_output2 = new_output1.clone();
let new_output3 = new_output1.clone();

let tx1 = parent
.as_advanced_builder()
.set_inputs(vec![CellInput::new(OutPoint::new(parent.hash(), 0), 0)])
.set_outputs(vec![new_output1, new_output2, new_output3])
.set_outputs_data(vec![Default::default(); 3])
.build();

let tx11 =
node0.new_transaction_with_capacity_and_index(tx1.hash(), capacity_bytes!(100), 0, 0);
let tx12 =
node0.new_transaction_with_capacity_and_index(tx1.hash(), capacity_bytes!(120), 0, 0);

let mut net = Net::new(
"orphan_tx_test",
node0.consensus(),
vec![SupportProtocols::RelayV3],
);
net.connect(node0);

assert!(
run_replay_tx(&net, node0, tx11, 1, 0),
"tx11 in orphan pool"
);

assert!(
run_replay_tx(&net, node0, tx12, 1, 0),
"tx12 is not in orphan pool"
);
}
}
10 changes: 10 additions & 0 deletions tx-pool/src/component/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ impl OrphanPool {

pub fn remove_orphan_tx(&mut self, id: &ProposalShortId) -> Option<Entry> {
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);
}
Expand Down Expand Up @@ -122,6 +123,15 @@ impl OrphanPool {
if self.entries.contains_key(&tx.proposal_short_id()) {
return;
}

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

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

self.entries.insert(
Expand Down
1 change: 1 addition & 0 deletions tx-pool/src/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl TxPool {
) {
for tx in txs {
let tx_hash = tx.hash();
debug!("try remove_committed_tx {}", tx_hash);
self.remove_committed_tx(tx, callbacks);

self.committed_txs_hash_cache
Expand Down
5 changes: 4 additions & 1 deletion tx-pool/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,14 +475,17 @@ impl TxPoolService {
let orphan = self.orphan.read().await;
let ids = orphan.find_by_previous(tx);
ids.iter()
.map(|id| orphan.get(id).cloned().unwrap())
.filter_map(|id| orphan.get(id).cloned())
.collect::<Vec<_>>()
}

pub(crate) async fn remove_orphan_tx(&self, id: &ProposalShortId) {
self.orphan.write().await.remove_orphan_tx(id);
}

/// Remove all orphans which are resolved by the given transaction
/// the process is like a breath first search, if there is a cycle in `orphan_queue`,
/// `_process_tx` will return `Reject` since we have checked duplicated tx
pub(crate) async fn process_orphan_tx(&self, tx: &TransactionView) {
let mut orphan_queue: VecDeque<TransactionView> = VecDeque::new();
orphan_queue.push_back(tx.clone());
Expand Down

0 comments on commit b4c38ad

Please sign in to comment.