<p>There is a <code>bitcoin::util::sighash</code> module which has all of the sighashing stuff. I'm not certain that it is the correct way, but it is definitely a way to get the result that you want.</p>
<p>It looks like you have to create a <a href="https://docs.rs/bitcoin/latest/bitcoin/util/sighash/struct.SighashCache.html" rel="nofollow noreferrer"><code>SighashCache</code></a> object, which you can then use to get all different kinds of sighashes for the transaction.</p>
<p>In your case, this code might make it work:</p>
<pre class="lang-rust prettyprint-override"><code>let previous_output_as_tx_out = TxOut {
    value: 50_0000_0000,
    script_pubkey: output_details.script_pubkey()
};
let prevouts = vec![previous_output_as_tx_out];

let mut sighash_cache = bitcoin::util::sighash::SighashCache::new(&amp;transaction);
let input_index = 0;

// taproot_key_spend_signature_hash is the crucial part
let signature_hash = sighash_cache.taproot_key_spend_signature_hash(input_index, &amp;Prevouts::All(&amp;prevouts), SchnorrSighashType::Default).unwrap();
let message = Message::from_slice(&amp;signature_hash.to_vec()).unwrap();
</code></pre>

CC BY-SA 4.0
2022-06-17T17:20:02.327Z
This is the correct way. I apologize for the misleading `Transaction::signature_hash` name, which should probably be renamed to `Transaction::legacy_signature_hash` and/or deprecated in favor of the `SighashCache` object.

To arik, the reason for the weird `SighashCache` API is that from segwit v0 onward, the signature hashes for different inputs in a transaction share a significant amount of computational work, which saves time when saving a whole transaction.
Andrew Poelstra
CC BY-SA 4.0
2022-06-17T21:06:59.630Z
Thanks for the response! There doesn't appear to be much documentation or really anything in terms of examples on how to use the `taproot_key_spend_signature_hash` method, in particular its `prevouts` parameters. But I should hopefully figure it out within a couple minutes.
arik
CC BY-SA 4.0
2022-06-17T21:19:34.093Z
All right, got it. Feel free to update your answer with the code I used :)
arik
CC BY-SA 4.0
2022-06-17T15:18:14.640Z
2022-10-19T21:36:24.130Z
2022-10-19T21:36:24.130Z
Ava Chow
<p>I'm trying to sign a segwit transaction in rust-bitcoin. To start with, my transaction setup looks as follows:</p>
<pre class="lang-rust prettyprint-override"><code>let previous_output = OutPoint::new(Txid::from_hex(&quot;991ab2b13f6bc6c13002d79d5e9775626a5e7328e14cd16837d50d1cc637dc6a&quot;).unwrap(), 0);
let tx_input = TxIn {
    previous_output,
    script_sig: Default::default(),
    sequence: 0xffffffff,
    witness: Default::default()
};

let tx_output = TxOut {
    value: 4999995000,
    script_pubkey: output_details.script_pubkey() // don't worry about this
};

let mut transaction = Transaction {
    version: 2,
    lock_time: 0,
    input: vec![tx_input],
    output: vec![tx_output]
};
</code></pre>
<p>In order to sign the transaction (using Schnorr, by the way), I extract the sighash as follows:</p>
<pre class="lang-rust prettyprint-override"><code>let signature_hash = transaction.signature_hash(0, &amp;output_details.script_pubkey(), 0); // is that really the most idiomatic way of passing a sighash flag in rust-bitcoin?
let message = Message::from_slice(&amp;signature_hash.to_vec()).unwrap();
</code></pre>
<p>When I print the hex-serialized <code>message</code>, I get the following value: <code>fa42b9b0f54972b31712b2efbc86db1bf78aa833bc9c969ea7860ef38a25fbaf</code>.</p>
<p>However, in order to sign a segwit transaction, the previous output's amount must also be committed to, and I'm not seeing a way to do that. As far as I can tell, the sighash I should be signing is in fact <code>61746ec9baa14bbe82586c7f149926b1492871c67dc7fe21e7cfe2f2260a1405</code>.</p>
<p>Finally, though less relevantly, if things were to work fine, here's how my signature process would conlude:</p>
<pre class="lang-rust prettyprint-override"><code>let signature = private_key.sign_schnorr(message);
let signature_vec = signature.as_ref().to_vec();
transaction.input[0].witness = Witness::from_vec(vec![signature_vec]);
</code></pre>
<p>Thanks in advance for helping me figure this out!</p>

