2

I'm attempting to create a P2SWH address with a script that locks the coins for some time. And then I want to spend those coins from that address.

I've read a lot, some of the most relevant:

These are the steps I've taken. Where am I going wrong?

  1. Create an address to be locked
bitcoin-cli -regtest -getnewaddress
bcrt1q45rq22tegkfu4sl9tfhty6svvkyaj6q4wu43fs
  1. Get the pubkey
bitcoin-cli -regtest getaddressinfo bcrt1q45rq22tegkfu4sl9tfhty6svvkyaj6q4wu43fs
{
  "address": "bcrt1q45rq22tegkfu4sl9tfhty6svvkyaj6q4wu43fs",
  "scriptPubKey": "0014ad060529794593cac3e55a6eb26a0c6589d96815",
  "ismine": true,
  "solvable": true,
  "desc": "wpkh([10304ad5/84'/1'/0'/0/0]0340469e0bd5cca35c04bcee20e203f8fe601b69d73793b493fe92900e620b67d8)#52elxezw",
  "parent_desc": "wpkh([10304ad5/84'/1'/0']tpubDDr5yrdp9CqDy4qv2Waa1Z5aeQUzQh4Rxs84XyT8vHXTNKEaR6rDhTY56sSYC4vBdbKj1fHbwEPuimcu1yY3RSN8u1RvSREdyAUEDmfWzFv/0/*)#82xg44pv",
  "iswatchonly": false,
  "isscript": false,
  "iswitness": true,
  "witness_version": 0,
  "witness_program": "ad060529794593cac3e55a6eb26a0c6589d96815",
  "pubkey": "0340469e0bd5cca35c04bcee20e203f8fe601b69d73793b493fe92900e620b67d8",
  "ischange": false,
  "timestamp": 1679657480,
  "hdkeypath": "m/84'/1'/0'/0/0",
  "hdseedid": "0000000000000000000000000000000000000000",
  "hdmasterfingerprint": "10304ad5",
  "labels": [
    ""
  ]
}
  1. Convert pubkey into pubkeyhash
echo -n 0340469e0bd5cca35c04bcee20e203f8fe601b69d73793b493fe92900e620b67d8 | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -rmd160
ad060529794593cac3e55a6eb26a0c6589d96815
  1. Get little-endian hex of timestamp for 1 March 2023 (1677628800)
printf '%x\n' 1677628800 | fold -w2 | tac | tr -d "\n"
8095fe63
  1. Create script using btcc from btcdeb
btcc 8095fe63 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 ad060529794593cac3e55a6eb26a0c6589d96815 OP_EQUALVERIFY OP_CHECKSIG
048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac
  1. Get ScriptHash
echo -n 048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac | xxd -r -p | openssl dgst -sha256
5ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb
  1. Decode script to check and get P2WSH (or could compute)
bitcoin-cli -regtest decodescript 048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac
{
  "asm": "1677628800 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 ad060529794593cac3e55a6eb26a0c6589d96815 OP_EQUALVERIFY OP_CHECKSIG",
  "desc": "raw(048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac)#snjtcwv8",
  "type": "nonstandard",
  "p2sh": "2N6zwcmxWbwkcVRwY275T8UXJ9mR9AtFaQo",
  "segwit": {
    "asm": "0 5ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb",
    "desc": "addr(bcrt1qtmm4qallkmnd2vl5y3w3an3uvq6w5v2ahqvfqm0mfxny8cnsdrashv8fsr)#afsheh6p",
    "hex": "00205ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb",
    "address": "bcrt1qtmm4qallkmnd2vl5y3w3an3uvq6w5v2ahqvfqm0mfxny8cnsdrashv8fsr",
    "type": "witness_v0_scripthash",
    "p2sh-segwit": "2N5EceqhW9HtQxRnL8qRCscz8Udv9P3bvwT"
  }
}
  1. Send some coins to address (and then generate some blocks to confirm txn)
bitcoin-cli -regtest -named sendtoaddress address="bcrt1qtmm4qallkmnd2vl5y3w3an3uvq6w5v2ahqvfqm0mfxny8cnsdrashv8fsr" amount="1.0" fee_rate=1.0
3259e33b721664a5aadae575a6870d1c26750cad789925f7df0282ac1a76f75c

Above txn decoded

