Example #1
0
    def transaction_chain_is_valid(chain):
        """
        This section deals with enforcing rules of a chain made up 
        of blocks of transactions. The following must apply:
            - Each transaction must only appear once in the chain.
            - There can only be one mining reward per block.
            - Each transaction must be valid.
        """
        transaction_ids = set()
        
        for i in range(len(chain)):
            block = chain[i]
            has_mining_reward = False

            for transaction_json in block.data:
                transaction = SystemTransactions.convert_transaction_data_from_json(transaction_json)

                if transaction.id in transaction_ids:
                    raise Exception(f'Transaction {transaction.id} is not unique')

                transaction_ids.add(transaction.id)
                
                if transaction.transaction_input == INPUT_FOR_MINING_REWARD:
                    if has_mining_reward:
                        raise Exception(
                            'There can only be one mining reward given per block.'\
                            f'Check block with the hash: {block.hash}'
                        )
                    has_mining_reward = True  
                else:
                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]
                    historic_balance = Wallet.wallet_balance_calculation(
                        historic_blockchain,
                        transaction.transaction_input['address']
                    )

                    if historic_balance != transaction.transaction_input['amount']:
                        raise Exception(
                            f'Transaction {transaction.id} has an invalid '\
                            'input amount'
                        )

                SystemTransactions.positively_validate_transaction(transaction)