examples: Add taproot PSBT example workflow#999
examples: Add taproot PSBT example workflow#999apoelstra merged 1 commit intorust-bitcoin:masterfrom
Conversation
|
Looks like a great start! |
|
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. |
|
This looks great. Thanks for the detailed instructions, I will try out them to see if I can re-produce the results. |
|
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 :) |
4924c33 to
fc63631
Compare
|
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. |
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
This is stale now, right? We have the println statement below that serves as documentation, same for the other examples.
There was a problem hiding this comment.
Oh yeah, I should clear that up. Thanks!
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
Does this mean there is going to be an example 3 added or are 2.1 and 2.2 counted as two?
There was a problem hiding this comment.
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?
|
BDK's |
|
I attempted to run through the example but got stuck on 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? |
fc63631 to
fea07e2
Compare
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? |
fea07e2 to
022525c
Compare
|
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. |
|
I don't think its descriptors being default that is the problem because I was passing |
There was a problem hiding this comment.
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.
examples/taproot-psbt.rs
Outdated
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Great, yeah that will be much easier!
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
| 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. |
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
Perhaps use consts for the values that users are not expected to change?
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
| let (tx, _) = benefactor.create_inheritance_funding_tx(1000, UTXO_2)?; | |
| let (tx, psbt) = benefactor.create_inheritance_funding_tx(1200, UTXO_3)?; |
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
| 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.
There was a problem hiding this comment.
We could use a const for the fee as well so as not to confuse it with locktime?
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
If you change the locktime then this will need updating too.
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
Yes, indeed! Sorry, just getting back to this today :)
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
| psbt.outputs = vec![Output { ..Default::default() }]; | |
| psbt.outputs = vec![Output::default()]; |
examples/taproot-psbt.rs
Outdated
There was a problem hiding this comment.
| use bitcoin_hashes::Hash; | |
| use bitcoin::hashes::Hash; |
|
@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! 🙏 |
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
022525c to
2765fb1
Compare
|
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. |
2765fb1 to
8df9a0b
Compare
|
Note, if #1079 goes in before this we will need to add a clippy call to |
tcharding
left a comment
There was a problem hiding this comment.
ACK 8df9a0b31cfca420c8949d619905faee789a84bb
… 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
|
Rebasing and getting this ready for a final review. Apologies for the hold up. |
8df9a0b to
c05188a
Compare
|
To fix CI use: "\nYou should now be able to broadcast the following transaction: \n\n{}", tx_hex_string |
|
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
left a comment
There was a problem hiding this comment.
ACK c05188a878501e8ff953f88b47897431e4385536
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.
c05188a to
1a89d52
Compare
|
We can clean this up nicely when we extend the PSBT input signing API for schnorr/taproot :) |
|
Can we get a second ACK on this one please? The PR only adds code to |
|
BOOM! |
…itcoin#999 I will test merge commits more thoroughly before signing off on them in future, sorry.
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
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.