Exemple #1
0
    def msg_inv(self, msg: InvBtcMessage) -> None:
        """
        Handle an inventory message.

        Requests all transactions and blocks that haven't been previously seen.
        :param msg: INV message
        """
        contains_block = False
        inventory_requests = []
        block_hashes = []
        for inventory_type, item_hash in msg:
            if InventoryType.is_block(inventory_type):
                if not self.node.should_process_block_hash(item_hash):
                    continue
                block_hashes.append(item_hash)
                if item_hash not in self.node.blocks_seen.contents:
                    contains_block = True
                    inventory_requests.append((inventory_type, item_hash))
            else:
                inventory_requests.append((inventory_type, item_hash))

        self.node.block_cleanup_service.mark_blocks_and_request_cleanup(
            block_hashes)

        if inventory_requests:
            get_data = GetDataBtcMessage(
                magic=msg.magic(),
                inv_vects=inventory_requests,
                request_witness_data=self.request_witness_data)
            self.connection.enqueue_msg(get_data, prepend=contains_block)

        self.node.block_queuing_service.mark_blocks_seen_by_blockchain_node(
            block_hashes)
    def test_parse_message_success_all_types(self):
        # TODO: pull these numbers into constants, along with all the BTC messages
        self.create_message_successfully(self.VERSION_BTC_MESSAGE,
                                         VersionBtcMessage)
        self.create_message_successfully(VerAckBtcMessage(self.MAGIC),
                                         VerAckBtcMessage)
        self.create_message_successfully(PingBtcMessage(self.MAGIC),
                                         PingBtcMessage)
        self.create_message_successfully(PongBtcMessage(self.MAGIC, 123),
                                         PongBtcMessage)
        self.create_message_successfully(GetAddrBtcMessage(self.MAGIC),
                                         GetAddrBtcMessage)
        self.create_message_successfully(
            AddrBtcMessage(self.MAGIC,
                           [(int(time.time()), "127.0.0.1", 8000)]),
            AddrBtcMessage)

        inv_vector = [(1, self.HASH), (2, self.HASH)]
        self.create_message_successfully(InvBtcMessage(self.MAGIC, inv_vector),
                                         InvBtcMessage)
        self.create_message_successfully(
            GetDataBtcMessage(self.MAGIC, inv_vector), GetDataBtcMessage)
        self.create_message_successfully(
            NotFoundBtcMessage(self.MAGIC, inv_vector), NotFoundBtcMessage)

        hashes = [self.HASH, self.HASH]
        self.create_message_successfully(
            GetHeadersBtcMessage(self.MAGIC, self.VERSION, hashes, self.HASH),
            GetHeadersBtcMessage)
        self.create_message_successfully(
            GetBlocksBtcMessage(self.MAGIC, self.VERSION, hashes, self.HASH),
            GetBlocksBtcMessage)

        self.create_message_successfully(
            TxBtcMessage(self.MAGIC, self.VERSION, [], [], 0), TxBtcMessage)

        txs = [TxIn(buf=bytearray(10), length=10, off=0).rawbytes()] * 5
        self.create_message_successfully(
            BlockBtcMessage(self.MAGIC, self.VERSION, self.HASH, self.HASH, 0,
                            0, 0, txs), BlockBtcMessage)
        self.create_message_successfully(
            HeadersBtcMessage(self.MAGIC,
                              [helpers.generate_bytearray(81)] * 2),
            HeadersBtcMessage)
        self.create_message_successfully(
            RejectBtcMessage(self.MAGIC, b"a message",
                             RejectBtcMessage.REJECT_MALFORMED, b"test break",
                             helpers.generate_bytearray(10)), RejectBtcMessage)
        self.create_message_successfully(SendHeadersBtcMessage(self.MAGIC),
                                         SendHeadersBtcMessage)

        self.create_message_successfully(
            FeeFilterBtcMessage(self.MAGIC, fee_rate=100), FeeFilterBtcMessage)

        self.create_message_successfully(
            BtcMessage(self.MAGIC, b'xversion', 0, bytearray(30)),
            XversionBtcMessage)
Exemple #3
0
 def on_block_sent(self, block_hash: Sha256Hash,
                   block_message: BlockBtcMessage):
     # After sending block message to Bitcoin node sending INV message for the same block to the node
     # This is needed to update Synced Headers value of the gateway peer on the Bitcoin node
     # If Synced Headers is not up-to-date than Bitcoin node does not push compact blocks to the gateway
     inv_msg = InvBtcMessage(
         magic=block_message.magic(),
         inv_vects=[(InventoryType.MSG_BLOCK, block_hash)],
     )
     self.node.send_msg_to_node(inv_msg)
