<p>Even when the rawtransaction is right, if you give the wrong script_pubkey, it will generate wrong sighash. Just try to make sure that you are giving the right one. Try giving p2pkh script_pubkey of your pubkey.</p>
<pre><code>let public_key = PublicKey::from_slice(own_public_key).unwrap();    
let script_code = bitcoin::Address::p2pkh(&amp;public_key, bitcoin::network::constants::Network::Testnet).script_pubkey();
let sighash = hash_cache
        .segwit_signature_hash(index, &amp;script_code, value, SIG_HASH_TYPE)
        .expect(&quot;Creating the segwit signature hash failed.&quot;);
</code></pre>

CC BY-SA 4.0
2022-12-30T00:08:38.333Z
2022-12-30T00:10:25.540Z
2022-12-30T00:10:25.540Z
vrx
<p>Using the <a href="https://crates.io/crates/bitcoin" rel="nofollow noreferrer">Bitcoin crate</a>, I'm trying to create a transaction programmatically in Rust that spends an output associated with a P2WPKH address. This is the relevant code snippet:</p>
<pre><code>fn sign_transaction&lt;SignFun&gt;(
    own_public_key: &amp;[u8],
    own_address: &amp;Address,
    own_utxos: &amp;[Utxo],
    mut transaction: Transaction,
    key_name: String,
    derivation_path: Vec&lt;Vec&lt;u8&gt;&gt;,
    signer: SignFun,
) -&gt; Transaction
where
    SignFun: Fn(String, Vec&lt;Vec&lt;u8&gt;&gt;, Vec&lt;u8&gt;) -&gt; Vec&lt;u8&gt;,
{

    let txclone = transaction.clone();
    let mut hash_cache = sighash::SighashCache::new(&amp;txclone);
    for (index, input) in transaction.input.iter_mut().enumerate() {
        let value = get_value(input, own_utxos);    // Look up the value by finding the corresponding UTXO
        let sighash = hash_cache
            .segwit_signature_hash(index, &amp;own_address.script_pubkey(), value, SIG_HASH_TYPE)
            .expect(&quot;Creating the segwit signature hash failed.&quot;);

        let signature = signer(key_name.clone(), derivation_path.clone(), sighash.to_vec()).await;

        // Convert signature to DER.
        let der_signature = sec1_to_der(signature);

        let mut sig_with_hashtype = der_signature;
        sig_with_hashtype.push(SIG_HASH_TYPE.to_u32() as u8);
        let witness_bytes = vec![sig_with_hashtype, own_public_key.to_vec()];
        input.witness = Witness::from_vec(witness_bytes);
    }

    transaction
}
</code></pre>
<p>When sending a signed transaction to my local Bitcoin node in <strong>RegTest</strong> mode, I get the following error:</p>
<pre><code>error code: -26
error message:
non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation)
</code></pre>
<p>I logged the following information:</p>
<ul>
<li>Public key: 0377f5de845ac601f24e7cbf2e4abcc9e1040cd4ae971ecaa00837b1c74684e15b</li>
<li>Address: bcrt1qh3zle7xs34azdyycg8cpf9wx5nxjpcqyqv4eyc</li>
<li>Input spent with value: 625000000</li>
<li>Transaction to sign: 0100000001ceac446d9350730c2a886220bed7ae154ca3f717897819091d5e72dcd0f0895e00000 00000ffffffff0200e1f505000000001600148be949ae15ee4b5da9af0ce2bf8d3f3c43c582da26 dc4a1f00000000160014bc45fcf8d08d7a26909841f01495c6a4cd20e00400000000</li>
<li>Sighash: d7e5696f18363b58c84b8d57014d291c9f7ebbac562d219f7e7014b9a5685bbf</li>
<li>SEC1 signature: c10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc64c9903bebaba4b bf998d217c80375c36b60b212a824b63435e30205b2ed5a6a</li>
<li>DER signature: 3045022100c10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc02206 4c9903bebaba4bbf998d217c80375c36b60b212a824b63435e30205b2ed5a6a</li>
<li>DER signature with Sighash type: 3045022100c10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc02206 4c9903bebaba4bbf998d217c80375c36b60b212a824b63435e30205b2ed5a6a01</li>
<li>Signed transaction: 01000000000101ceac446d9350730c2a886220bed7ae154ca3f717897819091d5e72dcd0f0895e0 000000000ffffffff0200e1f505000000001600148be949ae15ee4b5da9af0ce2bf8d3f3c43c582 da26dc4a1f00000000160014bc45fcf8d08d7a26909841f01495c6a4cd20e00402483045022100c 10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc022064c9903bebab a4bbf998d217c80375c36b60b212a824b63435e30205b2ed5a6a01210377f5de845ac601f24e7cb f2e4abcc9e1040cd4ae971ecaa00837b1c74684e15b00000000</li>
</ul>
<p>Note that a similar piece of code for legacy (P2PKH) transactions using the same ECDSA signer works perfectly, so I'm assuming the signer is okay.</p>
<p>Any help to figure out where the problem lies would be greatly appreciated!</p>

