Sunday, September 21, 2014

Writing your first bitcoin-ruby program

Imagine you wrote down a WIF private bitcoin key, but because your handwriting was unclear or you wrote it in a hurry, it turns out one character was copied down wrong.

Here is the incorrect WIF: 5KL6HJfzZ4Uj4CJRFYT11z2W1t5kbULaDqHd7rn6ktLwT6sgyrY

You want to go through each character in the WIF string, replacing each single character in turn with one of the 58 valid characters for the WIF format, and check if it's a valid WIF key.

#!/usr/bin/env ruby
# First the required includes for bitcoin and openssl
require 'bitcoin'
require 'openssl'

# This function performs the correct checksum on a proposed WIF key
# to determine if it is a genuine WIF key
# See http://gobittest.appspot.com/PrivateKey (TP's Go Bitcoin Tests) for an explanation
def wif_valid?(hex)
hex = Bitcoin::base58_to_hex(hex)
hex1 = hex[0..-9]
hex1 = Bitcoin::checksum(hex1)
hex2 = hex.reverse[0..7].reverse
if hex1 == hex2
return true
end
return false
end

# This is our one character wrong WIF
badwif = "5KL6HJfzZ4Uj4CJRFYT11z2W1t5kbULaDqHd7rn6ktLwT6sgyrY"

# And this function takes a WIF, and loops through each character,
# changing it by one, and checking if it is now valid.
# It prints out any valid WIF it finds (there should only be one)
def one_alter(awif)
code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
newwif = ""
for i in 1..awif.length-1
for j in 0..code_string.length-1
newwif = awif
   # Next line is a  hack to ensure that newwif is a new string 
   # and not a pointer to the same string as awif
newwif = newwif + ""
newwif[i] = code_string[j]
if wif_valid?(newwif) == true
    # print out the newwif if it is a correct key
puts newwif
end
end
end
end

one_alter badwif

So lets see what happens when we run it:

bitcoin-ruby$ ruby programs/address.rb 

5KL6HJfzZ4Uj4CJRFYT11z2W1t5kbULaDqHd7rn6ktLwT5sgyrY

There you go - the one valid WIF address within one character of the bad one is retrieved. And it's corresponding public address is 1MUDdayQ7Af39bT9mA6zRYd7ehEeuqFzLZ . Note: no balance, and unlike to have one for long from now on, given that I've committed the cardinal sin of bitcoin, and published the private key.

Setting up a Ruby Bitcoin Machine, part 2

Now we are going to install Ruby 1.9.3 and bitcoin-ruby plus required libraries.

1. First Ruby: go to the Ubuntu Software Center, and type 'ruby' in the search box. Select and install the standard 1.9.3 Ruby package. This installs the basic Ruby environment.

2. You're going to need a few extras to get bitcoin-ruby to run.

$ sudo apt-get install ruby1.9.1-dev
$ sudo apt-get install build-essential g++
$ sudo gem install eventmachine
$ sudo apt-get install openssl
$ sudo apt-get install sqlite libsqlite3-dev
$ sudo gem install sqlite3
$ sudo gem install sequel
$ sudo gem install em-dns
$ sudo apt-get install git 

3. And now bitcoin-ruby itself:

$ sudo git clone https://github.com/lian/bitcoin-ruby.git; cd bitcoin-ruby
$ ruby bin/bitcoin_node

The last command should execute without any errors, which shows that the system is working. Stop it with Ctrl+C.

The final step is to load all the blockchain data into an sqlite3 database, with the following command:

$ ruby bin/bitcoin_node --storage sequel::sqlite://bitcoin.db --import ~/.bitcoin/blocks --skip-validation

This reads the bitcoin blockchain from your bitcoin client directory, and parses it before loading relevant information into a bitcoin.db database in your bitcoin-ruby directory.

If you get an error about opening the database like SQLite3::CantOpenException: unable to open database file (Sequel::DatabaseConnectionError) try running the previous command with sudo in front.

Once this has been running for a bit you can check, for example, that the balance.rb program works:

$ ruby examples/balance.rb 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX

This should return:

INFO  storage: opened sequel store sqlite://bitcoin.db
Balance: 50.00000000

It's the first address used in the first (genesis) block of the blockchain. As these coins can never be redeemed it will always have a non-zero balance.

Now that we've shown that it all works, it's time to install the Ruby gem for bitcoin-ruby so the various methods and objects can be called from anywhere:

$ sudo gem build bitcoin-ruby.gemspec && sudo gem install bitcoin-ruby-0.0.5.gem

Right, with that all working, you can start writing Ruby programs to do stuff with bitcoin.

Setting up a Ruby Bitcoin Machine, part 1

The next few posts are a record for myself, on how to install and set up a Linux machine to allow me to write programs that do bitcoin related things in Ruby, using the bitcoin-ruby system.

Step 1: Install Ubuntu 14.04 on a spare laptop. Make sure it's a 64 bit AMD machine, and that you install the right version. The required file can be obtained from http://www.ubuntu.com/download/desktop

It's free if you select the "No, take me to the download" link at the bottom right. An iso file called ubuntu-14.04.1-desktop-amd64.iso will appear in your download folder. Burn it to a DVD as an image.

Reboot the machine you want to install on, and boot from the DVD. Choose to install it, and don't select home folder encryption because it will slow down your programs.

Step 2: Boot up and get all the updates for Ubuntu (in the top left swirl icon, type updater and click on "Software Updater"). Then download the bootstrap.dat bitcoin blockchain by selecting the torrent bootstrap.dat.torrent from the page http://sourceforge.net/projects/bitcoin/files/Bitcoin/blockchain/

This is a multi-gigabyte file so the torrent downloaded will take a while.

In the meantime install the Bitcoin-qt client. Open a terminal (Ctrl+Alt+T) and type:

$ sudo apt-add-repository ppa:bitcoin/bitcoin
$ sudo apt-get update
$ sudo apt-get install bitcoin-qt

Click on the swirl icon and type bitcoin. The Bitcoin program with the orange logo should appear. Run it, but stop it after about 5 minutes.

When bootstrap.dat has downloaded copy it from the Downloads folder to the .bitcoin folder (you need to select Show Hidden Files from the View menu in the file explorer, or  user Ctrl+H).

Now you can run the Bitcoin client, and it will load the blocks off disk (this took about 4 hours for my laptop), and will then catch up with the remaining blocks from the network (another 16 hours or so). Now there is a complete copy of the blockchain in ~/.bitcoin/blocks/