Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better tests for transaction conflict handling #1064

Merged
merged 9 commits into from
Oct 5, 2023

Conversation

LagginTimes
Copy link
Contributor

@LagginTimes LagginTimes commented Aug 7, 2023

Description

Fixes #1063.

This PR introduces a new TxTemplate struct to test different transaction conflict scenarios in TxGraph.
The following transaction conflict scenarios are tested:

  • 2 unconfirmed txs with different last_seens conflict. The most recent tx should be the only tx that appears in the list methods.
  • 3 unconfirmed txs with different last_seens conflict. The most recent tx should be the only tx that appears in the list methods.
  • An unconfirmed tx U conflicts with a tx anchored in orphaned block O. O has higher last_seen. O should be the only tx that appears in the list methods.
  • An unconfirmed tx U conflicts with a tx anchored in orphaned block O. U has higher last_seen. U should be the only tx that appears in the list methods.
  • Multiple unconfirmed txs conflict with a confirmed tx. None of the unconfirmed txs should appear in the list methods.
  • B and B' conflict. C spends B. B' is anchored in best chain. B and C should not appear in the list methods.
  • B and B' conflict. C spends B. B is anchored in best chain. B' should not appear in the list methods.
  • B and B' conflict. C spends both B and B'. C is impossible.
  • B and B' conflict. C spends both B and B'. C is impossible. B' is confirmed.
  • B and B' conflict. C spends both B and B'. C is impossible. D spends C.

These tests revealed that TxGraph::walk_conflicts was not checking ancestors of the root tx for conflicts. TxGraph::walk_conflicts has been refactored to check for conflicting ancestor transactions by using a new TxAncestors iterator in TxGraph.

Changelog notice

  • Introduced tx_template module
  • Introduced TxGraph::TxAncestors iterator
  • Refactored TxGraph::walk_conflicts to use TxGraph::TxAncestors
  • Added walk_ancestors to TxGraph

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature

Copy link
Member

@evanlinjin evanlinjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this, glad to see the progress. Just some comments!

crates/chain/tests/common/tx_template.rs Outdated Show resolved Hide resolved
crates/chain/tests/test_indexed_tx_graph.rs Outdated Show resolved Hide resolved
crates/chain/tests/test_indexed_tx_graph.rs Outdated Show resolved Hide resolved
@LagginTimes LagginTimes force-pushed the tx_conflict_tests branch 2 times, most recently from d112807 to 83c92b6 Compare August 11, 2023 10:06
@LagginTimes LagginTimes force-pushed the tx_conflict_tests branch 3 times, most recently from ce6cb40 to 67d9a5e Compare August 14, 2023 10:59
@LagginTimes LagginTimes force-pushed the tx_conflict_tests branch 3 times, most recently from af19b5a to 238f0f1 Compare August 17, 2023 09:50
@evanlinjin
Copy link
Member

Please rebase on master to fix the CI.

@LagginTimes LagginTimes force-pushed the tx_conflict_tests branch 2 times, most recently from 112e851 to b00b406 Compare August 22, 2023 09:27
@danielabrozzoni
Copy link
Member

I'll ACK this once we fix the commit messages.

In case you have never done that, https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History can be of help :)

@LagginTimes LagginTimes force-pushed the tx_conflict_tests branch 3 times, most recently from 7340a41 to 452627d Compare September 15, 2023 14:31
Copy link
Member

@evanlinjin evanlinjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 452627d

Copy link
Contributor

@LLFourn LLFourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @LagginTimes. I've pointed out what I think is a bug that I think should be fixed here. The other things I've identified I leave to you to resolve them here or we can do it in follow up work.

The key things we should (eventually) resolve are:

  1. The worst case time complexity of the algorithm to determine whether a single tx is in the chain is roughly linear in the number of unconfirmed transactions. If we are determining whether a bunch of txouts are in the chain and every unconfirmed tx has one this means it's quadratic. I fear by peppering the mempool with a bunch of unconfirmed txs and RBFing them a lot you could denial of service attack systems using this algorithm.
  2. I think it'd be better if TxDescendents and TxAncestors should be proximity to the root txid in the graph. The current order is depth first and at what "depth" the node is visited at depends on the order of the outputs or inputs that are being traversed. The iterator can give a depth of 7 to a tx that has a direct relationship to the root tx.