{
  "txid": "3259e33b721664a5aadae575a6870d1c26750cad789925f7df0282ac1a76f75c",
  "hash": "30e06e1c9b41029638e2d4e8f3e7813193299840f2333d61a4ddf244201723cb",
  "version": 2,
  "size": 246,
  "vsize": 165,
  "weight": 657,
  "locktime": 241,
  "vin": [
    {
      "txid": "47495befacd402d9f73f6ba8148e434fa6bf1d1957b87524fef41d8fdea409e4",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "txinwitness": [
        "30440220181c3f5b2144f4e11eb8fc6b4a996e530774936fb2de21f5d85db42928a003f002205065e3ccbf29978545bdf9088de8100f851f04026766c23a37b519a7fc104a4201",
        "022e6433df12239f3cce79c9260fa8394d53902f05d017e86ff430108cdfecc54e"
      ],
      "sequence": 4294967293
    }
  ],
  "vout": [
    {
      "value": 48.99999835,
      "n": 0,
      "scriptPubKey": {
        "asm": "1 063ae126ecdab401ee960d7431b0eff76c1c28986133f84d285c4ef988270552",
        "desc": "rawtr(063ae126ecdab401ee960d7431b0eff76c1c28986133f84d285c4ef988270552)#83pfucst",
        "hex": "5120063ae126ecdab401ee960d7431b0eff76c1c28986133f84d285c4ef988270552",
        "address": "bcrt1pqcawzfhvm26qrm5kp46rrv807akpc2ycvyelsnfgt380nzp8q4fqf67ehv",
        "type": "witness_v1_taproot"
      }
    },
    {
      "value": 1.00000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "0 5ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb",
        "desc": "addr(bcrt1qtmm4qallkmnd2vl5y3w3an3uvq6w5v2ahqvfqm0mfxny8cnsdrashv8fsr)#afsheh6p",
        "hex": "00205ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb",
        "address": "bcrt1qtmm4qallkmnd2vl5y3w3an3uvq6w5v2ahqvfqm0mfxny8cnsdrashv8fsr",
        "type": "witness_v0_scripthash"
      }
    }
  ]
}
  1. Create a new address to send to and define some variables, then create raw txn
LOCKTIME=247
OUT_ADDR=bcrt1qmydu04snguq9lrtg9rmenu4dvx0zzlefdtpe8p
OUT_AMNT="0.998"
IN_TXID=3259e33b721664a5aadae575a6870d1c26750cad789925f7df0282ac1a76f75c
IN_VOUT=1

