コード例 #1
0
    def __init__(self):
        self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket)

        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            self._tip = None
コード例 #2
0
 def __init__(self, address=None):
     self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket)
     try:
         self._tip = self._bucket.get('l')
     except KeyError:
         genesis = NewGnesisBlock().pow_of_block()
         self._block_put(genesis)
コード例 #3
0
  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()
コード例 #4
0
ファイル: blockchain.py プロジェクト: nk930439gj94/NMLab
    def __init__(self, address=None):
        self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket)

        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            cb_tx = CoinbaseTx(address, Blockchain.genesis_coinbase_data)
            genesis = Block([cb_tx]).pow_of_block()
            self._block_put(genesis)
コード例 #5
0
    def __init__(self, address=None):
        self._bucket = Bucket(BlockChain.db_file, BlockChain.block_bucket)

        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            if not address:
                self._tip = None
            else:
                cb_tx = CoinbaseTx(address, BlockChain.genesis_coinbase_data)
                genesis = Block([cb_tx], 0).proof_of_block()
                self._put_block(genesis)
コード例 #6
0
ファイル: blockchain.py プロジェクト: Jim-CTChen/block_chain
 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)
コード例 #7
0
class Blockchain(object):
    """ Represents a sequence of blocks

	Args:
		None

	Attributes:
		None

	"""
    def __init__(self):
        self._blocks = Bucket(DB_FILE, BLOCK_BUCKET)

    def __repr__(self):
        return 'Blockchain({0!r})'.format(self._blocks)

    def __str__(self):
        self._blocks.commit()
        return 'Blockchain({0!r})'.format(self._blocks)

    def addBlock(self, transaction):
        prevBlock = self._blocks[len(self._blocks) - 1]
        self._blocks.append(
            Block(prevBlock.height, prevBlock.hash, transaction))
        self._blocks.commit()

    def printBlock(self, height):
        block = self._blocks[height]
        print(block)
        self._blocks.commit()
コード例 #8
0
  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()
コード例 #9
0
class Blockchain(object):
    """ Blockchain keeps a sequence of Blocks
    Attributes:
        _tip (bytes): Point to the latest hash of block.
        _bucket (dict): bucket of DB 
    """
    latest = 'l'
    db_file = 'blockchain.db'
    block_bucket = 'blocks'
    genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'

    def __init__(self, address=None):
        self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket)
        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            genesis = NewGnesisBlock().pow_of_block()
            self._block_put(genesis)
            # if not address:
            #     self._tip = None
            # else:
            #     genesis = NewGnesisBlock().pow_of_block()
            #     self._block_put(genesis)

    def _block_put(self, block):
        self._bucket.put(block.hash, block.serialize())
        self._bucket.put('l', block.hash)
        self._tip = block.hash
        self._bucket.commit()

    @property
    def blocks(self):
        current_tip = self._tip
        while True:
            if not current_tip:
                # Encounter genesis block
                raise StopIteration
            encoded_block = self._bucket.get(current_tip)
            block = pickle.loads(encoded_block)
            yield block
            current_tip = block.prev_block_hash

    @property
    def length(self):
        return len(list(self.blocks))
