lib/bitcoin/storage/utxo/utxo_store.rb in bitcoin-ruby-0.0.5 vs lib/bitcoin/storage/utxo/utxo_store.rb in bitcoin-ruby-0.0.6

- old
+ new

@@ -3,13 +3,12 @@ module Bitcoin::Storage::Backends # Storage backend using Sequel to connect to arbitrary SQL databases. # Inherits from StoreBase and implements its interface. - class UtxoStore < StoreBase + class UtxoStore < SequelStoreBase - # possible script types SCRIPT_TYPES = [:unknown, :pubkey, :hash160, :multisig, :p2sh] if Bitcoin.namecoin? [:name_new, :name_firstupdate, :name_update].each {|n| SCRIPT_TYPES << n } end @@ -104,23 +103,23 @@ @spent_outs << { tx_hash: txin.prev_out.reverse.hth.to_sequel_blob, tx_idx: txin.prev_out_index } if @new_outs.size == size end tx.out.each.with_index do |txout, txout_tx_idx| - _, a, n = *parse_script(txout, txout_tx_idx) + _, a, n = *parse_script(txout, txout_tx_idx, tx.hash, txout_tx_idx) @new_outs << [{ :tx_hash => tx.hash.blob, :tx_idx => txout_tx_idx, :blk_id => block_id, :pk_script => txout.pk_script.blob, :value => txout.value }, @config[:index_all_addrs] ? a : a.select {|a| @watched_addrs.include?(a[1]) }, Bitcoin.namecoin? ? n : [] ] end + flush_spent_outs(depth) if @spent_outs.size > @config[:utxo_cache] + flush_new_outs(depth) if @new_outs.size > @config[:utxo_cache] end - flush_spent_outs(depth) if @spent_outs.size > @config[:utxo_cache] - flush_new_outs(depth) if @new_outs.size > @config[:utxo_cache] end def reorg new_side, new_main new_side.each do |block_hash| raise "trying to remove non-head block!" unless get_head.hash == block_hash @@ -189,10 +188,22 @@ end @new_outs = [] end end + # store hash160 and type of +addr+ + def store_addr(txout_id, addr) + hash160 = Bitcoin.hash160_from_address(addr) + type = ADDRESS_TYPES.index(Bitcoin.address_type(addr)) + + addr = @db[:addr][hash160: hash160, type: type] + addr_id = addr[:id] if addr + addr_id ||= @db[:addr].insert(hash160: hash160, type: type) + + @db[:addr_txout].insert(addr_id: addr_id, txout_id: txout_id) + end + def add_watched_address address hash160 = Bitcoin.hash160_from_address(address) @db[:addr].insert(hash160: hash160) unless @db[:addr][hash160: hash160] @watched_addrs << hash160 unless @watched_addrs.include?(hash160) end @@ -289,27 +300,29 @@ # get corresponding Models::TxOut for +txin+ def get_txout_for_txin(txin) wrap_txout(@db[:utxo][tx_hash: txin.prev_out.reverse.hth.blob, tx_idx: txin.prev_out_index]) end + # get the next input that references given output + # we only store unspent outputs, so it's always nil + def get_txin_for_txout(tx_hash, tx_idx) + nil + end + # get all Models::TxOut matching given +script+ def get_txouts_for_pk_script(script) utxos = @db[:utxo].filter(pk_script: script.blob).order(:blk_id) utxos.map {|utxo| wrap_txout(utxo) } end # get all Models::TxOut matching given +hash160+ - def get_txouts_for_hash160(hash160, unconfirmed = false) - addr = @db[:addr][hash160: hash160] + def get_txouts_for_hash160(hash160, type = :hash160, unconfirmed = false) + addr = @db[:addr][hash160: hash160, type: ADDRESS_TYPES.index(type)] return [] unless addr @db[:addr_txout].where(addr_id: addr[:id]).map {|ao| wrap_txout(@db[:utxo][id: ao[:txout_id]]) }.compact end - def get_balance hash160 - get_txouts_for_hash160(hash160).map(&:value).inject(:+) || 0 - end - # wrap given +block+ into Models::Block def wrap_block(block) return nil unless block data = {:id => block[:id], :depth => block[:depth], :chain => block[:chain], @@ -333,10 +346,10 @@ # wrap given +transaction+ into Models::Transaction def wrap_tx(tx_hash) utxos = @db[:utxo].where(tx_hash: tx_hash.blob) return nil unless utxos.any? - data = { blk_id: utxos.first[:blk_id] } + data = { blk_id: utxos.first[:blk_id], id: tx_hash } tx = Bitcoin::Storage::Models::Tx.new(self, data) tx.hash = tx_hash # utxos.first[:tx_hash].hth utxos.each {|u| tx.out[u[:tx_idx]] = wrap_txout(u) } return tx end