Developer’s Introduction to Bitcoin

One of the major advantages of Bitcoin is just how easy it is to work with from a developer’s standpoint. Bitcoin has no third party dependencies, no proprietary APIs, and no rapidly changing interface; all you need is your own favorite programming language, and chances are there is already a simple Bitcoin library that you can use to start sending and receiving bitcoins within a few hours. The purpose of this article will be to introduce a few of these libraries, and show the basics of working with Bitcoin addresses and transactions in any language.

Addresses, Keys, Transactions, Oh My!

The Bitcoin protocol in general can be split into three parts: address and key management, transactions, and blocks and mining. Blocks and mining are not important for you as a beginning Bitcoin developer; in most cases it is easier to simply rely on a third-party transaction-fetching service which abstracts the concept of blocks away, and if you are interested in mining the best approach is to simply buy a standard Bitcoin miner. Addresses, keys and transactions, however, you simply cannot avoid dealing with.

In Bitcoin key management, there are three types of objects that you will need to deal with: private keys, public keys and addresses. You may have heard of the terms “private key” and “public key” in the context of public key cryptography; that is exactly the kind of private and public keys we are talking about here. However, Bitcoin uses a newer kind of cryptography called elliptic curve cryptography, and not the older factoring-based cryptographic algorithms like RSA, so Bitcoin keys look a bit different from, say, PGP keys. A private key looks like this:

9d86361789d13823fd888fa45c9b356b76d41a7e33b2b2c3056632721c4c1255

And its corresponding public key is:

04d8f08938e78447b2b1a629c503d5e17483b0d15751a9e8f83c8460e6ec32fd
68d0b4068e83c012f54df995e52ed8bae38056a8d922f9687200ae83e5a6728d
ff

A private key can be converted into a public key, but a public key cannot be converted into a private key. A Bitcoin address is actually the hash of the public key; the Bitcoin address corresponding to the above public key is:

172YRdGzPqyXm9rm1EWKwPXTRsmcApoPQ6

One thing that you might notice is that the Bitcoin address is not in hexadecimal form like the private and public keys are. This is because, for some of its formats, Bitcoin uses its own representation format, known as base58check. The “base58” part comes from the fact that 58 different letters and numbers are used; O, 0, l and I are omitted because they are too easy to mistake for each other. Base 58 is similar to base 2, or base 3, or base 10. For example, the number 31337 in base 2 is ‘111101001101001’; in base 3 it’s ‘1120222122’, in base 10 it’s ‘31337’, in base 16 it’s ‘7a69’, in base 58 it’s ‘AKJ’ and, finally, in base 256 it’s just ‘zi’. The “check” part of base58check is also important; what it means is that the first four bytes of the hash of a message is added to the end of the message before encoding the result in base58. For example, the process of converting ‘zi’ from base 256 into base 58 works as follows:

  • Step 1: checksum = sha256(sha256(‘\x00’ + ‘zi’)) (note that we add a zero byte at the front)

    ’97fbc63584f26bd0109f99d467c447607dbecff51b903e450207466114672261′

  • Step 2: intermediate = ‘\x00’ + ‘zi’ + checksum[:4] (in binary form)

    ‘\x00zi\x97\xfb\xc6\x35’

  • Step 3: convert to base 58

    ‘123xZAaruJ’

However, you personally will not need to deal with all of these complexities; Bitcoin libraries exist to handle everything for you, and we will talk about a few later in the article. But first, transaction handling.

The first important point to keep in mind is that Bitcoin does not internally have the concept of “accounts” or “balances”; all funds are stored in objects known as “transaction outputs”. A transaction has one or more inputs, each input spending an existing unspent transaction output (“UTXO”), and the transaction can then send up to the same amount of BTC in total outputs that it has in inputs. Here is what a transaction looks like in deserialized form:

{
    "locktime": 0,
    "ins": [
        {
            "script": "",
            "outpoint": {
                "index": 0,
                "hash": "319ba90f1645eed46a8fd48e9754ca979c3371f59099d32634a8b56549ce02aa"
            },
            "sequence": 4294967295
        }
    ],
    "outs": [
        {
            "value": 1000000,
            "script": "76a914a41d15ae657ad3bfd0846771a34d7584c37d54a288ac"
        },
        {
            "value": 344164,
            "script": "76a914c4c5d791fcb4654a1ef5e03fe0ad3d9c598f982788ac"
        }
    ],
    "version": 1
}

And in serialized form:

