mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-05 23:03:06 +00:00
Merge branch 'Pravdyvy/accounts-dump-fetch' into Pravdyvy/sequencer-update
This commit is contained in:
commit
211b6f9115
@ -7,4 +7,5 @@ source env.sh
|
||||
RISC0_DEV_MODE=1 cargo test --release
|
||||
cd integration_tests
|
||||
export NSSA_WALLET_HOME_DIR=$(pwd)/configs/debug/wallet/
|
||||
export RUST_LOG=info
|
||||
cargo run $(pwd)/configs/debug all
|
||||
|
||||
@ -66,6 +66,8 @@ pub enum ExecutionFailureKind {
|
||||
ProveError(anyhow::Error),
|
||||
#[error("Failed to decode data from VM: {0:?}")]
|
||||
DecodeError(String),
|
||||
#[error("Failed to get account data from sequencer")]
|
||||
SequencerError,
|
||||
#[error("Inputs amounts does not match outputs")]
|
||||
AmountMismatchError,
|
||||
#[error("Accounts key not found")]
|
||||
|
||||
@ -84,7 +84,6 @@ pub async fn post_test(residual: (ServerHandle, JoinHandle<Result<()>>, TempDir)
|
||||
pub async fn test_success() {
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 0,
|
||||
to: ACC_RECEIVER.to_string(),
|
||||
amount: 100,
|
||||
};
|
||||
@ -144,7 +143,6 @@ pub async fn test_success_move_to_another_account() {
|
||||
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 0,
|
||||
to: new_persistent_account_addr.clone(),
|
||||
amount: 100,
|
||||
};
|
||||
@ -176,7 +174,6 @@ pub async fn test_success_move_to_another_account() {
|
||||
pub async fn test_failure() {
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 0,
|
||||
to: ACC_RECEIVER.to_string(),
|
||||
amount: 1000000,
|
||||
};
|
||||
@ -214,7 +211,6 @@ pub async fn test_failure() {
|
||||
pub async fn test_success_two_transactions() {
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 0,
|
||||
to: ACC_RECEIVER.to_string(),
|
||||
amount: 100,
|
||||
};
|
||||
@ -248,7 +244,6 @@ pub async fn test_success_two_transactions() {
|
||||
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 1,
|
||||
to: ACC_RECEIVER.to_string(),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit};
|
||||
use constants_types::{CipherText, Nonce};
|
||||
use elliptic_curve::point::AffineCoordinates;
|
||||
@ -18,6 +20,8 @@ pub mod secret_holders;
|
||||
pub struct KeyChain {
|
||||
top_secret_key_holder: TopSecretKeyHolder,
|
||||
pub utxo_secret_key_holder: UTXOSecretKeyHolder,
|
||||
///Map for all users accounts
|
||||
pub pub_account_signing_keys: HashMap<nssa::Address, nssa::PrivateKey>,
|
||||
pub nullifer_public_key: PublicKey,
|
||||
pub viewing_public_key: PublicKey,
|
||||
}
|
||||
@ -39,9 +43,47 @@ impl KeyChain {
|
||||
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<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(
|
||||
&self,
|
||||
ephemeral_public_key_sender: AffinePoint,
|
||||
|
||||
@ -4,135 +4,52 @@ use anyhow::Result;
|
||||
use k256::AffinePoint;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::key_management::{
|
||||
constants_types::{CipherText, Nonce},
|
||||
ephemeral_key_holder::EphemeralKeyHolder,
|
||||
KeyChain,
|
||||
};
|
||||
use crate::key_management::KeyChain;
|
||||
|
||||
pub type PublicKey = AffinePoint;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct NSSAUserData {
|
||||
pub key_holder: KeyChain,
|
||||
///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
|
||||
///
|
||||
/// known to each node about account `address`
|
||||
///
|
||||
/// Main usage is to encode data for other account
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct NSSAUserDataPublicMask {
|
||||
pub nullifier_public_key: AffinePoint,
|
||||
pub viewing_public_key: AffinePoint,
|
||||
}
|
||||
|
||||
impl NSSAUserDataPublicMask {
|
||||
pub fn encrypt_data(
|
||||
ephemeral_key_holder: &EphemeralKeyHolder,
|
||||
viewing_public_key_receiver: AffinePoint,
|
||||
data: &[u8],
|
||||
) -> (CipherText, Nonce) {
|
||||
//Using of parent NSSAUserData fuction
|
||||
NSSAUserData::encrypt_data(ephemeral_key_holder, viewing_public_key_receiver, data)
|
||||
}
|
||||
|
||||
//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();
|
||||
|
||||
Self {
|
||||
key_holder,
|
||||
accounts: HashMap::new(),
|
||||
Self { key_holder }
|
||||
}
|
||||
|
||||
fn valid_key_transaction_pairing_check(
|
||||
accounts_keys_map: &HashMap<nssa::Address, nssa::PrivateKey>,
|
||||
) -> bool {
|
||||
let mut check_res = true;
|
||||
for (addr, key) in accounts_keys_map {
|
||||
if &nssa::Address::from(&nssa::PublicKey::new_from_private_key(key)) != addr {
|
||||
check_res = false;
|
||||
}
|
||||
}
|
||||
check_res
|
||||
}
|
||||
|
||||
pub fn new_with_accounts(
|
||||
accounts_data: HashMap<nssa::Address, (nssa::PrivateKey, nssa_core::account::Account)>,
|
||||
) -> Self {
|
||||
let key_holder = KeyChain::new_os_random();
|
||||
|
||||
Self {
|
||||
key_holder,
|
||||
accounts: accounts_data,
|
||||
accounts_keys: HashMap<nssa::Address, nssa::PrivateKey>,
|
||||
) -> Result<Self> {
|
||||
if !Self::valid_key_transaction_pairing_check(&accounts_keys) {
|
||||
anyhow::bail!("Key transaction pairing check not satisfied, there is addresses, which is not derived from keys");
|
||||
}
|
||||
|
||||
let key_holder = KeyChain::new_os_random_with_accounts(accounts_keys);
|
||||
|
||||
Ok(Self { key_holder })
|
||||
}
|
||||
|
||||
pub fn generate_new_account(&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));
|
||||
let account = nssa_core::account::Account::default();
|
||||
|
||||
self.accounts.insert(address, (private_key, account));
|
||||
|
||||
address
|
||||
}
|
||||
|
||||
pub fn get_account_balance(&self, address: &nssa::Address) -> u128 {
|
||||
self.accounts
|
||||
.get(address)
|
||||
.map(|(_, acc)| acc.balance)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn get_account(&self, address: &nssa::Address) -> Option<&nssa_core::account::Account> {
|
||||
self.accounts.get(address).map(|(_, acc)| acc)
|
||||
self.key_holder.generate_new_private_key()
|
||||
}
|
||||
|
||||
pub fn get_account_signing_key(&self, address: &nssa::Address) -> Option<&nssa::PrivateKey> {
|
||||
self.accounts.get(address).map(|(key, _)| key)
|
||||
}
|
||||
|
||||
pub fn encrypt_data(
|
||||
ephemeral_key_holder: &EphemeralKeyHolder,
|
||||
viewing_public_key_receiver: AffinePoint,
|
||||
data: &[u8],
|
||||
) -> (CipherText, Nonce) {
|
||||
ephemeral_key_holder.encrypt_data(viewing_public_key_receiver, data)
|
||||
}
|
||||
|
||||
pub fn decrypt_data(
|
||||
&self,
|
||||
ephemeral_public_key_sender: AffinePoint,
|
||||
ciphertext: CipherText,
|
||||
nonce: Nonce,
|
||||
) -> Result<Vec<u8>, aes_gcm::Error> {
|
||||
self.key_holder
|
||||
.decrypt_data(ephemeral_public_key_sender, ciphertext, nonce)
|
||||
}
|
||||
|
||||
pub fn update_account_balance(&mut self, address: nssa::Address, new_balance: u128) {
|
||||
self.accounts
|
||||
.entry(address)
|
||||
.and_modify(|(_, acc)| acc.balance = new_balance);
|
||||
}
|
||||
|
||||
pub fn increment_account_nonce(&mut self, address: nssa::Address) {
|
||||
self.accounts
|
||||
.entry(address)
|
||||
.and_modify(|(_, acc)| acc.nonce += 1);
|
||||
}
|
||||
|
||||
//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,
|
||||
}
|
||||
self.key_holder.get_pub_account_signing_key(address)
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,29 +67,6 @@ mod tests {
|
||||
fn test_new_account() {
|
||||
let mut user_data = NSSAUserData::new();
|
||||
|
||||
let addr = user_data.generate_new_account();
|
||||
|
||||
assert_eq!(user_data.get_account_balance(&addr), 0);
|
||||
let _addr = user_data.generate_new_account();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_balance() {
|
||||
let mut user_data = NSSAUserData::new();
|
||||
|
||||
let address = user_data.generate_new_account();
|
||||
|
||||
user_data.update_account_balance(address, 500);
|
||||
|
||||
assert_eq!(user_data.get_account_balance(&address), 500);
|
||||
}
|
||||
|
||||
//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();
|
||||
|
||||
// assert_eq!(account.make_tag(), account_mask.make_tag());
|
||||
// }
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
risc0-zkvm = { version = "3.0.3" }
|
||||
risc0-zkvm = "3.0.3"
|
||||
serde = { version = "1.0", default-features = false }
|
||||
thiserror = { version = "2.0.12", optional = true }
|
||||
bytemuck = { version = "1.13", optional = true }
|
||||
|
||||
17
nssa/program_methods/guest/Cargo.lock
generated
17
nssa/program_methods/guest/Cargo.lock
generated
@ -648,9 +648,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.4.0"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
|
||||
checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
@ -2785,12 +2785,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.41"
|
||||
version = "0.3.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
|
||||
checksum = "8ca967379f9d8eb8058d86ed467d81d03e81acd45757e4ca341c24affbe8e8e3"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
@ -2800,15 +2799,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
|
||||
checksum = "a9108bb380861b07264b950ded55a44a14a4adc68b9f5efd85aafc3aa4d40a68"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.22"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
|
||||
checksum = "7182799245a7264ce590b349d90338f1c1affad93d2639aed5f8f69c090b334c"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
|
||||
@ -48,7 +48,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_produce_key() {
|
||||
let key = PrivateKey::new_os_random();
|
||||
println!("{:?}", key.0);
|
||||
let _key = PrivateKey::new_os_random();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ use anyhow::Result;
|
||||
use common::merkle_tree_public::merkle_tree::UTXOCommitmentsMerkleTree;
|
||||
use key_protocol::key_protocol_core::NSSAUserData;
|
||||
|
||||
use crate::config::{InitialAccountData, WalletConfig};
|
||||
use crate::config::{PersistentAccountData, WalletConfig};
|
||||
|
||||
pub struct WalletChainStore {
|
||||
pub user_data: NSSAUserData,
|
||||
@ -14,32 +14,27 @@ pub struct WalletChainStore {
|
||||
|
||||
impl WalletChainStore {
|
||||
pub fn new(config: WalletConfig) -> Result<Self> {
|
||||
let accounts_data: HashMap<nssa::Address, (nssa::PrivateKey, nssa_core::account::Account)> =
|
||||
config
|
||||
.initial_accounts
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|init_acc_data| {
|
||||
(
|
||||
init_acc_data.address,
|
||||
(init_acc_data.pub_sign_key, init_acc_data.account),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let accounts_keys: HashMap<nssa::Address, nssa::PrivateKey> = config
|
||||
.initial_accounts
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|init_acc_data| (init_acc_data.address, init_acc_data.pub_sign_key))
|
||||
.collect();
|
||||
|
||||
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
||||
|
||||
Ok(Self {
|
||||
user_data: NSSAUserData::new_with_accounts(accounts_data),
|
||||
user_data: NSSAUserData::new_with_accounts(accounts_keys)?,
|
||||
utxo_commitments_store,
|
||||
wallet_config: config,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn insert_account_data(&mut self, acc_data: InitialAccountData) {
|
||||
pub(crate) fn insert_account_data(&mut self, acc_data: PersistentAccountData) {
|
||||
self.user_data
|
||||
.accounts
|
||||
.insert(acc_data.address, (acc_data.pub_sign_key, acc_data.account));
|
||||
.key_holder
|
||||
.pub_account_signing_keys
|
||||
.insert(acc_data.address, acc_data.pub_sign_key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +96,6 @@ mod tests {
|
||||
|
||||
let store = WalletChainStore::new(config.clone()).unwrap();
|
||||
|
||||
assert_eq!(store.user_data.accounts.len(), 2);
|
||||
assert_eq!(
|
||||
store.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
||||
[0; 32]
|
||||
|
||||
@ -8,6 +8,12 @@ pub struct InitialAccountData {
|
||||
pub pub_sign_key: nssa::PrivateKey,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PersistentAccountData {
|
||||
pub address: nssa::Address,
|
||||
pub pub_sign_key: nssa::PrivateKey,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GasConfig {
|
||||
/// Gas spent per deploying one byte of data
|
||||
|
||||
@ -5,7 +5,7 @@ use key_protocol::key_protocol_core::NSSAUserData;
|
||||
use nssa::Address;
|
||||
|
||||
use crate::{
|
||||
config::{InitialAccountData, WalletConfig},
|
||||
config::{PersistentAccountData, WalletConfig},
|
||||
HOME_DIR_ENV_VAR,
|
||||
};
|
||||
|
||||
@ -31,7 +31,7 @@ pub fn produce_account_addr_from_hex(hex_str: String) -> Result<Address> {
|
||||
///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
|
||||
pub fn fetch_persistent_accounts() -> Result<Vec<InitialAccountData>> {
|
||||
pub fn fetch_persistent_accounts() -> Result<Vec<PersistentAccountData>> {
|
||||
let home = get_home()?;
|
||||
let accs_path = home.join("curr_accounts.json");
|
||||
|
||||
@ -50,13 +50,12 @@ pub fn fetch_persistent_accounts() -> Result<Vec<InitialAccountData>> {
|
||||
}
|
||||
|
||||
///Produces a list of accounts for storage
|
||||
pub fn produce_data_for_storage(user_data: &NSSAUserData) -> Vec<InitialAccountData> {
|
||||
pub fn produce_data_for_storage(user_data: &NSSAUserData) -> Vec<PersistentAccountData> {
|
||||
let mut vec_for_storage = vec![];
|
||||
|
||||
for (addr, (key, account)) in &user_data.accounts {
|
||||
vec_for_storage.push(InitialAccountData {
|
||||
for (addr, key) in &user_data.key_holder.pub_account_signing_keys {
|
||||
vec_for_storage.push(PersistentAccountData {
|
||||
address: *addr,
|
||||
account: account.clone(),
|
||||
pub_sign_key: key.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::{fs::File, io::Write, path::PathBuf, sync::Arc};
|
||||
use std::{fs::File, io::Write, path::PathBuf, str::FromStr, sync::Arc};
|
||||
|
||||
use base64::Engine;
|
||||
use common::{
|
||||
@ -13,6 +13,7 @@ use log::info;
|
||||
use nssa::Address;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use nssa_core::account::Account;
|
||||
|
||||
use crate::{
|
||||
helperfunctions::{
|
||||
@ -36,7 +37,7 @@ pub struct WalletCore {
|
||||
}
|
||||
|
||||
impl WalletCore {
|
||||
pub async fn start_from_config_update_chain(config: WalletConfig) -> Result<Self> {
|
||||
pub fn start_from_config_update_chain(config: WalletConfig) -> Result<Self> {
|
||||
let client = Arc::new(SequencerClient::new(config.sequencer_addr.clone())?);
|
||||
let tx_poller = TxPoller {
|
||||
polling_delay_millis: config.seq_poll_timeout_millis,
|
||||
@ -48,12 +49,9 @@ impl WalletCore {
|
||||
|
||||
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()?;
|
||||
for acc in persistent_accounts {
|
||||
storage.insert_account_data(acc);
|
||||
for pers_acc_data in persistent_accounts {
|
||||
storage.insert_account_data(pers_acc_data);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
@ -83,48 +81,77 @@ impl WalletCore {
|
||||
self.storage.user_data.generate_new_account()
|
||||
}
|
||||
|
||||
pub fn search_for_initial_account(&self, acc_addr: Address) -> Option<Account> {
|
||||
for initial_acc in &self.storage.wallet_config.initial_accounts {
|
||||
if initial_acc.address == acc_addr {
|
||||
return Some(initial_acc.account.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn send_public_native_token_transfer(
|
||||
&self,
|
||||
from: Address,
|
||||
nonce: u128,
|
||||
to: Address,
|
||||
balance_to_move: u128,
|
||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||
let account = self.storage.user_data.get_account(&from);
|
||||
if let Ok(balance) = self.get_account_balance(from).await {
|
||||
if balance >= balance_to_move {
|
||||
if let Ok(nonces) = self.get_accounts_nonces(vec![from]).await {
|
||||
let addresses = vec![from, to];
|
||||
let program_id = nssa::program::Program::authenticated_transfer_program().id();
|
||||
let message = nssa::public_transaction::Message::try_new(
|
||||
program_id,
|
||||
addresses,
|
||||
nonces,
|
||||
balance_to_move,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if let Some(account) = account {
|
||||
if account.balance >= balance_to_move {
|
||||
let addresses = vec![from, to];
|
||||
let nonces = vec![nonce];
|
||||
let program_id = nssa::program::Program::authenticated_transfer_program().id();
|
||||
let message = nssa::public_transaction::Message::try_new(
|
||||
program_id,
|
||||
addresses,
|
||||
nonces,
|
||||
balance_to_move,
|
||||
)
|
||||
.unwrap();
|
||||
let signing_key = self.storage.user_data.get_account_signing_key(&from);
|
||||
|
||||
let signing_key = self.storage.user_data.get_account_signing_key(&from);
|
||||
if let Some(signing_key) = signing_key {
|
||||
let witness_set = nssa::public_transaction::WitnessSet::for_message(
|
||||
&message,
|
||||
&[signing_key],
|
||||
);
|
||||
|
||||
if let Some(signing_key) = signing_key {
|
||||
let witness_set =
|
||||
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
||||
let tx = nssa::PublicTransaction::new(message, witness_set);
|
||||
|
||||
let tx = nssa::PublicTransaction::new(message, witness_set);
|
||||
|
||||
Ok(self.sequencer_client.send_tx(tx).await?)
|
||||
Ok(self.sequencer_client.send_tx(tx).await?)
|
||||
} else {
|
||||
Err(ExecutionFailureKind::KeyNotFoundError)
|
||||
}
|
||||
} else {
|
||||
Err(ExecutionFailureKind::KeyNotFoundError)
|
||||
Err(ExecutionFailureKind::SequencerError)
|
||||
}
|
||||
} else {
|
||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||
}
|
||||
} else {
|
||||
Err(ExecutionFailureKind::AmountMismatchError)
|
||||
Err(ExecutionFailureKind::SequencerError)
|
||||
}
|
||||
}
|
||||
|
||||
///Get account balance
|
||||
pub async fn get_account_balance(&self, acc: Address) -> Result<u128> {
|
||||
Ok(self
|
||||
.sequencer_client
|
||||
.get_account_balance(acc.to_string())
|
||||
.await?
|
||||
.balance)
|
||||
}
|
||||
|
||||
///Get accounts nonces
|
||||
pub async fn get_accounts_nonces(&self, accs: Vec<Address>) -> Result<Vec<u128>> {
|
||||
Ok(self
|
||||
.sequencer_client
|
||||
.get_accounts_nonces(accs.into_iter().map(|acc| acc.to_string()).collect())
|
||||
.await?
|
||||
.nonces)
|
||||
}
|
||||
|
||||
///Poll transactions
|
||||
pub async fn poll_public_native_token_transfer(
|
||||
&self,
|
||||
@ -137,27 +164,6 @@ impl WalletCore {
|
||||
|
||||
Ok(pub_tx)
|
||||
}
|
||||
|
||||
///Execute native token transfer at wallet accounts
|
||||
pub fn execute_native_token_transfer(
|
||||
&mut self,
|
||||
from: Address,
|
||||
to: Address,
|
||||
balance_to_move: u128,
|
||||
) {
|
||||
self.storage.user_data.increment_account_nonce(from);
|
||||
self.storage.user_data.increment_account_nonce(to);
|
||||
|
||||
let from_bal = self.storage.user_data.get_account_balance(&from);
|
||||
let to_bal = self.storage.user_data.get_account_balance(&to);
|
||||
|
||||
self.storage
|
||||
.user_data
|
||||
.update_account_balance(from, from_bal - balance_to_move);
|
||||
self.storage
|
||||
.user_data
|
||||
.update_account_balance(to, to_bal + balance_to_move);
|
||||
}
|
||||
}
|
||||
|
||||
///Represents CLI command for a wallet
|
||||
@ -169,9 +175,6 @@ pub enum Command {
|
||||
///from - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
from: String,
|
||||
///nonce - u128 integer
|
||||
#[arg(long)]
|
||||
nonce: u128,
|
||||
///to - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
to: String,
|
||||
@ -186,6 +189,16 @@ pub enum Command {
|
||||
#[arg(short, long)]
|
||||
tx_hash: String,
|
||||
},
|
||||
///Get account `addr` balance
|
||||
GetAccountBalance {
|
||||
#[arg(short, long)]
|
||||
addr: String,
|
||||
},
|
||||
///Get account `addr` nonce
|
||||
GetAccountNonce {
|
||||
#[arg(short, long)]
|
||||
addr: String,
|
||||
},
|
||||
}
|
||||
|
||||
///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config
|
||||
@ -199,20 +212,15 @@ pub struct Args {
|
||||
|
||||
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?;
|
||||
let mut wallet_core = WalletCore::start_from_config_update_chain(wallet_config)?;
|
||||
|
||||
match command {
|
||||
Command::SendNativeTokenTransfer {
|
||||
from,
|
||||
nonce,
|
||||
to,
|
||||
amount,
|
||||
} => {
|
||||
Command::SendNativeTokenTransfer { from, to, amount } => {
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let to = produce_account_addr_from_hex(to)?;
|
||||
|
||||
let res = wallet_core
|
||||
.send_public_native_token_transfer(from, nonce, to, amount)
|
||||
.send_public_native_token_transfer(from, to, amount)
|
||||
.await?;
|
||||
|
||||
info!("Results of tx send is {res:#?}");
|
||||
@ -222,8 +230,6 @@ pub async fn execute_subcommand(command: Command) -> Result<()> {
|
||||
.await?;
|
||||
|
||||
info!("Transaction data is {transfer_tx:?}");
|
||||
|
||||
wallet_core.execute_native_token_transfer(from, to, amount);
|
||||
}
|
||||
Command::RegisterAccount {} => {
|
||||
let addr = wallet_core.create_new_account();
|
||||
@ -241,6 +247,18 @@ pub async fn execute_subcommand(command: Command) -> Result<()> {
|
||||
|
||||
info!("Transaction object {tx_obj:#?}");
|
||||
}
|
||||
Command::GetAccountBalance { addr } => {
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
let balance = wallet_core.get_account_balance(addr).await?;
|
||||
info!("Accounts {addr:#?} balance is {balance}");
|
||||
}
|
||||
Command::GetAccountNonce { addr } => {
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
let nonce = wallet_core.get_accounts_nonces(vec![addr]).await?[0];
|
||||
info!("Accounts {addr:#?} nonce is {nonce}");
|
||||
}
|
||||
}
|
||||
|
||||
wallet_core.store_persistent_accounts()?;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user