Skip to content

Instantly share code, notes, and snippets.

@i0x0ff
Created June 24, 2021 07:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save i0x0ff/b29b2307b4e9ce316a4d6533464cf7a1 to your computer and use it in GitHub Desktop.
Save i0x0ff/b29b2307b4e9ce316a4d6533464cf7a1 to your computer and use it in GitHub Desktop.
"""
This example is based on Peter Todd's bitcoinlib: https://github.com/petertodd/python-bitcoinlib
The code is based directly out of the example script provided in bitcoinlib: https://github.com/petertodd/python-bitcoinlib/blob/master/examples/spend-p2wsh-txout.py
I'd like to understand what exactly am I doing wrong, every time the transaction gets broadcasted I get the following error:
{
"code": -26,
"message": "non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation)",
}
"""
import hashlib
from bitcoin import SelectParams
from bitcoin.core import b2x, lx, COIN, COutPoint, CMutableTxOut, CMutableTxIn, CMutableTransaction, CTxInWitness, CTxWitness
from bitcoin.core.script import CScript, CScriptWitness, OP_0, OP_CHECKSIG, SignatureHash, SIGHASH_ALL, SIGVERSION_WITNESS_V0
from bitcoin.wallet import CBitcoinSecret, CBitcoinAddress, P2WSHBitcoinAddress
SelectParams('signet')
# this is a passphrase of wallet tb1qhxy36055wje22qkxn4mtjl4k9vykcnq7avgtu3smnw6xpdxmw0qqjvywtn
# that currently holds 0.001 BTC on Signet
h = hashlib.sha256(b'asdf qnmioqa asdkln asdklj 12390u asddkln210ij kljnm1233iojfakjn ').digest()
seckey = CBitcoinSecret.from_secret_bytes(h)
txin_witnessScript = CScript([seckey.pub, OP_CHECKSIG])
# https://explorer.bc-2.jp/tx/66f66e7f6aecde304560433ae29bbf73c096410757868203286a4916d7c0eb79
txid = lx('66f66e7f6aecde304560433ae29bbf73c096410757868203286a4916d7c0eb79')
vout = 1
# Specify the amount send to your P2WSH address.
amount = int(0.0001 * COIN)
# Calculate an amount for the upcoming new UTXO. Set a high fee (5%) to bypass
# bitcoind minfee setting.
amount_less_fee = amount * 0.95
# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty as is necessary for spending a P2WSH output.
txin = CMutableTxIn(COutPoint(txid, vout))
# Specify a destination address and create the txout.
destination_address = CBitcoinAddress('tb1qffmyyg5v9atg3zzvlafzzu22ht6cexj7xt8sx4yl0f6c3zktzqrq8hempj').to_scriptPubKey()
txout = CMutableTxOut(amount_less_fee, destination_address)
# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])
# Calculate the signature hash for that transaction. Note how the script we use is
# the witnessScript, not the redeemScript.
sighash = SignatureHash(
script=txin_witnessScript,
txTo=tx,
inIdx=0,
hashtype=SIGHASH_ALL,
amount=amount,
sigversion=SIGVERSION_WITNESS_V0,
)
# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
# Construct a witness for this P2WSH transaction and add to tx.
witness = CScriptWitness([sig, txin_witnessScript])
tx.wit = CTxWitness([CTxInWitness(witness)])
# TODO: upgrade VerifyScript to support Segregated Witness and place verify the witness program here.
# Done! Print the transaction to standard output with the bytes-to-hex fn - this output has to be broadcasted manually
print(b2x(tx.serialize()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment