# Beneficiary Script Hash Address In this document, we introduce how to construct a beneficiary address and how to spend its fund in steps. We use the go library `btcsuite/btcd` to make examples. The goal of this script is to create an address which could be spent by two party, the owner and the beneficiary. The owner could spend funds in the address without any restriction. The beneficiary, on the other hand, can only use the fund after a given timestamp. ## Customized Redeem Script To achieve the goal, we need to introduce a customized redeem script. Here is how we do it. ### Multisig Beneficiary The owner can unlock the fund anytime with 2 signatures. The beneficiary, on the other hand, can unlock the fund only when current time exceeds the lock time. **Unlock Script** ```markup beneficiary: <beneficiary_sig> <beneficiary_pk> owner: 0 <owner_sig> <pod_sig> ``` **Redeem Script** The initial stack size of a P2PKH is 2. For a standard 2-3 multisig, the size is 3. The redeem script first check the stack size. If the size is equal to 2, it tests the lock time and validate the P2PKH in the end. If the size is not 2, it checks the signature in the regular multisig validation. ```markup OP_DEPTH OP_2 OP_EQUAL OP_IF <locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <beneficiary's pubKeyHash> EQUALVERIFY CHECKSIG OP_ELSE OP_2 <pubkey1> <pubkey2> <pubkey3> OP_3 OP_CHECKMULTISIG OP_ENDIF ``` ### P2PKH x 2 This is a beneficiary script that both the owner and the beneficiary hold regular bitcoin address. The beneficiary needs to add additional `<1>` into its unlock script to trigger the beneficiary validation. **Unlock Script** ```markup beneficiary: <sig1> <pk1> 1 owner: <sig2> <pk2> ``` **Redeem Script** ```markup OP_DUP OP_1 OP_EQUAL OP_IF OP_DROP <locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <beneficiary's pubKeyHash> EQUALVERIFY CHECKSIG OP_ELSE OP_DUP OP_HASH160 <owner's pubKeyHash> EQUALVERIFY CHECKSIG OP_ENDIF ``` ### Example Here is an example of creating a redeem script in golang ```go builder := txscript.NewScriptBuilder() builder. AddOp(txscript.OP_DEPTH).AddOp(txscript.OP_2).AddOp(txscript.OP_EQUAL).AddOp(txscript.OP_IF). // If OP_DEPTH == 2 AddInt64(lockTime).AddOp(txscript.OP_CHECKLOCKTIMEVERIFY).AddOp(txscript.OP_DROP). // check lock time and drop the time data AddOp(txscript.OP_DUP).AddOp(txscript.OP_HASH160).AddData(beneficiaryPKH). // beneficiary PKH check AddOp(txscript.OP_EQUALVERIFY).AddOp(txscript.OP_CHECKSIG). // beneficiary PKH check AddOp(txscript.OP_ELSE). // Else AddOp(txscript.OP_2).AddData(pubKey1).AddData(pubKey2).AddData(pubKey3). // 2-3 multisug AddOp(txscript.OP_3).AddOp(txscript.OP_CHECKMULTISIG). // 2-3 multisug AddOp(txscript.OP_ENDIF) ``` ## Addresses We can now generate both P2SH and P2WSH addresses by the redeem script ### P2SH For P2SH address, it turns a ScriptPubKey of the format of `OP_HASH160 <redeemScriptHash160> OP_EQUAL` into an address. Here is an example of how we generate P2SH address in golang: ```go btcutil.NewAddressScriptHashFromHash( btcutil.Hash160(redeemScript), &chaincfg.TestNet3Params) ``` ### P2WSH P2WSH, on the other hand, takes a leading zero and a following witness program as a ScriptPubKey. The witness program would be the SHA256 hash of a redeem script. The ScriptPubKey will be in format of `0 <redeemScriptSHA256>`. Here is an example of how we generate P2WSH address in golang: ```go btcutil.NewAddressWitnessScriptHash( chainhash.HashB(redeemScript), &chaincfg.TestNet3Params) ``` ## Redeem Fund In this section, we introduce how to spend funds from both beneficiary and owner's perspective. ### Beneficiary Since `OP_CHECKLOCKTIMEVERIFY` compares the in-script timestamp with the transaction `nlocktime`, it is required in a transaction that takes any beneficiary UTXOs as inputs. Besides, the input sequence needs to be set to a value other than `0xFFFFFFFF` [1]. The `nlocktime` is compared to the 11-block median time past [2] instead of the latest block time. With enough UTXOs, as well as, the destination and amount of the payment, we can construct a transaction as follow: ```go // create a transaction from scratch redeemTx := wire.NewMsgTx(wire.TxVersion) utxoHash, err := chainhash.NewHashFromStr(txid) if err != nil { panic(err) } // and add the index of the UTXO outPoint := wire.NewOutPoint(utxoHash, vinIndex) txIn := wire.NewTxIn(outPoint, nil, nil) txIn.Sequence = 0xFFFFFFFE // add vin redeemTx.AddTxIn(txIn) // decode an address and turn into a ScriptPubKey decodedAddr, err := btcutil.DecodeAddress(to, &chaincfg.TestNet3Params) if err != nil { panic(err) } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { panic(err) } redeemTxOut := wire.NewTxOut(amount, destinationAddrByte) // add vout redeemTx.AddTxOut(redeemTxOut) ``` Generate the ScriptSig to unlock the fund from vins: ```go // beneficiary account account, err := btcutil.DecodeWIF(wif) if err != nil { panic(err) } sigBeneficiary, err := txscript.RawTxInSignature(redeemTx, 0, redeemScript, txscript.SigHashAll, account.PrivKey) if err != nil { panic(err) } // create the scriptsig signature := txscript.NewScriptBuilder() signature.AddData(sigBeneficiary).AddData(account.SerializePubKey()).AddData(redeemScript) ``` Attach the ScriptSig to each vins accordingly. ```go redeemTx.TxIn[0].SignatureScript = signatureScript ``` The last step is to convert the redeem transaction into a hex string ```go var signedTx bytes.Buffer redeemTx.Serialize(&signedTx) hexSignedTx := hex.EncodeToString(signedTx.Bytes()) ``` ### Owner For the owner, it needs to construct the transaction the same as we beneficiary. Unlike beneficiary, it requires signatures from the owner as well as the pod signer. The signature will become: ```go signature := txscript.NewScriptBuilder() signature. AddOp(txscript.OP_0). // The OP_0 is required for a multisig Scriptsig. AddData(sigOwner). AddData(signPod). AddData(redeemScript) ``` The rest of step will is identical to what we did for the beneficiary. ## Redeem from Witness Address Unlike legacy address, we do not need generate ScriptSig. We provide witness to spend a fund instead. The witness is a stack of values [3]. That means there will be no operations in witness. For example, `OP_ADD` is not a valid item in witness. The last item of witness for P2WSH would be the redeem script. It will be hashed by SHA256 and compare to the witness program first. If the two values are matched, the witness stack will be checked as we do in the Scriptsig. ```go txSigHashes := txscript.NewTxSigHashes(redeemTx) accountSignature, err := txscript.RawTxInWitnessSignature( redeemTx, txSigHashes, 0, 10000, redeemScript, txscript.SigHashAll, account.PrivKey) ``` The redeem script of each vin is required for signing the signature. When a redeem transaction is constructed, the witness of the a vin needs to be set to an array with only one element which is the redeem script. ```go outPoint := wire.NewOutPoint(utxoHash, vinIndex) txIn := wire.NewTxIn(outPoint, nil, nil) txIn.Witness = wire.TxWitness{redeemScript} ``` In the end, we will concatenate all the signatures as well as the redeem script as the witness. ```go redeemTx.TxIn[0].Witness = wire.TxWitness{ {}, signature1, signature2, redeemScript, } ``` ## PSBT To create a PSBT, we construct inputs and outputs first. This is similar with constructing a transaction. We use the inputs and outputs to create a PSBT from scratch. ```go pC, err := psbt.New(inputs, outputs, wire.TxVersion, 0, []uint32{0xFFFFFFFF}) // Note: typically the sequence is `0xffffffff`! if err != nil { panic(err) } ``` Once we have a basic PSBT, we use the updater to add signing information. ```go u, err := psbt.NewUpdater(pC) if err != nil { panic(err) } u.AddInBip32Derivation(fingerprint1, []uint32{hardenedIndedx + 48, hardenedIndedx + 1, hardenedIndedx, hardenedIndedx + 2, 1, 1}, pub1, 0) u.AddInBip32Derivation(fingerprint2, []uint32{hardenedIndedx + 48, hardenedIndedx + 1, hardenedIndedx, hardenedIndedx + 2, 1, 1}, pub2, 0) pubkeyScript, _ := hex.DecodeString("0020d95df92e3d6410d9cc70139387cb4bfa02e06b094812f3c7ba4686eed6f7a967") txinUTXO := wire.NewTxOut(10000, pubkeyScript) u.AddInWitnessUtxo(txinUTXO, 0) u.AddInWitnessScript(redeemScript, 0) u.AddInSighashType(txscript.SigHashAll, 0) ``` The information includes the details of public keys which need to sign the PSBT, witness information and redeem scripts of each inputs. This forms a PSBT without signatures. We now encode them into base64 and hands them to each signers. ```go b64, _ := pC.B64Encode() // cHNidP8BAFIBAAAAAbpIi8SpfQ2sTVinlNZD5AeyM78IjuDfa+P034K7R4lpAAAAAAD/////AXQmAAAAAAAAFgAUxSUrmWARV702K1OosJbrrmuSVj8AAAAAAAEBKxAnAAAAAAAAIgAg2V35Lj1kENnMcBOTh8tL+gLgawlIEvPHukaG7tb3qWcBAwQBAAAAAQWPdFKHYwRS+KhgsXV2qRQdt1a2kXUIIjPrYhdX2S/GRubW1oisZ1IhA7aEMFWi7W6nGqKavcWzT8wjSjva0Ysc3/tNQiNQ8650IQKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYyED7/ao35XhSkLbINqIwm0LGl59nhzOiVhnoCWI01kULEBTrmgiBgK+6RGfyFK6ozLTEic3REAU5gfuxPxMJchAPQ3hsc5noRwVEt+NMAAAgAEAAIAAAACAAgAAgAEAAAABAAAAIgYDtoQwVaLtbqcaopq9xbNPzCNKO9rRixzf+01CI1DzrnQcxYgyAzAAAIABAACAAAAAgAIAAIABAAAAAQAAAAAA // // Check appendix for a decoded PSBT. ``` Users take this PSBT and add their signatures to it accordingly and send them back to finalizer. The finalizer will then turn the PSBT into a transaction and broadcast it to the network. ## References [1] [https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) > CHECKLOCKTIMEVERIFY redefines the existing NOP2 opcode. When executed, if any of the following conditions are true, the script interpreter will terminate with an error: the stack is empty; or the top item on the stack is less than 0; or the lock-time type (height vs. timestamp) of the top stack item and the nLockTime field are not the same; or the top stack item is greater than the transaction's nLockTime field; or the nSequence field of the txin is 0xffffffff; Otherwise, script execution will continue as if a NOP had been executed. [2] [https://en.bitcoin.it/wiki/NLockTime](https://en.bitcoin.it/wiki/NLockTime) > Note that since the adoption of BIP 113, the time-based nLockTime is compared to the 11-block median time past (the median timestamp of the 11 blocks preceding the block in which the transaction is mined), and not the block time itself. [3] [https://bitcoin.stackexchange.com/questions/85704/why-does-witness-use-count-instead-of-length](https://bitcoin.stackexchange.com/questions/85704/why-does-witness-use-count-instead-of-length) > Note that witnesses are not scripts. They do not contain opcodes. They are stack elements. Witnesses do not have explicit opcodes (witnessScripts are scripts but are single witness stack elements so their opcodes don't count). ### Other Links [https://bitcoin.stackexchange.com/questions/96283/how-to-sign-a-psbt-transaction](https://bitcoin.stackexchange.com/questions/96283/how-to-sign-a-psbt-transaction) [https://bitcoin.stackexchange.com/questions/77440/segwit-transaction-in-golang](https://bitcoin.stackexchange.com/questions/77440/segwit-transaction-in-golang) [https://wiki.bitcoinsv.io/index.php/Scripts_with_Flow_Control_(Conditional_Clauses)](https://wiki.bitcoinsv.io/index.php/Scripts_with_Flow_Control_(Conditional_Clauses)) [https://bitcoin.stackexchange.com/questions/85676/what-s-the-opcode-sequence-for-doing-the-reverse-of-multisig](https://bitcoin.stackexchange.com/questions/85676/what-s-the-opcode-sequence-for-doing-the-reverse-of-multisig) [https://bitcoin.stackexchange.com/questions/77440/segwit-transaction-in-golang](https://bitcoin.stackexchange.com/questions/77440/segwit-transaction-in-golang) [https://bitcoin.stackexchange.com/questions/77180/what-is-the-witness-and-what-data-does-it-contain](https://bitcoin.stackexchange.com/questions/77180/what-is-the-witness-and-what-data-does-it-contain) ## Steps for testing PSBT-signing using bitcoin-cli 1. create a descriptor wallet in bitcoin-cli and import a descriptor. We can see this wallet owns an address. You will use the public key of the address be part of the 2-3 beneficiary redeem script. ```shell= $ bitcoin-cli -datadir=/bitcoin -rpcwallet=p1 getaddressinfo tb1qrxaj4jz8d69dc0hk9cmapl39g9fkelulz0adrq { "address": "tb1qrxaj4jz8d69dc0hk9cmapl39g9fkelulz0adrq", "scriptPubKey": "001419bb2ac8476e8adc3ef62e37d0fe2541536cff9f", "ismine": true, "solvable": true, "desc": "wpkh([c5883203/48'/1'/0'/2'/1/1]02aef819ca2716e2a332d4e0ca6c89c954d91b2b8e682617d5eb7e4e784418dc63)#72dpkndz", "iswatchonly": false, "isscript": false, "iswitness": true, "witness_version": 0, "witness_program": "19bb2ac8476e8adc3ef62e37d0fe2541536cff9f", "pubkey": "02aef819ca2716e2a332d4e0ca6c89c954d91b2b8e682617d5eb7e4e784418dc63", "ischange": false, "timestamp": 1621910020, "hdkeypath": "m/48'/1'/0'/2'/1/1", "hdseedid": "0000000000000000000000000000000000000000", "hdmasterfingerprint": "c5883203", "labels": [ "" ] } ``` 2. Create a beneficiary address with the redeem script and send some money into it. Here is the transaction on testnet: ```shell= $ bitcoind bitcoin-cli -datadir=/bitcoin -rpcwallet=p1 getrawtransaction 698947bb82dff4e36bdfe08e08bf33b207e443d694a7584dac0d7da9c48b48ba 1 { "txid": "698947bb82dff4e36bdfe08e08bf33b207e443d694a7584dac0d7da9c48b48ba", "hash": "b25893d2f5ae5aaff6d5f6debacd545f0158c320f4e4de29164c389dde4ba170", "version": 1, "size": 235, "vsize": 153, "weight": 610, "locktime": 0, "vin": [ { "txid": "8509b8aaf2faaf4fa1278ae4c52b117fd8c345773181964182c99a5b7c3416bc", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "txinwitness": [ "30450221009ff157d17d2b9876662d1e4e27fbd9d821ca567dea5f183cc53e94132a41586e02207a713082f360a20f17b8faa080c1378cf1a2349e291fc618a01c3f97230adfc901", "03fb0e79ee07ace07eb2d3b3463bf43ffd4066761e93cb154124484fe3d05ec5d6" ], "sequence": 4294967295 } ], "vout": [ { "value": 0.00010000, "n": 0, "scriptPubKey": { "asm": "0 f0d39ff568984e46c8f1af0b3d6672ab8c454649a69179b613210e62bae8eded", "hex": "0020f0d39ff568984e46c8f1af0b3d6672ab8c454649a69179b613210e62bae8eded", "reqSigs": 1, "type": "witness_v0_scripthash", "addresses": [ "tb1q7rfelatgnp8ydj834u9n6enj4wxy23jf56ghndsnyy8x9whgahks27x5g9" ] } }, { "value": 0.00009691, "n": 1, "scriptPubKey": { "asm": "0 c5115c6037dde730165a3fde5962f187667f8789", "hex": "0014c5115c6037dde730165a3fde5962f187667f8789", "reqSigs": 1, "type": "witness_v0_keyhash", "addresses": [ "tb1qc5g4ccphmhnnq9j68l09jch3san8lpuf3e8sjw" ] } } ], "hex": "0100000001bc16347c5b9ac982419681317745c3d87f112bc5e48a27a14faffaf2aab809850000000000ffffffff021027000000000000220020f0d39ff568984e46c8f1af0b3d6672ab8c454649a69179b613210e62bae8ededdb25000000000000160014c5115c6037dde730165a3fde5962f187667f878900000000", "blockhash": "0000000000001dddfb695914b36dcd041c0ed88731804abdd8aeddc3c58291f4", "confirmations": 49, "time": 1622084077, "blocktime": 1622084077 } ``` 3. Create a PSBT and add the address we created above as one of bip32 derivation. ```shell= $ bitcoin-cli -datadir=/bitcoin -rpcwallet=p1 decodepsbt cHNidP8BAFIBAAAAAbpIi8SpfQ2sTVinlNZD5AeyM78IjuDfa+P034K7R4lpAAAAAAD/////AXQmAAAAAAAAFgAUxSUrmWARV702K1OosJbrrmuSVj8AAAAAAAEBKxAnAAAAAAAAIgAg8NOf9WiYTkbI8a8LPWZyq4xFRkmmkXm2EyEOYrro7e0BAwQBAAAAAQWPdFKHYwRS+KhgsXV2qRQdt1a2kXUIIjPrYhdX2S/GRubW1oisZ1IhA7aEMFWi7W6nGqKavcWzT8wjSjva0Ysc3/tNQiNQ8650IQKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYyED7/ao35XhSkLbINqIwm0LGl59nhzOiVhnoCWI01kULEBTrmgiBgKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYxzFiDIDMAAAgAEAAIAAAACAAgAAgAEAAAABAAAAIgYCvukRn8hSuqMy0xInN0RAFOYH7sT8TCXIQD0N4bHOZ6EcFRLfjTAAAIABAACAAAAAgAIAAIABAAAAAQAAAAAA { "tx": { "txid": "7e4186232f58215549c42cbd2fa79b518098c738ae30351d35cfd6a4751c262d", "hash": "7e4186232f58215549c42cbd2fa79b518098c738ae30351d35cfd6a4751c262d", "version": 1, "size": 82, "vsize": 82, "weight": 328, "locktime": 0, "vin": [ { "txid": "698947bb82dff4e36bdfe08e08bf33b207e443d694a7584dac0d7da9c48b48ba", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "sequence": 4294967295 } ], "vout": [ { "value": 0.00009844, "n": 0, "scriptPubKey": { "asm": "0 c5252b99601157bd362b53a8b096ebae6b92563f", "hex": "0014c5252b99601157bd362b53a8b096ebae6b92563f", "reqSigs": 1, "type": "witness_v0_keyhash", "addresses": [ "tb1qc5jjhxtqz9tm6d3t2w5tp9ht4e4ey43l4jyel5" ] } } ] }, "unknown": { }, "inputs": [ { "witness_utxo": { "amount": 0.00010000, "scriptPubKey": { "asm": "0 f0d39ff568984e46c8f1af0b3d6672ab8c454649a69179b613210e62bae8eded", "hex": "0020f0d39ff568984e46c8f1af0b3d6672ab8c454649a69179b613210e62bae8eded", "type": "witness_v0_scripthash", "address": "tb1q7rfelatgnp8ydj834u9n6enj4wxy23jf56ghndsnyy8x9whgahks27x5g9" } }, "sighash": "ALL", "witness_script": { "asm": "OP_DEPTH 2 OP_EQUAL OP_IF 1621686354 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 1db756b69175082233eb621757d92fc646e6d6d6 OP_EQUALVERIFY OP_CHECKSIG OP_ELSE 2 03b6843055a2ed6ea71aa29abdc5b34fcc234a3bdad18b1cdffb4d422350f3ae74 02aef819ca2716e2a332d4e0ca6c89c954d91b2b8e682617d5eb7e4e784418dc63 03eff6a8df95e14a42db20da88c26d0b1a5e7d9e1cce895867a02588d359142c40 3 OP_CHECKMULTISIG OP_ENDIF", "hex": "745287630452f8a860b17576a9141db756b69175082233eb621757d92fc646e6d6d688ac67522103b6843055a2ed6ea71aa29abdc5b34fcc234a3bdad18b1cdffb4d422350f3ae742102aef819ca2716e2a332d4e0ca6c89c954d91b2b8e682617d5eb7e4e784418dc632103eff6a8df95e14a42db20da88c26d0b1a5e7d9e1cce895867a02588d359142c4053ae68", "type": "nonstandard" }, "bip32_derivs": [ { "pubkey": "02aef819ca2716e2a332d4e0ca6c89c954d91b2b8e682617d5eb7e4e784418dc63", "master_fingerprint": "c5883203", "path": "m/48'/1'/0'/2'/1/1" }, { "pubkey": "02bee9119fc852baa332d3122737444014e607eec4fc4c25c8403d0de1b1ce67a1", "master_fingerprint": "1512df8d", "path": "m/48'/1'/0'/2'/1/1" } ] } ], "outputs": [ { } ], "fee": 0.00000156 } ``` 4. Run `walletprocesspsbt` using the descriptor wallet. However, the PSBT is not updated. ```shell= $ bitcoin-cli -datadir=/bitcoin -rpcwallet=p1 walletprocesspsbt cHNidP8BAFIBAAAAAbpIi8SpfQ2sTVinlNZD5AeyM78IjuDfa+P034K7R4lpAAAAAAD/////AXQmAAAAAAAAFgAUxSUrmWARV702K1OosJbrrmuSVj8AAAAAAAEBKxAnAAAAAAAAIgAg8NOf9WiYTkbI8a8LPWZyq4xFRkmmkXm2EyEOYrro7e0BAwQBAAAAAQWPdFKHYwRS+KhgsXV2qRQdt1a2kXUIIjPrYhdX2S/GRubW1oisZ1IhA7aEMFWi7W6nGqKavcWzT8wjSjva0Ysc3/tNQiNQ8650IQKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYyED7/ao35XhSkLbINqIwm0LGl59nhzOiVhnoCWI01kULEBTrmgiBgKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYxzFiDIDMAAAgAEAAIAAAACAAgAAgAEAAAABAAAAIgYCvukRn8hSuqMy0xInN0RAFOYH7sT8TCXIQD0N4bHOZ6EcFRLfjTAAAIABAACAAAAAgAIAAIABAAAAAQAAAAAA { "psbt": "cHNidP8BAFIBAAAAAbpIi8SpfQ2sTVinlNZD5AeyM78IjuDfa+P034K7R4lpAAAAAAD/////AXQmAAAAAAAAFgAUxSUrmWARV702K1OosJbrrmuSVj8AAAAAAAEBKxAnAAAAAAAAIgAg8NOf9WiYTkbI8a8LPWZyq4xFRkmmkXm2EyEOYrro7e0BAwQBAAAAAQWPdFKHYwRS+KhgsXV2qRQdt1a2kXUIIjPrYhdX2S/GRubW1oisZ1IhA7aEMFWi7W6nGqKavcWzT8wjSjva0Ysc3/tNQiNQ8650IQKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYyED7/ao35XhSkLbINqIwm0LGl59nhzOiVhnoCWI01kULEBTrmgiBgKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYxzFiDIDMAAAgAEAAIAAAACAAgAAgAEAAAABAAAAIgYCvukRn8hSuqMy0xInN0RAFOYH7sT8TCXIQD0N4bHOZ6EcFRLfjTAAAIABAACAAAAAgAIAAIABAAAAAQAAAAAA", "complete": false } ``` ## Appendix Analyze/Decode sample PSBT ``` cHNidP8BAFIBAAAAAbpIi8SpfQ2sTVinlNZD5AeyM78IjuDfa+P034K7R4lpAAAAAAD/////AXQmAAAAAAAAFgAUxSUrmWARV702K1OosJbrrmuSVj8AAAAAA AEBKxAnAAAAAAAAIgAg2V35Lj1kENnMcBOTh8tL+gLgawlIEvPHukaG7tb3qWcBAwQBAAAAAQWPdFKHYwRS+KhgsXV2qRQdt1a2kXUIIjPrYhdX2S/GRubW1oisZ1IhA7aEMFWi7W6nGqKavcWzT8wjSjva0Ysc 3/tNQiNQ8650IQKu+BnKJxbiozLU4MpsiclU2RsrjmgmF9Xrfk54RBjcYyED7/ao35XhSkLbINqIwm0LGl59nhzOiVhnoCWI01kULEBTrmgiBgK+6RGfyFK6ozLTEic3REAU5gfuxPxMJchAPQ3hsc5noRwVEt+ NMAAAgAEAAIAAAACAAgAAgAEAAAABAAAAIgYDtoQwVaLtbqcaopq9xbNPzCNKO9rRixzf+01CI1DzrnQcxYgyAzAAAIABAACAAAAAgAIAAIABAAAAAQAAAAAA ``` ```json= { "inputs": [ { "has_utxo": true, "is_final": false, "next": "updater" } ], "fee": 0.00000156, "next": "updater" } ``` ```json= { "tx": { "txid": "7e4186232f58215549c42cbd2fa79b518098c738ae30351d35cfd6a4751c262d", "hash": "7e4186232f58215549c42cbd2fa79b518098c738ae30351d35cfd6a4751c262d", "version": 1, "size": 82, "vsize": 82, "weight": 328, "locktime": 0, "vin": [ { "txid": "698947bb82dff4e36bdfe08e08bf33b207e443d694a7584dac0d7da9c48b48ba", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "sequence": 4294967295 } ], "vout": [ { "value": 0.00009844, "n": 0, "scriptPubKey": { "asm": "0 c5252b99601157bd362b53a8b096ebae6b92563f", "hex": "0014c5252b99601157bd362b53a8b096ebae6b92563f", "reqSigs": 1, "type": "witness_v0_keyhash", "addresses": [ "tb1qc5jjhxtqz9tm6d3t2w5tp9ht4e4ey43l4jyel5" ] } } ] }, "unknown": { }, "inputs": [ { "witness_utxo": { "amount": 0.00010000, "scriptPubKey": { "asm": "0 d95df92e3d6410d9cc70139387cb4bfa02e06b094812f3c7ba4686eed6f7a967", "hex": "0020d95df92e3d6410d9cc70139387cb4bfa02e06b094812f3c7ba4686eed6f7a967", "type": "witness_v0_scripthash", "address": "tb1qm9wljt3avsgdnnrszwfc0j6tlgpwq6cffqf083a6g6rwa4hh49nsk55wjs" } }, "sighash": "ALL", "witness_script": { "asm": "OP_DEPTH 2 OP_EQUAL OP_IF 1621686354 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 1db756b69175082233eb621757d92fc646e6d6d6 OP_EQUALVERIFY OP_CHECKSIG OP_ELSE 2 03b6843055a2ed6ea71aa29abdc5b34fcc234a3bdad18b1cdffb4d422350f3ae74 02aef819ca2716e2a332d4e0ca6c89c954d91b2b8e682617d5eb7e4e784418dc63 03eff6a8df95e14a42db20da88c26d0b1a5e7d9e1cce895867a02588d359142c40 3 OP_CHECKMULTISIG OP_ENDIF", "hex": "745287630452f8a860b17576a9141db756b69175082233eb621757d92fc646e6d6d688ac67522103b6843055a2ed6ea71aa29abdc5b34fcc234a3bdad18b1cdffb4d422350f3ae742102aef819ca2716e2a332d4e0ca6c89c954d91b2b8e682617d5eb7e4e784418dc632103eff6a8df95e14a42db20da88c26d0b1a5e7d9e1cce895867a02588d359142c4053ae68", "type": "nonstandard" }, "bip32_derivs": [ { "pubkey": "02bee9119fc852baa332d3122737444014e607eec4fc4c25c8403d0de1b1ce67a1", "master_fingerprint": "1512df8d", "path": "m/48'/1'/0'/2'/1/1" }, { "pubkey": "03b6843055a2ed6ea71aa29abdc5b34fcc234a3bdad18b1cdffb4d422350f3ae74", "master_fingerprint": "c5883203", "path": "m/48'/1'/0'/2'/1/1" } ] } ], "outputs": [ { } ], "fee": 0.00000156 } ```