Skip to content

examples: Add taproot PSBT example workflow#999

Merged
apoelstra merged 1 commit intorust-bitcoin:masterfrom
dunxen:2022-05-taproot-psbt-example
Oct 25, 2022
Merged

examples: Add taproot PSBT example workflow#999
apoelstra merged 1 commit intorust-bitcoin:masterfrom
dunxen:2022-05-taproot-psbt-example

Conversation

@dunxen
Copy link
Copy Markdown
Contributor

@dunxen dunxen commented May 24, 2022

Will address #893.

Currently includes a BIP86 example (no spendable script path)

Working on script path and key path spending when both are possible spending paths.

@apoelstra
Copy link
Copy Markdown
Member

Looks like a great start!

@tcharding
Copy link
Copy Markdown
Member

Looks good man, I'll be watching this one closely (your code and reviewers comments) so I can work out how to do #957. If you want to have input on that PR, that would be awesome too.

@sanket1729
Copy link
Copy Markdown
Member

This looks great. Thanks for the detailed instructions, I will try out them to see if I can re-produce the results.

@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Jun 2, 2022

Planning to get back to cleaning up the script path spending today and will try get it up this weekend. I just want to structure it properly otherwise it will be a bit messy to follow. It also requires instructions on actually constructing the output which is trickier IMO :)

@dunxen dunxen force-pushed the 2022-05-taproot-psbt-example branch from 4924c33 to fc63631 Compare June 15, 2022 13:23
@tcharding
Copy link
Copy Markdown
Member

tcharding commented Jun 20, 2022

Bro, this is sick! I read through the code, I'll have a play with bitcoind and verify all the docs and stuff for you.

Copy link
Copy Markdown
Member

@tcharding tcharding Jun 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is stale now, right? We have the println statement below that serves as documentation, same for the other examples.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, I should clear that up. Thanks!

Copy link
Copy Markdown
Member

@tcharding tcharding Jun 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean there is going to be an example 3 added or are 2.1 and 2.2 counted as two?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was only going to have those 3 but it seems a little confusing so will renumber. I'd also like to show a larger taptree example but not sure if we need to worry about that too much?

@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Jun 21, 2022

BDK's sign_psbt_schnorr() has mostly what we need for taproot support in the PSBT signing API PR @tcharding :)
I can add onto that one in a follow-up PR once you get it through. I'll review a bit of that today again too.

@tcharding
Copy link
Copy Markdown
Member

I attempted to run through the example but got stuck on Step 3, I couldn't get bitcoin-cli to get a new taproot address.

bt -rpcwallet=benefactor getnewaddress '' bech32m
error code: -12
error message:
Error: No bech32m addresses available.

I tried creating wallets with a bunch of different options to no avail. I tried importing an xpriv also to no avail. The closest I got was I did manage to import an xpub and create a taproot address. Any ideas?

@dunxen dunxen force-pushed the 2022-05-taproot-psbt-example branch from fc63631 to fea07e2 Compare June 22, 2022 09:45
@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Jun 22, 2022

I attempted to run through the example but got stuck on Step 3, I couldn't get bitcoin-cli to get a new taproot address.

bt -rpcwallet=benefactor getnewaddress '' bech32m
error code: -12
error message:
Error: No bech32m addresses available.

I tried creating wallets with a bunch of different options to no avail. I tried importing an xpriv also to no avail. The closest I got was I did manage to import an xpub and create a taproot address. Any ideas?

Thanks for trying to run it! I think I assumed these steps from a v23.0 perspective where descriptor wallets are default. I've updated it to indicate we need descriptor wallets. I think that's the issue you're having if I'm not mistaken?

@dunxen dunxen force-pushed the 2022-05-taproot-psbt-example branch from fea07e2 to 022525c Compare June 22, 2022 09:51
@tcharding
Copy link
Copy Markdown
Member

oooh, I was using 22.0 assuming Taproot was all that's required. Serves me right for not updating :( Will play some more with it, cheers mate.

@tcharding
Copy link
Copy Markdown
Member

I don't think its descriptors being default that is the problem because I was passing descriptors=true to createwallet. I started building bitcoind to get v23 but thought better of it. We should support the latest released version of bitcoind I rekon. I'll keep playing with v22 and see if I can work it out. Cheers.

Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one man, I got it all running using Bitcoin Core v23. I made a few minor changes to the third example so that all three examples could be worked through. Gave a few docs suggestions, use them as you wish. Gave a couple minor code suggestions but I did not review the exact logic of the two wallet types, simply because I'm not knowledgeable enough to do so.

I can confirm that I worked through all three examples.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace on this line.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't get this to work with v22 but v23 has been released now so I'd suggest just stating that the example docs are for Bitcoin Core v23. If you do that you can remove the descriptors=true from this and below.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, yeah that will be much easier!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
derivation_path: "m/86'/1'/0'/0/0", // The derivation path for the key that can spend this UTXO (from descriptor in step 4)
derivation_path: "m/86'/1'/0'/0/0", // The derivation path for the key that can spend this UTXO (from descriptor in step 4), you shouldn't need to change this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps use consts for the values that users are not expected to change?

