Find your topic in the index, or refer to one of the examples below.
Bitcoin Data Structures | Utilities | Crypto |
---|---|---|
Constants | Base58 | HashFunctions |
Address | Core Extensions | Key |
↳ PublicKeyAddress | Data | Keychain |
↳ ScriptHashAddress | Diagnostics | OpenSSL |
↳ WIF | Hash↔ID Conversions | |
Block | ProofOfWork | |
BlockHeader | WireFormat | |
Network | ||
Opcode | ||
Script | ||
Signatures and Hash Types | ||
Transaction | ||
TransactionInput | ||
TransactionOutput | ||
TransactionBuilder |
Address is a compact identifier that represents a destination for a Bitcoin payment. To parse addresses use base class BTC::Address. To encode addresses use subclasses BTC::PublicKeyAddress and BTC::ScriptHashAddress.
Base58 encoding is used to encode Bitcoin addresses, private keys in WIF and extended keys for BIP32 keychains.
Blocks and Block Headers form a block chain that contains transactions.
BIP32 ("HD Wallets") is a standard for deriving series of keys or addresses from a single seed. Use BTC::Keychain class to decode extended public and private keys (“xpubs” and “xprvs”) and derive chains of keys.
Data is what we call a binary string. BTCRuby uses binary strings by default. Use methods defined in BTC::Data namespace to convert strings between hex and binary and access raw bytes in a safe manner.
Hash functions used in Bitcoin are accessible via BTC
namespace: BTC.hash256
, BTC.hash160
, BTC.sha256
and so on.
Input is a part of a bitcoin transaction that unlocks bitcoins stored in the outputs of the previous transactions. Every input contains a reference to some output (transaction hash and a numeric index of the output) and a signature script that typically contains signatures and other data to satisfy conditions defined by the corresponding output script.
Keys allow signing transactions and verifying existing signatures. Class BTC::Key encapsulates a pair of public and private keys (or only a public key) and provides methods to sign transactions and verify signatures.
Keychain is a chain of keys generated from a single seed (or extended key) by a mechanism defined in BIP32.
Opcode is a basic unit of a script. It could represent a piece of binary data (e.g. a signature) or an operation on data (e.g. signature verification). See BTC::Opcode class for a list of available opcodes and related conversion methods.
Output is a part of a bitcoin transaction that specifies destination of the bitcoins being transferred. Every output has an amount (in satoshis) and a script (that typically corresponds to an address).
P2PKH (pay-to-pubkey-hash) is a classic type of address that compresses a public key in a 20-byte hash value. P2PKH-addresses start with "1" on mainnet and "n" or "m" on testnet. Use BTC::PublicKeyAddress class to encode these addresses.
P2SH (pay-to-script-hash) is a type of address that represents an arbitrary script as a single 20-byte hash. P2SH-address starts with "3" on mainnet and "2N" or "2M" on testnet. Use BTC::ScriptHashAddress class to encode these addresses.
Script is a predicate consisting of opcodes that defines control over bitcoins in a transaction output or satisfies a predicate when unlocking (spending) bitcoins in a transaction input. To create and inspect scripts, use BTC::Script class.
Transaction (abbreviated "tx") is an object that represents transfer of bitcoins from one or more inputs to one or more outputs. Use BTC::Transaction class to inspect transactions or create them transactions manually. To build transaction we recommend using BTC::TransactionBuilder, which takes care of a lot of difficulties and exposes easy to use, yet powerful enough API.
Transaction ID (abbreviated "txid") is a reversed hex representation of transaction hash. To convert between IDs and hashes of transactions and blocks, use BTC.hash_from_id
and BTC.id_from_hash
methods.
Transaction Builder is a high-level API to build transactions. It selects unspent outputs, prepares correct signature scripts, computes mining fees and takes care of the change.
WIF (Wallet Import Format aka "sipa format") is used to encode a single private key in Base58check encoding.
Wire Format is a low-level binary format to encode network messages. Used to encode transactions and blocks. Higher-level objects expose data
method that takes care of this encoding, but if you need to compose or parse some custom messages, use BTC::WireFormat class.
This example demonstrates how to generate a key and get its address.
key = BTC::Key.random
puts key.to_wif # private key in WIF format
# => L4RqZhbn2VsVgy2wCWW8kUPpA4xEkH7WbfPtj1MdFug5MayHzLeT
puts key.address.to_s # public address
# => 1MFqAcAxNsAKj5e6yksZCCyfNukSdDGsEY
puts key.to_wif(network: BTC::Network.testnet)
# => cUnq2cbdTZZkrQWCavKG7ntsnJFeQjDCfhYMqRp8m2L5cL1yHDmc
puts key.address(network: BTC::Network.testnet).to_s
# => n1mnTfFwBtbaWC7ihKqw28BzEuM9YqxRyw
Transaction builder helps composing arbitrary transactions using just keys or unspent outputs. It takes care of computing a proper change amount, adding fees and signing inputs. It is also highly customizable, so you may use it for very complex transactions.
builder = BTC::TransactionBuilder.new
# 1. Provide a list of addresses to get unspent outputs from.
# If address is a WIF instance, it will be used to sign corresponding input
# If address is a public address (or P2SH), its input will remain unsigned.
builder.input_addresses = [ "L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy" ]
# 2. Use external API (e.g. Chain.com) to fetch unspent outputs for the input addresses.
# In this example we simply hard-code a single unspent output.
# Note: transaction ID and output index must be provided.
builder.unspent_outputs_provider_block = lambda do |addresses, outputs_amount, outputs_size, fee_rate|
txout = BTC::TransactionOutput.new(
value: 50_000,
script: BTC::PublicKeyAddress.parse("17XBj6iFEsf8kzDMGQk5ghZipxX49VXuaV").script,
transaction_id: "115e8f72f39fad874cfab0deed11a80f24f967a84079fb56ddf53ea02e308986",
index: 0
)
[ txout ]
end
# 3. Specify payment address and amount
builder.outputs = [ BTC::TransactionOutput.new(
value: 10_000,
script: BTC::Address.parse("17XBj6iFEsf8kzDMGQk5ghZipxX49VXuaV").script) ]
# 4. Specify the change address
builder.change_address = BTC::Address.parse("1CBtcGivXmHQ8ZqdPgeMfcpQNJrqTrSAcG")
# 5. Build the transaction and broadcast it.
result = builder.build
tx = result.transaction
puts tx.to_hex
# => 01000000018689302ea03ef5dd56fb7940a867f9240fa811eddeb0fa4c87ad9ff3728f5e11
# 000000006b483045022100e280f71106a84a4a1b1a2035eae70266eb53630beab2b59cc8cf
# f40b1a5bdbb902201dcbae9bb12730fe5563dc37e3a33e064f2efa78ba0af5c0179187aece
# 180b6c0121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b5
# 9fffffffff0210270000000000001976a91447862fe165e6121af80d5dde1ecb478ed17056
# 5b88ac30750000000000001976a9147ab89f9fae3f8043dcee5f7b5467a0f0a6e2f7e188ac
# 00000000
To manually create a transaction, you will need to specify raw inputs, compute the signature and compose a signature script for each input and take care of calculating fees and change.
include BTC
tx = Transaction.new
# 1. Add a raw input with previous transaction ID and output index.
tx.add_input(TransactionInput.new(
previous_id: "aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31",
previous_index: 0))
# 2. Add a raw output with a script
tx.add_output(TransactionOutput.new(
value: 100_000,
script: PublicKeyAddress.parse("1CBtcGivXmHQ8ZqdPgeMfcpQNJrqTrSAcG").script))
# 3. Get the private key from WIF
key = Key.new(wif: "L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy")
# 4. Sign the input (assuming it links to an output with address 18oxCAnbuKHDjP7KzLBDj8mLjggDBjE1Q9)
hashtype = BTC::SIGHASH_ALL
sighash = tx.signature_hash(input_index: 0,
output_script: Address.parse("18oxCAnbuKHDjP7KzLBDj8mLjggDBjE1Q9").script,
hash_type: hashtype)
tx.inputs[0].signature_script = Script.new << (key.ecdsa_signature(sighash) + WireFormat.encode_uint8(hashtype)) << key.public_key
# Get transaction data and broadcast it
puts tx.data # => raw binary data
puts tx.to_hex # hex-encoded data
# => 0100000001313eb630b128102b60241ca895f1d0ffca2170d5a0990e094f2182c102ab94aa
# 000000006a473044022039148258144202301221a305adb38ce0a182ecb4055c6015cdd735
# 8372d7ad6d022008aa259c87177f0e4e887dd0947c57fd140eb8f8a826f14ef8389dbc26ef
# a7b20121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59f
# ffffffff01a0860100000000001976a9147ab89f9fae3f8043dcee5f7b5467a0f0a6e2f7e1
# 88ac00000000
To create a P2SH multisig address you will need a set of public keys. In the example below we generate three random keys and compose 2-of-3 multisig script which is then transformed into a P2SH address. To redeem from this address you will need not only two signatures, but also the original multisig script.
keys = [BTC::Key.random, BTC::Key.random, BTC::Key.random]
pubkeys = keys.map(&:public_key)
multisig_script = BTC::Script.multisig(public_keys: pubkeys, signatures_required: 2)
puts multisig_script.to_s # => "OP_2 02c008dc... 03cab527... 024ac920... OP_3 OP_CHECKMULTISIG"
p2sh_script = multisig_script.p2sh_script
puts p2sh_script.to_s # => "OP_HASH160 a6bdcfcac410d1c1acbf34701da382ca34a691a3 OP_EQUAL"
address = p2sh_script.standard_address
puts address.to_s # => 3GtfUjaNBqG9wjw3CCgbxLUrbjtSDg4nDf