Ejemplo n.º 1
0
    def verify_chain(cls, block_chain):
        """
        Function to verify if the current blockchain is valid.
        Returns
        -------
            True (Boolean): If blockchain is valid
            False (Boolean): If blockchain is invalid
        """
        logger.info('Verifying validity of block chain')
        for index, block in enumerate(block_chain):
            if index == 0:
                # No need to validate as the 1st block is always the genesis block
                continue
            computed_previous_hash = hash_block(block_chain[index - 1])
            if block.previous_hash != computed_previous_hash:
                logger.warning(
                    f'Computed hash {computed_previous_hash} for [block_index: {index-1} | block : {block_chain[index-1].__dict__}] is not equal to the \
                    previous hash mentioned in the [block_index: {index} | block : {block.__dict__}]'
                )
                return False
            # Eliminate the reward transaction when checking if the proof is
            # a valid proof that would satisfy the given hash condition
            if not cls.valid_proof(block.transactions[:-1],
                                   block.previous_hash, block.proof):
                logger.warning(
                    f'Proof of work is invalid in [block_index: {index} | block : {block.__dict__}]'
                )
                return False

        return True
Ejemplo n.º 2
0
    def mine_block(self, miner):
        '''
        Creates a block compiling of:
        1 - the current index
        2 - a hash of the last block in the chain
        3 - the list of open transactions
        4 - the proof

        Adds the block to the chain, then resets the open transactions.

        Args:
            miner: the user which is mining the block
        
        Returns:
            True if the process was successful
        '''
        hashed_block = hash_utils.hash_block(self.__chain[-1])
        copy_open_tx = self.__open_transactions[:]
        mined_tx = Transaction('MINED', miner, MINER_REWARD)
        copy_open_tx.append(mined_tx)
        block = Block(len(self.__chain), hashed_block,
                      copy_open_tx, self.proof_of_work())
        self.__chain.append(block)
        self.__open_transactions = []
        return True
Ejemplo n.º 3
0
    def add_block(self, block):
        transactions = [
            Transaction(tx['sender'], tx['recipient'], tx['signature'],
                        tx['amount']) for tx in block['transactions']
        ]
        valid_prood = Verification.valid_proof(transactions[:-1],
                                               block['previous_hash'],
                                               block['proof'])
        hashes_match = hash_block(self.chain[-1]) == block['previous_hash']

        if not valid_prood or not hashes_match:
            return False

        converted_block = Block(block['index'], block['previous_hash'],
                                transactions, block['proof'],
                                block['timestamp'])
        self.__chain.append(converted_block)

        stored_txs = self.__open_transactions[:]
        for incoming_tx in block['transactions']:
            for open_tx in stored_txs:
                if open_tx.sender == incoming_tx[
                        'sender'] and open_tx.recipient == incoming_tx[
                            'recipient'] and open_tx.amount == incoming_tx[
                                'amount'] and open_tx.signature == incoming_tx[
                                    'signature']:
                    try:
                        self.__open_transactions.remove(open_tx)
                    except ValueError:
                        print('TX was already removed')

        self.save_data()
        return True
Ejemplo n.º 4
0
    def proof_of_work(self):

        last_block = self.__chain[-1]
        last_hash = hash_utils.hash_block(last_block)
        proof = 0
        while not Validator.validate_proof(self.__open_transactions, last_hash, proof):
            proof += 1
        return proof
Ejemplo n.º 5
0
 def proof_of_work(self):
     last_block = self.__chain[-1]
     last_hash = hash_block(last_block)
     proof = 0
     while not Verification.valid_proof(self.__open_transactions, last_hash,
                                        proof):
         proof += 1
     return proof
 def verify_chain(cls, blockchain):
     """ Check if previous_hash value in block dict is equal to hashed version of previous block"""
     for (index, block) in enumerate(blockchain):
         if index == 0:
             continue
         if block.previous_hash != hash_block(blockchain[index - 1]):
             return False
         if not cls.valid_proof(block.transactions[:-1],
                                block.previous_hash, block.proof):
             print('Proof of work is invalid')
             return False
     return True