Copy link
Copy Markdown
Member

@tcharding tcharding Jun 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let (tx, _) = benefactor.create_inheritance_funding_tx(1000, UTXO_2)?;
let (tx, psbt) = benefactor.create_inheritance_funding_tx(1200, UTXO_3)?;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let spending_tx_hex = encode::serialize_hex(&spending_tx);
let spending_tx = beneficiary.spend_inheritance(psbt, 1200, &to_address, 1000)?;
let spending_tx_hex = encode::serialize_hex(&spending_tx);

Note I used 1200 instead of 1000 otherwise one cannot verify the locktime if example two has already been done.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use a const for the fee as well so as not to confuse it with locktime?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you change the locktime then this will need updating too.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still a todo?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, indeed! Sorry, just getting back to this today :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
psbt.outputs = vec![Output { ..Default::default() }];
psbt.outputs = vec![Output::default()];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course 🤦‍♂️ 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
use bitcoin_hashes::Hash;
use bitcoin::hashes::Hash;

@sanket1729
Copy link
Copy Markdown
Member

@dunxen Is this ready for review? If you have some more changes to make, feel free to tag me for review once you think this is ready. No rush :)

@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Jul 18, 2022

@dunxen Is this ready for review? If you have some more changes to make, feel free to tag me for review once you think this is ready. No rush :)

Been working on the last bits today and adding some changes from previous review.

Thanks, I will definitely tag you when ready! 🙏

sanket1729 added a commit that referenced this pull request Jul 19, 2022
cd2369b Run ecdsa-psbt example in test script (Tobin C. Harding)
6967c0e Add psbt example (Tobin Harding)

Pull request description:

  Add an example PSBT workflow. The workflow we simulate is that of a setup using a watch-only online wallet (contains only public keys) and a cold-storage wallet (contains the private keys).

  We create and update a PSBT using the watch-only wallet then pass the PSBT to the cold-storage wallet to sign.

  Partially resolves #892 (more done in #935).

  ## Note

  This PR includes a sub-module in `examples/psbt.rs` that implements ECDSA signing. This will hopefully eventually be merged into the main crate by way of #957.  We have three PRs that add examples/tests of PSBTs that need to do signing, in order to help us design a good AP in #957 I think it would be beneficial to complete and merge these three PRs.

  1. This PR (PSBT ECDSA example)
  2. PBST ECDSA integration test: #935
  3. PSBT taproot example: #999

  Note to self, this will need a change to `test.sh` if #1079 merges.

ACKs for top commit:
  apoelstra:
    ACK cd2369b
  sanket1729:
    ACK cd2369b. The example is clean, you can address the comments in followups.

Tree-SHA512: c4fb8ec631bf8bfc30534e8974b1f6c4bb7cc6def165a4ee2bb7aa73f5aa7fdc11d2000ca25792a4b534b2c5bf1592efe542ada14a9d702c7dfacbaa808f3aea
@dunxen dunxen force-pushed the 2022-05-taproot-psbt-example branch from 022525c to 2765fb1 Compare July 21, 2022 08:27
@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Jul 21, 2022

Just needed a rebase, but will limit the squashing/rebasing from now when I've promoted it from draft. There's probably still a bit of cleanup and dedup left.

@dunxen dunxen marked this pull request as ready for review July 21, 2022 08:28
@dunxen dunxen force-pushed the 2022-05-taproot-psbt-example branch from 2765fb1 to 8df9a0b Compare July 21, 2022 08:31
@tcharding
Copy link
Copy Markdown
Member

Note, if #1079 goes in before this we will need to add a clippy call to test.sh.

tcharding
tcharding previously approved these changes Jul 21, 2022
Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 8df9a0b31cfca420c8949d619905faee789a84bb

ChallengeDev210 pushed a commit to ChallengeDev210/rust-bitcoin that referenced this pull request Aug 1, 2022
… example

cd2369b Run ecdsa-psbt example in test script (Tobin C. Harding)
6967c0e Add psbt example (Tobin Harding)

Pull request description:

  Add an example PSBT workflow. The workflow we simulate is that of a setup using a watch-only online wallet (contains only public keys) and a cold-storage wallet (contains the private keys).

  We create and update a PSBT using the watch-only wallet then pass the PSBT to the cold-storage wallet to sign.

  Partially resolves #892 (more done in #935).

  ## Note

  This PR includes a sub-module in `examples/psbt.rs` that implements ECDSA signing. This will hopefully eventually be merged into the main crate by way of rust-bitcoin/rust-bitcoin#957.  We have three PRs that add examples/tests of PSBTs that need to do signing, in order to help us design a good AP in #957 I think it would be beneficial to complete and merge these three PRs.

  1. This PR (PSBT ECDSA example)
  2. PBST ECDSA integration test: rust-bitcoin/rust-bitcoin#935
  3. PSBT taproot example: rust-bitcoin/rust-bitcoin#999

  Note to self, this will need a change to `test.sh` if #1079 merges.

ACKs for top commit:
  apoelstra:
    ACK cd2369b
  sanket1729:
    ACK cd2369b. The example is clean, you can address the comments in followups.

