Example #1
0
async def ethereum_sign_tx(ctx, msg):
    from trezor.crypto.hashlib import sha3_256

    msg = sanitize(msg)
    check(msg)

    data_total = msg.data_length

    # detect ERC - 20 token
    token = None
    recipient = msg.to
    value = int.from_bytes(msg.value, 'big')
    if len(msg.to) == 20 and \
       len(msg.value) == 0 and \
       data_total == 68 and \
       len(msg.data_initial_chunk) == 68 and \
       msg.data_initial_chunk[:16] == b'\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':
        token = tokens.token_by_chain_address(msg.chain_id, msg.to)
        recipient = msg.data_initial_chunk[16:36]
        value = int.from_bytes(msg.data_initial_chunk[36:68], 'big')

    await require_confirm_tx(ctx, recipient, value, msg.chain_id, token)
    if token is None and msg.data_length > 0:
        await require_confirm_data(ctx, msg.data_initial_chunk, data_total)

    await require_confirm_fee(ctx, value, int.from_bytes(msg.gas_price, 'big'),
                              int.from_bytes(msg.gas_limit, 'big'),
                              msg.chain_id, token)

    data = bytearray()
    data += msg.data_initial_chunk
    data_left = data_total - len(msg.data_initial_chunk)

    total_length = get_total_length(msg, data_total)

    sha = HashWriter(sha3_256)
    sha.extend(rlp.encode_length(total_length, True))  # total length

    for field in [msg.nonce, msg.gas_price, msg.gas_limit, msg.to, msg.value]:
        sha.extend(rlp.encode(field))

    if data_left == 0:
        sha.extend(rlp.encode(data))
    else:
        sha.extend(rlp.encode_length(data_total, False))
        sha.extend(rlp.encode(data, False))

    while data_left > 0:
        resp = await send_request_chunk(ctx, data_left)
        data_left -= len(resp.data_chunk)
        sha.extend(resp.data_chunk)

    # eip 155 replay protection
    if msg.chain_id:
        sha.extend(rlp.encode(msg.chain_id))
        sha.extend(rlp.encode(0))
        sha.extend(rlp.encode(0))

    digest = sha.get_digest(True)  # True -> use keccak mode
    return await send_signature(ctx, msg, digest)
Example #2
0
async def sign_tx(ctx, msg, keychain):
    await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n,
                              CURVE)

    address_bytes = recipient = address.bytes_from_address(msg.to)
    value = int.from_bytes(msg.value, "big")
    recipient = msg.data_initial_chunk[16:36]
    value = int.from_bytes(msg.data_initial_chunk[36:68], "big")

    await require_confirm_tx(ctx, recipient, value, msg.chain_id, token,
                             msg.tx_type)

    data = bytearray()
    data += msg.data_initial_chunk
    data_left = data_total - len(msg.data_initial_chunk)

    total_length = get_total_length(msg, data_total)

    sha = HashWriter(sha3_256(keccak=True))
    sha.extend(rlp.encode_length(total_length, True))  # total length

    if msg.tx_type is not None:
        sha.extend(rlp.encode(msg.tx_type))

    for field in (msg.nonce, msg.gas_price, msg.gas_limit, address_bytes,
                  msg.value):
        sha.extend(rlp.encode(field))

    if data_left == 0:
        sha.extend(rlp.encode(data))
    else:
        sha.extend(rlp.encode_length(data_total, False))
        sha.extend(rlp.encode(data, False))

    while data_left > 0:
        resp = await send_request_chunk(ctx, data_left)
        data_left -= len(resp.data_chunk)
        sha.extend(resp.data_chunk)

    # eip 155 replay protection
    if msg.chain_id:
        sha.extend(rlp.encode(msg.chain_id))
        sha.extend(rlp.encode(0))
        sha.extend(rlp.encode(0))

    digest = sha.get_digest()
    result = sign_digest(msg, keychain, digest)

    return result
