<p>I have the following code laying around for the transaction <code>663becacc6368150a46725e404ccdfa34d1fffbececa784c31f0a7849b4dad08</code>, which I picked off my mempool the other day, whose hex is:</p>
<p><code>020000000001015ce1d4ffc716022f83cc0d557e6dad0500eeff9e9623bde014bdc09c5b672d750000000000fdffffff025fb7460b000000001600142cf4c1dc0352e0658971ca62a7457a1cd8c3389c4ce3a2000000000016001433f57fe374c6ceab61c8639128c038ac2a8c8db60247304402203cb50efb5c4a9aa7fd369ab6f4b226db99f44f9c610b5b50bc42f343a6aa401302201af791542eee6c1b11705e8895cc5adc36458910dc91aadcafb76a6478a29b9f01210242e811e66fd17e9a6e4ef772766c668d6e0595ca1d7f0583148bc460b575fbfdf0df0b00</code></p>
<pre class="lang-rust prettyprint-override"><code>use bitcoin::consensus::deserialize;
use bitcoin::hashes::{hex, sha256d, Hash};
use bitcoin::util::sighash;
use std::env;
use std::str::FromStr;

fn main() { 
    let rawtx = env::args().skip(1).next().unwrap();

    let bytes: Vec&lt;u8&gt; = hex::FromHex::from_hex(&amp;rawtx)
        .expect(&quot;hex decoding&quot;);
    let tx: bitcoin::Transaction = deserialize(&amp;bytes)
        .expect(&quot;tx deserialization&quot;);

    let pk = bitcoin::secp256k1::PublicKey::from_str(
        &quot;0242e811e66fd17e9a6e4ef772766c668d6e0595ca1d7f0583148bc460b575fbfd&quot;,
    ).unwrap();

    let mut sighash = sighash::SighashCache::new(&amp;tx);
    let mut out_bytes = vec![];
    sighash.segwit_encode_signing_data_to(
        &amp;mut out_bytes,
        0,
        &amp;bitcoin::Script::from_str(&quot;76a914f5693fbaf062221baf891d813d5856e4f8ab54eb88ac&quot;).unwrap(),
        200000000,
        bitcoin::EcdsaSighashType::All,
    ).expect(&quot;computing sighash&quot;);


    println!(&quot;{}&quot;, hex::ToHex::to_hex(&amp;out_bytes[..]));

    let sig = bitcoin::secp256k1::ecdsa::Signature::from_str(
        &quot;304402203cb50efb5c4a9aa7fd369ab6f4b226db99f44f9c610b5b50bc42f343a6aa401302201af791542eee6c1b11705e8895cc5adc36458910dc91aadcafb76a6478a29b9f&quot;,
    ).unwrap();
    let secp = bitcoin::secp256k1::Secp256k1::new();

    let hash = sha256d::Hash::hash(&amp;out_bytes);
    let msg = bitcoin::secp256k1::Message::from_slice(&amp;hash[..]).unwrap();
    secp.verify_ecdsa(
        &amp;msg,
        &amp;sig,
        &amp;pk,
    ).unwrap();
}
</code></pre>
<p>This works only for this specific p2wpkh transaction, but it may help you get started. The weird thing is that the <code>script_code</code> is created by synthethizing a p2pkh output from the p2wpkh output. For p2wsh or p2sh (as any CHECKMULTISIG) script will be, this is simpler: you can just use the redeem/witness script here.</p>

CC BY-SA 4.0
2023-03-06T14:48:49.767Z
2023-03-06T14:48:49.767Z
Andrew Poelstra
<p>I created a <a href="https://github.com/panicfarm/multisig-test/" rel="nofollow noreferrer">GitHub repo</a> with the answer examples.</p>