crates/chain/src/tx_graph.rs Show resolved Hide resolved
crates/chain/src/tx_graph.rs Outdated Show resolved Hide resolved
crates/chain/src/tx_graph.rs Outdated Show resolved Hide resolved
crates/chain/src/tx_graph.rs Outdated Show resolved Hide resolved
crates/chain/src/tx_graph.rs Show resolved Hide resolved
crates/chain/src/tx_graph.rs Outdated Show resolved Hide resolved
@danielabrozzoni
Copy link
Member

As discussed with @evanlinjin, I'm picking this up as it's high priority :)

danielabrozzoni and others added 4 commits October 3, 2023 11:25
Co-authored-by: Wei Chen <wzc110@gmail.com>
This commit also changes test_descendants_no_repeat to check
the order of the transactions returned
Co-authored-by: Wei Chen <wzc110@gmail.com>
Co-authored-by: Wei Chen <wzc110@gmail.com>
Copy link
Member

@danielabrozzoni danielabrozzoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed df1ee4f:

  • Rewrite commit history
  • Fix review comments

As a part of fixing the review comments I added a scenario in test_tx_graph_conflicts, I just wanted to say @LagginTimes, the Scenario/TxTemplate mechanism is super convenient! Good job :)

crates/chain/src/tx_graph.rs Outdated Show resolved Hide resolved
crates/chain/src/tx_graph.rs Show resolved Hide resolved
crates/chain/src/tx_graph.rs Outdated Show resolved Hide resolved
},
],
// B and C should not appear in the list methods
exp_chain_txs: HashSet::from(["A", "B'"]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't what we want to happen here is that B and C are canonical?

C has the more recent last seen which should transitively mean that B is chosen over B' . In other words the effective last_seen of a node is the max of all its descendants.

This PR at least makes the answer consistent but it seems we are actually asserting suboptimal behavior here. Can be done in a follow up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to give a bit of context, my reasoning behind this was: how would a node react if it saw B, then B', then C? And I think it would go like:

  • B: fine, I'll keep this
  • B': fine, I'll keep this, and drop B
  • C: I'll drop this, as it's spending B, which I dropped already

Which I don't know if it's coherent with the rest of the txgraph and the last_seen logic (it probably isn't).

Anyways, I just pushed a fix, it should be fine now :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which I don't know if it's coherent with the rest of the txgraph and the last_seen logic (it probably isn't).

Indeed. TxGraph is montone so doesn't record the order of things entering into it. Our conflict resolution mechanism is last_seen so I think we should take whichever subgraph has the tx with the latest one. Hopefully we can make this efficient!

Copy link
Contributor

@LLFourn LLFourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

danielabrozzoni and others added 5 commits October 4, 2023 14:00
...try_get_chain_pos

In try_get_chain_pos, when we notice that a transaction is not included
in the best chain, we check the transactions in mempool to find
conflicting ones, and decide based on that if our transaction is still
in mempool or has been dropped.
This commit adds a check for transactions conflicting with the
unconfirmed ancestors of our tx.

Co-authored-by: Wei Chen <wzc110@gmail.com>
Co-authored-by: Wei Chen <wzc110@gmail.com>
Co-authored-by: Wei Chen <wzc110@gmail.com>
Co-authored-by: Wei Chen <wzc110@gmail.com>
Co-authored-by: Wei Chen <wzc110@gmail.com>
Copy link
Member

@evanlinjin evanlinjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 6d601a7

Thanks @danielabrozzoni for taking this forward and @LagginTimes for the initial work.

@evanlinjin evanlinjin merged commit 4ee11aa into bitcoindevkit:master Oct 5, 2023
12 checks passed
@notmandatory notmandatory mentioned this pull request Oct 11, 2023
12 tasks
danielabrozzoni added a commit that referenced this pull request Nov 9, 2023
afbf83c chain(fix): conflict resolution for txs with same last_seen (Wei Chen)

Pull request description:

  ### Description

  Fixes #1102. If a conflicting tx has the same `last_seen`, then we check lexicographical sorting of txids.

  ### Notes to the reviewers

  The tests for this fix exist in the `TxTemplate` structure in #1064 which may need to be merged first.

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

ACKs for top commit:
  danielabrozzoni:
    ACK afbf83c

Tree-SHA512: 91b8fbff305b715247501b861ab7ea9e9d9ef99248b05d14e01aacf7e64ad7826f35773e8998cf421dbd04f663714026084c6e817ac5365bce4844c8ea3b7e3f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Better tests for transaction conflict handling.
7 participants