def getheaders_message(self, connection, message): self.sync.lock.acquire() try: logging.debug('received getheaders message with {} headers from {}' .format(len(message.locator.vHave), self.repr_connection(connection))) if connection.host[0] == self.private_ip: blocks = chainutil.respond_get_headers(self.chain.tips, BlockOrigin.private, message.locator.vHave, message.hashstop) else: blocks = chainutil.respond_get_headers(self.chain.tips, BlockOrigin.public, message.locator.vHave, message.hashstop) message = messages.msg_headers() message.headers = [core.CBlock(block.cblock.nVersion, block.cblock.hashPrevBlock, block.cblock.hashMerkleRoot, block.cblock.nTime, block.cblock.nBits, block.cblock.nNonce) for block in blocks] connection.send('headers', message) logging.debug('sent headers message with {} headers to {}' .format(len(message.headers), self.repr_connection(connection))) if len(message.headers) > 0: logging.debug('sent headers with starting hash={}'.format(core.b2lx(message.headers[0].GetHash()))) finally: self.sync.lock.release() logging.debug('processed getheaders message from {}'.format(self.repr_connection(connection)))
def test_headers_message_one_block_not_in_flight(self): header1 = CBlockHeader(nNonce=1) header2 = CBlockHeader(nNonce=2) message = messages.msg_headers() message.headers = [header1, header2] self.networking.blocks_in_flight = {header1.GetHash(): 'in_flight'} self.networking.headers_message(self.private_connection, message) self.assertEqual(self.private_connection.send.call_args[0][0], 'getdata') self.assertEqual(len(self.private_connection.send.call_args[0][1].inv), 1)
def test_headers_message_known_blocks(self): cblock1 = CBlock(nNonce=1) block1 = Block(cblock1, None) cblock2 = CBlock(nNonce=2) block2 = Block(cblock2, None) self.chain.blocks = {block1.hash(): block1, block2.hash(): block2} self.networking.request_blocks = MagicMock() message = messages.msg_headers() message.headers = [cblock1.get_header(), cblock2.get_header()] self.networking.headers_message(self.public_connection1, message) self.assertFalse(self.public_connection1.send.called) self.assertFalse(self.chain.process_header.called) self.assertFalse(self.private_connection.send.called) self.assertTrue(self.networking.request_blocks.called) self.assertEqual(len(self.networking.request_blocks.call_args[0][1]), 0)
def test_headers_message_two_unknown_blocks(self): header1 = CBlockHeader(nNonce=1) header2 = CBlockHeader(nNonce=2) message = messages.msg_headers() message.headers = [header1, header2] self.networking.blocks_in_flight = {} self.networking.request_blocks = MagicMock() self.networking.headers_message(self.private_connection, message) self.assertEqual(self.chain.process_header.call_count, 2) self.assertEqual(self.chain.process_header.call_args[0][1], BlockOrigin.private) self.assertTrue(self.networking.request_blocks.called) self.assertEqual(len(self.networking.request_blocks.call_args[0][1]), 2) self.assertIn(header1.GetHash(), self.networking.request_blocks.call_args[0][1]) self.assertIn(header2.GetHash(), self.networking.request_blocks.call_args[0][1])
def getheaders(self, message): blkmeta = self.chaindb.locate(message.locator) height = blkmeta.height top_height = self.getheight() end_height = height + 2000 if end_height > top_height: end_height = top_height msg = messages.msg_headers() while height <= end_height: blkhash = long(self.chaindb.height[str(height)]) if blkhash == message.hashstop: break db_block = self.chaindb.getblock(blkhash) block = copy.copy(db_block) block.vtx = [] msg.headers.append(block) height += 1 self.send_message(msg)
def got_message(self, message): gevent.sleep() if self.last_sent + 30 * 60 < time.time(): self.send_message(msg_ping(self.ver_send)) if verbose_recvmsg(message): self.log.info("recv %s" % repr(message)) if message.command == b"version": self.ver_send = min(PROTO_VERSION, message.nVersion) if self.ver_send < MIN_PROTO_VERSION: self.log.info("Obsolete version %d, closing" % (self.ver_send, )) self.handle_close() return self.remote_height = message.nStartingHeight self.send_message(msg_verack(self.ver_send)) if self.ver_send >= CADDR_TIME_VERSION: self.send_message(msg_getaddr(self.ver_send)) # self.send_getblocks() elif message.command == b'ping': if self.ver_send > BIP0031_VERSION: self.send_message(msg_pong(self.ver_send)) elif message.command == b"verack": self.ver_recv = self.ver_send self.send_message(msg_addr()) self.send_getaddr() elif message.command == b"inv": # special message sent to kick getblocks # if (len(message.inv) == 1 and # message.inv[0].type == MSG_BLOCK and # self.chaindb.haveblock(message.inv[0].hash, True)): # self.send_getblocks(False) # return want = msg_getdata(self.ver_send) for i in message.inv: if i.type == 1: want.inv.append(i) elif i.type == 2: want.inv.append(i) self.last_want = i.hash if len(want.inv): self.send_message(want) # elif message.command == b"block": # bhash = b2lx(message.block.GetHash()) # self.chaindb.putblock(message.block) # self.last_block_rx = time.time() # if self.last_want == 0: # gevent.spawn(self.send_getblocks) # elif bhash == b2lx(self.last_want): # gevent.spawn(self.send_getblocks) elif message.command == b"addr": self.peermgr.new_addrs(message.addrs) for addr in message.addrs: self.peermgr.add(addr.ip, addr.port) elif message.command == b'getheaders': self.send_message(msg_headers())