CC BY-SA 4.0
2023-03-30T22:54:12.237Z
2023-03-30T22:54:12.237Z
Alec Matusis
<p>I am looking for code examples (in <a href="https://docs.rs/bitcoin/latest/bitcoin/" rel="nofollow noreferrer">rust-bitcoin</a>, but even in Python) of how to calculate sighash for various input types. Specifically, I need to calculate the sighashes for M of N multisig unlocking script inputs for these transaction types: P2MS, P2SH, P2WSH  and P2TR (to determine which M of N keys correspond to the M input signatures).</p>
<p>For example for a P2SH case, I am looking at <a href="https://blockstream.info/tx/9cdb8525f3b9cbc0016baa90040fd42f191e115fecb75518a461c73d51f4e47a?expand" rel="nofollow noreferrer">output 0 in this tx</a>.</p>
<p>In the <a href="https://blockstream.info/tx/3589ada609ec2bbbb7a1ab0cee292eae4227ecaff5e327059b7ef101b4f1d965?expand" rel="nofollow noreferrer">spending transaction</a>, the input #3 contains a redeem 2 of 3 mutisig script with 3 compressed 33 byte PubKeys</p>
<p><code>OP_PUSHNUM_2 OP_PUSHBYTES_33 02261f84d51bb64371cb5e9eec3bbc0c0c7320eb7fa9c5076a394a48a9cd74bfd3 OP_PUSHBYTES_33 023e66621cf94ac25d8bb687abef86d01847805d6e9bff8c3999f18f478cde5ab6 OP_PUSHBYTES_33 02d844059fae247b8e1325f56519d1eb7d4b632ec77b9f71f03102167f3c7fa591 OP_PUSHNUM_3 OP_CHECKMULTISIG</code></p>
<p>and two signatures in the ScriptSig (<code>OP_PUSHBYTES_71</code> and <code>OP_PUSHBYTES_72</code>). I concretely want to know which two of the three PubKeys above correspond to these two signatures.</p>
<p>For that, I need to <a href="https://en.bitcoin.it/wiki/OP_CHECKMULTISIG" rel="nofollow noreferrer">double-loop</a> over the two keys and the three signatures and pass these pairs along with the scriphash into <a href="https://docs.rs/secp256k1/latest/secp256k1/struct.Secp256k1.html#method.verify_ecdsa" rel="nofollow noreferrer"><code>verify_ecdsa(&amp;script_hash, &amp;signature, &amp;pubkey)</code></a> from <a href="https://docs.rs/secp256k1/latest/secp256k1/struct.Secp256k1.html" rel="nofollow noreferrer">secp256k1</a>, and I would like to understand in detail how to compute the sighashes. I am also not clear if these multisig inputs can have any of these three sighash flags <code>SIGHASH_ALL</code>, <code>SIGHASH_SINGLE</code> and <code>SIGHASH_NONE</code>, or only the first one is ever used with multisig?</p>
<p>PS. In the <a href="https://bitcoin.stackexchange.com/a/117478/137810">Andrew Poelstra's answer</a>, there's an example sighash computation for P2WPKH. Although I do not need the P2(W)PKH cases because I am not trying to verify the blocks, the example involves manually converting the <code>P2WPKH</code> output into a <code>P2PKH</code> output by wrapping the pkh into <code>OP_DUP OP_HASH160 &lt;pkh-from-P2WPKH-out&gt; OP_EQUALVERIFY OP_CHECKSIG</code> and passing the result into <a href="https://docs.rs/bitcoin/latest/bitcoin/util/sighash/struct.SighashCache.html#method.segwit_encode_signing_data_to" rel="nofollow noreferrer"><code>sighash.segwit_encode_signing_data_to()</code></a>. It would be good to see explicit multisig examples.</p>

