Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support ton #583

Open
wants to merge 1 commit into
base: touch
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common/protob/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
for fn in sorted(glob(os.path.join(MYDIR, "messages-*.proto"))):
with open(fn, "rt") as f:
prefix = EXPECTED_PREFIX_RE.search(fn).group(1).capitalize()
if prefix in ("Bitcoin", "Bootloader", "Common", "Crypto", "Management"):
if prefix in ("Bitcoin", "Bootloader", "Common", "Crypto", "Management", "Ton"):
continue
if prefix == "Nem":
prefix = "NEM"
Expand Down
109 changes: 109 additions & 0 deletions common/protob/messages-ton.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
syntax = "proto2";
package hw.trezor.messages.ton;

// Sugar for easier handling in Java
option java_package = "com.satoshilabs.trezor.lib.protobuf";
option java_outer_classname = "TrezorMessageTon";

enum TonWalletVersion {
// V3R1 = 0;
// V3R2 = 1;
// V4R1 = 2;
V4R2 = 3;
}

enum TonWorkChain {
BASECHAIN = 0;
MASTERCHAIN = 1;
}

/**
* Request: Ask device for Ton address(account_id) corresponding to address_n path
* @start
* @next TonAddress
*/
message TonGetAddress {
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
optional bool show_display = 2; // optionally show on display before sending the result
optional TonWalletVersion wallet_version = 3 [default=V4R2]; // ton wallet version
optional bool is_bounceable = 4 [default=false]; // bounceable flag
optional bool is_testnet_only = 5 [default=false]; // testnet only flag
optional TonWorkChain workchain = 6 [default=BASECHAIN]; // 0 for the BaseChain, 1 for the MasterChain
optional uint32 wallet_id = 7 [default=698983191]; // 698983191 is the default subwallet_id value
}

/**
* Response: Contains an Ton address calculated from hash(initial code, initial state)
* @end
*/
message TonAddress {
required bytes public_key = 1;
required string address = 2; // ton base64 user-friendly url-safe address
}

/**
* Request: Require Device to sign toncoin/jetton message
* @start
* @next TonSignedMessage
* @next Failure
*/
message TonSignMessage {
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
required string destination = 2; // destination address of the message
optional string jetton_master_address = 3; // Jetton master smart contract address
optional string jetton_wallet_address = 4; // Jetton wallet smart contract address
required uint64 ton_amount = 5; // TON value for gas
optional uint64 jetton_amount = 6; // jetton value
optional uint64 fwd_fee = 7 [default=0]; // toncoin is needed to transfer notification message
optional string comment = 8; // message comment
optional bool is_raw_data = 9 [default=false]; // raw data flag
optional uint32 mode = 10 [default=3]; // message modes
required uint32 seqno = 11; // message sequence number
required uint64 expire_at = 12; // message expiration time
optional TonWalletVersion wallet_version = 13 [default=V4R2]; // ton wallet version
optional uint32 wallet_id = 14 [default=698983191]; // 698983191 is the default subwallet_id value
optional TonWorkChain workchain = 15 [default=BASECHAIN]; // 0: BaseChain, 1: MasterChain
optional bool is_bounceable = 16 [default=false]; // bounceable flag
optional bool is_testnet_only = 17 [default=false]; // testnet only flag
repeated string ext_destination = 18;
repeated uint64 ext_ton_amount = 19;
repeated string ext_payload = 20;
optional bytes jetton_amount_bytes = 21; // jetton value in bytes
optional bytes signing_message_hash = 22; // signing message hash
}

/**
* Response: transaction signature corresponding to TonSignMessage
* @end
*/
message TonSignedMessage {
optional bytes signature = 1; // signed transaction message
optional bytes signning_message = 2; // message to sign
}

/**
* Request: Require Device to sign proof
* @start
* @next TonSignedProof
* @next Failure
*/
message TonSignProof {
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
required bytes appdomain = 2; // dapp address
optional bytes comment = 3; // message comment
required uint64 expire_at = 4; // message expiration time
optional TonWalletVersion wallet_version = 5 [default=V4R2]; // ton wallet version
optional uint32 wallet_id = 6 [default=698983191]; // 698983191 is the default subwallet_id value
optional TonWorkChain workchain = 7 [default=BASECHAIN]; // 0: BaseChain, 1: MasterChain
optional bool is_bounceable = 8 [default=false]; // bounceable flag
optional bool is_testnet_only = 9 [default=false]; // testnet only flag
}

/**
* Response: transaction signature corresponding to TonSignProof
* @end
*/
message TonSignedProof {
optional bytes signature = 1; // signed transaction message
}