コード例 #10
0
class BlockChain():
    latest = 'l'
    latest_height = 'height'
    db_file = "blockchain.db"
    block_bucket = 'blocks'
    genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'

    def __init__(self, address=None):
        self._bucket = Bucket(BlockChain.db_file, BlockChain.block_bucket)

        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            if not address:
                self._tip = None
            else:
                cb_tx = CoinbaseTx(address, BlockChain.genesis_coinbase_data)
                genesis = Block([cb_tx], 0).proof_of_block()
                self._put_block(genesis)

    def _put_block(self, block):
        self._bucket.put(block.hash, block.serialize())
        self._bucket.put('l', block.hash)
        self._bucket.put('height', block.height)
        self._tip = block.hash
        self._bucket.save()

    def MineBlock(self, tx_lst):
        last_hash = self._bucket.get('l')
        last_height = self._bucket.get('height')

        for tx in tx_lst:
            if not self.verify_transaction(tx):
                print("ERROR: Invalid transaction")
                sys.exit()

        new_block = Block(tx_lst, last_height + 1, last_hash).proof_of_block()
        self._put_block(new_block)
        return new_block

    def find_unspent_transactions(self, pubkey_hash):
        spent_txo = defaultdict(list)
        unspent_txs = []
        for block in blocks:
            for tx in block.transactions:

                if not isinstance(tx, CoinbaseTx):
                    for vin in tx.vin:
                        if vin.uses_key(pubkey_hash):
                            spent_txo[tx.id].append(vin.vout)
                for out_idx, out in enumerate(tx.vout):
                    if spent_txo[tx.id]:
                        for spent_out in spent_txo[tx.id]:
                            if spent_out == out_idx:
                                continue
                    if out.is_locked_with_key(pubkey_hash):
                        unspent_txs.append(tx)
                        break
        return unspent_txs

    def find_utxo(self):
        utxo = defaultdict(list)
        spent_txos = defaultdict(list)

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

                for out_idx, out in enumerate(tx.vout):
                    if spent_txos[tx.id]:
                        for spent_out in spent_txos[tx.id]:
                            if spent_out == out_idx:
                                continue

                    utxo[tx.id].append(out)

                if not isinstance(tx, CoinbaseTx):
                    for vin in tx.vin:
                        spent_txos[vin.txid].append(vin.vout)

        return utxo

    def blocks(self, height=None):
        cur_tip = self._tip
        while True:
            if not cur_tip:
                break
            encoded_block = self._bucket.get(cur_tip)
            block = pickle.loads(encoded_block)
            cur_tip = block.prev_block_hash
            cur_height = block.height
            if height is not None:
                if cur_height == height:
                    yield block
                    return
                elif cur_height < height:
                    raise IndexError(height)
                else:
                    continue
            yield block

    def find_transaction(self, ID):
        for block in self.blocks():
            for tx in block.transactions:
                if tx.id == ID:
                    return tx

        return None

    def sign_transaction(self, tx, priv_key):
        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.txid)
            prev_txs[prev_tx.id] = prev_tx

        tx.sign(priv_key, prev_txs)

    def verify_transaction(self, tx):
        if isinstance(tx, CoinbaseTx):
            return True

        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.txid)
            prev_txs[prev_tx.id] = prev_tx

        return tx.verify(prev_txs)
コード例 #11
0
ファイル: utxo_set.py プロジェクト: nk930439gj94/NMLab
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()}
コード例 #12
0
ファイル: blockchain.py プロジェクト: Jim-CTChen/block_chain
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
コード例 #13
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
コード例 #14
0
ファイル: test.py プロジェクト: cwlin1998/blockchain-hw1
from block import Block
from blockchain import Blockchain
from db import Bucket

if __name__ == "__main__":
#	blockchain = Blockchain()
#	print(blockchain)
#	blockchain.addBlock('addBlock')
#	print(blockchain)
	bucket = Bucket('test.db', 'block')
	bucket2 = Bucket('test.db', 'block2')
	bucket['key1'] = 'value'
	print(bucket['key'])
	bucket2['key2'] = 'value'
	bucket.commit()
	bucket2.commit()
	print(bucket)
	print(bucket2)
