示例#1
0
 def setUp(self):
     super(BlockchainTest, self).setUp()
     self.chain_length = random.randint(5, 10)
     self.valid_chain = self._generate_valid_chain(self.chain_length)
     self.invalid_chain = self._generate_invalid_chain()
     self.blockchain = Blockchain(self.valid_chain)
     self.serialized = self.blockchain.serialize()
示例#2
0
 def test_transactions_pool_clear_pool(self):
     data = self.transactions_pool.data
     blockchain = Blockchain()
     blockchain.add_block(data)
     self.assertEqual(self.transactions_pool.size, len(data))
     self.transactions_pool.clear_pool(blockchain)
     self.assertEqual(self.transactions_pool.size, 0)
示例#3
0
 def _generate_blockchain(self, blocks: int = 5):
     blockchain = Blockchain()
     data = []
     for _ in range(0, blocks):
         transaction = self._generate_transaction()
         data.append(transaction.info)
     blockchain.add_block(data)
     return blockchain
示例#4
0
 def test_blockchain_is_valid_transaction_data_duplicate_transaction(self):
     transaction = self._generate_transaction()
     self.blockchain.add_block([transaction.info, transaction.info])
     err_message = 'Repetead transaction uuid found'
     with self.assertRaises(BlockchainError) as err:
         Blockchain.is_valid_transaction_data(self.blockchain.chain)
         self.assertIsInstance(err, BlockchainError)
         self.assertIn(err_message, err.message)
示例#5
0
 def test_blockchain_create_invalid_schema(self, mock_is_valid_schema):
     err_message = '[Blockchain] Validation error.'
     mock_is_valid_schema.side_effect = Mock(
         side_effect=BlockchainError(err_message))
     with self.assertRaises(BlockchainError) as err:
         Blockchain.create(self.invalid_chain)
         self.assertTrue(mock_is_valid_schema.called)
         self.assertIsInstance(err, BlockchainError)
         self.assertIn(err_message, err.message)
示例#6
0
 def test_blockchain_is_valid_transaction_data_multiple_rewards(self):
     reward_transaction_1 = Transaction.reward_mining(Wallet())
     reward_transaction_2 = Transaction.reward_mining(Wallet())
     self.blockchain.add_block(
         [reward_transaction_1.info, reward_transaction_2.info])
     err_message = 'Multiple mining rewards in the same block'
     with self.assertRaises(BlockchainError) as err:
         Blockchain.is_valid_transaction_data(self.blockchain.chain)
         self.assertIsInstance(err, BlockchainError)
         self.assertIn(err_message, err.message)
示例#7
0
 def test_blockchain_is_valid_transaction_data_invalid_transaction(self):
     invalid_transaction = self._generate_transaction()
     invalid_transaction.input['signature'] = Wallet().sign(
         invalid_transaction.output)
     self.blockchain.add_block([invalid_transaction.info])
     err_message = 'Invalid transaction'
     with self.assertRaises(BlockchainError) as err:
         Blockchain.is_valid_transaction_data(self.blockchain.chain)
         self.assertIsInstance(err, BlockchainError)
         self.assertIn(err_message, err.message)
示例#8
0
 def test_blockchain_is_valid_transaction_invalid_historic_balance(self):
     wallet = Wallet()
     invalid_transaction = self._generate_transaction(wallet)
     invalid_transaction.output[wallet.address] = 1000
     invalid_transaction.input['amount'] = 1001
     invalid_transaction.input['signature'] = wallet.sign(
         invalid_transaction.output)
     self.blockchain.add_block([invalid_transaction.info])
     err_message = 'historic balance inconsistency'
     with self.assertRaises(BlockchainError) as err:
         Blockchain.is_valid_transaction_data(self.blockchain.chain)
         self.assertIsInstance(err, BlockchainError)
         self.assertIn(err_message, err.message)
示例#9
0
 def setUp(self):
     self.host = '127.0.0.1'
     self.port = 3000
     self.blockchain = Blockchain()
     self.transactions_pool = TransactionsPool()
     self.p2p_server = P2PServer(self.blockchain, self.transactions_pool)
     self.p2p_server.bind(self.host, self.port)
