nSequence is not set when spending from satisfiable descriptor with relative timelock #31808

issue Randy808 openend this issue on February 6, 2025
  1. Randy808 commented at 0:36 am on February 6, 2025: contributor

    Is there an existing issue for this?

    • I have searched the existing issues

    Current behaviour

    While experimenting with miniscript expressions on regtest (on commit a43f08c4ae) with the cli, I imported a descriptor with the older fragment: wsh(and_v(v:older(2),pk(tprv8ZgxMBicQKsPe5EVQ3cw3S1GdWyKxTeVvgVujejwFgJYGPucrUyPhsR2Zd4ngq3QSfB4HehpXqSPtwdoV7b8JYunU2kPai1AWUUxvb5gkrf/84h/1h/0h/1/*)))#tcaf9v8u

    After sending money to an address made from this descriptor using sendtoaddress with an amount, I received the error message:

    0error code: -6
    1error message:
    2Signing transaction failed
    

    After stepping through the code in debug mode I found it was failing on the following line within CheckSequence: const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;

    This is because the nSequence on the input isn’t being set according to the value specified in older.

    The easy workaround to this is to use createrawtransaction and manually set nSequence

    Expected behaviour

    The expected behavior is a transaction is made with the descriptor-locked input. I’m split between labeling this as a bug or feature request, but chose to file as a bug because the wallet has everything it needs to spend the input. Please reclassify this as a feature request if you do find it fits better with that label.

    Steps to reproduce

    • Create a new wallet
    • Import the descriptor and derive an address:
    0export desc="wsh(and_v(v:older(2),pk(tprv8ZgxMBicQKsPe5EVQ3cw3S1GdWyKxTeVvgVujejwFgJYGPucrUyPhsR2Zd4ngq3QSfB4HehpXqSPtwdoV7b8JYunU2kPai1AWUUxvb5gkrf/84h/1h/0h/1/*)))#tcaf9v8u"
    1export descriptors="[{\"desc\":\"$desc\",\"timestamp\":\"now\"}]"
    2b importdescriptors $descriptors
    3b deriveaddresses $desc "[1,1]"
    
    • Send money to the generated address from another wallet
    • Generate 3 blocks
    • Switch back to the wallet with the above descriptor and try to send funds out

    Relevant log output

    No response

    How did you obtain Bitcoin Core

    Compiled from source

    What version of Bitcoin Core are you using?

    master@a43f08c4ae

    Operating system and version

    Ubuntu

    Machine specifications

    No response

  2. sipa commented at 4:32 pm on February 6, 2025: member

    We discussed this a bit off-line.

    There are a number of issues here, and the simple ones can be solved in specialized cases, but the general problem is really a sign of a deeper issue.

    The superficial problems are at least these, which stem from the specific order decisions are made: (1) coin selection, (2) transaction building, (3) input signing.

    • Coin selection may be picking coins which are not (yet) spendable (assuming the intent is to spend right now, and not something to be presigned and broadcast later).
    • Fees may be too wrong because a different spending path is expected to be used at coin selection time then the one actually signed for (which has a different weight), see also #26573.
    • Transaction building may be setting nLockTime / nSequence values which aren’t actually compatible with what we can sign for.

    In the “simple” case, where the signing keys are part of the wallet doing coin selection and transaction building itself, this is in theory solvable (for the locktime/sequence part at least a default could be provided based on the selected coins, but it may still need to be overridden for transactions intended to be broadcast later). I do wonder how common these cases are, though; I expect that most situations that involve multiple branches, locktimes, … also involve multiple parties. Can you elaborate on your use case?

    The more fundamental issue, I think, is that the descriptors-centric structuring of the wallet isn’t well-equiped to reason about “which keys/spending paths/… will be available at signing time”. It offers a way to derive a set of scriptPubKeys to watch (“we may have access to a group of participants/wallets which together can spend these coins, but unsure how”) and a way to actually sign after coin-selection and transaction building is already complete.

    But in the general case, one would need a way to provide additional information, in the wallet, or at transaction building time, about which signers/keys one expects the be available. With that information, coin selection can avoid coins which aren’t spendable by those parties, locktimes/sequences can be set appropriately for those coins, and fee estimation can be done more correctly. This feels like something wallet policies are more appropriate for, which are not implemented in Bitcoin Core.

  3. darosior commented at 5:06 pm on February 6, 2025: member

    I have searched the existing issues

    Hmm #27527. :)

    Transaction building may be setting nLockTime / nSequence values which aren’t actually compatible with what we can sign for.

    To add to this, the coin selection algorithm right now may even be selecting coins that are incompatible with each other: #27526.

  4. Randy808 commented at 9:25 pm on February 6, 2025: contributor
    @sipa My original usecase was a decaying multisig using thresh like your “A 3-of-3 that turns into a 2-of-3 after 90 days” example on https://bitcoin.sipa.be/miniscript/ except I was doing a 2-of-2 that turned into a 1-of-2. In this case my wallet would have one of the private keys available at the time of spending with the older clause met. Also, to re-iterate, I can still spend the utxo if I construct the transaction using createrawtransaction, signrawtransactionwithwallet, and sendrawtransaction given I set a compatible sequence value for the input in createrawtransaction. @darosior For the record, #27527 title scopes it to coin selection while this problem falls into the 3rd point “Transaction building may be setting nLockTime / nSequence values which aren’t actually compatible with what we can sign for.” The wallet I’m using is full of spendable utxos and the amounts associated with my attempted spend could be satisfied by any one of them.

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-14 12:13 UTC

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