Skip to content

Repository files navigation

This is a ruby library for interacting with the bitcoin protocol/network.

Some of the main features are:

  • Bitcoin::Key provides a high-level API for creating and handling keys/addresses

  • Bitcoin::Util provides the basic bitcoin utility functions for base58, ECC, etc.

  • Bitcoin::Protocol can parse/create all protocol messages

  • Bitcoin::Script implementation, create/run scripts and verify signatures

  • Bitcoin::Builder provides a high-level API for creating transactions (and blocks)

  • Bitcoin::Litecoin implements all the litecoin-specific differences

  • ruby 2.4.x

  • ruby 2.5.x

  • ruby 2.6.x

gem install bitcoin-ruby
# OR
git clone https://github.com/lian/bitcoin-ruby.git; cd bitcoin-ruby; bundle install

Note that some aspects of the library (such as networking, storage, etc.) need additional dependencies which are not specified in the gemspec. The core requirements are intentionally kept to a minimum, so nobody has to install unneeded dependencies.

  • rspec to run the specs

  • scrypt to use a much faster scrypt hash implementation for Litecoin

If you would like to install using Bundler, put it in your Gemfile and run bundle install

gem'bitcoin-ruby', git:'https://github.com/lian/bitcoin-ruby', branch:'master', require:'bitcoin'

There are different aspects to the library which can be used separately or in combination. Here are some ideas of what you could do. There are also some demo scripts in examples/, see EXAMPLES.

Generate a Bitcoin::Key

key = Bitcoin::Key.generatekey.privkey.pubkey.addrsig = key.sign("data")
key.verify("data", sig)
recovered_key = Bitcoin::Key.from_base58(key.to_base58)

Parse a Bitcoin::Protocol::Block

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

Parse a Bitcoin::Protocol::Tx

raw_tx = File.open('spec/bitcoin/fixtures/rawtx-01.bin', 'rb') {|f|f.read}
tx = Bitcoin::Protocol::Tx.new(raw_tx)
tx.hash#=> 6e9dd16625b62cfcd4bf02edb89ca1f5a8c30c4b1601507090fb28e59f2d02b4tx.in.size#=> 1tx.out.size#=> 2tx.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"

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

If you want to control the Bitcoin::Script yourself, you can do so

txin = tx1.in.firsttxout = tx2.out[txin.prev_out_index]
script = Bitcoin::Script.new(txin.script_sig+txout.pk_script)
result = script.rundo|pubkey, sig, hash_type|hash = tx1.signature_hash_for_input(0, nil, txout.pk_script)
Bitcoin.verify_signature(hash, sig, pubkey.unpack("H*")[0])
endresult#=> true

You need to know the previous output you want to spend (tx hash and output index), as well as the private key for the address required to sign for it.

# use testnet so you don't accidentally blow your whole money!Bitcoin.network = :testnet3# make the DSL methods available in your scopeincludeBitcoin::Builder# the previous transaction that has an output to your addressprev_hash = "6c44b284c20fa22bd69c57a9dbff91fb71deddc8c54fb2f5aa41fc78c96c1ad1"# the number of the output you want to useprev_out_index = 0# fetch the tx from whereever you like and parse itprev_tx = Bitcoin::P::Tx.from_json(open("http://test.webbtc.com/tx/#{prev_hash}.json"))
# the key needed to sign an input that spends the previous outputkey = Bitcoin::Key.from_base58("92ZRu28m2GHSKaaF2W7RswJ2iJYpTzVhBaN6ZLs7TENCs4b7ML8")
# create a new transaction (and sign the inputs)new_tx = build_txdo|t|# add the input you picked out earliert.inputdo|i|i.prev_outprev_txi.prev_out_indexprev_out_indexi.signature_keykeyend# add an output that sends some bitcoins to another addresst.outputdo|o|o.value50000000# 0.5 BTC in satoshiso.script {|s|s.recipient"mugwYJ1sKyr8EDDgXtoh8sdDQuNWKYNf88" }
end# add another output spending the remaining amount back to yourself# if you want to pay a tx fee, reduce the value of this output accordingly# if you want to keep your financial history private, use a different addresst.outputdo|o|o.value49000000# 0.49 BTC, leave 0.01 BTC as feeo.script {|s|s.recipientkey.addr }
endend# examine your transaction. you can relay it through http://test.webbtc.com/relay_tx# that will also give you a hint on the error if something goes wrongputsnew_tx.to_json

Always trying to improve, any help appreciated! If anything is unclear to you, let us know!

Documentation is generated using yardoc:

rakedoc

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

Specs require libsecp256k1 in order to be fully run. Therefore, the first step in running the specs is to build this library if you haven’t already:

rakebuild_libsecp256k1

The majority of specs can be run with

rakerspec

or, if you want to run a single spec

bundleexecrspecspec/bitcoin/bitcoin_spec.rb

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

To run specs for changes that monkey patch significant functionality, you should run the specs individually. For example, to run the Dogecoin specs:

rakecoin_spec[dogecoin]

If support is added for any new coins a corresponding coin spec should also be added to test specific functionality of that coin.

Any help or feedback is greatly appreciated! From getting knee-deep into elliptic-curve acrobatics, to cleaning up high-level naming conventions, there is something for everyone to do. Even if you are completely lost, just pointing out what is unclear helps a lot!

If you are curious or like to participate in development, drop by #bitcoin-ruby on irc.freenode.net!

Available here: [COPYING]

About

bitcoin utils and protocol in ruby.

Resources

Stars

921 stars

Watchers

80 watching

Forks

Releases

Packages

Used by

Contributors

Languages