0100000001aa02ce4965b5a83426d39990f571339c97ca54978ed48f6ad4ee45
160fa99b310000000000ffffffff0230750000000000001976a914a41d15ae65
7ad3bfd0846771a34d7584c37d54a288ac204e0000000000001976a914c4c5d7
91fcb4654a1ef5e03fe0ad3d9c598f982788ac00000000

The “script” parameter is just another way of representing an address; converting the two scripts in the above transaction to addresses we get “1FxkfJQLJTXpW6QmxGT6oF43ZH959ns8Cq” and “1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T”, respectively. The single input in the transaction is a reference to a previous transaction output; looking it up on the blockchain, we see that it has 1354164 satoshis available to spend (1 satoshi is the smallest unit of a bitcoin, with 100 million satoshi = 1 BTC). The two outputs spend 1344164, leaving 10000 satoshis as a fee.

Note that a transaction can only spend an output in its entirety, and not partially. To get around this, the standard mechanism is the concept of “change” – send one output to the intended destination, and then another output sending the rest back to yourself. The above transaction is an example of that – the first output would be a 0.01 BTC payment, and the second would be the change. Once you create a transaction, you then need to sign each input with the private key that corresponds to each address. The process for doing so is pretty involved, but fortunately libraries handle it for you. Here is what the above transaction looks like once it’s signed:

0100000001aa02ce4965b5a83426d39990f571339c97ca54978ed48f6ad4ee45
160fa99b31000000008b48304502203bcabb367ca84b2af394597bff4a6169fa
55b156708557256d2c584f1bd54e1502210086fdf257e58dbb5e1f3b4686f438
5e86ea89e677a6c90a3c87ce276d88ad2b31014104e6eb4c73192bcc7b63f7e3
c05ed52c0d98abac6f6aa0876e2e57eeda6b60fe03098cb63633d08077b14cc3
0efe9bc5c9866ebc1297c03399e27381539025f887ffffffff0240420f000000
00001976a914a41d15ae657ad3bfd0846771a34d7584c37d54a288ac64400500
000000001976a914c4c5d791fcb4654a1ef5e03fe0ad3d9c598f982788ac0000
0000

Then, finally, you need to push the signed transaction to the blockchain. The best way to do this manually is at http://blockchain.info/pushtx. And that’s basically all there is to Bitcoin – until we get into advanced features like multisignature transactions, that is, but those are best described in more detail in another article.

Bitcoind

Bitcoind is the “reference client” created by the core Bitcoin development team; it is a full Bitcoin node that downloads the entire blockchain and processes transactions. Bitcoind is somewhat limited in functionality; for example, it cannot give you the transaction history of an address unless you had imported that address beforehand. However, it is nevertheless fairly powerful. Once you download bitcoind from its project page and build it, the first step is to create a file in your Bitcoin directory (~/.bitcoin on Linux) with the following contents:

rpcuser=user
rpcpassword=pass
rpcport=8332
txindex=1

Substitute in your own username and password if desired. Once you do this, navigate to the directory containing the executable (/bin if your version came with an executable pre-made, /src if you made it yourself), and run ./bitcoind --daemon on the command line to start up the daemon. At that point, you have two ways of running bitcoind commands.

The first way is simpler: just enter “bitcoind” followed by the name of the command and the arguments on the command line. For example:

> ./bitcoind getblockhash 1
00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

> ./bitcoind getblock 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

{
    "hash" : "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048",
    "confirmations" : 212362,
    "size" : 215,
    "height" : 1,
    "version" : 1,
    "merkleroot" : "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
    "tx" : [
        "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
    ],
    "time" : 1231469665,
    "nonce" : 2573394689,
    "bits" : "1d00ffff",
    "difficulty" : 1.00000000,
    "previousblockhash" : "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
    "nextblockhash" : "000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd"
}


> bitcoind getrawtransaction 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098
01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000

The second way is using JSON-RPC. JSON-RPC is a generic interface that allows you to connect to bitcoind and run commands with it from any language – potentially even from another computer. The Bitcoin wiki has a page describing some of the ways to make a JSON-RPC call in different programming languages; for the sake of brevity I will only list two.

In Python:

import httplib, json, base64
def mkrequest(url,user,pass,method,params,hasresponse=True):
    connection = httplib.HTTPConnection(url)                          
    postdata = json.dumps({ "method": method, "params": params })                         
    req = urllib2.Request('http://localhost:8001',postdata,{                              
        'Authorization': b'Basic '+base64.b64encode(user+':'+pass),                        
    })                                                                                    
    if hasresponse: return urllib2.urlopen(req).read().strip()

And on the command line using curl:

curl --user <user> --pass <pass> --data-binary '{"method": <method>,
"params": [<param1>,<param2>...] }' http://localhsot:8332

