diff options
Diffstat (limited to 'doc/multisig-tutorial.md')
-rw-r--r-- | doc/multisig-tutorial.md | 58 |
1 files changed, 28 insertions, 30 deletions
diff --git a/doc/multisig-tutorial.md b/doc/multisig-tutorial.md index 1d2b3244bc..1f21acc2be 100644 --- a/doc/multisig-tutorial.md +++ b/doc/multisig-tutorial.md @@ -9,15 +9,13 @@ This tutorial uses [jq](https://github.com/stedolan/jq) JSON processor to proces Before starting this tutorial, start the bitcoin node on the signet network. ```bash -./src/bitcoind -signet -daemon +./build/src/bitcoind -signet -daemon ``` This tutorial also uses the default WPKH derivation path to get the xpubs and does not conform to [BIP 45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) or [BIP 87](https://github.com/bitcoin/bips/blob/master/bip-0087.mediawiki). At the time of writing, there is no way to extract a specific path from wallets in Bitcoin Core. For this, an external signer/xpub can be used. -[PR #22341](https://github.com/bitcoin/bitcoin/pull/22341), which is still under development, introduces a new wallet RPC `getxpub`. It takes a BIP32 path as an argument and returns the xpub, along with the master key fingerprint. - ## 1.1 Basic Multisig Workflow ### 1.1 Create the Descriptor Wallets @@ -29,7 +27,7 @@ These three wallets should not be used directly for privacy reasons (public key ```bash for ((n=1;n<=3;n++)) do - ./src/bitcoin-cli -signet createwallet "participant_${n}" + ./build/src/bitcoin-cli -signet createwallet "participant_${n}" done ``` @@ -49,9 +47,9 @@ declare -A xpubs for ((n=1;n<=3;n++)) do - xpubs["internal_xpub_${n}"]=$(./src/bitcoin-cli -signet -rpcwallet="participant_${n}" listdescriptors | jq '.descriptors | [.[] | select(.desc | startswith("wpkh") and contains("/1/*"))][0] | .desc' | grep -Po '(?<=\().*(?=\))') + xpubs["internal_xpub_${n}"]=$(./build/src/bitcoin-cli -signet -rpcwallet="participant_${n}" listdescriptors | jq '.descriptors | [.[] | select(.desc | startswith("wpkh") and contains("/1/*"))][0] | .desc' | grep -Po '(?<=\().*(?=\))') - xpubs["external_xpub_${n}"]=$(./src/bitcoin-cli -signet -rpcwallet="participant_${n}" listdescriptors | jq '.descriptors | [.[] | select(.desc | startswith("wpkh") and contains("/0/*") )][0] | .desc' | grep -Po '(?<=\().*(?=\))') + xpubs["external_xpub_${n}"]=$(./build/src/bitcoin-cli -signet -rpcwallet="participant_${n}" listdescriptors | jq '.descriptors | [.[] | select(.desc | startswith("wpkh") and contains("/0/*") )][0] | .desc' | grep -Po '(?<=\().*(?=\))') done ``` @@ -73,8 +71,8 @@ Define the external and internal multisig descriptors, add the checksum and then external_desc="wsh(sortedmulti(2,${xpubs["external_xpub_1"]},${xpubs["external_xpub_2"]},${xpubs["external_xpub_3"]}))" internal_desc="wsh(sortedmulti(2,${xpubs["internal_xpub_1"]},${xpubs["internal_xpub_2"]},${xpubs["internal_xpub_3"]}))" -external_desc_sum=$(./src/bitcoin-cli -signet getdescriptorinfo $external_desc | jq '.descriptor') -internal_desc_sum=$(./src/bitcoin-cli -signet getdescriptorinfo $internal_desc | jq '.descriptor') +external_desc_sum=$(./build/src/bitcoin-cli -signet getdescriptorinfo $external_desc | jq '.descriptor') +internal_desc_sum=$(./build/src/bitcoin-cli -signet getdescriptorinfo $internal_desc | jq '.descriptor') multisig_ext_desc="{\"desc\": $external_desc_sum, \"active\": true, \"internal\": false, \"timestamp\": \"now\"}" multisig_int_desc="{\"desc\": $internal_desc_sum, \"active\": true, \"internal\": true, \"timestamp\": \"now\"}" @@ -96,7 +94,7 @@ There are other fields that can be added to the descriptors: * `internal`: Indicates whether matching outputs should be treated as something other than incoming payments (e.g. change). * `timestamp`: Sets the time from which to start rescanning the blockchain for the descriptor, in UNIX epoch time. -Documentation for these and other parameters can be found by typing `./src/bitcoin-cli help importdescriptors`. +Documentation for these and other parameters can be found by typing `./build/src/bitcoin-cli help importdescriptors`. `multisig_desc` concatenates external and internal descriptors in a JSON array and then it will be used to create the multisig wallet. @@ -109,17 +107,17 @@ Then import the descriptors created in the previous step using the `importdescri After that, `getwalletinfo` can be used to check if the wallet was created successfully. ```bash -./src/bitcoin-cli -signet -named createwallet wallet_name="multisig_wallet_01" disable_private_keys=true blank=true +./build/src/bitcoin-cli -signet -named createwallet wallet_name="multisig_wallet_01" disable_private_keys=true blank=true -./src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" importdescriptors "$multisig_desc" +./build/src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" importdescriptors "$multisig_desc" -./src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getwalletinfo +./build/src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getwalletinfo ``` Once the wallets have already been created and this tutorial needs to be repeated or resumed, it is not necessary to recreate them, just load them with the command below: ```bash -for ((n=1;n<=3;n++)); do ./src/bitcoin-cli -signet loadwallet "participant_${n}"; done +for ((n=1;n<=3;n++)); do ./build/src/bitcoin-cli -signet loadwallet "participant_${n}"; done ``` ### 1.4 Fund the wallet @@ -133,9 +131,9 @@ The url used by the script can also be accessed directly. At time of writing, th Coins received by the wallet must have at least 1 confirmation before they can be spent. It is necessary to wait for a new block to be mined before continuing. ```bash -receiving_address=$(./src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getnewaddress) +receiving_address=$(./build/src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getnewaddress) -./contrib/signet/getcoins.py -c ./src/bitcoin-cli -a $receiving_address +./contrib/signet/getcoins.py -c ./build/src/bitcoin-cli -a $receiving_address ``` To copy the receiving address onto the clipboard, use the following command. This can be useful when getting coins via the signet faucet mentioned above. @@ -147,7 +145,7 @@ echo -n "$receiving_address" | xclip -sel clip The `getbalances` RPC may be used to check the balance. Coins with `trusted` status can be spent. ```bash -./src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getbalances +./build/src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getbalances ``` ### 1.5 Create a PSBT @@ -163,13 +161,13 @@ For simplicity, the destination address is taken from the `participant_1` wallet The `walletcreatefundedpsbt` RPC is used to create and fund a transaction in the PSBT format. It is the first step in creating the PSBT. ```bash -balance=$(./src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getbalance) +balance=$(./build/src/bitcoin-cli -signet -rpcwallet="multisig_wallet_01" getbalance) amount=$(echo "$balance * 0.8" | bc -l | sed -e 's/^\./0./' -e 's/^-\./-0./') -destination_addr=$(./src/bitcoin-cli -signet -rpcwallet="participant_1" getnewaddress) +destination_addr=$(./build/src/bitcoin-cli -signet -rpcwallet="participant_1" getnewaddress) -funded_psbt=$(./src/bitcoin-cli -signet -named -rpcwallet="multisig_wallet_01" walletcreatefundedpsbt outputs="{\"$destination_addr\": $amount}" | jq -r '.psbt') +funded_psbt=$(./build/src/bitcoin-cli -signet -named -rpcwallet="multisig_wallet_01" walletcreatefundedpsbt outputs="{\"$destination_addr\": $amount}" | jq -r '.psbt') ``` There is also the `createpsbt` RPC, which serves the same purpose, but it has no access to the wallet or to the UTXO set. It is functionally the same as `createrawtransaction` and just drops the raw transaction into an otherwise blank PSBT. [[source](https://bitcointalk.org/index.php?topic=5131043.msg50573609#msg50573609)] In most cases, `walletcreatefundedpsbt` solves the problem. @@ -183,9 +181,9 @@ Optionally, the PSBT can be decoded to a JSON format using `decodepsbt` RPC. The `analyzepsbt` RPC analyzes and provides information about the current status of a PSBT and its inputs, e.g. missing signatures. ```bash -./src/bitcoin-cli -signet decodepsbt $funded_psbt +./build/src/bitcoin-cli -signet decodepsbt $funded_psbt -./src/bitcoin-cli -signet analyzepsbt $funded_psbt +./build/src/bitcoin-cli -signet analyzepsbt $funded_psbt ``` ### 1.7 Update the PSBT @@ -195,9 +193,9 @@ In the code above, two PSBTs are created. One signed by `participant_1` wallet a The `walletprocesspsbt` is used by the wallet to sign a PSBT. ```bash -psbt_1=$(./src/bitcoin-cli -signet -rpcwallet="participant_1" walletprocesspsbt $funded_psbt | jq '.psbt') +psbt_1=$(./build/src/bitcoin-cli -signet -rpcwallet="participant_1" walletprocesspsbt $funded_psbt | jq '.psbt') -psbt_2=$(./src/bitcoin-cli -signet -rpcwallet="participant_2" walletprocesspsbt $funded_psbt | jq '.psbt') +psbt_2=$(./build/src/bitcoin-cli -signet -rpcwallet="participant_2" walletprocesspsbt $funded_psbt | jq '.psbt') ``` ### 1.8 Combine the PSBT @@ -205,7 +203,7 @@ psbt_2=$(./src/bitcoin-cli -signet -rpcwallet="participant_2" walletprocesspsbt The PSBT, if signed separately by the co-signers, must be combined into one transaction before being finalized. This is done by `combinepsbt` RPC. ```bash -combined_psbt=$(./src/bitcoin-cli -signet combinepsbt "[$psbt_1, $psbt_2]") +combined_psbt=$(./build/src/bitcoin-cli -signet combinepsbt "[$psbt_1, $psbt_2]") ``` There is an RPC called `joinpsbts`, but it has a different purpose than `combinepsbt`. `joinpsbts` joins the inputs from multiple distinct PSBTs into one PSBT. @@ -219,9 +217,9 @@ The `finalizepsbt` RPC is used to produce a network serialized transaction which It checks that all inputs have complete scriptSigs and scriptWitnesses and, if so, encodes them into network serialized transactions. ```bash -finalized_psbt_hex=$(./src/bitcoin-cli -signet finalizepsbt $combined_psbt | jq -r '.hex') +finalized_psbt_hex=$(./build/src/bitcoin-cli -signet finalizepsbt $combined_psbt | jq -r '.hex') -./src/bitcoin-cli -signet sendrawtransaction $finalized_psbt_hex +./build/src/bitcoin-cli -signet sendrawtransaction $finalized_psbt_hex ``` ### 1.10 Alternative Workflow (PSBT sequential signatures) @@ -231,11 +229,11 @@ Instead of each wallet signing the original PSBT and combining them later, the w After that, the rest of the process is the same: the PSBT is finalized and transmitted to the network. ```bash -psbt_1=$(./src/bitcoin-cli -signet -rpcwallet="participant_1" walletprocesspsbt $funded_psbt | jq -r '.psbt') +psbt_1=$(./build/src/bitcoin-cli -signet -rpcwallet="participant_1" walletprocesspsbt $funded_psbt | jq -r '.psbt') -psbt_2=$(./src/bitcoin-cli -signet -rpcwallet="participant_2" walletprocesspsbt $psbt_1 | jq -r '.psbt') +psbt_2=$(./build/src/bitcoin-cli -signet -rpcwallet="participant_2" walletprocesspsbt $psbt_1 | jq -r '.psbt') -finalized_psbt_hex=$(./src/bitcoin-cli -signet finalizepsbt $psbt_2 | jq -r '.hex') +finalized_psbt_hex=$(./build/src/bitcoin-cli -signet finalizepsbt $psbt_2 | jq -r '.hex') -./src/bitcoin-cli -signet sendrawtransaction $finalized_psbt_hex +./build/src/bitcoin-cli -signet sendrawtransaction $finalized_psbt_hex ``` |