diff --git a/src/components/wasm/src/wasm.rs b/src/components/wasm/src/wasm.rs index 55a6e4259..4d0268f39 100644 --- a/src/components/wasm/src/wasm.rs +++ b/src/components/wasm/src/wasm.rs @@ -75,7 +75,7 @@ use { open_blind_asset_record as open_bar, AssetRecordType, AssetRecordType::NonConfidentialAmount_NonConfidentialAssetType, }, - sig::{XfrKeyPair, XfrPublicKey, XfrSecretKey}, + sig::{KeyType, XfrKeyPair, XfrPublicKey, XfrSecretKey}, structs::{ AssetRecordTemplate, AssetType as NoahAssetType, XfrBody, ASSET_TYPE_LENGTH, @@ -1826,6 +1826,12 @@ use ring::pbkdf2; use std::num::NonZeroU32; use std::str; +#[wasm_bindgen] +/// Returns human-readable encoded representation of an XfrPublicKey. +pub fn public_key_to_human(key: &XfrPublicKey) -> String { + wallet::public_key_to_human(key) +} + #[wasm_bindgen] /// Returns bech32 encoded representation of an XfrPublicKey. pub fn public_key_to_bech32(key: &XfrPublicKey) -> String { @@ -1940,6 +1946,20 @@ pub fn create_keypair_from_secret(sk_str: String) -> Result Ok(sk.into_keypair()) } +#[wasm_bindgen] +#[allow(missing_docs)] +pub fn create_keypair_from_secret_secp256k1( + sk_str: String, +) -> Result { + let mut bytes = vec![KeyType::Secp256k1.to_byte()]; + bytes.extend(hex::decode(&sk_str).c(d!()).map_err(error_to_jsvalue)?); + let sk = XfrSecretKey::noah_from_bytes(&bytes) + .c(d!()) + .map_err(error_to_jsvalue)?; + + Ok(sk.into_keypair()) +} + #[wasm_bindgen] #[allow(missing_docs)] pub fn get_pk_from_keypair(kp: &XfrKeyPair) -> XfrPublicKey { diff --git a/src/libs/globutils/Cargo.toml b/src/libs/globutils/Cargo.toml index 01bc71da1..4ba1a5a7f 100644 --- a/src/libs/globutils/Cargo.toml +++ b/src/libs/globutils/Cargo.toml @@ -26,6 +26,7 @@ ed25519-dalek-bip32 = { git = "https://github.com/FindoraNetwork/ed25519-dalek-b tracing = "0.1.13" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } bs58 = "0.4" +sha3 = "0.10" [dev-dependencies] rand_chacha = "0.3" diff --git a/src/libs/globutils/src/wallet.rs b/src/libs/globutils/src/wallet.rs index cddc6207d..59ad3b21c 100644 --- a/src/libs/globutils/src/wallet.rs +++ b/src/libs/globutils/src/wallet.rs @@ -8,16 +8,18 @@ use bech32::{self, FromBase32, ToBase32}; use bip0039::{Count, Language, Mnemonic}; use ed25519_dalek_bip32::{DerivationPath, ExtendedSecretKey}; use noah::anon_xfr::structs::Nullifier; +use noah::xfr::sig::XfrPublicKeyInner; use noah::{ anon_xfr::{ keys::{AXfrKeyPair, AXfrPubKey}, structs::Commitment, }, - xfr::sig::{XfrKeyPair, XfrPublicKey, XfrSecretKey}, + xfr::sig::{KeyType, XfrKeyPair, XfrPublicKey, XfrSecretKey}, }; use noah_algebra::serialization::NoahFromToBytes; use noah_crypto::basic::hybrid_encryption::{XPublicKey, XSecretKey}; use ruc::*; +use sha3::{Digest, Keccak256}; /// Randomly generate a 12words-length mnemonic. #[inline(always)] @@ -313,17 +315,46 @@ pub fn nullifier_to_base58(n: &Nullifier) -> String { bs58::encode(&Nullifier::noah_to_bytes(n)).into_string() } +/// Convert a XfrPublicKey to human-readable address +#[inline(always)] +pub fn public_key_to_human(key: &XfrPublicKey) -> String { + match key.inner() { + XfrPublicKeyInner::Ed25519(_) | XfrPublicKeyInner::Secp256k1(_) => { + public_key_to_bech32(key) + } + XfrPublicKeyInner::Address(bytes) => { + // checksum encode + let hex = hex::encode(bytes); + + let mut hasher = Keccak256::new(); + hasher.update(hex.as_bytes()); + let hash = hasher.finalize(); + let check_hash = hex::encode(hash); + + let mut res = String::from("0x"); + for (index, byte) in hex[..40].chars().enumerate() { + if check_hash.chars().nth(index).unwrap().to_digit(16).unwrap() > 7 { + res += &byte.to_uppercase().to_string(); + } else { + res += &byte.to_string(); + } + } + res + } + } +} + /// Convert a XfrPublicKey to bech32 human-readable address #[inline(always)] pub fn public_key_to_bech32(key: &XfrPublicKey) -> String { let bytes = &XfrPublicKey::noah_to_bytes(key); - match bytes[0] { - 0u8 => bech32enc_fra(<&[u8; 32]>::try_from(&bytes[1..33]).unwrap()), - 1u8 => bech32enc_eth(<&[u8; 33]>::try_from(&bytes[1..34]).unwrap()), - 2u8 => { - panic!("public key not supported") + let keytype = KeyType::from_byte(bytes[0]); + match keytype { + KeyType::Ed25519 => bech32enc_fra(<&[u8; 32]>::try_from(&bytes[1..33]).unwrap()), + KeyType::Secp256k1 => { + bech32enc_eth(<&[u8; 33]>::try_from(&bytes[1..34]).unwrap()) } - _ => { + KeyType::Address => { panic!("public key not supported") } }