<p>The problem is you're creating a bare multisig output, not a P2WSH output. When you're subsequently trying to spend it as if it were a P2WSH output, Bitcoin Core errors because bare multisig inputs aren't supposed to have witness items.</p>

CC BY-SA 4.0
2024-03-05T16:45:26.570Z
This did solve the problem. Recreated the transaction that was used as input as proper p2wsh instead of bare multisig and then spending it did work fine with the code above. Thanks.
f321x
CC BY-SA 4.0
2024-02-22T00:52:53.020Z
2024-02-22T00:52:53.020Z
Vojtěch Strnad
<p>i try to spend a P2WSH 2of2 multisig input in Python for learning purposes.
When i check my assembled TX with testmempoolaccept i get &quot;bad-witness-nonstandard&quot;.</p>
<p>This is my function to assemble the witness:</p>
<pre class="lang-python prettyprint-override"><code>def get_p2wsh_witness(privs: List[bytes], msg: bytes) -&gt; bytes:
    sigs = [sign(priv, msg) for priv in privs]
    witness = bytes.fromhex(&quot;04&quot;)
    witness += bytes.fromhex(&quot;00&quot;)
    for sig in sigs:
        witness += len(sig).to_bytes(1, &quot;little&quot;) + sig
    musig_script = b&quot;&quot;
    op2 = bytes.fromhex(&quot;52&quot;)
    op_checkmultisig = bytes.fromhex(&quot;ae&quot;)
    musig_script += op2
    for key in privs:
        key = get_pub_from_priv(key)
        musig_script += bytes.fromhex(&quot;21&quot;)  # 33 bytes
        musig_script += key
    musig_script += op2
    musig_script += op_checkmultisig
    musig_script = len(musig_script).to_bytes(1, &quot;little&quot;) + musig_script
    witness += musig_script
    return witness
</code></pre>
<p>This is how i assembled the commitment hash:</p>
<pre class="lang-python prettyprint-override"><code>def get_commitment_hash(outpoint: bytes, scriptcode: bytes, value: int, outputs: List[bytes]) -&gt; bytes:
    def dsha256(data: bytes) -&gt; bytes:
        return hashlib.new(&quot;sha256&quot;, hashlib.new(&quot;sha256&quot;, data).digest()).digest()
    result = b&quot;&quot;
    result += (2).to_bytes(4, &quot;little&quot;)
    result += dsha256(outpoint)  # hashPrevouts
    result += dsha256(bytes.fromhex(&quot;ffffffff&quot;))
    result += outpoint
    # Passed scriptcode (hex): 522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852ae 
    if len(scriptcode) &gt; 30:
        result += len(scriptcode).to_bytes(1, &quot;little&quot;) + scriptcode
    else:
        result += scriptcode
    result += value.to_bytes(8, &quot;little&quot;)
    result += bytes.fromhex(&quot;ffffffff&quot;)
    result += dsha256(b&quot;&quot;.join(outputs))
    result += bytes.fromhex(&quot;00000000&quot;)
    result += bytes.fromhex(&quot;01000000&quot;)
    return dsha256(result)

</code></pre>
<p>This is the UTXO's origin transaction:</p>
<pre><code>02000000000101f823195349b831db24d266223c16030ce52062e984c113df966be11a3cef881d7e00000000ffffffff0240420f000000000047522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852aec26e7b000000000016001437528e3adfd4f8c5322164689306f9a3c24571aa02483045022100d0a4effc5f870a8845a33c584d9239b97b8a28a85e95c43e5e7dd2bc31876fe202201c6996b0b3ee4981fcfd620ca3199f20b3630ae846b2cfd28a82004d85acdcc50121023e7362dad760249706fc4526d8781a70571b125a2ff51b817ba5b8fa5706ec1400000000
0400483045022100ec7dfded7d97f8d990d8470b0855a705c118dff718aed9f5a6c5faa24c33a03402207919d822f44bb3a36ffb0771e2e4dc99688e002e26a71fc53224eba84aa526d6014830450221009535cda9d3533a8b95ab3cbd8004b1fc4d689d5104ae0c027b4e857a6345e54b022020b8df4231a2fb0fbcbf2d7593f0fbdb63d72feea04167afcd1708fba130dd8a0147522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852ae
</code></pre>
<p>These are the (private signet) private keys in hex to sign with:</p>
<pre><code>3e2d99b06d1e763e8a208d0f2522432596fc1ae75825e777fb6b04ecf7260848 27d7edd524be491da6f5996e830e92b5477844800155e47f672cd5527f3a0e7d
</code></pre>
<p>This is the final assembled tx, spending to one OP_Return and change:</p>
<pre><code>02000000000101693328a732e0d167e50b70342a5301a467aa96d2008117dcac64852f0b11fe410000000000ffffffff020000000000000000076a056633323178583e0f000000000016001437528e3adfd4f8c5322164689306f9a3c24571aa04004830450221009549d71c7826fdb55b1934d91ee261c4e47930e2ec837d15237a8a3ac2efeddf02204f50948a3babaabc53b42f49ab140c6a1988f4ef90af3badc72c1ff43305b84b0147304402203e61b80619eac28e15e15bdef2844bc942f87be00f7945c241fb0e474ffba5fd0220327c0b6c413ac3cbe3f1e75052c9042899353ab70c7b5312175605125139024e0147522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852ae00000000
</code></pre>
<p>Can anybody see an obvious mistake here, assuming sign() and the given keys are correct, or give a hint on how to verify the output myself?</p>

