bitcoin-ruby 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +2 -7
  4. data/COPYING +1 -1
  5. data/Gemfile +2 -6
  6. data/Gemfile.lock +34 -0
  7. data/README.rdoc +16 -68
  8. data/Rakefile +3 -6
  9. data/bin/bitcoin_shell +0 -1
  10. data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
  11. data/lib/bitcoin.rb +350 -296
  12. data/lib/bitcoin/builder.rb +3 -1
  13. data/lib/bitcoin/connection.rb +2 -1
  14. data/lib/bitcoin/contracthash.rb +76 -0
  15. data/lib/bitcoin/dogecoin.rb +97 -0
  16. data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
  17. data/lib/bitcoin/ffi/openssl.rb +98 -2
  18. data/lib/bitcoin/ffi/secp256k1.rb +144 -0
  19. data/lib/bitcoin/key.rb +12 -2
  20. data/lib/bitcoin/logger.rb +3 -12
  21. data/lib/bitcoin/protocol/block.rb +3 -9
  22. data/lib/bitcoin/protocol/parser.rb +6 -2
  23. data/lib/bitcoin/protocol/tx.rb +44 -13
  24. data/lib/bitcoin/protocol/txin.rb +4 -2
  25. data/lib/bitcoin/protocol/txout.rb +2 -2
  26. data/lib/bitcoin/script.rb +212 -37
  27. data/lib/bitcoin/trezor/mnemonic.rb +130 -0
  28. data/lib/bitcoin/version.rb +1 -1
  29. data/spec/bitcoin/bitcoin_spec.rb +32 -3
  30. data/spec/bitcoin/builder_spec.rb +18 -0
  31. data/spec/bitcoin/contracthash_spec.rb +45 -0
  32. data/spec/bitcoin/dogecoin_spec.rb +176 -0
  33. data/spec/bitcoin/ffi_openssl.rb +45 -0
  34. data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
  35. data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
  36. data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
  37. data/spec/bitcoin/fixtures/coinbase.json +24 -0
  38. data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
  39. data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
  40. data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
  41. data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
  42. data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
  43. data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
  44. data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
  45. data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
  46. data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
  47. data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
  48. data/spec/bitcoin/protocol/block_spec.rb +0 -22
  49. data/spec/bitcoin/protocol/tx_spec.rb +145 -2
  50. data/spec/bitcoin/script/script_spec.rb +282 -0
  51. data/spec/bitcoin/secp256k1_spec.rb +48 -0
  52. data/spec/bitcoin/spec_helper.rb +0 -51
  53. data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
  54. metadata +48 -98
  55. data/bin/bitcoin_dns_seed +0 -130
  56. data/bin/bitcoin_gui +0 -80
  57. data/bin/bitcoin_node +0 -153
  58. data/bin/bitcoin_node_cli +0 -81
  59. data/bin/bitcoin_wallet +0 -402
  60. data/doc/CONFIG.rdoc +0 -66
  61. data/doc/EXAMPLES.rdoc +0 -13
  62. data/doc/NAMECOIN.rdoc +0 -34
  63. data/doc/NODE.rdoc +0 -225
  64. data/doc/STORAGE.rdoc +0 -33
  65. data/doc/WALLET.rdoc +0 -102
  66. data/examples/balance.rb +0 -66
  67. data/examples/forwarder.rb +0 -73
  68. data/examples/index_nhash.rb +0 -24
  69. data/examples/reindex_p2sh_addrs.rb +0 -44
  70. data/examples/relay_tx.rb +0 -22
  71. data/examples/verify_tx.rb +0 -57
  72. data/lib/bitcoin/config.rb +0 -58
  73. data/lib/bitcoin/gui/addr_view.rb +0 -44
  74. data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
  75. data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
  76. data/lib/bitcoin/gui/conn_view.rb +0 -38
  77. data/lib/bitcoin/gui/connection.rb +0 -70
  78. data/lib/bitcoin/gui/em_gtk.rb +0 -30
  79. data/lib/bitcoin/gui/gui.builder +0 -1643
  80. data/lib/bitcoin/gui/gui.rb +0 -292
  81. data/lib/bitcoin/gui/helpers.rb +0 -115
  82. data/lib/bitcoin/gui/tree_view.rb +0 -84
  83. data/lib/bitcoin/gui/tx_view.rb +0 -69
  84. data/lib/bitcoin/namecoin.rb +0 -280
  85. data/lib/bitcoin/network/command_client.rb +0 -104
  86. data/lib/bitcoin/network/command_handler.rb +0 -570
  87. data/lib/bitcoin/network/connection_handler.rb +0 -387
  88. data/lib/bitcoin/network/node.rb +0 -565
  89. data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
  90. data/lib/bitcoin/storage/models.rb +0 -171
  91. data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
  92. data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
  93. data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
  94. data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
  95. data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
  96. data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
  97. data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
  98. data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
  99. data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
  100. data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
  101. data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
  102. data/lib/bitcoin/storage/storage.rb +0 -517
  103. data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
  104. data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
  105. data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
  106. data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
  107. data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
  108. data/lib/bitcoin/validation.rb +0 -400
  109. data/lib/bitcoin/wallet/coinselector.rb +0 -33
  110. data/lib/bitcoin/wallet/keygenerator.rb +0 -77
  111. data/lib/bitcoin/wallet/keystore.rb +0 -207
  112. data/lib/bitcoin/wallet/txdp.rb +0 -118
  113. data/lib/bitcoin/wallet/wallet.rb +0 -281
  114. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
  115. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
  116. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
  117. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
  118. data/spec/bitcoin/namecoin_spec.rb +0 -182
  119. data/spec/bitcoin/node/command_api_spec.rb +0 -663
  120. data/spec/bitcoin/storage/models_spec.rb +0 -104
  121. data/spec/bitcoin/storage/reorg_spec.rb +0 -236
  122. data/spec/bitcoin/storage/storage_spec.rb +0 -387
  123. data/spec/bitcoin/storage/validation_spec.rb +0 -300
  124. data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
  125. data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
  126. data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
  127. data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
  128. data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
