Skip to content

wallet, rpc: add anti-fee-sniping to send and sendall #28944

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ishaanam
Copy link
Contributor

Currently, send and sendall don't do anti-fee-sniping because they don't use CreateTransaction. This PR adds anti-fee-sniping to these RPCs by calling DiscourageFeeSniping from FinishTransaction when the user does not specify a locktime.

@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 26, 2023

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

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/28944.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK S3RK, Sjors
Stale ACK achow101, murchandamus

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:

  • #32857 (wallet: allow skipping script paths by Sjors)

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.

LLM Linter (✨ experimental)

Possible typos and grammar issues:

  • In spend.h doc comment: missing closing parenthesis
    Original: “…unless we are not synced with the current chain”
    Should be: “…unless we are not synced with the current chain)” [closes the parenthetical]

drahtbot_id_4_m

@S3RK
Copy link
Contributor

S3RK commented Nov 27, 2023

Concept ACK

@achow101
Copy link
Member

ACK 5c9ac14

A test for send would be nice as well.

@DrahtBot DrahtBot requested a review from S3RK November 28, 2023 15:24
@ishaanam ishaanam force-pushed the sendall_anti_fee_sniping branch from 5c9ac14 to 5101f05 Compare November 29, 2023 15:12
@ishaanam
Copy link
Contributor Author

A test for send would be nice as well.

Done

@ishaanam ishaanam force-pushed the sendall_anti_fee_sniping branch from 5101f05 to f348ead Compare December 4, 2023 23:41
Copy link
Member

@achow101 achow101 left a comment

Choose a reason for hiding this comment

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

ACK f348ead

Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

Concept ACK and almost crACK d76f880 except that there seems to be a type mix-up:

 wallet/rpc/spend.cpp:1299:20: error: no matching function for call to 'FinishTransaction'
            return FinishTransaction(pwallet, options, CMutableTransaction(*txr.tx));
                   ^~~~~~~~~~~~~~~~~
wallet/rpc/spend.cpp:79:17: note: candidate function not viable: expects an lvalue for 3rd argument
static UniValue FinishTransaction(const std::shared_ptr<CWallet> pwallet, const UniValue& options, CMutableTransaction& rawTx)
                ^
1 error generated.

@ishaanam ishaanam force-pushed the sendall_anti_fee_sniping branch from d76f880 to c8de459 Compare December 27, 2023 20:19
@ishaanam
Copy link
Contributor Author

Fixed silent merge conflict.

Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

ACK c8de459

@ishaanam
Copy link
Contributor Author

--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -293,6 +293,7 @@ class ImportRescanTest(BitcoinTestFramework):
                 add_to_wallet=False,
                 inputs=[unspent_txid_map[variant.initial_txid]],
                 outputs=[{ADDRESS_BCRT1_UNSPENDABLE : variant.initial_amount}],
+                locktime=0,
                 subtract_fee_from_outputs=[0]
             )
             variant.child_txid = child["txid"]

Done

It seems that you may have been working on an update, but it might not have been pushed. Is that possible?

I pushed this change, but I had forgotten to comment until later.

}

if (can_anti_fee_snipe) {
LOCK(pwallet->cs_wallet);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not clear why do we need a wallet lock here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here the wallet is locked because it runs CWallet::GetLastBlockHash and CWallet::GetLastBlockHeight which both require pwallet->cs_wallet to be locked.

@ishaanam ishaanam force-pushed the sendall_anti_fee_sniping branch from fa1fa35 to b11d00d Compare June 27, 2024 19:06
luke-jr pushed a commit to bitcoinknots/bitcoin that referenced this pull request Aug 1, 2024
…niping is compatible with transaction

Currently DiscourageFeeSniping will assert unless sequences are all either MAX_SEQUENCE_NONFINAL or MAX_BIP125_RBF_SEQUENCE.

Github-Pull: bitcoin#28944
Rebased-From: 6825ae0
luke-jr pushed a commit to bitcoinknots/bitcoin that referenced this pull request Aug 1, 2024
Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

crACK b11d00d

Comment on lines +1309 to +1343
CMutableTransaction tx = CMutableTransaction(*txr.tx);
return FinishTransaction(pwallet, options, tx);
Copy link
Contributor

Choose a reason for hiding this comment

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

It’s not clear to me why this change was made. It does not seem to be affecting function, is this just for readability?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because FinishTransaction now takes a CMutableTransaction& instead of a const CMutableTransaction&, we can't give it an rvalue.

@DrahtBot
Copy link
Contributor

Needs rebase, if still relevant.

@murchandamus
Copy link
Contributor

Hey @ishaanam, I noticed that this PR was rebased, but it is still set to Draft. Should this be marked as ready for review?

@Sjors
Copy link
Member

Sjors commented Jul 9, 2025

Concept ACK. Discovered this after I tried to implement it myself in #32892 :-)

I might be useful to borrow the idea from 642e4b6 of renaming DiscourageFeeSniping to MaybeDiscourageFeeSniping. Right now the code that decides whether to do this is duplicated between FinishTransaction and CreateTransactionInternal. Both places look at coin_control.m_locktime and loop through the inputs, but implemented in slightly different ways.

In wallet_send.py it would be useful to check that a generated PSBT has the correct lock time (you could use either set psbt or use a watch-only wallet which always produces a PSBT).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants