1

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:

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:

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?

1
  • 1
    Can you also include the final assembled transaction? Commented Feb 2 at 12:36

1 Answer 1

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.

1
  • 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
    Commented Mar 5 at 16:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.