class UTXOSet(object): db_file = 'blockchain.db' utxo_bucket = 'utxo' def __init__(self, blockchain): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.utxo_bucket) self._bc = blockchain @property def blockchain(self): return self._bc def reindex(self): # Rebuilds the UTXO set self._bucket.reset() utxos = self._bc.find_utxo() for tx_id, outs in utxos.items(): self._bucket.put(tx_id, utils.serialize(outs)) self._bucket.commit() def find_spendable_outputs(self, pubkey_hash, amount): # Finds and returns unspent outputs to reference in inputs accumulated = 0 unspent_outputs = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.is_locked_with_key(pubkey_hash) and accumulated < amount: accumulated += out.value unspent_outputs[tx_id].append(out_idx) return accumulated, unspent_outputs def find_utxo(self, pubkey_hash): # Finds UTXO for a public key hash utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: if out.is_locked_with_key(pubkey_hash): utxos.append(out) return utxos def print_utxo(self): utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: print(out) def count_transactions(self): # Returns the number of transactions in the UTXO set return len(self._bucket) def update(self, block): # Updates the UTXO set with transactions from the Block for tx in block.transactions: if not isinstance(tx, CoinbaseTx): for vin in tx.vin: update_outs = [] outs_bytes = self._bucket.get(vin.tx_id) outs = utils.deserialize(outs_bytes) for out_idx, out in enumerate(outs): if out_idx != vin.vout: update_outs.append(out) if len(update_outs) == 0: self._bucket.delete(vin.tx_id) else: self._bucket.put( vin.tx_id, utils.serialize(update_outs)) # Add new outputs new_outputs = [out for out in tx.vout] self._bucket.put(tx.ID, utils.serialize(new_outputs)) self._bucket.commit() @property def utxo_set(self): return {k: utils.deserialize(v) for k, v in self._bucket.kv.items()}
class UTXOSet(): db_file = "utxo.db" utxo_bucket = "utxo" def __init__(self, blockchain): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.utxo_bucket) self._bc = blockchain def reindex(self): self._bucket.reset() utxos = self._bc.find_utxo() for txid, outs in utxos.items(): self._bucket.put(txid, utils.serialize(outs)) self._bucket.save() def find_spendable_outputs(self, pubkey_hash, amount): account_amount = 0 unspent_outputs = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.is_locked_with_key( pubkey_hash) and account_amount < amount: account_amount += out.value unspent_outputs[tx_id].append(out_idx) return account_amount, unspent_outputs def update(self, block): for tx in block.transactions: if not isinstance(tx, CoinbaseTx): for vin in tx.vin: update_outs = [] outs_bytes = self._bucket.get(vin.txid) outs = utils.deserialize(outs_bytes) for out_idx, out in enumerate(outs): if out_idx != vin.vout: update_outs.append(out) if len(update_outs) == 0: self._bucket.delete(vin.txid) else: self._bucket.put(vin.txid, utils.serialize(update_outs)) # Add new outputs new_outputs = [out for out in tx.vout] self._bucket.put(tx.id, utils.serialize(new_outputs)) self._bucket.save() def print_utxo(self): utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: print(out.value) def find_utxo(self, pubkey_hash): utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: if out.is_locked_with_key(pubkey_hash): utxos.append(out) return utxos @property def blockchain(self): return self._bc
class UTXOSet(object): ''' Maintain all UTXOs in current blockchain ''' db_file = 'block_chain.db' bucket = 'utxo' def __init__(self, block_chain): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) self._bc = block_chain def reset(self): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) self._bucket.reset() utxos = self._bc.find_all_utxo() for tx_id, vout_idx in utxos.items(): self._bucket.put(tx_id, utils.serialize(vout_idx)) self._bucket.commit() def update(self, block): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) transactions = block.transactions for tx in transactions: if not isinstance(tx, CoinBaseTx): for vin in tx.vin: update_outs = [] encoded_outs = self._bucket.get(vin.txid) outs = utils.deserialize(encoded_outs) for out_idx, out in enumerate(outs): if out_idx != vin.vout_idx: update_outs.append(out) if len(update_outs) == 0: self._bucket.delete(vin.txid) else: self._bucket.put( vin.txid, utils.serialize(update_outs)) new_output = [out for out in tx.vout] self._bucket.put(tx.id, utils.serialize(new_output)) self._bucket.commit() def find_spendable_output(self, address, amount): accumulate = 0 spendable_output = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.address == address: accumulate += out.value spendable_output[tx_id].append(out_idx) if accumulate >= amount: return accumulate, spendable_output return accumulate, spendable_output def find_utxo_by_address(self, address): accumulate = 0 utxos = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.address == address: accumulate += out.value utxos[tx_id].append(out_idx) return accumulate, utxos