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.
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)