Incorrect balance when dealing with coinbase UTXOs that will be mature on h + 1 #32098

issue luisschwab openend this issue on March 19, 2025
  1. luisschwab commented at 6:58 pm on March 19, 2025: contributor

    Bitcoin Core is reporting the wrong balance when dealing with coinbase UTXOs that will become mature on the next block.

    Scenario: On regtest, I mine 101 blocks. Since coinbase maturity height is 100 blocks, I have 1 mature UTXO (50 BTC) at height 101. However, at height 102, another coinbase UTXO (50 BTC) will have matured and will be accepted by the mempool as an input to a transaction. Therefore, my spendable balance at height 102 will be 50+50 BTC (2 UTXOs available for selection).

    Currently, only a the first coin (50 BTC) is available for selection.

    I first discovered this when doing (manual) differential testing between BDK and Bitcoin Core (see https://github.com/bitcoindevkit/bdk/issues/1878).

  2. luisschwab renamed this:
    Incorrect balance when dealing with coinbase UTXOs that will be mature on _h_ + 1
    Incorrect balance when dealing with coinbase UTXOs that will be mature on `h + 1`
    on Mar 19, 2025
  3. maflcko added the label Wallet on Mar 19, 2025
  4. luisschwab commented at 7:20 pm on March 19, 2025: contributor

    Apparently this is a simple fix:

     0scr/wallet/wallet.cpp
     1
     2int CWallet::GetTxBlocksToMaturity(const CWalletTx& wtx) const
     3{
     4    AssertLockHeld(cs_wallet);
     5
     6    if (!wtx.IsCoinBase()) {
     7        return 0;
     8    }
     9    int chain_depth = GetTxDepthInMainChain(wtx);
    10    assert(chain_depth >= 0); // coinbase tx should not be conflicted
    11-   return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
    12+   return std::max(0, COINBASE_MATURITY - chain_depth); 
    13}
    
  5. maflcko commented at 7:26 pm on March 19, 2025: member
    I presume this was last touched in commit bf3a20a6e8cafdf723ef101af078df303ea06fec, which explains that there may be a race condition where the transaction is rejected, because the 100th block has not been relayed yet to the peer when the transaction is sent.
  6. maflcko commented at 3:19 pm on March 20, 2025: member
    So I guess this can be closed, or the code could be updated with the rationale as docs?
  7. luisschwab commented at 3:54 pm on March 20, 2025: contributor
    Shouldn’t these be separate concerns (transaction building and transaction broadcasting)?
  8. maflcko commented at 4:13 pm on March 20, 2025: member
    The wallet generally is a bit conservative when it comes to creating transactions that may not propagate well. (For example, it doesn’t yet offer fullrbf bumps). Of course, anyone is free to manually create the wanted transaction early and propagate it manually.
  9. luisschwab commented at 5:17 pm on March 20, 2025: contributor
    I understand that, but I think the wallet should strive for correctness, given we’re dealing with coinbase UTXOs which only knowledgeable people have access to (miners and developers). This is an edge case regular users won’t ever experience outside of test networks, myself included.
  10. sipa commented at 5:23 pm on March 20, 2025: member
    @luisschwab Well it’s not incorrect to be conservative. And if regular users don’t experience it, why does it matter at all?
  11. luisschwab commented at 5:33 pm on March 20, 2025: contributor
    I don’t think not being able to select an otherwise spendable UTXO is correct.
  12. instagibbs commented at 4:26 pm on March 25, 2025: member
    re:propagation, do we not have the same race condition on most wallet made transactions due to the anti fee sniping logic?

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: 2025-03-28 15:12 UTC

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