Skip to content

Commit bd6cd60

Browse files
committed
Merge #227: [examples] Add segwit example for spending a P2WPKH output
df646ad [examples] Add segwit example for spending a P2WPKH output (Bryan Bishop) Pull request description: Here's an example for using P2WPKH. ACKs for top commit: JSwambo: ACK df646ad Tree-SHA512: 3a8b57c0da5cc953163eb8ef4b981503b5db3e984741077dcf9c883db46fb0af00bbff37905b40545e990de52cdf1d2291b369e62d610b331322f47742faa69a
2 parents f67b2cb + df646ad commit bd6cd60

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

examples/spend-p2wpkh.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (C) 2020 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 P2WPKH output."""
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, b2lx, lx, COIN, COutPoint, CTxOut, CTxIn, CTxInWitness, CTxWitness, CScriptWitness, CMutableTransaction, Hash160
25+
from bitcoin.core.script import CScript, OP_0, SignatureHash, SIGHASH_ALL, SIGVERSION_WITNESS_V0
26+
from bitcoin.wallet import CBitcoinSecret, P2WPKHBitcoinAddress
27+
from bitcoin.rpc import Proxy
28+
29+
SelectParams("regtest")
30+
connection = Proxy()
31+
32+
if connection._call("getblockchaininfo")["chain"] != "regtest":
33+
sys.stderr.write("This example is intended for regtest only.\n")
34+
sys.exit(1)
35+
36+
37+
# Create the (in)famous correct brainwallet secret key.
38+
h = hashlib.sha256(b'correct horse battery staple').digest()
39+
seckey = CBitcoinSecret.from_secret_bytes(h)
40+
41+
# Create an address from that private key.
42+
public_key = seckey.pub
43+
scriptPubKey = CScript([OP_0, Hash160(public_key)])
44+
address = P2WPKHBitcoinAddress.from_scriptPubKey(scriptPubKey)
45+
46+
# Give the private key to bitcoind (for ismine, listunspent, etc).
47+
connection._call("importprivkey", str(seckey))
48+
49+
# Check if there's any funds available.
50+
unspentness = lambda: connection._call("listunspent", 6, 9999, [str(address)], True, {"minimumAmount": 1.0})
51+
unspents = unspentness()
52+
while len(unspents) == 0:
53+
# mine some funds into the address
54+
connection._call("generatetoaddress", 110, str(address))
55+
unspents = unspentness()
56+
57+
# Choose the first UTXO, let's spend it!
58+
unspent_utxo_details = unspents[0]
59+
txid = unspent_utxo_details["txid"]
60+
vout = unspent_utxo_details["vout"]
61+
amount = int(float(unspent_utxo_details["amount"]) * COIN)
62+
63+
# Calculate an amount for the upcoming new UTXO. Set a high fee to bypass
64+
# bitcoind minfee setting.
65+
amount_less_fee = int(amount - (0.01 * COIN))
66+
67+
# Create a destination to send the coins.
68+
destination_address = connection._call("getnewaddress", "python-bitcoinlib-example", "bech32")
69+
destination_address = P2WPKHBitcoinAddress(destination_address)
70+
target_scriptPubKey = destination_address.to_scriptPubKey()
71+
72+
# Create the unsigned transaction.
73+
txin = CTxIn(COutPoint(lx(txid), vout))
74+
txout = CTxOut(amount_less_fee, target_scriptPubKey)
75+
tx = CMutableTransaction([txin], [txout])
76+
77+
# Specify which transaction input is going to be signed for.
78+
txin_index = 0
79+
80+
# When signing a P2WPKH transaction, use an "implicit" script that isn't
81+
# specified in the scriptPubKey or the witness.
82+
redeem_script = address.to_redeemScript()
83+
84+
# Calculate the signature hash for the transaction. This is then signed by the
85+
# private key that controls the UTXO being spent here at this txin_index.
86+
sighash = SignatureHash(redeem_script, tx, txin_index, SIGHASH_ALL, amount=amount, sigversion=SIGVERSION_WITNESS_V0)
87+
signature = seckey.sign(sighash) + bytes([SIGHASH_ALL])
88+
89+
# Construct a witness for this transaction input. The public key is given in
90+
# the witness so that the appropriate redeem_script can be calculated by
91+
# anyone. The original scriptPubKey had only the Hash160 hash of the public
92+
# key, not the public key itself, and the redeem script can be entirely
93+
# re-constructed (from implicit template) if given just the public key. So the
94+
# public key is added to the witness. This is P2WPKH in bip141.
95+
witness = [signature, public_key]
96+
97+
# Aggregate all of the witnesses together, and then assign them to the
98+
# transaction object.
99+
ctxinwitnesses = [CTxInWitness(CScriptWitness(witness))]
100+
tx.wit = CTxWitness(ctxinwitnesses)
101+
102+
# Broadcast the transaction to the regtest network.
103+
spend_txid = connection.sendrawtransaction(tx)
104+
105+
# Done! Print the transaction to standard output. Show the transaction
106+
# serialization in hex (instead of bytes), and render the txid.
107+
print("serialized transaction: {}".format(b2x(tx.serialize())))
108+
print("txid: {}".format(b2lx(spend_txid)))

0 commit comments

Comments
 (0)