bitcoin-ruby 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|