<segregated-witness><transaction-input><sighash><rust-bitcoin>
How do you commit to the previous output's amount when signing a segwit input with rust-bitcoin?
arik
# How do you commit to the previous output's amount when signing a segwit input with rust-bitcoin?

(Asked by: username_0 on 2022-06-17)

I'm trying to sign a segwit transaction in rust-bitcoin. To start with, my transaction setup looks as follows:

```rust
let previous_output = OutPoint::new(Txid::from_hex("991ab2b13f6bc6c13002d79d5e9775626a5e7328e14cd16837d50d1cc637dc6a").unwrap(), 0);
let tx_input = TxIn {
    previous_output,
    script_sig: Default::default(),
    sequence: 0xffffffff,
    witness: Default::default()
};

let tx_output = TxOut {
    value: 4999995000,
    script_pubkey: output_details.script_pubkey() // don't worry about this
};

let mut transaction = Transaction {
    version: 2,
    lock_time: 0,
    input: vec![tx_input],
    output: vec![tx_output]
};

```

In order to sign the transaction (using Schnorr, by the way), I extract the sighash as follows:

```rust
let signature_hash = transaction.signature_hash(0, &output_details.script_pubkey(), 0); // is that really the most idiomatic way of passing a sighash flag in rust-bitcoin?
let message = Message::from_slice(&signature_hash.to_vec()).unwrap();

```

When I print the hex-serialized `message`, I get the following value: `fa42b9b0f54972b31712b2efbc86db1bf78aa833bc9c969ea7860ef38a25fbaf`.

However, in order to sign a segwit transaction, the previous output's amount must also be committed to, and I'm not seeing a way to do that. As far as I can tell, the sighash I should be signing is in fact `61746ec9baa14bbe82586c7f149926b1492871c67dc7fe21e7cfe2f2260a1405`.

Finally, though less relevantly, if things were to work fine, here's how my signature process would conlude:

```rust
let signature = private_key.sign_schnorr(message);
let signature_vec = signature.as_ref().to_vec();
transaction.input[0].witness = Witness::from_vec(vec![signature_vec]);

```

Thanks in advance for helping me figure this out!

**Tags:** segregated-witness, transaction-input, sighash, rust-bitcoin


---

## 1 answers

### Answer by username_1 on 2022-06-17. Score: 4 | Accepted answer

There is a `bitcoin::util::sighash` module which has all of the sighashing stuff. I'm not certain that it is the correct way, but it is definitely a way to get the result that you want.

It looks like you have to create a [`SighashCache`](https://docs.rs/bitcoin/latest/bitcoin/util/sighash/struct.SighashCache.html) object, which you can then use to get all different kinds of sighashes for the transaction.

In your case, this code might make it work:

```rust
let previous_output_as_tx_out = TxOut {
    value: 50_0000_0000,
    script_pubkey: output_details.script_pubkey()
};
let prevouts = vec![previous_output_as_tx_out];

let mut sighash_cache = bitcoin::util::sighash::SighashCache::new(&transaction);
let input_index = 0;

// taproot_key_spend_signature_hash is the crucial part
let signature_hash = sighash_cache.taproot_key_spend_signature_hash(input_index, &Prevouts::All(&prevouts), SchnorrSighashType::Default).unwrap();
let message = Message::from_slice(&signature_hash.to_vec()).unwrap();

```

> **Comments:**
> **username_2**: This is the correct way. I apologize for the misleading `Transaction::signature_hash` name, which should probably be renamed to `Transaction::legacy_signature_hash` and/or deprecated in favor of the `SighashCache` object.  To username_0, the reason for the weird `SighashCache` API is that from segwit v0 onward, the signature hashes for different inputs in a transaction share a significant amount of computational work, which saves time when saving a whole transaction.  
> **username_0**: Thanks for the response! There doesn't appear to be much documentation or really anything in terms of examples on how to use the `taproot_key_spend_signature_hash` method, in particular its `prevouts` parameters. But I should hopefully figure it out within a couple minutes.  
> **username_0**: All right, got it. Feel free to update your answer with the code I used :)  

---

