1200wd / bitcoinlib

Bitcoin and other Cryptocurrencies Library for Python. Includes a fully functional wallet, Mnemonic key generation and management and connection with various service providers to receive and send blockchain and transaction information.
http://bitcoinlib.readthedocs.io/
GNU General Public License v3.0
604 stars 200 forks source link

Getting error "non-mandatory-script-verify-flag (Witness program hash mismatch)" when trying to send raw signed transaction #387

Closed jahvi closed 6 months ago

jahvi commented 7 months ago

I'm trying to send a fairly simple segwit transaction with multiple input and outputs, here's how the simplified code looks like:

from bitcoinlib.transactions import Output, Key, Transaction

# (prev_txid, output_n, address, value in satoshis)
inputs = [
    (u'4ab923ee400a3899dc0790c7658af9931e54fc40dc1a8a79281a989e6a56ddd2', 125, 'bc1p0val59xpljwfr52hdg667v0nnnjzusfmvgys6warv7hklrfjum7sjgj75j', 1077938),
]

outputs = []
outputs.append(Output(15260, address='bc1pylrxedd66287hl0e000qy9c86u9tagg206yvyymp4j2c6c5npfjseyjpdu'))

 # 1000 = 10.00 sat/vB
fee_per_kb = 1000

t = Transaction(outputs=outputs, witness_type='segwit', version=2)

for ti in inputs:
    ki = Key("PRIVATE_KEY")
    t.add_input(prev_txid=ti[0], output_n=ti[1], address=ti[2], value=ti[3],  keys=ki.public(), witness_type='segwit')

fee = round((t.estimate_size(1) * fee_per_kb) / 100)

total_inputs = 0
for ti in inputs:
    total_inputs += ti[3]

total_output = 15260
change = total_inputs - total_output - fee

# Add change output
t.add_output(change, address='bc1pyr9x8f7z5t9cxykfzzx66y2xc3davshzmd3xmf9dcxdpkg4tjuusschhpq')

icount = 0
for ti in inputs:
    ki = Key("PRIVATE_KEY")
    t.sign(ki.private_byte, icount)
    icount += 1

t.update_totals()
t.verify()
t.info()
print()
print("Raw Signed Transaction: %s" % t.raw_hex())
Transaction b2b765f26c3d8f766e205f1ae4bd82950f6283013ed23c0dd6d337c15b30d97a
Date: None
Network: bitcoin
Version: 2
Witness type: segwit
Status: new
Verified: True
Inputs
- bc1p0val59xpljwfr52hdg667v0nnnjzusfmvgys6warv7hklrfjum7sjgj75j 0.01077938 BTC 4ab923ee400a3899dc0790c7658af9931e54fc40dc1a8a79281a989e6a56ddd2 125
  segwit sig_pubkey; sigs: 1 (1-of-1) valid
Outputs
- bc1pylrxedd66287hl0e000qy9c86u9tagg206yvyymp4j2c6c5npfjseyjpdu 0.00015260 BTC p2tr U
- bc1pyr9x8f7z5t9cxykfzzx66y2xc3davshzmd3xmf9dcxdpkg4tjuusschhpq 0.01061148 BTC p2tr U
Size: 236
Vsize: 153
Fee: 1530
Confirmations: None
Block: None

Raw Signed Transaction: 02000000000101d2dd566a9e981a28798a1adc40fc541e93f98a65c79007dc99380a40ee23b94a7d00000000ffffffff029c3b00000000000022512027c66cb5bad28febfdf97bde021707d70abea10a7e88c21361ac958d62930a651c3110000000000022512020ca63a7c2a2cb8312c9108dad1146c45bd642e2db626da4adc19a1b22ab973902473044022019d43d372c8d6967f377f76d20a24d31fb3cb046a5640e9a02197afa526738dd02201afdc3e421665b35397ef2adf40908aeb3031569e49aab367285a9015effbd1f0121023f5bdab1fb426681f1a020998ffc69c844f380fe6e0d67b73e7fc9bc3291018b00000000

Everything seems ok when running the script and it even shows Verified as True but when I try to send it through bitcoin-cli I get a "non-mandatory-script-verify-flag (Witness program hash mismatch)" error.

I think I'm making a mistake signing my inputs but I'm not sure how, I checked the private key multiple times and it does match the address that currently holds the UTXO.

Can anyone advise what to do?

EDIT:

