Merge branch 'Pravdyvy/key-protocol-update-public-part' into Pravdyvy/accounts-dump-fetch

This commit is contained in:
Oleksandr Pravdyvyi 2025-09-02 08:25:00 +03:00
commit 4363a16a62
No known key found for this signature in database
GPG Key ID: 9F8955C63C443871
14 changed files with 106 additions and 218 deletions

View File

@ -4,136 +4,53 @@ 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,
}
}
}
impl Default for NSSAUserData {
@ -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());
// }
}

View File

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
thiserror = "2.0.12"
risc0-zkvm = "3.0.1"
risc0-zkvm = "3.0.3"
nssa-core = { path = "core" }
program-methods = { path = "program_methods" }
serde = "1.0.219"

View File

@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2024"
[dependencies]
risc0-zkvm = "3.0.1"
risc0-zkvm = "3.0.3"
serde = { version = "1.0", default-features = false }

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[build-dependencies]
risc0-build = { version = "3.0.1" }
risc0-build = { version = "3.0.3" }
[package.metadata.risc0]
methods = ["guest"]

View File

@ -627,9 +627,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",
@ -1608,6 +1608,27 @@ dependencies = [
"libm",
]
[[package]]
name = "num_enum"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
dependencies = [
"num_enum_derive",
"rustversion",
]
[[package]]
name = "num_enum_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.104",
]
[[package]]
name = "objc"
version = "0.2.7"
@ -2059,9 +2080,9 @@ dependencies = [
[[package]]
name = "risc0-binfmt"
version = "3.0.1"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2af322c052ae9973054f67434bc953eae44dbac68054d304b46848634d2a45d"
checksum = "1c8f97f81bcdead4101bca06469ecef481a2695cd04e7e877b49dea56a7f6f2a"
dependencies = [
"anyhow",
"borsh",
@ -2081,9 +2102,9 @@ dependencies = [
[[package]]
name = "risc0-build"
version = "3.0.1"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b042a8a6fdd02793c0acb526fbd3f0d92abe664f1158be38d45a92def57385b2"
checksum = "1bbb512d728e011d03ce0958ca7954624ee13a215bcafd859623b3c63b2a3f60"
dependencies = [
"anyhow",
"cargo_metadata",
@ -2105,9 +2126,9 @@ dependencies = [
[[package]]
name = "risc0-circuit-keccak"
version = "4.0.1"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "966ba960d718123e16c603d6919a0c5d7cd2f872d428639ab5650108520f133a"
checksum = "5f195f865ac1afdc21a172d7756fdcc21be18e13eb01d78d3d7f2b128fa881ba"
dependencies = [
"anyhow",
"bytemuck",
@ -2121,9 +2142,9 @@ dependencies = [
[[package]]
name = "risc0-circuit-recursion"
version = "4.0.1"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30f6afac63cfd291aaa7f40edf976db5452698e66cd79f16ccbf7c0eb5a5d94e"
checksum = "dca8f15c8abc0fd8c097aa7459879110334d191c63dd51d4c28881c4a497279e"
dependencies = [
"anyhow",
"bytemuck",
@ -2136,9 +2157,9 @@ dependencies = [
[[package]]
name = "risc0-circuit-rv32im"
version = "4.0.1"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fdd0865593941a6800c65a7c3b48be8700f73eb597681f6f594c7465839ce8a"
checksum = "ae1b0689f4a270a2f247b04397ebb431b8f64fe5170e98ee4f9d71bd04825205"
dependencies = [
"anyhow",
"bit-vec",
@ -2164,9 +2185,9 @@ dependencies = [
[[package]]
name = "risc0-groth16"
version = "3.0.1"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b68a622c69d0b97f511ee43db1d7f7f00b4dacead9c8aceae03fc5383f4764c1"
checksum = "724285dc79604abfb2d40feaefe3e335420a6b293511661f77d6af62f1f5fae9"
dependencies = [
"anyhow",
"ark-bn254",
@ -2185,19 +2206,20 @@ dependencies = [
[[package]]
name = "risc0-zkos-v1compat"
version = "2.0.2"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "328c9f0ec5f6eb8b7624347b5dcf82729f304adbc364399825f3ab6f8588189c"
checksum = "840c2228803557a8b7dc035a8f196516b6fd68c9dc6ac092f0c86241b5b1bafb"
dependencies = [
"include_bytes_aligned",
"no_std_strings",
"risc0-zkvm-platform",
]
[[package]]
name = "risc0-zkp"
version = "3.0.1"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c246f34b86a165308e37a064afa86e66ee7b8525f02bcf03f2124aaeedba04f"
checksum = "ffb6bf356f469bb8744f72a07a37134c5812c1d55d6271bba80e87bdb7a58c8e"
dependencies = [
"anyhow",
"blake2",
@ -2220,9 +2242,9 @@ dependencies = [
[[package]]
name = "risc0-zkvm"
version = "3.0.1"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdf8d11f9e61cfd3e577fb6e6e11cc34ca247831c2555ee0a6a53deba9702d2"
checksum = "3fcce11648a9ff60b8e7af2f0ce7fbf8d25275ab6d414cc91b9da69ee75bc978"
dependencies = [
"anyhow",
"bincode",
@ -2256,15 +2278,17 @@ dependencies = [
[[package]]
name = "risc0-zkvm-platform"
version = "2.0.4"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06fc0e464f4ac44c3f1fd17b479e09e3ccbd1c40219837d750580b03030dca60"
checksum = "5c826f09626ab2ae76671673e5a232548ddd95a34eece2ea4ced5f010383f95b"
dependencies = [
"bytemuck",
"cfg-if",
"getrandom 0.2.16",
"getrandom 0.3.3",
"libm",
"num_enum",
"paste",
"stability",
]
@ -2394,9 +2418,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "rzup"
version = "0.5.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76c6dfdbd72b2b0a537ad1e6256a3ce493ac87b9e89815465e393ee6595968e2"
checksum = "5d2aed296f203fa64bcb4b52069356dd86d6ec578593985b919b6995bee1f0ae"
dependencies = [
"hex",
"rsa",
@ -2730,12 +2754,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",
@ -2745,15 +2768,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",

View File

@ -6,5 +6,5 @@ edition = "2021"
[workspace]
[dependencies]
risc0-zkvm = { version = "3.0.1", default-features = false, features = ['std'] }
risc0-zkvm = { version = "3.0.3", default-features = false, features = ['std'] }
nssa-core = { path = "../../core" }

View File

@ -1,12 +1,9 @@
use std::{fmt::Display, str::FromStr};
use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use crate::signature::PublicKey;
pub const LENGTH_MISMATCH_ERROR_MESSAGE: &str = "Slice length != 32 ";
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Address {
value: [u8; 32],
@ -28,18 +25,6 @@ impl AsRef<[u8]> for Address {
}
}
impl TryFrom<Vec<u8>> for Address {
type Error = anyhow::Error;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
let addr_val: [u8; 32] = value
.try_into()
.map_err(|_| anyhow!(LENGTH_MISMATCH_ERROR_MESSAGE))?;
Ok(Address::new(addr_val))
}
}
impl From<&PublicKey> for Address {
fn from(value: &PublicKey) -> Self {
// TODO: Check specs

View File

@ -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();
}
}

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[build-dependencies]
risc0-build = { version = "3.0.1" }
risc0-build = { version = "3.0.3" }
[package.metadata.risc0]
methods = ["guest"]

View File

@ -6,5 +6,5 @@ edition = "2021"
[workspace]
[dependencies]
risc0-zkvm = { version = "3.0.1", default-features = false, features = ['std'] }
risc0-zkvm = { version = "3.0.3", default-features = false, features = ['std'] }
nssa-core = { path = "../../core" }

View File

@ -23,15 +23,7 @@ impl SequecerChainStore {
) -> Self {
let init_accs: Vec<(Address, u128)> = initial_accounts
.iter()
.map(|acc_data| {
(
hex::decode(acc_data.addr.clone())
.unwrap()
.try_into()
.unwrap(),
acc_data.balance,
)
})
.map(|acc_data| (acc_data.addr.parse().unwrap(), acc_data.balance))
.collect();
let state = nssa::V01State::new_with_genesis_accounts(&init_accs);

View File

@ -18,7 +18,7 @@ reqwest.workspace = true
thiserror.workspace = true
tokio.workspace = true
tempfile.workspace = true
risc0-zkvm = "3.0.1"
risc0-zkvm = "3.0.3"
hex.workspace = true
actix-rt.workspace = true
clap.workspace = true

View File

@ -14,23 +14,17 @@ 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,
})
@ -101,7 +95,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]

View File

@ -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,
@ -46,15 +47,7 @@ impl WalletCore {
client: client.clone(),
};
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);
}
let storage = WalletChainStore::new(config)?;
Ok(Self {
storage,
@ -83,6 +76,15 @@ 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,
@ -90,7 +92,7 @@ impl WalletCore {
to: Address,
balance_to_move: u128,
) -> Result<SendTxResponse, ExecutionFailureKind> {
let account = self.storage.user_data.get_account(&from);
let account = self.search_for_initial_account(from);
if let Some(account) = account {
if account.balance >= balance_to_move {