-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Remove ResendWalletTransactions from the Validation Interface #15632
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
Conversation
Depends on #10973 |
Obviously requires careful testing. We don't currently have any automated testing for wallet rebroadcasts (
|
Marking WIP until automated tests are written |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
This seems to add a lot of lines of code for something intended to be a simplification? |
Only the last 3 commits are relevant here. The first 4 commits come from #10973 which would conflict with this PR, so John chose it as a base, but is actually independent. This PR could just as easily be based on master. |
05af37e
to
80f698a
Compare
Indeed. It didn't make sense to make or review changes in the node<->wallet interface while Russ's PR was open. It's merged now so I've rebased on master. Changes are now +28/-35 |
80f698a
to
012c7d2
Compare
Tests added. See #15646 . Removing WIP tag. |
012c7d2
to
3e7bea5
Compare
Rebased on the updated #15646 (please leave review comments for the test in that PR) |
The test is currently unreliable for me. I think there's a bad interaction between using mocktime and the scheduler thread scheduling tasks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 3e7bea5. I don't feel like I know CScheduler
and SendMessages()
code well enough to be extremely confident that this change doesn't break anything, but assuming CWallet::ResendWalletTransactions()
is still called when it needs to be called, everything else looks correct to me and the changes are a nice simplification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 3e7bea5
SendMessages
is called for every "active" peer after a sleep of 1000ms, so if the scheduler does it for the wallets once every 1000ms, that should still be more than sufficient.
src/wallet/wallet.cpp
Outdated
@@ -2138,8 +2138,13 @@ std::vector<uint256> CWallet::ResendWalletTransactionsBefore(interfaces::Chain:: | |||
return result; | |||
} | |||
|
|||
void CWallet::ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime) | |||
// Resend wallet transactions that haven't gotten in a block yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Resend wallet transactions that haven't gotten in a block yet | |
// Resend wallet transactions that haven't gotten in a block yet; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just moved this comment from net_processing, but you're right that I should also improve it. Done!
src/wallet/wallet.cpp
Outdated
void CWallet::ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime) | ||
// Resend wallet transactions that haven't gotten in a block yet | ||
// Except during reindex, importing and IBD, when old wallet | ||
// transactions become unconfirmed and spams other nodes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// transactions become unconfirmed and spams other nodes. | |
// transactions become unconfirmed and spam other nodes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC before this change ResendWalletTransactionsBefore
could be called more frequently than once per second.
But considering
Lines 2152 to 2155 in 656a15e
// Only do it if there's been a new block since last time | |
if (nBestBlockTime < nLastResend) | |
return; | |
nLastResend = GetTime(); |
It would wait for a new block to resend wallet transactions.
So I don't see a reason to not increase the scheduler period from 1 second to, for instance, 1 minute?
Edit: maybe the reason is to rush for the next block?
utACK 3e7bea5, I think this is a valid refactor: remove Broadcast
signal from SendMessages
and related cleanup.
src/wallet/wallet.cpp
Outdated
// Get the best block time | ||
auto locked_chain = chain().lock(); | ||
Optional<int> tip_height = locked_chain->getHeight(); | ||
int64_t best_block_time = tip_height ? locked_chain->getBlockTime(*tip_height) : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On further thoughts on this, it seems brittle to use the time the miner decided to put in the block header as opposed to our local time, which at least can be assumed to be monotonic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right that we should use the local time of the block received, but only in order to maintain existing behaviour.
Can you explain how using block time would be brittle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will hurt privacy even for tx that have a sufficient fee to get into the next block (+5 min). They will be rebroadcast regardless because a miner might have set the the block time to at least 5 minutes into the future.
Similarly, if the block time is set into the past, you might not rebroadcast transactions for quite some time, even if a block has been mined without your txs in the meantime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really following how this is any worse for privacy, but I've reverted to using the local time of the tip being updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not consistently worse, but in some race-conditions, one of which is enough to give an attacker useful observations
- Attacker opens a bunch of new connections to you
- You create tx with fee target of next block
- tx is broadcast (attacker sees it)
- less than 5 minutes pass, enough to mine a new block, but not enough to propagate the tx to miners
- A block is mined with a timestamp of 60 min in the future, without your tx
- Attacker sees the new block and opens a bunch of new connections to you
- previous random wait in ResendWalletTransactions times out
- we send the tx again to the attacker (we wouldn't do this for non-wallet txs, nor if we used local
GetTime()
for the block time)
3e7bea5
to
930cfbe
Compare
Could add |
I don't understand this. How would this avoid using the schedule timer? |
@jnewbery untested, but see promag@afc7ac5. |
Thanks @promag . Your change is definitely a simplification, but I think it makes the already bad privacy of rebroadcasts even worse. Currently, wallet rebroadcasts are pretty bad for privacy: If you connect to a peer and they send you the same broadcast repeatedly, then it's their tx. Furthermore, they'll send all of their txs together, so it's even easier to identify which txs are rebroadcast. The fact that we randomize when we rebroadcast transactions makes this slightly less bad. Your suggested change would be to only rebroadcast your wallet txs immediately after receiving a block. That would pretty obviously identify which txs are yours. Ways we could improve rebroadcast privacy:
|
I think I don't change the behavior? |
Your change would mean that wallet txs are only ever rebroadcast immediately after a block is received. In the existing code, and in this PR, wallet txs are rebroadcast at random times. |
…llet Summary: Move nTimeBestReceived (which is only used for wallet rebroadcasts) into the wallet. bitcoin/bitcoin@f463cd1 --- Depends on D5947 This is a partial backport of Core [[bitcoin/bitcoin#15632 | PR15632]] Test Plan: cmake .. -GNinja ninja check check-functional Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D5948
Summary: Removes the now-unused Broadcast/ResendWalletTransactions interface from validationinterface. The wallet_resendwallettransactions.py needs a sleep added at the start to make sure that the rebroadcast scheduler is warmed up before the next block is mined. bitcoin/bitcoin@52b760f --- This is a partial backport of Core [[bitcoin/bitcoin#15632 | PR15632]] Test Plan: cmake .. -GNinja -DENABLE_WERROR=ON ninja check-all Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D6031
…om ResendWalletTransactions Summary: bitcoin/bitcoin@833d98a --- This completes the backport of Core [[bitcoin/bitcoin#15632 | PR15632]] Test Plan: cmake .. -GNinja -DENABLE_WERROR=ON ninja check-all Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D6032
7a9046e [wallet] Refactor CWalletTx::RelayWalletTransaction() (John Newbery) Pull request description: Refactor `CWalletTx::RelayWalletTransaction()` function. This was a suggestion from the wallet-node separation PR: bitcoin#15288 (comment), which we deferred until after the main PR was merged. There are also makes two minor behavior changes: - no longer assert if fBroadcastTransactions is false. Just return false from the function. - no longer print the relay message if p2pEnabled is set to false (since the transaction is not actually relayed). ACKs for commit 7a9046: promag: utACK 7a9046e. MeshCollider: utACK bitcoin@7a9046e ryanofsky: utACK 7a9046e. No changes at all, just rebase after base PR bitcoin#15632 was merged Tree-SHA512: 2ae6214cfadd917a1b3a892c4277e5e57c3eb791e17f67511470e6fbc634d19356554b9f9c55af6b779fdef821914aad59b7cc9e6c13ece145df003bf507d486
7a9046e [wallet] Refactor CWalletTx::RelayWalletTransaction() (John Newbery) Pull request description: Refactor `CWalletTx::RelayWalletTransaction()` function. This was a suggestion from the wallet-node separation PR: bitcoin#15288 (comment), which we deferred until after the main PR was merged. There are also makes two minor behavior changes: - no longer assert if fBroadcastTransactions is false. Just return false from the function. - no longer print the relay message if p2pEnabled is set to false (since the transaction is not actually relayed). ACKs for commit 7a9046: promag: utACK 7a9046e. MeshCollider: utACK bitcoin@7a9046e ryanofsky: utACK 7a9046e. No changes at all, just rebase after base PR bitcoin#15632 was merged Tree-SHA512: 2ae6214cfadd917a1b3a892c4277e5e57c3eb791e17f67511470e6fbc634d19356554b9f9c55af6b779fdef821914aad59b7cc9e6c13ece145df003bf507d486
7a9046e [wallet] Refactor CWalletTx::RelayWalletTransaction() (John Newbery) Pull request description: Refactor `CWalletTx::RelayWalletTransaction()` function. This was a suggestion from the wallet-node separation PR: bitcoin#15288 (comment), which we deferred until after the main PR was merged. There are also makes two minor behavior changes: - no longer assert if fBroadcastTransactions is false. Just return false from the function. - no longer print the relay message if p2pEnabled is set to false (since the transaction is not actually relayed). ACKs for commit 7a9046: promag: utACK 7a9046e. MeshCollider: utACK bitcoin@7a9046e ryanofsky: utACK 7a9046e. No changes at all, just rebase after base PR bitcoin#15632 was merged Tree-SHA512: 2ae6214cfadd917a1b3a892c4277e5e57c3eb791e17f67511470e6fbc634d19356554b9f9c55af6b779fdef821914aad59b7cc9e6c13ece145df003bf507d486
7a9046e [wallet] Refactor CWalletTx::RelayWalletTransaction() (John Newbery) Pull request description: Refactor `CWalletTx::RelayWalletTransaction()` function. This was a suggestion from the wallet-node separation PR: bitcoin#15288 (comment), which we deferred until after the main PR was merged. There are also makes two minor behavior changes: - no longer assert if fBroadcastTransactions is false. Just return false from the function. - no longer print the relay message if p2pEnabled is set to false (since the transaction is not actually relayed). ACKs for commit 7a9046: promag: utACK 7a9046e. MeshCollider: utACK bitcoin@7a9046e ryanofsky: utACK 7a9046e. No changes at all, just rebase after base PR bitcoin#15632 was merged Tree-SHA512: 2ae6214cfadd917a1b3a892c4277e5e57c3eb791e17f67511470e6fbc634d19356554b9f9c55af6b779fdef821914aad59b7cc9e6c13ece145df003bf507d486
7a9046e [wallet] Refactor CWalletTx::RelayWalletTransaction() (John Newbery) Pull request description: Refactor `CWalletTx::RelayWalletTransaction()` function. This was a suggestion from the wallet-node separation PR: bitcoin#15288 (comment), which we deferred until after the main PR was merged. There are also makes two minor behavior changes: - no longer assert if fBroadcastTransactions is false. Just return false from the function. - no longer print the relay message if p2pEnabled is set to false (since the transaction is not actually relayed). ACKs for commit 7a9046: promag: utACK 7a9046e. MeshCollider: utACK bitcoin@7a9046e ryanofsky: utACK 7a9046e. No changes at all, just rebase after base PR bitcoin#15632 was merged Tree-SHA512: 2ae6214cfadd917a1b3a892c4277e5e57c3eb791e17f67511470e6fbc634d19356554b9f9c55af6b779fdef821914aad59b7cc9e6c13ece145df003bf507d486
Remove the
Broadcast()
/ResendWalletTransactions()
notification from the Validation interface.Closes #15619. See that issue for discussion.