Skip to content

Commit

Permalink
fix: cannot derive sub account with hrp (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
XuNeal authored Aug 27, 2024
1 parent d4f34db commit 386d5bb
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 10 deletions.
22 changes: 13 additions & 9 deletions token-core/tcx-btc-kin/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ impl WIFDisplay for TypedPrivateKey {
Ok(key.to_ss58check_with_version(&version))
}
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BtcKinAddress {
pub network: BtcKinNetwork,
Expand Down Expand Up @@ -139,10 +140,13 @@ impl BtcKinAddress {
fn bech32_network(bech32: &str) -> Option<&BtcKinNetwork> {
let bech32_prefix = bech32.rfind('1').map(|sep| bech32.split_at(sep).0);

match bech32_prefix {
Some(prefix) => BtcKinNetwork::find_by_hrp(prefix),
None => None,
if bech32_prefix.is_some() {
let prefix = bech32_prefix.unwrap();
if (!prefix.is_empty()) {
return BtcKinNetwork::find_by_hrp(prefix);
}
}
return None;
}

fn decode_base58(addr: &str) -> result::Result<Vec<u8>, LibAddressError> {
Expand Down Expand Up @@ -419,36 +423,36 @@ mod tests {
let coin = coin_info_from_param("BITCOIN", "MAINNET", "P2WPKH", "").unwrap();
assert!(BtcKinAddress::is_valid(
"3Js9bGaZSQCNLudeGRHL4NExVinc25RbuG",
&coin
&coin,
));

let coin = coin_info_from_param("BITCOIN", "MAINNET", "NONE", "").unwrap();
assert!(BtcKinAddress::is_valid(
"1Gx9QwpQBFnAjF27Uiz3ea2zYBDrLx31bw",
&coin
&coin,
));

let coin = coin_info_from_param("BITCOIN", "MAINNET", "VERSION_0", "").unwrap();
assert!(BtcKinAddress::is_valid(
"bc1qnfv46v0wtarc6n82dnehtvzj2gtnqzjhj5wxqj",
&coin
&coin,
));

let coin = coin_info_from_param("LITECOIN", "MAINNET", "NONE", "").unwrap();
assert!(BtcKinAddress::is_valid(
"Ldfdegx3hJygDuFDUA7Rkzjjx8gfFhP9DP",
&coin
&coin,
));
let coin = coin_info_from_param("LITECOIN", "MAINNET", "P2WPKH", "").unwrap();
assert!(BtcKinAddress::is_valid(
"MR5Hu9zXPX3o9QuYNJGft1VMpRP418QDfW",
&coin
&coin,
));

let coin = coin_info_from_param("LITECOIN", "MAINNET", "P2WPKH", "").unwrap();
assert!(!BtcKinAddress::is_valid(
"MR5Hu9zXPX3o9QuYNJGft1VMpRP418QDf",
&coin
&coin,
));

let coin = coin_info_from_param("LITECOIN", "MAINNET", "P2WPKH", "").unwrap();
Expand Down
1 change: 1 addition & 0 deletions token-core/tcx-proto/src/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ message DeriveSubAccountsParam {
string segWit = 4;
repeated string relativePaths = 5;
string extendedPublicKey = 6;
string hrp = 7;
}

message DeriveSubAccountsResult {
Expand Down
2 changes: 2 additions & 0 deletions token-core/tcx/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,8 @@ pub struct DeriveSubAccountsParam {
pub relative_paths: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(string, tag = "6")]
pub extended_public_key: ::prost::alloc::string::String,
#[prost(string, tag = "7")]
pub hrp: ::prost::alloc::string::String,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
Expand Down
3 changes: 3 additions & 0 deletions token-core/tcx/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,8 @@ pub fn derive_sub_accounts(data: &[u8]) -> Result<Vec<u8>> {
&param.curve,
)?;
coin_info.derivation_path = relative_path.to_string();
coin_info.hrp = param.hrp.to_string();

let acc: Account = derive_sub_account(&xpub, &coin_info)?;

let enc_xpub = encrypt_xpub(&param.extended_public_key.to_string())?;
Expand Down Expand Up @@ -1394,6 +1396,7 @@ mod tests {
"BITCOIN".to_string(),
"BITCOINCASH".to_string(),
"LITECOIN".to_string(),
"DOGECOIN".to_string(),
]
);
assert_eq!(decoded.curve, CurveType::SECP256k1);
Expand Down
62 changes: 62 additions & 0 deletions token-core/tcx/tests/derive_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ pub fn test_derive_btc_legacy_sub_accounts() {
seg_wit: "NONE".to_string(),
relative_paths: vec!["0/0".to_string(), "0/1".to_string(), "1/0".to_string()],
extended_public_key: accounts.accounts[0].extended_public_key.to_string(),
hrp: "".to_string(),
};

let result_bytes = derive_sub_accounts(&encode_message(params).unwrap()).unwrap();
Expand Down Expand Up @@ -536,6 +537,7 @@ pub fn test_derive_btc_p2wpkh_sub_accounts() {
seg_wit: "P2WPKH".to_string(),
relative_paths: vec!["0/0".to_string(), "0/1".to_string(), "1/0".to_string()],
extended_public_key: accounts.accounts[0].extended_public_key.to_string(),
hrp: "".to_string(),
};

let result_bytes = derive_sub_accounts(&encode_message(params).unwrap()).unwrap();
Expand Down Expand Up @@ -577,6 +579,7 @@ pub fn test_derive_eth_sub_accounts() {
seg_wit: "".to_string(),
relative_paths: vec!["0/0".to_string(), "0/1".to_string()],
extended_public_key: accounts.accounts[0].extended_public_key.to_string(),
hrp: "".to_string(),
};

let result_bytes = derive_sub_accounts(&encode_message(params).unwrap()).unwrap();
Expand All @@ -592,6 +595,65 @@ pub fn test_derive_eth_sub_accounts() {
})
}

#[test]
#[serial]
pub fn test_derive_cosmos_sub_accounts() {
run_test(|| {
let derivation = Derivation {
chain_type: "COSMOS".to_string(),
path: "m/44'/118'/0'/0/0".to_string(),
network: "MAINNET".to_string(),
seg_wit: "".to_string(),
chain_id: "".to_string(),
curve: "secp256k1".to_string(),
hrp: "cosmos".to_string(),
};

let (_, accounts) = import_and_derive(derivation);
let params = DeriveSubAccountsParam {
chain_type: "COSMOS".to_string(),
curve: "secp256k1".to_string(),
network: "MAINNET".to_string(),
seg_wit: "".to_string(),
relative_paths: vec!["0/0".to_string(), "0/1".to_string()],
extended_public_key: accounts.accounts[0].extended_public_key.to_string(),
hrp: "cosmos".to_string(),
};

let result_bytes = derive_sub_accounts(&encode_message(params).unwrap()).unwrap();
let result = DeriveSubAccountsResult::decode(result_bytes.as_slice()).unwrap();
assert_eq!(
"cosmos1ajz9y0x3wekez7tz2td2j6l2dftn28v26dd992",
result.accounts[0].address
);
assert_eq!(
"cosmos1nkujjlktqdue52xc0k09yzc7h3xswsfpl568zc",
result.accounts[1].address
);

let params = DeriveSubAccountsParam {
chain_type: "COSMOS".to_string(),
curve: "secp256k1".to_string(),
network: "MAINNET".to_string(),
seg_wit: "".to_string(),
relative_paths: vec!["0/0".to_string(), "0/1".to_string()],
extended_public_key: accounts.accounts[0].extended_public_key.to_string(),
hrp: "osmo".to_string(),
};

let result_bytes = derive_sub_accounts(&encode_message(params).unwrap()).unwrap();
let result = DeriveSubAccountsResult::decode(result_bytes.as_slice()).unwrap();
assert_eq!(
"osmo1ajz9y0x3wekez7tz2td2j6l2dftn28v2jk74nc",
result.accounts[0].address
);
assert_eq!(
"osmo1nkujjlktqdue52xc0k09yzc7h3xswsfph0fh52",
result.accounts[1].address
)
})
}

#[test]
#[serial]
pub fn test_mnemonic_to_public() {
Expand Down
3 changes: 2 additions & 1 deletion token-core/tcx/tests/export_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,8 @@ pub fn test_backup_private_key() {
vec![
"BITCOIN".to_string(),
"BITCOINCASH".to_string(),
"LITECOIN".to_string()
"LITECOIN".to_string(),
"DOGECOIN".to_string()
],
import_result.identified_chain_types
);
Expand Down

0 comments on commit 386d5bb

Please sign in to comment.