@@ -1,52 +0,0 @@
1
- Sequel.migration do
2
-
3
-
4
- up do
5
-
6
- @log.info { "Running migration #{__FILE__}" }
7
-
8
- binary = adapter_scheme == :postgres ? :bytea : :varchar
9
-
10
- alter_table :schema_info do
11
- add_column :magic, :varchar # network magic-head
12
- add_column :backend, :varchar # storage backend
13
- end
14
-
15
- next if tables.include?(:blk)
16
-
17
- create_table :blk do
18
- primary_key :id
19
- column :hash, binary, :null => false, :unique => true, :index => true
20
- column :depth, :int, :null => false, :index => true
21
- column :version, :bigint, :null => false
22
- column :prev_hash, binary, :null => false, :index => true
23
- column :mrkl_root, binary, :null => false
24
- column :time, :bigint, :null => false
25
- column :bits, :bigint, :null => false
26
- column :nonce, :bigint, :null => false
27
- column :blk_size, :int, :null => false
28
- column :chain, :int, :null => false
29
- column :work, binary, :index => true
30
- column :aux_pow, binary
31
- end
32
-
33
- create_table :addr do
34
- primary_key :id
35
- column :hash160, String, :null => false, :index => true
36
- end
37
-
38
- create_table :addr_txout do
39
- column :addr_id, :int, :null => false, :index => true
40
- column :txout_id, :int, :null => false, :index => true
41
- end
42
-
43
- create_table :names do
44
- column :txout_id, :int, :null => false, :index => true
45
- column :hash, binary, :index => true
46
- column :name, binary, :index => true
47
- column :value, binary
48
- end
49
-
50
- end
51
-
52
- end
@@ -1,18 +0,0 @@
1
- Sequel.migration do
2
-
3
- up do
4
-
5
- @log.info { "Running migration #{__FILE__}" }
6
-
7
- create_table :utxo do
8
- primary_key :id
9
- column :tx_hash, String, null: false, index: true
10
- column :tx_idx, :int, null: false, index: true
11
- column :blk_id, :int, null: false, index: true
12
- column :pk_script, (@db.adapter_scheme == :postgres ? :bytea : :blob), null: false
13
- column :value, :bigint, null: false, index: true
14
- end
15
-
16
- end
17
-
18
- end
@@ -1,14 +0,0 @@
1
- Sequel.migration do
2
- up do
3
- @log.info { "Running migration #{__FILE__}" }
4
-
5
- alter_table :utxo do
6
- # This is used when deleting spent uxto rows
7
- add_index([:tx_hash, :tx_idx])
8
-
9
- # These don't seem to be necessary
10
- drop_index :tx_idx
11
- drop_index :value
12
- end
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- # Add column addr.type and correct the type for all p2sh addresses
2
-
3
- Sequel.migration do
4
-
5
- up do
6
-
7
- @log.info { "Running migration #{__FILE__}" }
8
-
9
- add_column :addr, :type, :int, default: 0, null: false
10
- add_index :addr, [:hash160, :type]
11
-
12
- end
13
-
14
- end
@@ -1,374 +0,0 @@
1
- Bitcoin.require_dependency :sequel, message:
2
- "Note: You will also need an adapter for your database like sqlite3, mysql2, postgresql"
3
-
4
- module Bitcoin::Storage::Backends
5
-
6
- # Storage backend using Sequel to connect to arbitrary SQL databases.
7
- # Inherits from StoreBase and implements its interface.
8
- class UtxoStore < SequelStoreBase
9
-
10
- # possible script types
11
- SCRIPT_TYPES = [:unknown, :pubkey, :hash160, :multisig, :p2sh]
12
- if Bitcoin.namecoin?
13
- [:name_new, :name_firstupdate, :name_update].each {|n| SCRIPT_TYPES << n }
14
- end
15
-
16
- # sequel database connection
17
- attr_accessor :db
18
-
19
- DEFAULT_CONFIG = {
20
- # cache head block; it is only updated when new block comes in,
21
- # so this should only be used by the store receiving new blocks.
22
- cache_head: false,
23
- # cache this many utxo records before syncing to disk.
24
- # this should only be enabled during initial sync, because
25
- # with it the store cannot reorg properly.
26
- utxo_cache: 250,
27
- # cache this many blocks.
28
- # NOTE: this is also the maximum number of blocks the store can reorg.
29
- block_cache: 120,
30
- # keep an index of utxos for all addresses, not just the ones
31
- # we are explicitly told about.
32
- index_all_addrs: false
33
- }
34
-
35
- # create sequel store with given +config+
36
- def initialize config, *args
37
- super config, *args
38
- @spent_outs, @new_outs, @watched_addrs = [], [], []
39
- @deleted_utxos, @tx_cache, @block_cache = {}, {}, {}
40
- end
41
-
42
- # connect to database
43
- def connect
44
- super
45
- load_watched_addrs
46
- # rescan
47
-
48
- end
49
-
50
- # reset database; delete all data
51
- def reset
52
- [:blk, :utxo, :addr, :addr_txout].each {|table| @db[table].delete }
53
- @head = nil
54
- end
55
-
56
- # persist given block +blk+ to storage.
57
- def persist_block blk, chain, depth, prev_work = 0
58
- load_watched_addrs
59
- @db.transaction do
60
- attrs = {
61
- :hash => blk.hash.htb.blob,
62
- :depth => depth,
63
- :chain => chain,
64
- :version => blk.ver,
65
- :prev_hash => blk.prev_block.reverse.blob,
66
- :mrkl_root => blk.mrkl_root.reverse.blob,
67
- :time => blk.time,
68
- :bits => blk.bits,
69
- :nonce => blk.nonce,
70
- :blk_size => blk.payload.bytesize,
71
- :work => (prev_work + blk.block_work).to_s
72
- }
73
- existing = @db[:blk].filter(:hash => blk.hash.htb.blob)
74
- if existing.any?
75
- existing.update attrs
76
- block_id = existing.first[:id]
77
- else
78
- block_id = @db[:blk].insert(attrs)
79
- end
80
-
81
- if @config[:block_cache] > 0
82
- @block_cache.shift if @block_cache.size > @config[:block_cache]
83
- @deleted_utxos.shift if @deleted_utxos.size > @config[:block_cache]
84
- @block_cache[blk.hash] = blk
85
- end
86
-
87
- if chain == MAIN
88
- persist_transactions(blk.tx, block_id, depth)
89
- @tx_cache = {}
90
- @head = wrap_block(attrs.merge(id: block_id)) if chain == MAIN
91
- end
92
- return depth, chain
93
- end
94
- end
95
-
96
- def persist_transactions txs, block_id, depth
97
- txs.each.with_index do |tx, tx_blk_idx|
98
- tx.in.each.with_index do |txin, txin_tx_idx|
99
- next if txin.coinbase?
100
- size = @new_outs.size
101
- @new_outs.delete_if {|o| o[0][:tx_hash] == txin.prev_out.reverse.hth &&
102
- o[0][:tx_idx] == txin.prev_out_index }
103
- @spent_outs << {
104
- tx_hash: txin.prev_out.reverse.hth.to_sequel_blob,
105
- tx_idx: txin.prev_out_index } if @new_outs.size == size
106
- end
107
- tx.out.each.with_index do |txout, txout_tx_idx|
108
- _, a, n = *parse_script(txout, txout_tx_idx, tx.hash, txout_tx_idx)
109
- @new_outs << [{
110
- :tx_hash => tx.hash.blob,
111
- :tx_idx => txout_tx_idx,
112
- :blk_id => block_id,
113
- :pk_script => txout.pk_script.blob,
114
- :value => txout.value },
115
- @config[:index_all_addrs] ? a : a.select {|a| @watched_addrs.include?(a[1]) },
116
- Bitcoin.namecoin? ? n : [] ]
117
- end
118
- flush_spent_outs(depth) if @spent_outs.size > @config[:utxo_cache]
119
- flush_new_outs(depth) if @new_outs.size > @config[:utxo_cache]
120
- end
121
- end
122
-
123
- def reorg new_side, new_main
124
- new_side.each do |block_hash|
125
- raise "trying to remove non-head block!" unless get_head.hash == block_hash
126
- depth = get_depth
127
- blk = @db[:blk][hash: block_hash.htb.blob]
128
- delete_utxos = @db[:utxo].where(blk_id: blk[:id])
129
- @db[:addr_txout].where("txout_id IN ?", delete_utxos.map{|o|o[:id]}).delete
130
-
131
- delete_utxos.delete
132
- (@deleted_utxos[depth] || []).each do |utxo|
133
- utxo[:pk_script] = utxo[:pk_script].to_sequel_blob
134
- utxo_id = @db[:utxo].insert(utxo)
135
- addrs = Bitcoin::Script.new(utxo[:pk_script]).get_addresses
136
- addrs.each do |addr|
137
- hash160 = Bitcoin.hash160_from_address(addr)
138
- store_addr(utxo_id, hash160)
139
- end
140
- end
141
-
142
- @db[:blk].where(id: blk[:id]).update(chain: SIDE)
143
- end
144
-
145
- new_main.each do |block_hash|
146
- block = @db[:blk][hash: block_hash.htb.blob]
147
- blk = @block_cache[block_hash]
148
- persist_transactions(blk.tx, block[:id], block[:depth])
149
- @db[:blk].where(id: block[:id]).update(chain: MAIN)
150
- end
151
- end
152
-
153
- def flush_spent_outs depth
154
- log.time "flushed #{@spent_outs.size} spent txouts in %.4fs" do
155
- if @spent_outs.any?
156
- @spent_outs.each_slice(250) do |slice|
157
- if @db.adapter_scheme == :postgres
158
- condition = slice.map {|o| "(tx_hash = '#{o[:tx_hash]}' AND tx_idx = #{o[:tx_idx]})" }.join(" OR ")
159
- else
160
- condition = slice.map {|o| "(tx_hash = X'#{o[:tx_hash].hth}' AND tx_idx = #{o[:tx_idx]})" }.join(" OR ")
161
- end
162
- @db["DELETE FROM addr_txout WHERE EXISTS
163
- (SELECT 1 FROM utxo WHERE
164
- utxo.id = addr_txout.txout_id AND (#{condition}));"].all
165
- @db["DELETE FROM utxo WHERE #{condition};"].first
166
-
167
- end
168
- end
169
- @spent_outs = []
170
- end
171
- end
172
-
173
- def flush_new_outs depth
174
- log.time "flushed #{@new_outs.size} new txouts in %.4fs" do
175
- new_utxo_ids = @db[:utxo].insert_multiple(@new_outs.map{|o|o[0]})
176
- @new_outs.each.with_index do |d, idx|
177
- d[1].each do |i, hash160|
178
- next unless i && hash160
179
- store_addr(new_utxo_ids[idx], hash160)
180
- end
181
- end
182
-
183
- @new_outs.each.with_index do |d, idx|
184
- d[2].each do |i, script|
185
- next unless i && script
186
- store_name(script, new_utxo_ids[idx])
187
- end
188
- end
189
- @new_outs = []
190
- end
191
- end
192
-
193
- # store hash160 and type of +addr+
194
- def store_addr(txout_id, addr)
195
- hash160 = Bitcoin.hash160_from_address(addr)
196
- type = ADDRESS_TYPES.index(Bitcoin.address_type(addr))
197
-
198
- addr = @db[:addr][hash160: hash160, type: type]
199
- addr_id = addr[:id] if addr
200
- addr_id ||= @db[:addr].insert(hash160: hash160, type: type)
201
-
202
- @db[:addr_txout].insert(addr_id: addr_id, txout_id: txout_id)
203
- end
204
-
205
- def add_watched_address address
206
- hash160 = Bitcoin.hash160_from_address(address)
207
- @db[:addr].insert(hash160: hash160) unless @db[:addr][hash160: hash160]
208
- @watched_addrs << hash160 unless @watched_addrs.include?(hash160)
209
- end
210
-
211
- def load_watched_addrs
212
- @watched_addrs = @db[:addr].all.map{|a| a[:hash160] } unless @config[:index_all_addrs]
213
- end
214
-
215
- def rescan
216
- load_watched_addrs
217
- @rescan_lock ||= Monitor.new
218
- @rescan_lock.synchronize do
219
- log.info { "Rescanning #{@db[:utxo].count} utxos for #{@watched_addrs.size} addrs" }
220
- count = @db[:utxo].count; n = 100_000
221
- @db[:utxo].order(:id).each_slice(n).with_index do |slice, index|
222
- log.debug { "rescan progress: %.2f%" % (100.0 / count * (index*n)) }
223
- slice.each do |utxo|
224
- next if utxo[:pk_script].bytesize >= 10_000
225
- hash160 = Bitcoin::Script.new(utxo[:pk_script]).get_hash160
226
- if @config[:index_all_addrs] || @watched_addrs.include?(hash160)
227
- log.info { "Found utxo for address #{Bitcoin.hash160_to_address(hash160)}: " +
228
- "#{utxo[:tx_hash][0..8]}:#{utxo[:tx_idx]} (#{utxo[:value]})" }
229
- addr = @db[:addr][hash160: hash160]
230
- addr_utxo = {addr_id: addr[:id], txout_id: utxo[:id]}
231
- @db[:addr_txout].insert(addr_utxo) unless @db[:addr_txout][addr_utxo]
232
- end
233
- end
234
- end
235
- end
236
- end
237
-
238
- # check if block +blk_hash+ exists
239
- def has_block(blk_hash)
240
- !!@db[:blk].where(:hash => blk_hash.htb.blob).get(1)
241
- end
242
-
243
- # check if transaction +tx_hash+ exists
244
- def has_tx(tx_hash)
245
- !!@db[:utxo].where(:tx_hash => tx_hash.blob).get(1)
246
- end
247
-
248
- # get head block (highest block from the MAIN chain)
249
- def get_head
250
- (@config[:cache_head] && @head) ? @head :
251
- @head = wrap_block(@db[:blk].filter(:chain => MAIN).order(:depth).last)
252
- end
253
-
254
- # get depth of MAIN chain
255
- def get_depth
256
- return -1 unless get_head
257
- get_head.depth
258
- end
259
-
260
- # get block for given +blk_hash+
261
- def get_block(blk_hash)
262
- wrap_block(@db[:blk][:hash => blk_hash.htb.blob])
263
- end
264
-
265
- # get block by given +depth+
266
- def get_block_by_depth(depth)
267
- wrap_block(@db[:blk][:depth => depth, :chain => MAIN])
268
- end
269
-
270
- # get block by given +prev_hash+
271
- def get_block_by_prev_hash(prev_hash)
272
- wrap_block(@db[:blk][:prev_hash => prev_hash.htb.blob, :chain => MAIN])
273
- end
274
-
275
- # get block by given +tx_hash+
276
- def get_block_by_tx(tx_hash)
277
- block_id = @db[:utxo][tx_hash: tx_hash.blob][:blk_id]
278
- get_block_by_id(block_id)
279
- end
280
-
281
- # get block by given +id+
282
- def get_block_by_id(block_id)
283
- wrap_block(@db[:blk][:id => block_id])
284
- end
285
-
286
- # get transaction for given +tx_hash+
287
- def get_tx(tx_hash)
288
- @tx_cache[tx_hash] ||= wrap_tx(tx_hash)
289
- end
290
-
291
- # get transaction by given +tx_id+
292
- def get_tx_by_id(tx_id)
293
- get_tx(tx_id)
294
- end
295
-
296
- def get_txout_by_id(id)
297
- wrap_txout(@db[:utxo][id: id])
298
- end
299
-
300
- # get corresponding Models::TxOut for +txin+
301
- def get_txout_for_txin(txin)
302
- wrap_txout(@db[:utxo][tx_hash: txin.prev_out.reverse.hth.blob, tx_idx: txin.prev_out_index])
303
- end
304
-
305
- # get the next input that references given output
306
- # we only store unspent outputs, so it's always nil
307
- def get_txin_for_txout(tx_hash, tx_idx)
308
- nil
309
- end
310
-
311
- # get all Models::TxOut matching given +script+
312
- def get_txouts_for_pk_script(script)
313
- utxos = @db[:utxo].filter(pk_script: script.blob).order(:blk_id)
314
- utxos.map {|utxo| wrap_txout(utxo) }
315
- end
316
-
317
- # get all Models::TxOut matching given +hash160+
318
- def get_txouts_for_hash160(hash160, type = :hash160, unconfirmed = false)
319
- addr = @db[:addr][hash160: hash160, type: ADDRESS_TYPES.index(type)]
320
- return [] unless addr
321
- @db[:addr_txout].where(addr_id: addr[:id]).map {|ao| wrap_txout(@db[:utxo][id: ao[:txout_id]]) }.compact
322
- end
323
-
324
- # wrap given +block+ into Models::Block
325
- def wrap_block(block)
326
- return nil unless block
327
-
328
- data = {:id => block[:id], :depth => block[:depth], :chain => block[:chain],
329
- :work => block[:work].to_i, :hash => block[:hash].hth}
330
- blk = Bitcoin::Storage::Models::Block.new(self, data)
331
-
332
- blk.ver = block[:version]
333
- blk.prev_block = block[:prev_hash].reverse
334
- blk.mrkl_root = block[:mrkl_root].reverse
335
- blk.time = block[:time].to_i
336
- blk.bits = block[:bits]
337
- blk.nonce = block[:nonce]
338
-
339
- if cached = @block_cache[block[:hash].hth]
340
- blk.tx = cached.tx
341
- end
342
-
343
- blk.recalc_block_hash
344
- blk
345
- end
346
-
347
- # wrap given +transaction+ into Models::Transaction
348
- def wrap_tx(tx_hash)
349
- utxos = @db[:utxo].where(tx_hash: tx_hash.blob)
350
- return nil unless utxos.any?
351
- data = { blk_id: utxos.first[:blk_id], id: tx_hash }
352
- tx = Bitcoin::Storage::Models::Tx.new(self, data)
353
- tx.hash = tx_hash # utxos.first[:tx_hash].hth
354
- utxos.each {|u| tx.out[u[:tx_idx]] = wrap_txout(u) }
355
- return tx
356
- end
357
-
358
- # wrap given +output+ into Models::TxOut
359
- def wrap_txout(utxo)
360
- return nil unless utxo
361
- data = {id: utxo[:id], tx_id: utxo[:tx_hash], tx_idx: utxo[:tx_idx]}
362
- txout = Bitcoin::Storage::Models::TxOut.new(self, data)
363
- txout.value = utxo[:value]
364
- txout.pk_script = utxo[:pk_script]
365
- txout
366
- end
367
-
368
- def check_consistency(*args)
369
- log.warn { "Utxo store doesn't support consistency check" }
370
- end
371
-
372
- end
373
-
374
- end