bitcoin-ruby 0.0.6 → 0.0.7

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 (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