wallet: limit anti fee sniping locktime backdating when spending unconfirmed UTXOs #34449

pull danielabrozzoni wants to merge 4 commits into bitcoin:master from danielabrozzoni:issue/26527-dont-backtime-nlocktime-unconf changing 6 files +75 −7
  1. danielabrozzoni commented at 4:19 pm on January 29, 2026: member

    Fixes #26527

    The Bitcoin Core wallet implements an anti fee sniping mechanism that sets a transaction’s nLockTime to the current block height, and occasionally to an earlier height.

    When the wallet spends unconfirmed UTXOs, this logic can currently choose a locktime for the child transaction that is earlier than the locktime of its unconfirmed parent. This creates an unrealistic “transaction signed earlier but only broadcast now” scenario and may act as a wallet fingerprint.

    This PR fixes the issue by preventing a transaction’s nLockTime from being set to a value earlier than the nLockTime of any unconfirmed parent. This is done by passing a minimum nLockTime to DiscourageFeeSniping when spending unconfirmed inputs, set to the maximum nLockTime of the unconfirmed parents, or 0 if there are none.

    DiscourageFeeSniping is currently invoked by the following RPCs:

    • sendall
    • send
    • sendtoaddress
    • sendmany
    • fundrawtransaction
    • walletcreatefundedpsbt

    Tests are added for this behavior for the sendall and send RPCs. These are the only RPCs that can hit this case, since sendtoaddress and sendmany don’t spend unconfirmed inputs, and fundrawtransaction and walletcreatefundedpsbt don’t apply fee sniping (instead, they always set nLockTime to 0 unless explicitly provided by the user).

    You can cherry-pick the two commits adding tests on master and see them intermittently failing (this might take a couple of re-tries to see).

  2. DrahtBot added the label Wallet on Jan 29, 2026
  3. danielabrozzoni force-pushed on Jan 29, 2026
  4. DrahtBot commented at 4:19 pm on January 29, 2026: contributor

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

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    LLM Linter (✨ experimental)

    Possible places where comparison-specific test macros should replace generic comparisons:

    • test/functional/wallet_create_tx.py “assert 101 <= tx[’locktime’] <= 201” -> Replace bare assert with test helpers. E.g.:
      • assert_greater_than_or_equal(tx[’locktime’], self.nodes[0].getblockcount() - 100)
      • (and if available) assert_less_than_or_equal(tx[’locktime’], self.nodes[0].getblockcount() + 100)

    No other comparison macro suggestions were found.

    2026-01-29 16:43:32

  5. DrahtBot added the label CI failed on Jan 29, 2026
  6. danielabrozzoni force-pushed on Jan 29, 2026
  7. wallet: don't back-date locktime when spending unconfirmed UTXOs
    When the wallet spends unconfirmed UTXOs, the anti fee sniping logic
    in DiscourageFeeSniping might choose a nlocktime for the transaction
    that is earlier than the nlocktime in the unconfirmed parent(s). This
    behavior makes the scenario "transaction signed earlier but only broadcast now"
    unrealistic, and may act as a wallet fingerprint.
    
    This is fixed by adding a `min_locktime` parameter to `DiscourageFeeSniping` and
    preventing backdating before that value. When calling
    `DiscourageFeeSniping`, the minimum locktime is set to the maximum nLockTime
    of all unconfirmed parents, or 0 if there are none.
    
    Co-Authored-By: ishaanam <ishaana.misra@gmail.com>
    589a445174
  8. test: assert anti-fee-sniping locktime is within 100 blocks
    The previous assertion only verified that nLockTime was non-zero.
    Tighten the check to ensure the locktime is within the allowed range,
    up to 100 blocks in the past.
    6b18707d12
  9. test: check send RPC does not backdate locktime for unconfirmed inputs f2736a2a79
  10. test: check sendall RPC does not backdate locktime for unconfirmed inputs 5f5a041fe2
  11. danielabrozzoni force-pushed on Jan 29, 2026
  12. danielabrozzoni renamed this:
    wallet: don’t backdate locktime when spending unconfirmed UTXOs
    wallet: limit anti fee sniping locktime backdating when spending unconfirmed UTXOs
    on Jan 29, 2026
  13. danielabrozzoni commented at 4:58 pm on January 29, 2026: member
    I realized this needs a bit more polishing, closing for now
  14. danielabrozzoni closed this on Jan 29, 2026


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-02-11 18:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me