示例#10
0
 def test_blockchain_deserialize(self):
     deserialized = Blockchain.deserialize(self.serialized)
     self.assertIsInstance(deserialized, Blockchain)
     self.assertTrue(hasattr(deserialized, 'chain'))
     for block_one, block_two in zip(deserialized.chain,
                                     self.blockchain.chain):
         self.assertTrue(block_one == block_two)
示例#11
0
 def setUp(self):
     super(ApiTest, self).setUp()
     chain_length = random.randint(5, 10)
     chain = self._generate_valid_chain(chain_length)
     pool = self._generate_transactions_pool()
     app.blockchain = Blockchain(chain)
     app.transactions_pool = TransactionsPool(pool)
     self.client = TestClient(app)
示例#12
0
    async def _message_handler(self, socket: Socket):
        """
        Handle the incoming socket client and process the message data.
        It exits normally when the connection is closed.

        :param Socket socket: incoming socket client.
        """
        async for message in socket:
            data = parse(message)
            channel = data.get('channel')
            if channel == CHANNELS.get('node'):
                uri = data.get('content')
                info_msg = f'Uri listed. {uri}.'
                logger.info(f'[P2PServer] Node received. {info_msg}')
                self.add_uris(uri)
                await self._connect_socket(self._send_chain, uri)
            elif channel == CHANNELS.get('sync'):
                uris = data.get('content')
                self.add_uris(uris)
                info_msg = f'Total uris: {self.nodes.uris.array}.'
                logger.info(
                    f'[P2PServer] Synchronization finished. {info_msg}')
            elif channel == CHANNELS.get('chain'):
                chain = data.get('content')
                logger.info(f'[P2PServer] Chain received. {chain}.')
                blockchain = Blockchain.deserialize(chain)
                self.blockchain.set_valid_chain(blockchain.chain)
                self.transactions_pool.clear_pool(self.blockchain)
            elif channel == CHANNELS.get('transact'):
                transaction_info = data.get('content')
                logger.info(
                    f'[P2PServer] Transaction received. {transaction_info}.')
                transaction = Transaction.deserialize(transaction_info)
                self.transactions_pool.add_transaction(transaction)
            else:
                error_msg = f'Unknown channel received: {channel}.'
                logger.error(f'[P2PServer] Channel error. {error_msg}')
示例#13
0
 def blockchain(self) -> Blockchain:
     if not hasattr(self, '_blockchain'):
         self._blockchain = Blockchain()
     return self._blockchain
示例#14
0
 def test_blockchain_create_valid_schema(self, mock_is_valid_schema):
     mock_is_valid_schema.return_value = True
     blockchain = Blockchain.create(self.valid_chain)
     self.assertTrue(mock_is_valid_schema.called)
     self.assertIsInstance(blockchain, Blockchain)
     self.assertEqual(blockchain.chain, self.valid_chain)
