def getblocks(self, message): blkmeta = self.chaindb.locate(message.locator) height = blkmeta.height top_height = self.getheight() end_height = height + 500 if end_height > top_height: end_height = top_height msg = messages.msg_inv() while height <= end_height: hash = long(self.chaindb.height[str(height)]) if hash == message.hashstop: break inv = net.CInv() inv.type = messages.MSG_BLOCK inv.hash = hash msg.inv.append(inv) height += 1 if len(msg.inv) > 0: self.send_message(msg) if height <= top_height: self.hash_continue = msg.inv[-1].hash
def test_inv_message_msg_unknown(self): inv = net.CInv() inv.type = "Unknown" msg = messages.msg_inv msg.inv = [inv] self.networking.inv_message(self.private_connection, msg) self.assertFalse(self.private_connection.send.called) self.assertFalse(self.public_connection1.send.called) self.assertFalse(self.public_connection2.send.called)
def test_inv_message_msg_error(self): inv = net.CInv() inv.type = networking.inv_typemap['Error'] msg = messages.msg_inv msg.inv = [inv] self.networking.inv_message(self.private_connection, msg) self.assertFalse(self.private_connection.send.called) self.assertFalse(self.public_connection1.send.called) self.assertFalse(self.public_connection2.send.called)
def test_inv_message_msg_tx_known(self): inv = net.CInv() inv.type = networking.inv_typemap['TX'] inv.hash = 'hash1' msg = messages.msg_inv() msg.inv = [inv] self.networking.txs = {inv.hash: 'saved_transaction'} self.networking.inv_message(self.private_connection, msg) self.assertFalse(self.private_connection.send.called) self.assertFalse(self.public_connection1.send.called) self.assertFalse(self.public_connection2.send.called)
def send_getblocks(self): our_height = self.chaindb.getheight() if our_height < 0: gd = messages.msg_getdata(protover=self.ver_send) inv = net.CInv() inv.type = 2 inv.hash = self.params.GENESIS_BLOCK.GetHash() gd.inv.append(inv) self.send_message(gd) elif our_height < self.remote_height: gb = messages.msg_getblocks(protover=self.ver_send) if our_height >= 0: gb.locator.vHave.append(self.chaindb.gettophash()) self.send_message(gb)
def test_inv_message_msg_block_private(self, mock): mock.return_value = ['hash20', 'hash19'] self.networking.request_blocks = MagicMock() inv = net.CInv() inv.hash = 'hash1' inv.type = networking.inv_typemap['Block'] msg = messages.msg_inv msg.inv = [inv] self.networking.inv_message(self.private_connection, msg) self.assertEqual(self.private_connection.send.call_count, 1) self.assertTrue(mock.called) self.assertEqual(self.private_connection.send.call_args_list[0][0][0], 'getheaders')
def test_inv_message_msg_request_block(self, mock): mock.return_value = ['hash20', 'hash19'] self.networking.request_blocks = MagicMock() inv = net.CInv() inv.hash = 'hash1' inv.type = networking.inv_typemap['Block'] msg = messages.msg_inv msg.inv = [inv] self.networking.inv_message(self.private_connection, msg) self.assertTrue(self.networking.request_blocks.called) self.assertEqual(self.networking.request_blocks.call_args[0][0], self.private_connection) self.assertEqual(self.networking.request_blocks.call_args[0][1], ['hash1'])
def getdata_block(self, blkhash): block = self.chaindb.getblock(blkhash) if block is None: return msg = messages.msg_block() msg.block = block self.send_message(msg) if blkhash == self.hash_continue: self.hash_continue = None inv = net.CInv() inv.type = messages.MSG_BLOCK inv.hash = self.chaindb.gettophash() msg = messages.msg_inv() msg.inv.append(inv) self.send_message(msg)
def got_message(self, message): gevent.sleep() if self.last_sent + 30 * 60 < time.time(): self.send_message(messages.msg_ping(self.ver_send)) self.log.debug("recv %s" % repr(message)) if message.command == "version": self.ver_send = min(self.params.PROTO_VERSION, message.nVersion) if self.ver_send < self.params.MIN_PROTO_VERSION: self.log.info("Obsolete version %d, closing" % (self.ver_send, )) self.handle_close() return if (self.ver_send >= self.params.NOBLKS_VERSION_START and self.ver_send <= self.params.NOBLKS_VERSION_END): self.getblocks_ok = False self.remote_height = message.nStartingHeight self.send_message(messages.msg_verack(self.ver_send)) if self.ver_send >= self.params.CADDR_TIME_VERSION: self.send_message(messages.msg_getaddr(self.ver_send)) self.request_latest() self.client_version = message.strSubVer elif message.command == "verack": self.ver_recv = self.ver_send if self.ver_send >= self.params.MEMPOOL_GD_VERSION: self.send_message(messages.msg_mempool()) elif message.command == "ping": if self.ver_send > self.params.BIP0031_VERSION: self.send_message(messages.msg_pong(self.ver_send)) elif message.command == "addr": self.peermgr.new_addrs(message.addrs) elif message.command == "inv": # special message sent to kick getblocks if (len(message.inv) == 1 and message.inv[0].type == messages.MSG_BLOCK and self.chaindb.haveblock(message.inv[0].hash, True)): self.request_latest(False) return want = messages.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) if len(want.inv): self.send_message(want) elif message.command == "tx": if self.chaindb.tx_is_orphan(message.tx): self.log.info("MemPool: Ignoring orphan TX {}".format( message.tx.GetHash().encode('hex'))) elif not self.chaindb.tx_signed(message.tx, None, True): self.log.info("MemPool: Ignoring failed-sig TX {}".format( message.tx.GetHash().encode('hex'))) else: self.mempool.add(message.tx) elif message.command == "block": self.chaindb.putblock(message.block) self.last_block_rx = time.time() elif message.command == "headers": self.chaindb.putblock(message.block) self.last_block_rx = time.time() elif message.command == "getdata": self.getdata(message) elif message.command == "getblocks": self.getblocks(message) elif message.command == "getheaders": self.getheaders(message) elif message.command == "getaddr": msg = messages.msg_addr() msg.addrs = self.peermgr.random_addrs() self.send_message(msg) elif message.command == "mempool": msg = messages.msg_inv() for k in self.mempool.pool.iterkeys(): inv = net.CInv() inv.type = messages.MSG_TX inv.hash = k msg.inv.append(inv) if len(msg.inv) == 50000: break self.send_message(msg) # if we haven't seen a 'block' message in a little while, # and we're still not caught up, send another getblocks last_blkmsg = time.time() - self.last_block_rx if last_blkmsg > 5: self.request_latest()
def hash_to_inv(inv_type, inv_hash): inv = net.CInv() inv.type = inv_typemap[inv_type] inv.hash = inv_hash return inv