Beispiel #1
0
def sign_transaction(path: Derivation, tx: Transaction):
    INS = 0x04
    P2 = 0x00

    path_construct = PrefixedArray(Byte, Int32ub)
    path_apdu = path_construct.build(path.to_list())

    data = path_apdu + rlp.encode(tx)

    class DeviceResponse(NamedTuple):
        v: int
        r: int
        s: int

    def f(client: LedgerClient) -> DeviceResponse:
        raw_response = bytes()

        for idx, each in enumerate(chunk(data, 255)):
            P1 = 0x00 if idx == 0 else 0x80
            raw_response = client.apdu_exchange(INS, each, P1, P2)

        response_template = Struct(
            v=BytesInteger(1),
            r=BytesInteger(32),
            s=BytesInteger(32),
        )
        parsed_response = response_template.parse(raw_response)

        return DeviceResponse(
            v=parsed_response.v,
            r=parsed_response.r,
            s=parsed_response.s,
        )

    return f
Beispiel #2
0
def get_wallet_public_key(path: Derivation, opts: GetWalletPublicKeyOpts):
    # TODO: support user-validation token

    if opts.scheme is not None and not Scheme.is_member(opts.scheme):
        raise ValueError(f"unrecognized Scheme value: {opts.scheme}")

    INS = 0x40
    P1 = 0x01 if opts.display_address else 0x00
    P2 = opts.scheme.value if opts.scheme is not None else Scheme.P2PKH

    if opts.display_address and path.depth != 5:
        raise ValueError(
            f"cannot derive address at BIP-32 path {path}: invalid depth {path.depth}"
        )

    if opts.scheme is not None and path.depth != 5:
        raise ValueError(
            f"scheme not expected at BIP-32 path {path}: {opts.scheme.name}")

    path_construct = PrefixedArray(Byte, Int32ub)
    path_apdu = path_construct.build(path.to_list())

    data = path_apdu

    class DeviceResponse(NamedTuple):
        public_key: bytes
        address: str
        chain_code: bytes

    def f(client: LedgerClient) -> DeviceResponse:
        response = client.apdu_exchange(INS, data, P1, P2)

        response_template = Struct(
            public_key=Prefixed(Int8ub, GreedyBytes),
            address=PascalString(Int8ub, "ascii"),
            chain_code=Bytes(32),
        )

        parsed_response = response_template.parse(response)
        return DeviceResponse(
            public_key=parsed_response.public_key,
            address=parsed_response.address,
            chain_code=parsed_response.chain_code,
        )

    return f
Beispiel #3
0
def get_eth_public_address(path: Derivation, opts: GetEthPublicAddressOpts):
    INS = 0x02
    P1 = 0x01 if opts.display_address else 0x00
    P2 = 0x01 if opts.return_chain_code else 0x00

    path_construct = PrefixedArray(Byte, Int32ub)
    path_apdu = path_construct.build(path.to_list())

    data = path_apdu

    class DeviceResponse(NamedTuple):
        public_key: bytes
        address: str
        chain_code: Optional[bytes]

    def f(client: LedgerClient) -> DeviceResponse:
        response = client.apdu_exchange(INS, data, P1, P2)

        struct_kwargs = dict(
            public_key=Prefixed(Int8ub, GreedyBytes),
            address=PascalString(Int8ub, "ascii"),
        )
        if opts.return_chain_code:
            struct_kwargs["chain_code"] = Bytes(32)

        response_template = Struct(**struct_kwargs)

        parsed_response = response_template.parse(response)
        return DeviceResponse(
            public_key=parsed_response.public_key,
            address=parsed_response.address,
            chain_code=parsed_response.chain_code
            if opts.return_chain_code else None,
        )

    return f