예제 #1
0
    def test_recover_multiple_iterations(self):
        for tx_message in self.transactions:
            helpers.receive_node_message(self.node1, self.relay_fileno,
                                         tx_message.rawbytes())
        helpers.clear_node_buffer(self.node1, self.blockchain_fileno)

        get_txs_message = self._send_compressed_block_to_node_1()
        txs_message = self._build_txs_message(
            get_txs_message.get_short_ids()[:5])
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())

        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()
        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.BLOCK_RECOVERY_RECOVERY_INTERVAL_S[0])
        self.node1.alarm_queue.fire_alarms()

        get_txs_bytes_2 = helpers.get_queued_node_bytes(
            self.node1, self.relay_fileno, GetTxsMessage.MESSAGE_TYPE)
        get_txs_message_2 = GetTxsMessage(buf=get_txs_bytes_2.tobytes())
        self.assertEqual(5, len(get_txs_message_2.get_short_ids()))

        txs_message = self._build_txs_message(
            get_txs_message_2.get_short_ids()[:-1])
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())

        # retry again in a longer interval
        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()

        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.BLOCK_RECOVERY_RECOVERY_INTERVAL_S[0])
        self.node1.alarm_queue.fire_alarms()

        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()

        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.BLOCK_RECOVERY_RECOVERY_INTERVAL_S[1])
        self.node1.alarm_queue.fire_alarms()

        get_txs_bytes_3 = helpers.get_queued_node_bytes(
            self.node1, self.relay_fileno, GetTxsMessage.MESSAGE_TYPE)
        get_txs_message_3 = GetTxsMessage(buf=get_txs_bytes_3.tobytes())
        self.assertEqual(1, len(get_txs_message_3.get_short_ids()))

        txs_message = self._build_txs_message(
            get_txs_message_3.get_short_ids())
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())

        self._assert_sent_block_node_1()
예제 #2
0
    def test_recover_from_single_tx_short_id(self):
        for tx_message in self.transactions_with_short_ids[:-1]:
            helpers.receive_node_message(self.node1, self.relay_fileno,
                                         tx_message.rawbytes())
        helpers.clear_node_buffer(self.node1, self.blockchain_fileno)

        _get_txs_message = self._send_compressed_block_to_node_1()

        helpers.receive_node_message(
            self.node1, self.relay_fileno,
            self.transactions_with_short_ids[-1].rawbytes())
        self._assert_sent_block_node_1()
예제 #3
0
    def test_recover_all_short_ids(self):
        for tx_message in self.transactions:
            helpers.receive_node_message(self.node1, self.relay_fileno,
                                         tx_message.rawbytes())
        helpers.clear_node_buffer(self.node1, self.blockchain_fileno)

        get_txs_message = self._send_compressed_block_to_node_1()

        self.assertEqual(10, len(get_txs_message.get_short_ids()))
        txs_message = self._build_txs_message(get_txs_message.get_short_ids())

        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())
        self._assert_sent_block_node_1()
예제 #4
0
    def _send_compressed_block_to_node_1(self):
        for tx_message_with_short_id in self.transactions_with_short_ids:
            helpers.receive_node_message(self.node2, self.relay_fileno,
                                         tx_message_with_short_id.rawbytes())
        helpers.clear_node_buffer(self.node1, self.blockchain_fileno)

        helpers.receive_node_message(self.node2, self.blockchain_fileno,
                                     self.block.rawbytes())

        broadcast_bytes = helpers.get_queued_node_bytes(
            self.node2, self.relay_fileno, BroadcastMessage.MESSAGE_TYPE)

        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     broadcast_bytes)

        get_txs_bytes = helpers.get_queued_node_bytes(
            self.node1, self.relay_fileno, GetTxsMessage.MESSAGE_TYPE)
        get_txs_message = GetTxsMessage(buf=get_txs_bytes.tobytes())

        self._assert_no_block_node_1()
        return get_txs_message
예제 #5
0
 def clear_all_buffers(self):
     helpers.clear_node_buffer(self.node1, self.blockchain_fileno)
     helpers.clear_node_buffer(self.node1, self.relay_fileno)
     helpers.clear_node_buffer(self.node1, self.gateway_fileno)
     helpers.clear_node_buffer(self.node2, self.blockchain_fileno)
     helpers.clear_node_buffer(self.node2, self.relay_fileno)
     helpers.clear_node_buffer(self.node2, self.gateway_fileno)
