Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ aes-gcm = "0.10" # AES-256-GCM (quantum-safe with 256-bit keys)
# Quantus crypto dependencies (aligned with chain)
qp-rusty-crystals-dilithium = { version = "2.4.0" }
qp-rusty-crystals-hdwallet = { version = "2.3.0" }
qp-dilithium-crypto = { version = "0.2.5", features = ["serde"] }
qp-dilithium-crypto = { version = "0.3.0", features = ["serde"] }
qp-poseidon = { version = "1.4.0" }

# HTTP client for Subsquid queries
Expand Down
1 change: 0 additions & 1 deletion src/wallet/keystore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ impl QuantumKeyPair {
.map_err(|_| WalletError::KeyGeneration.into())
}

#[allow(dead_code)]
pub fn from_resonance_pair(keypair: &DilithiumPair) -> Self {
use sp_core::Pair;
Self {
Expand Down
37 changes: 19 additions & 18 deletions src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ pub mod password;

use crate::error::{Result, WalletError};
pub use keystore::{Keystore, QuantumKeyPair, WalletData};
use qp_rusty_crystals_hdwallet::{derive_key_from_mnemonic, generate_mnemonic, SensitiveBytes32};
use qp_dilithium_crypto::DilithiumPair;
use qp_rusty_crystals_hdwallet::{
derive_key_from_mnemonic, generate_mnemonic, mnemonic_to_seed, SensitiveBytes32,
};
use rand::{rng, RngCore};
use serde::{Deserialize, Serialize};
use sp_runtime::traits::IdentifyAccount;
Expand Down Expand Up @@ -75,13 +78,10 @@ impl WalletManager {
.map_err(|_| WalletError::KeyGeneration)?;
let quantum_keypair = QuantumKeyPair::from_dilithium_keypair(&dilithium_keypair);

// Create wallet data
let mut metadata = std::collections::HashMap::new();
metadata.insert("version".to_string(), "1.0.0".to_string());
metadata.insert("algorithm".to_string(), "ML-DSA-87".to_string());
metadata.insert("derivation_path".to_string(), derivation_path.to_string());

// Generate address from public key (simplified version)
let address = quantum_keypair.to_account_id_ss58check();

let wallet_data = WalletData {
Expand Down Expand Up @@ -217,15 +217,15 @@ impl WalletManager {
return Err(WalletError::AlreadyExists.into());
}

// Generate new mnemonic and use master seed directly (no derivation path)
let mut seed = [0u8; 32];
rng().fill_bytes(&mut seed);
let sensitive_seed = SensitiveBytes32::from(&mut seed);
let mnemonic = generate_mnemonic(sensitive_seed).map_err(|_| WalletError::KeyGeneration)?;
// For "no derivation" mode, we use the root path m/
let dilithium_keypair = derive_key_from_mnemonic(&mnemonic, None, "m/44'/189189'/0'")
.map_err(|_| WalletError::KeyGeneration)?;
let quantum_keypair = QuantumKeyPair::from_dilithium_keypair(&dilithium_keypair);
let seed64 =
mnemonic_to_seed(mnemonic.clone(), None).map_err(|_| WalletError::KeyGeneration)?;
let dilithium_pair =
DilithiumPair::from_seed(&seed64).map_err(|_| WalletError::KeyGeneration)?;
let quantum_keypair = QuantumKeyPair::from_resonance_pair(&dilithium_pair);

// Create wallet data
let mut metadata = std::collections::HashMap::new();
Expand Down Expand Up @@ -271,10 +271,12 @@ impl WalletManager {
return Err(WalletError::AlreadyExists.into());
}

// Use mnemonic to generate keys directly (no derivation path)
let dilithium_keypair = derive_key_from_mnemonic(mnemonic, None, "m/44'/189189'/0'")
// No derivation path - get the seed and create a key from the seed
let seed64 = mnemonic_to_seed(mnemonic.to_string(), None)
.map_err(|_| WalletError::InvalidMnemonic)?;
let quantum_keypair = QuantumKeyPair::from_dilithium_keypair(&dilithium_keypair);
let dilithium_pair =
DilithiumPair::from_seed(&seed64).map_err(|_| WalletError::KeyGeneration)?;
let quantum_keypair = QuantumKeyPair::from_resonance_pair(&dilithium_pair);

// Create wallet data
let mut metadata = std::collections::HashMap::new();
Expand Down Expand Up @@ -322,10 +324,9 @@ impl WalletManager {
return Err(WalletError::AlreadyExists.into());
}

// Validate and import from mnemonic using derivation path
let dilithium_keypair = derive_key_from_mnemonic(mnemonic, None, derivation_path)
let dilithium_pair = derive_key_from_mnemonic(mnemonic, None, derivation_path)
.map_err(|_| WalletError::InvalidMnemonic)?;
let quantum_keypair = QuantumKeyPair::from_dilithium_keypair(&dilithium_keypair);
let quantum_keypair = QuantumKeyPair::from_dilithium_keypair(&dilithium_pair);

// Create wallet data
let mut metadata = std::collections::HashMap::new();
Expand Down Expand Up @@ -773,8 +774,8 @@ mod tests {

let (wallet_manager, _temp_dir) = create_test_wallet_manager().await;
let test_mnemonic = "orchard answer curve patient visual flower maze noise retreat penalty cage small earth domain scan pitch bottom crunch theme club client swap slice raven";
let expected_address = "qzpJj8HRv7m9Ur9fYRsGFMggz4FLtMQEEi1rTPsKQZJUttjkV";
let expected_address_no_derive = "qzpFin6y47r9MDdH2cxhGDENagYKVTn7Fkvy7XRJh7f7L9qvJ";
let expected_address_no_derive = "qzmTAz3UUw1WGUuVh8nbFmPwcftomduwy6twq6NDR6y9qqtEs";
let expected_address_hd_0 = "qzm5QCox8Dp5A3oSXZZYHD8YoYgPz7enykZb6RPUropdCyN5h";

let imported_wallet = wallet_manager
.import_wallet("imported-test-wallet", test_mnemonic, Some("import-password"))
Expand All @@ -790,7 +791,7 @@ mod tests {
.await
.expect("Failed to import wallet");

assert_eq!(imported_wallet.address, expected_address, "address at index 0 is wrong");
assert_eq!(imported_wallet.address, expected_address_hd_0, "address at index 0 is wrong");
assert_eq!(
imported_wallet_no_derive.address, expected_address_no_derive,
"no-derivation address is wrong"
Expand Down
Loading