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)
Esempio n. 2
0
    def getblockheader(self, block_hash, verbose=False):
        """Get block header <block_hash>

        verbose - If true a dict is returned with the values returned by
                  getblockheader that are not in the block header itself
                  (height, nextblockhash, etc.)

        Raises IndexError if block_hash is not valid.
        """
        try:
            block_hash = b2lx(block_hash)
        except TypeError:
            raise TypeError('%s.getblockheader(): block_hash must be bytes; got %r instance' %
                    (self.__class__.__name__, block_hash.__class__))
        try:
            r = self._call('getblockheader', block_hash, verbose)
        except InvalidAddressOrKeyError as ex:
            raise IndexError('%s.getblockheader(): %s (%d)' %
                    (self.__class__.__name__, ex.error['message'], ex.error['code']))

        if verbose:
            nextblockhash = None
            if 'nextblockhash' in r:
                nextblockhash = lx(r['nextblockhash'])
            return {'confirmations':r['confirmations'],
                    'height':r['height'],
                    'mediantime':r['mediantime'],
                    'nextblockhash':nextblockhash,
                    'chainwork':x(r['chainwork'])}
        else:
            return CBlockHeader.deserialize(unhexlify(r))
Esempio n. 3
0
    def getblockheader(self, block_hash, verbose=False):
        """Get block header <block_hash>

        verbose - If true a dict is returned with the values returned by
                  getblockheader that are not in the block header itself
                  (height, nextblockhash, etc.)

        Raises IndexError if block_hash is not valid.
        """
        try:
            block_hash = b2lx(block_hash)
        except TypeError:
            raise TypeError(
                '%s.getblockheader(): block_hash must be bytes; got %r instance'
                % (self.__class__.__name__, block_hash.__class__))
        try:
            r = self._call('getblockheader', block_hash, verbose)
        except InvalidAddressOrKeyError as ex:
            raise IndexError('%s.getblockheader(): %s (%d)' %
                             (self.__class__.__name__, ex.error['message'],
                              ex.error['code']))

        if verbose:
            nextblockhash = None
            if 'nextblockhash' in r:
                nextblockhash = lx(r['nextblockhash'])
            return {
                'confirmations': r['confirmations'],
                'height': r['height'],
                'mediantime': r['mediantime'],
                'nextblockhash': nextblockhash,
                'chainwork': x(r['chainwork'])
            }
        else:
            return CBlockHeader.deserialize(unhexlify(r))
Esempio n. 4
0
 def _commit_block(self, height, block_id, hash_of_previous, bits, timestamp, target):
     cursor = self.db.cursor()
     cursor.execute('''SELECT totalWork FROM blocks WHERE height=?''', (height-1,))
     total_work = cursor.fetchone()[0] + CBlockHeader.calc_difficulty(bits)
     cursor = self.db.cursor()
     cursor.execute('''INSERT INTO blocks(totalWork, height, blockID, hashOfPrevious, timestamp, target) VALUES (?,?,?,?,?,?)''',
                    (total_work, height, block_id, hash_of_previous, timestamp, target))
     self.db.commit()
     self._cull()
Esempio n. 5
0
def header_from_insight_block(d):
    version = int(d['version'])
    prev_block = lx(d['previousblockhash'])
    merkle_root = lx(d['merkleroot'])
    time = int(d['time'])
    bits = int(d['bits'], 16)
    nonce = int(d['nonce'])
    return b2x(
        CBlockHeader(version, prev_block, merkle_root, time, bits,
                     nonce).serialize())
Esempio n. 6
0
 def get_header(self):
     """Return the block header
     Returned header is a new object.
     """
     return CBlockHeader(nVersion=self.nVersion,
                         hashPrevBlock=self.hashPrevBlock,
                         hashMerkleRoot=self.hashMerkleRoot,
                         nTime=self.nTime,
                         nBits=self.nBits,
                         nNonce=self.nNonce)
