You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge #34: Various improvements of Taproot signing example
30563ea Various improvements of Taproot signing example (Martin Habovštiak)
Pull request description:
The Taproot signing example had some parts that were unidiomatic, weirdly worded or just plain wrong. This change fixes some of them though not all. There's still things missing such as using `witness_mut` method on `SighashCache` and possibly things I missed because I was only looking for obvious things.
ACKs for top commit:
storopoli:
ACK 30563ea
apoelstra:
ACK 30563ea
Tree-SHA512: 43607b70679dfb4805954e198249f13ab94b455fde9e511e7df3c1aed9c107410797494864055fb20f07e09f54137321413081e9dfadd0f24ea60debcd46f8d8
In a real application this would be the address of the receiver.
83
-
We use the method `Address::from_str` to parse the string `"bc1p0dq0tzg2r780hldthn5mrznmpxsxc0jux5f20fwj0z3wqxxk6fpqm7q0va"`[^arbitrary_address] into an address.
84
-
Hence, it is necessary to import the `std::str::FromStr` trait.
79
+
We use the `parse` method on `&str` to parse `"bc1p0dq0tzg2r780hldthn5mrznmpxsxc0jux5f20fwj0z3wqxxk6fpqm7q0va"`[^arbitrary_address] as an address.
85
80
Note that `bc1p0dq0tzg2r780hldthn5mrznmpxsxc0jux5f20fwj0z3wqxxk6fpqm7q0va` is a [Bech32](https://bitcoinops.org/en/topics/bech32/) address.
86
81
This is an arbitrary, however valid, Bitcoin mainnet address.
87
-
Hence we use the `require_network` method to ensure that the address is valid for mainnet.
82
+
Bitcoin applications are usually configured with specific Bitcoin network at the start and use that.
83
+
To prevent mistakes related to people sending satoshis to a wrong network we need to call the `require_network` method to ensure that the address is valid for the network, in our case mainnet.
@@ -129,14 +125,12 @@ and a value of the `const DUMMY_UTXO_AMOUNT` that we defined earlier.
129
125
P2TR UTXOs could be tweaked ([`TweakedPublicKey`](https://docs.rs/bitcoin/0.32.0/bitcoin/key/struct.TweakedPublicKey.html))
130
126
or untweaked ([`UntweakedPublicKey`](https://docs.rs/bitcoin/0.32.0/bitcoin/key/type.UntweakedPublicKey.html)).
131
127
We are using the latter, since we are not going to tweak the key.
132
-
We are using the [`OutPoint`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.OutPoint.html) struct to represent the transaction output.
128
+
We are using the [`OutPoint`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.OutPoint.html) struct to represent the previous transaction output.
133
129
Finally, we return the tuple `(out_point, utxo)`.
134
130
135
131
Now we are ready for our main function that will sign a transaction that spends a `p2tr` unspent output:
@@ -263,19 +257,19 @@ All of these are helper functions that we defined earlier.
263
257
In `let input = TxIn {...}` we are instantiating the input for the transaction we are constructing
264
258
Inside the [`TxIn`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.TxIn.html) struct we are setting the following fields:
265
259
266
-
-`previous_output` is the outpoint of the dummy UTXO we are spending; it is a[`OutPoint`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.OutPoint.html) type.
267
-
-`script_sig` is the script code required to spend an output; it is a[`ScriptBuf`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/script/struct.ScriptBuf.html) type.
260
+
-`previous_output` is the outpoint of the dummy UTXO we are spending; it has the[`OutPoint`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.OutPoint.html) type.
261
+
-`script_sig` is the script code required to spend an output; it has the[`ScriptBuf`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/script/struct.ScriptBuf.html) type.
268
262
We are instantiating a new empty script with [`ScriptBuf::new()`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/script/struct.ScriptBuf.html#method.new).
269
-
-`sequence` is the sequence number; it is a[`Sequence`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.Sequence.html) type.
263
+
-`sequence` is the sequence number; it has the[`Sequence`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.Sequence.html) type.
270
264
We are using the [`ENABLE_RBF_NO_LOCKTIME`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.Sequence.html#associatedconstant.ENABLE_RBF_NO_LOCKTIME) constant.
271
-
-`witness` is the witness stack; it is a[`Witness`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/witness/struct.Witness.html) type.
265
+
-`witness` is the witness stack; has the[`Witness`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/witness/struct.Witness.html) type.
272
266
We are using the [`default`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/witness/struct.Witness.html#impl-Default) method to create an empty witness that will be filled in later after signing.
273
267
This is possible because `Witness` implements the [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) trait.
274
268
275
269
In `let spend = TxOut {...}` we are instantiating the spend output.
276
270
Inside the [`TxOut`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.TxOut.html) struct we are setting the following fields:
277
271
278
-
-`value` is the amount we are spending; it is a[`u64`](https://doc.rust-lang.org/std/primitive.u64.html) type.
272
+
-`value` is the amount we are assigning to be spendable by given `script_pubkey`; it has the[`Amount`](https://docs.rs/bitcoin/0.32.0/bitcoin/struct.Amount.html) type.
279
273
We are using the `const SPEND_AMOUNT` that we defined earlier.
280
274
-`script_pubkey` is the script code required to spend a P2TR output; it is a [`ScriptBuf`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/script/struct.ScriptBuf.html) type.
281
275
We are using the [`script_pubkey`](https://docs.rs/bitcoin/0.32.0/bitcoin/address/struct.Address.html#method.script_pubkey) method to generate the script pubkey from the receivers address.
@@ -289,7 +283,7 @@ which generates P2TR-type of script pubkey.
289
283
In `let unsigned_tx = Transaction {...}` we are instantiating the transaction we want to sign and broadcast using the [`Transaction`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.Transaction.html) struct.
290
284
We set the following fields:
291
285
292
-
-`version` is the transaction version; it is a[`i32`](https://doc.rust-lang.org/std/primitive.u32.html) type.
286
+
-`version` is the transaction version; it has the[`transaction::Version`](https://docs.rs/bitcoin/0.32.2/bitcoin/blockdata/transaction/struct.Version.html) type.
293
287
We are using version `2` which means that [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) applies.
294
288
-`lock_time` is the transaction lock time;
295
289
it is a [`LockTime`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/locktime/absolute/enum.LockTime.html) enum.
@@ -312,13 +306,14 @@ This is a type that efficiently calculates [signature hash message](https://deve
312
306
We are using the `new` method to instantiate the struct with the `unsigned_tx` that we defined earlier.
313
307
`new` takes any `Borrow<Transaction>` as an argument.
314
308
[`Borrow<T>`](https://doc.rust-lang.org/std/borrow/trait.Borrow.html) is a trait that allows us to pass either a reference to a `T` or a `T` itself.
315
-
Hence, you can pass a `Transaction` or a `&Transaction` to `new`.
309
+
Hence, you can pass a `Transaction`, a `&Transaction` or a smart pointer to `new`.
316
310
317
-
`sighash_cache` is instantiated as mutable because we require a mutable reference when creating the sighash to sign using [`taproot_signature_hash`](https://docs.rs/bitcoin/0.32.0/bitcoin/sighash/struct.SighashCache.html#method.taproot_signature_hash) to it.
311
+
`sighash_cache` is bound as mutable because we are updating it with computed values during signing.
312
+
This is reflected by [`taproot_signature_hash`](https://docs.rs/bitcoin/0.32.0/bitcoin/sighash/struct.SighashCache.html#method.taproot_signature_hash) taking a mutable reference.
318
313
This computes the [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) sighash for any flag type.
319
314
It takes the following arguments:
320
315
321
-
-`input_index` is the index of the input we are signing; it is a[`usize`](https://doc.rust-lang.org/std/primitive.usize.html) type.
316
+
-`input_index` is the index of the input we are signing; it has the[`usize`](https://doc.rust-lang.org/std/primitive.usize.html) type.
322
317
We are using `0` since we only have one input.
323
318
-`&prevouts` is a reference to the [`Prevouts`](https://docs.rs/bitcoin/0.32.0/bitcoin/sighash/enum.Prevouts.html) enum that we defined earlier.
324
319
This is used to reference the outputs of previous transactions and also used to calculate our transaction value.
@@ -330,19 +325,19 @@ It takes the following arguments:
330
325
We are using the [`All`](https://docs.rs/bitcoin/0.32.0/bitcoin/sighash/enum.TapSighashType.html#variant.All) variant,
331
326
which indicates that the sighash will include all the inputs and outputs.
332
327
333
-
Taproot signatures are generated by tweaking the private (and public) key(s).
We create the message `msg` by converting the `sighash` to a [`Message`](https://docs.rs/secp256k1/0.29.0/secp256k1/struct.Message.html) type.
337
332
This is a the message that we will sign.
338
-
The [Message::from](https://docs.rs/secp256k1/0.29.0/secp256k1/struct.Message.html#impl-From%3C%26%27_%20bitcoin%3A%3Ahashes%3A%3Asha256d%3A%3AHash%3E) method takes anything that implements the promises to be a thirty two byte hash i.e., 32 bytes that came from a cryptographically secure hashing algorithm.
333
+
The [Message::from](https://docs.rs/secp256k1/0.29.0/secp256k1/struct.Message.html#impl-From%3C%26%27_%20bitcoin%3A%3Ahashes%3A%3Asha256d%3A%3AHash%3E) method is available for types that are intended and safe for signing.
339
334
340
335
We compute the signature `sig` by using the [`sign_schnorr`](https://docs.rs/secp256k1/0.29.0/secp256k1/struct.Secp256k1.html#method.sign_schnorr) method.
341
336
It takes a reference to a [`Message`](https://docs.rs/secp256k1/0.29.0/secp256k1/struct.Message.html) and a reference to a [`Keypair`](https://docs.rs/secp256k1/0.29.0/secp256k1/struct.Keypair.html) as arguments,
342
337
and returns a [`Signature`](https://docs.rs/secp256k1/0.29.0/secp256k1/ecdsa/struct.Signature.html) type.
343
338
344
-
In the next step, we update the witness stack for the input we just signed by first converting the`sighash_cache` into a[`Transaction`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.Transaction.html)
345
-
by using the [`into_transaction`](https://docs.rs/bitcoin/0.32.0/bitcoin/sighash/struct.SighashCache.html#method.into_transaction) method.
339
+
In the next step, we update the witness stack for the input we just signed by first releasing the [`Transaction`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/transaction/struct.Transaction.html)
340
+
from `sighash_cache`by using the [`into_transaction`](https://docs.rs/bitcoin/0.32.0/bitcoin/sighash/struct.SighashCache.html#method.into_transaction) method.
346
341
We access the witness field of the first input with `tx.input[0].witness`.
347
342
It is a [`Witness`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/witness/struct.Witness.html) type.
348
343
We use the [`push`](https://docs.rs/bitcoin/0.32.0/bitcoin/blockdata/witness/struct.Witness.html#method.push) method
0 commit comments