-
Notifications
You must be signed in to change notification settings - Fork 4
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: ikc add get_extended_public_key api [R2D2-10567] #70
Changes from 2 commits
aa45d6e
70d1c69
8f19ca6
93ba478
fc24d5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,7 +67,7 @@ impl SubstrateAddress { | |
return Err(CoinError::ImkeySignatureVerifyFail.into()); | ||
} | ||
|
||
Ok(pubkey.to_string()) | ||
Ok(pubkey.to_lowercase()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里为什么要改成小写? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 现在返回给的公钥信息不都要统一成小写嘛?而且我看tcx这个接口返回的都是小写,为了保持统一。 |
||
} | ||
|
||
pub fn get_address(path: &str, address_type: &AddressType) -> Result<String> { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,4 @@ | ||
use crate::api::{ | ||
AccountResponse, DeriveAccountsParam, DeriveAccountsResult, DeriveSubAccountsParam, | ||
DeriveSubAccountsResult, | ||
}; | ||
use crate::api::{AccountResponse, DeriveAccountsParam, DeriveAccountsResult, DeriveSubAccountsParam, DeriveSubAccountsResult, GetExtendedPublicKeysParam, GetExtendedPublicKeysResult}; | ||
use crate::message_handler::encode_message; | ||
use crate::Result; | ||
use anyhow::anyhow; | ||
|
@@ -26,6 +23,7 @@ use ikc_common::utility::{ | |
}; | ||
use prost::Message; | ||
use std::str::FromStr; | ||
use bitcoin::Network; | ||
|
||
pub(crate) fn derive_accounts(data: &[u8]) -> Result<Vec<u8>> { | ||
let param: DeriveAccountsParam = | ||
|
@@ -168,6 +166,7 @@ pub(crate) fn derive_sub_accounts(data: &[u8]) -> Result<Vec<u8>> { | |
let ext_pub_key = extended_pub_key_derive(&xpub.0, &relative_path)?; | ||
let pub_key_uncompressed = ext_pub_key.public_key.serialize_uncompressed().to_vec(); | ||
account.public_key = format!("0x{}", ext_pub_key.public_key.serialize().to_hex()); | ||
account.path = relative_path; | ||
let address = match param.chain_type.as_str() { | ||
"ETHEREUM" => EthAddress::from_pub_key(pub_key_uncompressed)?, | ||
"BITCOIN" | "LITECOIN" => { | ||
|
@@ -195,6 +194,23 @@ pub(crate) fn derive_sub_accounts(data: &[u8]) -> Result<Vec<u8>> { | |
}) | ||
} | ||
|
||
pub(crate) fn get_extended_public_key(data: &[u8]) -> Result<Vec<u8>> { | ||
let param: GetExtendedPublicKeysParam = GetExtendedPublicKeysParam::decode(data)?; | ||
let mut extended_public_keys = vec![]; | ||
for public_key_derivation in param.derivations.iter(){ | ||
// if "".eq(&public_key_derivation.path) || &public_key_derivation.path.split("/") { } | ||
let extended_public_key = match public_key_derivation.curve.as_str() { | ||
"secp256k1" => BtcAddress::get_xpub(Network::Bitcoin, public_key_derivation.path.as_str())?, | ||
"ed25519" => SubstrateAddress::get_public_key(public_key_derivation.path.as_str(), &AddressType::Polkadot)?, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 下面这个为什么方法叫做 get_public_key ?tcx 我记得不返回 ed25519 的 xpub 。因为ed25519 没法使用 xpub 派生子地址来着。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tcx不支持支持ed25519的xpub,但是可以直接返回派生的公钥。这个get_public_key方法是通过path来获取公钥,之前就已经有了,命名上可能有些歧义。 |
||
_ => return Err(anyhow!("unsupported_chain_type")), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个报错信息应该是 unsupported_curve ? |
||
}; | ||
extended_public_keys.push(extended_public_key); | ||
} | ||
encode_message(GetExtendedPublicKeysResult{ | ||
extended_public_keys | ||
}) | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use crate::api::derive_accounts_param::Derivation; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,7 +41,7 @@ pub mod tezos_signer; | |
extern crate lazy_static; | ||
extern crate anyhow; | ||
use crate::error_handling::{landingpad, LAST_ERROR}; | ||
use crate::handler::derive_accounts; | ||
use crate::handler::{derive_accounts, get_extended_public_key}; | ||
use crate::message_handler::encode_message; | ||
use ikc_transport::message; | ||
|
||
|
@@ -272,6 +272,7 @@ pub unsafe extern "C" fn call_imkey_api(hex_str: *const c_char) -> *const c_char | |
|
||
"btc_get_xpub" => landingpad(|| btc_address::get_btc_xpub(&action.param.unwrap().value)), | ||
|
||
"get_extended_public_key" => landingpad(|| get_extended_public_key(&action.param.unwrap().value)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tcx 的名字应该叫 get_extended_public_keys。你上面参数名称也叫 GetExtendedPublicKeys |
||
_ => landingpad(|| Err(anyhow!("unsupported_method"))), | ||
}; | ||
match reply { | ||
|
@@ -311,9 +312,7 @@ pub unsafe extern "C" fn imkey_get_last_err_message() -> *const c_char { | |
mod tests { | ||
use super::*; | ||
use crate::api::derive_accounts_param::Derivation; | ||
use crate::api::{ | ||
DeriveAccountsParam, DeriveAccountsResult, DeriveSubAccountsParam, DeriveSubAccountsResult, | ||
}; | ||
use crate::api::{DeriveAccountsParam, DeriveAccountsResult, DeriveSubAccountsParam, DeriveSubAccountsResult, GetExtendedPublicKeysParam, GetExtendedPublicKeysResult, PublicKeyDerivation}; | ||
|
||
use ikc_device::deviceapi::{BindAcquireReq, BindCheckRes}; | ||
use ikc_transport::hid_api::hid_connect; | ||
|
@@ -1401,6 +1400,175 @@ mod tests { | |
); | ||
} | ||
|
||
#[test] | ||
fn test_get_extended_public_key() { | ||
connect_and_bind(); | ||
|
||
let derivations = vec![ | ||
PublicKeyDerivation{ | ||
chain_type: "BITCOIN".to_string(), | ||
path: "m/44'/145'/0'/0/0".to_string(), | ||
curve: "secp256k1".to_string(), | ||
}, | ||
PublicKeyDerivation{ | ||
chain_type: "ETHEREUM".to_string(), | ||
path: "m/44'/60'/0'/0/0".to_string(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 测试最好是到 Account 级别的。如果全用 index 级别的似乎意义不大 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 已添加account级别path测试 |
||
curve: "secp256k1".to_string(), | ||
}, | ||
PublicKeyDerivation{ | ||
chain_type: "POLKADOT".to_string(), | ||
path: "m/44'/354'/0'/0'/0'".to_string(), | ||
curve: "ed25519".to_string(), | ||
}, | ||
PublicKeyDerivation{ | ||
chain_type: "KUSAMA".to_string(), | ||
path: "m/44'/434'/0'/0'/0'".to_string(), | ||
curve: "ed25519".to_string(), | ||
}, | ||
PublicKeyDerivation{ | ||
chain_type: "BITCOIN".to_string(), | ||
path: "m/0/1".to_string(), | ||
curve: "secp256k1".to_string(), | ||
}, | ||
PublicKeyDerivation{ | ||
chain_type: "POLKADOT".to_string(), | ||
path: "m/0'/1'".to_string(), | ||
curve: "ed25519".to_string(), | ||
}, | ||
]; | ||
let param = GetExtendedPublicKeysParam{ | ||
derivations, | ||
}; | ||
let action: ImkeyAction = ImkeyAction { | ||
method: "get_extended_public_key".to_string(), | ||
param: Some(::prost_types::Any { | ||
type_url: "get_extended_public_key".to_string(), | ||
value: encode_message(param).unwrap(), | ||
}), | ||
}; | ||
let action = hex::encode(encode_message(action).unwrap()); | ||
let ret_hex = unsafe { _to_str(call_imkey_api(_to_c_char(action.as_str()))) }; | ||
let ret_bytes = hex::decode(ret_hex).unwrap(); | ||
let extended_public_key: GetExtendedPublicKeysResult = | ||
GetExtendedPublicKeysResult::decode(ret_bytes.as_slice()).unwrap(); | ||
assert_eq!(extended_public_key.extended_public_keys[0], "xpub6GZjFnyumLtEwC4KQkigvc3vXJdZvy71QxHTsFQQv1YtEUWNEwynKWsK2LBFZNLWdTk3w1Y9cRv4NN7V2pnDBoWgH3PkVE9r9Q2kSQL2zkH"); | ||
assert_eq!(extended_public_key.extended_public_keys[1], "xpub6FmdMKZ36pLzf1iF7DLCzKtZms33cZ6mVjvBSy2dCPugFCH23cS3jgHfQ9PKmxs989ZyiyALuADMtLokCzpw7Fi35ap4uybfQAY5WVakan7"); | ||
assert_eq!(extended_public_key.extended_public_keys[2], "edb9955556c8e07287df95ad77fad826168f8a50488cce0d738df3769e24613a"); | ||
assert_eq!(extended_public_key.extended_public_keys[3], "873cf8e52a7b93a55197ef2846e9627a6f105b0a06c86659c813f1a50438b479"); | ||
assert_eq!(extended_public_key.extended_public_keys[4], "xpub6AQmexrYd5utZNmD9Gnf4CjrzJ4kuvaxacLyuSD5sA34g4oKuzBpX5rhAZrCZoxkcqWLVyWSz1rEh5ECs4PDRN16PLfNKFftxm48y6zsWX3"); | ||
assert_eq!(extended_public_key.extended_public_keys[5], "99908c0806ddcda0a8779c4f0c0a87fb679c08c444798cafb21a28cd459388fe"); | ||
} | ||
|
||
#[test] | ||
fn test_get_extended_public_key_error_case() { | ||
connect_and_bind(); | ||
|
||
let test_data = vec![ | ||
vec![ | ||
PublicKeyDerivation{ | ||
chain_type: "POLKADOT".to_string(), | ||
path: "m/44'/354'/0'/0'/0'".to_string(), | ||
curve: "sr25519".to_string(), | ||
}, | ||
], | ||
vec![ | ||
PublicKeyDerivation{ | ||
chain_type: "BITCOIN".to_string(), | ||
path: "".to_string(), | ||
curve: "secp256k1".to_string(), | ||
}, | ||
], | ||
vec![ | ||
PublicKeyDerivation{ | ||
chain_type: "BITCOIN".to_string(), | ||
path: "m/0".to_string(), | ||
curve: "secp256k1".to_string(), | ||
}, | ||
], | ||
vec![ | ||
PublicKeyDerivation{ | ||
chain_type: "POLKADOT".to_string(), | ||
path: "".to_string(), | ||
curve: "ed25519".to_string(), | ||
}, | ||
], | ||
vec![ | ||
PublicKeyDerivation{ | ||
chain_type: "POLKADOT".to_string(), | ||
path: "m/0'".to_string(), | ||
curve: "ed25519".to_string(), | ||
}, | ||
], | ||
]; | ||
for i in 0..test_data.len() { | ||
let param = GetExtendedPublicKeysParam{ | ||
derivations: test_data[i].clone(), | ||
}; | ||
let action: ImkeyAction = ImkeyAction { | ||
method: "get_extended_public_key".to_string(), | ||
param: Some(::prost_types::Any { | ||
type_url: "get_extended_public_key".to_string(), | ||
value: encode_message(param).unwrap(), | ||
}), | ||
}; | ||
let action = hex::encode(encode_message(action).unwrap()); | ||
let ret_hex = unsafe { _to_str(call_imkey_api(_to_c_char(action.as_str()))) }; | ||
let err = unsafe { _to_str(imkey_get_last_err_message()) }; | ||
assert!(!err.is_empty()); | ||
let error_ret: ErrorResponse = ErrorResponse::decode(hex::decode(err).unwrap().as_slice()).unwrap(); | ||
match i { | ||
0 => { assert_eq!(error_ret.error, "unsupported_chain_type"); }, | ||
1 => { assert_eq!(error_ret.error, "imkey_path_illegal"); }, | ||
2 => { assert_eq!(error_ret.error, "imkey_path_illegal"); }, | ||
3 => { assert_eq!(error_ret.error, "imkey_path_illegal"); }, | ||
4 => { assert_eq!(error_ret.error, "imkey_path_illegal"); }, | ||
_ => {} | ||
}; | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_get_extended_public_key_wrong_path() { | ||
connect_and_bind(); | ||
|
||
let derivations = vec![ | ||
PublicKeyDerivation{ | ||
chain_type: "POLKADOT".to_string(), | ||
path: "m/44'/354'/0'/0'/0'".to_string(), | ||
curve: "sr25519".to_string(), | ||
}, | ||
// PublicKeyDerivation{ | ||
// chain_type: "BITCOIN".to_string(), | ||
// path: "".to_string(), | ||
// curve: "secp256k1".to_string(), | ||
// }, | ||
// PublicKeyDerivation{ | ||
// chain_type: "BITCOIN".to_string(), | ||
// path: "m/0".to_string(), | ||
// curve: "secp256k1".to_string(), | ||
// }, | ||
]; | ||
let param = GetExtendedPublicKeysParam{ | ||
derivations, | ||
}; | ||
let action: ImkeyAction = ImkeyAction { | ||
method: "get_extended_public_key".to_string(), | ||
param: Some(::prost_types::Any { | ||
type_url: "get_extended_public_key".to_string(), | ||
value: encode_message(param).unwrap(), | ||
}), | ||
}; | ||
let action = hex::encode(encode_message(action).unwrap()); | ||
let ret_hex = unsafe { _to_str(call_imkey_api(_to_c_char(action.as_str()))) }; | ||
let err = unsafe { _to_str(imkey_get_last_err_message()) }; | ||
assert!(!err.is_empty()); | ||
let error_ret: ErrorResponse = ErrorResponse::decode(hex::decode(err).unwrap().as_slice()).unwrap(); | ||
assert_eq!( | ||
error_ret.error, | ||
"unsupported_chain_type" | ||
); | ||
} | ||
|
||
fn derive_account(derivation: Derivation) -> DeriveAccountsResult { | ||
connect_and_bind(); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个 tag 数字要填对。不然后续容易对不上