SX

There are two alternative command line tools for dealing with Bitcoin transactions: pybitcointools and SX. SX was created by libbitcoin developer Amir Taaki, and is now being actively maintained by a small team; pybitcointools was written by myself. The syntax is fairly similar, although there are differences. Installing SX is relatively simple; all that you need to do is download a text file called install-sx.sh, install a few libraries, and run the text file. On Ubuntu, the command line instructions are as follows:

wget http://sx.dyne.org/install-sx.sh
sudo apt-get install git build-essential autoconf libtool libboost-all-dev pkg-config libcurl4-openssl-dev libleveldb-dev libzmq-dev libconfig++-dev libncurses5-dev qrencode
chmod +x install-sx.sh
./install-sx.sh

Then, once SX is installed, here is some of what you can do with it. If you are simply building a payment processing platform, it would be enough to simply fetch address the history of addresses and perhaps fetch transactions:

> sx history 114tTpMrJHJpNvkPZmz8KVcJoQjD5Utosd
Address: 114tTpMrJHJpNvkPZmz8KVcJoQjD5Utosd
  output: eb84dd62287a1d85e3f31b0de869534a8f800fad559e36f779a45470aa4e8976:0
  output_height: 277978
  value:  100000
  spend: 3216bc4b8294532cddab1ae2a95a336ee841be02e6246c1ad9cf1e7db788d10e:0
  spend_height: 277979

Address: 114tTpMrJHJpNvkPZmz8KVcJoQjD5Utosd
  output: 5a45c86c5aff8200db4c7f8a91b9a3e51932510cbeb2dc173fc8611bee5aeaaf:1
  output_height: 278076
  value:  70000
  spend: 4817f863ace4337be7ea95476b2c73723fb83fbe0e1a6236fbf30f2a8aa14dee:0
  spend_height: 278076

> sx fetch-transaction 516f0bfe2ed3703112434f645fdc7d805bba51c94c9d8f88b666f1c832eb423c
010000000142f2e85e078a214d5c61b58276da5cec01311e026355c570b650c2e665585011010000008a47304402203aa40adefd0dc4a3f960b230a9e1b284d78a4b4dec9119368fdeb006af3b6c7b022071165df64ea4502003d8b6e9c46c28b5c5c748226737b4fe1ee8fc4269b50ee5014104a70f7c8b0a835f549f061b725bd3e06744963a07cb2f76097bafe040f939d6e6d23c6cc89e5b50aa944d26b7d1c8a1f3b8b4e6f7c2f54cf35fb46b0e4b9442e1ffffffff02a0860100000000001976a914ba55b9859c7356c5e5549c8a30c463e3db64e84488ac80054800000000001976a9145a35a4558b8a0140f4a73aaac0be891b99e3790e88ac00000000

If you want to calculate the balance of an address, you would need to get the history (perhaps using sx history -j 114tTpMrJHJpNvkPZmz8KVcJoQjD5Utosd for a more computer-friendly format), filter out the items that have already been spent, and add the values of the rest. This will give you the total number of satoshis that the address haas available to spend (100 million satoshis = 1 BTC). If you want to make sense of transactions, you can paste the transaction into a file and then run sx showtx on the file.

You can also work with private keys and addresses:

> sx newkey > priv1
> cat priv1
5JRLqUG1FwSimZwSzNLPG1BKCENCRhDwkVveL59AEqt97bbkCD1
> cat priv1 | sx pubkey
04bfc8181cd833567e078cb03ec44034c226bf23dbb2482db53513e0fcea205c40bd6dc73db0c33296d8fa8e0bd347099e07787e17a2a40293004efdb512ff51e2
> cat priv1 | sx addr
1B772AGqphjSQqqeecdTBmnBdgMBPYDXt7

And make transactions. Here we use the output 819171fa2eaa33fc684c800ae2ce34cff8400d4d966e995c6a2f0e970b6f703d:0 to send 90000 satoshis to 18qk7SqRHuS4Kf3f6dmsvqqv7iw1xy77Z6:

