Example #1
0
 def check_pow(self):
     """Returns whether this block satisfies proof of work"""
     # get the hash256 of the serialization of this block
     block_hash = hash256(self.serialize())
     # interpret this hash as a little-endian number
     proof = little_endian_to_int(block_hash)
     # return whether this integer is less than the target
     return proof < self.target()
Example #2
0
    def parse(cls, stream):
        """Takes a byte stream and parses the block header at the start
        return a Block object
        """

        # version is an integer in 4 bytes, little-endian
        version = little_endian_to_int(stream.read(4))
        # previous block is a 32 bytes little-endian reversed with [::-1]
        prev_block = stream.read(32)[::-1]
        # merkle root is a 32 bytes little-endian reversed with [::-1]
        merkle_root = stream.read(32)[::-1]
        # timestamp is an integer in 4 bytes, little-endian,
        timestamp = little_endian_to_int(stream.read(4))
        # bits is a 4 bytes
        bits = stream.read(4)
        # nonce is a 4 bytes
        nonce = stream.read(4)

        return cls(version, prev_block, merkle_root, timestamp, bits, nonce)
Example #3
0
    def parse(cls, s):
        version = little_endian_to_int(s.read(4))
        services = little_endian_to_int(s.read(8))
        timestamp = little_endian_to_int(s.read(8))
        receiver_services = little_endian_to_int(s.read(8))
        receiver_ip = s.read(16).strip(b"\x00").strip(b"\xff")
        receiver_port = int.from_bytes(s.read(2), "big")

        sender_services = little_endian_to_int(s.read(8))
        sender_ip = s.read(16).strip(b"\x00").strip(b"\xff")
        sender_port = int.from_bytes(s.read(2), "big")
        nonce = s.read(8)
        user_agent_len = read_varint(s)
        user_agent = s.read(user_agent_len)
        latest_block = little_endian_to_int(s.read(4))
        relay = s.read(1) == b"\x01"

        return cls(
            version,
            services,
            timestamp,
            receiver_services,
            receiver_ip,
            receiver_port,
            sender_services,
            sender_ip,
            sender_port,
            nonce,
            user_agent,
            latest_block,
            relay,
        )
Example #4
0
 def parse(cls, s):
     """Takes a byte stream and parses a merkle block. Returns a Merkle Block object"""
     # version - 4 bytes, Little-Endian integer
     version = little_endian_to_int(s.read(4))
     # prev_block - 32 bytes (use [::-1])
     prev_block = s.read(32)[::-1]
     # merkle_root - 32 bytes (use [::-1])
     merkle_root = s.read(32)[::-1]
     # timestamp - 4 bytes, Little-Endian integer
     timestamp = little_endian_to_int(s.read(4))
     # bits - 4 bytes
     bits = s.read(4)
     # nonce - 4 bytes
     nonce = s.read(4)
     # total transactions in block - 4 bytes, Little-Endian integer
     total = little_endian_to_int(s.read(4))
     # number of transaction hashes - varint
     num_hashes = read_varint(s)
     # each transaction is 32 bytes, Little-Endian
     hashes = []
     for _ in num_hashes:
         hashes.append(little_endian_to_int(s.read(32)[::-1]))
     # length of flags field - varint
     flags_length = read_varint(s)
     # read the flags field
     flags = s.read(flags_length)
     # initialize class
     return cls(
         version,
         prev_block,
         merkle_root,
         timestamp,
         bits,
         nonce,
         total,
         hashes,
         flags,
     )
Example #5
0
    def parse(cls, s, testnet=False):
        """Takes a stream and creates a NetworkEnvelope"""
        # First 4 bytes are the network magic
        magic = s.read(4)
        if magic == b"":
            raise IOError("Connection reset!")
        if testnet:
            expected_magic = TESTNET_NETWORK_MAGIC
        else:
            expected_magic = NETWORK_MAGIC
        if magic != expected_magic:
            raise SyntaxError(
                "magic is not right {} vs {}".format(magic.hex(), expected_magic.hex())
            )

        # next 12 bytes are the command field
        # more details about each commands https://en.bitcoin.it/wiki/Protocol_documentation
        command = s.read(12)
        # remove trailing x00 bytes from command
        command = command.strip(b"\x00")

        # 4 bytes payload length in little endian
        payload_length = little_endian_to_int(s.read(4))

        # 4 bytes payload checksum first 4 bytes of hash256 of the payload
        payload_checksum = s.read(4)

        # payload
        payload = s.read(payload_length)

        # get first 4 bytes of the payload hash256
        calculated_checksum = hash256(payload)[:4]

        # check if the first 4 bytes hash256 of the payload match the checksum
        if calculated_checksum != payload_checksum:
            raise IOError("checksum does not match")
        return cls(command, payload, testnet=testnet)