CC BY-SA 4.0
2022-09-12T12:50:20.337Z
p2wpkh is weird -- the scriptCode is not the scriptPubKey but this weird sythetic pseudo-legacy scriptpubkey. See BIP 143 https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki and search "The item 5:".
Andrew Poelstra
CC BY-SA 4.0
2022-09-13T09:50:22.780Z
Thanks a lot for the tip! I wasn't aware of that. I'm not sure how the code needs to be updated, though. When printing out `own_address.script_pubkey()`, I get `0x0014{20-byte-pubkey-hash}`. I changed it manually to `0x1976a914{20-byte-pubkey-hash}88ac` based on the documentation you provided.
I updated the `witness_bytes` in my code above providing these bytes instead but the transaction was still rejected.
Next, I provided a script based on these bytes to `segwit_signature_hash` as well but that's not the solution, either.
Any advice on how to update the code correctly?
THLO
CC BY-SA 4.0
2022-09-15T00:01:26.437Z
It's difficult to comment directly because your code doesn't work in isolation (e.g. I'd need to understand your signing logic) but in terms of general advice, I'd grab a known-working transaction off the blockchain and try to verify *its* signature with your logic. Once you've figured that out you have some assurance that your sighashing logic is alright and the problem lies elsewhere.
Andrew Poelstra
CC BY-SA 4.0
2022-09-26T11:22:08.183Z
Thanks for the suggestion. I currently don't have any signature verification logic. I just run the code against bitcoind, which worked nicely for P2PKH using the same signing logic as mentioned above.
I think what would help the most is simply a working example for P2WPKH using the Bitcoin crate. My code is actually based on [this implementation](https://github.com/rust-bitcoin/rust-wallet/blob/235e07668d10e45a45c037fbcc9ad8ea3b0df6a5/src/account.rs#L680-L698) with all the deprecated parts updated. Unfortunately, I didn't find any code working with the current version of the crate.
THLO
<segregated-witness><raw-transaction><rust-bitcoin>
Using the Bitcoin Crate to Sign a Segwit Transaction
THLO
# Using the Bitcoin Crate to Sign a Segwit Transaction

(Asked by: username_0 on 2022-09-02)

Using the [Bitcoin crate](https://crates.io/crates/bitcoin), I'm trying to create a transaction programmatically in Rust that spends an output associated with a P2WPKH address. This is the relevant code snippet:

```
fn sign_transaction<SignFun>(
    own_public_key: &[u8],
    own_address: &Address,
    own_utxos: &[Utxo],
    mut transaction: Transaction,
    key_name: String,
    derivation_path: Vec<Vec<u8>>,
    signer: SignFun,
) -> Transaction
where
    SignFun: Fn(String, Vec<Vec<u8>>, Vec<u8>) -> Vec<u8>,
{

    let txclone = transaction.clone();
    let mut hash_cache = sighash::SighashCache::new(&txclone);
    for (index, input) in transaction.input.iter_mut().enumerate() {
        let value = get_value(input, own_utxos);    // Look up the value by finding the corresponding UTXO
        let sighash = hash_cache
            .segwit_signature_hash(index, &own_address.script_pubkey(), value, SIG_HASH_TYPE)
            .expect("Creating the segwit signature hash failed.");

        let signature = signer(key_name.clone(), derivation_path.clone(), sighash.to_vec()).await;

        // Convert signature to DER.
        let der_signature = sec1_to_der(signature);

        let mut sig_with_hashtype = der_signature;
        sig_with_hashtype.push(SIG_HASH_TYPE.to_u32() as u8);
        let witness_bytes = vec![sig_with_hashtype, own_public_key.to_vec()];
        input.witness = Witness::from_vec(witness_bytes);
    }

    transaction
}

```

When sending a signed transaction to my local Bitcoin node in **RegTest** mode, I get the following error:

```
error code: -26
error message:
non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation)

```

I logged the following information:

* Public key: 0377f5de845ac601f24e7cbf2e4abcc9e1040cd4ae971ecaa00837b1c74684e15b
* Address: bcrt1qh3zle7xs34azdyycg8cpf9wx5nxjpcqyqv4eyc
* Input spent with value: 625000000
* Transaction to sign: 0100000001ceac446d9350730c2a886220bed7ae154ca3f717897819091d5e72dcd0f0895e00000 00000ffffffff0200e1f505000000001600148be949ae15ee4b5da9af0ce2bf8d3f3c43c582da26 dc4a1f00000000160014bc45fcf8d08d7a26909841f01495c6a4cd20e00400000000
* Sighash: d7e5696f18363b58c84b8d57014d291c9f7ebbac562d219f7e7014b9a5685bbf
* SEC1 signature: c10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc64c9903bebaba4b bf998d217c80375c36b60b212a824b63435e30205b2ed5a6a
* DER signature: 3045022100c10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc02206 4c9903bebaba4bbf998d217c80375c36b60b212a824b63435e30205b2ed5a6a
* DER signature with Sighash type: 3045022100c10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc02206 4c9903bebaba4bbf998d217c80375c36b60b212a824b63435e30205b2ed5a6a01
* Signed transaction: 01000000000101ceac446d9350730c2a886220bed7ae154ca3f717897819091d5e72dcd0f0895e0 000000000ffffffff0200e1f505000000001600148be949ae15ee4b5da9af0ce2bf8d3f3c43c582 da26dc4a1f00000000160014bc45fcf8d08d7a26909841f01495c6a4cd20e00402483045022100c 10c09b210914e49f295c07c9f96352e085df9d2c4272292239445d6f89483bc022064c9903bebab a4bbf998d217c80375c36b60b212a824b63435e30205b2ed5a6a01210377f5de845ac601f24e7cb f2e4abcc9e1040cd4ae971ecaa00837b1c74684e15b00000000

Note that a similar piece of code for legacy (P2PKH) transactions using the same ECDSA signer works perfectly, so I'm assuming the signer is okay.

Any help to figure out where the problem lies would be greatly appreciated!

**Tags:** segregated-witness, raw-transaction, rust-bitcoin

> **Comments:**
> **username_1**: p2wpkh is weird -- the scriptCode is not the scriptPubKey but this weird sythetic pseudo-legacy scriptpubkey. See BIP 143 https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki and search "The item 5:".  
> **username_0**: Thanks a lot for the tip! I wasn't aware of that. I'm not sure how the code needs to be updated, though. When printing out `own_address.script_pubkey()`, I get `0x0014{20-byte-pubkey-hash}`. I changed it manually to `0x1976a914{20-byte-pubkey-hash}88ac` based on the documentation you provided. I updated the `witness_bytes` in my code above providing these bytes instead but the transaction was still rejected. Next, I provided a script based on these bytes to `segwit_signature_hash` as well but that's not the solution, either. Any advice on how to update the code correctly?  
> **username_1**: It's difficult to comment directly because your code doesn't work in isolation (e.g. I'd need to understand your signing logic) but in terms of general advice, I'd grab a known-working transaction off the blockchain and try to verify *its* signature with your logic. Once you've figured that out you have some assurance that your sighashing logic is alright and the problem lies elsewhere.  
> **username_0**: Thanks for the suggestion. I currently don't have any signature verification logic. I just run the code against bitcoind, which worked nicely for P2PKH using the same signing logic as mentioned above. I think what would help the most is simply a working example for P2WPKH using the Bitcoin crate. My code is actually based on [this implementation](https://github.com/rust-bitcoin/rust-wallet/blob/235e07668d10e45a45c037fbcc9ad8ea3b0df6a5/src/account.rs#L680-L698) with all the deprecated parts updated. Unfortunately, I didn't find any code working with the current version of the crate.  

---

## 1 answers

### Answer by username_2 on 2022-12-30. Score: 0

Even when the rawtransaction is right, if you give the wrong script\_pubkey, it will generate wrong sighash. Just try to make sure that you are giving the right one. Try giving p2pkh script\_pubkey of your pubkey.

```
let public_key = PublicKey::from_slice(own_public_key).unwrap();    
let script_code = bitcoin::Address::p2pkh(&public_key, bitcoin::network::constants::Network::Testnet).script_pubkey();
let sighash = hash_cache
        .segwit_signature_hash(index, &script_code, value, SIG_HASH_TYPE)
        .expect("Creating the segwit signature hash failed.");

```


---