> sx mktx txfile.tx -i 819171fa2eaa33fc684c800ae2ce34cff8400d4d966e995c6a2f0e970b6f703d:0 -o 18qk7SqRHuS4Kf3f6dmsvqqv7iw1xy77Z6:90000
> cat txfile.tx
01000000013d706f0b970e2f6a5c996e964d0d40f8cf34cee20a804c68fc33aa2efa7191810000000000ffffffff01905f0100000000001976a9145600d581a94f65067a09103609e919e3c01141ed88ac00000000
> sx rawscript dup hash160 [ `echo 1B772AGqphjSQqqeecdTBmnBdgMBPYDXt7 | sx decode-addr` ] equalverify checksig > raw.script
> cat raw.script
76a9146ed8c762b24ba024df09cb323ea525b06da3acb788ac
> echo 5JRLqUG1FwSimZwSzNLPG1BKCENCRhDwkVveL59AEqt97bbkCD1 | sx sign-input txfile.tx 0 `cat raw.script` > sig
> cat sig
3044022069f05eacfe93fc6c028bd078228d7807af07c5ed7566491c709b181950d735830220788e089c63512c07239b94740a36de724b54c076192dbd27584b5b729986420d01
> sx rawscript [ `cat sig` ] [ 04bfc8181cd833567e078cb03ec44034c226bf23dbb2482db53513e0fcea205c40bd6dc73db0c33296d8fa8e0bd347099e07787e17a2a40293004efdb512ff51e2 ] | sx set-input txfile.tx 0 > txfile2.tx
> cat txfile2.tx
01000000013d706f0b970e2f6a5c996e964d0d40f8cf34cee20a804c68fc33aa2efa719181000000008a473044022069f05eacfe93fc6c028bd078228d7807af07c5ed7566491c709b181950d735830220788e089c63512c07239b94740a36de724b54c076192dbd27584b5b729986420d014104bfc8181cd833567e078cb03ec44034c226bf23dbb2482db53513e0fcea205c40bd6dc73db0c33296d8fa8e0bd347099e07787e17a2a40293004efdb512ff51e2ffffffff01905f0100000000001976a9145600d581a94f65067a09103609e919e3c01141ed88ac00000000
> sx broadcast-tx txfile2.tx

And you can also validate a transaction:

> sx validtx txfile2.tx
Status: Validation of inputs failed
Unconfirmed: 0

The error makes sense because the outputs I used above were already spent. Altogether, SX allows you to essentially put together a flyweight “Bitcoin client”, selecting transaction outputs and making transactions manually. Just a warning though: this is a very risky thing to do, since if you accidentally leave a zero off a transaction output the system is too low-level to catch your error and you will end up paying a 90% fee.

Pybitcointools

Pybitcointools is really two things in one; it is at the same time a Python library which allows you to manipulate Bitcoin addresses, keys and transactions and an SX-like command line tool. To install both, download pybitcointools here, navigate to the directory, and run sudo python setup.py install. From there, open up a Python console and type from pybitcointools import * to import all of the pybitcointools commands.

First key management:

> priv = sha256('some big long brainwallet password')
> priv
'57c617d9b4e1f7af6ec97ca2ff57e94a28279a7eedd4d12a99fa11170e94f5a4'
> pub = privtopub(priv)
> pub
'0420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9'
> addr = pubtoaddr(pub)
> addr
'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'

But, as mentioned above, pybitcointools also includes pybtctool, an SX-like command line tool. To use pybtctool, run:

> pybtctool sha256 "some big long brainwallet password"
57c617d9b4e1f7af6ec97ca2ff57e94a28279a7eedd4d12a99fa11170e94f5a4

> pybtctool privtopub 57c617d9b4e1f7af6ec97ca2ff57e94a28279a7eedd4d12a99fa11170e94f5a4
0420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9

> pybtctool pubtoaddr 0420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9
1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6

Now, on to history and transaction fetching:

> h = history(addr)
> h
[{'output': u'97f7c7d8ac85e40c255f8a763b6cd9a68f3a94d2e93e8bfa08f977b92e55465e:0', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}, {'output': u'4cc806bb04f730c445c60b3e0f4f44b54769a1c196ca37d8d4002135e4abd171:1', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}]

> fetchtx('97f7c7d8ac85e40c255f8a763b6cd9a68f3a94d2e93e8bfa08f977b92e55465e')
'0100000002b8497b5d250420d0e0ef55150ae49f451846791f54b858e4d7b50e23c087b560010000008c493046022100a49c01bbf7a6200b05c61072f79fbbcbb56182e0082f85734ff501efd8f2180a022100a6d2b19a1023c4197206b1ea0d58165fa4d6170e7823d90d1cdb0f2704ceb5d0014104ba8b7ec1189b046d0f6dc68d2cafa4bfc30ea34b8f52a0f815550ffd5f5dfe12df06f2c9a3c1b206b833fe274601fe19e0afd9c47e251ba247edfa7a0237ab3affffffff71d1abe4352100d4d837ca96c1a16947b5444f0f3e0bc645c430f704bb06c84c000000008c493046022100c7309b13e54896533ebb6c369b1f46992ed7f8d96c8eb606cfd66a06bf6a061d022100e1cb8d32b380dac42584a5e1a6ff00c209767471b8bb82a13bf8d36221a39aa9014104a88f9a448cfcf259df1da679a37dd8e4c148cb6f0ba6a9b1e7d7019b09ef1034495f02d4cdf27d2bab41da3bce3f9508b20f6ad265b5940799610b69a12d02a5ffffffff0250c30000000000001976a9147d13547544ecc1f28eda0c0766ef4eb214de104588ac953d0800000000001976a9145fe616df99d43ae8001ca941f381572cd1cb74b388ac00000000'

