bitcoin-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. data/.gitignore +12 -0
  2. data/COPYING +18 -0
  3. data/Gemfile +4 -0
  4. data/README.rdoc +189 -0
  5. data/Rakefile +104 -0
  6. data/bin/bitcoin_dns_seed +130 -0
  7. data/bin/bitcoin_gui +80 -0
  8. data/bin/bitcoin_node +174 -0
  9. data/bin/bitcoin_shell +12 -0
  10. data/bin/bitcoin_wallet +323 -0
  11. data/bitcoin-ruby.gemspec +27 -0
  12. data/concept-examples/blockchain-pow.rb +151 -0
  13. data/doc/CONFIG.rdoc +66 -0
  14. data/doc/EXAMPLES.rdoc +9 -0
  15. data/doc/NODE.rdoc +35 -0
  16. data/doc/STORAGE.rdoc +21 -0
  17. data/doc/WALLET.rdoc +102 -0
  18. data/examples/balance.rb +60 -0
  19. data/examples/bbe_verify_tx.rb +55 -0
  20. data/examples/connect.rb +36 -0
  21. data/examples/relay_tx.rb +22 -0
  22. data/examples/verify_tx.rb +57 -0
  23. data/lib/bitcoin.rb +370 -0
  24. data/lib/bitcoin/builder.rb +266 -0
  25. data/lib/bitcoin/config.rb +56 -0
  26. data/lib/bitcoin/connection.rb +126 -0
  27. data/lib/bitcoin/ffi/openssl.rb +121 -0
  28. data/lib/bitcoin/gui/addr_view.rb +42 -0
  29. data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
  30. data/lib/bitcoin/gui/bitcoin-ruby.svg +80 -0
  31. data/lib/bitcoin/gui/conn_view.rb +36 -0
  32. data/lib/bitcoin/gui/connection.rb +68 -0
  33. data/lib/bitcoin/gui/em_gtk.rb +28 -0
  34. data/lib/bitcoin/gui/gui.builder +1643 -0
  35. data/lib/bitcoin/gui/gui.rb +290 -0
  36. data/lib/bitcoin/gui/helpers.rb +113 -0
  37. data/lib/bitcoin/gui/tree_view.rb +82 -0
  38. data/lib/bitcoin/gui/tx_view.rb +67 -0
  39. data/lib/bitcoin/key.rb +125 -0
  40. data/lib/bitcoin/logger.rb +65 -0
  41. data/lib/bitcoin/network/command_client.rb +93 -0
  42. data/lib/bitcoin/network/command_handler.rb +179 -0
  43. data/lib/bitcoin/network/connection_handler.rb +274 -0
  44. data/lib/bitcoin/network/node.rb +399 -0
  45. data/lib/bitcoin/protocol.rb +140 -0
  46. data/lib/bitcoin/protocol/address.rb +48 -0
  47. data/lib/bitcoin/protocol/alert.rb +47 -0
  48. data/lib/bitcoin/protocol/block.rb +154 -0
  49. data/lib/bitcoin/protocol/handler.rb +38 -0
  50. data/lib/bitcoin/protocol/parser.rb +148 -0
  51. data/lib/bitcoin/protocol/tx.rb +205 -0
  52. data/lib/bitcoin/protocol/txin.rb +97 -0
  53. data/lib/bitcoin/protocol/txout.rb +73 -0
  54. data/lib/bitcoin/protocol/version.rb +70 -0
  55. data/lib/bitcoin/script.rb +634 -0
  56. data/lib/bitcoin/storage/dummy.rb +164 -0
  57. data/lib/bitcoin/storage/models.rb +133 -0
  58. data/lib/bitcoin/storage/sequel.rb +335 -0
  59. data/lib/bitcoin/storage/sequel_store/sequel_migrations.rb +84 -0
  60. data/lib/bitcoin/storage/storage.rb +243 -0
  61. data/lib/bitcoin/version.rb +3 -0
  62. data/lib/bitcoin/wallet/coinselector.rb +30 -0
  63. data/lib/bitcoin/wallet/keygenerator.rb +75 -0
  64. data/lib/bitcoin/wallet/keystore.rb +203 -0
  65. data/lib/bitcoin/wallet/txdp.rb +116 -0
  66. data/lib/bitcoin/wallet/wallet.rb +243 -0
  67. data/spec/bitcoin/bitcoin_spec.rb +472 -0
  68. data/spec/bitcoin/builder_spec.rb +90 -0
  69. data/spec/bitcoin/fixtures/0d0affb5964abe804ffe85e53f1dbb9f29e406aa3046e2db04fba240e63c7fdd.json +27 -0
  70. data/spec/bitcoin/fixtures/23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63.json +23 -0
  71. data/spec/bitcoin/fixtures/477fff140b363ec2cc51f3a65c0c58eda38f4d41f04a295bbd62babf25e4c590.json +27 -0
  72. data/spec/bitcoin/fixtures/60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1.json +45 -0
  73. data/spec/bitcoin/fixtures/bc179baab547b7d7c1d5d8d6f8b0cc6318eaa4b0dd0a093ad6ac7f5a1cb6b3ba.json +34 -0
  74. data/spec/bitcoin/fixtures/rawblock-0.bin +0 -0
  75. data/spec/bitcoin/fixtures/rawblock-0.json +39 -0
  76. data/spec/bitcoin/fixtures/rawblock-1.bin +0 -0
  77. data/spec/bitcoin/fixtures/rawblock-1.json +39 -0
  78. data/spec/bitcoin/fixtures/rawblock-131025.bin +0 -0
  79. data/spec/bitcoin/fixtures/rawblock-131025.json +5063 -0
  80. data/spec/bitcoin/fixtures/rawblock-170.bin +0 -0
  81. data/spec/bitcoin/fixtures/rawblock-170.json +68 -0
  82. data/spec/bitcoin/fixtures/rawblock-9.bin +0 -0
  83. data/spec/bitcoin/fixtures/rawblock-9.json +39 -0
  84. data/spec/bitcoin/fixtures/rawblock-testnet-26478.bin +0 -0
  85. data/spec/bitcoin/fixtures/rawblock-testnet-26478.json +64 -0
  86. data/spec/bitcoin/fixtures/rawtx-01.bin +0 -0
  87. data/spec/bitcoin/fixtures/rawtx-01.json +27 -0
  88. data/spec/bitcoin/fixtures/rawtx-02.bin +0 -0
  89. data/spec/bitcoin/fixtures/rawtx-02.json +27 -0
  90. data/spec/bitcoin/fixtures/rawtx-03.bin +0 -0
  91. data/spec/bitcoin/fixtures/rawtx-03.json +48 -0
  92. data/spec/bitcoin/fixtures/rawtx-04.json +27 -0
  93. data/spec/bitcoin/fixtures/rawtx-0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9.bin +0 -0
  94. data/spec/bitcoin/fixtures/rawtx-05.json +23 -0
  95. data/spec/bitcoin/fixtures/rawtx-14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984.bin +0 -0
  96. data/spec/bitcoin/fixtures/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin +0 -0
  97. data/spec/bitcoin/fixtures/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.json +27 -0
  98. data/spec/bitcoin/fixtures/rawtx-406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602.json +23 -0
  99. data/spec/bitcoin/fixtures/rawtx-52250a162c7d03d2e1fbc5ebd1801a88612463314b55102171c5b5d817d2d7b2.bin +0 -0
  100. data/spec/bitcoin/fixtures/rawtx-b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d.bin +0 -0
  101. data/spec/bitcoin/fixtures/rawtx-ba1ff5cd66713133c062a871a8adab92416f1e38d17786b2bf56ac5f6ffdfdf5.json +37 -0
  102. data/spec/bitcoin/fixtures/rawtx-c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73.json +24 -0
  103. data/spec/bitcoin/fixtures/rawtx-de35d060663750b3975b7997bde7fb76307cec5b270d12fcd9c4ad98b279c28c.json +23 -0
  104. data/spec/bitcoin/fixtures/rawtx-f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16.bin +0 -0
  105. data/spec/bitcoin/fixtures/rawtx-testnet-a220adf1902c46a39db25a24bc4178b6a88440f977a7e2cabfdd8b5c1dd35cfb.json +27 -0
  106. data/spec/bitcoin/fixtures/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.bin +0 -0
  107. data/spec/bitcoin/fixtures/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.json +41 -0
  108. data/spec/bitcoin/fixtures/reorg/blk_0_to_4.dat +0 -0
  109. data/spec/bitcoin/fixtures/reorg/blk_3A.dat +0 -0
  110. data/spec/bitcoin/fixtures/reorg/blk_4A.dat +0 -0
  111. data/spec/bitcoin/fixtures/reorg/blk_5A.dat +0 -0
  112. data/spec/bitcoin/fixtures/testnet/block_0.bin +0 -0
  113. data/spec/bitcoin/fixtures/testnet/block_1.bin +0 -0
  114. data/spec/bitcoin/fixtures/testnet/block_2.bin +0 -0
  115. data/spec/bitcoin/fixtures/testnet/block_3.bin +0 -0
  116. data/spec/bitcoin/fixtures/testnet/block_4.bin +0 -0
  117. data/spec/bitcoin/fixtures/testnet/block_5.bin +0 -0
  118. data/spec/bitcoin/fixtures/txdp-1.txt +32 -0
  119. data/spec/bitcoin/fixtures/txdp-2-signed.txt +19 -0
  120. data/spec/bitcoin/fixtures/txdp-2-unsigned.txt +14 -0
  121. data/spec/bitcoin/key_spec.rb +123 -0
  122. data/spec/bitcoin/network_spec.rb +48 -0
  123. data/spec/bitcoin/protocol/addr_spec.rb +68 -0
  124. data/spec/bitcoin/protocol/alert_spec.rb +20 -0
  125. data/spec/bitcoin/protocol/block_spec.rb +101 -0
  126. data/spec/bitcoin/protocol/inv_spec.rb +124 -0
  127. data/spec/bitcoin/protocol/ping_spec.rb +49 -0
  128. data/spec/bitcoin/protocol/tx_spec.rb +226 -0
  129. data/spec/bitcoin/protocol/version_spec.rb +77 -0
  130. data/spec/bitcoin/reorg_spec.rb +129 -0
  131. data/spec/bitcoin/script/opcodes_spec.rb +417 -0
  132. data/spec/bitcoin/script/script_spec.rb +246 -0
  133. data/spec/bitcoin/spec_helper.rb +36 -0
  134. data/spec/bitcoin/storage_spec.rb +229 -0
  135. data/spec/bitcoin/wallet/coinselector_spec.rb +35 -0
  136. data/spec/bitcoin/wallet/keygenerator_spec.rb +64 -0
  137. data/spec/bitcoin/wallet/keystore_spec.rb +188 -0
  138. data/spec/bitcoin/wallet/txdp_spec.rb +74 -0
  139. data/spec/bitcoin/wallet/wallet_spec.rb +207 -0
  140. 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
@@ -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)