コード例 #15
0
ファイル: blockchain.py プロジェクト: nk930439gj94/NMLab
class Blockchain(object):
    """ Blockchain keeps a sequence of Blocks

    Attributes:
        _tip (bytes): Point to the latest hash of block.
        _bucket (dict): bucket of DB 
    """
    latest = 'l'
    db_file = 'blockchain.db'
    block_bucket = 'blocks'
    genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'

    def __init__(self, address=None):
        self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket)

        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            if not address:
                self._tip = None
            else:
                cb_tx = CoinbaseTx(
                    address, Blockchain.genesis_coinbase_data)
                genesis = Block([cb_tx]).pow_of_block()
                self._block_put(genesis)

    def _block_put(self, block):
        self._bucket.put(block.hash, block.serialize())
        self._bucket.put('l', block.hash)
        self._tip = block.hash
        self._bucket.commit()

    def MineBlock(self, transaction_lst):
        # Mines a new block with the provided transactions
        last_hash = self._bucket.get('l')

        for tx in transaction_lst:
            if not self.verify_transaction(tx):
                print("ERROR: Invalid transaction")
                sys.exit()

        new_block = Block(transaction_lst, last_hash).pow_of_block()
        self._block_put(new_block)
        return new_block

    def find_unspent_transactions(self, pubkey_hash):
        # Returns a list of transactions containing unspent outputs
        spent_txo = defaultdict(list)
        unspent_txs = []
        for block in self.blocks:
            for tx in block.transactions:

                if not isinstance(tx, CoinbaseTx):
                    for vin in tx.vin:
                        if vin.uses_key(pubkey_hash):
                            tx_id = vin.tx_id
                            spent_txo[tx_id].append(vin.vout)

                tx_id = tx.ID
                try:
                    for out_idx, out in enumerate(tx.vout):
                        # Was the output spent?
                        if spent_txo[tx_id]:
                            for spent_out in spent_txo[tx_id]:
                                if spent_out == out_idx:
                                    raise ContinueIt

                        if out.is_locked_with_key(pubkey_hash):
                            unspent_txs.append(tx)
                except ContinueIt:
                    pass

        return unspent_txs

    def find_utxo(self):
        # Finds all unspent transaction outputs
        utxo = defaultdict(list)
        spent_txos = defaultdict(list)

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

                try:
                    for out_idx, out in enumerate(tx.vout):
                        # Was the output spent?
                        if spent_txos[tx.ID]:
                            for spent_out in spent_txos[tx.ID]:
                                if spent_out == out_idx:
                                    raise ContinueIt

                        utxo[tx.ID].append(out)
                except ContinueIt:
                    pass

                if not isinstance(tx, CoinbaseTx):
                    for vin in tx.vin:
                        spent_txos[vin.tx_id].append(vin.vout)

        return utxo

    @property
    def blocks(self):
        current_tip = self._tip
        while True:
            if not current_tip:
                # Encounter genesis block
                raise StopIteration
            encoded_block = self._bucket.get(current_tip)
            block = pickle.loads(encoded_block)
            yield block
            current_tip = block.prev_block_hash

    def find_transaction(self, ID):
        # finds a transaction by its ID
        for block in self.blocks:
            for tx in block.transactions:
                if tx.ID == ID:
                    return tx

        # return None
        raise NotFoundTransaction

    def sign_transaction(self, tx, priv_key):
        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.tx_id)
            prev_txs[prev_tx.ID] = prev_tx

        tx.sign(priv_key, prev_txs)

    def verify_transaction(self, tx):
        if isinstance(tx, CoinbaseTx):
            return True

        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.tx_id)
            prev_txs[prev_tx.ID] = prev_tx

        return tx.verify(prev_txs)
コード例 #16
0
ファイル: blockchain.py プロジェクト: nk930439gj94/NMLab
class Blockchain(object):
    """ 
    Attributes:
        _tip (bytes): Point to the latest hash of block.
        _bucket (dict): bucket of DB 
    """
    db_file = 'blockchain.db'
    block_bucket = 'blocks'
    genesis_coinbase_data = 'mother f****r first block'

    def __init__(self, address=None):
        self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket)

        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            cb_tx = CoinbaseTx(address, Blockchain.genesis_coinbase_data)
            genesis = Block([cb_tx]).pow_of_block()
            self._block_put(genesis)

    def _block_put(self, block):
        self._bucket.put( block.hash, pickle.dumps(block) )
        self._bucket.put('l', block.hash)
        self._tip = block.hash
        self._bucket.commit()

    def MineBlock(self, transaction_lst):
        # Mines a new block with the provided transactions
        last_hash = self._bucket.get('l')

        for tx in transaction_lst:
            if not self.verify_transaction(tx):
                print("ERROR: Invalid transaction")
                sys.exit()
        print( 'Verifying complete\n' )

        new_block = Block(transaction_lst, last_hash).pow_of_block()
        self._block_put(new_block)
        return new_block

    @property
    def latest_block(self):
        return pickle.loads( self._bucket.get( self._tip ) )

    @property
    def blocks(self):
        current_tip = self._tip
        while True:
            if not current_tip:
                raise StopIteration
            encoded_block = self._bucket.get(current_tip)
            block = pickle.loads(encoded_block)
            yield block
            current_tip = block.prev_block_hash

    @property
    def height(self):
        return len( self._bucket.kv )-1

    def find_transaction(self, ID):
        # finds a transaction by its ID
        for block in self.blocks:
            for tx in block.transactions:
                if tx.ID == ID:
                    return tx

        return None

    def sign_transaction(self, tx, priv_key):
        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.tx_id)
            prev_txs[prev_tx.ID] = prev_tx

        tx.sign(priv_key, prev_txs)

    def verify_transaction(self, tx):
        if isinstance(tx, CoinbaseTx):
            return True

        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.tx_id)
            prev_txs[prev_tx.ID] = prev_tx

        return tx.verify(prev_txs)