Note that pybtctool includes a convenient -s switch that you can use to chain some operations together:

> pybtctool sha256 'some big long brainwallet password' | pybtctool -s privtoaddr | pybtctool -s history
[{'output': u'97f7c7d8ac85e40c255f8a763b6cd9a68f3a94d2e93e8bfa08f977b92e55465e:0', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}, {'output': u'4cc806bb04f730c445c60b3e0f4f44b54769a1c196ca37d8d4002135e4abd171:1', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}]

> pybtctool fetchtx 97f7c7d8ac85e40c255f8a763b6cd9a68f3a94d2e93e8bfa08f977b92e55465e | pybtctool -s deserialize
{"locktime": 0, "outs": [{"value": 50000, "script": "76a9147d13547544ecc1f28eda0c0766ef4eb214de104588ac"}, {"value": 540053, "script": "76a9145fe616df99d43ae8001ca941f381572cd1cb74b388ac"}], "version": 1, "ins": [{"script": "493046022100a49c01bbf7a6200b05c61072f79fbbcbb56182e0082f85734ff501efd8f2180a022100a6d2b19a1023c4197206b1ea0d58165fa4d6170e7823d90d1cdb0f2704ceb5d0014104ba8b7ec1189b046d0f6dc68d2cafa4bfc30ea34b8f52a0f815550ffd5f5dfe12df06f2c9a3c1b206b833fe274601fe19e0afd9c47e251ba247edfa7a0237ab3a", "outpoint": {"index": 1, "hash": "60b587c0230eb5d7e458b8541f794618459fe40a1555efe0d02004255d7b49b8"}, "sequence": 4294967295}, {"script": "493046022100c7309b13e54896533ebb6c369b1f46992ed7f8d96c8eb606cfd66a06bf6a061d022100e1cb8d32b380dac42584a5e1a6ff00c209767471b8bb82a13bf8d36221a39aa9014104a88f9a448cfcf259df1da679a37dd8e4c148cb6f0ba6a9b1e7d7019b09ef1034495f02d4cdf27d2bab41da3bce3f9508b20f6ad265b5940799610b69a12d02a5", "outpoint": {"index": 0, "hash": "4cc806bb04f730c445c60b3e0f4f44b54769a1c196ca37d8d4002135e4abd171"}, "sequence": 4294967295}]}

Note the deserialize command; you can of course use it in the pybitcointools library as well. And, of course, you can make transactions:

> pybtctool mktx 97f7c7d8ac85e40c255f8a763b6cd9a68f3a94d2e93e8bfa08f977b92e55465e:0 4cc806bb04f730c445c60b3e0f4f44b54769a1c196ca37d8d4002135e4abd171:1 16iw1MQ1sy1DtRPYw3ao1bCamoyBJtRB4t:90000 | pybtctool -s sign 0 57c617d9b4e1f7af6ec97ca2ff57e94a28279a7eedd4d12a99fa11170e94f5a4
01000000025e46552eb977f908fa8b3ee9d2943a8fa6d96c3b768a5f250ce485acd8c7f797000000008b483045022100dd29d89a28451febb990fb1dafa21245b105140083ced315ebcdea187572b3990220713f2e554f384d29d7abfedf39f0eb92afba0ef46f374e49d43a728a0ff6046e01410420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9ffffffff71d1abe4352100d4d837ca96c1a16947b5444f0f3e0bc645c430f704bb06c84c0100000000ffffffff01905f0100000000001976a9143ec6c3ed8dfc3ceabcc1cbdb0c5aef4e2d02873c88ac00000000

You can then push the transaction using pushtx or eligius_pushtx to push straight to a medium-sized mining pool. eligius_pushtx is useful for so-called “non-standard” transactionsthat ordinary Bitcoin nodes reject; for example, multisignatures transactions between more than three parties can be sent through here.

Libraries

Pybitcointools and SX are not the only tools out there; there are Bitcoin libraries in nearly every language. Here are a few:

Happy coding!

Leave a Reply

Your email address will not be published. Required fields are marked *