11 changes: 9 additions & 2 deletions common/protob/messages.proto
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ enum MessageType {
MessageType_KaspaSignedTx = 11303 [(wire_out) = true];
MessageType_KaspaTxInputRequest = 11304 [(wire_out) = true];
MessageType_KaspaTxInputAck = 11305 [(wire_in) = true];

// Nexa
MessageType_NexaGetAddress = 11400 [(wire_in) = true];
MessageType_NexaAddress = 11401 [(wire_out) = true];
Expand All @@ -520,11 +520,18 @@ enum MessageType {
MessageType_NostrSignSchnorr = 11508 [(wire_in) = true];
MessageType_NostrSignedSchnorr = 11509 [(wire_out) = true];

// Ton
MessageType_TonGetAddress = 11901 [(wire_in) = true];
MessageType_TonAddress = 11902 [(wire_out) = true];
MessageType_TonSignMessage = 11903 [(wire_in) = true];
MessageType_TonSignedMessage = 11904 [(wire_out) = true];
MessageType_TonSignProof = 11905 [(wire_in) = true];
MessageType_TonSignedProof = 11906 [(wire_out) = true];

// lnurl
MessageType_LnurlAuth = 11600 [(wire_in) = true];
MessageType_LnurlAuthResp = 11601 [(wire_out) = true];


//onekey
MessageType_DeviceBackToBoot = 903 [(wire_in) = true];
MessageType_RebootToBoardloader = 904 [(wire_in) = true];
Expand Down
6 changes: 6 additions & 0 deletions core/SConscript.firmware
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,12 @@ if FROZEN:

SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/tron/*.py'))

SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ton/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ton/*/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ton/*/*/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ton/*/*/*/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/ton/*/*/*/*/*.py'))

SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py'))

SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py'))
Expand Down
1 change: 1 addition & 0 deletions core/embed/firmware/memory_H.ld
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ SECTIONS {
.flash2 : ALIGN(512) {
build/firmware/frozen_mpy.o(.rodata*);
build/firmware/embed/lvgl/lv_font_pljs_bold_36.o(.rodata*);
build/firmware/embed/lvgl/lv_font_pljs_bold_48.o(.rodata*);
build/firmware/vendor/secp256k1-zkp/src/secp256k1.o(.rodata*);
. = ALIGN(512);
} >EXRAM AT>FLASH2
Expand Down
2 changes: 1 addition & 1 deletion core/embed/firmware/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
#define MICROPY_PY_COLLECTIONS (1)
#define MICROPY_PY_COLLECTIONS_DEQUE (0)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0)
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0)
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
#define MICROPY_PY_MATH_ISCLOSE (0)
#define MICROPY_PY_MATH_FACTORIAL (0)
#define MICROPY_PY_CMATH (0)
Expand Down
2 changes: 1 addition & 1 deletion core/embed/unix/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
#define MICROPY_PY_COLLECTIONS (1)
#define MICROPY_PY_COLLECTIONS_DEQUE (0)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0)
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0)
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
#define MICROPY_PY_MATH_ISCLOSE (0)
#define MICROPY_PY_MATH_FACTORIAL (0)
#define MICROPY_PY_CMATH (0)
Expand Down
68 changes: 68 additions & 0 deletions core/src/all_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@
import trezor.enums.SafetyCheckLevel
trezor.enums.SdProtectOperationType
import trezor.enums.SdProtectOperationType
trezor.enums.TonWalletVersion
import trezor.enums.TonWalletVersion
trezor.enums.TonWorkChain
import trezor.enums.TonWorkChain
trezor.enums.TronResourceCode
import trezor.enums.TronResourceCode
trezor.enums.WordRequestType
Expand Down Expand Up @@ -779,6 +783,70 @@
import apps.sui.sign_message
apps.sui.sign_tx
import apps.sui.sign_tx
apps.ton
import apps.ton
apps.ton.get_address
import apps.ton.get_address
apps.ton.layout
import apps.ton.layout
apps.ton.sign_message
import apps.ton.sign_message
apps.ton.sign_proof
import apps.ton.sign_proof
apps.ton.tokens
import apps.ton.tokens
apps.ton.tonsdk
import apps.ton.tonsdk
apps.ton.tonsdk.boc
import apps.ton.tonsdk.boc
apps.ton.tonsdk.boc._bit_string
import apps.ton.tonsdk.boc._bit_string
apps.ton.tonsdk.boc._builder
import apps.ton.tonsdk.boc._builder
apps.ton.tonsdk.boc._cell
import apps.ton.tonsdk.boc._cell
apps.ton.tonsdk.boc._dict_builder
import apps.ton.tonsdk.boc._dict_builder
apps.ton.tonsdk.boc.dict
import apps.ton.tonsdk.boc.dict
apps.ton.tonsdk.boc.dict.find_common_prefix
import apps.ton.tonsdk.boc.dict.find_common_prefix
apps.ton.tonsdk.boc.dict.serialize_dict
import apps.ton.tonsdk.boc.dict.serialize_dict
apps.ton.tonsdk.contract
import apps.ton.tonsdk.contract
apps.ton.tonsdk.contract.token
import apps.ton.tonsdk.contract.token
apps.ton.tonsdk.contract.token.ft
import apps.ton.tonsdk.contract.token.ft
apps.ton.tonsdk.contract.token.ft.jetton_minter
import apps.ton.tonsdk.contract.token.ft.jetton_minter
apps.ton.tonsdk.contract.token.ft.jetton_wallet
import apps.ton.tonsdk.contract.token.ft.jetton_wallet
apps.ton.tonsdk.contract.token.nft
import apps.ton.tonsdk.contract.token.nft
apps.ton.tonsdk.contract.token.nft.nft_collection
import apps.ton.tonsdk.contract.token.nft.nft_collection
apps.ton.tonsdk.contract.token.nft.nft_item
import apps.ton.tonsdk.contract.token.nft.nft_item
apps.ton.tonsdk.contract.token.nft.nft_sale
import apps.ton.tonsdk.contract.token.nft.nft_sale
apps.ton.tonsdk.contract.token.nft.nft_utils
import apps.ton.tonsdk.contract.token.nft.nft_utils
apps.ton.tonsdk.contract.wallet
import apps.ton.tonsdk.contract.wallet
apps.ton.tonsdk.contract.wallet._wallet_contract
import apps.ton.tonsdk.contract.wallet._wallet_contract
apps.ton.tonsdk.contract.wallet._wallet_contract_v3
import apps.ton.tonsdk.contract.wallet._wallet_contract_v3
apps.ton.tonsdk.contract.wallet._wallet_contract_v4
import apps.ton.tonsdk.contract.wallet._wallet_contract_v4
apps.ton.tonsdk.utils
import apps.ton.tonsdk.utils
apps.ton.tonsdk.utils._address
import apps.ton.tonsdk.utils._address
apps.ton.tonsdk.utils._utils
import apps.ton.tonsdk.utils._utils
apps.tron
import apps.tron
apps.tron.address
Expand Down
8 changes: 8 additions & 0 deletions core/src/apps/ton/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CURVE = "ed25519"

SLIP44_ID = 607
# https://github.com/satoshilabs/slips/blob/master/slip-0010.md

PATTERN = "m/44'/coin_type'/account'"
PRIMARY_COLOR = 0x0098EA
ICON = "A:/res/chain-ton.png"
56 changes: 56 additions & 0 deletions core/src/apps/ton/get_address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from typing import TYPE_CHECKING

from trezor import wire
from trezor.enums import TonWalletVersion, TonWorkChain
from trezor.lvglui.scrs import lv
from trezor.messages import TonAddress, TonGetAddress
from trezor.ui.layouts import show_address

from apps.common import paths, seed
from apps.common.keychain import Keychain, auto_keychain

from . import ICON, PRIMARY_COLOR
from .tonsdk.contract.wallet import Wallets, WalletVersionEnum

if TYPE_CHECKING:
from trezor.wire import Context


@auto_keychain(__name__)
async def get_address(
ctx: Context, msg: TonGetAddress, keychain: Keychain
) -> TonAddress:
await paths.validate_path(ctx, keychain, msg.address_n)

node = keychain.derive(msg.address_n)
public_key = seed.remove_ed25519_prefix(node.public_key())
workchain = (
-1 if msg.workchain == TonWorkChain.MASTERCHAIN else TonWorkChain.BASECHAIN
)

if msg.wallet_version == TonWalletVersion.V4R2:
wallet_version = WalletVersionEnum.v4r2
else:
raise wire.DataError("Invalid wallet version.")

wallet = Wallets.ALL[wallet_version](
public_key=public_key, wallet_id=msg.wallet_id, wc=workchain
)
address = wallet.address.to_string(
is_user_friendly=True,
is_url_safe=True,
is_bounceable=msg.is_bounceable,
is_test_only=msg.is_testnet_only,
)

if msg.show_display:
path = paths.address_n_to_str(msg.address_n)
ctx.primary_color, ctx.icon_path = lv.color_hex(PRIMARY_COLOR), ICON
await show_address(
ctx,
address=address,
address_n=path,
network="TON",
)

return TonAddress(public_key=public_key, address=address)
Loading
Loading