Skip to content

refactor: TxDownloadManager + fuzzing#30110

Merged
achow101 merged 29 commits intobitcoin:masterfrom
glozow:2024-05-txdownload
Oct 29, 2024
Merged

refactor: TxDownloadManager + fuzzing#30110
achow101 merged 29 commits intobitcoin:masterfrom
glozow:2024-05-txdownload

Conversation

@glozow
Copy link
Member

@glozow glozow commented May 15, 2024

Part of #27463.

This PR does 3 things:

(1) It modularizes transaction download logic into a TxDownloadManager. Transaction download logic refers to the process of deciding what transactions to request, download, and validate.[1] There should be no behavior changes. Using --color_moved=dimmed_zebra -w may help.
(2) It adds unit and fuzz (:magic_wand:) testing for transaction download.
(3) It makes a few small behavioral changes:

  • Stop (debug-only) logging tx invs during IBD
  • Just like all other transactions, require orphans have RecursiveDynamicUsage < 100k before adding to vExtraTxnForCompact
  • Don't return a 1p1c that contains a parent or child in recent rejects. Don't process any orphan already in recent rejects. These cases should not happen in actual node operation; it's just to allow tighter sanity checks during fuzzing.

There are several benefits to this interface, such as:

  • Unit test coverage and fuzzing for logic that currently isn't feasible to test as thoroughly (without lots of overhead) and/or currently only lightly tested through assert_debug_log (not good) in functional tests.
  • When we add more functionality (e.g. package relay messages, more robust orphan handling), the vast majority of it will be within TxDownloadManager instead of PeerManager, making it easier to review and test. See Package Relay 1/3: Introduce TxDownloadManager and improve orphan-handling #28031 for what this looks like.
  • PeerManager will no longer know anything about / have access to TxOrphanage, TxRequestTracker or the rejection caches. Its primary interface with TxDownloadManager would be much simpler:
    • Passing on ValidationInterface callbacks
    • Telling txdownloadman when a peer {connects, disconnects}
    • Telling txdownloadmanwhen a {transaction, package} is {accepted, rejected} from mempool
    • Telling txdownloadman when invs, notfounds, and txs are received.
    • Getting instructions on what to download.
    • Getting instructions on what {transactions, packages, orphans} to validate.
    • Get whether a peer HaveMoreWork for the ProessMessages loop
  • (todo) Thread-safety can be handled internally.

[1]: This module is concerned with tx download, not upload. It excludes transaction announcements/gossip which happens after we download/accept a transaction. Txreconciliation (erlay) is excluded from this module, as it only relates to deciding which invs to send or helping the other peer decide which invs to send. It is independent from this logic.

@DrahtBot
Copy link
Contributor

DrahtBot commented May 15, 2024

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK theStack, instagibbs, naumenkogs, achow101
Concept ACK l0rinc
Approach ACK ismaelsadeeq

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #30572 (Halt processing of unrequested transactions v2 by ariard)
  • #30538 (Doc: add a comment referencing past vulnerability next to where it was fixed by darosior)
  • #30116 (p2p: Fill reconciliation sets (Erlay) attempt 2 by sr-gi)
  • #29492 (refactor: Remove redundant definitions by Empact)
  • #27052 (test: rpc: add last block announcement time to getpeerinfo result by LarryRuane)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@glozow glozow force-pushed the 2024-05-txdownload branch from dc30dc1 to 1d9a82c Compare May 15, 2024 10:56
@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the
documentation.

Possibly this is due to a silent merge conflict (the changes in this pull request being
incompatible with the current code in the target branch). If so, make sure to rebase on the latest
commit of the target branch.

Leave a comment here, if you need help tracking down a confusing failure.

Debug: https://github.com/bitcoin/bitcoin/runs/24992798939

@glozow
Copy link
Member Author

glozow commented May 20, 2024

Rebased for #29817 and added a "ensure we can always download a tx as long as we have 1 good outbound peer" fuzz test

glozow added 22 commits October 24, 2024 21:23
These invs are ignored anyway, and this allows us to more easily move
the inv handling to TxDownloadManager in the next commit.
ProcessInvalidTx will return a PackageToValidate, so it needs to be
defined afterward.
…Compact

There does not appear to be any reason why orphan transactions should be
given special treatment.
Move-only. Also delete external RecentRejectsFilter() access since it is
no longer necessary.
Also delete external RecentRejectsReconsiderableFilter() access since it
is no longer necessary.
This is a slight behavior change: if a transaction is in both
reconsiderable rejects and AlreadyHaveTx in another way, we don't try to
return a 1p1c package. This is the correct thing to do, as we don't want
to reconsider transactions that have multiple things wrong with them.
For example, if a transaction is low feerate, and then later found to
have a bad signature, we shouldn't try it again in a package.
This should never happen normally, but just in case.
Avoid the fuzzer situation where:
1. Orphanage has 2 transactions with the same txid, one with witness,
   one without witness.
2. The transaction with witness is found to have
   `TX_INPUTS_NOT_STANDARD` error. The txid is added to recent rejects
filter, and the tx with witness is deleted from orphanage.
3. A low feerate parent is found. Find1P1CPackage finds the transaction
   with no witness in orphanage, and returns the package.
4. net_processing has just been handed a package in which the child is
   already in recent rejects.
Forward this bool to the TxRequestTracker ctor. This is needed for
stablity in TxDownloadManager fuzzers
The txdownload_impl is similar but allows us to check specific
invariants within its implementation. It will also change a lot more
than the external interface (txdownloadman) will, so we will add more to
this target later.
Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

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

ACK 0f4bc63

bool m_ignore_inv_txid;
bool m_ignore_inv_wtxid;

// Constructor. We are passing and casting ints because they are more readable in a table (see all_expected_results).
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Constructor. We are passing and casting ints because they are more readable in a table (see all_expected_results).
// Constructor. We are passing and casting ints because they are more readable in a table (see expected_behaviors).

Copy link
Member Author

Choose a reason for hiding this comment

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

Will fix if I retouch / in the next PR

Copy link
Member Author

Choose a reason for hiding this comment

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

picked up in #31190

Comment on lines +433 to +435
// Jump ahead in time
time += fuzzed_data_provider.PickValueInArray(TIME_SKIPS);
CheckInvariants(txdownload_impl, max_orphan_count);
Copy link
Contributor

Choose a reason for hiding this comment

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

is it intentional to do no backward jumps in time here? (in contrast to the txdownloadman fuzz test above)

Copy link
Member Author

Choose a reason for hiding this comment

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

Not intentional! I haven't tried negative yet.

Copy link
Member Author

Choose a reason for hiding this comment

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

added in #31190

Copy link
Member

@instagibbs instagibbs left a comment

Choose a reason for hiding this comment

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

reACK 0f4bc63

could use some fuzzing c @marcofleon

Copy link
Contributor

@naumenkogs naumenkogs left a comment

Choose a reason for hiding this comment

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

ACK 0f4bc63

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, so

/** New inv has been received. May be added as a candidate to txrequest. */ is inaccurate, right? There is no new INV received in p2p_inv=false case, but rather it's called from orphan consideration after processing a TX?

@marcofleon
Copy link
Contributor

Fuzzed the two targets for about 250 cpu hours each. Coverage looks good.
txdownloadman
txdownloadman_impl

Finally, the children hanging out in the recent reject filter are quiet 😌

I'll look to run the one honest peer test as well once it's ready.

@achow101
Copy link
Member

light ACK 0f4bc63

@glozow
Copy link
Member Author

glozow commented Oct 30, 2024

Thanks for the reviews. Working on the followups + one_honest_peer fuzzer PR now

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.