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