Esempio n. 7
0
    def deserialize(self, raw):
        """Deserialize hex-encoded block/block header."""
        only_header = False
        if len(raw) == 160:
            only_header = True

        block = None
        block_header = None

        try:
            if only_header:
                block_header = CBlockHeader.deserialize(x(raw))
            else:
                # We don't use block.get_header() in case the header is
                # correct but the rest of the block isn't.
                block_header = CBlockHeader.deserialize(x(raw[0:160]))
                block = CBlock.deserialize(x(raw))
        except Exception:
            pass

        return (block, block_header)
Esempio n. 8
0
    def deserialize(self, raw):
        """Deserialize hex-encoded block/block header."""
        only_header = False
        if len(raw) == 160:
            only_header = True

        block = None
        block_header = None

        try:
            if only_header:
                block_header = CBlockHeader.deserialize(x(raw))
            else:
                # We don't use block.get_header() in case the header is
                # correct but the rest of the block isn't.
                block_header = CBlockHeader.deserialize(x(raw[0:160]))
                block = CBlock.deserialize(x(raw))
        except Exception:
            pass

        return (block, block_header)
Esempio n. 9
0
 def get_block_header(self,
                      block_hash: bytes,
                      verbose: bool = False) -> CBlockHeader:
     payload = {
         "method": "getblockheader",
         "params": [block_hash.hex(), verbose],
         "jsonrpc": "2.0",
         "id": 0,
     }
     json_response = self.make_request(payload)
     result = json_response["result"]
     header_bytes = bytes.fromhex(result)
     return CBlockHeader.deserialize(header_bytes)
Esempio n. 10
0
 def _commit_block(self, height, block_id, hash_of_previous, bits,
                   timestamp, target):
     cursor = self.db.cursor()
     cursor.execute('''SELECT totalWork FROM blocks WHERE height=?''',
                    (height - 1, ))
     total_work = cursor.fetchone()[0] + CBlockHeader.calc_difficulty(bits)
     cursor = self.db.cursor()
     cursor.execute(
         '''INSERT INTO blocks(totalWork, height, blockID, hashOfPrevious, timestamp, target) VALUES (?,?,?,?,?,?)''',
         (total_work, height, block_id, hash_of_previous, timestamp,
          target))
     self.db.commit()
     self._cull()
Esempio n. 11
0
    def getblockheader(self, block_hash):
        """Get block header <block_hash>

        Raises IndexError if block_hash is not valid.
        """
        try:
            block_hash = b2lx(block_hash)
        except TypeError:
            raise TypeError('%s.getblockheader(): block_hash must be bytes; got %r instance' %
                    (self.__class__.__name__, block_hash.__class__))
        try:
            r = self._call('getblockheader', block_hash, False)
        except JSONRPCError as ex:
            raise IndexError('%s.getblockheader(): %s (%d)' %
                    (self.__class__.__name__, ex.error['message'], ex.error['code']))
        return CBlockHeader.deserialize(unhexlify(r))
Esempio n. 12
0
    def getblockheader(self, block_hash):
        """Get block header <block_hash>

        Raises IndexError if block_hash is not valid.
        """
        try:
            block_hash = b2lx(block_hash)
        except TypeError:
            raise TypeError(
                '%s.getblockheader(): block_hash must be bytes; got %r instance'
                % (self.__class__.__name__, block_hash.__class__))
        try:
            r = self._call('getblockheader', block_hash, False)
        except JSONRPCError as ex:
            raise IndexError('%s.getblockheader(): %s (%d)' %
                             (self.__class__.__name__, ex.error['message'],
                              ex.error['code']))
        return CBlockHeader.deserialize(unhexlify(r))
Esempio n. 13
0
    def getblockheader(self, block_hash):
        """Get block header <block_hash>

        Raises IndexError if block_hash is not valid.

        There's no getblockheader RPC command, so it actually calls getblock
        but only deserializes the first 80 bytes.
        """
        try:
            block_hash = b2lx(block_hash)
        except TypeError:
            raise TypeError('%s.getblock(): block_hash must be bytes; got %r instance' %
                    (self.__class__.__name__, block_hash.__class__))
        try:
            r = self._call('getblock', block_hash, False)
        except JSONRPCException as ex:
            raise IndexError('%s.getblockheader(): %s (%d)' %
                    (self.__class__.__name__, ex.error['message'], ex.error['code']))
        return CBlockHeader.deserialize(unhexlify(r[0:80*2]))