Tree-SHA512: c4fb8ec631bf8bfc30534e8974b1f6c4bb7cc6def165a4ee2bb7aa73f5aa7fdc11d2000ca25792a4b534b2c5bf1592efe542ada14a9d702c7dfacbaa808f3aea
@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Sep 15, 2022

Rebasing and getting this ready for a final review. Apologies for the hold up.

@tcharding
Copy link
Copy Markdown
Member

To fix CI use:

"\nYou should now be able to broadcast the following transaction: \n\n{}", tx_hex_string

@tcharding
Copy link
Copy Markdown
Member

Looks good to me bro, I had a bit of a fiddle with the imports, mainly because they displayed how untidy our API is (cleaning it up is one thing I'm working on right now). No need to change but if you are interested this is what I did

diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs
index e43f7546..043d8f86 100644
--- a/bitcoin/examples/taproot-psbt.rs
+++ b/bitcoin/examples/taproot-psbt.rs
@@ -78,30 +78,26 @@ const UTXO_3: P2trUtxo = P2trUtxo {
 use std::collections::BTreeMap;
 use std::str::FromStr;
 
-use bitcoin::absolute::PackedLockTime;
 use bitcoin::consensus::encode;
 use bitcoin::constants::COIN_VALUE;
 use bitcoin::hashes::hex::FromHex;
-use bitcoin::locktime::absolute;
+use bitcoin::hashes::Hash;
 use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP};
 use bitcoin::psbt::serialize::Serialize;
-use bitcoin::psbt::Output;
+use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType};
 use bitcoin::schnorr::TapTweak;
-use bitcoin::secp256k1::Secp256k1;
+use bitcoin::secp256k1::{Message, Secp256k1};
 use bitcoin::util::bip32::{
     ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint,
 };
-use bitcoin::util::psbt::{self, Input, Psbt, PsbtSighashType};
 use bitcoin::util::sighash;
 use bitcoin::util::taproot::{
     LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo,
 };
 use bitcoin::{
-    script, Address, Amount, OutPoint, SchnorrSig, SchnorrSighashType, Script, SighashCache,
-    Transaction, TxIn, TxOut, Txid, Witness, XOnlyPublicKey,
+    absolute, script, Address, Amount, OutPoint, SchnorrSig, SchnorrSighashType, Script,
+    SighashCache, Transaction, TxIn, TxOut, Txid, Witness, XOnlyPublicKey,
 };
-use bitcoin_hashes::Hash;
-use secp256k1::Message;
 
 fn main() -> Result<(), Box<dyn std::error::Error>> {
     let secp = Secp256k1::new();
@@ -133,7 +129,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
         ],
     )?);
     println!(
-        "\nYou should now be able to broadcast the following transaction: \n\n{tx_hex_string}",
+        "\nYou should now be able to broadcast the following transaction: \n\n{}", tx_hex_string
     );
 
     println!("\nEND EXAMPLE 1\n");
@@ -637,7 +633,7 @@ impl BeneficiaryWallet {
         let input_value = psbt.inputs[0].witness_utxo.as_ref().unwrap().value;

tcharding
tcharding previously approved these changes Sep 15, 2022
Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK c05188a878501e8ff953f88b47897431e4385536

@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Sep 16, 2022

To fix CI use:

"\nYou should now be able to broadcast the following transaction: \n\n{}", tx_hex_string

Oh yeah. MSRV things

This example shows how to use the PSBT API for taproot transactions.
We have a simple BIP86-style spend and an example of an inheritance
timelock that can be spent either by the beneficiary via the script
path after a timelock, or via the key path by the benefactor so that
they can refresh the timelock at any time.
@dunxen
Copy link
Copy Markdown
Contributor Author

dunxen commented Sep 16, 2022

We can clean this up nicely when we extend the PSBT input signing API for schnorr/taproot :)

Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 1a89d52

@tcharding
Copy link
Copy Markdown
Member

Can we get a second ACK on this one please? The PR only adds code to bitcoin/examples so there is no risk of merging without deep security review. All the other psbt example and signing improvements have merged now.

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 1a89d52

@apoelstra apoelstra merged commit 9fb8c21 into rust-bitcoin:master Oct 25, 2022
@tcharding
Copy link
Copy Markdown
Member

BOOM!

apoelstra added a commit to apoelstra/rust-bitcoin that referenced this pull request Oct 25, 2022
…itcoin#999

I will test merge commits more thoroughly before signing off on them in future, sorry.
sanket1729 added a commit that referenced this pull request Oct 27, 2022
c4084b9 Fix broken build due to conflict between #1340 and #999 (Andrew Poelstra)

Pull request description:

  I will test merge commits more thoroughly before signing off on them in future, sorry.

ACKs for top commit:
  DanGould:
    tACK c4084b9
  tcharding:
    ACK c4084b9
  sanket1729:
    ACK c4084b9

Tree-SHA512: 51ece3aa43045e81138d21b8402b1ec1559a0b37bdfc4c5246ff46fd085364517449a2e20e625934cbc0c96f18eb2fc6121a6e993fd5b9535ae54c863d032a0b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants