Class: Bitcoin::Store::UtxoDB
- Inherits:
-
Object
- Object
- Bitcoin::Store::UtxoDB
- Defined in:
- lib/bitcoin/store/utxo_db.rb
Constant Summary collapse
- KEY_PREFIX =
{ out_point: 'o', # key: out_point(tx_hash and index), value: Utxo script: 's', # key: script_pubkey and out_point(tx_hash and index), value: Utxo height: 'h', # key: block_height and out_point, value: Utxo tx_hash: 't', # key: tx_hash of transaction, value: [block_height, tx_index] block: 'b', # key: block_height and tx_index, value: tx_hash tx_payload: 'p', # key: tx_hash, value: Tx }
Instance Attribute Summary collapse
-
#level_db ⇒ Object
readonly
Returns the value of attribute level_db.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
Instance Method Summary collapse
- #close ⇒ Object
-
#delete_utxo(out_point) ⇒ Bitcoin::Wallet::Utxo
Delete utxo from db.
-
#get_balance(account, current_block_height: 9999999, min: 0, max: 9999999) ⇒ Object
return [Bitcoin::Wallet::Utxo …].
-
#get_tx(tx_hash) ⇒ block_height, ...
Get transaction stored via save_tx and save_tx_position.
-
#get_utxo(out_point) ⇒ Bitcoin::Wallet::Utxo
Get utxo of the specified out point.
-
#initialize(path = "#{Bitcoin.base_dir}/db/utxo") ⇒ UtxoDB
constructor
A new instance of UtxoDB.
-
#list_unspent(current_block_height: 9999999, min: 0, max: 9999999, addresses: nil) ⇒ Object
return [Bitcoin::Wallet::Utxo …].
-
#list_unspent_in_account(account, current_block_height: 9999999, min: 0, max: 9999999) ⇒ Object
return [Bitcoin::Wallet::Utxo …].
-
#save_tx(tx_hash, tx_payload) ⇒ Object
Save payload of a transaction into db.
-
#save_tx_position(tx_hash, block_height, tx_index) ⇒ Object
Save tx position (block height and index in the block) into db When node receives ‘header` message, node should call save_tx_position to store block height and its index.
-
#save_utxo(out_point, value, script_pubkey, block_height = nil) ⇒ Object
Save utxo into db.
Constructor Details
#initialize(path = "#{Bitcoin.base_dir}/db/utxo") ⇒ UtxoDB
Returns a new instance of UtxoDB.
18 19 20 21 22 |
# File 'lib/bitcoin/store/utxo_db.rb', line 18 def initialize(path = "#{Bitcoin.base_dir}/db/utxo") FileUtils.mkdir_p(path) @level_db = ::LevelDBNative::DB.new(path) @logger = Bitcoin::Logger.create(:debug) end |
Instance Attribute Details
#level_db ⇒ Object (readonly)
Returns the value of attribute level_db.
16 17 18 |
# File 'lib/bitcoin/store/utxo_db.rb', line 16 def level_db @level_db end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
16 17 18 |
# File 'lib/bitcoin/store/utxo_db.rb', line 16 def logger @logger end |
Instance Method Details
#close ⇒ Object
24 25 26 |
# File 'lib/bitcoin/store/utxo_db.rb', line 24 def close level_db.close end |
#delete_utxo(out_point) ⇒ Bitcoin::Wallet::Utxo
Delete utxo from db
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/bitcoin/store/utxo_db.rb', line 110 def delete_utxo(out_point) level_db.batch do # [:out_point] key = KEY_PREFIX[:out_point] + out_point.to_hex return unless level_db.contains?(key) utxo = Bitcoin::Wallet::Utxo.parse_from_payload(level_db.get(key)) level_db.delete(key) # [:script] if utxo.script_pubkey key = KEY_PREFIX[:script] + utxo.script_pubkey.to_hex + out_point.to_hex level_db.delete(key) end if utxo.block_height # [:height] key = KEY_PREFIX[:height] + [utxo.block_height].pack('N').bth + out_point.to_hex level_db.delete(key) # [:block] key = KEY_PREFIX[:block] + [utxo.block_height, utxo.index].pack('N2').bth level_db.delete(key) end # handles both [:tx_hash] and [:tx_payload] if utxo.tx_hash key = KEY_PREFIX[:tx_hash] + utxo.tx_hash level_db.delete(key) key = KEY_PREFIX[:tx_payload] + utxo.tx_hash level_db.delete(key) end utxo end end |
#get_balance(account, current_block_height: 9999999, min: 0, max: 9999999) ⇒ Object
return [Bitcoin::Wallet::Utxo …]
186 187 188 |
# File 'lib/bitcoin/store/utxo_db.rb', line 186 def get_balance(account, current_block_height: 9999999, min: 0, max: 9999999) list_unspent_in_account(account, current_block_height: current_block_height, min: min, max: max).sum { |u| u.value } end |
#get_tx(tx_hash) ⇒ block_height, ...
Get transaction stored via save_tx and save_tx_position
97 98 99 100 101 102 103 104 |
# File 'lib/bitcoin/store/utxo_db.rb', line 97 def get_tx(tx_hash) key = KEY_PREFIX[:tx_hash] + tx_hash return [] unless level_db.contains?(key) block_height, tx_index = level_db.get(key).htb.unpack('N2') key = KEY_PREFIX[:tx_payload] + tx_hash tx_payload = level_db.get(key) [block_height, tx_index, tx_payload] end |
#get_utxo(out_point) ⇒ Bitcoin::Wallet::Utxo
Get utxo of the specified out point
151 152 153 154 155 156 157 |
# File 'lib/bitcoin/store/utxo_db.rb', line 151 def get_utxo(out_point) level_db.batch do key = KEY_PREFIX[:out_point] + out_point.to_hex return unless level_db.contains?(key) return Bitcoin::Wallet::Utxo.parse_from_payload(level_db.get(key)) end end |
#list_unspent(current_block_height: 9999999, min: 0, max: 9999999, addresses: nil) ⇒ Object
return [Bitcoin::Wallet::Utxo …]
160 161 162 163 164 165 166 |
# File 'lib/bitcoin/store/utxo_db.rb', line 160 def list_unspent(current_block_height: 9999999, min: 0, max: 9999999, addresses: nil) if addresses list_unspent_by_addresses(current_block_height, min: min, max: max, addresses: addresses) else list_unspent_by_block_height(current_block_height, min: min, max: max) end end |
#list_unspent_in_account(account, current_block_height: 9999999, min: 0, max: 9999999) ⇒ Object
return [Bitcoin::Wallet::Utxo …]
170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/bitcoin/store/utxo_db.rb', line 170 def list_unspent_in_account(account, current_block_height: 9999999, min: 0, max: 9999999) return [] unless account script_pubkeys = case account.purpose when Bitcoin::Wallet::Account::PURPOSE_TYPE[:legacy] account.watch_targets.map { |t| Bitcoin::Script.to_p2pkh(t).to_hex } when Bitcoin::Wallet::Account::PURPOSE_TYPE[:nested_witness] account.watch_targets.map { |t| Bitcoin::Script.to_p2wpkh(t).to_p2sh.to_hex } when Bitcoin::Wallet::Account::PURPOSE_TYPE[:native_segwit] account.watch_targets.map { |t| Bitcoin::Script.to_p2wpkh(t).to_hex } end list_unspent_by_script_pubkeys(current_block_height, min: min, max: max, script_pubkeys: script_pubkeys) end |
#save_tx(tx_hash, tx_payload) ⇒ Object
Save payload of a transaction into db
32 33 34 35 36 37 38 39 |
# File 'lib/bitcoin/store/utxo_db.rb', line 32 def save_tx(tx_hash, tx_payload) logger.info("UtxoDB#save_tx:#{[tx_hash, tx_payload]}") level_db.batch do # tx_hash -> [block_height, tx_index] key = KEY_PREFIX[:tx_payload] + tx_hash level_db.put(key, tx_payload) end end |
#save_tx_position(tx_hash, block_height, tx_index) ⇒ Object
Save tx position (block height and index in the block) into db When node receives ‘header` message, node should call save_tx_position to store block height and its index.
47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/bitcoin/store/utxo_db.rb', line 47 def save_tx_position(tx_hash, block_height, tx_index) logger.info("UtxoDB#save_tx_position:#{[tx_hash, block_height, tx_index]}") level_db.batch do # tx_hash -> [block_height, tx_index] key = KEY_PREFIX[:tx_hash] + tx_hash level_db.put(key, [block_height, tx_index].pack('N2').bth) # block_hash and tx_index -> tx_hash key = KEY_PREFIX[:block] + [block_height, tx_index].pack('N2').bth level_db.put(key, tx_hash) end end |
#save_utxo(out_point, value, script_pubkey, block_height = nil) ⇒ Object
Save utxo into db
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/bitcoin/store/utxo_db.rb', line 66 def save_utxo(out_point, value, script_pubkey, block_height=nil) logger.info("UtxoDB#save_utxo:#{[out_point, value, script_pubkey, block_height]}") level_db.batch do utxo = Bitcoin::Wallet::Utxo.new(out_point.tx_hash, out_point.index, value, script_pubkey, block_height) payload = utxo.to_payload # out_point key = KEY_PREFIX[:out_point] + out_point.to_hex return if level_db.contains?(key) level_db.put(key, payload) # script_pubkey if script_pubkey key = KEY_PREFIX[:script] + script_pubkey.to_hex + out_point.to_hex level_db.put(key, payload) end # height unless block_height.nil? key = KEY_PREFIX[:height] + [block_height].pack('N').bth + out_point.to_hex level_db.put(key, payload) end utxo end end |