Esempio n. 14
0
    def getblockheader(self, block_hash):
        """Get block header <block_hash>

        Raises IndexError if block_hash is not valid.

        There's no getblockheader RPC command, so it actually calls getblock
        but only deserializes the first 80 bytes.
        """
        try:
            block_hash = b2lx(block_hash)
        except TypeError:
            raise TypeError(
                '%s.getblock(): block_hash must be bytes; got %r instance' %
                (self.__class__.__name__, block_hash.__class__))
        try:
            r = self._call('getblock', block_hash, False)
        except JSONRPCException as ex:
            raise IndexError('%s.getblockheader(): %s (%d)' %
                             (self.__class__.__name__, ex.error['message'],
                              ex.error['code']))
        return CBlockHeader.deserialize(unhexlify(r[0:80 * 2]))
Esempio n. 15
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 setUp(self):
        self.first_block_chain_a = Block(None, BlockOrigin.private)
        self.first_block_chain_a.height = 1
        self.first_block_chain_a.prevBlock = test_util.genesis_block
        self.first_block_chain_a.cached_hash = '1a'
        self.first_block_chain_a.cblock_header = CBlockHeader(nNonce=11)
        self.first_block_chain_a.cblock = CBlock(nNonce=11)

        self.second_block_chain_a = Block(None, BlockOrigin.private)
        self.second_block_chain_a.height = 2
        self.second_block_chain_a.prevBlock = self.first_block_chain_a
        self.second_block_chain_a.cached_hash = '2a'
        self.second_block_chain_a.cblock_header = CBlockHeader(nNonce=21)
        self.second_block_chain_a.cblock = CBlock(nNonce=21)

        self.third_a_block_chain_a = Block(None, BlockOrigin.private)
        self.third_a_block_chain_a.height = 3
        self.third_a_block_chain_a.prevBlock = self.second_block_chain_a
        self.third_a_block_chain_a.cached_hash = '3a_1'
        self.third_a_block_chain_a.cblock_header = CBlockHeader(nNonce=311)
        self.third_a_block_chain_a.cblock = CBlock(nNonce=311)

        self.third_b_block_chain_a = Block(None, BlockOrigin.private)
        self.third_b_block_chain_a.height = 3
        self.third_b_block_chain_a.prevBlock = self.second_block_chain_a
        self.third_b_block_chain_a.cached_hash = '3a_2'
        self.third_b_block_chain_a.cblock_header = CBlockHeader(nNonce=312)
        self.third_b_block_chain_a.cblock = CBlock(nNonce=312)

        self.fourth_block_chain_a = Block(None, BlockOrigin.private)
        self.fourth_block_chain_a.height = 4
        self.fourth_block_chain_a.prevBlock = self.third_a_block_chain_a
        self.fourth_block_chain_a.cached_hash = '4a'
        self.fourth_block_chain_a.cblock_header = CBlockHeader(nNonce=41)
        self.fourth_block_chain_a.cblock = CBlock(nNonce=41)

        self.first_block_chain_b = Block(None, BlockOrigin.public)
        self.first_block_chain_b.height = 1
        self.first_block_chain_b.prevBlock = test_util.genesis_block
        self.first_block_chain_b.cached_hash = '1b'
        self.first_block_chain_b.cblock_header = CBlockHeader(nNonce=12)
        self.first_block_chain_b.cblock = CBlock(nNonce=12)

        self.second_block_chain_b = Block(None, BlockOrigin.public)
        self.second_block_chain_b.height = 2
        self.second_block_chain_b.prevBlock = self.first_block_chain_b
        self.second_block_chain_b.cached_hash = '2b'
        self.second_block_chain_b.cblock_header = CBlockHeader(nNonce=22)
        self.second_block_chain_b.cblock = CBlock(nNonce=22)

        self.third_a_block_chain_b = Block(None, BlockOrigin.public)
        self.third_a_block_chain_b.height = 3
        self.third_a_block_chain_b.prevBlock = self.second_block_chain_b
        self.third_a_block_chain_b.cached_hash = '3b_1'
        self.third_a_block_chain_b.cblock_header = CBlockHeader(nNonce=321)
        self.third_a_block_chain_b.cblock = CBlock(nNonce=321)

        self.third_b_block_chain_b = Block(None, BlockOrigin.public)
        self.third_b_block_chain_b.height = 3
        self.third_b_block_chain_b.prevBlock = self.second_block_chain_b
        self.third_b_block_chain_b.cached_hash = '3b_2'
        self.third_b_block_chain_b.cblock_header = CBlockHeader(nNonce=322)
        self.third_b_block_chain_b.cblock = CBlock(nNonce=322)

        self.fourth_block_chain_b = Block(None, BlockOrigin.public)
        self.fourth_block_chain_b.height = 4
        self.fourth_block_chain_b.prevBlock = self.third_a_block_chain_b
        self.fourth_block_chain_b.cached_hash = '4b'
        self.fourth_block_chain_b.cblock_header = CBlockHeader(nNonce=42)
        self.fourth_block_chain_b.cblock = CBlock(nNonce=42)
