Skip to content

Commit

Permalink
Merge pull request #139 from KeystoneHQ/sui-address
Browse files Browse the repository at this point in the history
Sui
  • Loading branch information
soralit authored Oct 12, 2023
2 parents 575e51a + ead99ff commit 016062f
Show file tree
Hide file tree
Showing 38 changed files with 863 additions and 107 deletions.
2 changes: 1 addition & 1 deletion external/lvgl/lv_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/

/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
#define LV_USE_LARGE_COORD 0
#define LV_USE_LARGE_COORD 1

/*==================
* FONT USAGE
Expand Down
14 changes: 6 additions & 8 deletions rust/apps/sui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use third_party::{blake2::{
digest::{Update, VariableOutput},
Blake2bVar,
}, serde_json};
use third_party::{base58, bcs, hex};
use third_party::{bcs, hex};
use types::{intent::IntentMessage, msg::PersonalMessageUtf8};

pub mod errors;
Expand All @@ -31,11 +31,9 @@ pub enum Intent {
PersonalMessage(IntentMessage<PersonalMessageUtf8>),
}

pub fn generate_address(xpub: &str) -> Result<String> {
pub fn generate_address(pub_key: &str) -> Result<String> {
let mut hasher = Blake2bVar::new(32).unwrap();
let mut xpub_buf = base58::decode(xpub)?;
let len = xpub_buf.len();
let mut buf: Vec<u8> = xpub_buf.drain(len - 4 - 32..len - 4).collect();
let mut buf: Vec<u8> = hex::decode(pub_key)?;
// insert flag, ed25519 is 0, secp256k1 is 1, secp256r1 is 2, multi sign is 3.
buf.insert(0, 0);
hasher.update(&buf);
Expand Down Expand Up @@ -101,10 +99,10 @@ mod tests {

#[test]
fn test_generate_address() {
let xpub = "xpub6FpeLDgZhZfkYXMwMZtxLqNDzWfNyPQKoLAQE9re4Qcv3zZmKWiwfkg8HEGstz1uNoKtYqCXJzWMuQhYw7EYKLzqty13z1SE4yrjYSuTcPd";
let address = generate_address(xpub).unwrap();
let pub_key = "edbe1b9b3b040ff88fbfa4ccda6f5f8d404ae7ffe35f9b220dec08679d5c336f";
let address = generate_address(pub_key).unwrap();
assert_eq!(
"0xf195b51c63745071891b1f53170cac2cab2a49da6ee1fe8eabe50989234c8119",
"0x504886c9ec43bff70af37f55865094cc3a799cb54479f252d30cd3717f15ecdc",
address
);
}
Expand Down
1 change: 1 addition & 0 deletions rust/apps/wallets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod keplr;
pub mod metamask;
pub mod okx;
pub mod solana;
pub mod sui;
mod utils;
pub mod xrp_toolkit;

Expand Down
13 changes: 13 additions & 0 deletions rust/apps/wallets/src/sui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::utils::generate_crypto_multi_accounts_sync_ur;
use alloc::collections::BTreeMap;
use alloc::string::String;
use third_party::bitcoin::bip32::DerivationPath;
use third_party::ur_registry::error::URResult;
use third_party::ur_registry::extend::crypto_multi_accounts::CryptoMultiAccounts;

pub fn generate_sync_ur(
master_fingerprint: &[u8; 4],
public_keys: BTreeMap<DerivationPath, String>,
) -> URResult<CryptoMultiAccounts> {
generate_crypto_multi_accounts_sync_ur(master_fingerprint, public_keys, &"SUI")
}
2 changes: 1 addition & 1 deletion rust/rust_c/src/interfaces/connect_wallets/aptos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub extern "C" fn get_connect_aptos_wallet_ur(
for x in public_keys {
let pubkey = recover_c_char(x.xpub);
let path = recover_c_char(x.path);
match DerivationPath::from_str(path.as_str()) {
match DerivationPath::from_str(path.to_lowercase().as_str()) {
Ok(path) => {
keys.insert(path, pubkey);
}
Expand Down
3 changes: 2 additions & 1 deletion rust/rust_c/src/interfaces/connect_wallets/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
mod aptos;
pub mod aptos;
pub mod keplr;
pub mod okx;
pub mod solana;
pub mod structs;
pub mod sui;
mod utils;
pub mod xrp_toolkit;

Expand Down
70 changes: 70 additions & 0 deletions rust/rust_c/src/interfaces/connect_wallets/sui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use alloc::collections::BTreeMap;
use alloc::format;
use core::slice;
use core::str::FromStr;
use third_party::bitcoin::bip32::DerivationPath;
use third_party::hex;
use third_party::ur_registry::error::URError;
use third_party::ur_registry::traits::RegistryItem;

use crate::interfaces::errors::RustCError;
use crate::interfaces::ffi::CSliceFFI;
use crate::interfaces::structs::ExtendedPublicKey;
use crate::interfaces::types::PtrT;
use crate::interfaces::ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT};
use crate::interfaces::utils::{recover_c_array, recover_c_char};
use app_wallets::sui::generate_sync_ur;
use third_party::ur_registry::extend::crypto_multi_accounts::CryptoMultiAccounts;

#[no_mangle]
pub extern "C" fn get_connect_sui_wallet_ur(
master_fingerprint: *mut u8,
length: u32,
public_keys: PtrT<CSliceFFI<ExtendedPublicKey>>,
) -> *mut UREncodeResult {
if length != 4 {
return UREncodeResult::from(URError::UrEncodeError(format!(
"master fingerprint length must be 4, current is {}",
length
)))
.c_ptr();
}
unsafe {
let mfp = slice::from_raw_parts(master_fingerprint, length as usize);
let public_keys = recover_c_array(public_keys);
let master_fingerprint =
third_party::bitcoin::bip32::Fingerprint::from_str(hex::encode(mfp.to_vec()).as_str())
.map_err(|_e| RustCError::InvalidMasterFingerprint);
match master_fingerprint {
Ok(fp) => {
let mut keys = BTreeMap::new();
for x in public_keys {
let pubkey = recover_c_char(x.xpub);
let path = recover_c_char(x.path);
match DerivationPath::from_str(path.to_lowercase().as_str()) {
Ok(path) => {
keys.insert(path, pubkey);
}
Err(_e) => {
return UREncodeResult::from(RustCError::InvalidHDPath).c_ptr();
}
}
}
let result = generate_sync_ur(fp.as_ref(), keys);
match result.map(|v| v.try_into()) {
Ok(v) => match v {
Ok(data) => UREncodeResult::encode(
data,
CryptoMultiAccounts::get_registry_type().get_type(),
FRAGMENT_MAX_LENGTH_DEFAULT,
)
.c_ptr(),
Err(e) => UREncodeResult::from(e).c_ptr(),
},
Err(e) => UREncodeResult::from(e).c_ptr(),
}
}
Err(e) => UREncodeResult::from(e).c_ptr(),
}
}
}
2 changes: 2 additions & 0 deletions rust/rust_c/src/interfaces/free.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use cty::c_char;

use super::ethereum::structs::DisplayContractData;
use super::structs::Response;
use super::sui::structs::DisplaySuiIntentMessage;

pub trait Free {
fn free(&self);
Expand Down Expand Up @@ -111,6 +112,7 @@ make_free_method!(TransactionParseResult<DisplayXrpTx>);
make_free_method!(TransactionParseResult<DisplayETHPersonalMessage>);
make_free_method!(TransactionParseResult<DisplaySolanaMessage>);
make_free_method!(TransactionParseResult<DisplayETHTypedData>);
make_free_method!(TransactionParseResult<DisplaySuiIntentMessage>);
make_free_method!(TransactionCheckResult);

#[no_mangle]
Expand Down
41 changes: 36 additions & 5 deletions rust/rust_c/src/interfaces/sui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use crate::interfaces::structs::{SimpleResponse, TransactionCheckResult, Transac
use crate::interfaces::types::{PtrBytes, PtrString, PtrT, PtrUR};
use crate::interfaces::ur::{UREncodeResult, FRAGMENT_MAX_LENGTH_DEFAULT};
use crate::interfaces::utils::{convert_c_char, recover_c_char};
use alloc::string::ToString;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use app_sui::errors::SuiError;
use app_utils::normalize_path;
use core::slice;
use cty::c_char;
use third_party::ur_registry::sui::sui_sign_request::SuiSignRequest;
Expand All @@ -15,6 +18,21 @@ use third_party::ur_registry::traits::RegistryItem;

pub mod structs;

fn get_public_key(seed: &[u8], path: &String) -> Result<Vec<u8>, SuiError> {
let path = normalize_path(path);
let public_key =
match keystore::algorithms::ed25519::slip10_ed25519::get_public_key_by_seed(seed, &path) {
Ok(pub_key) => pub_key,
Err(e) => {
return Err(SuiError::SignFailure(format!(
"derive public key failed {:?}",
e
)))
}
};
Ok(public_key.to_vec())
}

#[no_mangle]
pub extern "C" fn sui_check_request(
ptr: PtrUR,
Expand Down Expand Up @@ -43,9 +61,9 @@ pub extern "C" fn sui_check_request(
}

#[no_mangle]
pub extern "C" fn sui_generate_address(x_pub: PtrString) -> *mut SimpleResponse<c_char> {
let x_pub = recover_c_char(x_pub);
let address = app_sui::generate_address(&x_pub);
pub extern "C" fn sui_generate_address(pub_key: PtrString) -> *mut SimpleResponse<c_char> {
let pub_key = recover_c_char(pub_key);
let address = app_sui::generate_address(&pub_key);
match address {
Ok(result) => SimpleResponse::success(convert_c_char(result) as *mut c_char).simple_c_ptr(),
Err(e) => SimpleResponse::from(e).simple_c_ptr(),
Expand Down Expand Up @@ -86,8 +104,21 @@ pub extern "C" fn sui_sign_intent(
Ok(v) => v,
Err(e) => return UREncodeResult::from(e).c_ptr(),
};
UREncodeResult::encode(
let pub_key = match get_public_key(seed, &path) {
Ok(v) => v,
Err(e) => return UREncodeResult::from(e).c_ptr(),
};
let sig = SuiSignature::new(
sign_request.get_request_id(),
signature.to_vec(),
Some(pub_key),
);
let sig_data: Vec<u8> = match sig.try_into() {
Ok(v) => v,
Err(e) => return UREncodeResult::from(e).c_ptr(),
};
UREncodeResult::encode(
sig_data,
SuiSignature::get_registry_type().get_type(),
FRAGMENT_MAX_LENGTH_DEFAULT,
)
Expand Down
8 changes: 8 additions & 0 deletions rust/rust_c/src/interfaces/test_cmds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use third_party::ur_registry::crypto_psbt::CryptoPSBT;
use third_party::ur_registry::ethereum::eth_sign_request::{DataType, EthSignRequest};
use third_party::ur_registry::near::near_sign_request::NearSignRequest;
use third_party::ur_registry::solana::sol_sign_request::SolSignRequest;
use third_party::ur_registry::sui::sui_sign_request::SuiSignRequest;
use third_party::ur_registry::traits::RegistryItem;

use crate::interfaces::connect_wallets::get_connect_blue_wallet_ur;
Expand Down Expand Up @@ -275,6 +276,13 @@ pub extern "C" fn test_get_sol_sign_message(cbor: *mut c_char) -> *mut URParseRe
.c_ptr()
}

#[no_mangle]
pub extern "C" fn test_get_sui_sign_request(cbor: *mut c_char) -> *mut URParseResult {
let cbor_str = recover_c_char(cbor);
let sign_request = SuiSignRequest::try_from(hex::decode(cbor_str).unwrap()).unwrap();
URParseResult::single(ViewType::SuiTx, URType::SuiSignRequest, sign_request).c_ptr()
}

#[no_mangle]
pub extern "C" fn test_get_near_sign_request(cbor: *mut c_char) -> *mut URParseResult {
let cbor_str = recover_c_char(cbor);
Expand Down
9 changes: 9 additions & 0 deletions rust/rust_c/src/interfaces/ur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use third_party::ur_registry::extend::crypto_multi_accounts::CryptoMultiAccounts
use third_party::ur_registry::near::near_sign_request::NearSignRequest;
use third_party::ur_registry::registry_types::URType as InnerURType;
use third_party::ur_registry::solana::sol_sign_request::SolSignRequest;
use third_party::ur_registry::sui::sui_sign_request::SuiSignRequest;
use third_party::ur_registry::traits::RegistryItem;

use crate::interfaces::errors::{ErrorCodes, RustCError};
Expand Down Expand Up @@ -167,6 +168,7 @@ pub enum ViewType {
XRPTx,
CosmosTx,
CosmosEvmTx,
SuiTx,
WebAuthResult,
ViewTypeUnKnown,
}
Expand All @@ -183,6 +185,7 @@ pub enum URType {
CardanoSignRequest,
CosmosSignRequest,
EvmSignRequest,
SuiSignRequest,
}

impl URType {
Expand All @@ -196,6 +199,7 @@ impl URType {
InnerURType::NearSignRequest(_) => Ok(URType::NearSignRequest),
InnerURType::CosmosSignRequest(_) => Ok(URType::CosmosSignRequest),
InnerURType::EvmSignRequest(_) => Ok(URType::EvmSignRequest),
InnerURType::SuiSignRequest(_) => Ok(URType::SuiSignRequest),
_ => Err(URError::NotSupportURTypeError(value.get_type_str())),
}
}
Expand Down Expand Up @@ -289,6 +293,9 @@ fn free_ur(ur_type: &URType, data: PtrUR) {
URType::EvmSignRequest => {
free_ptr_with_type!(data, EvmSignRequest);
}
URType::SuiSignRequest => {
free_ptr_with_type!(data, SuiSignRequest);
}
_ => {}
}
}
Expand Down Expand Up @@ -415,6 +422,7 @@ pub fn decode_ur(ur: String) -> URParseResult {
URType::CardanoSignRequest => _decode_ur::<CardanoSignRequest>(ur, ur_type),
URType::CosmosSignRequest => _decode_ur::<CosmosSignRequest>(ur, ur_type),
URType::EvmSignRequest => _decode_ur::<EvmSignRequest>(ur, ur_type),
URType::SuiSignRequest => _decode_ur::<SuiSignRequest>(ur, ur_type),
URType::URTypeUnKnown => URParseResult::from(URError::NotSupportURTypeError(
"UnKnown ur type".to_string(),
)),
Expand Down Expand Up @@ -468,6 +476,7 @@ fn receive_ur(ur: String, decoder: &mut KeystoneURDecoder) -> URParseMultiResult
URType::CardanoSignRequest => _receive_ur::<CardanoSignRequest>(ur, ur_type, decoder),
URType::CosmosSignRequest => _receive_ur::<CosmosSignRequest>(ur, ur_type, decoder),
URType::EvmSignRequest => _receive_ur::<EvmSignRequest>(ur, ur_type, decoder),
URType::SuiSignRequest => _receive_ur::<SuiSignRequest>(ur, ur_type, decoder),
URType::URTypeUnKnown => URParseMultiResult::from(URError::NotSupportURTypeError(
"UnKnown ur type".to_string(),
)),
Expand Down
7 changes: 7 additions & 0 deletions rust/rust_c/src/interfaces/ur_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use third_party::ur_registry::pb::protoc;
use third_party::ur_registry::pb::protoc::Base;

use third_party::ur_registry::solana::sol_sign_request::SolSignRequest;
use third_party::ur_registry::sui::sui_sign_request::SuiSignRequest;

pub trait InferViewType {
fn infer(&self) -> Result<ViewType, URError> {
Expand Down Expand Up @@ -60,6 +61,12 @@ impl InferViewType for EvmSignRequest {
}
}

impl InferViewType for SuiSignRequest {
fn infer(&self) -> Result<ViewType, URError> {
Ok(ViewType::SuiTx)
}
}

impl InferViewType for Bytes {
fn infer(&self) -> Result<ViewType, URError> {
match from_slice::<Value>(self.get_bytes().as_slice()) {
Expand Down
10 changes: 10 additions & 0 deletions src/crypto/account_public_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ static const ChainItem_t g_chainTable[] = {
{XPUB_TYPE_SOL_BIP44_CHANGE_7, ED25519, "sol_bip44_change_7", "M/44'/501'/7'/0'" },
{XPUB_TYPE_SOL_BIP44_CHANGE_8, ED25519, "sol_bip44_change_8", "M/44'/501'/8'/0'" },
{XPUB_TYPE_SOL_BIP44_CHANGE_9, ED25519, "sol_bip44_change_9", "M/44'/501'/9'/0'" },
{XPUB_TYPE_SUI_0, ED25519, "sui_0", "M/44'/784'/0'/0'/0'"},
{XPUB_TYPE_SUI_1, ED25519, "sui_1", "M/44'/784'/1'/0'/0'"},
{XPUB_TYPE_SUI_2, ED25519, "sui_2", "M/44'/784'/2'/0'/0'"},
{XPUB_TYPE_SUI_3, ED25519, "sui_3", "M/44'/784'/3'/0'/0'"},
{XPUB_TYPE_SUI_4, ED25519, "sui_4", "M/44'/784'/4'/0'/0'"},
{XPUB_TYPE_SUI_5, ED25519, "sui_5", "M/44'/784'/5'/0'/0'"},
{XPUB_TYPE_SUI_6, ED25519, "sui_6", "M/44'/784'/6'/0'/0'"},
{XPUB_TYPE_SUI_7, ED25519, "sui_7", "M/44'/784'/7'/0'/0'"},
{XPUB_TYPE_SUI_8, ED25519, "sui_8", "M/44'/784'/8'/0'/0'"},
{XPUB_TYPE_SUI_9, ED25519, "sui_9", "M/44'/784'/9'/0'/0'"},
};

void AccountPublicHomeCoinGet(WalletState_t *walletList, uint8_t count)
Expand Down
10 changes: 10 additions & 0 deletions src/crypto/account_public_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ typedef enum {
XPUB_TYPE_SOL_BIP44_CHANGE_7,
XPUB_TYPE_SOL_BIP44_CHANGE_8,
XPUB_TYPE_SOL_BIP44_CHANGE_9,
XPUB_TYPE_SUI_0,
XPUB_TYPE_SUI_1,
XPUB_TYPE_SUI_2,
XPUB_TYPE_SUI_3,
XPUB_TYPE_SUI_4,
XPUB_TYPE_SUI_5,
XPUB_TYPE_SUI_6,
XPUB_TYPE_SUI_7,
XPUB_TYPE_SUI_8,
XPUB_TYPE_SUI_9,

XPUB_TYPE_NUM,
} ChainType;
Expand Down
1 change: 1 addition & 0 deletions src/tasks/qrdecode_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static SetChainData_t g_chainViewArray[] = {
{REMAPVIEW_ETH_TYPEDDATA, GuiSetEthUrData},
{REMAPVIEW_TRX, GuiSetTrxUrData},
{REMAPVIEW_COSMOS, GuiSetCosmosUrData},
{REMAPVIEW_SUI, GuiSetSuiUrData},
};

osThreadId_t g_qrDecodeTaskHandle;
Expand Down
Loading

0 comments on commit 016062f

Please sign in to comment.