Example #3
0
async def sign_tx(ctx, msg, keychain):
    msg = sanitize(msg)
    check(msg)
    await paths.validate_path(ctx, keychain, msg.address_n)

    data_total = msg.data_length

    # detect ERC - 20 token
    token = None
    address_bytes = recipient = address.bytes_from_address(msg.to)
    value = int.from_bytes(msg.value, "big")
    if (len(msg.to) in (40, 42) and len(msg.value) == 0 and data_total == 68
            and len(msg.data_initial_chunk) == 68
            and msg.data_initial_chunk[:16] ==
            b"\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        ):
        token = tokens.token_by_chain_address(msg.chain_id, address_bytes)
        recipient = msg.data_initial_chunk[16:36]
        value = int.from_bytes(msg.data_initial_chunk[36:68], "big")

        if token is tokens.UNKNOWN_TOKEN:
            await require_confirm_unknown_token(ctx, address_bytes)

    await require_confirm_tx(ctx, recipient, value, msg.chain_id, token,
                             msg.tx_type)
    if token is None and msg.data_length > 0:
        await require_confirm_data(ctx, msg.data_initial_chunk, data_total)

    await require_confirm_fee(
        ctx,
        value,
        int.from_bytes(msg.gas_price, "big"),
        int.from_bytes(msg.gas_limit, "big"),
        msg.chain_id,
        token,
        msg.tx_type,
    )

    data = bytearray()
    data += msg.data_initial_chunk
    data_left = data_total - len(msg.data_initial_chunk)

    total_length = get_total_length(msg, data_total)

    sha = HashWriter(sha3_256(keccak=True))
    sha.extend(rlp.encode_length(total_length, True))  # total length

    if msg.tx_type is not None:
        sha.extend(rlp.encode(msg.tx_type))

    for field in (msg.nonce, msg.gas_price, msg.gas_limit, address_bytes,
                  msg.value):
        sha.extend(rlp.encode(field))

    if data_left == 0:
        sha.extend(rlp.encode(data))
    else:
        sha.extend(rlp.encode_length(data_total, False))
        sha.extend(rlp.encode(data, False))

    while data_left > 0:
        resp = await send_request_chunk(ctx, data_left)
        data_left -= len(resp.data_chunk)
        sha.extend(resp.data_chunk)

    # eip 155 replay protection
    if msg.chain_id:
        sha.extend(rlp.encode(msg.chain_id))
        sha.extend(rlp.encode(0))
        sha.extend(rlp.encode(0))

    digest = sha.get_digest()
    result = sign_digest(msg, keychain, digest)

    return result
Example #4
0
async def sign_tx(ctx, msg, keychain):
    msg = sanitize(msg)  #TODO refine `sanitize` to support more fields
    check(msg)  #TODO refine check to support ~
    await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n,
                              CURVE)

    node = keychain.derive(msg.address_n)
    seckey = node.private_key()
    public_key = secp256k1.publickey(seckey, False)  # uncompressed
    sender_address = sha3_256(public_key[1:], keccak=True).digest()[12:]

    recipient = address.bytes_from_address(msg.to)
    # TODO- check sender and real sender addr

    value = int.from_bytes(msg.value, "big")
    await require_confirm_tx(ctx, recipient, value, msg.chain_id, None,
                             msg.tx_type)

    # TODO if fee delegation tx? -> require_confirm_fee_delegation
    await require_confirm_fee(
        ctx,
        value,
        int.from_bytes(msg.gas_price, "big"),
        int.from_bytes(msg.gas_limit, "big"),
        msg.chain_id,
        msg.fee_ratio,
        None,
        msg.tx_type,
    )

    data_total = msg.data_length

    data = bytearray()
    data += msg.data_initial_chunk
    data_left = data_total - len(msg.data_initial_chunk)

    total_length = get_total_length(msg, data_total)
    print("total length: ", total_length)

    sha = HashWriter(sha3_256(keccak=True))

    if msg.tx_type is None:
        sha.extend(rlp.encode_length(total_length, True))  # total length

        for field in (msg.nonce, msg.gas_price, msg.gas_limit, recipient,
                      msg.value):
            sha.extend(rlp.encode(field))

        if data_left == 0:
            sha.extend(rlp.encode(data))
        else:
            sha.extend(rlp.encode_length(data_total, False))
            sha.extend(rlp.encode(data, False))

        if msg.chain_id:
            sha.extend(rlp.encode(msg.chain_id))
            sha.extend(rlp.encode(0))
            sha.extend(rlp.encode(0))

    else:
        basic_type = to_basic_type(msg.tx_type)
        attributes = [msg.tx_type, msg.nonce, msg.gas_price, msg.gas_limit]

        # TxTypeValueTransfer(0x08)
        if basic_type == 0x08:
            attributes += [recipient, msg.value, sender_address]
            if to_fee_type(msg.tx_type) == TX_TYPE_PARTIAL_FEE_DELEGATION:
                attributes.append(msg.fee_ratio)

        # TxTypeValueTransferMemo(0x10), TxTypeSmartContractExecution(0x30)
        elif basic_type == 0x10 or basic_type == 0x30:
            attributes += [recipient, msg.value, sender_address, data]
            if to_fee_type(msg.tx_type) == TX_TYPE_PARTIAL_FEE_DELEGATION:
                attributes.append(msg.fee_ratio)

        # TxTypeSmartContractDeploy(0x28)
        elif basic_type == 0x28:
            human_readable = 0x00
            if msg.human_readable:
                human_readable = 0x01
            attributes += [
                recipient, msg.value, sender_address, data, human_readable
            ]
            if to_fee_type(msg.tx_type) == TX_TYPE_PARTIAL_FEE_DELEGATION:
                attributes.append(msg.fee_ratio)
            attributes.append(msg.code_format)

        # TxTypeCancel(0x38)
        elif basic_type == 0x38:
            attributes.append(sender_address)
            if to_fee_type(msg.tx_type) == TX_TYPE_PARTIAL_FEE_DELEGATION:
                attributes.append(msg.fee_ratio)

        # not supported tx type
        else:
            raise wire.DataError("Not supported transaction type")

        encoded_out = rlp.encode(attributes)
        sha.extend(rlp.encode([encoded_out, msg.chain_id, 0, 0], True))

    digest = sha.get_digest()
    result = sign_digest(msg, keychain, digest)

    return result