예제 #6
0
    def test_recover_give_up(self):
        gateway_constants.BLOCK_RECOVERY_MAX_RETRY_ATTEMPTS = 3

        for tx_message in self.transactions:
            helpers.receive_node_message(self.node1, self.relay_fileno,
                                         tx_message.rawbytes())
        helpers.clear_node_buffer(self.node1, self.blockchain_fileno)

        self._send_compressed_block_to_node_1()
        txs_message = self._build_txs_message([])
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())

        # retry, first attempt
        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()

        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.BLOCK_RECOVERY_RECOVERY_INTERVAL_S[0])
        self.node1.alarm_queue.fire_alarms()

        get_txs_bytes_2 = helpers.get_queued_node_bytes(
            self.node1, self.relay_fileno, GetTxsMessage.MESSAGE_TYPE)
        get_txs_message_2 = GetTxsMessage(buf=get_txs_bytes_2.tobytes())
        self.assertEqual(10, len(get_txs_message_2.get_short_ids()))

        txs_message = self._build_txs_message([])
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())

        # retry, attempt 2
        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()

        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.BLOCK_RECOVERY_RECOVERY_INTERVAL_S[1])
        self.node1.alarm_queue.fire_alarms()

        get_txs_bytes_3 = helpers.get_queued_node_bytes(
            self.node1, self.relay_fileno, GetTxsMessage.MESSAGE_TYPE)
        get_txs_message_3 = GetTxsMessage(buf=get_txs_bytes_3.tobytes())
        self.assertEqual(10, len(get_txs_message_3.get_short_ids()))

        txs_message = self._build_txs_message([])
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())

        # retry, attempt 3
        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()

        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.BLOCK_RECOVERY_RECOVERY_INTERVAL_S[2])
        self.node1.alarm_queue.fire_alarms()

        get_txs_bytes_4 = helpers.get_queued_node_bytes(
            self.node1, self.relay_fileno, GetTxsMessage.MESSAGE_TYPE)
        get_txs_message_4 = GetTxsMessage(buf=get_txs_bytes_4.tobytes())
        self.assertEqual(10, len(get_txs_message_4.get_short_ids()))

        txs_message = self._build_txs_message([])
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     txs_message.rawbytes())

        # retry given up
        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()

        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.BLOCK_RECOVERY_RECOVERY_INTERVAL_S[3] * 20)
        self.node1.alarm_queue.fire_alarms()

        # no bytes, even after timeout
        bytes_to_send = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertEqual(0, len(bytes_to_send))
        self._assert_no_block_node_1()
예제 #7
0
    def test_request_block_propagation(self):
        block = btc_block().rawbytes()

        # propagate block
        helpers.receive_node_message(self.node1, self.blockchain_fileno, block)

        block_hold_request_relay = self.node1.get_bytes_to_send(
            self.relay_fileno)
        self.assertIn(BlockHoldingMessage.MESSAGE_TYPE,
                      block_hold_request_relay.tobytes())
        self.node1.on_bytes_sent(self.relay_fileno,
                                 len(block_hold_request_relay))

        relayed_block = self.node1.get_bytes_to_send(self.relay_fileno)
        self.assertIn(BroadcastMessage.MESSAGE_TYPE, relayed_block.tobytes())

        block_hold_request_gateway = self.node1.get_bytes_to_send(
            self.gateway_fileno)
        self.assertIn(BlockHoldingMessage.MESSAGE_TYPE,
                      block_hold_request_gateway.tobytes())
        self.clear_all_buffers()

        # receipt timeout
        time.time = MagicMock(
            return_value=time.time() +
            gateway_constants.NEUTRALITY_BROADCAST_BLOCK_TIMEOUT_S)
        self.node1.alarm_queue.fire_alarms()

        key_msg_gateway = self.node1.get_bytes_to_send(self.gateway_fileno)
        self.assertIn(KeyMessage.MESSAGE_TYPE, key_msg_gateway.tobytes())
        self.node1.on_bytes_sent(self.gateway_fileno, len(key_msg_gateway))

        block_prop_request = self.node1.get_bytes_to_send(self.gateway_fileno)
        self.assertIn(BlockPropagationRequestMessage.MESSAGE_TYPE,
                      block_prop_request.tobytes())
        self.clear_all_buffers()

        # get new block to send
        helpers.receive_node_message(self.node2, self.gateway_fileno,
                                     block_prop_request)
        new_relayed_block = self.node2.get_bytes_to_send(self.relay_fileno)
        self.assertIn(BroadcastMessage.MESSAGE_TYPE,
                      new_relayed_block.tobytes())
        helpers.clear_node_buffer(self.node2, self.relay_fileno)

        # receive new block
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     new_relayed_block)
        block_receipt = self.node1.get_bytes_to_send(self.gateway_fileno)
        self.assertIn(BlockReceivedMessage.MESSAGE_TYPE,
                      block_receipt.tobytes())

        # receive block receipt
        helpers.receive_node_message(self.node2, self.gateway_fileno,
                                     block_receipt)
        key_message = self.node2.get_bytes_to_send(self.relay_fileno)
        self.assertIn(KeyMessage.MESSAGE_TYPE, key_message.tobytes())

        # receive key, but already seen so dont forward to blockchain
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     key_message)
        bytes_to_blockchain = self.node1.get_bytes_to_send(
            self.blockchain_fileno)
        self.assertEqual(OutputBuffer.EMPTY, bytes_to_blockchain)

        # clear blocks seen, rereceive
        self.node1.blocks_seen = ExpiringSet(
            self.node1.alarm_queue,
            gateway_constants.GATEWAY_BLOCKS_SEEN_EXPIRATION_TIME_S, "testset")
        helpers.receive_node_message(self.node1, self.relay_fileno,
                                     key_message)
        # ignore key message even if block is not in "blocks_seen"
        bytes_to_blockchain = self.node1.get_bytes_to_send(
            self.blockchain_fileno)
        self.assertEqual(OutputBuffer.EMPTY, bytes_to_blockchain)