bitcoin-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +12 -0
- data/COPYING +18 -0
- data/Gemfile +4 -0
- data/README.rdoc +189 -0
- data/Rakefile +104 -0
- data/bin/bitcoin_dns_seed +130 -0
- data/bin/bitcoin_gui +80 -0
- data/bin/bitcoin_node +174 -0
- data/bin/bitcoin_shell +12 -0
- data/bin/bitcoin_wallet +323 -0
- data/bitcoin-ruby.gemspec +27 -0
- data/concept-examples/blockchain-pow.rb +151 -0
- data/doc/CONFIG.rdoc +66 -0
- data/doc/EXAMPLES.rdoc +9 -0
- data/doc/NODE.rdoc +35 -0
- data/doc/STORAGE.rdoc +21 -0
- data/doc/WALLET.rdoc +102 -0
- data/examples/balance.rb +60 -0
- data/examples/bbe_verify_tx.rb +55 -0
- data/examples/connect.rb +36 -0
- data/examples/relay_tx.rb +22 -0
- data/examples/verify_tx.rb +57 -0
- data/lib/bitcoin.rb +370 -0
- data/lib/bitcoin/builder.rb +266 -0
- data/lib/bitcoin/config.rb +56 -0
- data/lib/bitcoin/connection.rb +126 -0
- data/lib/bitcoin/ffi/openssl.rb +121 -0
- data/lib/bitcoin/gui/addr_view.rb +42 -0
- data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
- data/lib/bitcoin/gui/bitcoin-ruby.svg +80 -0
- data/lib/bitcoin/gui/conn_view.rb +36 -0
- data/lib/bitcoin/gui/connection.rb +68 -0
- data/lib/bitcoin/gui/em_gtk.rb +28 -0
- data/lib/bitcoin/gui/gui.builder +1643 -0
- data/lib/bitcoin/gui/gui.rb +290 -0
- data/lib/bitcoin/gui/helpers.rb +113 -0
- data/lib/bitcoin/gui/tree_view.rb +82 -0
- data/lib/bitcoin/gui/tx_view.rb +67 -0
- data/lib/bitcoin/key.rb +125 -0
- data/lib/bitcoin/logger.rb +65 -0
- data/lib/bitcoin/network/command_client.rb +93 -0
- data/lib/bitcoin/network/command_handler.rb +179 -0
- data/lib/bitcoin/network/connection_handler.rb +274 -0
- data/lib/bitcoin/network/node.rb +399 -0
- data/lib/bitcoin/protocol.rb +140 -0
- data/lib/bitcoin/protocol/address.rb +48 -0
- data/lib/bitcoin/protocol/alert.rb +47 -0
- data/lib/bitcoin/protocol/block.rb +154 -0
- data/lib/bitcoin/protocol/handler.rb +38 -0
- data/lib/bitcoin/protocol/parser.rb +148 -0
- data/lib/bitcoin/protocol/tx.rb +205 -0
- data/lib/bitcoin/protocol/txin.rb +97 -0
- data/lib/bitcoin/protocol/txout.rb +73 -0
- data/lib/bitcoin/protocol/version.rb +70 -0
- data/lib/bitcoin/script.rb +634 -0
- data/lib/bitcoin/storage/dummy.rb +164 -0
- data/lib/bitcoin/storage/models.rb +133 -0
- data/lib/bitcoin/storage/sequel.rb +335 -0
- data/lib/bitcoin/storage/sequel_store/sequel_migrations.rb +84 -0
- data/lib/bitcoin/storage/storage.rb +243 -0
- data/lib/bitcoin/version.rb +3 -0
- data/lib/bitcoin/wallet/coinselector.rb +30 -0
- data/lib/bitcoin/wallet/keygenerator.rb +75 -0
- data/lib/bitcoin/wallet/keystore.rb +203 -0
- data/lib/bitcoin/wallet/txdp.rb +116 -0
- data/lib/bitcoin/wallet/wallet.rb +243 -0
- data/spec/bitcoin/bitcoin_spec.rb +472 -0
- data/spec/bitcoin/builder_spec.rb +90 -0
- data/spec/bitcoin/fixtures/0d0affb5964abe804ffe85e53f1dbb9f29e406aa3046e2db04fba240e63c7fdd.json +27 -0
- data/spec/bitcoin/fixtures/23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63.json +23 -0
- data/spec/bitcoin/fixtures/477fff140b363ec2cc51f3a65c0c58eda38f4d41f04a295bbd62babf25e4c590.json +27 -0
- data/spec/bitcoin/fixtures/60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1.json +45 -0
- data/spec/bitcoin/fixtures/bc179baab547b7d7c1d5d8d6f8b0cc6318eaa4b0dd0a093ad6ac7f5a1cb6b3ba.json +34 -0
- data/spec/bitcoin/fixtures/rawblock-0.bin +0 -0
- data/spec/bitcoin/fixtures/rawblock-0.json +39 -0
- data/spec/bitcoin/fixtures/rawblock-1.bin +0 -0
- data/spec/bitcoin/fixtures/rawblock-1.json +39 -0
- data/spec/bitcoin/fixtures/rawblock-131025.bin +0 -0
- data/spec/bitcoin/fixtures/rawblock-131025.json +5063 -0
- data/spec/bitcoin/fixtures/rawblock-170.bin +0 -0
- data/spec/bitcoin/fixtures/rawblock-170.json +68 -0
- data/spec/bitcoin/fixtures/rawblock-9.bin +0 -0
- data/spec/bitcoin/fixtures/rawblock-9.json +39 -0
- data/spec/bitcoin/fixtures/rawblock-testnet-26478.bin +0 -0
- data/spec/bitcoin/fixtures/rawblock-testnet-26478.json +64 -0
- data/spec/bitcoin/fixtures/rawtx-01.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-01.json +27 -0
- data/spec/bitcoin/fixtures/rawtx-02.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-02.json +27 -0
- data/spec/bitcoin/fixtures/rawtx-03.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-03.json +48 -0
- data/spec/bitcoin/fixtures/rawtx-04.json +27 -0
- data/spec/bitcoin/fixtures/rawtx-0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-05.json +23 -0
- data/spec/bitcoin/fixtures/rawtx-14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.json +27 -0
- data/spec/bitcoin/fixtures/rawtx-406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602.json +23 -0
- data/spec/bitcoin/fixtures/rawtx-52250a162c7d03d2e1fbc5ebd1801a88612463314b55102171c5b5d817d2d7b2.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-ba1ff5cd66713133c062a871a8adab92416f1e38d17786b2bf56ac5f6ffdfdf5.json +37 -0
- data/spec/bitcoin/fixtures/rawtx-c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73.json +24 -0
- data/spec/bitcoin/fixtures/rawtx-de35d060663750b3975b7997bde7fb76307cec5b270d12fcd9c4ad98b279c28c.json +23 -0
- data/spec/bitcoin/fixtures/rawtx-f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-a220adf1902c46a39db25a24bc4178b6a88440f977a7e2cabfdd8b5c1dd35cfb.json +27 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.json +41 -0
- data/spec/bitcoin/fixtures/reorg/blk_0_to_4.dat +0 -0
- data/spec/bitcoin/fixtures/reorg/blk_3A.dat +0 -0
- data/spec/bitcoin/fixtures/reorg/blk_4A.dat +0 -0
- data/spec/bitcoin/fixtures/reorg/blk_5A.dat +0 -0
- data/spec/bitcoin/fixtures/testnet/block_0.bin +0 -0
- data/spec/bitcoin/fixtures/testnet/block_1.bin +0 -0
- data/spec/bitcoin/fixtures/testnet/block_2.bin +0 -0
- data/spec/bitcoin/fixtures/testnet/block_3.bin +0 -0
- data/spec/bitcoin/fixtures/testnet/block_4.bin +0 -0
- data/spec/bitcoin/fixtures/testnet/block_5.bin +0 -0
- data/spec/bitcoin/fixtures/txdp-1.txt +32 -0
- data/spec/bitcoin/fixtures/txdp-2-signed.txt +19 -0
- data/spec/bitcoin/fixtures/txdp-2-unsigned.txt +14 -0
- data/spec/bitcoin/key_spec.rb +123 -0
- data/spec/bitcoin/network_spec.rb +48 -0
- data/spec/bitcoin/protocol/addr_spec.rb +68 -0
- data/spec/bitcoin/protocol/alert_spec.rb +20 -0
- data/spec/bitcoin/protocol/block_spec.rb +101 -0
- data/spec/bitcoin/protocol/inv_spec.rb +124 -0
- data/spec/bitcoin/protocol/ping_spec.rb +49 -0
- data/spec/bitcoin/protocol/tx_spec.rb +226 -0
- data/spec/bitcoin/protocol/version_spec.rb +77 -0
- data/spec/bitcoin/reorg_spec.rb +129 -0
- data/spec/bitcoin/script/opcodes_spec.rb +417 -0
- data/spec/bitcoin/script/script_spec.rb +246 -0
- data/spec/bitcoin/spec_helper.rb +36 -0
- data/spec/bitcoin/storage_spec.rb +229 -0
- data/spec/bitcoin/wallet/coinselector_spec.rb +35 -0
- data/spec/bitcoin/wallet/keygenerator_spec.rb +64 -0
- data/spec/bitcoin/wallet/keystore_spec.rb +188 -0
- data/spec/bitcoin/wallet/txdp_spec.rb +74 -0
- data/spec/bitcoin/wallet/wallet_spec.rb +207 -0
- metadata +295 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bitcoin/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "bitcoin-ruby"
|
7
|
+
s.version = Bitcoin::VERSION
|
8
|
+
s.authors = ["lian"]
|
9
|
+
s.email = ["meta.rb@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Gem for working with Bitcoin network}
|
12
|
+
s.description = %q{Gem for working with Bitcoin network}
|
13
|
+
|
14
|
+
s.rubyforge_project = "bitcoin-ruby"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.required_rubygems_version = ">= 1.3.6"
|
22
|
+
s.add_dependency "rake", ">= 0.8.0"
|
23
|
+
s.add_dependency "eventmachine"
|
24
|
+
|
25
|
+
s.add_development_dependency "bacon"
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
#
|
2
|
+
# Ruby Example of the 'proof of work' explanation
|
3
|
+
# from https://en.bitcoin.it/wiki/Proof_of_work
|
4
|
+
#
|
5
|
+
# note: block data passed to do_work is simplified.
|
6
|
+
# bitcoin blockchain is more complex too.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'digest/sha2'
|
10
|
+
|
11
|
+
|
12
|
+
def do_work(data, target, nonce=0)
|
13
|
+
found = nil
|
14
|
+
while !found
|
15
|
+
d = data + [nonce].pack("I")
|
16
|
+
h = Digest::SHA256.hexdigest( Digest::SHA256.digest( d ) ).to_i(16)
|
17
|
+
|
18
|
+
if h <= target
|
19
|
+
found = [h.to_s(16).rjust(64, '0'), nonce]
|
20
|
+
break
|
21
|
+
end
|
22
|
+
|
23
|
+
nonce+=1
|
24
|
+
end
|
25
|
+
found
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def next_block(blocks, target, data)
|
30
|
+
block_id = blocks.size
|
31
|
+
last_block = last_hash(blocks)
|
32
|
+
data = last_block + " " + data
|
33
|
+
|
34
|
+
hash, nonce = nil, nil
|
35
|
+
|
36
|
+
work_time = t{ hash, nonce = do_work(data, target.to_i(16)) }
|
37
|
+
verify_time = t{ hash, nonce = do_work(data, target.to_i(16), nonce) }
|
38
|
+
|
39
|
+
print_block( block_id, target, data, nonce, hash, work_time, verify_time )
|
40
|
+
|
41
|
+
[ hash, nonce, target, data, work_time, verify_time ]
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
def print_block(*args)
|
47
|
+
puts <<-TEXT % args
|
48
|
+
-------------------- block %s
|
49
|
+
target: %s
|
50
|
+
data: '%s' + %s (nonce)
|
51
|
+
found: %s
|
52
|
+
|
53
|
+
time:
|
54
|
+
took: %f
|
55
|
+
verify: %f
|
56
|
+
|
57
|
+
TEXT
|
58
|
+
end
|
59
|
+
|
60
|
+
def last_hash(blocks)
|
61
|
+
if blocks.empty?
|
62
|
+
"0000000000000000000000000000000000000000000000000000000000000000"
|
63
|
+
else
|
64
|
+
blocks.last[0]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def t; x = Time.now; yield; Time.now - x; end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
if $0 == __FILE__
|
73
|
+
|
74
|
+
target = "00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
75
|
+
blocks = []
|
76
|
+
|
77
|
+
|
78
|
+
blocks << next_block( blocks, target, "hello ruby" )
|
79
|
+
blocks << next_block( blocks, target, "this is" )
|
80
|
+
blocks << next_block( blocks, target, "a blockchain" )
|
81
|
+
blocks << next_block( blocks, target, "and proof-of-work" )
|
82
|
+
blocks << next_block( blocks, target, "example!" )
|
83
|
+
|
84
|
+
|
85
|
+
puts <<-TEXT % [ blocks.size, target, blocks.inject(0){|e,i| e+=i[-2] }, blocks.inject(0){|e,i| e+=i[-1] } ]
|
86
|
+
-------------------- blockchain time summary
|
87
|
+
chain length: %d
|
88
|
+
difficulty: %s
|
89
|
+
total work time: %f
|
90
|
+
total verify time: %f
|
91
|
+
|
92
|
+
TEXT
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
__END__
|
98
|
+
% ruby concept-examples/blockchain-pow.rb
|
99
|
+
|
100
|
+
-------------------- block 0
|
101
|
+
target: 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
102
|
+
data: '0000000000000000000000000000000000000000000000000000000000000000 hello ruby' + 1373297 (nonce)
|
103
|
+
found: 00000b1522d81f532d5e33c4fd22537b66f1ff052315b47000e61496510ceaa2
|
104
|
+
|
105
|
+
time:
|
106
|
+
took: 41.073509
|
107
|
+
verify: 0.000060
|
108
|
+
|
109
|
+
-------------------- block 1
|
110
|
+
target: 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
111
|
+
data: '00000b1522d81f532d5e33c4fd22537b66f1ff052315b47000e61496510ceaa2 this is' + 2877742 (nonce)
|
112
|
+
found: 0000006f3ac527d921b57a88d3d6e5793f0813d4fafb17e0b31456ad1d652e05
|
113
|
+
|
114
|
+
time:
|
115
|
+
took: 86.098830
|
116
|
+
verify: 0.000058
|
117
|
+
|
118
|
+
-------------------- block 2
|
119
|
+
target: 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
120
|
+
data: '0000006f3ac527d921b57a88d3d6e5793f0813d4fafb17e0b31456ad1d652e05 a blockchain' + 255946 (nonce)
|
121
|
+
found: 000000196f5e67ca66f281cf6b884b312984173651ddf12e151db6b1428a882b
|
122
|
+
|
123
|
+
time:
|
124
|
+
took: 7.648288
|
125
|
+
verify: 0.000057
|
126
|
+
|
127
|
+
-------------------- block 3
|
128
|
+
target: 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
129
|
+
data: '000000196f5e67ca66f281cf6b884b312984173651ddf12e151db6b1428a882b and proof-of-work' + 2930300 (nonce)
|
130
|
+
found: 00000a197372b28e93479598afa504c92bcb50af2c5c6893686e91ce47ad0747
|
131
|
+
|
132
|
+
time:
|
133
|
+
took: 87.530473
|
134
|
+
verify: 0.000058
|
135
|
+
|
136
|
+
-------------------- block 4
|
137
|
+
target: 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
138
|
+
data: '00000a197372b28e93479598afa504c92bcb50af2c5c6893686e91ce47ad0747 example!' + 85074 (nonce)
|
139
|
+
found: 00000a406be803d6a02c5aded00c159b664fe11ed768dbcb3ecb7b2ec6257706
|
140
|
+
|
141
|
+
time:
|
142
|
+
took: 2.555810
|
143
|
+
verify: 0.000058
|
144
|
+
|
145
|
+
-------------------- blockchain time summary
|
146
|
+
chain length: 5
|
147
|
+
difficulty: 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
148
|
+
total work time: 224.906909
|
149
|
+
total verify time: 0.000292
|
150
|
+
|
151
|
+
|
data/doc/CONFIG.rdoc
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
= Config
|
2
|
+
|
3
|
+
All commands accept configuration, either via config file, or at the command line.
|
4
|
+
|
5
|
+
== Locations
|
6
|
+
|
7
|
+
There are 3 default locations where configfiles are loaded from:
|
8
|
+
|
9
|
+
* +/etc/bitcoin-ruby.yml+
|
10
|
+
* +~/.bitcoin-ruby.yml+
|
11
|
+
* +./bitcoin-ruby.yml+
|
12
|
+
|
13
|
+
Files are loaded in order (if they exist) and override each others settings.
|
14
|
+
|
15
|
+
To specify a different config file use the +--config+ option.
|
16
|
+
|
17
|
+
== Files
|
18
|
+
|
19
|
+
Inside a config file, you can put options for the different commands, separated
|
20
|
+
into categories.
|
21
|
+
|
22
|
+
all:
|
23
|
+
network: bitcoin
|
24
|
+
storage: sequel::postgres:/bitcoin
|
25
|
+
command: 127.0.0.1:1234
|
26
|
+
blockchain:
|
27
|
+
max:
|
28
|
+
connect: 30
|
29
|
+
wallet:
|
30
|
+
keystore: "simple::file=keys.json"
|
31
|
+
|
32
|
+
Options in the +all+ category are loaded by every command, and are loaded first
|
33
|
+
(so command-specific options will override them).
|
34
|
+
|
35
|
+
Other categories are loaded by the corresponding command and may override options
|
36
|
+
from the +all+ category (ie. +bitcoin_wallet+ loads +all+ and +wallet+).
|
37
|
+
|
38
|
+
== Default Values
|
39
|
+
|
40
|
+
all:
|
41
|
+
network: bitcoin # network identifier ("bitcoin" or "testnet")
|
42
|
+
command: "127.0.0.1:9999" # IP:Port to listen for incomming command connections
|
43
|
+
listen: "0.0.0.0:8332" # IP:Port to listen for incoming peer connections
|
44
|
+
connect: "" # List of IP:Port,IP:Port of nodes to connect to
|
45
|
+
storage: "sequel::sqlite://bitcoin.db" # storage backend to use (see STORAGE)
|
46
|
+
node:
|
47
|
+
headers_only: false # download/store only block headers (experimental)
|
48
|
+
dns: true # query peers from dns server
|
49
|
+
epoll: false
|
50
|
+
epoll_limit: 10000
|
51
|
+
epoll_user: nil
|
52
|
+
log: # log levels (debug, info, warn, error, fatal)
|
53
|
+
network: info
|
54
|
+
storage: info
|
55
|
+
max:
|
56
|
+
connections: 32 # number of peer connections
|
57
|
+
addr: 1024 # peer-address store size
|
58
|
+
queue: 500 # storage-queue size
|
59
|
+
inv: 500 # inventory-queue size
|
60
|
+
intervals:
|
61
|
+
queue: 5 # work storage queue
|
62
|
+
inv_queue: 5 # work inventory queue
|
63
|
+
addrs: 15 # collect new peer addrs
|
64
|
+
connect: 30 # connect to new peers
|
65
|
+
wallet:
|
66
|
+
keystore: "simple::file=~/.bitcoin-ruby/keys.json" # keystore to use
|
data/doc/EXAMPLES.rdoc
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
= Examples
|
2
|
+
|
3
|
+
There are a few demo scripts in `examples/` that might give you an idea where to start.
|
4
|
+
|
5
|
+
examples/connect.rb:: Connect to a network node and chat a little.
|
6
|
+
examples/verify_tx.rb:: Fetch a transaction from local storage and verify signatures.
|
7
|
+
examples/bbe_verify_tx.rb:: Fetch transaction from blockexplorer.com and verify signatures.
|
8
|
+
examples/balance.rb:: Display balance/transactions for given address.
|
9
|
+
examples/relay_tx.rb:: Relay transaction to the network.
|
data/doc/NODE.rdoc
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
= NODE
|
2
|
+
|
3
|
+
Bitcoin Node. Connects to the network and downloads the blockchain into local storage.
|
4
|
+
|
5
|
+
== Usage
|
6
|
+
|
7
|
+
To run the node with the default options (download the blockchain into ./bitcoin.db
|
8
|
+
using the sequel::sqlite3 STORAGE backend):
|
9
|
+
|
10
|
+
bitcoin_node
|
11
|
+
|
12
|
+
You can specify options (see +--help+) or pass a config file with +--config+ (see CONFIG).
|
13
|
+
|
14
|
+
Some common options you might want to change:
|
15
|
+
|
16
|
+
<tt>-n --network</tt> <i><name></i>::
|
17
|
+
+bitcoin+ or +testnet+ network
|
18
|
+
<tt>--connect</tt> <i><ip:port></i>::
|
19
|
+
list of peers to connect to
|
20
|
+
<tt>-s --storage</tt> <i><backend-string></i>::
|
21
|
+
storage backend to use (see STORAGE)
|
22
|
+
|
23
|
+
It will take some time to download/store the entire blockchain at first, so be patient ;)
|
24
|
+
|
25
|
+
|
26
|
+
== Command client
|
27
|
+
|
28
|
+
The node opens a separate command socket which you can connect to and query statistics
|
29
|
+
or get notified about new blocks/tx, etc.
|
30
|
+
|
31
|
+
bitcoin_node info # general statistics
|
32
|
+
|
33
|
+
bitcoin_node help # list all commands
|
34
|
+
|
35
|
+
bitcoin_node monitor block # wait for new blocks and output their hashes
|
data/doc/STORAGE.rdoc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
= Storage
|
2
|
+
|
3
|
+
There is support for different storage backends, currently the `sequel` backend is the most stable and should work with `sqlite` and `postgres` databases. see Bitcoin::Storage
|
4
|
+
|
5
|
+
== Backends
|
6
|
+
|
7
|
+
For examples that require storage backends, you can specify them using
|
8
|
+
a string containing the backend name and a configuration string.
|
9
|
+
The default backend is +sequel::sqlite://bitcoin.db+ which is a sqlite database
|
10
|
+
called +bitcoin.db+ in the current directory
|
11
|
+
|
12
|
+
sequel::sqlite:/ # in-memory
|
13
|
+
sequel::sqlite://bitcoin.db
|
14
|
+
sequel::sqlite:///tmp/bitcoin.db
|
15
|
+
sequel::postgres:/bitcoin
|
16
|
+
sequel::postgres://<user>:<pass>@<host>:<port>/<database>
|
17
|
+
|
18
|
+
== Custom Backends
|
19
|
+
|
20
|
+
To implement a custom backend you need to inherit from Bitcoin::Storage::Backends::StoreBase
|
21
|
+
and implement the methods defined there.
|
data/doc/WALLET.rdoc
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
= WALLET
|
2
|
+
|
3
|
+
The wallet stores your keys/addresses, knows which transactions belong to them,
|
4
|
+
can create transactions, etc.
|
5
|
+
|
6
|
+
== Keystores
|
7
|
+
|
8
|
+
A keystore is responsible for storing/accessing your keys/addresses.
|
9
|
+
|
10
|
+
The +simple+ keystore (Bitcoin::Wallet::SimpleKeyStore) will create one key
|
11
|
+
and put it into the given file. You can later ask it to generate more keys
|
12
|
+
or add labels to the keys.
|
13
|
+
|
14
|
+
The +deterministic+ keystore (Bitcoin::Wallet::KeyGenerator) uses the seed
|
15
|
+
(which should be a large, unique, random string!) and generates the given number
|
16
|
+
of keys. The nonce is optional, it just speeds up finding the first key.
|
17
|
+
Note: Currently this keystore is not usable because it doesn't support labels yet.
|
18
|
+
|
19
|
+
|
20
|
+
== Config
|
21
|
+
|
22
|
+
To use the wallet you should create a configfile. It's not required but more convenient.
|
23
|
+
See CONFIG for details.
|
24
|
+
|
25
|
+
wallet:
|
26
|
+
keystore: "simple::file=keys.json"
|
27
|
+
# keystore: "deterministic::seed=foo,nonce=2116,keys=7"
|
28
|
+
|
29
|
+
|
30
|
+
== Usage
|
31
|
+
|
32
|
+
Then you can list all addresses in the wallet:
|
33
|
+
|
34
|
+
bitcoin_wallet list
|
35
|
+
|
36
|
+
Display transaction history for a specific address:
|
37
|
+
|
38
|
+
bitcoin_wallet list <address>
|
39
|
+
|
40
|
+
Create new keys/addresses:
|
41
|
+
|
42
|
+
bitcoin_wallet new
|
43
|
+
|
44
|
+
Import keys from base58 format:
|
45
|
+
|
46
|
+
bitcoin_wallet import <base58>
|
47
|
+
|
48
|
+
Export keys to base58 format:
|
49
|
+
|
50
|
+
bitcoin_wallet export <address>
|
51
|
+
|
52
|
+
== Transactions
|
53
|
+
|
54
|
+
Transactions consist of multiple inputs and outputs. Inputs are selected
|
55
|
+
automatically, and you can define outputs of different types.
|
56
|
+
Each output has a +value+ (specified in base units/"satoshis"), and script represented by
|
57
|
+
the script type (see below) and one or more recipients (addresses or public keys).
|
58
|
+
|
59
|
+
Outputs can be specified as a combination of type, recipient(s) and value.
|
60
|
+
|
61
|
+
bitcoin_wallet send <type>:<recipients>:<value> [<fee>]
|
62
|
+
|
63
|
+
This will create and sign a transaction and display it, asking for confirmation.
|
64
|
+
If you accept, it will be sent to your node and relayed to the rest of the network.
|
65
|
+
|
66
|
+
|
67
|
+
There are different script types:
|
68
|
+
|
69
|
+
|
70
|
+
=== Address
|
71
|
+
|
72
|
+
Specify address/hash160 of the public key needed to spend the output again.
|
73
|
+
This is the most commonly used transaction type at the moment.
|
74
|
+
|
75
|
+
bitcoin_wallet send address:1GQkkFvAFW2ts3YLnEvMnu76WyCB6yDb4d:0.1 0.005
|
76
|
+
|
77
|
+
|
78
|
+
=== Pubkey
|
79
|
+
|
80
|
+
Specify public key needed to spend the output.
|
81
|
+
Somewhat deprecated (because of the higher long-term storage requirements compared
|
82
|
+
to address-transactions).
|
83
|
+
|
84
|
+
bitcoin_wallet send pubkey:<pubkey in hex>:1.0 0.005
|
85
|
+
|
86
|
+
|
87
|
+
=== Multisig
|
88
|
+
|
89
|
+
Specify multiple addresses needed to spend the output.
|
90
|
+
|
91
|
+
bitcoin_wallet send <type>:<m>:<key>:<key>:<amount> [<fee>]
|
92
|
+
bitcoin_wallet send multisig:1:1GQkkFvAFW2ts3YLnEvMnu76WyCB6yDb4d:1C5uWeXorS46ZubciCLN4zyR7sAqeNJfLD:1.0 0.005
|
93
|
+
|
94
|
+
You can give up to 3 addresses/keys and +m+ specifies how many of them are required to spend
|
95
|
+
the output.
|
96
|
+
|
97
|
+
Note: Currently you need to have all keys in the same wallet for this to work.
|
98
|
+
|
99
|
+
|
100
|
+
=== P2SH
|
101
|
+
|
102
|
+
# TODO
|
data/examples/balance.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Collect all unspent outputs for given address and display balance.
|
4
|
+
# Optionally display list of transactions.
|
5
|
+
#
|
6
|
+
# examples/balance.rb <address> [--list]
|
7
|
+
# examples/balance.rb 1Q2TWHE3GMdB6BZKafqwxXtWAWgFt5Jvm3
|
8
|
+
|
9
|
+
$:.unshift( File.expand_path("../../lib", __FILE__) )
|
10
|
+
require 'bitcoin'
|
11
|
+
|
12
|
+
Bitcoin.network = :bitcoin
|
13
|
+
store = Bitcoin::Storage.sequel(:db => "sqlite://bitcoin.db")
|
14
|
+
|
15
|
+
address = ARGV.shift
|
16
|
+
|
17
|
+
unless Bitcoin.valid_address?(address)
|
18
|
+
puts "Address #{address} is invalid."
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# format value to be displayed
|
24
|
+
def str_val(val, pre = "")
|
25
|
+
("#{pre}#{"%.8f" % (val / 1e8)}").rjust(20)
|
26
|
+
end
|
27
|
+
|
28
|
+
if ARGV[0] == "--list"
|
29
|
+
txouts = store.get_txouts_for_address(address)
|
30
|
+
unless txouts.any?
|
31
|
+
puts "Address not seen."
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
total = 0
|
36
|
+
txouts.each do |txout|
|
37
|
+
tx = txout.get_tx
|
38
|
+
total += txout.value
|
39
|
+
puts "#{tx.hash} |#{str_val(txout.value, '+ ')} |=> #{str_val(total)}"
|
40
|
+
|
41
|
+
txout.get_tx.in.map(&:get_prev_out).each do |prev_out|
|
42
|
+
puts " from #{prev_out.get_addresses.join(", ")}"
|
43
|
+
end
|
44
|
+
puts
|
45
|
+
|
46
|
+
if txin = txout.get_next_in
|
47
|
+
tx = txin.get_tx
|
48
|
+
total -= txout.value
|
49
|
+
puts "#{tx.hash} |#{str_val(txout.value, '- ')} |=> #{str_val(total)}"
|
50
|
+
txin.get_tx.out.each do |out|
|
51
|
+
puts " to #{out.get_addresses.join(", ")}"
|
52
|
+
end
|
53
|
+
puts
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
hash160 = Bitcoin.hash160_from_address(address)
|
59
|
+
balance = store.get_balance(hash160)
|
60
|
+
puts "Balance: %.8f" % (balance / 1e8)
|