Bitcoin-ruby

This is a ruby library for interacting with the bitcoin protocol/network. It can parse and generate protocol messages, run basic scripts, connect to other peers and download and store the blockchain (WITHOUT verification yet!).

Installation

We assume you already have a ruby 1.9 compatible interpreter and rubygems environment.

git clone https://github.com/lian/bitcoin-ruby.git; cd bitcoin-ruby
ruby -Ilib bin/bitcoin_connect

Note that some aspects of the library (such as networking, or storage) may need additional dependencies which are not specified in the gemspec. You'll find out what's missing once it fails when you try to use it ;)

Demos

There are a few demo scripts you can run to try things out:

bin/bitcoin_connect

Connect to a network node and chat a little.

bin/bitcoin_blockchain

Connect to a node and download the whole blockchain into storage.

bin/bbe_verify_tx

Fetch a transaction and all its prev_outs from blockexplorer.com and verify the signatures.

./bin/bbe_verify_tx <tx_hash> [testnet]

bin/bitcoin_shell

Launches an irb session with bitcoin loaded where you can try stuff out.

Library Usage

There are different aspects to the library which can be used separately or in combination. Here are some examples of what you could do.

Keys / Addresses

Generate a key:

key = Bitcoin::generate_key
key #=> [<privkey>, <pubkey>]

Get the address from a public key

address = Bitcoin::pubkey_to_address(key[1])
address #=> <bitcoin address>

Check if an address is valid

Bitcoin::valid_address?(address) #=> true

Blocks / Transactions parsing

Parse a block

raw_block = File.open('spec/bitcoin/fixtures/rawblock-0.bin', 'rb') {|f| f.read}
blk = Bitcoin::Protocol::Block.new(raw_block)
blk.hash #=> 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
blk.tx.count #=> 1
blk.to_hash #=> ...
Bitcoin::Protocol::Block.from_json( blk.to_json )

Parse a transaction

raw_tx = File.open('spec/bitcoin/fixtures/rawtx-01.bin', 'rb') {|f| f.read}
tx = Bitcoin::Protocol::Tx.new(raw_tx)
tx.hash #=> 6e9dd16625b62cfcd4bf02edb89ca1f5a8c30c4b1601507090fb28e59f2d02b4
tx.in.size #=> 1
tx.out.size #=> 2
tx.to_hash #=> ...
Bitcoin::Protocol::Tx.from_json( tx.to_json )

Bitcoin::Script.new(tx.out[0].pk_script).to_string
#=> "OP_DUP OP_HASH160 b2e21c1db922e3bdc529de7b38b4c401399e9afd OP_EQUALVERIFY OP_CHECKSIG"

Transaction verification / Scripts

Get the matching transactions (in this example tx1 is the spending transaction)

rawtx1 = File.open("spec/bitcoin/fixtures/rawtx-f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16.bin", 'rb') {|f| f.read}
rawtx2 = File.open("spec/bitcoin/fixtures/rawtx-0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9.bin", 'rb') {|f| f.read}
tx1 = Bitcoin::Protocol::Tx.new(rawtx1)
tx2 = Bitcoin::Protocol::Tx.new(rawtx2)

Then simply ask the transaction to verify an input

tx1.verify_input_signature(0, tx2) #=> true

Or, if you want to control the script yourself

txin = tx1.in.first
txout = tx2.out[txin.prev_out_index]
script = Bitcoin::Script.new(txin.script_sig + txout.pk_script)

result = script.run do |pubkey, sig, hash_type|
  hash = tx1.signature_hash_for_input(0, nil, txout.pk_script)
  Bitcoin.verify_signature(hash, sig, pubkey.unpack("H*")[0])
end
result #=> true

Node / Network connections

The networking part is still work in progress. For now, you'll probably want to roll your own; see connection.rb or network/node.rb for examples.

Storage / Database backends

There are multiple database backends available, currently an in-memory dummy and and activerecord/postgres backend.

store = Bitcoin::Storage::Backends::Dummy.new
store.store_block(Bitcoin.network[:genesis_block])
store.get_block(Bitcoin.network[:genesis_hash])
store.get_head #=> Bitcoin.network[:genesis_hash]

Documentation

Still needs some love, but you can generate RDoc documentation

rake rdoc

The specs are also a good place to see how something works.

Specs

The specs can be run with

rake bacon

or, if you want to run a single spec

ruby spec/bitcoin/bitcoin_spec.rb

If you make changes to the code or add functionality, please also add specs.