Exemplo n.º 1
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
Exemplo n.º 2
0
class BlockChain(object):
  bucket = 'blocks'
  db_file = 'block_chain.db'
  genesis_block_data = 'This is a Genesis block!'

  def __init__(self, address=None):
    self._bucket = Bucket(BlockChain.db_file, BlockChain.bucket)
    
    try:
      self._address = self._bucket.get('address')
      self._last_hash = self._bucket.get('l')
      self._last_block = pickle.loads(self._bucket.get(self._last_hash))
    except KeyError:
      if not address: # no data & no given address
        print('Block Chain not created yet!\nPlease create a new block chain with given address first!')
        sys.exit()
      else:
        self.reset(address)


  def _put_block(self, block):
    self._last_block = block
    self._last_hash = block.hash
    self._bucket.put('l', block.hash)
    self._bucket.put(block.hash, block.serialize())
    self._bucket.commit()

  def add_block(self, transactions):
    '''
    Args:
      transactions (list): List of transactions
    '''
    current_height = self._last_block.height

    new_block = Block(current_height+1, self._last_hash, transactions)
    new_block.set_hash()
    self._put_block(new_block)

  def reset(self, address):
    self._bucket.reset()
    coinbaseTx = CoinBaseTx(address)
    genesis_block = Block(0, '', [coinbaseTx])
    genesis_block.set_hash()
    self._put_block(genesis_block)
    self._address = address
    self._last_block = genesis_block
    self._last_hash = genesis_block.hash
    self._bucket.put('address', address)
    self._bucket.commit()
    return self

  @property
  def blocks(self):
    current_hash = self._last_hash
    while current_hash:
      encoded_block = self._bucket.get(current_hash)
      block = pickle.loads(encoded_block)
      yield block
      current_hash = block.prev_hash

  @property
  def address(self):
    return self._address

  @property
  def last_block(self):
    return self._last_block

  @property
  def last_hash(self):
    return self._last_hash

  def print_all_blocks(self):
    for block in self.blocks:
      block.print_block()
    
  def print_block_with_height(self, height):
    for block in self.blocks:
      if block.height == height:
        block.print_block()
        return
    print('No block with height {} found!'.format(height))

  def find_all_utxo(self):
    utxo = defaultdict(list)
    stxo = defaultdict(list)

    for block in self.blocks:
      for tx in block.transactions:

        try:
          for out_idx, out in enumerate(tx.vout):
            if stxo[tx.id]:
              for spent_out in stxo[tx.id]:
                if spent_out == out_idx:
                  raise utils.ContinueIt
            
            utxo[tx.id].append(out)
        except utils.ContinueIt:
          pass

        if not isinstance(tx, CoinBaseTx):
          for vin in tx.vin:
            stxo[tx.id].append(vin.vout_idx)
    return utxo
Exemplo n.º 3
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()}
Exemplo n.º 4
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