Ejemplo n.º 7
0
    def proof_of_work(self):
        """
        Function to find the valid proof of work that the proof validation condition

        Returns
        -------
            proof (integer): Proof of work which satisfies condition

        """
        logger.info('Finding proof of work')
        last_block = self.__chain[-1]
        last_hash = hash_block(last_block)
        proof = 0
        while not Verification.valid_proof(self.__open_transactions, last_hash,
                                           proof):
            proof += 1
        return proof
Ejemplo n.º 8
0
    def mine_block(self):
        if self.public_key == None:
            return None
        last_block = self.__chain[-1]  # get last_block from blockchain list
        hashed_block = hash_block(last_block)
        proof = self.proof_of_work()
        reward_tx = Transaction('MINING', self.public_key, '', MINING_REWARD)

        # Copy trans. instead of mutating original open_tx.
        copied_open_transactions = self.__open_transactions[:]

        # Verify each transaction in block
        for tx in copied_open_transactions:
            if not Wallet.verify_transaction(tx):
                return None

        # Add reward transaction
        copied_open_transactions.append(reward_tx)

        # Create a block object
        block = Block(len(self.__chain), hashed_block,
                      copied_open_transactions, proof)

        # Add newly created block to blockchain
        self.__chain.append(block)

        self.__open_transactions = []
        self.save_data()
        for node in self.__peer_nodes:
            url = 'http://{}/broadcast_block'.format(node)
            converted_block = block.__dict__.copy()
            converted_block['transactions'] = [
                tx.__dict__ for tx in converted_block['transactions']
            ]
            try:
                response = requests.post(url, json={"block": converted_block})
                if response.status_code == 400 or response.status_code == 500:
                    print("Couldn't add broadcasted block to blockchain")
                if response.status_code == 409:
                    self.resolve_conflicts = True
            except requests.exceptions.ConnectionError:
                continue
        return block
Ejemplo n.º 9
0
    def mine_block(self):
        """
        Function to mine blocks from the list of open transactions.
        Also adds a reward transaction to the miner.
        """
        if self.hosting_node is None:
            logger.warning('No wallet available.')
            return None

        last_block = self.__chain[-1]
        hashed_block = hash_block(last_block)
        logger.debug(f'Computed hash of previous block: {hashed_block}')

        proof = self.proof_of_work()
        logger.debug(f'Found valid proof: {proof}')

        # Rewarding users who mine blocks is a way to get coins into the blockchain
        logger.info('Creating Mining Reward Transaction')
        reward_transaction = Transaction('MINING', self.hosting_node, '',
                                         MINING_REWARD)

        # Add the reward transaction to the list of
        # open transactions before mining the block
        copied_transactions = self.__open_transactions[:]

        # Verify Transaction signatures before awarding the mining reward
        for tx in copied_transactions:
            if not Wallet.verify_transaction_signature(tx):
                logger.warning('Invalid transaction signatures in the block')
                return None

        copied_transactions.append(reward_transaction)
        self.__open_transactions.append(reward_transaction)

        logger.debug('Creating new block with all open + reward transactions')
        block = Block(len(self.__chain), hashed_block, copied_transactions,
                      proof)

        self.__chain.append(block)
        self.__open_transactions = []
        self.save_data()
        return block
Ejemplo n.º 10
0
    def is_valid_chain(cls, blockchain):
        '''
        Validates that the blockchain itself is pure.
        Done by comparing the hashes and proofs of each 
        block to ensure correctness.

        Args:  
            blockchain: the chain of blocks to validate

        Returns:
            True if the blockchain is indeed valid 
            False if it is not.

        '''
        for (i, block) in enumerate(blockchain):
            if i == 0:
                continue  # No need to verify the the genesis block
            if block.previous_hash != hash_utils.hash_block(blockchain[i - 1]):
                return False
            if not cls.validate_proof(block.transactions[:-1],
                                      block.transactions, block.proof):
                return False
        return True