Beispiel #1
0
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()}
Beispiel #2
0
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
Beispiel #3
0
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