I just tried creating the same transaction manually with Sparrow using the same wallets and they look very different, I'm able to send the one from sparrow just fine:

Sparrow (raw unsigned) 0200000001d2dd566a9e981a28798a1adc40fc541e93f98a65c79007dc99380a40ee23b94a7d00000000f400000002083110000000000022512020ca63a7c2a2cb8312c9108dad1146c45bd642e2db626da4adc19a1b22ab97399c3b00000000000022512027c66cb5bad28febfdf97bde021707d70abea10a7e88c21361ac958d62930a6500000000

Sparrow (raw signed) 02000000000101d2dd566a9e981a28798a1adc40fc541e93f98a65c79007dc99380a40ee23b94a7d00000000f400000002083110000000000022512020ca63a7c2a2cb8312c9108dad1146c45bd642e2db626da4adc19a1b22ab97399c3b00000000000022512027c66cb5bad28febfdf97bde021707d70abea10a7e88c21361ac958d62930a65014076dca5b3231f6bca4b2142f2f388158f57ec61845edc34358f4b8d9da9532810512cbac2bb9ff49905c15f1a7bafab8cb9e7aa6a9761f9e8f611207a048b7c1600000000

bitcoinlib (raw unsigned) 02000000000101d2dd566a9e981a28798a1adc40fc541e93f98a65c79007dc99380a40ee23b94a7d00000000f4000000029c3b00000000000022512027c66cb5bad28febfdf97bde021707d70abea10a7e88c21361ac958d62930a65083110000000000022512020ca63a7c2a2cb8312c9108dad1146c45bd642e2db626da4adc19a1b22ab97390000000000

bitcoinlib (raw signed) 02000000000101d2dd566a9e981a28798a1adc40fc541e93f98a65c79007dc99380a40ee23b94a7d0000006a47304402203a0962afe594a0f1d15ff1b8a55e72c566157c1ac02af659509c925b9122d83e02207533c881f368c89be823fbcaed39a431670b9a6c141829bf8f57c73b00eb0c3e0121023f5bdab1fb426681f1a020998ffc69c844f380fe6e0d67b73e7fc9bc3291018bf4000000029c3b00000000000022512027c66cb5bad28febfdf97bde021707d70abea10a7e88c21361ac958d62930a65083110000000000022512020ca63a7c2a2cb8312c9108dad1146c45bd642e2db626da4adc19a1b22ab97390000000000

EDIT 2:

If I add script_type="p2wpkh" to my inputs then the transaction looks more similar to Sparrow's but the witness data is completely different:

Sparrow

"inputs": [
        {
            "addresses": [
                "bc1p0val59xpljwfr52hdg667v0nnnjzusfmvgys6warv7hklrfjum7sjgj75j"
            ],
            "age": 835519,
            "output_index": 125,
            "output_value": 1077938,
            "prev_hash": "4ab923ee400a3899dc0790c7658af9931e54fc40dc1a8a79281a989e6a56ddd2",
            "script_type": "pay-to-taproot",
            "sequence": 244,
            "witness": [
                "76dca5b3231f6bca4b2142f2f388158f57ec61845edc34358f4b8d9da9532810512cbac2bb9ff49905c15f1a7bafab8cb9e7aa6a9761f9e8f611207a048b7c16"
            ]
        }
    ],

bitcoinlib

"inputs": [
        {
            "addresses": [
                "bc1p0val59xpljwfr52hdg667v0nnnjzusfmvgys6warv7hklrfjum7sjgj75j"
            ],
            "age": 835519,
            "output_index": 125,
            "output_value": 1077938,
            "prev_hash": "4ab923ee400a3899dc0790c7658af9931e54fc40dc1a8a79281a989e6a56ddd2",
            "script_type": "pay-to-taproot",
            "sequence": 244,
            "witness": [
                "30440220387c744f51688777465cb0621d94a419c7b92fe6f9b75c66186ffba46eed0f680220383da6b94e24e3ef80b0c6287b28b5f5befece93a14e3541d2b539d1cd5b0cd201",
                "023f5bdab1fb426681f1a020998ffc69c844f380fe6e0d67b73e7fc9bc3291018b"
            ]
        }
    ],
mccwdev commented 6 months ago

The input is a p2tr script, and taproot is not supported yet unfortunately.

See also issue: https://github.com/1200wd/bitcoinlib/issues/358

jahvi commented 6 months ago

@mccwdev Thanks, ended up using bitcoinutils instead for my use case