CC BY-SA 4.0
2024-02-02T12:36:49.297Z
Can you also include the final assembled transaction?
Vojtěch Strnad
<transactions><segregated-witness><signature><python><learning>
Nonstandard witness when building a transaction
f321x
# Nonstandard witness when building a transaction

(Asked by: username_0 on 2024-02-02)

i try to spend a P2WSH 2of2 multisig input in Python for learning purposes.
When i check my assembled TX with testmempoolaccept i get "bad-witness-nonstandard".

This is my function to assemble the witness:

```python
def get_p2wsh_witness(privs: List[bytes], msg: bytes) -> bytes:
    sigs = [sign(priv, msg) for priv in privs]
    witness = bytes.fromhex("04")
    witness += bytes.fromhex("00")
    for sig in sigs:
        witness += len(sig).to_bytes(1, "little") + sig
    musig_script = b""
    op2 = bytes.fromhex("52")
    op_checkmultisig = bytes.fromhex("ae")
    musig_script += op2
    for key in privs:
        key = get_pub_from_priv(key)
        musig_script += bytes.fromhex("21")  # 33 bytes
        musig_script += key
    musig_script += op2
    musig_script += op_checkmultisig
    musig_script = len(musig_script).to_bytes(1, "little") + musig_script
    witness += musig_script
    return witness

```

This is how i assembled the commitment hash:

```python
def get_commitment_hash(outpoint: bytes, scriptcode: bytes, value: int, outputs: List[bytes]) -> bytes:
    def dsha256(data: bytes) -> bytes:
        return hashlib.new("sha256", hashlib.new("sha256", data).digest()).digest()
    result = b""
    result += (2).to_bytes(4, "little")
    result += dsha256(outpoint)  # hashPrevouts
    result += dsha256(bytes.fromhex("ffffffff"))
    result += outpoint
    # Passed scriptcode (hex): 522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852ae 
    if len(scriptcode) > 30:
        result += len(scriptcode).to_bytes(1, "little") + scriptcode
    else:
        result += scriptcode
    result += value.to_bytes(8, "little")
    result += bytes.fromhex("ffffffff")
    result += dsha256(b"".join(outputs))
    result += bytes.fromhex("00000000")
    result += bytes.fromhex("01000000")
    return dsha256(result)

```

This is the UTXO's origin transaction:

```
02000000000101f823195349b831db24d266223c16030ce52062e984c113df966be11a3cef881d7e00000000ffffffff0240420f000000000047522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852aec26e7b000000000016001437528e3adfd4f8c5322164689306f9a3c24571aa02483045022100d0a4effc5f870a8845a33c584d9239b97b8a28a85e95c43e5e7dd2bc31876fe202201c6996b0b3ee4981fcfd620ca3199f20b3630ae846b2cfd28a82004d85acdcc50121023e7362dad760249706fc4526d8781a70571b125a2ff51b817ba5b8fa5706ec1400000000
0400483045022100ec7dfded7d97f8d990d8470b0855a705c118dff718aed9f5a6c5faa24c33a03402207919d822f44bb3a36ffb0771e2e4dc99688e002e26a71fc53224eba84aa526d6014830450221009535cda9d3533a8b95ab3cbd8004b1fc4d689d5104ae0c027b4e857a6345e54b022020b8df4231a2fb0fbcbf2d7593f0fbdb63d72feea04167afcd1708fba130dd8a0147522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852ae

```

These are the (private signet) private keys in hex to sign with:

```
3e2d99b06d1e763e8a208d0f2522432596fc1ae75825e777fb6b04ecf7260848 27d7edd524be491da6f5996e830e92b5477844800155e47f672cd5527f3a0e7d

```

This is the final assembled tx, spending to one OP\_Return and change:

```
02000000000101693328a732e0d167e50b70342a5301a467aa96d2008117dcac64852f0b11fe410000000000ffffffff020000000000000000076a056633323178583e0f000000000016001437528e3adfd4f8c5322164689306f9a3c24571aa04004830450221009549d71c7826fdb55b1934d91ee261c4e47930e2ec837d15237a8a3ac2efeddf02204f50948a3babaabc53b42f49ab140c6a1988f4ef90af3badc72c1ff43305b84b0147304402203e61b80619eac28e15e15bdef2844bc942f87be00f7945c241fb0e474ffba5fd0220327c0b6c413ac3cbe3f1e75052c9042899353ab70c7b5312175605125139024e0147522103abd618be2d6e412bb31457bf416cf05138592da9ab4c9647a79577492710eacb2103bc2e2480bd8f5a66d45ceb333db45a980283a3c55df3c23eed22f30aa99e82e852ae00000000

```

Can anybody see an obvious mistake here, assuming sign() and the given keys are correct, or give a hint on how to verify the output myself?

**Tags:** transactions, segregated-witness, signature, python, learning

> **Comments:**
> **username_1**: Can you also include the final assembled transaction?  

---

## 1 answers

### Answer by username_1 on 2024-02-22. Score: 0

The problem is you're creating a bare multisig output, not a P2WSH output. When you're subsequently trying to spend it as if it were a P2WSH output, Bitcoin Core errors because bare multisig inputs aren't supposed to have witness items.

> **Comments:**
> **username_0**: This did solve the problem. Recreated the transaction that was used as input as proper p2wsh instead of bare multisig and then spending it did work fine with the code above. Thanks.  

---

