Skip to main content

Developer’s Introduction to Bitcoin

Op-ed - 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:


And its corresponding public key is:


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:


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)
  • Step 2: intermediate = 'x00' + 'zi' + checksum[:4] (in binary form)
  • Step 3: convert to base 58

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:


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:


Then, finally, you need to push the signed transaction to the blockchain. The best way to do this manually is at 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 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:


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 100000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048> ./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 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd51209801000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000

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, base64def 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 --pass --data-binary '{"method": ,"params": [,...] }' http://localhsot:8332


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 a few libraries, and run the text file. On Ubuntu, the command line instructions are as follows:

wget apt-get install git build-essential autoconf libtool libboost-all-dev pkg-config libcurl4-openssl-dev libleveldb-dev libzmq-dev libconfig++-dev libncurses5-dev qrencodechmod +x

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 114tTpMrJHJpNvkPZmz8KVcJoQjD5UtosdAddress: 114tTpMrJHJpNvkPZmz8KVcJoQjD5Utosd output: eb84dd62287a1d85e3f31b0de869534a8f800fad559e36f779a45470aa4e8976:0 output_height: 277978 value: 100000 spend: 3216bc4b8294532cddab1ae2a95a336ee841be02e6246c1ad9cf1e7db788d10e:0 spend_height: 277979Address: 114tTpMrJHJpNvkPZmz8KVcJoQjD5Utosd output: 5a45c86c5aff8200db4c7f8a91b9a3e51932510cbeb2dc173fc8611bee5aeaaf:1 output_height: 278076 value: 70000 spend: 4817f863ace4337be7ea95476b2c73723fb83fbe0e1a6236fbf30f2a8aa14dee:0 spend_height: 278076> sx fetch-transaction 516f0bfe2ed3703112434f645fdc7d805bba51c94c9d8f88b666f1c832eb423c010000000142f2e85e078a214d5c61b58276da5cec01311e026355c570b650c2e665585011010000008a47304402203aa40adefd0dc4a3f960b230a9e1b284d78a4b4dec9119368fdeb006af3b6c7b022071165df64ea4502003d8b6e9c46c28b5c5c748226737b4fe1ee8fc4269b50ee5014104a70f7c8b0a835f549f061b725bd3e06744963a07cb2f76097bafe040f939d6e6d23c6cc89e5b50aa944d26b7d1c8a1f3b8b4e6f7c2f54cf35fb46b0e4b9442e1ffffffff02a0860100000000001976a914ba55b9859c7356c5e5549c8a30c463e3db64e84488ac80054800000000001976a9145a35a4558b8a0140f4a73aaac0be891b99e3790e88ac00000000

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 priv15JRLqUG1FwSimZwSzNLPG1BKCENCRhDwkVveL59AEqt97bbkCD1> cat priv1 | sx pubkey04bfc8181cd833567e078cb03ec44034c226bf23dbb2482db53513e0fcea205c40bd6dc73db0c33296d8fa8e0bd347099e07787e17a2a40293004efdb512ff51e2> cat priv1 | sx addr1B772AGqphjSQqqeecdTBmnBdgMBPYDXt7

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.tx01000000013d706f0b970e2f6a5c996e964d0d40f8cf34cee20a804c68fc33aa2efa7191810000000000ffffffff01905f0100000000001976a9145600d581a94f65067a09103609e919e3c01141ed88ac00000000> sx rawscript dup hash160 [ `echo 1B772AGqphjSQqqeecdTBmnBdgMBPYDXt7 | sx decode-addr` ] equalverify checksig > raw.script> cat raw.script76a9146ed8c762b24ba024df09cb323ea525b06da3acb788ac> echo 5JRLqUG1FwSimZwSzNLPG1BKCENCRhDwkVveL59AEqt97bbkCD1 | sx sign-input txfile.tx 0 `cat raw.script` > sig> cat sig3044022069f05eacfe93fc6c028bd078228d7807af07c5ed7566491c709b181950d735830220788e089c63512c07239b94740a36de724b54c076192dbd27584b5b729986420d01> sx rawscript [ `cat sig` ] [ 04bfc8181cd833567e078cb03ec44034c226bf23dbb2482db53513e0fcea205c40bd6dc73db0c33296d8fa8e0bd347099e07787e17a2a40293004efdb512ff51e2 ] | sx set-input txfile.tx 0 > txfile2.tx> cat txfile2.tx01000000013d706f0b970e2f6a5c996e964d0d40f8cf34cee20a804c68fc33aa2efa719181000000008a473044022069f05eacfe93fc6c028bd078228d7807af07c5ed7566491c709b181950d735830220788e089c63512c07239b94740a36de724b54c076192dbd27584b5b729986420d014104bfc8181cd833567e078cb03ec44034c226bf23dbb2482db53513e0fcea205c40bd6dc73db0c33296d8fa8e0bd347099e07787e17a2a40293004efdb512ff51e2ffffffff01905f0100000000001976a9145600d581a94f65067a09103609e919e3c01141ed88ac00000000> sx broadcast-tx txfile2.tx

And you can also validate a transaction:

> sx validtx txfile2.txStatus: Validation of inputs failedUnconfirmed: 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 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 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 57c617d9b4e1f7af6ec97ca2ff57e94a28279a7eedd4d12a99fa11170e94f5a40420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9> pybtctool pubtoaddr 0420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e91CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6

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 57c617d9b4e1f7af6ec97ca2ff57e94a28279a7eedd4d12a99fa11170e94f5a401000000025e46552eb977f908fa8b3ee9d2943a8fa6d96c3b768a5f250ce485acd8c7f797000000008b483045022100dd29d89a28451febb990fb1dafa21245b105140083ced315ebcdea187572b3990220713f2e554f384d29d7abfedf39f0eb92afba0ef46f374e49d43a728a0ff6046e01410420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9ffffffff71d1abe4352100d4d837ca96c1a16947b5444f0f3e0bc645c430f704bb06c84c0100000000ffffffff01905f0100000000001976a9143ec6c3ed8dfc3ceabcc1cbdb0c5aef4e2d02873c88ac00000000

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" transactions that ordinary Bitcoin nodes reject; for example, multisignatures transactions between more than three parties can be sent through here.


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

Happy coding!