Skip to content
Merged
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
8 changes: 4 additions & 4 deletions .github/workflows/build-pro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ jobs:
bitcoin_only: 1
secret_key_1_name: "SECRET_KEY_1"
secret_key_2_name: "SECRET_KEY_2"
output_dir: prod-bc-only
artifact_suffix: "prod-bc-only"
output_dir: prod-btc-only
artifact_suffix: "prod-btc-only"
- production: 0
bitcoin_only: 0
secret_key_1_name: "SECRET_QA_KEY_1"
Expand All @@ -39,8 +39,8 @@ jobs:
bitcoin_only: 1
secret_key_1_name: "SECRET_QA_KEY_1"
secret_key_2_name: "SECRET_QA_KEY_2"
output_dir: qa-bc-only
artifact_suffix: "qa-bc-only"
output_dir: qa-btc-only
artifact_suffix: "qa-btc-only"

steps:
- name: "Checkout"
Expand Down
1 change: 1 addition & 0 deletions common/protob/messages-polkadot.proto
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ message PolkadotSignTx {
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
required bytes raw_tx = 2; // serialized raw transaction
required string network = 3; // Network name
optional uint32 prefix = 4; // SS58 address-type
}

/**
Expand Down
4 changes: 2 additions & 2 deletions core/embed/firmware/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#define FIX_VERSION_BUILD VERSION_BUILD

#define ONEKEY_VERSION_MAJOR 4
#define ONEKEY_VERSION_MINOR 17
#define ONEKEY_VERSION_PATCH 1
#define ONEKEY_VERSION_MINOR 18
#define ONEKEY_VERSION_PATCH 0
#define ONEKEY_VERSION_BUILD 0

// Minimum SE version required for firmware upgrade
Expand Down
10 changes: 8 additions & 2 deletions core/src/apps/polkadot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
CURVE = "ed25519-ledger"
SLIP44_ID = 354
PATTERN = PATTERN_BIP44
PRIMARY_COLOR = 0xE6007A
PRIMARY_COLOR_KSM = 0xFFFFFF
PRIMARY_COLOR = 0x00FF33
PRIMARY_COLOR_KSM = 0x00FF33
PRIMARY_COLOR_WESTEND = 0x969696
PRIMARY_COLOR_ASTAR = 0x04E2FE
PRIMARY_COLOR_JOY = 0x4038FF
PRIMARY_COLOR_MAMTA = 0x26C8BF
PRIMARY_COLOR_HYDRATION = 0x00FF33
PRIMARY_COLOR_BIFROST = 0x00FF33
PRIMARY_COLOR_BIFROST_KSMC = 0x00FF33
ICON = "A:/res/chain-dot.png"
ICON_KSM = "A:/res/chain-kusama.png"
ICON_WESTEND = "A:/res/chain-westend.png"
ICON_ASTAR = "A:/res/chain-astar.png"
ICON_JOY = "A:/res/chain-joystream.png"
ICON_MANTA = "A:/res/chain-manta.png"
ICON_HYDRATION = "A:/res/chain-hydration.png"
ICON_BIFROST = "A:/res/chain-bifrost.png"
ICON_BIFROST_KSM = "A:/res/chain-bifrost-ksm.png"
41 changes: 38 additions & 3 deletions core/src/apps/polkadot/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@
from . import (
ICON,
ICON_ASTAR,
ICON_BIFROST,
ICON_BIFROST_KSM,
ICON_HYDRATION,
ICON_JOY,
ICON_KSM,
ICON_MANTA,
ICON_WESTEND,
PRIMARY_COLOR,
PRIMARY_COLOR_ASTAR,
PRIMARY_COLOR_BIFROST,
PRIMARY_COLOR_BIFROST_KSMC,
PRIMARY_COLOR_HYDRATION,
PRIMARY_COLOR_JOY,
PRIMARY_COLOR_KSM,
PRIMARY_COLOR_MAMTA,
Expand All @@ -30,6 +36,9 @@
["astar", 5],
["joystream", 126],
["manta", 77],
["hydration", 0],
["bifrost", 0],
["bifrost-ksm", 0],
]

COIN_AMOUNT_DECIMAL_PLACES = 10
Expand All @@ -41,6 +50,8 @@
ASTAR_COIN_TICKER = "ASTR"
JOY_COIN_TICKER = "JOY"
MANTA_COIN_TICKER = "MANTA"
HYDRATION_COIN_TICKER = "HDX"
BIFROST_COIN_TICKER = "BNC"


def ss58_encode(address: bytes, ss58_format: int = 42) -> str:
Expand Down Expand Up @@ -118,6 +129,30 @@ def retrieval_chain_res(ctx: Context, network: str) -> tuple[str, str, int]:
chain_name = "Manta"
symbol = MANTA_COIN_TICKER
decimal = COIN_AMOUNT_DECIMAL_PLACES_18
elif network == "hydration":
ctx.primary_color, ctx.icon_path = (
lv.color_hex(PRIMARY_COLOR_HYDRATION),
ICON_HYDRATION,
)
chain_name = "Hydration"
symbol = HYDRATION_COIN_TICKER
decimal = COIN_AMOUNT_DECIMAL_PLACES_12
elif network == "bifrost":
ctx.primary_color, ctx.icon_path = (
lv.color_hex(PRIMARY_COLOR_BIFROST),
ICON_BIFROST,
)
chain_name = "Bifrost"
symbol = BIFROST_COIN_TICKER
decimal = COIN_AMOUNT_DECIMAL_PLACES_12
elif network == "bifrost-ksm":
ctx.primary_color, ctx.icon_path = (
lv.color_hex(PRIMARY_COLOR_BIFROST_KSMC),
ICON_BIFROST_KSM,
)
chain_name = "Bifrost-KSM"
symbol = BIFROST_COIN_TICKER
decimal = COIN_AMOUNT_DECIMAL_PLACES_12
else:
ctx.primary_color, ctx.icon_path = lv.color_hex(PRIMARY_COLOR), ICON
chain_name = "UNKN Chain"
Expand All @@ -126,10 +161,10 @@ def retrieval_chain_res(ctx: Context, network: str) -> tuple[str, str, int]:
return chain_name, symbol, decimal


def get_address_type(network: str) -> int:
address_type = 42
def get_address_type(network: str, preset_prefix: int | None = None) -> int:
address_type = preset_prefix if preset_prefix is not None else 42
for element in POLKADOT_ADDRESS_TYPES:
if network == element[0]:
address_type = element[1]

break
return address_type
2 changes: 1 addition & 1 deletion core/src/apps/polkadot/sign_tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async def sign_tx(
public_key = node.public_key()[1:]
else:
public_key = ed25519.publickey(node.private_key())
address_type = helper.get_address_type(msg.network)
address_type = helper.get_address_type(msg.network, msg.prefix)
address = helper.ss58_encode(public_key, address_type)
chain_name, symbol, decimal = helper.retrieval_chain_res(ctx, msg.network)
tx = transaction.Transaction.deserialize(msg.raw_tx, msg.network)
Expand Down
122 changes: 95 additions & 27 deletions core/src/apps/polkadot/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,26 @@ async def layout(
return None

@staticmethod
def _readAccountIdLookupOfT_V15(rawtx: codec.base.ScaleBytes, address_type) -> str:
value = rawtx.get_next_bytes(1)[0]
if value == 0: # Id
def _readAccountIdLookupOfT_V15(
rawtx: codec.base.ScaleBytes, address_type, skip_type_lookup: bool = False
) -> str:
if not skip_type_lookup:
value = rawtx.get_next_bytes(1)[0]
else:
value = 0
if value == 0:
accountid = helper.ss58_encode(rawtx.get_next_bytes(32), address_type)
elif value == 1: # Index
elif value == 1:
obj = codec.types.Compact(rawtx)
accountid = str(obj.decode(check_remaining=False))
elif value == 2: # Raw
elif value == 2:
obj = codec.types.Compact(rawtx)
value = obj.decode(check_remaining=False)
clen = int(0 if value is None else value)
accountid = hexlify(rawtx.get_next_bytes(clen)).decode()
elif value == 3: # Address32
elif value == 3:
accountid = hexlify(rawtx.get_next_bytes(32)).decode()
elif value == 4: # Address20
elif value == 4:
accountid = hexlify(rawtx.get_next_bytes(20)).decode()
else:
raise Exception("Unexpected value")
Expand All @@ -49,23 +54,23 @@ def deserialize_polkadot(
rawtx: codec.base.ScaleBytes, callPrivIdx: int
) -> "Transaction":
tx = TransactionUnknown(rawtx)
if callPrivIdx in (1287, 1280):
if callPrivIdx in (1287, 1280, 2560):
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 0)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransfer(desc, balance)
elif callPrivIdx == 1282:
elif callPrivIdx in (1282, 2562):
source = Transaction._readAccountIdLookupOfT_V15(rawtx, 0)
dest = Transaction._readAccountIdLookupOfT_V15(rawtx, 0)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesForceTransfer(source, dest, balance)
elif callPrivIdx == 1283:
elif callPrivIdx in (1283, 2563):
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 0)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransferKeepAlive(desc, balance)
elif callPrivIdx == 1284:
elif callPrivIdx in (1284, 2564):
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 0)
keep_alive = rawtx.get_next_bytes(1)[0]
tx = BalancesTransferAll(desc, keep_alive)
Expand All @@ -77,23 +82,23 @@ def deserialize_kusama(
rawtx: codec.base.ScaleBytes, callPrivIdx: int
) -> "Transaction":
tx = TransactionUnknown(rawtx)
if callPrivIdx in (1031, 1024):
if callPrivIdx in (1031, 1024, 2560):
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 2)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransfer(desc, balance)
elif callPrivIdx == 1026:
elif callPrivIdx in (1026, 2562):
source = Transaction._readAccountIdLookupOfT_V15(rawtx, 2)
dest = Transaction._readAccountIdLookupOfT_V15(rawtx, 2)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesForceTransfer(source, dest, balance)
elif callPrivIdx == 1027:
elif callPrivIdx in (1027, 2563):
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 2)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransferKeepAlive(desc, balance)
elif callPrivIdx == 1028:
elif callPrivIdx in (1028, 2564):
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 2)
keep_alive = rawtx.get_next_bytes(1)[0]
tx = BalancesTransferAll(desc, keep_alive)
Expand Down Expand Up @@ -162,47 +167,101 @@ def deserialize_joy(
) -> "Transaction":
tx = TransactionUnknown(rawtx)
if callPrivIdx == 1280:
dest = helper.ss58_encode(rawtx.get_next_bytes(32), 126)
dest = Transaction._readAccountIdLookupOfT_V15(
rawtx, 126, skip_type_lookup=True
)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransfer(dest, balance)
elif callPrivIdx == 1282:
source = Transaction._readAccountIdLookupOfT_V15(
rawtx, 126, skip_type_lookup=True
)
dest = Transaction._readAccountIdLookupOfT_V15(
rawtx, 126, skip_type_lookup=True
)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesForceTransfer(source, dest, balance)
elif callPrivIdx == 1283:
dest = helper.ss58_encode(rawtx.get_next_bytes(32), 126)
dest = Transaction._readAccountIdLookupOfT_V15(
rawtx, 126, skip_type_lookup=True
)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransferKeepAlive(dest, balance)
elif callPrivIdx == 1284:
dest = helper.ss58_encode(rawtx.get_next_bytes(32), 126)
dest = Transaction._readAccountIdLookupOfT_V15(
rawtx, 126, skip_type_lookup=True
)
keep_alive = rawtx.get_next_bytes(1)[0]
tx = BalancesTransferAll(dest, keep_alive)

return tx

@staticmethod
def deserialize_manta(
rawtx: codec.base.ScaleBytes, callPrivIdx: int
rawtx: codec.base.ScaleBytes, callPrivIdx: int, address_type: int
) -> "Transaction":
tx = TransactionUnknown(rawtx)
if callPrivIdx == 2560:
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 77)
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, address_type)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransfer(desc, balance)
elif callPrivIdx == 2562:
source = Transaction._readAccountIdLookupOfT_V15(rawtx, address_type)
dest = Transaction._readAccountIdLookupOfT_V15(rawtx, address_type)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesForceTransfer(source, dest, balance)
elif callPrivIdx == 2563:
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 77)
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, address_type)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransferKeepAlive(desc, balance)
elif callPrivIdx == 2564:
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, 77)
desc = Transaction._readAccountIdLookupOfT_V15(rawtx, address_type)
keep_alive = rawtx.get_next_bytes(1)[0]
tx = BalancesTransferAll(desc, keep_alive)
elif callPrivIdx == 2562:
source = Transaction._readAccountIdLookupOfT_V15(rawtx, 77)
dest = Transaction._readAccountIdLookupOfT_V15(rawtx, 77)

return tx

@staticmethod
def deserialize_hydration(
rawtx: codec.base.ScaleBytes, callPrivIdx: int
) -> "Transaction":
tx = TransactionUnknown(rawtx)
if callPrivIdx == 1792:
desc = Transaction._readAccountIdLookupOfT_V15(
rawtx, 0, skip_type_lookup=True
)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransfer(desc, balance)
elif callPrivIdx == 1794:
source = Transaction._readAccountIdLookupOfT_V15(
rawtx, 0, skip_type_lookup=True
)
dest = Transaction._readAccountIdLookupOfT_V15(
rawtx, 0, skip_type_lookup=True
)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesForceTransfer(source, dest, balance)
elif callPrivIdx == 1795:
desc = Transaction._readAccountIdLookupOfT_V15(
rawtx, 0, skip_type_lookup=True
)
obj = codec.types.Compact(rawtx)
balance = obj.decode(check_remaining=False)
tx = BalancesTransferKeepAlive(desc, balance)
elif callPrivIdx == 1796:
desc = Transaction._readAccountIdLookupOfT_V15(
rawtx, 0, skip_type_lookup=True
)
keep_alive = rawtx.get_next_bytes(1)[0]
tx = BalancesTransferAll(desc, keep_alive)

return tx

Expand All @@ -224,8 +283,14 @@ def deserialize(raw_tx: bytes, network: str) -> "Transaction":
tx = Transaction.deserialize_astar(rawtx, callPrivIdx)
elif network == "joystream":
tx = Transaction.deserialize_joy(rawtx, callPrivIdx)
elif network == "manta":
tx = Transaction.deserialize_manta(rawtx, callPrivIdx)
elif network in ("manta", "bifrost", "bifrost-ksm"):
if network == "manta":
address_type = 77
else:
address_type = 0
tx = Transaction.deserialize_manta(rawtx, callPrivIdx, address_type)
elif network == "hydration":
tx = Transaction.deserialize_hydration(rawtx, callPrivIdx)
else:
tx = TransactionUnknown(rawtx)

Expand All @@ -248,6 +313,9 @@ def deserialize(raw_tx: bytes, network: str) -> "Transaction":
tip = obj.decode(check_remaining=False)
tx.tip = tip if tip is not None else 0

# optional: assetId(asset location if assetId is not equal to 0)
# optional: mode

return tx


Expand Down
Loading
Loading