|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +# Copyright (C) 2014 The python-bitcoinlib developers |
| 4 | +# |
| 5 | +# This file is part of python-bitcoinlib. |
| 6 | +# |
| 7 | +# It is subject to the license terms in the LICENSE file found in the top-level |
| 8 | +# directory of this distribution. |
| 9 | +# |
| 10 | +# No part of python-bitcoinlib, including this file, may be copied, modified, |
| 11 | +# propagated, or distributed except according to the terms contained in the |
| 12 | +# LICENSE file. |
| 13 | + |
| 14 | +"""Low-level example of how to spend a P2WSH/BIP141 txout""" |
| 15 | + |
| 16 | +import sys |
| 17 | +if sys.version_info.major < 3: |
| 18 | + sys.stderr.write('Sorry, Python 3.x required by this example.\n') |
| 19 | + sys.exit(1) |
| 20 | + |
| 21 | +import hashlib |
| 22 | + |
| 23 | +from bitcoin import SelectParams |
| 24 | +from bitcoin.core import b2x, lx, COIN, COutPoint, CMutableTxOut, CMutableTxIn, CMutableTransaction, CTxInWitness, CTxWitness |
| 25 | +from bitcoin.core.script import CScript, CScriptWitness, OP_0, OP_CHECKSIG, SignatureHash, SIGHASH_ALL, SIGVERSION_WITNESS_V0 |
| 26 | +from bitcoin.wallet import CBitcoinSecret, CBitcoinAddress, P2WSHBitcoinAddress |
| 27 | + |
| 28 | +SelectParams('testnet') |
| 29 | + |
| 30 | +# Create the (in)famous correct brainwallet secret key. |
| 31 | +h = hashlib.sha256(b'correct horse battery staple').digest() |
| 32 | +seckey = CBitcoinSecret.from_secret_bytes(h) |
| 33 | + |
| 34 | +# Create a witnessScript and corresponding redeemScript. Similar to a scriptPubKey |
| 35 | +# the redeemScript must be satisfied for the funds to be spent. |
| 36 | +txin_witnessScript = CScript([seckey.pub, OP_CHECKSIG]) |
| 37 | +txin_scriptHash = hashlib.sha256(txin_witnessScript).digest() |
| 38 | +txin_redeemScript = CScript([OP_0, txin_scriptHash]) |
| 39 | + |
| 40 | + |
| 41 | +# Convert the P2WSH scriptPubKey to a base58 Bitcoin address and print it. |
| 42 | +# You'll need to send some funds to it to create a txout to spend. |
| 43 | +txin_p2wsh_address = P2WSHBitcoinAddress.from_scriptPubKey(txin_redeemScript) |
| 44 | +print('Pay to:', str(txin_p2wsh_address)) |
| 45 | + |
| 46 | +# Same as the txid:vout the createrawtransaction RPC call requires |
| 47 | +# lx() takes *little-endian* hex and converts it to bytes; in Bitcoin |
| 48 | +# transaction hashes are shown little-endian rather than the usual big-endian. |
| 49 | +txid = lx('ace9dc7c987a52266e38fe8544c2d12182401341c98d151f4b394cf69aa5c3e5') |
| 50 | +vout = 0 |
| 51 | + |
| 52 | +# Specify the amount send to your P2WSH address. |
| 53 | +amount = int(0.0001 * COIN) |
| 54 | + |
| 55 | +# Calculate an amount for the upcoming new UTXO. Set a high fee (5%) to bypass |
| 56 | +# bitcoind minfee setting. |
| 57 | +amount_less_fee = amount * 0.95 |
| 58 | + |
| 59 | +# Create the txin structure, which includes the outpoint. The scriptSig |
| 60 | +# defaults to being empty as is necessary for spending a P2WSH output. |
| 61 | +txin = CMutableTxIn(COutPoint(txid, vout)) |
| 62 | + |
| 63 | + |
| 64 | +# Specify a destination address and create the txout. |
| 65 | +destination_address = CBitcoinAddress( |
| 66 | + '2NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE').to_scriptPubKey() |
| 67 | +txout = CMutableTxOut(amount_less_fee, destination_address) |
| 68 | + |
| 69 | +# Create the unsigned transaction. |
| 70 | +tx = CMutableTransaction([txin], [txout]) |
| 71 | + |
| 72 | +# Calculate the signature hash for that transaction. Note how the script we use |
| 73 | +# is the witnessScript, not the redeemScript. |
| 74 | +sighash = SignatureHash(script=txin_witnessScript, txTo=tx, inIdx=0, |
| 75 | + hashtype=SIGHASH_ALL, amount=amount, sigversion=SIGVERSION_WITNESS_V0) |
| 76 | + |
| 77 | +# Now sign it. We have to append the type of signature we want to the end, in |
| 78 | +# this case the usual SIGHASH_ALL. |
| 79 | +sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) |
| 80 | + |
| 81 | + |
| 82 | +# # Construct a witness for this P2WSH transaction and add to tx. |
| 83 | +witness = CScriptWitness([sig, txin_witnessScript]) |
| 84 | +tx.wit = CTxWitness([CTxInWitness(witness)]) |
| 85 | + |
| 86 | +# TODO: upgrade VerifyScript to support Segregated Witness and place verify the witness program here. |
| 87 | + |
| 88 | +# Done! Print the transaction to standard output with the bytes-to-hex |
| 89 | +# function. |
| 90 | +print(b2x(tx.serialize())) |
| 91 | + |
0 commit comments