|
| 1 | +#!/usr/bin/python3 |
| 2 | + |
| 3 | +# Distributed under the MIT/X11 software license, see the accompanying |
| 4 | +# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 5 | + |
| 6 | +"""Low-level example of how to spend a P2SH/BIP16 txout""" |
| 7 | + |
| 8 | +import hashlib |
| 9 | + |
| 10 | +from bitcoin import SelectParams |
| 11 | +from bitcoin.core import b2x, lx, COIN, COutPoint, CTxOut, CTxIn, CTransaction, Hash160 |
| 12 | +from bitcoin.core.script import CScript, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG, SignatureHash, SIGHASH_ALL |
| 13 | +from bitcoin.core.scripteval import VerifyScript, SCRIPT_VERIFY_P2SH |
| 14 | +from bitcoin.wallet import CBitcoinAddress, CBitcoinSecret |
| 15 | + |
| 16 | +SelectParams('mainnet') |
| 17 | + |
| 18 | +# Create the (in)famous correct brainwallet secret key. |
| 19 | +h = hashlib.sha256(b'correct horse battery staple').digest() |
| 20 | +seckey = CBitcoinSecret.from_secret_bytes(h) |
| 21 | + |
| 22 | +# Create a redeemScript. Similar to a scriptPubKey the redeemScript must be |
| 23 | +# satisfied for the funds to be spent. |
| 24 | +txin_redeemScript = CScript([seckey.pub, OP_CHECKSIG]) |
| 25 | +print(b2x(txin_redeemScript)) |
| 26 | + |
| 27 | +# Create the magic P2SH scriptPubKey format from that redeemScript. You should |
| 28 | +# look at the CScript.to_p2sh_scriptPubKey() function in bitcoin.core.script to |
| 29 | +# understand what's happening, as well as read BIP16: |
| 30 | +# https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki |
| 31 | +txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey() |
| 32 | + |
| 33 | +# Convert the P2SH scriptPubKey to a base58 Bitcoin address and print it. |
| 34 | +# You'll need to send some funds to it to create a txout to spend. |
| 35 | +txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey) |
| 36 | +print('Pay to:',str(txin_p2sh_address)) |
| 37 | + |
| 38 | +# Same as the txid:vout the createrawtransaction RPC call requires |
| 39 | +# |
| 40 | +# lx() takes *little-endian* hex and converts it to bytes; in Bitcoin |
| 41 | +# transaction hashes are shown little-endian rather than the usual big-endian. |
| 42 | +# There's also a corresponding x() convenience function that takes big-endian |
| 43 | +# hex and converts it to bytes. |
| 44 | +txid = lx('bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae') |
| 45 | +vout = 0 |
| 46 | + |
| 47 | +# Create the txin structure, which includes the outpoint. The scriptSig |
| 48 | +# defaults to being empty. |
| 49 | +txin = CTxIn(COutPoint(txid, vout)) |
| 50 | + |
| 51 | +# Create the txout. This time we create the scriptPubKey from a Bitcoin |
| 52 | +# address. |
| 53 | +txout = CTxOut(0.0005*COIN, CBitcoinAddress('323uf9MgLaSn9T7vDaK1cGAZ2qpvYUuqSp').to_scriptPubKey()) |
| 54 | + |
| 55 | +# Create the unsigned transaction. |
| 56 | +tx = CTransaction([txin],[txout]) |
| 57 | + |
| 58 | +# Calculate the signature hash for that transaction. Note how the script we use |
| 59 | +# is the redeemScript, not the scriptPubKey. That's because when the CHECKSIG |
| 60 | +# operation happens EvalScript() will be evaluating the redeemScript, so the |
| 61 | +# corresponding SignatureHash() function will use that same script when it |
| 62 | +# replaces the scriptSig in the transaction being hashed with the script being |
| 63 | +# executed. |
| 64 | +sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL) |
| 65 | + |
| 66 | +# Now sign it. We have to append the type of signature we want to the end, in |
| 67 | +# this case the usual SIGHASH_ALL. |
| 68 | +sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) |
| 69 | + |
| 70 | +# Set the scriptSig of our transaction input appropriately. |
| 71 | +txin.scriptSig = CScript([sig, txin_redeemScript]) |
| 72 | + |
| 73 | +# Verify the signature worked. This calls EvalScript() and actually executes |
| 74 | +# the opcodes in the scripts to see if everything worked out. If it doesn't an |
| 75 | +# exception will be raised. |
| 76 | +print(b2x(txin_scriptPubKey)) |
| 77 | +VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) |
| 78 | + |
| 79 | +# Done! Print the transaction to standard output with the bytes-to-hex |
| 80 | +# function. |
| 81 | +print(b2x(tx.serialize())) |
0 commit comments