diff --git a/key_protocol/Cargo.toml b/key_protocol/Cargo.toml index eeae994..2f2bb07 100644 --- a/key_protocol/Cargo.toml +++ b/key_protocol/Cargo.toml @@ -17,6 +17,7 @@ hex.workspace = true aes-gcm.workspace = true lazy_static.workspace = true tiny-keccak.workspace = true +nssa-core = { path = "../nssa/core" } [dependencies.common] path = "../common" diff --git a/key_protocol/src/key_management/mod.rs b/key_protocol/src/key_management/mod.rs index 2a653af..bc6d14c 100644 --- a/key_protocol/src/key_management/mod.rs +++ b/key_protocol/src/key_management/mod.rs @@ -1,15 +1,15 @@ +use std::collections::HashMap; + use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit}; use constants_types::{CipherText, Nonce}; use elliptic_curve::point::AffineCoordinates; use k256::AffinePoint; use log::info; -use rand::{rngs::OsRng, Rng}; use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder}; use serde::{Deserialize, Serialize}; use crate::key_protocol_core::PublicKey; pub type PublicAccountSigningKey = [u8; 32]; -use nssa::{self}; pub mod constants_types; pub mod ephemeral_key_holder; @@ -20,7 +20,8 @@ pub mod secret_holders; pub struct KeyChain { top_secret_key_holder: TopSecretKeyHolder, pub utxo_secret_key_holder: UTXOSecretKeyHolder, - pub_account_signing_key: nssa::PrivateKey, + ///Map for all users accounts + pub_account_signing_keys: HashMap, pub nullifer_public_key: PublicKey, pub viewing_public_key: PublicKey, } @@ -37,26 +38,50 @@ impl KeyChain { let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key(); let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key(); - let mut rng = OsRng; - let pub_account_signing_key = loop { - match nssa::PrivateKey::try_new(rng.gen()) { - Ok(key) => break key, - Err(_) => continue, - } - }; + Self { + top_secret_key_holder, + utxo_secret_key_holder, + nullifer_public_key, + viewing_public_key, + pub_account_signing_keys: HashMap::new(), + } + } + + pub fn new_os_random_with_accounts(accounts: HashMap) -> Self { + //Currently dropping SeedHolder at the end of initialization. + //Now entirely sure if we need it in the future. + let seed_holder = SeedHolder::new_os_random(); + let top_secret_key_holder = seed_holder.produce_top_secret_key_holder(); + + let utxo_secret_key_holder = top_secret_key_holder.produce_utxo_secret_holder(); + + let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key(); + let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key(); Self { top_secret_key_holder, utxo_secret_key_holder, nullifer_public_key, viewing_public_key, - pub_account_signing_key, + pub_account_signing_keys: accounts, } } + pub fn generate_new_private_key(&mut self) -> nssa::Address { + let private_key = nssa::PrivateKey::new_os_random(); + let address = nssa::Address::from(&nssa::PublicKey::new_from_private_key(&private_key)); + + self.pub_account_signing_keys.insert(address, private_key); + + address + } + /// Returns the signing key for public transaction signatures - pub fn get_pub_account_signing_key(&self) -> &nssa::PrivateKey { - &self.pub_account_signing_key + pub fn get_pub_account_signing_key( + &self, + address: &nssa::Address, + ) -> Option<&nssa::PrivateKey> { + self.pub_account_signing_keys.get(address) } pub fn calculate_shared_secret_receiver( @@ -318,9 +343,15 @@ mod tests { #[test] fn test_get_public_account_signing_key() { - let address_key_holder = KeyChain::new_os_random(); - let signing_key = address_key_holder.get_pub_account_signing_key(); - assert_eq!(signing_key, &address_key_holder.pub_account_signing_key); + let mut address_key_holder = KeyChain::new_os_random(); + + let address = address_key_holder.generate_new_private_key(); + + let is_private_key_generated = address_key_holder + .get_pub_account_signing_key(&address) + .is_some(); + + assert!(is_private_key_generated); } #[test] @@ -333,13 +364,7 @@ mod tests { let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key(); let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key(); - let mut rng = OsRng; - let pub_account_signing_key = loop { - match nssa::PrivateKey::try_new(rng.gen()) { - Ok(key) => break key, - Err(_) => continue, - } - }; + let pub_account_signing_key = nssa::PrivateKey::new_os_random(); let public_key = nssa::PublicKey::new_from_private_key(&pub_account_signing_key); diff --git a/key_protocol/src/key_protocol_core/address.rs b/key_protocol/src/key_protocol_core/address.rs deleted file mode 100644 index 83ce792..0000000 --- a/key_protocol/src/key_protocol_core/address.rs +++ /dev/null @@ -1,3 +0,0 @@ -// TODO: Consider wrapping `AccountAddress` in a struct. - -pub type AccountAddress = [u8; 32]; diff --git a/key_protocol/src/key_protocol_core/mod.rs b/key_protocol/src/key_protocol_core/mod.rs index c50d713..cd9ab39 100644 --- a/key_protocol/src/key_protocol_core/mod.rs +++ b/key_protocol/src/key_protocol_core/mod.rs @@ -1,8 +1,7 @@ +use std::collections::HashMap; + use anyhow::Result; -use common::transaction::Tag; use k256::AffinePoint; -use log::info; -use nssa::Address; use serde::{Deserialize, Serialize}; use crate::key_management::{ @@ -13,58 +12,10 @@ use crate::key_management::{ pub type PublicKey = AffinePoint; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct NSSAUserData { pub key_holder: KeyChain, - pub address: Address, - pub balance: u64, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct NSSAUserDataForSerialization { - pub key_holder: KeyChain, - pub address: Address, - pub balance: u64, -} - -impl From for NSSAUserDataForSerialization { - fn from(value: NSSAUserData) -> Self { - NSSAUserDataForSerialization { - key_holder: value.key_holder, - address: value.address, - balance: value.balance, - } - } -} - -impl From for NSSAUserData { - fn from(value: NSSAUserDataForSerialization) -> Self { - NSSAUserData { - key_holder: value.key_holder, - address: value.address, - balance: value.balance, - } - } -} - -impl Serialize for NSSAUserData { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let account_for_serialization: NSSAUserDataForSerialization = From::from(self.clone()); - account_for_serialization.serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for NSSAUserData { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let account_for_serialization = ::deserialize(deserializer)?; - Ok(account_for_serialization.into()) - } + pub accounts: HashMap, } ///A strucure, which represents all the visible(public) information @@ -76,8 +27,6 @@ impl<'de> Deserialize<'de> for NSSAUserData { pub struct NSSAUserDataPublicMask { pub nullifier_public_key: AffinePoint, pub viewing_public_key: AffinePoint, - pub address: Address, - pub balance: u64, } impl NSSAUserDataPublicMask { @@ -90,39 +39,45 @@ impl NSSAUserDataPublicMask { NSSAUserData::encrypt_data(ephemeral_key_holder, viewing_public_key_receiver, data) } - pub fn make_tag(&self) -> Tag { - self.address.value()[0] - } + //ToDo: Part of a private keys update + // pub fn make_tag(&self) -> Tag { + // self.address.value()[0] + // } } impl NSSAUserData { pub fn new() -> Self { let key_holder = KeyChain::new_os_random(); - let public_key = - nssa::PublicKey::new_from_private_key(key_holder.get_pub_account_signing_key()); - let address = nssa::Address::from(&public_key); - let balance = 0; Self { key_holder, - address, - balance, + accounts: HashMap::new(), } } - pub fn new_with_balance(balance: u64) -> Self { - let key_holder = KeyChain::new_os_random(); - let public_key = - nssa::PublicKey::new_from_private_key(key_holder.get_pub_account_signing_key()); - let address = nssa::Address::from(&public_key); + pub fn new_with_accounts( + accounts_keys: HashMap, + accounts: HashMap, + ) -> Self { + let key_holder = KeyChain::new_os_random_with_accounts(accounts_keys); Self { key_holder, - address, - balance, + accounts, } } + pub fn generate_new_account(&mut self) -> nssa::Address { + let address = self.key_holder.generate_new_private_key(); + self.accounts.insert(address, nssa_core::account::Account::default()); + + address + } + + pub fn get_account_balance(&self, address: &nssa::Address) -> u128 { + self.accounts.get(address).map(|acc| acc.balance).unwrap_or(0) + } + pub fn encrypt_data( ephemeral_key_holder: &EphemeralKeyHolder, viewing_public_key_receiver: AffinePoint, @@ -141,27 +96,23 @@ impl NSSAUserData { .decrypt_data(ephemeral_public_key_sender, ciphertext, nonce) } - pub fn update_public_balance(&mut self, new_balance: u64) { - self.balance = new_balance; + pub fn update_account_balance(&mut self, address: nssa::Address, new_balance: u128) { + self.accounts + .entry(address) + .and_modify(|acc| acc.balance = new_balance) + .or_insert(nssa_core::account::Account::default()); } - pub fn log(&self) { - info!("Keys generated"); - info!("NSSAUserData address is {:?}", hex::encode(self.address)); - info!("NSSAUserData balance is {:?}", self.balance); - } - - pub fn make_tag(&self) -> Tag { - self.address.value()[0] - } + //ToDo: Part of a private keys update + // pub fn make_tag(&self) -> Tag { + // self.address.value()[0] + // } ///Produce account public mask pub fn make_account_public_mask(&self) -> NSSAUserDataPublicMask { NSSAUserDataPublicMask { nullifier_public_key: self.key_holder.nullifer_public_key, viewing_public_key: self.key_holder.viewing_public_key, - address: self.address, - balance: self.balance, } } } @@ -178,25 +129,31 @@ mod tests { #[test] fn test_new_account() { - let account = NSSAUserData::new(); + let mut user_data = NSSAUserData::new(); - assert_eq!(account.balance, 0); + let addr = user_data.generate_new_account(); + + assert_eq!(user_data.get_account_balance(&addr), 0); } #[test] - fn test_update_public_balance() { - let mut account = NSSAUserData::new(); - account.update_public_balance(500); + fn test_update_balance() { + let mut user_data = NSSAUserData::new(); - assert_eq!(account.balance, 500); + let address = user_data.generate_new_account(); + + user_data.update_account_balance(address, 500); + + assert_eq!(user_data.get_account_balance(&address), 500); } - #[test] - fn accounts_accounts_mask_tag_consistency() { - let account = NSSAUserData::new(); + //ToDo: Part of a private keys update + // #[test] + // fn accounts_accounts_mask_tag_consistency() { + // let account = NSSAUserData::new(); - let account_mask = account.make_account_public_mask(); + // let account_mask = account.make_account_public_mask(); - assert_eq!(account.make_tag(), account_mask.make_tag()); - } + // assert_eq!(account.make_tag(), account_mask.make_tag()); + // } } diff --git a/key_protocol/src/lib.rs b/key_protocol/src/lib.rs index 5adef9e..1a52c20 100644 --- a/key_protocol/src/lib.rs +++ b/key_protocol/src/lib.rs @@ -1,2 +1,2 @@ -pub mod key_protocol_core; pub mod key_management; +pub mod key_protocol_core; diff --git a/nssa/src/signature/private_key.rs b/nssa/src/signature/private_key.rs index b35d7da..abe5af6 100644 --- a/nssa/src/signature/private_key.rs +++ b/nssa/src/signature/private_key.rs @@ -1,3 +1,4 @@ +use rand::{Rng, rngs::OsRng}; use serde::{Deserialize, Serialize}; use crate::error::NssaError; @@ -8,6 +9,17 @@ use crate::error::NssaError; pub struct PrivateKey([u8; 32]); impl PrivateKey { + pub fn new_os_random() -> Self { + let mut rng = OsRng; + + loop { + match Self::try_new(rng.r#gen()) { + Ok(key) => break key, + Err(_) => continue, + }; + } + } + fn is_valid_key(value: [u8; 32]) -> bool { secp256k1::SecretKey::from_byte_array(value).is_ok() } @@ -33,4 +45,10 @@ mod tests { let key = PrivateKey::try_new([1; 32]).unwrap(); assert_eq!(key.value(), &key.0); } + + #[test] + fn test_produce_key() { + let key = PrivateKey::new_os_random(); + println!("{:?}", key.0); + } } diff --git a/wallet/src/chain_storage/mod.rs b/wallet/src/chain_storage/mod.rs index 8c57284..80a14f8 100644 --- a/wallet/src/chain_storage/mod.rs +++ b/wallet/src/chain_storage/mod.rs @@ -1,9 +1,9 @@ use std::collections::HashMap; //TODO: NOT USER DATA, ACCOUNT -use key_protocol::key_protocol_core::NSSAUserData; use anyhow::Result; use common::merkle_tree_public::merkle_tree::UTXOCommitmentsMerkleTree; +use key_protocol::key_protocol_core::NSSAUserData; use nssa::Address; use serde::{Deserialize, Serialize}; diff --git a/wallet/src/config.rs b/wallet/src/config.rs index 087762b..a6bf634 100644 --- a/wallet/src/config.rs +++ b/wallet/src/config.rs @@ -32,7 +32,7 @@ pub struct WalletConfig { ///Sequencer polling duration for new blocks in seconds pub seq_poll_timeout_secs: u64, ///Initial accounts for wallet - /// + /// /// TODO: NOT USRE DATA, ACCOUNT pub initial_accounts: Vec, } diff --git a/wallet/src/helperfunctions.rs b/wallet/src/helperfunctions.rs index 790d9d6..334129b 100644 --- a/wallet/src/helperfunctions.rs +++ b/wallet/src/helperfunctions.rs @@ -1,7 +1,7 @@ use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr}; -use key_protocol::key_protocol_core::NSSAUserData; use anyhow::Result; +use key_protocol::key_protocol_core::NSSAUserData; use nssa::Address; use crate::{config::WalletConfig, HOME_DIR_ENV_VAR}; @@ -28,7 +28,7 @@ pub fn produce_account_addr_from_hex(hex_str: String) -> Result
{ ///Fetch list of accounts stored at `NSSA_WALLET_HOME_DIR/curr_accounts.json` /// /// If file not present, it is considered as empty list of persistent accounts -/// +/// /// ToDo: NOT USER DATA, ACCOUNT pub fn fetch_persistent_accounts() -> Result> { let home = get_home()?; diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 5746bcf..a8ab45f 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -5,10 +5,10 @@ use common::{ ExecutionFailureKind, }; -use key_protocol::key_protocol_core::NSSAUserData; use anyhow::Result; use chain_storage::WalletChainStore; use config::WalletConfig; +use key_protocol::key_protocol_core::NSSAUserData; use log::info; use nssa::Address; @@ -55,7 +55,6 @@ impl WalletCore { pub async fn create_new_account(&mut self) -> Address { let account = NSSAUserData::new(); - account.log(); let addr = account.address;