CC BY-SA 4.0
2023-03-06T14:39:18.990Z
I would suggest rewriting this question to emphasize that you actually want to compute a sighash, which is very different and more complicated than figuring out the CMS pubkey mapping. To answer the easy parts of your question: no, Bitcoin Core does not expose sighashes in any RPC, and its internal architecture would make this a little tricy. rust-bitcoin exposes the [https://docs.rs/bitcoin/latest/bitcoin/util/sighash/struct.SighashCache.html](SigHashCache) type which will assist in computing sighashes, but we have not written any worked examples.
Andrew Poelstra
CC BY-SA 4.0
2023-03-06T14:43:49.993Z
I have opened https://github.com/rust-bitcoin/rust-bitcoin/issues/1698 to track the lack of documentation in rust-bitcoin.
Andrew Poelstra
CC BY-SA 4.0
2023-03-08T22:48:37.717Z
Andrew, I have rewritten the question. When you synthesize the P2PKH output locking script `76a914f5693fbaf062221baf891d813d5856e4f8ab54eb88ac` from P2WPKH output in your answer, you drop the first 0x19 byte from 
 https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki : "The item 5 :

For P2WPKH witness program, the scriptCode is 0x1976a914{20-byte-pubkey-hash}88ac"  Why is that 0x19 there in the BIP 143?
Alec Matusis
CC BY-SA 4.0
2023-03-11T20:52:43.090Z
The 0x19 is a length prefix. It is automatically incuded by rust-bitcoin.
Andrew Poelstra
<multi-signature><sighash><rust-bitcoin>
Code for computing SigHash for various input types
Alec Matusis
# Code for computing SigHash for various input types

(Asked by: username_0 on 2023-03-05)

I am looking for code examples (in [rust-bitcoin](https://docs.rs/bitcoin/latest/bitcoin/), but even in Python) of how to calculate sighash for various input types. Specifically, I need to calculate the sighashes for M of N multisig unlocking script inputs for these transaction types: P2MS, P2SH, P2WSH and P2TR (to determine which M of N keys correspond to the M input signatures).

For example for a P2SH case, I am looking at [output 0 in this tx](https://blockstream.info/tx/9cdb8525f3b9cbc0016baa90040fd42f191e115fecb75518a461c73d51f4e47a?expand).

In the [spending transaction](https://blockstream.info/tx/3589ada609ec2bbbb7a1ab0cee292eae4227ecaff5e327059b7ef101b4f1d965?expand), the input #3 contains a redeem 2 of 3 mutisig script with 3 compressed 33 byte PubKeys

`OP_PUSHNUM_2 OP_PUSHBYTES_33 02261f84d51bb64371cb5e9eec3bbc0c0c7320eb7fa9c5076a394a48a9cd74bfd3 OP_PUSHBYTES_33 023e66621cf94ac25d8bb687abef86d01847805d6e9bff8c3999f18f478cde5ab6 OP_PUSHBYTES_33 02d844059fae247b8e1325f56519d1eb7d4b632ec77b9f71f03102167f3c7fa591 OP_PUSHNUM_3 OP_CHECKMULTISIG`

and two signatures in the ScriptSig (`OP_PUSHBYTES_71` and `OP_PUSHBYTES_72`). I concretely want to know which two of the three PubKeys above correspond to these two signatures.

For that, I need to [double-loop](https://en.bitcoin.it/wiki/OP_CHECKMULTISIG) over the two keys and the three signatures and pass these pairs along with the scriphash into [`verify_ecdsa(&script_hash, &signature, &pubkey)`](https://docs.rs/secp256k1/latest/secp256k1/struct.Secp256k1.html#method.verify_ecdsa) from [secp256k1](https://docs.rs/secp256k1/latest/secp256k1/struct.Secp256k1.html), and I would like to understand in detail how to compute the sighashes. I am also not clear if these multisig inputs can have any of these three sighash flags `SIGHASH_ALL`, `SIGHASH_SINGLE` and `SIGHASH_NONE`, or only the first one is ever used with multisig?

PS. In the [username_1's answer](https://bitcoin.stackexchange.com/a/117478/137810), there's an example sighash computation for P2WPKH. Although I do not need the P2(W)PKH cases because I am not trying to verify the blocks, the example involves manually converting the `P2WPKH` output into a `P2PKH` output by wrapping the pkh into `OP_DUP OP_HASH160  OP_EQUALVERIFY OP_CHECKSIG` and passing the result into [`sighash.segwit_encode_signing_data_to()`](https://docs.rs/bitcoin/latest/bitcoin/util/sighash/struct.SighashCache.html#method.segwit_encode_signing_data_to). It would be good to see explicit multisig examples.

**Tags:** multi-signature, sighash, rust-bitcoin

> **Comments:**
> **username_1**: I would suggest rewriting this question to emphasize that you actually want to compute a sighash, which is very different and more complicated than figuring out the CMS pubkey mapping. To answer the easy parts of your question: no, Bitcoin Core does not expose sighashes in any RPC, and its internal architecture would make this a little tricy. rust-bitcoin exposes the [https://docs.rs/bitcoin/latest/bitcoin/util/sighash/struct.SighashCache.html](SigHashCache) type which will assist in computing sighashes, but we have not written any worked examples.  
> **username_1**: I have opened https://github.com/rust-bitcoin/rust-bitcoin/issues/1698 to track the lack of documentation in rust-bitcoin.  
> **username_0**: Andrew, I have rewritten the question. When you synthesize the P2PKH output locking script `76a914f5693fbaf062221baf891d813d5856e4f8ab54eb88ac` from P2WPKH output in your answer, you drop the first 0x19 byte from   https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki : "The item 5 :  For P2WPKH witness program, the scriptCode is 0x1976a914{20-byte-pubkey-hash}88ac"  Why is that 0x19 there in the BIP 143?  
> **username_1**: The 0x19 is a length prefix. It is automatically incuded by rust-bitcoin.  

---

## 2 answers

### Answer by username_1 on 2023-03-06. Score: 3

I have the following code laying around for the transaction 663becacc6368150a46725e404ccdfa34d1fffbececa784c31f0a7849b4dad08, which I picked off my mempool the other day, whose hex is:
020000000001015ce1d4ffc716022f83cc0d557e6dad0500eeff9e9623bde014bdc09c5b672d750000000000fdffffff025fb7460b000000001600142cf4c1dc0352e0658971ca62a7457a1cd8c3389c4ce3a2000000000016001433f57fe374c6ceab61c8639128c038ac2a8c8db60247304402203cb50efb5c4a9aa7fd369ab6f4b226db99f44f9c610b5b50bc42f343a6aa401302201af791542eee6c1b11705e8895cc5adc36458910dc91aadcafb76a6478a29b9f01210242e811e66fd17e9a6e4ef772766c668d6e0595ca1d7f0583148bc460b575fbfdf0df0b00
use bitcoin::consensus::deserialize;
use bitcoin::hashes::{hex, sha256d, Hash};
use bitcoin::util::sighash;
use std::env;
use std::str::FromStr;

fn main() { 
    let rawtx = env::args().skip(1).next().unwrap();

    let bytes: Vec = hex::FromHex::from_hex(&rawtx)
        .expect("hex decoding");
    let tx: bitcoin::Transaction = deserialize(&bytes)
        .expect("tx deserialization");

    let pk = bitcoin::secp256k1::PublicKey::from_str(
        "0242e811e66fd17e9a6e4ef772766c668d6e0595ca1d7f0583148bc460b575fbfd",
    ).unwrap();

    let mut sighash = sighash::SighashCache::new(&tx);
    let mut out_bytes = vec![];
    sighash.segwit_encode_signing_data_to(
        &mut out_bytes,
        0,
        &bitcoin::Script::from_str("76a914f5693fbaf062221baf891d813d5856e4f8ab54eb88ac").unwrap(),
        200000000,
        bitcoin::EcdsaSighashType::All,
    ).expect("computing sighash");


    println!("{}", hex::ToHex::to_hex(&out_bytes[..]));

    let sig = bitcoin::secp256k1::ecdsa::Signature::from_str(
        "304402203cb50efb5c4a9aa7fd369ab6f4b226db99f44f9c610b5b50bc42f343a6aa401302201af791542eee6c1b11705e8895cc5adc36458910dc91aadcafb76a6478a29b9f",
    ).unwrap();
    let secp = bitcoin::secp256k1::Secp256k1::new();

    let hash = sha256d::Hash::hash(&out_bytes);
    let msg = bitcoin::secp256k1::Message::from_slice(&hash[..]).unwrap();
    secp.verify_ecdsa(
        &msg,
        &sig,
        &pk,
    ).unwrap();
}

This works only for this specific p2wpkh transaction, but it may help you get started. The weird thing is that the script_code is created by synthethizing a p2pkh output from the p2wpkh output. For p2wsh or p2sh (as any CHECKMULTISIG) script will be, this is simpler: you can just use the redeem/witness script here.


---

### Answer by username_0 on 2023-03-30. Score: 0

I created a [GitHub repo](https://github.com/panicfarm/multisig-test/) with the answer examples.


---

