Command-line Bitcoin Transactions

The “spend” tool is obsolete, which makes this post not-so-useful. Look at the “tx” tool mentioned in this post instead.

Creating a signed transaction is the holy grail of Bitcoin. Without this functionality, a Bitcoin client can’t really be called a client. Being able to sign a transaction though… wow! The whole Bitcoin world is at your fingertips!

OK, that may be a bit of an overstatement… but it’s still pretty neat stuff.

My pycoin project features a Python command-line script “spend” that will let you generate a standard transaction that reassigns coins from one set of addresses to another set. It’s obviously not nearly as easy as using a GUI app to spend your bitcoin. But it is very simple-to-follow sample code that you can use as a template should you want to create your own Bitcoin transactions programmatically.

To create a transaction, you need the coin sources. These are the TxOut portions of the transactions that assigned bitcoin to an address. The “spend” script takes bitcoin addresses as input, and queries the blockchain.info web site to get the list of unclosed spendable transactions. This script “spends” all your bitcoin on the addresses you give. No problem though: you can send coins you want to keep (the “change”) to an address you control.

Here’s an example blockchain.info query:

http://blockchain.info/unspent?active=12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX

(If Satoshi ever gets around to spending all these coins, this URL will throw a 500.)

Of course, it’s not enough to have the sources for the coins; you need the private key. Although pycoin deals with this private key in its native “secret exponent” numerical form, the spend script expects WIF format. So you need to create a file with the WIF. How you get the WIF depends on how you generated the address. In Electrum, right-click on the address and choose “Private Key”, and the WIF will be displayed.

For maximal security, you might think about creating this WIF file on a RAM disk. On Mac OS X,

diskutil erasevolume HFS+ RAMDISK `hdiutil attach -nomount ram://2048`

and it will mount in /Volumes/RAMDISK.

Create a “wifs” text file, and add the WIF elements, one per line. You can add extraneous WIF with no worries; just make sure you have a WIF entry for every source address so the “spend” script has the information it needs to sign the outgoing transactions.

cat >> /Volumes/RAMDISK/wifs
(paste WIF)

Since it’s on a RAM disk, you don’t have to worry about someone scraping your unused drive sectors later. Unless that RAM gets paged to disk. Oh no, a security rabbit hole!! HELP

You also need to specify where you want the coins to go. That’s a simple list of (bitcoin address, coin value) pairs.

Those three elements — coin source, private keys, coin destination — are all you need to create a transaction.

$ spend -s 1BHeaS4vn9NsA6Fi4KFYREGzYmdhdZuJhH -f /Volumes/RAMDISK/wifs -d 15jpiqB2AHb2iwi83KJNxzohouxd1PEDyu/0.04476
transaction fee: 0 BTC
warning: transaction fee lower than (casually calculated) expected value of 0.00010000 BTC, transaction might not propogate
copy the following hex to http://blockchain.info/pushtx to put the transaction on the network:

0100000001068ded23b986c6fc01106596ccbabfc157c850569359ea082ab2e813f277142201\
0000008b483045022100ef5b8504a227f967a7a7c2af55e79f9886e4f9182027745fcdb7fcc4\
b8afdf830220421704dd397cee26e1634e458b1678d80c37cafdf13a0f41a6dd98bff350d9f9\
014104430ba52cd1a88b7049295ceee2e6576af7211e8a9b01b70e572ff70f4718699a64b4c8\
ea0dd3ddb3c7dab0ee53dcc4e70c6913ee0cf904853da94422b5c1b289ffffffff01604c4400\
000000001976a91433f9cf2774a90c53a3e55e5e8bbb5cb3d1090a9988ac00000000

The spend script also displays how much bitoin is unaccounted for in outputs. This amount becomes a transaction fee for the block.

The script generates the transaction and displays it as hex on the screen. It does not send it to the network. You can paste the hex onto blockchain.info to get the transaction on the network and into a block.

Note that if you generate what seems like should be the exact same transaction again, you will (hopefully) get a different hex output. That’s because part of the process of signing a transaction uses a randomly generated value K. If the value for K is known, observers can work backwards to figure out the secret key from the signature generated. In fact, if you use the same value for K to sign two different transactions, the secret key can be recovered. So it’s important that this K value be generated securely, using a cryptographically-safe random number generator.