Esempio n. 17
0
def block_header(block_header_bytes):
    yield CBlockHeader.deserialize(block_header_bytes)
Esempio n. 18
0
	def connect(self):
		self.send_lock.acquire()
		self.recv_transaction_cache = FlaggedArraySet(1000)
		self.send_transaction_cache = FlaggedArraySet(1000)
		self.relay_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.relay_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
		try:
			try:
				self.relay_sock.connect((self.server, 8336))
				self.relay_sock.sendall(pack('>3I', self.MAGIC_BYTES, self.VERSION_TYPE, len(self.VERSION_STRING)))
				self.relay_sock.sendall(self.VERSION_STRING)
			finally:
				self.send_lock.release()

			while True:
				msg_header = unpack('>3I', self.relay_sock.recv(3 * 4, socket.MSG_WAITALL))
				if msg_header[0] != self.MAGIC_BYTES:
					raise ProtocolError("Invalid magic bytes: " + str(msg_header[0]) + " != " +  str(self.MAGIC_BYTES))
				if msg_header[2] > 1000000:
					raise ProtocolError("Got message too large: " + str(msg_header[2]))

				if msg_header[1] == self.VERSION_TYPE:
					version = self.relay_sock.recv(msg_header[2], socket.MSG_WAITALL)
					if version != self.VERSION_STRING:
						raise ProtocolError("Got back unknown version type " + str(version))
					print("Connected to relay node with protocol version " + str(version))
				elif msg_header[1] == self.BLOCK_TYPE:
					if msg_header[2] > 10000:
						raise ProtocolError("Got a BLOCK message with far too many transactions: " + str(msg_header[2]))

					wire_bytes = 3 * 4

					header_data = self.relay_sock.recv(80, socket.MSG_WAITALL)
					wire_bytes += 80
					self.data_recipient.provide_block_header(header_data)
					if deserialize_utils:
						header = CBlockHeader.deserialize(header_data)
						print("Got block header: " + str(b2lx(header.GetHash())))

					if msg_header[2] < 0xfd:
						block_data = header_data + pack('B', msg_header[2])
					elif msg_header[2] < 0xffff:
						block_data = header_data + b'\xfd' + pack('<H', msg_header[2])
					elif msg_header[2] < 0xffffffff:
						block_data = header_data + b'\xfe' + pack('<I', msg_header[2])
					else:
						raise ProtocolError("WTF?????")

					for i in range(0, msg_header[2]):
						index = unpack('>H', self.relay_sock.recv(2, socket.MSG_WAITALL))[0]
						wire_bytes += 2
						if index == 0xffff:
							data_length = unpack('>HB', self.relay_sock.recv(3, socket.MSG_WAITALL))
							wire_bytes += 3
							data_length = data_length[0] << 8 | data_length[1]
							if data_length > 1000000:
								raise ProtocolError("Got in-block transaction of size > MAX_BLOCK_SIZE: " + str(dat_length))
							transaction_data = self.relay_sock.recv(data_length, socket.MSG_WAITALL)
							wire_bytes += data_length
							if deserialize_utils:
								transaction = CTransaction.deserialize(transaction_data)
								print("Got in-block full transaction: " + str(b2lx(transaction.GetHash())) + " of length " + str(data_length))
							else:
								print("Got in-block full transaction of length " + str(data_length))
							block_data += transaction_data
						else:
							transaction_data = self.recv_transaction_cache.get_by_index(index)
							if transaction_data is None:
								raise ProtocolError("Got index for a transaction we didn't have")
							self.recv_transaction_cache.remove(transaction_data)
							block_data += transaction_data

					self.data_recipient.provide_block(block_data)

					if deserialize_utils:
						print("Got full block " + str(b2lx(header.GetHash())) + " with " + str(msg_header[2]) + " transactions in " + str(wire_bytes) + " wire bytes")
						block = CBlock.deserialize(block_data)
						print("Deserialized full block " + str(b2lx(block.GetHash())))
					else:
						print("Got full block with " + str(msg_header[2]) + " transactions in " + str(wire_bytes) + " wire bytes")

					if unpack('>3I', self.relay_sock.recv(3 * 4, socket.MSG_WAITALL)) != (self.MAGIC_BYTES, self.END_BLOCK_TYPE, 0):
						raise ProtocolError("Invalid END_BLOCK message after block")

				elif msg_header[1] == self.TRANSACTION_TYPE:
					if msg_header[2] > self.MAX_RELAY_TRANSACTION_BYTES and (self.recv_transaction_cache.get_flag_count() >= self.MAX_EXTRA_OVERSIZE_TRANSACTIONS or msg_header[2] > self.MAX_RELAY_OVERSIZE_TRANSACTION_BYTES):
						raise ProtocolError("Got a freely relayed transaction too large (" + str(msg_header[2]) + ") bytes")
					transaction_data = self.relay_sock.recv(msg_header[2], socket.MSG_WAITALL)
					self.recv_transaction_cache.add(transaction_data, msg_header[2] > self.MAX_RELAY_OVERSIZE_TRANSACTION_BYTES)

					self.data_recipient.provide_transaction(transaction_data)

					if deserialize_utils:
						transaction = CTransaction.deserialize(transaction_data)
						print("Got transaction: " + str(b2lx(transaction.GetHash())))
					else:
						print("Got transaction of length " + str(msg_header[2]))

				elif msg_header[1] == self.MAX_VERSION_TYPE:
					version = self.relay_sock.recv(msg_header[2], socket.MSG_WAITALL)
					print("Relay network now uses version " + str(version) + " (PLEASE UPGRADE)")

				else:
					raise ProtocolError("Unknown message type: " + str(msg_header[1]))

		except (OSError, socket.error) as err:
			print("Lost connect to relay node:", err)
			self.reconnect()
		except ProtocolError as err:
			print("Error processing data from relay node:", err)
			self.reconnect()
		except Exception as err:
			print("Unknown error processing data from relay node:", err)
			self.reconnect()
    def difficulty(self):
        """Returns the block's difficulty target as a float"""
        if self._difficulty is None:
            self._difficulty = CBlockHeader.calc_difficulty(self.bits)

        return self._difficulty
Esempio n. 20
0
def gen_block_header(block_height):
    return CBlockHeader(
        nTime=block_height * 10,  # So that block times are increasing.
    )
    def difficulty(self):
        """Returns the block's difficulty target as a float"""
        if self._difficulty is None:
            self._difficulty = CBlockHeader.calc_difficulty(self.bits)

        return self._difficulty