wallet: reject duplicate inputs in sendall #36344

pull Bruce039 wants to merge 1 commits into bitcoin:master from Bruce039:fix-sendall-duplicate-inputs changing 2 files +18 −0
  1. Bruce039 commented at 9:57 AM on September 26, 2026: none

    sendall with the inputs option doesn't check for duplicates. Each listed input is added to total_input_value in the loop at spend.cpp:1472, so passing the same UTXO twice counts its value twice.

    On regtest, with a wallet that has a single 1 BTC UTXO:

    sendall '["<addr>"]' '{"inputs": [<utxo>, <utxo>]}'
    
    • the RPC returns complete: true
    • the committed tx has 2 inputs (the same outpoint twice) and one output of 1.99998230 BTC
    • it isn't in the mempool, and testmempoolaccept rejects it with bad-txns-inputs-duplicate
    • after that, listunspent is empty and getbalances shows nonmempool: -1.0 until the tx is abandoned

    send and walletcreatefundedpsbt aren't affected, because CCoinControl::Select removes duplicates.

    This rejects a duplicated input with Invalid parameter, duplicated input: <txid>:<vout> (RPC_INVALID_PARAMETER). The message matches what createrawtransaction says for duplicated addresses. The new sendall_fails_on_duplicate_input test fails on master ("No exception raised") and passes with the fix. wallet_send.py still passes.

  2. DrahtBot added the label Wallet on Sep 26, 2026
  3. DrahtBot commented at 9:57 AM on September 26, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    ACK achow101
    Concept ACK l0rinc

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35302 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/35302.svg"></sub> (Silent Payments: Sending (take 2) by Eunovo)

    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.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. wallet: reject duplicate inputs in sendall
    sendall with the inputs option adds up the value of each listed input
    without checking for duplicates. When the same UTXO is given twice, the
    input value is counted twice, and the wallet builds, signs and commits
    a transaction that spends one outpoint twice and pays out twice its
    value. The RPC reports success, but the transaction is consensus-invalid
    (bad-txns-inputs-duplicate), and the coin disappears from listunspent
    until the transaction is abandoned.
    
    Reject duplicated inputs with an error, like createrawtransaction does
    for duplicated addresses.
    c46a0b34fd
  5. Bruce039 force-pushed on Sep 26, 2026
  6. DrahtBot added the label CI failed on Sep 26, 2026
  7. DrahtBot removed the label CI failed on Sep 26, 2026
  8. achow101 commented at 11:21 PM on September 29, 2026: member

    ACK c46a0b34fd06c874191cf880ba7082790b96c194

  9. in test/functional/wallet_sendall.py:257 in c46a0b34fd
     252 | +        utxo = self.wallet.listunspent()[0]
     253 | +
     254 | +        assert_raises_rpc_error(-8,
     255 | +                "Invalid parameter, duplicated input: {}:{}".format(utxo["txid"], utxo["vout"]),
     256 | +                self.wallet.sendall, recipients=[self.remainder_target], inputs=[utxo, utxo])
     257 | +        assert_equal(self.wallet.getbalances()["mine"]["untrusted_pending"], 0)
    


    l0rinc commented at 6:06 AM on October 18, 2026:

    The previous line correctly fails without the fix, but this assertion would pass before and after because the invalid transaction never enters the mempool - we should assert the affected wallet state instead.

    See my suggested alternative in https://github.com/l0rinc/bitcoin/pull/308/commits which demonstrates the full state transition by first characterizing the old behavior and then updating the expectations with the fix.

  10. l0rinc changes_requested
  11. l0rinc commented at 6:08 AM on October 18, 2026: contributor

    Concept ACK

    The RPC-error assertion catches the missing rejection, but we should cover the reported wallet-state correction also - see inline suggestion.


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-10-18 10:51 UTC

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