The Python library pycoin (http://github.com/richardkiss/pycoin), originally written and maintained by Richard Kiss, is a Python-based library that supports manipulation of bitcoin keys and transactions, even supporting the scripting language enough to properly deal with non-standard transactions. As of June, 2014, the latest released version is 0.42, and all examples here are based on that version; be warned that it is still under active development, so later versions may have differences in API or command-line tools.
The pycoin library supports both Python 2 (2.7.x) and Python 3 (after 3.3), and comes with some handy command-line utilities, ku and tx.
To install:
$ python3 -m venv /tmp/pycoin $ . /tmp/pycoin/bin/activate $ pip install pycoin==0.42 Downloading/unpacking pycoin==0.42 Downloading pycoin-0.42.tar.gz (66kB): 66kB downloaded Running setup.py (path:/tmp/pycoin/build/pycoin/setup.py) egg_info for package pycoin
Installing collected packages: pycoin Running setup.py install for pycoin
Installing tx script to /tmp/pycoin/bin Installing cache_tx script to /tmp/pycoin/bin Installing bu script to /tmp/pycoin/bin Installing fetch_unspent script to /tmp/pycoin/bin Installing block script to /tmp/pycoin/bin Installing spend script to /tmp/pycoin/bin Installing ku script to /tmp/pycoin/bin Installing genwallet script to /tmp/pycoin/bin Successfully installed pycoin Cleaning up... $
The command-line utility
("key utility") is Swiss Army knife for manipulating keys. It supports BIP32 keys, WIF, and address (bitcoin and alt coins). Here are some examples.ku
Create a BIP32 Key using the default entropy sources of GPG and /dev/random:
$ ku create
input : create network : Bitcoin wallet key : xprv9s21ZrQH143K3LU5ctPZTBnb9kTjA5Su9DcWHvXJemiJBsY7VqXUG7hipgdWaU\ m2nhnzdvxJf5KJo9vjP2nABX65c5sFsWsV8oXcbpehtJi public version : xpub661MyMwAqRbcFpYYiuvZpKjKhnJDZYAkWSY76JvvD7FH4fsG3Nqiov2CfxzxY8\ DGcpfT56AMFeo8M8KPkFMfLUtvwjwb6WPv8rY65L2q8Hz tree depth : 0 fingerprint : 9d9c6092 parent f'print : 00000000 child index : 0 chain code : 80574fb260edaa4905bc86c9a47d30c697c50047ed466c0d4a5167f6821e8f3c private key : yes secret exponent : 112471538590155650688604752840386134637231974546906847202389294096567806844862 hex : f8a8a28b28a916e1043cc0aca52033a18a13cab1638d544006469bc171fddfbe wif : L5Z54xi6qJusQT42JHA44mfPVZGjyb4XBRWfxAzUWwRiGx1kV4sP uncompressed : 5KhoEavGNNH4GHKoy2Ptu4KfdNp4r56L5B5un8FP6RZnbsz5Nmb public pair x : 76460638240546478364843397478278468101877117767873462127021560368290114016034 public pair y : 59807879657469774102040120298272207730921291736633247737077406753676825777701 x as hex : a90b3008792432060fa04365941e09a8e4adf928bdbdb9dad41131274e379322 y as hex : 843a0f6ed9c0eb1962c74533795406914fe3f1957c5238951f4fe245a4fcd625 y parity : odd key pair as sec : 03a90b3008792432060fa04365941e09a8e4adf928bdbdb9dad41131274e379322 uncompressed : 04a90b3008792432060fa04365941e09a8e4adf928bdbdb9dad41131274e379322\ 843a0f6ed9c0eb1962c74533795406914fe3f1957c5238951f4fe245a4fcd625 hash160 : 9d9c609247174ae323acfc96c852753fe3c8819d uncompressed : 8870d869800c9b91ce1eb460f4c60540f87c15d7 Bitcoin address : 1FNNRQ5fSv1wBi5gyfVBs2rkNheMGt86sp uncompressed : 1DSS5isnH4FsVaLVjeVXewVSpfqktdiQAM
Create a BIP32 key from a passphrase:
THE PASSPHRASE IN THIS EXAMPLE IS WAY TOO EASY TO GUESS.
$ ku P:foo
input : P:foo network : Bitcoin wallet key : xprv9s21ZrQH143K31AgNK5pyVvW23gHnkBq2wh5aEk6g1s496M8ZMjxncCKZKgb5j\ ZoY5eSJMJ2Vbyvi2hbmQnCuHBujZ2WXGTux1X2k9Krdtq public version : xpub661MyMwAqRbcFVF9ULcqLdsEa5WnCCugQAcgNd9iEMQ31tgH6u4DLQWoQayvtS\ VYFvXz2vPPpbXE1qpjoUFidhjFj82pVShWu9curWmb2zy tree depth : 0 fingerprint : 5d353a2e parent f'print : 00000000 child index : 0 chain code : 5eeb1023fd6dd1ae52a005ce0e73420821e1d90e08be980a85e9111fd7646bbc private key : yes secret exponent : 65825730547097305716057160437970790220123864299761908948746835886007793998275 hex : 91880b0e3017ba586b735fe7d04f1790f3c46b818a2151fb2def5f14dd2fd9c3 wif : L26c3H6jEPVSqAr1usXUp9qtQJw6NHgApq6Ls4ncyqtsvcq2MwKH uncompressed : 5JvNzA5vXDoKYJdw8SwwLHxUxaWvn9mDea6k1vRPCX7KLUVWa7W public pair x : 81821982719381104061777349269130419024493616650993589394553404347774393168191 public pair y : 58994218069605424278320703250689780154785099509277691723126325051200459038290 x as hex : b4e599dfa44555a4ed38bcfff0071d5af676a86abf123c5b4b4e8e67a0b0b13f y as hex : 826d8b4d3010aea16ff4c1c1d3ae68541d9a04df54a2c48cc241c2983544de52 y parity : even key pair as sec : 02b4e599dfa44555a4ed38bcfff0071d5af676a86abf123c5b4b4e8e67a0b0b13f uncompressed : 04b4e599dfa44555a4ed38bcfff0071d5af676a86abf123c5b4b4e8e67a0b0b13f\ 826d8b4d3010aea16ff4c1c1d3ae68541d9a04df54a2c48cc241c2983544de52 hash160 : 5d353a2ecdb262477172852d57a3f11de0c19286 uncompressed : e5bd3a7e6cb62b4c820e51200fb1c148d79e67da Bitcoin address : 19Vqc8uLTfUonmxUEZac7fz1M5c5ZZbAii uncompressed : 1MwkRkogzBRMehBntgcq2aJhXCXStJTXHT
Get info as JSON:
$ ku P:foo -P -j { "y_parity": "even", "public_pair_y_hex": "826d8b4d3010aea16ff4c1c1d3ae68541d9a04df54a2c48cc241c2983544de52", "private_key": "no", "parent_fingerprint": "00000000", "tree_depth": "0", "network": "Bitcoin", "btc_address_uncompressed": "1MwkRkogzBRMehBntgcq2aJhXCXStJTXHT", "key_pair_as_sec_uncompressed": "04b4e599dfa44555a4ed38bcfff0071d5af676a86abf123c5b4b4e8e67a0b0b13f826d8b4d3010aea16ff4c1c1d3ae68541d9a04df54a2c48cc241c2983544de52", "public_pair_x_hex": "b4e599dfa44555a4ed38bcfff0071d5af676a86abf123c5b4b4e8e67a0b0b13f", "wallet_key": "xpub661MyMwAqRbcFVF9ULcqLdsEa5WnCCugQAcgNd9iEMQ31tgH6u4DLQWoQayvtSVYFvXz2vPPpbXE1qpjoUFidhjFj82pVShWu9curWmb2zy", "chain_code": "5eeb1023fd6dd1ae52a005ce0e73420821e1d90e08be980a85e9111fd7646bbc", "child_index": "0", "hash160_uncompressed": "e5bd3a7e6cb62b4c820e51200fb1c148d79e67da", "btc_address": "19Vqc8uLTfUonmxUEZac7fz1M5c5ZZbAii", "fingerprint": "5d353a2e", "hash160": "5d353a2ecdb262477172852d57a3f11de0c19286", "input": "P:foo", "public_pair_x": "81821982719381104061777349269130419024493616650993589394553404347774393168191", "public_pair_y": "58994218069605424278320703250689780154785099509277691723126325051200459038290", "key_pair_as_sec": "02b4e599dfa44555a4ed38bcfff0071d5af676a86abf123c5b4b4e8e67a0b0b13f" }
Public BIP32 Key:
$ ku -w -P P:foo xpub661MyMwAqRbcFVF9ULcqLdsEa5WnCCugQAcgNd9iEMQ31tgH6u4DLQWoQayvtSVYFvXz2vPPpbXE1qpjoUFidhjFj82pVShWu9curWmb2zy
Generate a subkey:
$ ku -w -s3/2 P:foo xprv9wTErTSkjVyJa1v4cUTFMFkWMe5eu8ErbQcs9xajnsUzCBT7ykHAwdrxvG3g3f6BFk7ms5hHBvmbdutNmyg6iogWKxx6mefEw4M8EroLgKj
Hardened subkey:
$ ku -w -s3/2H P:foo xprv9wTErTSu5AWGkDeUPmqBcbZWX1xq85ZNX9iQRQW9DXwygFp7iRGJo79dsVctcsCHsnZ3XU3DhsuaGZbDh8iDkBN45k67UKsJUXM1JfRCdn1
WIF:
$ ku -W P:foo L26c3H6jEPVSqAr1usXUp9qtQJw6NHgApq6Ls4ncyqtsvcq2MwKH
Address:
$ ku -a P:foo 19Vqc8uLTfUonmxUEZac7fz1M5c5ZZbAii
Generate a bunch of subkeys:
$ ku P:foo -s 0/0-5 -w xprv9xWkBDfyBXmZjBG9EiXBpy67KK72fphUp9utJokEBFtjsjiuKUUDF5V3TU8U8cDzytqYnSekc8bYuJS8G3bhXxKWB89Ggn2dzLcoJsuEdRK xprv9xWkBDfyBXmZnzKf3bAGifK593gT7WJZPnYAmvc77gUQVej5QHckc5Adtwxa28ACmANi9XhCrRvtFqQcUxt8rUgFz3souMiDdWxJDZnQxzx xprv9xWkBDfyBXmZqdXA8y4SWqfBdy71gSW9sjx9JpCiJEiBwSMQyRxan6srXUPBtj3PTxQFkZJAiwoUpmvtrxKZu4zfsnr3pqyy2vthpkwuoVq xprv9xWkBDfyBXmZsA85GyWj9uYPyoQv826YAadKWMaaEosNrFBKgj2TqWuiWY3zuqxYGpHfv9cnGj5P7e8EskpzKL1Y8Gk9aX6QbryA5raK73p xprv9xWkBDfyBXmZv2q3N66hhZ8DAcEnQDnXML1J62krJAcf7Xb1HJwuW2VMJQrCofY2jtFXdiEY8UsRNJfqK6DAdyZXoMvtaLHyWQx3FS4A9zw xprv9xWkBDfyBXmZw4jEYXUHYc9fT25k9irP87n2RqfJ5bqbjKdT84Mm7Wtc2xmzFuKg7iYf7XFHKkSsaYKWKJbR54bnyAD9GzjUYbAYTtN4ruo
Generate the corresponding addresses:
$ ku P:foo -s 0/0-5 -a 1MrjE78H1R1rqdFrmkjdHnPUdLCJALbv3x 1AnYyVEcuqeoVzH96zj1eYKwoWfwte2pxu 1GXr1kZfxE1FcK6ZRD5sqqqs5YfvuzA1Lb 116AXZc4bDVQrqmcinzu4aaPdrYqvuiBEK 1Cz2rTLjRM6pMnxPNrRKp9ZSvRtj5dDUML 1WstdwPnU6HEUPme1DQayN9nm6j7nDVEM
Generate the corresponding WIFS:
$ ku P:foo -s 0/0-5 -W L5a4iE5k9gcJKGqX3FWmxzBYQc29PvZ6pgBaePLVqT5YByEnBomx Kyjgne6GZwPGB6G6kJEhoPbmyjMP7D5d3zRbHVjwcq4iQXD9QqKQ L4B3ygQxK6zH2NQGxLDee2H9v4Lvwg14cLJW7QwWPzCtKHdWMaQz L2L2PZdorybUqkPjrmhem4Ax5EJvP7ijmxbNoQKnmTDMrqemY8UF L2oD6vA4TUyqPF8QG4vhUFSgwCyuuvFZ3v8SKHYFDwkbM765Nrfd KzChTbc3kZFxUSJ3Kt54cxsogeFAD9CCM4zGB22si8nfKcThQn8C
Check that it works by choosing a BIP32 string (the one corresponding to subkey 0/3):
$ ku -W xprv9xWkBDfyBXmZsA85GyWj9uYPyoQv826YAadKWMaaEosNrFBKgj2TqWuiWY3zuqxYGpHfv9cnGj5P7e8EskpzKL1Y8Gk9aX6QbryA5raK73p L2L2PZdorybUqkPjrmhem4Ax5EJvP7ijmxbNoQKnmTDMrqemY8UF $ ku -a xprv9xWkBDfyBXmZsA85GyWj9uYPyoQv826YAadKWMaaEosNrFBKgj2TqWuiWY3zuqxYGpHfv9cnGj5P7e8EskpzKL1Y8Gk9aX6QbryA5raK73p 116AXZc4bDVQrqmcinzu4aaPdrYqvuiBEK
Yep, looks familiar.
From secret exponent:
$ ku 1
input : 1 network : Bitcoin secret exponent : 1 hex : 1 wif : KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn uncompressed : 5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf public pair x : 55066263022277343669578718895168534326250603453777594175500187360389116729240 public pair y : 32670510020758816978083085130507043184471273380659243275938904335757337482424 x as hex : 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 y as hex : 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 y parity : even key pair as sec : 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 uncompressed : 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\ 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 hash160 : 751e76e8199196d454941c45d1b3a323f1433bd6 uncompressed : 91b24bf9f5288532960ac687abb035127b1d28a5 Bitcoin address : 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH uncompressed : 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm
Litecoin version:
$ ku -nL 1
input : 1 network : Litecoin secret exponent : 1 hex : 1 wif : T33ydQRKp4FCW5LCLLUB7deioUMoveiwekdwUwyfRDeGZm76aUjV uncompressed : 6u823ozcyt2rjPH8Z2ErsSXJB5PPQwK7VVTwwN4mxLBFrao69XQ public pair x : 55066263022277343669578718895168534326250603453777594175500187360389116729240 public pair y : 32670510020758816978083085130507043184471273380659243275938904335757337482424 x as hex : 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 y as hex : 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 y parity : even key pair as sec : 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 uncompressed : 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\ 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 hash160 : 751e76e8199196d454941c45d1b3a323f1433bd6 uncompressed : 91b24bf9f5288532960ac687abb035127b1d28a5 Litecoin address : LVuDpNCSSj6pQ7t9Pv6d6sUkLKoqDEVUnJ uncompressed : LYWKqJhtPeGyBAw7WC8R3F7ovxtzAiubdM
Dogecoin WIF:
$ ku -nD -W 1 QNcdLVw8fHkixm6NNyN6nVwxKek4u7qrioRbQmjxac5TVoTtZuot
From public pair (on Testnet):
$ ku -nT 55066263022277343669578718895168534326250603453777594175500187360389116729240,even
input : 550662630222773436695787188951685343262506034537775941755001873603\ 89116729240,even network : Bitcoin testnet public pair x : 55066263022277343669578718895168534326250603453777594175500187360389116729240 public pair y : 32670510020758816978083085130507043184471273380659243275938904335757337482424 x as hex : 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 y as hex : 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 y parity : even key pair as sec : 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 uncompressed : 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\ 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 hash160 : 751e76e8199196d454941c45d1b3a323f1433bd6 uncompressed : 91b24bf9f5288532960ac687abb035127b1d28a5 Bitcoin testnet address : mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r uncompressed : mtoKs9V381UAhUia3d7Vb9GNak8Qvmcsme
From hash160:
$ ku 751e76e8199196d454941c45d1b3a323f1433bd6
input : 751e76e8199196d454941c45d1b3a323f1433bd6 network : Bitcoin hash160 : 751e76e8199196d454941c45d1b3a323f1433bd6 Bitcoin address : 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH
As a Dogecoin address:
$ ku -nD 751e76e8199196d454941c45d1b3a323f1433bd6
input : 751e76e8199196d454941c45d1b3a323f1433bd6 network : Dogecoin hash160 : 751e76e8199196d454941c45d1b3a323f1433bd6 Dogecoin address : DFpN6QqFfUm3gKNaxN6tNcab1FArL9cZLE
The command-line utility
will display transactions in human-readable form, fetch base transactions from pycoin’s transaction cache or from web services (blockchain.info, blockr.io, biteasy.com are currently supported), merge transactions, add or delete inputs or outputs, and sign transactions.tx
Examples:
View the famous "pizza" transaction [PIZZA]:
$ tx 49d2adb6e476fa46d8357babf78b1b501fd39e177ac7833124b3f67b17c40c2a warning: consider setting environment variable PYCOIN_CACHE_DIR=~/.pycoin_cache to cache transactions fetched via web services warning: no service providers found for get_tx; consider setting environment variable PYCOIN_SERVICE_PROVIDERS=BLOCKR_IO:BLOCKCHAIN_INFO:BITEASY:BLOCKEXPLORER usage: tx [-h] [-t TRANSACTION_VERSION] [-l LOCK_TIME] [-n NETWORK] [-a] [-i address] [-f path-to-private-keys] [-g GPG_ARGUMENT] [--remove-tx-in tx_in_index_to_delete] [--remove-tx-out tx_out_index_to_delete] [-F transaction-fee] [-u] [-b BITCOIND_URL] [-o path-to-output-file] argument [argument ...] tx: error: can't find Tx with id 49d2adb6e476fa46d8357babf78b1b501fd39e177ac7833124b3f67b17c40c2a
Oops! We don’t have web services set up. Let’s do that now.
$ PYCOIN_CACHE_DIR=~/.pycoin_cache $ PYCOIN_SERVICE_PROVIDERS=BLOCKR_IO:BLOCKCHAIN_INFO:BITEASY:BLOCKEXPLORER $ export PYCOIN_CACHE_DIR PYCOIN_SERVICE_PROVIDERS
It’s not done automatically so a command-line tool won’t leak potentially private information about what transactions you’re interested in to a third party web site. If you don’t care, you could put these lines into your .profile.
Let’s try again:
$ tx 49d2adb6e476fa46d8357babf78b1b501fd39e177ac7833124b3f67b17c40c2a Version: 1 tx hash 49d2adb6e476fa46d8357babf78b1b501fd39e177ac7833124b3f67b17c40c2a 159 bytes TxIn count: 1; TxOut count: 1 Lock time: 0 (valid anytime) Input: 0: (unknown) from 1e133f7de73ac7d074e2746a3d6717dfc99ecaa8e9f9fade2cb8b0b20a5e0441:0 Output: 0: 1CZDM6oTttND6WPdt3D6bydo7DYKzd9Qik receives 10000000.00000 mBTC Total output 10000000.00000 mBTC including unspents in hex dump since transaction not fully signed 010000000141045e0ab2b0b82cdefaf9e9a8ca9ec9df17673d6a74e274d0c73ae77d3f131e000000004a493046022100a7f26eda874931999c90f87f01ff1ffc76bcd058fe16137e0e63fdb6a35c2d78022100a61e9199238eb73f07c8f209504c84b80f03e30ed8169edd44f80ed17ddf451901ffffffff010010a5d4e80000001976a9147ec1003336542cae8bded8909cdd6b5e48ba0ab688ac00000000
-
can’t validate transaction as source transactions missing
The final line appears because to validate the transactions' signatures, you technically need to the source transactions. So let’s add
to augment the transactions with source information.-a
$ tx -a 49d2adb6e476fa46d8357babf78b1b501fd39e177ac7833124b3f67b17c40c2a warning: transaction fees recommendations casually calculated and estimates may be incorrect warning: transaction fee lower than (casually calculated) expected value of 0.1 mBTC, transaction might not propogate Version: 1 tx hash 49d2adb6e476fa46d8357babf78b1b501fd39e177ac7833124b3f67b17c40c2a 159 bytes TxIn count: 1; TxOut count: 1 Lock time: 0 (valid anytime) Input: 0: 17WFx2GQZUmh6Up2NDNCEDk3deYomdNCfk from 1e133f7de73ac7d074e2746a3d6717dfc99ecaa8e9f9fade2cb8b0b20a5e0441:0 10000000.00000 mBTC sig ok Output: 0: 1CZDM6oTttND6WPdt3D6bydo7DYKzd9Qik receives 10000000.00000 mBTC Total input 10000000.00000 mBTC Total output 10000000.00000 mBTC Total fees 0.00000 mBTC 010000000141045e0ab2b0b82cdefaf9e9a8ca9ec9df17673d6a74e274d0c73ae77d3f131e000000004a493046022100a7f26eda874931999c90f87f01ff1ffc76bcd058fe16137e0e63fdb6a35c2d78022100a61e9199238eb73f07c8f209504c84b80f03e30ed8169edd44f80ed17ddf451901ffffffff010010a5d4e80000001976a9147ec1003336542cae8bded8909cdd6b5e48ba0ab688ac00000000 all incoming transaction values validated
We can see the transactions have been cached.
$ ls ~/.pycoin_cache/txs/ 1e133f7de73ac7d074e2746a3d6717dfc99ecaa8e9f9fade2cb8b0b20a5e0441_tx.bin 49d2adb6e476fa46d8357babf78b1b501fd39e177ac7833124b3f67b17c40c2a_tx.bin
Now, let’s create a new transaction with some Satoshi coinbase coins. In block #1, we see a coinbase transaction to 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX. Let’s use fetch_unspent to find all coins in this address.
$ fetch_unspent 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX a3a6f902a51a2cbebede144e48a88c05e608c2cce28024041a5b9874013a1e2a/0/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/333000 cea36d008badf5c7866894b191d3239de9582d89b6b452b596f1f1b76347f8cb/31/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/10000 065ef6b1463f552f675622a5d1fd2c08d6324b4402049f68e767a719e2049e8d/86/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/10000 a66dddd42f9f2491d3c336ce5527d45cc5c2163aaed3158f81dc054447f447a2/0/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/10000 ffd901679de65d4398de90cefe68d2c3ef073c41f7e8dbec2fb5cd75fe71dfe7/0/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/100 d658ab87cc053b8dbcfd4aa2717fd23cc3edfe90ec75351fadd6a0f7993b461d/5/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/911 36ebe0ca3237002acb12e1474a3859bde0ac84b419ec4ae373e63363ebef731c/1/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/100000 fd87f9adebb17f4ebb1673da76ff48ad29e64b7afa02fda0f2c14e43d220fe24/0/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/1 dfdf0b375a987f17056e5e919ee6eadd87dad36c09c4016d4a03cea15e5c05e3/1/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/1337 cb2679bfd0a557b2dc0d8a6116822f3fcbe281ca3f3e18d3855aa7ea378fa373/0/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/1337 d6be34ccf6edddc3cf69842dce99fe503bf632ba2c2adb0f95c63f6706ae0c52/1/76a914119b098e2e980a229e139a9ed01a469e518e6f2688ac/2000000 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098/0/410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac/5000000000
Wow, that yields a lot of options. The last one is the coinbase source from block #1. Let’s write a transaction that sends these coins to my donation address.
$ tx 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098/0/410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac/5000000000 1KissFDVu2wAYWPRm4UGh5ZCDU9sE9an8T -o tx.bin all incoming transaction values validated $ ls -l tx.bin -rw-r--r-- 1 kiss staff 161 Apr 27 18:23 tx.bin
Now, let’s dump it.
$ tx tx.bin warning: transaction fees recommendations casually calculated and estimates may be incorrect Version: 1 tx hash 3d36aed60ecb311a55a6329f5c2af785f06e147fc35b7678eb798eca7f603c83 85 bytes TxIn count: 1; TxOut count: 1 Lock time: 0 (valid anytime) Input: 0: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098:0 50000.00000 mBTC BAD SIG Output: 0: 1KissFDVu2wAYWPRm4UGh5ZCDU9sE9an8T receives 49999.90000 mBTC Total input 50000.00000 mBTC Total output 49999.90000 mBTC Total fees 0.10000 mBTC including unspents in hex dump since transaction not fully signed 0100000001982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e0000000000ffffffff01f0ca052a010000001976a914cd5dc792f0abb0aa8ba4ca36c9fe5eda8e495ff988ac0000000000f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac all incoming transaction values validated
We see a transaction that sends most of the 50 BTC to a new address. The signature is not correct though. If we had the private key, we could sign it like this:
$ tx tx.bin -f wifs.gpg -o signed_tx.bin
You need a passphrase to unlock the secret key for user: "Richard Kiss <[email protected]>" 2048-bit ELG-E key, ID 681E71C8, created 1999-11-08 (main key ID DBD8AB6A)
gpg: encrypted with 2048-bit ELG-E key, ID 681E71C8, created 1999-11-08 "Richard Kiss <[email protected]>" signing... warning: 1 TxIn items still unsigned all incoming transaction values validated
Yep, if the file passed to -f ends with
, then .gpg
is automatically invoked, and you can type your GPG passphrase. So gpg -d
plus tx
is actually a pretty reasonably secure solution! And if you keep your WIF.gpg file on an airgapped machine, this solves the problem of cold storage!gpg
$ shasum tx.bin signed_tx.bin 3ba7db8417e0fe1aeb7b4a1cbf13880bf84f38bc tx.bin 3ba7db8417e0fe1aeb7b4a1cbf13880bf84f38bc signed_tx.bin
Unfortunately for me, this file didn’t include the WIF to the outgoing transaction, so the transaction remains unsigned.
You can also use
to fetch all unspents (via the web) for a given bitcoin address and split it up.-i
$ tx -F 85000 -i 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX 1KissFDVu2wAYWPRm4UGh5ZCDU9sE9an8T 1KissEskteXTAXbh17qJYLtMes1B6kJxZj 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX/50 warning: transaction fees recommendations casually calculated and estimates may be incorrect warning: transaction fee of 0.85 exceeds expected value of 0.1 mBTC Version: 1 tx hash fb3551086baa047f4e8b55a28c275502b48c637c003b89dbececb3cab8897089 604 bytes TxIn count: 12; TxOut count: 3 Lock time: 0 (valid anytime) Inputs: 0: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from a3a6f902a51a2cbebede144e48a88c05e608c2cce28024041a5b9874013a1e2a:0 3.33000 mBTC BAD SIG 1: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from cea36d008badf5c7866894b191d3239de9582d89b6b452b596f1f1b76347f8cb:31 0.10000 mBTC BAD SIG 2: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from 065ef6b1463f552f675622a5d1fd2c08d6324b4402049f68e767a719e2049e8d:86 0.10000 mBTC BAD SIG 3: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from a66dddd42f9f2491d3c336ce5527d45cc5c2163aaed3158f81dc054447f447a2:0 0.10000 mBTC BAD SIG 4: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from ffd901679de65d4398de90cefe68d2c3ef073c41f7e8dbec2fb5cd75fe71dfe7:0 0.00100 mBTC BAD SIG 5: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from d658ab87cc053b8dbcfd4aa2717fd23cc3edfe90ec75351fadd6a0f7993b461d:5 0.00911 mBTC BAD SIG 6: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from 36ebe0ca3237002acb12e1474a3859bde0ac84b419ec4ae373e63363ebef731c:1 1.00000 mBTC BAD SIG 7: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from fd87f9adebb17f4ebb1673da76ff48ad29e64b7afa02fda0f2c14e43d220fe24:0 0.00001 mBTC BAD SIG 8: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from dfdf0b375a987f17056e5e919ee6eadd87dad36c09c4016d4a03cea15e5c05e3:1 0.01337 mBTC BAD SIG 9: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from cb2679bfd0a557b2dc0d8a6116822f3fcbe281ca3f3e18d3855aa7ea378fa373:0 0.01337 mBTC BAD SIG 10: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from d6be34ccf6edddc3cf69842dce99fe503bf632ba2c2adb0f95c63f6706ae0c52:1 20.00000 mBTC BAD SIG 11: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX from 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098:0 50000.00000 mBTC BAD SIG Outputs: 0: 1KissFDVu2wAYWPRm4UGh5ZCDU9sE9an8T receives 25011.90818 mBTC 1: 1KissEskteXTAXbh17qJYLtMes1B6kJxZj receives 25011.90818 mBTC 2: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX receives 0.00050 mBTC Total input 50024.66686 mBTC Total output 50023.81686 mBTC Total fees 0.85000 mBTC including unspents in hex dump since transaction not fully signed 010000000c2a1e3a0174985b1a042480e2ccc208e6058ca8484e14debebe2c1aa502f9a6a30000000000ffffffffcbf84763b7f1f196b552b4b6892d58e99d23d391b1946886c7f5ad8b006da3ce1f00000000ffffffff8d9e04e219a767e7689f0402444b32d6082cfdd1a52256672f553f46b1f65e065600000000ffffffffa247f4474405dc818f15d3ae3a16c2c55cd42755ce36c3d391249f2fd4dd6da60000000000ffffffffe7df71fe75cdb52fecdbe8f7413c07efc3d268fece90de98435de69d6701d9ff0000000000ffffffff1d463b99f7a0d6ad1f3575ec90feedc33cd27f71a24afdbc8d3b05cc87ab58d60500000000ffffffff1c73efeb6333e673e34aec19b484ace0bd59384a47e112cb2a003732cae0eb360100000000ffffffff24fe20d2434ec1f2a0fd02fa7a4be629ad48ff76da7316bb4e7fb1ebadf987fd0000000000ffffffffe3055c5ea1ce034a6d01c4096cd3da87ddeae69e915e6e05177f985a370bdfdf0100000000ffffffff73a38f37eaa75a85d3183e3fca81e2cb3f2f8216618a0ddcb257a5d0bf7926cb0000000000ffffffff520cae06673fc6950fdb2a2cba32f63b50fe99ce2d8469cfc3ddedf6cc34bed60100000000ffffffff982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e0000000000ffffffff03a2241595000000001976a914cd5dc792f0abb0aa8ba4ca36c9fe5eda8e495ff988aca2241595000000001976a914cd5dc78d67a621ad4564aac6cc1f931b4d8be8d988ac32000000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac00000000c8140500000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac10270000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac10270000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac10270000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac64000000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac8f030000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688aca0860100000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac01000000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac39050000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac39050000000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac80841e00000000001976a914119b098e2e980a229e139a9ed01a469e518e6f2688ac00f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac all incoming transaction values validated
Note that 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX was explicitly budgeted 50 satoshis. A custom fee of 85000 satoshis was paid, and the remainder was split between the other two addresses.
OK, let’s try actually signing a transaction. Let’s use the WIF for secret exponent 1.
$ ku -a -u 1 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm
Investigation on blockchain.info show a transaction payable to this bitcoin address with id d61aa2a5f5bce59d2a57447134f7ce9ce9d29b5c471f4bf747c43bf82aa26c2a.
$ tx -u d61aa2a5f5bce59d2a57447134f7ce9ce9d29b5c471f4bf747c43bf82aa26c2a d61aa2a5f5bce59d2a57447134f7ce9ce9d29b5c471f4bf747c43bf82aa26c2a/0/76a9149b92770a85b1252448ec69900e77f1371d6a620188ac/70594320 d61aa2a5f5bce59d2a57447134f7ce9ce9d29b5c471f4bf747c43bf82aa26c2a/1/76a91491b24bf9f5288532960ac687abb035127b1d28a588ac/12345678
-
can’t validate transaction as source transactions missing
The
shows the unspents, which can be passed as inputs to tx.-u
$ tx d61aa2a5f5bce59d2a57447134f7ce9ce9d29b5c471f4bf747c43bf82aa26c2a/1/76a91491b24bf9f5288532960ac687abb035127b1d28a588ac/12345678 1KissFDVu2wAYWPRm4UGh5ZCDU9sE9an8T -o tx.bin all incoming transaction values validated
$ tx tx.bin warning: transaction fees recommendations casually calculated and estimates may be incorrect Version: 1 tx hash ab963a39df0e095bbd76840de90fe208e903d5d43e891ef245b217dbcd29a8a7 85 bytes TxIn count: 1; TxOut count: 1 Lock time: 0 (valid anytime) Input: 0: 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm from d61aa2a5f5bce59d2a57447134f7ce9ce9d29b5c471f4bf747c43bf82aa26c2a:1 123.45678 mBTC BAD SIG Output: 0: 1KissFDVu2wAYWPRm4UGh5ZCDU9sE9an8T receives 123.35678 mBTC Total input 123.45678 mBTC Total output 123.35678 mBTC Total fees 0.10000 mBTC including unspents in hex dump since transaction not fully signed 01000000012a6ca22af83bc447f74b1f475c9bd2e99ccef7347144572a9de5bcf5a5a21ad60100000000ffffffff013e3abc00000000001976a914cd5dc792f0abb0aa8ba4ca36c9fe5eda8e495ff988ac000000004e61bc00000000001976a91491b24bf9f5288532960ac687abb035127b1d28a588ac all incoming transaction values validated
Now, let’s sign it.
$ tx tx.bin KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn -o signed_tx.hex signing... all incoming transaction values validated $ cat signed_tx.hex 01000000012a6ca22af83bc447f74b1f475c9bd2e99ccef7347144572a9de5bcf5a5a21ad6010000008b48304502210084fd73b302520381dea1885efda58bc446653998864db7a2cd04906fc6d5536302206325303c8e50f84d25c95eff2849441382d4aafb2f678f636a6d164b721bf0f101410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ffffffff013e3abc00000000001976a914cd5dc792f0abb0aa8ba4ca36c9fe5eda8e495ff988ac00000000 $ tx -a signed_tx.hex warning: transaction fees recommendations casually calculated and estimates may be incorrect Version: 1 tx hash 0995cf6f55e1cf22f7c31f5ad52d111e897b0b9b7e37a1bb755a470324b4a2c4 224 bytes TxIn count: 1; TxOut count: 1 Lock time: 0 (valid anytime) Input: 0: 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm from d61aa2a5f5bce59d2a57447134f7ce9ce9d29b5c471f4bf747c43bf82aa26c2a:1 123.45678 mBTC sig ok Output: 0: 1KissFDVu2wAYWPRm4UGh5ZCDU9sE9an8T receives 123.35678 mBTC Total input 123.45678 mBTC Total output 123.35678 mBTC Total fees 0.10000 mBTC 01000000012a6ca22af83bc447f74b1f475c9bd2e99ccef7347144572a9de5bcf5a5a21ad6010000008b48304502210084fd73b302520381dea1885efda58bc446653998864db7a2cd04906fc6d5536302206325303c8e50f84d25c95eff2849441382d4aafb2f678f636a6d164b721bf0f101410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ffffffff013e3abc00000000001976a914cd5dc792f0abb0aa8ba4ca36c9fe5eda8e495ff988ac00000000 all incoming transaction values validated
Wow! It worked! (It wrote the output as hex because of the ".hex" suffix.)
So why not just broadcast this transaction and collect our winnings? Well, the coins have already been spent. Oh well.
Note that pycoin uses a deterministic algorithm to create the signatures, so if you try this at home, you will get the exact same transaction with the exact same 0995cf6f55e1cf22f7c31f5ad52d111e897b0b9b7e37a1bb755a470324b4a2c4 hash.
You can also use pycoin to create and validate keys programmatically. >>> from pycoin.key import Key >>> k = Key.from_text("1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH") >>> print(k.address()) 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH >>> print(k.hash160()) b'u\x1ev\xe8\x19\x91\x96\xd4T\x94\x1cE\xd1\xb3\xa3#\xf1C;\xd6' >>> from pycoin.serialize import b2h >>> print(b2h(k.hash160())) 751e76e8199196d454941c45d1b3a323f1433bd6 Compare to using ku: $ ku 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH input : 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH network : Bitcoin mainnet netcode : BTC hash160 : 751e76e8199196d454941c45d1b3a323f1433bd6 Bitcoin mainnet address : 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH >>> from pycoin.key.validate import is_address_valid >>> v = is_address_valid("1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH") >>> print(v) 'BTC' # you can also specify certain networks, like Litecoin >>> v = is_address_valid("1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH", allowable_netcodes=["LTC"]) >>> print(v) None # not a valid LTC address >>> v = is_address_valid("1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH", allowable_types=["pay_to_script"]) >>> print(v) None # not a valid pay-to-script address (they start with a "3") >>> v = is_address_valid("1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH", allowable_types=["address"]) >>> print(v) BTC >>> from pycoin.key import Key >>> k = Key(secret_exponent=1) >>> print(k.address()) 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH >>> print(k.wif()) KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn >>> print(k.as_text()) KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn $ ku KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn input : KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn network : Bitcoin mainnet netcode : BTC secret exponent : 1 hex : 1 wif : KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn uncompressed : 5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf public pair x : 55066263022277343669578718895168534326250603453777594175500187360389116729240 public pair y : 32670510020758816978083085130507043184471273380659243275938904335757337482424 x as hex : 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 y as hex : 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 y parity : even key pair as sec : 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 uncompressed : 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\ 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 hash160 : 751e76e8199196d454941c45d1b3a323f1433bd6 uncompressed : 91b24bf9f5288532960ac687abb035127b1d28a5 Bitcoin mainnet address : 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH Bitcoin mainnet uncompressed : 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm Different networks have different representations of the same WIF. $ ku -W 1 KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn $ ku -W -n XTN 1 cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA $ ku -W 1 -n DOGE QNcdLVw8fHkixm6NNyN6nVwxKek4u7qrioRbQmjxac5TVoTtZuot $ ku -W 1 -n LTC T33ydQRKp4FCW5LCLLUB7deioUMoveiwekdwUwyfRDeGZm76aUjV
Fetch, parse a tx, stream a tx
$ tx 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 -o tx.out all incoming transaction values validated
>>> from pycoin.tx import Tx >>> tx = Tx.parse(open("tx.out", "rb")) >>> print(tx) Tx [0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098] >>> print(tx.txs_in[0]) TxIn<COINBASE: 04ffff001d0104> >>> print(tx.txs_out[0]) TxOut<5E+4 mbtc "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee OP_CHECKSIG"> >>> f1 = open("tx1.out", "wb") >>> tx.stream(f1) $ ls -l tx1.out -rw-r—r-- 1 kiss staff 134 Jun 11 17:02 tx1.out $ tx tx1.out warning: transaction fees recommendations casually calculated and estimates may be incorrect warning: transaction fee lower than (casually calculated) expected value of 0.1 mBTC, transaction might not propogate Version: 1 tx hash 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 134 bytes TxIn count: 1; TxOut count: 1 Lock time: 0 (valid anytime) Input: 0: COINBASE 50000.00000 mBTC Output: 0: 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX receives 50000.00000 mBTC Total input 50000.00000 mBTC Total output 50000.00000 mBTC Total fees 0.00000 mBTC 01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000 all incoming transaction values validated
A simple script to grab and spend coins. #!/usr/bin/env python from pycoin.key import Key from pycoin.key.validate import is_address_valid, is_wif_valid from pycoin.services import spendables_for_address from pycoin.tx.tx_utils import create_signed_tx def get_address(which): while 1: print("enter the %s address=> " % which, end='') address = input() is_valid = is_address_valid(address) if is_valid: return address print("invalid address, please try again") src_address = get_address("source") spendables = spendables_for_address(src_address) print(spendables) while 1: print("enter the WIF for %s=> " % src_address, end='') wif = input() is_valid = is_wif_valid(wif) if is_valid: break print("invalid wif, please try again") key = Key.from_text(wif) if src_address not in (key.address(use_uncompressed=False), key.address(use_uncompressed=True)): print("** WIF doesn't correspond to %s" % src_address) print("The secret exponent is %d" % key.secret_exponent()) dst_address = get_address("destination") tx = create_signed_tx(spendables, payables=[dst_address], wifs=[wif]) print("here is the signed output transaction") print(tx.as_hex())