partial spend avoidance makes partial spends and getbalances doesn't notice #17603

issue dooglus opened this issue on November 25, 2019
  1. dooglus commented at 10:32 PM on November 25, 2019: contributor

    In v0.19.0.1, I'm running regtest, creating a wallet with avoid_reuse=true, generating 31 blocks in that wallet, then generating 100 more blocks to a throwaway address to have the rewards mature.

    Then I send 1 BTC to a throwaway address, expecting to see all 31 block rewards spent at once, but the resulting transaction only has 1 input. The other 30 rewards show as "reused":true when I listunspent, but when I run getbalances I see them showing us as trusted, not as used like I would expect.

    Here's a log:

    $ junk=mmmmmmmmmmmmmmmmmmmmmmmmmmmmq4S8nX
    $ alias bcr-'bitcoin-cli -regtest'
    $ alias bcrt='bcr -rpcwallet=test'
    $ bcr -named createwallet wallet_name=test avoid_reuse=true
    {
      "name": "test",
      "warning": ""
    }
    $ addr=$(bcrt getnewaddress)
    $ bcr generatetoaddress 31 $addr | wc -l # generate 31 rewards
    33
    $ bcr generatetoaddress 100 $junk | wc -l # let them mature
    102
    $ bcrt getbalances
    {
      "mine": {
        "trusted": 1550.00000000,
        "untrusted_pending": 0.00000000,
        "immature": 0.00000000,
        "used": 0.00000000
      }
    }
    $ txid=$(bcrt sendtoaddress $junk 1)
    # list the #confs for each input of the spend tx - note only one utxo was spent
    $ bcrt getrawtransaction $txid 1 | jq -r '.vin[] | .txid' | while read txid; do bcrt gettransaction $txid | jq -r .confirmations; done
    107
    # list the #confs for the unspent rewards - note the 107 conf utxo is missing
    $ echo $(bcrt listunspent | jq -cM '.[] | .confirmations' | sort)
    101 102 103 104 105 106 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    $ bcrt getbalances # but the 30 unspent rewards are still "trusted" not "used"
    {
      "mine": {
        "trusted": 1548.99996640,
        "untrusted_pending": 0.00000000,
        "immature": 0.00000000,
        "used": 0.00000000
      }
    }
    # although they show as "reused" in listunspent:
    $ bcrt listunspent 0 | jq -cM '.[] | {reused,amount,confirmations,spendable,address}' | sort | head -n 10
    {"reused":false,"amount":48.9999664,"confirmations":0,"spendable":true,"address":"2NAnHxL7tve4xnom7Y3f5747qzyFDEpP1Li"}
    {"reused":true,"amount":50,"confirmations":101,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":102,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":103,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":104,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":105,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":106,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":108,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":109,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    {"reused":true,"amount":50,"confirmations":110,"spendable":true,"address":"2Mww9FTTSMjc9HGsrc6swRVVzkNaus6SEMw"}
    $ 
  2. dooglus added the label Bug on Nov 25, 2019
  3. laanwj added the label Wallet on Nov 28, 2019
  4. fjahr cross-referenced this on Dec 29, 2019 from issue wallet: Prefer full destination groups in coin selection by fjahr
  5. fjahr commented at 1:50 PM on December 29, 2019: contributor

    Thank you for reporting this! I have suggested a fix for the issue related to coin selection and I will submit an improvement for getbalances as well.

  6. kallewoof commented at 5:31 AM on December 31, 2019: member

    The reason why you are only seeing one single input is because you are creating exactly 31 outputs. The code will create up to 10 size groups for a single destination, to avoid inadvertently creating massive transactions.

    In your case, you will receive groups of 10, 10, 10, and 1 UTXO. The last one will obviously result in the most efficient transaction as it is 10x smaller than the others.

    Unfortunately, this results in 1499 btc being marked as dirty in this particular case, but I don't believe this is particularly common in the wild. It is not ideal for a regtest with avoidreuse enabled, though, that's for sure.

    To see what I mean, change the 31 to 30 in your initial generate to $addr, then txid should give a tx with 10 inputs, not 1.

  7. kallewoof cross-referenced this on Dec 31, 2019 from issue test: test the >10 UTXO case for output groups by kallewoof
  8. dooglus commented at 3:11 PM on December 31, 2019: contributor

    It has been a while since I reported this, but wasn't the point to defeat chain analysis companies that spam our wallets with dust? If so, those companies can spam us with 10 pieces of dust per address to trigger this issue.

    I used regtest because it's quicker and cheaper than doing the same thing on mainnet but I think the result would be the same whichever network I used wouldn't it?

    Either way, having the remaining balance show up as "trusted" when it should show as "used" seems wrong to me.

  9. fjahr commented at 3:55 PM on December 31, 2019: contributor

    It has been a while since I reported this, but wasn't the point to defeat chain analysis companies that spam our wallets with dust? If so, those companies can spam us with 10 pieces of dust per address to trigger this issue.

    It is not that easy. It works in your example only because the amount you send in the transaction is smaller than each one of the outputs in the destination (1 BTC < 50 BTC block reward). If you keep everything else the same and send 51 BTC instead of 1 BTC the transaction should have 10 inputs as intended. So the attack is still possible but it would be much more expensive because dust outputs would not be enough to be selected as the input in most normal transactions and, as you said, they would have to send at least 10 of them if the address had not been reused before. Essentially the chain analysis company would have to spam a used destination with 10 outputs and then hope that the wallet user sends a transaction that is smaller than each one of the 10 outputs and that then one of the 10 outputs is selected as the input.

    The other outputs are not showing up as "used" because cached values are used when that should not be the case. I am working on improving this.

  10. fjahr cross-referenced this on Jan 2, 2020 from issue wallet: Reset reused transactions cache by fjahr
  11. meshcollider closed this on Jan 15, 2020

  12. meshcollider reopened this on Jan 15, 2020

  13. sidhujag referenced this in commit a1b399c72d on Jan 15, 2020
  14. MarcoFalke commented at 4:14 PM on January 15, 2020: member

    What is left to do here?

  15. MarcoFalke commented at 4:15 PM on January 15, 2020: member

    Oh, #17824 is not yet merged

  16. meshcollider closed this on Apr 17, 2020

  17. sidhujag referenced this in commit 155d8bdac1 on Apr 17, 2020
  18. sidhujag referenced this in commit 6376dfd958 on Nov 10, 2020
  19. bitcoin locked this on Feb 15, 2022
  20. Munkybooty referenced this in commit a97979100a on Sep 6, 2022
  21. Munkybooty referenced this in commit ce23dd5119 on Sep 19, 2022
  22. Munkybooty referenced this in commit 531e6b5feb on Oct 3, 2022
  23. Munkybooty referenced this in commit e6879bbabd on Oct 13, 2022
  24. Munkybooty referenced this in commit 85ac0d7c32 on Oct 13, 2022
  25. Munkybooty referenced this in commit 3b125bf5a6 on Oct 17, 2022
  26. PastaPastaPasta referenced this in commit 3b5b8d0a94 on Oct 17, 2022
  27. vijaydasmp referenced this in commit 918ed363fe on May 6, 2023
  28. vijaydasmp referenced this in commit 02b7683a16 on Jul 2, 2023
  29. vijaydasmp referenced this in commit eec28cf50e on Jul 4, 2023
  30. vijaydasmp referenced this in commit c761f8e40f on Jul 4, 2023
  31. vijaydasmp referenced this in commit 9763181721 on Jul 5, 2023
  32. vijaydasmp referenced this in commit 43d85d92bf on Jul 7, 2023
  33. vijaydasmp referenced this in commit f8d5b4dc8a on Jul 7, 2023
  34. vijaydasmp referenced this in commit 1f865d8bb0 on Jul 9, 2023
  35. vijaydasmp referenced this in commit c99426ebda on Jul 9, 2023
  36. vijaydasmp referenced this in commit 7ca1c7173b on Jul 9, 2023
  37. vijaydasmp referenced this in commit 0890fa4ef3 on Jul 9, 2023
  38. vijaydasmp referenced this in commit eed2338bb4 on Jul 9, 2023
  39. vijaydasmp referenced this in commit 7f32149246 on Jul 9, 2023
  40. vijaydasmp referenced this in commit d9b4172b79 on Jul 10, 2023
  41. vijaydasmp referenced this in commit 3bea34b3fb on Jul 10, 2023
  42. vijaydasmp referenced this in commit 1a6e170aa6 on Jul 11, 2023
  43. vijaydasmp referenced this in commit 7ce581c0a9 on Jul 11, 2023
  44. vijaydasmp referenced this in commit fb1171f3ca on Jul 11, 2023
  45. vijaydasmp referenced this in commit 68783f8f8e on Jul 14, 2023
  46. vijaydasmp referenced this in commit 1beea14894 on Jul 14, 2023
  47. vijaydasmp referenced this in commit 3ada594521 on Jul 14, 2023
  48. vijaydasmp referenced this in commit 7fd204f709 on Jul 14, 2023
  49. vijaydasmp referenced this in commit 0681805825 on Jul 14, 2023
  50. vijaydasmp referenced this in commit 7b3b5cdd8c on Jul 17, 2023
  51. vijaydasmp referenced this in commit 9940196b22 on Jul 18, 2023
  52. vijaydasmp referenced this in commit 4370b5db33 on Jul 20, 2023
  53. vijaydasmp referenced this in commit ffc50f17dd on Jul 21, 2023
  54. PastaPastaPasta referenced this in commit f83b4bfdb3 on Jul 21, 2023

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-05-20 06:54 UTC