示例#15
0
class BlockchainTest(BlockchainMixin):
    def setUp(self):
        super(BlockchainTest, self).setUp()
        self.chain_length = random.randint(5, 10)
        self.valid_chain = self._generate_valid_chain(self.chain_length)
        self.invalid_chain = self._generate_invalid_chain()
        self.blockchain = Blockchain(self.valid_chain)
        self.serialized = self.blockchain.serialize()

    def test_blockchain_string_representation(self):
        blockchain_str = str(self.blockchain)
        self.assertIn('Blockchain', blockchain_str)
        self.assertIn('Block', blockchain_str)
        self.assertTrue(
            all([
                f'index: {index}' in blockchain_str
                for index in range(self.chain_length)
            ]))

    def test_blockchain_genesis_property(self):
        self.assertTrue(self.blockchain.genesis == self._get_genesis_block())

    @patch.object(Block, 'mine_block')
    def test_blockchain_last_block_property(self, mock_mine_block):
        last_block = self.blockchain.last_block
        new_block = self._generate_block(last_block)
        mock_mine_block.return_value = new_block
        self.assertTrue(last_block == self.blockchain.chain[-1])
        self.blockchain.add_block(new_block.data)
        self.assertFalse(last_block == self.blockchain.last_block)

    @patch.object(Block, 'mine_block')
    def test_blockchain_length_property(self, mock_mine_block):
        last_block = self.blockchain.last_block
        new_block = self._generate_block(last_block)
        mock_mine_block.return_value = new_block
        self.assertEqual(self.blockchain.length, self.chain_length)
        self.blockchain.add_block(new_block.data)
        self.assertNotEqual(self.blockchain.length, self.chain_length)

    def test_blockchain_serialize(self):
        self.assertIsInstance(self.serialized, list)
        self.assertTrue(
            all([isinstance(block, str) for block in self.serialized]))

    def test_blockchain_deserialize(self):
        deserialized = Blockchain.deserialize(self.serialized)
        self.assertIsInstance(deserialized, Blockchain)
        self.assertTrue(hasattr(deserialized, 'chain'))
        for block_one, block_two in zip(deserialized.chain,
                                        self.blockchain.chain):
            self.assertTrue(block_one == block_two)

    @patch.object(Blockchain, 'is_valid_schema')
    def test_blockchain_create_valid_schema(self, mock_is_valid_schema):
        mock_is_valid_schema.return_value = True
        blockchain = Blockchain.create(self.valid_chain)
        self.assertTrue(mock_is_valid_schema.called)
        self.assertIsInstance(blockchain, Blockchain)
        self.assertEqual(blockchain.chain, self.valid_chain)

    @patch.object(Blockchain, 'is_valid_schema')
    def test_blockchain_create_invalid_schema(self, mock_is_valid_schema):
        err_message = '[Blockchain] Validation error.'
        mock_is_valid_schema.side_effect = Mock(
            side_effect=BlockchainError(err_message))
        with self.assertRaises(BlockchainError) as err:
            Blockchain.create(self.invalid_chain)
            self.assertTrue(mock_is_valid_schema.called)
            self.assertIsInstance(err, BlockchainError)
            self.assertIn(err_message, err.message)

    @patch.object(Block, 'mine_block')
    def test_add_block(self, mock_mine_block):
        last_block = self.blockchain.last_block
        new_block = self._generate_block(last_block)
        mock_mine_block.return_value = new_block
        self.blockchain.add_block(new_block.data)
        self.assertEqual(self.blockchain.length, self.chain_length + 1)
        self.assertFalse(self.blockchain.last_block == last_block)

    @patch.object(Blockchain, 'is_valid')
    def test_set_valid_chain_shorter_chain(self, mock_is_valid):
        mock_is_valid.return_value = True
        initial_length = self.blockchain.length
        short_chain = self.valid_chain.copy()
        short_chain.pop()
        self.blockchain.set_valid_chain(short_chain)
        self.assertFalse(mock_is_valid.called)
        self.assertTrue(len(short_chain) < self.blockchain.length)
        self.assertEqual(self.blockchain.length, initial_length)

    @patch.object(Blockchain, 'is_valid')
    def test_set_valid_chain_longer_chain(self, mock_is_valid):
        mock_is_valid.return_value = True
        longer_chain = self.valid_chain.copy()
        self.blockchain.chain.pop()
        initial_length = self.blockchain.length
        self.blockchain.set_valid_chain(longer_chain)
        self.assertTrue(mock_is_valid.called)
        self.assertTrue(initial_length < len(longer_chain))
        self.assertTrue(initial_length < self.blockchain.length)
        self.assertEqual(self.blockchain.length, len(longer_chain))

    def test_set_valid_chain_replace_chain(self):
        longer_chain = self.valid_chain.copy()
        self.blockchain.chain.pop()
        initial_length = self.blockchain.length
        self.blockchain.set_valid_chain(longer_chain)
        self.assertTrue(initial_length < len(longer_chain))
        self.assertTrue(initial_length < self.blockchain.length)
        self.assertEqual(self.blockchain.length, len(longer_chain))

    def test_set_valid_chain_invalid(self):
        initial_length = self.blockchain.length
        err_message = '[Blockchain] Validation error.'
        with self.assertRaises(AssertionError) as err:
            self.blockchain.set_valid_chain(self.invalid_chain)
            self.assertTrue(len(self.invalid_chain) > self.blockchain.length)
            self.assertTrue(self.blockchain.length, initial_length)
            self.assertIsInstance(err, AssertionError)
            self.assertIn(err_message, err.message)

    def test_blockchain_is_valid_schema_valid(self):
        Blockchain.is_valid(self.valid_chain)

    def test_blockchain_is_valid_schema_invalid(self):
        err_message = '[Blockchain] Validation error.'
        with self.assertRaises(BlockchainError) as err:
            Blockchain.is_valid(self.invalid_chain)
            self.assertIsInstance(err, BlockchainError)
            self.assertIn(err_message, err.message)

    def test_blockchain_is_valid_transaction_data(self):
        Blockchain.is_valid_transaction_data(self.blockchain.chain)

    def test_blockchain_is_valid_transaction_data_invalid_transaction(self):
        invalid_transaction = self._generate_transaction()
        invalid_transaction.input['signature'] = Wallet().sign(
            invalid_transaction.output)
        self.blockchain.add_block([invalid_transaction.info])
        err_message = 'Invalid transaction'
        with self.assertRaises(BlockchainError) as err:
            Blockchain.is_valid_transaction_data(self.blockchain.chain)
            self.assertIsInstance(err, BlockchainError)
            self.assertIn(err_message, err.message)

    def test_blockchain_is_valid_transaction_data_duplicate_transaction(self):
        transaction = self._generate_transaction()
        self.blockchain.add_block([transaction.info, transaction.info])
        err_message = 'Repetead transaction uuid found'
        with self.assertRaises(BlockchainError) as err:
            Blockchain.is_valid_transaction_data(self.blockchain.chain)
            self.assertIsInstance(err, BlockchainError)
            self.assertIn(err_message, err.message)

    def test_blockchain_is_valid_transaction_data_multiple_rewards(self):
        reward_transaction_1 = Transaction.reward_mining(Wallet())
        reward_transaction_2 = Transaction.reward_mining(Wallet())
        self.blockchain.add_block(
            [reward_transaction_1.info, reward_transaction_2.info])
        err_message = 'Multiple mining rewards in the same block'
        with self.assertRaises(BlockchainError) as err:
            Blockchain.is_valid_transaction_data(self.blockchain.chain)
            self.assertIsInstance(err, BlockchainError)
            self.assertIn(err_message, err.message)

    def test_blockchain_is_valid_transaction_invalid_historic_balance(self):
        wallet = Wallet()
        invalid_transaction = self._generate_transaction(wallet)
        invalid_transaction.output[wallet.address] = 1000
        invalid_transaction.input['amount'] = 1001
        invalid_transaction.input['signature'] = wallet.sign(
            invalid_transaction.output)
        self.blockchain.add_block([invalid_transaction.info])
        err_message = 'historic balance inconsistency'
        with self.assertRaises(BlockchainError) as err:
            Blockchain.is_valid_transaction_data(self.blockchain.chain)
            self.assertIsInstance(err, BlockchainError)
            self.assertIn(err_message, err.message)
示例#16
0
 def test_blockchain_is_valid_transaction_data(self):
     Blockchain.is_valid_transaction_data(self.blockchain.chain)
示例#17
0
 def test_blockchain_is_valid_schema_valid(self):
     Blockchain.is_valid(self.valid_chain)
示例#18
0
 def test_blockchain_is_valid_schema_invalid(self):
     err_message = '[Blockchain] Validation error.'
     with self.assertRaises(BlockchainError) as err:
         Blockchain.is_valid(self.invalid_chain)
         self.assertIsInstance(err, BlockchainError)
         self.assertIn(err_message, err.message)