Ejemplo n.º 1
0
    def test_getdata_message_with_two_blocks(self):
        cblock1 = CBlock()
        block1 = Block(cblock1, BlockOrigin.private)
        block1.cblock = cblock1
        cInv1 = CInv()
        cInv1.type = networking.inv_typemap['Block']
        cInv1.hash = cblock1.GetHash()
        cblock2 = CBlock()
        block2 = Block(cblock2, BlockOrigin.private)
        block2.cblock = cblock2
        cInv2 = CInv()
        cInv2.type = networking.inv_typemap['Block']
        cInv2.hash = cblock2.GetHash()
        message = messages.msg_getdata()
        message.inv = [cInv1, cInv2]

        self.chain.blocks = {
            cblock1.GetHash(): block1,
            cblock2.GetHash(): block2
        }

        self.networking.getdata_message(self.public_connection1, message)

        self.assertTrue(self.public_connection1.send.called)
        self.assertEqual(self.public_connection1.send.call_count, 2)
Ejemplo n.º 2
0
def connection_mock(signed_transaction):
    connection = MagicMock()

    connection.getsockname.return_value = ('127.0.0.1', 8800)
    connection.getpeername.return_value = ('127.0.0.1', 8800)
    connection.getpeername.return_value = ('127.0.0.1', 8800)

    protocol_version = 6002
    version = msg_version(protocol_version).to_bytes()
    verack = msg_verack(protocol_version).to_bytes()

    getdata = msg_getdata(protocol_version)
    getdata = getdata.msg_deser(BytesIO(b'\x01\x01\x00\x00\x00' + signed_transaction.tx.GetHash())).to_bytes()

    connection.recv.side_effect = (
        version + verack,
        getdata,
    )

    capture = BitcoinTestNet.capture_messages

    def capture_messages_mock(*args, **kwargs):
        if msg_reject in args[1]:
            return None
        else:
            return capture(*args, **kwargs)

    with patch('socket.create_connection', return_value=connection):
        with patch('socket.gethostbyname_ex', return_value=(None, None, ['127.0.0.1'])):
            with patch.object(BitcoinTestNet, 'capture_messages', new=capture_messages_mock):
                yield
Ejemplo n.º 3
0
    def request_blocks(self, connection, inv):
        if len(inv) > 0:
            for hash_ in inv:
                self.blocks_in_flight[hash_] = BlockInFlight(hash_, time.time())

            message = messages.msg_getdata()
            message.inv = [hash_to_inv('Block', hash_) for hash_ in inv]
            connection.send('getdata', message)
            logging.info('requested getdata for {} blocks'.format(len(inv)))
Ejemplo n.º 4
0
 def got_message(self, msg):
     if msg.command == 'ping':
         pong = msg_pong(nonce=msg.nonce)
         self.sock.send(pong.to_bytes())
     elif msg.command == 'inv':
         for i in msg.inv:
             # transaction/block/txlrequest/txlvote
             if i.type in (1, 2, 4, 5):
                 gd = msg_getdata()
                 gd.inv.append(i)
                 self.sock.send(gd.to_bytes())
     if msg.command in self.route:
         self.route[msg.command](msg)
Ejemplo n.º 5
0
 def got_message(self, msg):
     if msg.command == 'ping':
         pong = msg_pong(nonce=msg.nonce)
         self.sock.send(pong.to_bytes())
     elif msg.command == 'inv':
         for i in msg.inv:
             # transaction/block/txlrequest/txlvote
             if i.type in (1, 2, 4, 5):
                 gd = msg_getdata()
                 gd.inv.append(i)
                 self.sock.send(gd.to_bytes())
     if msg.command in self.route:
         self.route[msg.command](msg)
Ejemplo n.º 6
0
 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)
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
    def test_getdata_message_without_tx(self):
        message = messages.msg_getdata()
        inv = CInv()
        inv.type = networking.inv_typemap['TX']
        inv.hash = 'hash1'
        message.inv = [inv]

        self.networking.get_tx = MagicMock()
        self.networking.get_tx.return_value = None

        self.networking.getdata_message(self.public_connection1, message)

        self.assertFalse(self.private_connection.send.called)
        self.assertFalse(self.public_connection1.send.called)
        self.assertFalse(self.public_connection2.send.called)
Ejemplo n.º 9
0
    def test_getdata_message_with_unknown_hashes(self):
        message = messages.msg_getdata()
        cInv1 = CInv()
        cInv1.type = networking.inv_typemap['Block']
        cInv1.hash = 'hash1'
        cInv2 = CInv()
        cInv2.type = networking.inv_typemap['Block']
        cInv2.hash = 'hash2'
        message.inv = [cInv1, cInv2]

        self.chain.blocks = {}

        self.networking.getdata_message(self.public_connection1, message)

        self.assertFalse(self.public_connection1.send.called)
Ejemplo n.º 10
0
    def test_getdata_message_cblock_not_available(self):
        cblock = CBlock()
        hash_ = cblock.GetHash()
        block = Block(cblock, BlockOrigin.private)
        message = messages.msg_getdata()
        cInv = CInv()
        cInv.type = networking.inv_typemap['Block']
        cInv.hash = hash_
        message.inv = [cInv]

        self.chain.blocks = {hash_: block}
        self.networking.deferred_block_requests = {}
        self.networking.getdata_message(self.public_connection1, message)

        self.assertFalse(self.public_connection1.called)
        self.assertIn(hash_, self.networking.deferred_block_requests)
        self.assertIn(self.public_connection1.host[0],
                      self.networking.deferred_block_requests[hash_])