Exemple #4
0
    def msg_reject(self, msg):
        """
        Handle REJECT message from Bitcoin node
        :param msg: REJECT message
        """

        # Send inv message to the send in case of rejected block
        # remaining sync communication will proxy to remote blockchain node
        if msg.message() == BtcMessageType.BLOCK:
            inv_msg = InvBtcMessage(magic=self.magic,
                                    inv_vects=[(InventoryType.MSG_BLOCK,
                                                msg.obj_hash())])
            self.node.send_msg_to_node(inv_msg)
Exemple #5
0
    def msg_get_data(self, msg: GetDataBtcMessage) -> None:
        """
        Handle GETDATA message from Bitcoin node.
        :param msg: GETDATA message
        """

        for inv_type, object_hash in msg:
            if InventoryType.is_block(inv_type):
                block_stats.add_block_event_by_block_hash(
                    object_hash,
                    BlockStatEventType.REMOTE_BLOCK_REQUESTED_BY_GATEWAY,
                    network_num=self.connection.network_num,
                    more_info="Protocol: {}, Network: {}".format(
                        self.node.opts.blockchain_protocol,
                        self.node.opts.blockchain_network))
            inv_msg = InvBtcMessage(magic=self.magic,
                                    inv_vects=[(InventoryType.MSG_BLOCK,
                                                object_hash)])
            self.node.send_msg_to_node(inv_msg)
        return self.msg_proxy_request(msg)
Exemple #6
0
    def msg_block(self, msg) -> None:
        """
        Handle block message
        """
        block_hash = msg.block_hash()
        if not self.node.should_process_block_hash(block_hash):
            return
        if self.node.block_cleanup_service.is_marked_for_cleanup(block_hash):
            self.connection.log_trace("Marked block for cleanup: {}",
                                      block_hash)
            self.node.block_cleanup_service.clean_block_transactions(
                transaction_service=self.node.get_tx_service(), block_msg=msg)
        else:
            self.process_msg_block(msg)

        # After receiving block message sending INV message for the same block to Bitcoin node
        # This is needed to update Synced Headers value of the gateway peer on the Bitcoin node
        # If Synced Headers is not up-to-date than Bitcoin node does not push compact blocks to the gateway
        inv_msg = InvBtcMessage(magic=self.node.opts.blockchain_net_magic,
                                inv_vects=[(InventoryType.MSG_BLOCK,
                                            msg.block_hash())])
        self.connection.enqueue_msg(inv_msg)
Exemple #7
0
    def test_get_data_only_new_data(self):
        seen_block_hash = BtcObjectHash(
            buf=helpers.generate_bytearray(BTC_SHA_HASH_LEN),
            length=BTC_SHA_HASH_LEN)
        not_seen_block_hash = BtcObjectHash(
            buf=helpers.generate_bytearray(BTC_SHA_HASH_LEN),
            length=BTC_SHA_HASH_LEN)
        self.node.blocks_seen.add(seen_block_hash)

        inv_message = InvBtcMessage(
            magic=123,
            inv_vects=[(InventoryType.MSG_TX, seen_block_hash),
                       (InventoryType.MSG_BLOCK, not_seen_block_hash),
                       (InventoryType.MSG_BLOCK, seen_block_hash)])
        self.sut.msg_inv(inv_message)

        get_data_msg_bytes = self.sut.connection.get_bytes_to_send()
        get_data_msg = GetDataBtcMessage(buf=get_data_msg_bytes)
        self.assertEqual(2, get_data_msg.count())
        self.assertIn((InventoryType.MSG_TX, seen_block_hash), get_data_msg)
        self.assertIn((InventoryType.MSG_BLOCK, not_seen_block_hash),
                      get_data_msg)
Exemple #8
0
 def _create_inv_msg(self):
     return InvBtcMessage(magic=123,
                          inv_vects=[(InventoryType.MSG_TX, self.tx_hash),
                                     (InventoryType.MSG_BLOCK,
                                      self.block_hash)])
Exemple #9
0
 def build_block_header_message(
         self, block_hash: Sha256Hash,
         block_message: BlockBtcMessage) -> InvBtcMessage:
     return InvBtcMessage(block_message.magic(),
                          [(InventoryType.MSG_BLOCK, block_hash)])