コード例 #1
0
def padded_varint_serializations_test() -> None:
    for _ in range(500):
        num: int = randint(0, 2**16)

        var_int: bytes = to_var_int(num)
        length: int = len(var_int)

        rpc_var_int: bytes = to_rpc_var_int(num)
        rpc_length: int = len(rpc_var_int)

        before: int = randint(0, 32)
        for i in range(before):
            var_int = bytes([randint(0, 255)]) + var_int
            rpc_var_int = bytes([randint(0, 255)]) + rpc_var_int
        for i in range(randint(0, 32)):
            var_int += bytes([randint(0, 255)])
            rpc_var_int += bytes([randint(0, 255)])

        res: Tuple[int, int] = from_var_int(var_int, before)
        assert res[0] == num
        assert res[1] == before + length

        rpc_res: Tuple[int, int] = from_rpc_var_int(rpc_var_int, before)
        assert res[0] == num
        assert res[1] == before + length
コード例 #2
0
    def __init__(self, tx_hash: bytes, json: Dict[str, Any]) -> None:
        """Constructor."""

        # Hash.
        self.tx_hash: bytes = tx_hash

        # Unlock time.
        self.unlock_time: int = json["unlock_time"]

        # Parse the inputs.
        self.inputs: List[AbstractInput] = []
        if "gen" in json["vin"][0]:
            self.inputs.append(MinerInput(json["vin"][0]["gen"]["height"]))
        else:
            for i in range(len(json["vin"])):
                self.inputs.append(
                    Input(
                        json["vin"][i]["key"]["key_offsets"],
                        bytes.fromhex(json["vin"][i]["key"]["k_image"]),
                    ))

        # Parse the outputs.
        self.outputs: List[AbstractOutput] = []
        for o in range(len(json["vout"])):
            if "gen" in json["vin"][0]:
                self.outputs.append(
                    MinerOutput(
                        bytes.fromhex(json["vout"][o]["target"]["key"]),
                        json["vout"][o]["amount"],
                    ))
            else:
                self.outputs.append(
                    Output(
                        bytes.fromhex(json["vout"][o]["target"]["key"]),
                        bytes.fromhex(
                            json["rct_signatures"]["ecdhInfo"][o]["amount"]),
                        bytes.fromhex(json["rct_signatures"]["outPk"][o]),
                    ))

        # Parse extra.
        self.extra: bytes = bytes(json["extra"])

        self.Rs: List[bytes] = []
        self.payment_IDs: List[bytes] = []

        def skip_tag(cursor: int) -> int:
            tag_or_length: Tuple[int, int] = from_var_int(self.extra, cursor)
            cursor = tag_or_length[1]
            tag_or_length = from_var_int(self.extra, cursor)
            cursor = tag_or_length[1] + tag_or_length[0]
            return cursor

        def check_R(R: bytes) -> bool:
            if len(R) != 32:
                return False
            # This originally also called decodepoint which then calls isoncurve.
            # It always errored, even with valid Rs.
            return True

        try:
            cursor: int = 0
            while cursor < len(self.extra):
                tag: Tuple[int, int] = from_var_int(self.extra, cursor)
                cursor = tag[1]

                # TX_EXTRA_TAG_PADDING
                if tag[0] == 0x00:
                    cursor += 8 + int.from_bytes(self.extra[cursor:cursor + 8],
                                                 byteorder="little")

                # TX_EXTRA_TAG_PUBKEY
                elif tag[0] == 0x01:
                    potential_R: bytes = self.extra[cursor:cursor + 32]
                    if not check_R(potential_R):
                        break

                    self.Rs.append(potential_R)
                    cursor += 32

                # TX_EXTRA_NONCE
                elif tag[0] == 0x02:
                    length: Tuple[int, int] = from_var_int(self.extra, cursor)
                    cursor = length[1]
                    end: int = cursor + length[0]

                    while cursor + 9 <= end:
                        # Unencrypted payment IDs are a 1-byte header and 32-byte value.
                        # Encrypted payment IDs are a 1-byte header and 8-byte value.

                        # TX_EXTRA_NONCE_PAYMENT_ID
                        if self.extra[cursor] == 0x00:
                            self.payment_IDs.append(self.extra[cursor +
                                                               1:cursor + 33])
                            cursor += 33
                            continue
                        # TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID
                        if self.extra[cursor] == 0x01:
                            self.payment_IDs.append(self.extra[cursor +
                                                               1:cursor + 9])
                            cursor += 9
                        else:
                            break

                    cursor = end

                # TX_EXTRA_TAG_ADDITIONAL_PUBKEYS
                elif tag[0] == 0x04:
                    keys: Tuple[int, int] = from_var_int(self.extra, cursor)
                    cursor = keys[1]

                    for _ in range(keys[0]):
                        potential_R: bytes = self.extra[cursor:cursor + 32]
                        if not check_R(potential_R):
                            break

                        self.Rs.append(potential_R)
                        cursor += 32

                # TX_EXTRA_MERGE_MINING_TAG, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG
                elif (tag[0] == 0x03) or (tag[0] == tag[0] == 0xDE):
                    cursor = skip_tag(cursor)

                else:
                    break
        except IndexError:
            pass

        # Remove duplicate Rs.
        # This isn't necessarily secure due to the existence of torsion points, where effectively duplicate Rs can remain.
        # It must be partnered with a check if we already found an output was spendable.
        # Since that check would be comprehensive, this is effectively an optimization.
        self.Rs = list(set(self.Rs))
        # Remove duplicate payment IDs.
        self.payment_IDs = list(set(self.payment_IDs))
コード例 #3
0
 def skip_tag(cursor: int) -> int:
     tag_or_length: Tuple[int, int] = from_var_int(self.extra, cursor)
     cursor = tag_or_length[1]
     tag_or_length = from_var_int(self.extra, cursor)
     cursor = tag_or_length[1] + tag_or_length[0]
     return cursor
コード例 #4
0
def varint_serializations_test() -> None:
    for _ in range(500):
        num: int = randint(0, 2**16)
        assert from_var_int(to_var_int(num), 0)[0] == num
        assert from_rpc_var_int(to_rpc_var_int(num), 0)[0] == num