Beispiel #1
0
    def handle_msg(self, msg_name, msg_data):
        """
        This method must be invoked for each message that comes from the peer
        (or at least, those of type tx, block, merkleblock and notfound).
        It resolves the appropriate futures and handles the messy merkleblock
        message (where a the given list of transactions are automatically sent
        after the merkleblock message is sent).

        The "merkleblock" item is augmented with .tx_futures that can be
        waited on.
        """
        if msg_name is None:
            self._is_closed = True
            for f in self._futures.values():
                if not f.done():
                    f.set_exception(EOFError())
        if msg_name in self.ITEM_LOOKUP:
            item = msg_data[self.ITEM_LOOKUP[msg_name]]
            the_hash = item.hash()
            the_type = self.TYPE_DB[msg_name]
            inv_item = InvItem(the_type, the_hash)
            future = self._futures.get(inv_item)
            if future is None:
                return
            if msg_name == "merkleblock":
                # we now expect a bunch of tx messages
                tx_inv_items = [
                    InvItem(ITEM_TYPE_TX, h) for h in msg_data["tx_hashes"]
                ]
                # create futures for items
                # we don't need to add them to the request queue since
                # they're supposed to be sent next anyway
                item.tx_futures = [
                    self._future_for_inv_item(inv_item)
                    for inv_item in tx_inv_items
                ]
                # we need to keep the futures around so they're not automatically
                # garbage collected, as they're kept in a WeakValueDictionary
                # so they're jammed into the item (which is a merkleblock).
                # Once the item is gone, we don't care about the futures anyway.
            if not future.done():
                future.set_result(item)
        if msg_name == "notfound":
            for inv_item in msg_data["items"]:
                the_hash = inv_item.data
                future = self._futures.get(inv_item)
                if future is not None:
                    # we don't need to delete the future since it should
                    # be garbage collected, but hey, why not
                    del self._futures[inv_item]
                    future.set_result(None)
Beispiel #2
0
 def handle_block_event(self, peer, name, data):
     block = data["block" if name == "block" else "header"]
     block_hash = block.hash()
     if name == "block":
         inv_item = InvItem(ITEM_TYPE_BLOCK, block_hash)
     elif name == "header":
         inv_item = InvItem(ITEM_TYPE_MERKLEBLOCK, block_hash)
     else:
         raise ValueError(peer, name, data)
     if str(inv_item) in self._inv_item_hash_to_future:
         f = self._inv_item_hash_to_future[str(inv_item)]
         if not f.done():
             f.set_result(block)
     else:
         logger.warning("missing future for block %s", block.id())
Beispiel #3
0
 async def get_block(self, blockhash: str, peers=None, timeout=None, privileged_peers=False) -> Dict:
     inv_item = InvItem(ITEM_TYPE_SEGWIT_BLOCK, h2b_rev(blockhash))
     response = await self.pool.get(inv_item, peers=peers, timeout=timeout, privileged=privileged_peers)
     return response and {
         "block_hash": str(blockhash),
         "header_bytes": response[:80],
         "block_bytes": response
     }
Beispiel #4
0
 async def get_block(self, blockhash: str, peers=None, timeout=None) -> Dict:
     inv_item = InvItem(ITEM_TYPE_SEGWIT_BLOCK, h2b_rev(blockhash))
     response = await self.pool.get(inv_item, peers=peers, timeout=timeout)
     return response and {
         "block_hash": str(response.hash()),
         "prev_block_hash": str(response.previous_block_hash),
         "timestamp": int(response.timestamp),
         "header_bytes": bytes(response.as_blockheader().as_bin()),
         "block_object": response,
         "block_bytes": bytes(response.as_bin())
     }
 async def get_block(self,
                     blockhash: str,
                     peers=None,
                     timeout=None,
                     privileged_peers=False,
                     segwit=True) -> Dict:
     Logger.p2p.debug('Downloading block %s' % blockhash)
     block_type = segwit and ITEM_TYPE_SEGWIT_BLOCK or ITEM_TYPE_BLOCK
     inv_item = InvItem(block_type, h2b_rev(blockhash))
     response = await self.pool.get(inv_item,
                                    peers=peers,
                                    timeout=timeout,
                                    privileged=privileged_peers)
     return response and {
         "block_hash": str(blockhash),
         "header_bytes": response[:80],
         "block_bytes": response
     }