Example #1
0
 def test_transaction_is_valid_invalid_output(self, mock_is_valid_schema):
     mock_is_valid_schema.return_value = True
     self.transaction.output[self.wallet.address] = self._generate_float()
     with self.assertRaises(TransactionError) as err:
         Transaction.is_valid(self.transaction)
         self.assertTrue(mock_is_valid_schema.called)
         self.assertIsInstance(err, TransactionError)
         self.assertIn('Invalid transaction amount', err.message)
Example #2
0
 def test_transaction_is_valid_invalid_signature(self,
                                                 mock_is_valid_schema):
     mock_is_valid_schema.return_value = True
     self.transaction.output[self.wallet.address] = self._generate_float()
     self.transaction.input['signature'] = self.wallet.sign(
         self.transaction.output)
     with self.assertRaises(TransactionError) as err:
         Transaction.is_valid(self.transaction)
         self.assertTrue(mock_is_valid_schema.called)
         self.assertIsInstance(err, TransactionError)
         self.assertIn('Invalid signature verification', err.message)
Example #3
0
    def is_valid_transaction_data(chain: list):
        """
        Perform checks to enforce the consistnecy of transactions data in the chain blocks:
        Each transaction mush only appear once in the chain, there can only be one mining
        reward per block and each transaction must be valid.

        :param list chain: blockchain chain of blocks.
        :raise BlockchainError: on invalid transaction data.
        """
        from src.client.models.transaction import Transaction
        from src.client.models.wallet import Wallet
        transaction_uuids = set()
        for index, block in enumerate(chain, start=0):
            has_reward = False
            for transaction_info in block.data:
                try:
                    transaction = Transaction.create(**transaction_info)
                    Transaction.is_valid(transaction)
                except TransactionError as err:
                    message = f'Invalid transaction. {err.message}.'
                    logger.error(f'[Blockchain] Validation error. {message}')
                    raise BlockchainError(message)

                if transaction.uuid in transaction_uuids:
                    message = f'Repetead transaction uuid found: {transaction.uuid}.'
                    logger.error(f'[Blockchain] Validation error. {message}')
                    raise BlockchainError(message)
                transaction_uuids.add(transaction.uuid)

                address = transaction.input.get('address')
                if address == MINING_REWARD_INPUT.get('address'):
                    if has_reward:
                        message = f'Multiple mining rewards in the same block: {block}.'
                        logger.error(
                            f'[Blockchain] Validation error. {message}')
                        raise BlockchainError(message)
                    has_reward = True
                else:
                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[:index]
                    historic_balance = Wallet.get_balance(
                        historic_blockchain, address)
                    amount = transaction.input.get('amount')
                    if historic_balance != amount:
                        message = f'Address {address} historic balance inconsistency: {historic_balance} ({amount}).'
                        logger.error(
                            f'[Blockchain] Validation error. {message}')
                        raise BlockchainError(message)
Example #4
0
 def test_transaction_is_valid_mining_reward(self, mock_is_valid_schema):
     mock_is_valid_schema.return_value = True
     wallet = Wallet()
     transaction = Transaction.reward_mining(wallet)
     Transaction.is_valid(transaction)
     self.assertTrue(mock_is_valid_schema.called)
Example #5
0
 def test_transaction_is_valid(self, mock_is_valid_schema):
     mock_is_valid_schema.return_value = True
     Transaction.is_valid(self.transaction)
     self.assertTrue(mock_is_valid_schema.called)