10 thoughts on “Command-line Bitcoin Transactions

  1. Dmcrypt (linux) your whole drive and put your swap position in the encrypted partition! Love all this bitcoin having you are doing!

  2. Hey it looks good. I am not a python programmer but I could use scripts like these. The deterministic wallet generation is especially cool. Command line generation of deterministic wallets opens up all sorts of possibilities.

    The more I learn about bitcoin related software the more I feel I really really need to learn python 🙂

  3. Hey Richard,

    with


    $ python --version
    Python 3.2.3rc2

    the spend command ended for me with an error at line 38 of file pycoin/services/blockchain_info.py:

    TypeError: ‘str’ does not support the buffer interface”

    It went through after adding two “encode()” calls by changing lines 38,39


    tx_out = TxOut(unspent_output["value"], 5 binascii.unhexlify(unspent_output["script"]))
    coins_source = (binascii.unhexlify(unspent_output["tx_hash"]), unspent_output["tx_output_n"], tx_out)

    to


    tx_out = TxOut(unspent_output["value"], binascii.unhexlify(unspent_output["script"].encode()))
    coins_source = (binascii.unhexlify(unspent_output["tx_hash"].encode()), unspent_output["tx_output_n"], tx_out)

    (And copying the raw transaction to http://blockchain.info/pushtx succeeded as well)

    Stephan

  4. Is it correct to say that if I have 1.0 BTC and I transfer 0.5 BTC to another address I’m automatically offering 0.5 BTC as transferfee?

    So the send.py might need a piece of code that takes the unspend BTC, substracts the transaction fee and sends that amount to the public address you can calculate from the WIF (if only one given).

    Correct?

  5. You are correct that unaccounted BTC gets consumed as a transfer fee.

    However, not that although the spend.py script creates a transaction, it doesn’t actually transmit it to anywhere besides the screen as a raw hex dump. It also prints a warning if the transaction fees seems too large. Since further action is required to actually cause the transaction to be submitted to the network, I would think this warning is enough to alert the user that something is up.

  6. What would be the proper way to get the transaction on the network?
    Off course using urllib2 sending a POST request to blockchain.info would work 🙂

  7. The “proper” way is any way that works. 🙂 Using blockchain.info is the easiest way. Another way would be to use (or write) a client that connects to the network, and dump the transaction into it.

    Either way, it ends up in the same place: the block chain.

  8. hi,
    I’m trying to spend a transaction from a p2sh address to an other but the output address cannot be parsed properly. If I add the “-i” option:

    tx 8d852ef1b2d290b515763f604f753e84352059cf31766845eadcb4ac8ab4edbb/0/a9146de2a879701db827dafec3c1f895b35093205d4587/30000 -i3AAhGP5qDfo3DvAEZ1WeQgp71y4c112NBr -o tx.bin
    warning: transaction has no outputs
    all incoming transaction values validated

    tx tx.bin
    warning: transaction has no outputs
    warning: transaction fees recommendations casually calculated and estimates may be incorrect
    warning: transaction fee of 0.3 exceeds expected value of 0.1 mBTC
    Version: 1 tx hash dcc195f8871586a31fd39fec009b33deab7c075f08509e764770e51c2b83f269 51 bytes
    TxIn count: 1; TxOut count: 0
    Lock time: 0 (valid anytime)
    Input:
    0: 3Bi36w9RZHmibi1ip7ud9dvtpDt59ij7GC from 8d852ef1b2d290b515763f604f753e84352059cf31766845eadcb4ac8ab4edbb:0 0.30000 mBTC BAD SIG
    Outputs:
    Total input 0.30000 mBTC
    Total output 0.00000 mBTC
    Total fees 0.30000 mBTC
    including unspents in hex dump since transaction not fully signed
    0100000001bbedb48aacb4dcea45687631cf592035843e754f603f7615b590d2b2f12e858d0000000000ffffffff0000000000307500000000000017a9146de2a879701db827dafec3c1f895b35093205d4587
    all incoming transaction values validated

  9. The -i flag doesn’t set your 3AAhGP5qDfo3DvAEZ1WeQgp71y4c112NBr address as an output; it fetches all unspents payed to that address and makes them inputs.

    You want 3AAhGP5qDfo3DvAEZ1WeQgp71y4c112NBr on the command line by itself (no -i). However, it looks like pay-to-script-hash addresses (the ones that start with a “3”) don’t work at this time in the “tx” tool. There is support elsewhere in pycoin, so this tool really ought to support it too.

  10. Thank you Richard for the prompt replay.
    The bitter reality is that I cannot write a multisig transaction in python with pycoin because I cannot understand how to build it and sign it.

    Is there a snippet somewhere to build a multisig transaction and to sign it partially (something like one sig of two required) ?
    I’m trying to build something to be sent to cryptocorp.co/api to have them sign the remaining part.

    I have looked at the tests but they don’t help a lot.
    I would say I should provide the p2sh address (to retrieve the spendable), the script, the wif, the output/amount, the fees and the version but I really cannot figure out how.

    Great library BTW. Thank you for the contribute to Bitcoin.

Comments are closed.