Ejemplo n.º 11
0
    def test_getdata_message_with_block(self):
        cblock = CBlock()
        block = Block(cblock, BlockOrigin.private)
        block.cblock = cblock
        message = messages.msg_getdata()
        cInv = CInv()
        cInv.type = networking.inv_typemap['Block']
        cInv.hash = cblock.GetHash()
        message.inv = [cInv]

        self.chain.blocks = {cblock.GetHash(): block}

        self.networking.getdata_message(self.public_connection1, message)

        self.assertTrue(self.public_connection1.send.called)
        self.assertEqual(self.public_connection1.send.call_args[0][0], 'block')
        self.assertEqual(self.public_connection1.send.call_args[0][1].block,
                         cblock)
Ejemplo n.º 12
0
    def send_getblocks(self, timecheck=True):
        if not self.getblocks_ok:
            return
        now = time.time()
        # if timecheck and (now - self.last_getblocks) < 1:
        #     return
        self.last_getblocks = now

        our_height = self.chaindb.getheight()
        if our_height < 0:
            gd = msg_getdata(self.ver_send)
            inv = CInv()
            inv.type = 2
            inv.hash = bitcoin.params.GENESIS_BLOCK.GetHash()
            gd.inv.append(inv)
            self.send_message(gd)
        elif our_height < self.remote_height:
            gb = msg_getblocks(self.ver_send)
            if our_height >= 0:
                gb.locator.vHave = self.chaindb.getlocator()
            self.send_message(gb)
Ejemplo n.º 13
0
 def send_getdata(self):
     start_block_hash = self.parameters_store.get_last_block_analized()
     block_hashes = self.block_chain.get_next_n_blocks_hashes(
         start_block_hash, 5000)
     if len(block_hashes) == 0:
         self.stop_client = True
         print("Analysis ended!")
     self.data_request = len(block_hashes)
     invs = []
     for block_hash in block_hashes:
         inv = CInv()
         '''
         MSG_FILTERED_BLOCK    
         Indicates the reply should be a merkleblock message rather than a block message; 
         this only works if a bloom filter has been set.
         '''
         inv.type = 3
         inv.hash = lx(block_hash)
         invs.append(inv)
     msg = msg_getdata()
     msg.inv = invs
     self.send_message(msg)
Ejemplo n.º 14
0
    def send_getblocks(self, timecheck=True):
        if not self.getblocks_ok:
            return
        now = time.time()
        # if timecheck and (now - self.last_getblocks) < 1:
        #     return
        self.last_getblocks = now

        our_height = self.chaindb.getheight()
        if our_height < 0:
            gd = msg_getdata(self.ver_send)
            inv = CInv()
            inv.type = 2
            inv.hash = lx(
                'cf7938a048f1442dd34f87ce56d3e25455b22a44f676325f1ae8c7a33d0731c7'
            )
            gd.inv.append(inv)
            self.send_message(gd)
        elif our_height < self.remote_height:
            gb = msg_getblocks(self.ver_send)
            if our_height >= 0:
                gb.locator.vHave = self.chaindb.getlocator()
            self.send_message(gb)
Ejemplo n.º 15
0
    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)
                # break #UNDO
                self.last_want = i.hash
            if len(want.inv):
                self.send_message(want)

        elif message.command == b"tx":
            if self.chaindb.tx_is_orphan(message.tx):
                self.log.info("MemPool: Ignoring orphan TX %s" %
                              (b2lx(message.tx.GetHash()), ))
            # elif not self.chaindb.tx_signed(message.tx, None, True):
            #     self.log.info("MemPool: Ignoring failed-sig TX %s" % (b2lx(message.tx.GetHash()),))
            else:
                self.chaindb.mempool_add(message.tx)

        elif message.command == b"block":
            bhash = b2lx(message.block.GetHash())
            self.chaindb.putblock(message.block)
            # b = BytesIO()
            # message.block.stream_serialize(b)
            # s = b.getvalue()
            # print(b2lx(s))
            self.last_block_rx = time.time()
            #UNDO
            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"getheaders":
            self.getheaders(message)
        # elif message.command == b"addr":
        # if len(message.addrs) == 1:
        #     gevent.spawn(self.send_getblocks)
        # for addr in message.addrs:
        #     host = '%s:%s' % (addr.ip, addr.port)
        #     if host not in self.addresses_seen:
        #         self.addresses_seen.append(host)

        # elif message.command == b'tx':
        #      for idx, vout in enumerate(message.tx.vout):
        #         script = vout.scriptPubKey
        #         if len(script) >= 38 and script[:6] == bitcoin.core.WITNESS_COINBASE_SCRIPTPUBKEY_MAGIC:
        #             continue
        #         script = CScript(vout.scriptPubKey)
        #         if script.is_unspendable():
        #             print("Unspendable %s" % vout.scriptPubKey)
        #             if vout.scriptPubKey[:4] == b'j\x07\xfe\xab':
        #                 print(vout.scriptPubKey[4:].decode('utf-8'))
        #             continue

        last_blkmsg = time.time() - self.last_block_rx
        if last_blkmsg > 5:
            self.send_getblocks()
Ejemplo n.º 16
0
    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()
Ejemplo n.º 17
0
    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())
Ejemplo n.º 18
0
    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()