mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-05 23:03:06 +00:00
fix: first batch of wallet methods
This commit is contained in:
parent
0abb23e26a
commit
0c7456d7a0
@ -7,6 +7,7 @@ use json::{SendTxRequest, SendTxResponse, SequencerRpcRequest, SequencerRpcRespo
|
|||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use crate::rpc_primitives::requests::{GetTransactionByHashRequest, GetTransactionByHashResponse};
|
||||||
use crate::sequencer_client::json::AccountInitialData;
|
use crate::sequencer_client::json::AccountInitialData;
|
||||||
use crate::{SequencerClientError, SequencerRpcError};
|
use crate::{SequencerClientError, SequencerRpcError};
|
||||||
|
|
||||||
@ -137,4 +138,22 @@ impl SequencerClient {
|
|||||||
|
|
||||||
Ok(resp_deser)
|
Ok(resp_deser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Get tx data for `tx_hash` from sequencer
|
||||||
|
pub async fn get_transaction_by_hash(
|
||||||
|
&self,
|
||||||
|
tx_hash: String,
|
||||||
|
) -> Result<GetTransactionByHashResponse, SequencerClientError> {
|
||||||
|
let block_req = GetTransactionByHashRequest { hash: tx_hash };
|
||||||
|
|
||||||
|
let req = serde_json::to_value(block_req)?;
|
||||||
|
|
||||||
|
let resp = self
|
||||||
|
.call_method_with_payload("get_transaction_by_hash", req)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let resp_deser = serde_json::from_value(resp)?;
|
||||||
|
|
||||||
|
Ok(resp_deser)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit};
|
use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit};
|
||||||
use constants_types::{CipherText, Nonce};
|
use constants_types::{CipherText, Nonce};
|
||||||
use elliptic_curve::point::AffineCoordinates;
|
use elliptic_curve::point::AffineCoordinates;
|
||||||
@ -20,8 +18,6 @@ pub mod secret_holders;
|
|||||||
pub struct KeyChain {
|
pub struct KeyChain {
|
||||||
top_secret_key_holder: TopSecretKeyHolder,
|
top_secret_key_holder: TopSecretKeyHolder,
|
||||||
pub utxo_secret_key_holder: UTXOSecretKeyHolder,
|
pub utxo_secret_key_holder: UTXOSecretKeyHolder,
|
||||||
///Map for all users accounts
|
|
||||||
pub_account_signing_keys: HashMap<nssa::Address, nssa::PrivateKey>,
|
|
||||||
pub nullifer_public_key: PublicKey,
|
pub nullifer_public_key: PublicKey,
|
||||||
pub viewing_public_key: PublicKey,
|
pub viewing_public_key: PublicKey,
|
||||||
}
|
}
|
||||||
@ -43,47 +39,9 @@ impl KeyChain {
|
|||||||
utxo_secret_key_holder,
|
utxo_secret_key_holder,
|
||||||
nullifer_public_key,
|
nullifer_public_key,
|
||||||
viewing_public_key,
|
viewing_public_key,
|
||||||
pub_account_signing_keys: HashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_os_random_with_accounts(accounts: HashMap<nssa::Address, nssa::PrivateKey>) -> 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_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,
|
|
||||||
address: &nssa::Address,
|
|
||||||
) -> Option<&nssa::PrivateKey> {
|
|
||||||
self.pub_account_signing_keys.get(address)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn calculate_shared_secret_receiver(
|
pub fn calculate_shared_secret_receiver(
|
||||||
&self,
|
&self,
|
||||||
ephemeral_public_key_sender: AffinePoint,
|
ephemeral_public_key_sender: AffinePoint,
|
||||||
@ -341,19 +299,6 @@ mod tests {
|
|||||||
assert_eq!(decrypted_data, plaintext);
|
assert_eq!(decrypted_data, plaintext);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_public_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]
|
#[test]
|
||||||
fn key_generation_test() {
|
fn key_generation_test() {
|
||||||
let seed_holder = SeedHolder::new_os_random();
|
let seed_holder = SeedHolder::new_os_random();
|
||||||
|
|||||||
@ -15,7 +15,8 @@ pub type PublicKey = AffinePoint;
|
|||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct NSSAUserData {
|
pub struct NSSAUserData {
|
||||||
pub key_holder: KeyChain,
|
pub key_holder: KeyChain,
|
||||||
pub accounts: HashMap<nssa::Address, nssa_core::account::Account>,
|
///Map for all users accounts
|
||||||
|
pub accounts: HashMap<nssa::Address, (nssa::PrivateKey, nssa_core::account::Account)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
///A strucure, which represents all the visible(public) information
|
///A strucure, which represents all the visible(public) information
|
||||||
@ -56,21 +57,22 @@ impl NSSAUserData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_accounts(
|
pub fn new_with_accounts(
|
||||||
accounts_keys: HashMap<nssa::Address, nssa::PrivateKey>,
|
accounts_data: HashMap<nssa::Address, (nssa::PrivateKey, nssa_core::account::Account)>,
|
||||||
accounts: HashMap<nssa::Address, nssa_core::account::Account>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let key_holder = KeyChain::new_os_random_with_accounts(accounts_keys);
|
let key_holder = KeyChain::new_os_random();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
key_holder,
|
key_holder,
|
||||||
accounts,
|
accounts: accounts_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_new_account(&mut self) -> nssa::Address {
|
pub fn generate_new_account(&mut self) -> nssa::Address {
|
||||||
let address = self.key_holder.generate_new_private_key();
|
let private_key = nssa::PrivateKey::new_os_random();
|
||||||
self.accounts
|
let address = nssa::Address::from(&nssa::PublicKey::new_from_private_key(&private_key));
|
||||||
.insert(address, nssa_core::account::Account::default());
|
let account = nssa_core::account::Account::default();
|
||||||
|
|
||||||
|
self.accounts.insert(address, (private_key, account));
|
||||||
|
|
||||||
address
|
address
|
||||||
}
|
}
|
||||||
@ -78,16 +80,16 @@ impl NSSAUserData {
|
|||||||
pub fn get_account_balance(&self, address: &nssa::Address) -> u128 {
|
pub fn get_account_balance(&self, address: &nssa::Address) -> u128 {
|
||||||
self.accounts
|
self.accounts
|
||||||
.get(address)
|
.get(address)
|
||||||
.map(|acc| acc.balance)
|
.map(|(_, acc)| acc.balance)
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_account(&self, address: &nssa::Address) -> Option<&nssa_core::account::Account> {
|
pub fn get_account(&self, address: &nssa::Address) -> Option<&nssa_core::account::Account> {
|
||||||
self.accounts.get(address)
|
self.accounts.get(address).map(|(_, acc)| acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_account_signing_key(&self, address: &nssa::Address) -> Option<&nssa::PrivateKey> {
|
pub fn get_account_signing_key(&self, address: &nssa::Address) -> Option<&nssa::PrivateKey> {
|
||||||
self.key_holder.get_pub_account_signing_key(address)
|
self.accounts.get(address).map(|(key, _)| key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt_data(
|
pub fn encrypt_data(
|
||||||
@ -111,8 +113,7 @@ impl NSSAUserData {
|
|||||||
pub fn update_account_balance(&mut self, address: nssa::Address, new_balance: u128) {
|
pub fn update_account_balance(&mut self, address: nssa::Address, new_balance: u128) {
|
||||||
self.accounts
|
self.accounts
|
||||||
.entry(address)
|
.entry(address)
|
||||||
.and_modify(|acc| acc.balance = new_balance)
|
.and_modify(|(_, acc)| acc.balance = new_balance);
|
||||||
.or_default();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ToDo: Part of a private keys update
|
//ToDo: Part of a private keys update
|
||||||
|
|||||||
@ -14,24 +14,23 @@ pub struct WalletChainStore {
|
|||||||
|
|
||||||
impl WalletChainStore {
|
impl WalletChainStore {
|
||||||
pub fn new(config: WalletConfig) -> Result<Self> {
|
pub fn new(config: WalletConfig) -> Result<Self> {
|
||||||
let accounts: HashMap<nssa::Address, nssa_core::account::Account> = config
|
let accounts_data: HashMap<nssa::Address, (nssa::PrivateKey, nssa_core::account::Account)> =
|
||||||
.initial_accounts
|
config
|
||||||
.clone()
|
.initial_accounts
|
||||||
.into_iter()
|
.clone()
|
||||||
.map(|init_acc_data| (init_acc_data.address, init_acc_data.account))
|
.into_iter()
|
||||||
.collect();
|
.map(|init_acc_data| {
|
||||||
|
(
|
||||||
let accounts_keys: HashMap<nssa::Address, nssa::PrivateKey> = config
|
init_acc_data.address,
|
||||||
.initial_accounts
|
(init_acc_data.pub_sign_key, init_acc_data.account),
|
||||||
.clone()
|
)
|
||||||
.into_iter()
|
})
|
||||||
.map(|init_acc_data| (init_acc_data.address, init_acc_data.pub_sign_key))
|
.collect();
|
||||||
.collect();
|
|
||||||
|
|
||||||
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
user_data: NSSAUserData::new_with_accounts(accounts_keys, accounts),
|
user_data: NSSAUserData::new_with_accounts(accounts_data),
|
||||||
utxo_commitments_store,
|
utxo_commitments_store,
|
||||||
wallet_config: config,
|
wallet_config: config,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr};
|
use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use key_protocol::key_protocol_core::NSSAUserData;
|
||||||
use nssa::Address;
|
use nssa::Address;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -47,3 +48,17 @@ pub fn fetch_persistent_accounts() -> Result<Vec<InitialAccountData>> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn produce_data_for_storage(user_data: &NSSAUserData) -> Vec<InitialAccountData> {
|
||||||
|
let mut vec_for_storage = vec![];
|
||||||
|
|
||||||
|
for (addr, (key, account)) in &user_data.accounts {
|
||||||
|
vec_for_storage.push(InitialAccountData {
|
||||||
|
address: *addr,
|
||||||
|
account: account.clone(),
|
||||||
|
pub_sign_key: key.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_for_storage
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use std::{fs::File, io::Write, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use common::{
|
use common::{
|
||||||
sequencer_client::{json::SendTxResponse, SequencerClient},
|
sequencer_client::{json::SendTxResponse, SequencerClient},
|
||||||
@ -14,7 +14,8 @@ use nssa::Address;
|
|||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
use crate::helperfunctions::{
|
use crate::helperfunctions::{
|
||||||
fetch_config, fetch_persistent_accounts, produce_account_addr_from_hex,
|
fetch_config, fetch_persistent_accounts, get_home, produce_account_addr_from_hex,
|
||||||
|
produce_data_for_storage,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const HOME_DIR_ENV_VAR: &str = "NSSA_WALLET_HOME_DIR";
|
pub const HOME_DIR_ENV_VAR: &str = "NSSA_WALLET_HOME_DIR";
|
||||||
@ -35,6 +36,9 @@ impl WalletCore {
|
|||||||
|
|
||||||
let mut storage = WalletChainStore::new(config)?;
|
let mut storage = WalletChainStore::new(config)?;
|
||||||
|
|
||||||
|
//Updating user data with stored accounts
|
||||||
|
//We do not store/update any key data connected to private executions
|
||||||
|
//ToDo: Add this into persistent data
|
||||||
let persistent_accounts = fetch_persistent_accounts()?;
|
let persistent_accounts = fetch_persistent_accounts()?;
|
||||||
for acc in persistent_accounts {
|
for acc in persistent_accounts {
|
||||||
storage
|
storage
|
||||||
@ -48,7 +52,20 @@ impl WalletCore {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_new_account(&mut self) -> Address {
|
pub fn store_persistent_accounts(&self) -> Result<PathBuf> {
|
||||||
|
let home = get_home()?;
|
||||||
|
let accs_path = home.join("curr_accounts.json");
|
||||||
|
let accs = serde_json::to_vec(&produce_data_for_storage(&self.storage.user_data))?;
|
||||||
|
|
||||||
|
let mut accs_file = File::create(accs_path.as_path())?;
|
||||||
|
accs_file.write_all(&accs)?;
|
||||||
|
|
||||||
|
info!("Stored accounts data at {accs_path:#?}");
|
||||||
|
|
||||||
|
Ok(accs_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_new_account(&mut self) -> Address {
|
||||||
self.storage.user_data.generate_new_account()
|
self.storage.user_data.generate_new_account()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +131,13 @@ pub enum Command {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
amount: u128,
|
amount: u128,
|
||||||
},
|
},
|
||||||
|
///Register new account
|
||||||
|
RegisterAccount {},
|
||||||
|
///Fetch transaction by `hash`
|
||||||
|
FetchTx {
|
||||||
|
#[arg(short, long)]
|
||||||
|
tx_hash: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config
|
///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config
|
||||||
@ -126,6 +150,9 @@ pub struct Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_subcommand(command: Command) -> Result<()> {
|
pub async fn execute_subcommand(command: Command) -> Result<()> {
|
||||||
|
let wallet_config = fetch_config()?;
|
||||||
|
let mut wallet_core = WalletCore::start_from_config_update_chain(wallet_config).await?;
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
Command::SendNativeTokenTransfer {
|
Command::SendNativeTokenTransfer {
|
||||||
from,
|
from,
|
||||||
@ -133,13 +160,9 @@ pub async fn execute_subcommand(command: Command) -> Result<()> {
|
|||||||
to,
|
to,
|
||||||
amount,
|
amount,
|
||||||
} => {
|
} => {
|
||||||
let wallet_config = fetch_config()?;
|
|
||||||
|
|
||||||
let from = produce_account_addr_from_hex(from)?;
|
let from = produce_account_addr_from_hex(from)?;
|
||||||
let to = produce_account_addr_from_hex(to)?;
|
let to = produce_account_addr_from_hex(to)?;
|
||||||
|
|
||||||
let wallet_core = WalletCore::start_from_config_update_chain(wallet_config).await?;
|
|
||||||
|
|
||||||
let res = wallet_core
|
let res = wallet_core
|
||||||
.send_public_native_token_transfer(from, nonce, to, amount)
|
.send_public_native_token_transfer(from, nonce, to, amount)
|
||||||
.await?;
|
.await?;
|
||||||
@ -148,7 +171,25 @@ pub async fn execute_subcommand(command: Command) -> Result<()> {
|
|||||||
|
|
||||||
//ToDo: Insert transaction polling logic here
|
//ToDo: Insert transaction polling logic here
|
||||||
}
|
}
|
||||||
|
Command::RegisterAccount {} => {
|
||||||
|
let addr = wallet_core.create_new_account();
|
||||||
|
|
||||||
|
let key = wallet_core.storage.user_data.get_account_signing_key(&addr);
|
||||||
|
|
||||||
|
info!("Generated new account with addr {addr:#?}");
|
||||||
|
info!("With key {key:#?}");
|
||||||
|
}
|
||||||
|
Command::FetchTx { tx_hash } => {
|
||||||
|
let tx_obj = wallet_core
|
||||||
|
.sequencer_client
|
||||||
|
.get_transaction_by_hash(tx_hash)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
info!("Transaction object {tx_obj:#?}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wallet_core.store_persistent_accounts()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user