コード例 #17
0
class Blockchain(object):
    """ Blockchain keeps a sequence of Blocks

    Attributes:
        _tip (bytes): Point to the latest hash of block.
        _bucket (dict): bucket of DB 
    """
    latest = 'l'
    db_file = GetAppDir() + str(r'\blockchain.db')
    block_bucket = 'blocks'
    genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'

    def __init__(self):
        self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket)

        try:
            self._tip = self._bucket.get('l')
        except KeyError:
            self._tip = None

    def _block_put(self, block):

        for tx in block._tx_lst:
            if not self.verify_transaction(tx):
                utils.logg(
                    'Verify transactions faild, block contains one or more txs wich cant be verified'
                )
                return False

        self._bucket.put(block.hash, block.serialize())
        self._bucket.put('l', block.hash)
        self._tip = block.hash

        return self._bucket.commit()

    def find_unspent_transactions(self, pubkey_hash):
        # Returns a list of transactions containing unspent outputs
        spent_txo = defaultdict(list)
        unspent_txs = []
        for block in self.blocks:
            for tx in block.transactions:

                if not isinstance(tx, CoinbaseTx):
                    for vin in tx.vin:
                        if vin.uses_key(pubkey_hash):
                            tx_id = vin.tx_id
                            spent_txo[tx_id].append(vin.vout)

                tx_id = tx.ID
                try:
                    for out_idx, out in enumerate(tx.vout):
                        # Was the output spent?
                        if spent_txo[tx_id]:
                            for spent_out in spent_txo[tx_id]:
                                if spent_out == out_idx:
                                    raise ContinueIt

                        if out.is_locked_with_key(pubkey_hash):
                            unspent_txs.append(tx)
                except ContinueIt:
                    pass

        return unspent_txs

    def find_utxo(self):
        # Finds all unspent transaction outputs
        utxo = defaultdict(list)
        spent_txos = defaultdict(list)

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

                try:
                    for out_idx, out in enumerate(tx.vout):
                        # Was the output spent?
                        if spent_txos[tx.ID]:
                            for spent_out in spent_txos[tx.ID]:
                                if spent_out == out_idx:
                                    raise ContinueIt

                        utxo[tx.ID].append(out)
                except ContinueIt:
                    pass

                if not isinstance(tx, CoinbaseTx):
                    for vin in tx.vin:
                        spent_txos[vin.tx_id].append(vin.vout)

        return utxo

    @property
    def blocks(self):
        current_tip = self._tip
        while True:
            if not current_tip:
                # Encounter genesis block
                break
            encoded_block = self._bucket.get(current_tip)
            block = pickle.loads(encoded_block)
            yield block
            current_tip = block.prev_block_hash

    def haveBlock(self, block_hash):
        for block in self.blocks:
            if block.hash == block_hash:
                return True
        return False

    def getBlock(self, block_hash):
        if self.haveBlock(block_hash):
            for block in self.blocks:
                if block.hash == block_hash:
                    return block
        return None

    def find_transaction(self, ID):
        # finds a transaction by its ID
        for block in self.blocks:
            for tx in block.transactions:
                if tx.ID == ID:
                    return tx
        # return None
        raise NotFoundTransaction

    def sign_transaction(self, tx, priv_key):
        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.tx_id)
            prev_txs[prev_tx.ID] = prev_tx

        tx.sign(priv_key, prev_txs)

    def verify_transaction(self, tx):
        if tx.isCoinBase():
            return True

        prev_txs = {}
        for vin in tx.vin:
            prev_tx = self.find_transaction(vin.tx_id)
            prev_txs[prev_tx.ID] = prev_tx

        return tx.verify(prev_txs)
コード例 #18
0
 def __init__(self, blockchain):
     self._bucket = Bucket(UTXOSet.db_file, UTXOSet.utxo_bucket)
     self._bc = blockchain
コード例 #19
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
コード例 #20
0
 def __init__(self):
     self._blocks = Bucket(DB_FILE, BLOCK_BUCKET)