Skip to content

Commit

Permalink
hotfix: import private key of dogecoin (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
tyrone98 authored Aug 16, 2024
1 parent e244c49 commit d4f34db
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 10 deletions.
2 changes: 1 addition & 1 deletion imkey-core/ikc-wallet/coin-bitcoin/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use ikc_common::utility::{bigint_to_byte_vec, hex_to_bytes, secp256k1_sign};
use ikc_device::device_binding::KEY_MANAGER;
use ikc_transport::message::{send_apdu, send_apdu_timeout};
use secp256k1::ecdsa::Signature;
use secp256k1::PublicKey;
use std::borrow::Borrow;
use std::str::FromStr;
use secp256k1::PublicKey;

#[derive(Clone)]
pub struct Utxo {
Expand Down
31 changes: 31 additions & 0 deletions token-core/tcx-btc-kin/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ impl Display for BtcKinAddress {
#[cfg(test)]
mod tests {
use bitcoin::SchnorrSighashType::Default;
use secp256k1::rand::seq::index::sample;
use std::str::FromStr;
use tcx_common::{FromHex, ToHex};

Expand Down Expand Up @@ -511,6 +512,36 @@ mod tests {
assert_eq!(account.ext_pub_key, "xpub6CDSaXHQokkKmHHG2kNCFZeirJkcZgRZE97ZZUtViif3SFHSNVAvRpWC3CxeRt2VZetEGCcPTmWEFpKF4NDeeZrMNPQgfUaX5Hkw89kW8qE");
}

#[test]
fn test_dogecoin_address_from_str() {
let addr = BtcKinAddress::from_str("DQ4tVEqdPWHc1aVBm4Sfwft8XyNRPMEchR").unwrap();
assert_eq!(addr.network.coin, "DOGECOIN");
assert_eq!(addr.network.network, "MAINNET");
}

#[test]
fn test_xpub() {
let mut hd = sample_hd_keystore();

let test_cases = [
("BITCOIN", "MAINNET", "m/44'/0'/0/0", "xpub6CqzLtyBHdq6tZD7Bdxo9bpCEWfFBg7dim6UMxs83nqNYzFatwkr9yGkLtG5ktiKcgaUqP5BpuTMJLyaLQ167gANU8ZsfLRN86VXyx3atJX"),
("LITECOIN", "MAINNET", "m/44'/2'/0'/0/0", "xpub6D3MqTwuLWB5veAfhDjPu1oHfS6L1imVbf22zQFWJW9EtnSmYYqiGMGkW1MCsT2HmkW872tefMY9deewW6DGd8zE7RcXVv8wKhZnbJeidjT"),
("DOGECOIN", "MAINNET", "m/44'/3'/0'/0/0", "xpub6CDSaXHQokkKmHHG2kNCFZeirJkcZgRZE97ZZUtViif3SFHSNVAvRpWC3CxeRt2VZetEGCcPTmWEFpKF4NDeeZrMNPQgfUaX5Hkw89kW8qE"),
];

for (coin, network, path, xpub) in test_cases {
let coin_info = CoinInfo {
coin: coin.to_string(),
derivation_path: path.to_string(),
curve: CurveType::SECP256k1,
network: network.to_string(),
seg_wit: "NONE".to_string(),
hrp: "".to_string(),
};
let account = hd.derive_coin::<BtcKinAddress>(&coin_info).unwrap();
assert_eq!(account.ext_pub_key, xpub);
}
}

#[test]
fn test_bip84_spec_vector() {
Expand Down
24 changes: 16 additions & 8 deletions token-core/tcx-constants/src/coin_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,56 +302,64 @@ lazy_static! {
curve: CurveType::SECP256k1,
network: "MAINNET".to_string(),
seg_wit: "NONE".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
CoinInfo {
coin: "DOGECOIN".to_string(),
derivation_path: "m/44'/1'/0'/0/0".to_string(),
curve: CurveType::SECP256k1,
network: "TESTNET".to_string(),
seg_wit: "NONE".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
CoinInfo {
coin: "DOGECOIN".to_string(),
derivation_path: "m/49'/3'/0'/0/0".to_string(),
curve: CurveType::SECP256k1,
network: "MAINNET".to_string(),
seg_wit: "P2WPKH".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
CoinInfo {
coin: "DOGECOIN".to_string(),
derivation_path: "m/49'/1'/0'/0/0".to_string(),
curve: CurveType::SECP256k1,
network: "TESTNET".to_string(),
seg_wit: "P2WPKH".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
CoinInfo {
coin: "DOGECOIN".to_string(),
derivation_path: "m/84'/3'/0'/0/0".to_string(),
curve: CurveType::SECP256k1,
network: "MAINNET".to_string(),
seg_wit: "VERSION_0".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
CoinInfo {
coin: "DOGECOIN".to_string(),
derivation_path: "m/84'/1'/0'/0/0".to_string(),
curve: CurveType::SECP256k1,
network: "TESTNET".to_string(),
seg_wit: "VERSION_0".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
CoinInfo {
coin: "DOGECOIN".to_string(),
derivation_path: "m/86'/3'/0'/0/0".to_string(),
curve: CurveType::SECP256k1,
network: "MAINNET".to_string(),
seg_wit: "VERSION_1".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
CoinInfo {
coin: "DOGECOIN".to_string(),
derivation_path: "m/86'/1'/0'/0/0".to_string(),
curve: CurveType::SECP256k1,
network: "TESTNET".to_string(),
seg_wit: "VERSION_1".to_string(),
hrp: "".to_string(),},
hrp: "".to_string(),
},
];

RwLock::new(coin_infos)
Expand Down
5 changes: 5 additions & 0 deletions token-core/tcx/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ pub(crate) fn decode_private_key(private_key: &str) -> Result<DecodedPrivateKey>
chain_types.push("BITCOIN".to_string());
chain_types.push("BITCOINCASH".to_string());
chain_types.push("LITECOIN".to_string());
chain_types.push("DOGECOIN".to_string());
}
0x80 => {
if data_len == 37 {
Expand All @@ -310,6 +311,10 @@ pub(crate) fn decode_private_key(private_key: &str) -> Result<DecodedPrivateKey>
network = "MAINNET".to_string();
chain_types.push("LITECOIN".to_string());
}
0x9e => {
network = "MAINNET".to_string();
chain_types.push("DOGECOIN".to_string());
}
_ => return Err(anyhow!("unknow ver header when parse wif, ver: {}", ver[0])),
}
}
Expand Down
83 changes: 82 additions & 1 deletion token-core/tcx/tests/import_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,15 @@ pub fn test_import_private_key() {
curve: "secp256k1".to_string(),
hrp: "".to_string(),
},
Derivation {
chain_type: "DOGECOIN".to_string(),
path: "pk_not_need_path".to_string(),
network: "MAINNET".to_string(),
seg_wit: "NONE".to_string(),
chain_id: "".to_string(),
curve: "secp256k1".to_string(),
hrp: "".to_string(),
},
];
let param = DeriveAccountsParam {
id: import_result.id.to_string(),
Expand All @@ -322,7 +331,7 @@ pub fn test_import_private_key() {
let derived_accounts_bytes = call_api("derive_accounts", param).unwrap();
let derived_accounts: DeriveAccountsResult =
DeriveAccountsResult::decode(derived_accounts_bytes.as_slice()).unwrap();
assert_eq!(13, derived_accounts.accounts.len());
assert_eq!(14, derived_accounts.accounts.len());
assert_eq!(
"LgGNTHMkgETS7oQcoekvACJQcH355xECog",
derived_accounts.accounts[0].address
Expand Down Expand Up @@ -392,6 +401,11 @@ pub fn test_import_private_key() {
derived_accounts.accounts[12].address
);

assert_eq!(
"DSBWjKzZtz7fPzu4N6mBRwQFHCQ6KQSjue",
derived_accounts.accounts[13].address
);

// pk rederive
let derivations = vec![Derivation {
chain_type: "LITECOIN".to_string(),
Expand Down Expand Up @@ -1079,6 +1093,73 @@ pub fn test_import_multi_curve() {
})
}

#[test]
#[serial]
pub fn test_import_wif() {
run_test(|| {
let import_result: KeystoreResult = import_default_wallet();

let export_param = ExportPrivateKeyParam {
id: import_result.id.to_string(),
key: Some(crate::api::export_private_key_param::Key::Password(
TEST_PASSWORD.to_owned(),
)),
chain_type: "DOGECOIN".to_string(),
network: "MAINNET".to_string(),
curve: "secp256k1".to_string(),
path: "m/44'/3'/0'/0'".to_string(),
};

let export_pk_bytes = call_api("export_private_key", export_param).unwrap();
let export_pk: ExportPrivateKeyResult =
ExportPrivateKeyResult::decode(export_pk_bytes.as_slice()).unwrap();
assert_eq!(
export_pk.private_key,
"QNfA3BhQaV73MY3QMYAoNrZXSPRyVqUFxb4akc6hBpN6TwZC8GDQ"
);

let param: ImportPrivateKeyParam = ImportPrivateKeyParam {
private_key: export_pk.private_key.to_string(),
password: TEST_PASSWORD.to_string(),
name: "import_private_key_wallet".to_string(),
password_hint: "".to_string(),
network: "MAINNET".to_string(),
overwrite_id: "".to_string(),
};
let ret = call_api("import_private_key", param).unwrap();
let import_result: ImportPrivateKeyResult =
ImportPrivateKeyResult::decode(ret.as_slice()).unwrap();

let derivation = Derivation {
chain_type: "DOGECOIN".to_string(),
path: "m/44'/145'/0'/0/0".to_string(),
network: "MAINNET".to_string(),
seg_wit: "NONE".to_string(),
chain_id: "".to_string(),
curve: "secp256k1".to_string(),
hrp: "".to_string(),
};
let param = DeriveAccountsParam {
id: import_result.id.to_string(),
key: Some(crate::api::derive_accounts_param::Key::Password(
TEST_PASSWORD.to_owned(),
)),
derivations: vec![derivation],
};

let ret = call_api("derive_accounts", param).unwrap();
let result: DeriveAccountsResult = DeriveAccountsResult::decode(ret.as_slice()).unwrap();
let account = result.accounts.first().unwrap();
assert_eq!(account.chain_type, "DOGECOIN");
assert_eq!(account.address, "DGge46gf1ipekESG6eDFYxA15PxWf2UfrS");

assert_eq!(
import_result.identifier,
"im14x5EL1LDHgsXPpvzsF5RQCKE982c9XmM1VZx"
);
})
}

#[test]
#[serial]
pub fn test_import_hex_private_key() {
Expand Down

0 comments on commit d4f34db

Please sign in to comment.