bitcoin-cli -regtest -named createrawtransaction inputs='[{"txid":"'$IN_TXID'", "vout":'$IN_VOUT'}]' outputs='[{"'$OUT_ADDR'":'$OUT_AMNT'}]' locktime=$LOCKTIME replaceable=true
02000000015cf7761aac8202dff7259978ad0c75261c0d87a675e5daaaa56416723be359320100000000fdffffff01c0d3f20500000000160014d91bc7d61347005f8d6828f799f2ad619e217f297e022500
  1. Create scriptpubky: OP_HASH160 hash160(redeemScript) OP_EQUAL redeemScript is 0200 + scripthash (I'm not too sure about this step...)
echo -n 00205ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -rmd160
838403567aa049ada65f944d0a2a320d7b93e7ee
# combine rest of script hex
A914838403567aa049ada65f944d0a2a320d7b93e7ee87
  1. More variables and attempt to sign raw txn

TX_DATA=02000000015cf7761aac8202dff7259978ad0c75261c0d87a675e5daaaa56416723be359320100000000fdffffff01c0d3f20500000000160014d91bc7d61347005f8d6828f799f2ad619e217f29f7000000
WITNESSCRIPT=048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac
SCRIPTHASH=5ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb
REDEEMSCRIPT=00205ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb
SCRIPTPUBKEY=A914838403567aa049ada65f944d0a2a320d7b93e7ee87

bitcoin-cli -regtest -named signrawtransactionwithwallet hexstring=$TX_DATA prevtxs='[{"txid":"'$IN_TXID'","vout":'$IN_VOUT',"redeemScript":"'$REDEEMSCRIPT'","scriptPubKey":"'$SCRIPTPUBKEY'","witnessScript":"'$WITNESSCRIPT'","amount":"'$OUT_AMNT'"}]'

error code: -22
error message:
Previous output scriptPubKey mismatch:
0 5ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb
vs:
OP_HASH160 838403567aa049ada65f944d0a2a320d7b93e7ee OP_EQUAL

Based on that error, it seems to be expecting the redeemscript, so I give that a try and get a different error:

bitcoin-cli -regtest -named signrawtransactionwithwallet hexstring=$TX_DATA prevtxs='[{"txid":"'$IN_TXID'","vout":'$IN_VOUT',"redeemScript":"'$REDEEMSCRIPT'","scriptPubKey":"'$REDEEMSCRIPT'","witnessScript":"'$WITNESSCRIPT'","amount":"'$OUT_AMNT'"}]'
{
  "hex": "02000000015cf7761aac8202dff7259978ad0c75261c0d87a675e5daaaa56416723be359320100000000fdffffff01c0d3f20500000000160014d91bc7d61347005f8d6828f799f2ad619e217f29f7000000",
  "complete": false,
  "errors": [
    {
      "txid": "3259e33b721664a5aadae575a6870d1c26750cad789925f7df0282ac1a76f75c",
      "vout": 1,
      "witness": [
      ],
      "scriptSig": "",
      "sequence": 4294967293,
      "error": "Witness program was passed an empty witness"
    }
  ]
}

Looking at the decoded hex of this incomplete txn, I see there is no witness data. Am I supposed to be supplying that? I'm probably getting something wrong along the way, but not sure what.

1 Answer 1

0

It looks like you're trying to create and spend from a P2WSH (Pay-to-Witness-Script-Hash) address with a time-lock condition. I'll highlight where there might be issues or confusion, as well as how to resolve them.

1. Script Construction

You correctly generated a P2WSH script that uses OP_CHECKLOCKTIMEVERIFY (CLTV) to lock the coins until a certain time.

The script you're using is:

048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac

This translates to:

  • 8095fe63: The locktime (timestamp for 1 March 2023 in little-endian format).
  • b175: OP_CHECKLOCKTIMEVERIFY and OP_DROP.
  • 76a914ad060529794593cac3e55a6eb26a0c6589d9681588ac: P2PKH part of the script (OP_DUP OP_HASH160 <pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG).

This script seems correct for locking coins with a CLTV condition.

2. Generating the Address

You computed the correct witness script hash (P2WSH) for the locking script:

  • 5ef75077ffb6e6d533f4245d1ece3c6034ea315db818906dfb49a643e27068fb.

This P2WSH can be verified by the output of the decodescript command and the address you generated:

  • bcrt1qtmm4qallkmnd2vl5y3w3an3uvq6w5v2ahqvfqm0mfxny8cnsdrashv8fsr is the correct P2WSH address.

So, this part of the process looks correct.

3. Sending Funds to the Address

You successfully sent 1 BTC to the P2WSH address (bcrt1qtmm4qallkmnd2vl5y3w3an3uvq6w5v2ahqvfqm0mfxny8cnsdrashv8fsr), and the transaction seems confirmed.

4. Spending from the Time-Locked Address

Here's where the complexity increases, as spending from a CLTV-locked P2WSH requires meeting specific conditions:

  1. Locktime in Transaction: The nLocktime of the transaction must be set to a value greater than or equal to the locktime in the script (i.e., 1677628800).
  2. Sequence Number: The input's sequence number must be less than 0xFFFFFFFF (which you correctly set to 4294967293), indicating that the input is allowed to be spent according to locktime rules.
  3. Witness Stack: To spend the P2WSH output, the witness stack must include:
    • The signature for the public key.
    • The public key.
    • The locking script (048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac).

Key Areas to Check:

  1. Locktime Mismatch: The nLocktime in your raw transaction is set to 247:

    02000000015cf7761aac8202dff7259978ad0c75261c0d87a675e5daaaa56416723be359320100000000fdffffff01c0d3f20500000000160014d91bc7d61347005f8d6828f799f2ad619e217f297e022500
    

    However, the locktime in your script is 1677628800, so you need to set the locktime of the transaction to at least 1677628800 (March 1, 2023). Without doing this, the transaction will be invalid because the nLocktime doesn’t meet the script's requirement.

  2. Creating the Correct Witness Data: For spending from a P2WSH address, you need to provide the correct witness data:

    • The first element is the unlocking signature.
    • The second element is the public key.
    • The third element is the actual script itself (which includes the OP_CHECKLOCKTIMEVERIFY part).
  3. Raw Transaction Creation:

    • When creating the raw transaction, make sure you include the witness program for the script and use the correct nLocktime in the transaction.
  4. Redeem Script Confusion: You mention a redeem script (which is used in P2SH-P2WSH), but you're working directly with a P2WSH. If you were using P2SH-P2WSH, you would need a redeem script to "reveal" the P2WSH. Since you're using native P2WSH, you don't need a redeem script. The witness data directly includes the locking script.

Suggested Fixes:

  1. Set Correct nLocktime: When creating the spending transaction, set nLocktime to 1677628800 or a later block.

    Example:

    bitcoin-cli -regtest -named createrawtransaction inputs='[{"txid":"'$IN_TXID'", "vout":'$IN_VOUT'}]' outputs='[{"'$OUT_ADDR'":'$OUT_AMNT'}]' locktime=1677628800 replaceable=true
    
  2. Create Correct Witness: Ensure the witness field contains the signature, public key, and locking script.

  3. Include Locking Script: When constructing the witness for the spending transaction, use the full locking script (048095fe63b17576a914ad060529794593cac3e55a6eb26a0c6589d9681588ac) as the last element.

Summary of Process:

  1. Locking Transaction: You correctly created a P2WSH address that locks coins with OP_CHECKLOCKTIMEVERIFY. The transaction that sent coins to this address is also correct.
  2. Spending Transaction: Ensure the spending transaction’s nLocktime matches or exceeds the locktime in the locking script. Construct the witness correctly when spending, including the signature, public key, and the locking script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.