fix: structural upgrades finalized

This commit is contained in:
Oleksandr Pravdyvyi 2025-08-13 13:42:00 +03:00
parent 490ac908b8
commit 939553cc85
No known key found for this signature in database
GPG Key ID: 9F8955C63C443871
24 changed files with 345 additions and 126 deletions

View File

@ -4,18 +4,14 @@ use anyhow::Result;
use common::{merkle_tree_public::TreeHashType, transaction::Tag};
use k256::AffinePoint;
use log::info;
use nssa::Address;
use serde::{Deserialize, Serialize};
use utxo::utxo_core::UTXO;
pub mod address;
use crate::{
account_core::address::AccountAddress,
key_management::{
constants_types::{CipherText, Nonce},
ephemeral_key_holder::EphemeralKeyHolder,
AddressKeyHolder,
},
use crate::key_management::{
constants_types::{CipherText, Nonce},
ephemeral_key_holder::EphemeralKeyHolder,
AddressKeyHolder,
};
pub type PublicKey = AffinePoint;
@ -23,7 +19,7 @@ pub type PublicKey = AffinePoint;
#[derive(Clone, Debug)]
pub struct Account {
pub key_holder: AddressKeyHolder,
pub address: AccountAddress,
pub address: Address,
pub balance: u64,
pub utxos: HashMap<TreeHashType, UTXO>,
}
@ -31,7 +27,7 @@ pub struct Account {
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AccountForSerialization {
pub key_holder: AddressKeyHolder,
pub address: AccountAddress,
pub address: Address,
pub balance: u64,
pub utxos: HashMap<String, UTXO>,
}
@ -95,7 +91,7 @@ impl<'de> Deserialize<'de> for Account {
pub struct AccountPublicMask {
pub nullifier_public_key: AffinePoint,
pub viewing_public_key: AffinePoint,
pub address: AccountAddress,
pub address: Address,
pub balance: u64,
}
@ -110,7 +106,7 @@ impl AccountPublicMask {
}
pub fn make_tag(&self) -> Tag {
self.address[0]
self.address.tag()
}
}
@ -119,13 +115,13 @@ impl Account {
let key_holder = AddressKeyHolder::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(&public_key);
let address = nssa::Address::from(&public_key);
let balance = 0;
let utxos = HashMap::new();
Self {
key_holder,
address: *address.value(),
address,
balance,
utxos,
}
@ -135,12 +131,12 @@ impl Account {
let key_holder = AddressKeyHolder::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(&public_key);
let address = nssa::Address::from(&public_key);
let utxos = HashMap::new();
Self {
key_holder,
address: *address.value(),
address,
balance,
utxos,
}
@ -185,7 +181,7 @@ impl Account {
privacy_flag: bool,
) -> Result<()> {
let asset_utxo = UTXO::new(
self.address,
*self.address.value(),
serde_json::to_vec(&asset)?,
amount,
privacy_flag,
@ -203,7 +199,7 @@ impl Account {
}
pub fn make_tag(&self) -> Tag {
self.address[0]
self.address.tag()
}
///Produce account public mask
@ -241,8 +237,8 @@ mod tests {
#[test]
fn test_add_new_utxo_outputs() {
let mut account = Account::new();
let utxo1 = generate_dummy_utxo(account.address, 100);
let utxo2 = generate_dummy_utxo(account.address, 200);
let utxo1 = generate_dummy_utxo(*account.address.value(), 100);
let utxo2 = generate_dummy_utxo(*account.address.value(), 200);
let result = account.add_new_utxo_outputs(vec![utxo1.clone(), utxo2.clone()]);

View File

@ -343,7 +343,7 @@ mod tests {
let public_key = nssa::PublicKey::new_from_private_key(&pub_account_signing_key);
let address = nssa::Address::from_public_key(&public_key);
let address = nssa::Address::from(&public_key);
println!("======Prerequisites======");
println!();

View File

@ -5,10 +5,10 @@
"seq_poll_timeout_secs": 10,
"initial_accounts": [
{
"address": [27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143],
"address": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
"balance": 10000,
"key_holder": {
"address": [27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143],
"address": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
"nullifer_public_key": "03A340BECA9FAAB444CED0140681D72EA1318B5C611704FEE017DA9836B17DB718",
"pub_account_signing_key": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
"top_secret_key_holder": {
@ -23,10 +23,10 @@
"utxos": {}
},
{
"address": [77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234, 216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102],
"address": "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
"balance": 20000,
"key_holder": {
"address": [77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234, 216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102],
"address": "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
"nullifer_public_key": "02172F50274DE67C4087C344F5D58E11DF761D90285B095060E0994FAA6BCDE271",
"pub_account_signing_key": [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
"top_secret_key_holder": {

View File

@ -12,7 +12,10 @@ serde = "1.0.219"
sha2 = "0.10.9"
secp256k1 = "0.31.1"
rand = "0.8"
hex = "0.4.3"
anyhow.workspace = true
serde_json.workspace = true
[dev-dependencies]
test-program-methods = { path = "test_program_methods" }
hex = "0.4.3"

View File

@ -8,4 +8,3 @@ risc0-build = { version = "2.3.1" }
[package.metadata.risc0]
methods = ["guest"]

View File

@ -7,5 +7,4 @@ edition = "2021"
[dependencies]
risc0-zkvm = { version = "2.3.1", default-features = false, features = ['std'] }
nssa-core = {path = "../../core"}
nssa-core = { path = "../../core" }

View File

@ -2,4 +2,3 @@
channel = "stable"
components = ["rustfmt", "rust-src"]
profile = "minimal"

View File

@ -1,8 +1,11 @@
use serde::{Deserialize, Serialize};
use anyhow::anyhow;
use serde::{Deserialize, Serialize, de::Visitor};
use crate::signature::PublicKey;
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
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],
}
@ -12,12 +15,221 @@ impl Address {
Self { value }
}
pub fn from_public_key(public_key: &PublicKey) -> Self {
// TODO: Check specs
Address::new(*public_key.value())
pub fn tag(&self) -> u8 {
self.value[0]
}
pub fn value(&self) -> &[u8; 32] {
&self.value
}
}
impl AsRef<[u8]> for Address {
fn as_ref(&self) -> &[u8] {
&self.value
}
}
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
Self::new(*value.value())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HexString(String);
impl HexString {
pub fn inner(&self) -> &str {
&self.0
}
}
#[derive(Debug, thiserror::Error)]
pub enum HexStringConsistencyError {
#[error("Hex decode error")]
HexError(#[from] hex::FromHexError),
#[error("Decode slice does not fit 32 bytes")]
SizeError(#[from] anyhow::Error),
}
impl TryFrom<&str> for HexString {
type Error = HexStringConsistencyError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let decoded_str = hex::decode(value)?;
let _: Address = decoded_str.try_into()?;
Ok(Self(value.to_string()))
}
}
impl Serialize for HexString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.0)
}
}
struct HexStringVisitor;
impl<'de> Visitor<'de> for HexStringVisitor {
type Value = String;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("expected a valid string")
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.to_string())
}
}
impl<'de> Deserialize<'de> for HexString {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let str_cand = deserializer.deserialize_string(HexStringVisitor)?;
let hex_string =
HexString::try_from(str_cand.as_str()).map_err(|err| serde::de::Error::custom(err))?;
Ok(hex_string)
}
}
impl From<HexString> for Address {
fn from(value: HexString) -> Self {
Address::try_from(hex::decode(value.inner()).unwrap()).unwrap()
}
}
impl From<Address> for HexString {
fn from(value: Address) -> Self {
HexString::try_from(hex::encode(value).as_str()).unwrap()
}
}
impl Serialize for Address {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let hex_string: HexString = (*self).into();
hex_string.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Address {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let hex_sring = HexString::deserialize(deserializer)?;
Ok(hex_sring.into())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Serialize, Deserialize)]
struct Ser1 {
f1: String,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Ser2 {
f1: HexString,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Ser3 {
f1: Address,
}
#[test]
fn test_hex_ser() {
let str_for_tests = hex::encode([42; 32]);
let hex_str_for_tests = HexString::try_from(str_for_tests.as_str()).unwrap();
let ser1_str = Ser1 { f1: str_for_tests };
let ser2_str = Ser2 {
f1: hex_str_for_tests,
};
let ser1_str_ser = serde_json::to_string(&ser1_str).unwrap();
let ser2_str_ser = serde_json::to_string(&ser2_str).unwrap();
println!("{ser2_str_ser:#?}");
assert_eq!(ser1_str_ser, ser2_str_ser);
}
#[test]
fn test_hex_deser() {
let raw_json = r#"{
"f1": "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"
}"#;
let str_for_tests = hex::encode([42; 32]);
let hex_str_for_tests = HexString::try_from(str_for_tests.as_str()).unwrap();
let ser2_str = Ser2 {
f1: hex_str_for_tests,
};
let ser1_str: Ser2 = serde_json::from_str(raw_json).unwrap();
assert_eq!(ser1_str, ser2_str);
}
#[test]
fn test_addr_deser() {
let raw_json = r#"{
"f1": "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"
}"#;
let addr_for_tests = Address::new([42; 32]);
let ser2_str = Ser3 {
f1: addr_for_tests,
};
let ser1_str: Ser3 = serde_json::from_str(raw_json).unwrap();
assert_eq!(ser1_str, ser2_str);
}
}

View File

@ -1,4 +1,4 @@
mod address;
pub mod address;
pub mod error;
pub mod program;
pub mod public_transaction;

View File

@ -39,7 +39,7 @@ impl PublicTransaction {
self.witness_set
.signatures_and_public_keys()
.iter()
.map(|(_, public_key)| Address::from_public_key(public_key))
.map(|(_, public_key)| Address::from(public_key))
.collect()
}
@ -129,14 +129,14 @@ pub mod tests {
fn keys_for_tests() -> (PrivateKey, PrivateKey, Address, Address) {
let key1 = PrivateKey::try_new([1; 32]).unwrap();
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let addr1 = Address::from_public_key(&PublicKey::new_from_private_key(&key1));
let addr2 = Address::from_public_key(&PublicKey::new_from_private_key(&key2));
let addr1 = Address::from(&PublicKey::new_from_private_key(&key1));
let addr2 = Address::from(&PublicKey::new_from_private_key(&key2));
(key1, key2, addr1, addr2)
}
fn state_for_tests() -> V01State {
let (_, _, addr1, addr2) = keys_for_tests();
let initial_data = [(*addr1.value(), 10000), (*addr2.value(), 20000)];
let initial_data = [(addr1, 10000), (addr2, 20000)];
V01State::new_with_genesis_accounts(&initial_data)
}

View File

@ -49,8 +49,8 @@ mod tests {
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let pubkey1 = PublicKey::new_from_private_key(&key1);
let pubkey2 = PublicKey::new_from_private_key(&key2);
let addr1 = Address::from_public_key(&pubkey1);
let addr2 = Address::from_public_key(&pubkey2);
let addr1 = Address::from(&pubkey1);
let addr2 = Address::from(&pubkey2);
let nonces = vec![1, 2];
let instruction = vec![1, 2, 3, 4];
let message = Message::try_new([0; 8], vec![addr1, addr2], nonces, instruction).unwrap();

View File

@ -10,18 +10,17 @@ pub struct V01State {
}
impl V01State {
pub fn new_with_genesis_accounts(initial_data: &[([u8; 32], u128)]) -> Self {
pub fn new_with_genesis_accounts(initial_data: &[(Address, u128)]) -> Self {
let authenticated_transfer_program = Program::authenticated_transfer_program();
let public_state = initial_data
.iter()
.copied()
.map(|(address_value, balance)| {
.map(|(address, balance)| {
let account = Account {
balance,
program_owner: authenticated_transfer_program.id(),
..Account::default()
};
let address = Address::new(address_value);
(address, account)
})
.collect();
@ -106,9 +105,9 @@ mod tests {
fn test_new_with_genesis() {
let key1 = PrivateKey::try_new([1; 32]).unwrap();
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let addr1 = Address::from_public_key(&PublicKey::new_from_private_key(&key1));
let addr2 = Address::from_public_key(&PublicKey::new_from_private_key(&key2));
let initial_data = [(*addr1.value(), 100u128), (*addr2.value(), 151u128)];
let addr1 = Address::from(&PublicKey::new_from_private_key(&key1));
let addr2 = Address::from(&PublicKey::new_from_private_key(&key2));
let initial_data = [(addr1, 100u128), (addr2, 151u128)];
let program = Program::authenticated_transfer_program();
let expected_public_state = {
let mut this = HashMap::new();
@ -157,8 +156,8 @@ mod tests {
#[test]
fn test_get_account_by_address_non_default_account() {
let key = PrivateKey::try_new([1; 32]).unwrap();
let addr = Address::from_public_key(&PublicKey::new_from_private_key(&key));
let initial_data = [(*addr.value(), 100u128)];
let addr = Address::from(&PublicKey::new_from_private_key(&key));
let initial_data = [(addr, 100u128)];
let state = V01State::new_with_genesis_accounts(&initial_data);
let expected_account = state.public_state.get(&addr).unwrap();
@ -190,8 +189,8 @@ mod tests {
#[test]
fn transition_from_authenticated_transfer_program_invocation_default_account_destination() {
let key = PrivateKey::try_new([1; 32]).unwrap();
let address = Address::from_public_key(&PublicKey::new_from_private_key(&key));
let initial_data = [(*address.value(), 100)];
let address = Address::from(&PublicKey::new_from_private_key(&key));
let initial_data = [(address, 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data);
let from = address;
let to = Address::new([2; 32]);
@ -210,8 +209,8 @@ mod tests {
#[test]
fn transition_from_authenticated_transfer_program_invocation_insuficient_balance() {
let key = PrivateKey::try_new([1; 32]).unwrap();
let address = Address::from_public_key(&PublicKey::new_from_private_key(&key));
let initial_data = [(*address.value(), 100)];
let address = Address::from(&PublicKey::new_from_private_key(&key));
let initial_data = [(address, 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data);
let from = address;
let from_key = key;
@ -233,9 +232,9 @@ mod tests {
fn transition_from_authenticated_transfer_program_invocation_non_default_account_destination() {
let key1 = PrivateKey::try_new([1; 32]).unwrap();
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let address1 = Address::from_public_key(&PublicKey::new_from_private_key(&key1));
let address2 = Address::from_public_key(&PublicKey::new_from_private_key(&key2));
let initial_data = [(*address1.value(), 100), (*address2.value(), 200)];
let address1 = Address::from(&PublicKey::new_from_private_key(&key1));
let address2 = Address::from(&PublicKey::new_from_private_key(&key2));
let initial_data = [(address1, 100), (address2, 200)];
let mut state = V01State::new_with_genesis_accounts(&initial_data);
let from = address2;
let from_key = key2;
@ -255,10 +254,10 @@ mod tests {
#[test]
fn transition_from_chained_authenticated_transfer_program_invocations() {
let key1 = PrivateKey::try_new([8; 32]).unwrap();
let address1 = Address::from_public_key(&PublicKey::new_from_private_key(&key1));
let address1 = Address::from(&PublicKey::new_from_private_key(&key1));
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let address2 = Address::from_public_key(&PublicKey::new_from_private_key(&key2));
let initial_data = [(*address1.value(), 100)];
let address2 = Address::from(&PublicKey::new_from_private_key(&key2));
let initial_data = [(address1, 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data);
let address3 = Address::new([3; 32]);
let balance_to_move = 5;
@ -336,7 +335,7 @@ mod tests {
#[test]
fn test_program_should_fail_if_modifies_nonces() {
let initial_data = [([1; 32], 100)];
let initial_data = [(Address::new([1; 32]), 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data).with_test_programs();
let addresses = vec![Address::new([1; 32])];
let program_id = Program::nonce_changer_program().id();
@ -352,7 +351,7 @@ mod tests {
#[test]
fn test_program_should_fail_if_output_accounts_exceed_inputs() {
let initial_data = [([1; 32], 100)];
let initial_data = [(Address::new([1; 32]), 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data).with_test_programs();
let addresses = vec![Address::new([1; 32])];
let program_id = Program::extra_output_program().id();
@ -368,7 +367,7 @@ mod tests {
#[test]
fn test_program_should_fail_with_missing_output_accounts() {
let initial_data = [([1; 32], 100)];
let initial_data = [(Address::new([1; 32]), 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data).with_test_programs();
let addresses = vec![Address::new([1; 32]), Address::new([2; 32])];
let program_id = Program::missing_output_program().id();
@ -384,7 +383,7 @@ mod tests {
#[test]
fn test_program_should_fail_if_modifies_program_owner_with_only_non_default_program_owner() {
let initial_data = [([1; 32], 0)];
let initial_data = [(Address::new([1; 32]), 0)];
let mut state = V01State::new_with_genesis_accounts(&initial_data).with_test_programs();
let address = Address::new([1; 32]);
let account = state.get_account_by_address(&address);
@ -478,7 +477,7 @@ mod tests {
#[test]
fn test_program_should_fail_if_transfers_balance_from_non_owned_account() {
let initial_data = [([1; 32], 100)];
let initial_data = [(Address::new([1; 32]), 100)];
let mut state = V01State::new_with_genesis_accounts(&initial_data).with_test_programs();
let sender_address = Address::new([1; 32]);
let receiver_address = Address::new([2; 32]);

View File

@ -8,4 +8,3 @@ risc0-build = { version = "2.3.1" }
[package.metadata.risc0]
methods = ["guest"]

View File

@ -7,5 +7,4 @@ edition = "2021"
[dependencies]
risc0-zkvm = { version = "2.3.1", default-features = false, features = ['std'] }
nssa-core = {path = "../../core"}
nssa-core = { path = "../../core" }

View File

@ -33,6 +33,9 @@ path = "../utxo"
[dependencies.common]
path = "../common"
[dependencies.nssa]
path = "../nssa"
[dependencies.secp256k1-zkp]
workspace = true
features = ["std", "rand-std", "rand", "serde", "global-context"]

View File

@ -1,5 +1,6 @@
use bincode;
use common::merkle_tree_public::merkle_tree::UTXOCommitmentsMerkleTree;
use nssa::Address;
use rand::{thread_rng, RngCore};
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
use sha2::{Digest, Sha256};
@ -82,7 +83,7 @@ pub fn private_circuit(
for in_utxo in input_utxos {
let nullifier_public_key = public_context
.account_masks
.get(&in_utxo.owner)
.get(&Address::new(in_utxo.owner))
.unwrap()
.nullifier_public_key;
@ -125,7 +126,7 @@ pub fn deshielded_circuit(
for in_utxo in input_utxos {
let nullifier_public_key = public_context
.account_masks
.get(&in_utxo.owner)
.get(&Address::new(in_utxo.owner))
.unwrap()
.nullifier_public_key;

View File

@ -1,7 +1,8 @@
use std::collections::BTreeMap;
use accounts::account_core::{address::AccountAddress, AccountPublicMask};
use accounts::account_core::AccountPublicMask;
use common::merkle_tree_public::{merkle_tree::UTXOCommitmentsMerkleTree, TreeHashType};
use nssa::Address;
use serde::{ser::SerializeStruct, Serialize};
pub const PUBLIC_SC_CONTEXT: &str = "PublicSCContext";
@ -16,9 +17,9 @@ pub const NULLIFIERS_SET: &str = "nullifiers_set";
///Strucutre, representing context, given to a smart contract on a call
pub struct PublicSCContext {
pub caller_address: AccountAddress,
pub caller_address: Address,
pub caller_balance: u64,
pub account_masks: BTreeMap<AccountAddress, AccountPublicMask>,
pub account_masks: BTreeMap<Address, AccountPublicMask>,
pub comitment_store_root: TreeHashType,
pub commitments_tree: UTXOCommitmentsMerkleTree,
}
@ -28,7 +29,12 @@ impl Serialize for PublicSCContext {
where
S: serde::Serializer,
{
let mut account_masks_keys: Vec<[u8; 32]> = self.account_masks.keys().cloned().collect();
let mut account_masks_keys: Vec<[u8; 32]> = self
.account_masks
.keys()
.cloned()
.map(|addr| *addr.value())
.collect();
account_masks_keys.sort();
let mut account_mask_values: Vec<AccountPublicMask> =
@ -94,7 +100,7 @@ mod tests {
use super::*;
fn create_test_context() -> PublicSCContext {
let caller_address = [1; 32];
let caller_address = Address::new([1; 32]);
let comitment_store_root = [3; 32];
let commitments_tree =

View File

@ -1,9 +1,8 @@
use std::path::Path;
use accounts::account_core::address::AccountAddress;
use block_store::SequecerBlockStore;
use common::block::HashableBlockData;
use nssa;
use nssa::{self, Address};
use rand::{rngs::OsRng, RngCore};
use crate::config::AccountInitialData;
@ -22,7 +21,7 @@ impl SequecerChainStore {
is_genesis_random: bool,
initial_accounts: &[AccountInitialData],
) -> Self {
let init_accs: Vec<(AccountAddress, u128)> = initial_accounts
let init_accs: Vec<(Address, u128)> = initial_accounts
.iter()
.map(|acc_data| {
(

View File

@ -1,8 +1,9 @@
use accounts::account_core::{address::AccountAddress, Account};
use accounts::account_core::Account;
use nssa::Address;
use std::collections::HashMap;
pub struct WalletAccountsStore {
pub accounts: HashMap<AccountAddress, Account>,
pub accounts: HashMap<Address, Account>,
}
impl WalletAccountsStore {
@ -16,7 +17,7 @@ impl WalletAccountsStore {
self.accounts.insert(account.address, account);
}
pub fn unregister_account(&mut self, account_addr: AccountAddress) {
pub fn unregister_account(&mut self, account_addr: Address) {
self.accounts.remove(&account_addr);
}
}
@ -82,7 +83,7 @@ mod tests {
let mut store = WalletAccountsStore::new();
let account_addr: [u8; 32] = pad_to_32("nonexistent".to_string().as_bytes());
store.unregister_account(account_addr);
store.unregister_account(Address::new(account_addr));
assert!(store.accounts.is_empty());
}

View File

@ -1,8 +1,9 @@
use std::collections::{BTreeMap, HashMap};
use accounts::account_core::{address::AccountAddress, Account};
use accounts::account_core::Account;
use anyhow::Result;
use common::merkle_tree_public::merkle_tree::UTXOCommitmentsMerkleTree;
use nssa::Address;
use sc_core::public_context::PublicSCContext;
use serde::{Deserialize, Serialize};
@ -37,7 +38,7 @@ impl From<AccMap> for HashMap<[u8; 32], Account> {
}
pub struct WalletChainStore {
pub acc_map: HashMap<AccountAddress, Account>,
pub acc_map: HashMap<Address, Account>,
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
pub wallet_config: WalletConfig,
}
@ -54,7 +55,7 @@ impl WalletChainStore {
})
}
pub fn produce_context(&self, caller: AccountAddress) -> PublicSCContext {
pub fn produce_context(&self, caller: Address) -> PublicSCContext {
let mut account_masks = BTreeMap::new();
for (acc_addr, acc) in &self.acc_map {
@ -80,7 +81,7 @@ mod tests {
fn create_initial_accounts() -> Vec<Account> {
let initial_acc1 = serde_json::from_str(r#"{
"address": [27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143],
"address": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
"balance": 100,
"key_holder": {
"nullifer_public_key": "03A340BECA9FAAB444CED0140681D72EA1318B5C611704FEE017DA9836B17DB718",
@ -98,7 +99,7 @@ mod tests {
}"#).unwrap();
let initial_acc2 = serde_json::from_str(r#"{
"address": [77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234, 216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102],
"address": "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
"balance": 200,
"key_holder": {
"nullifer_public_key": "02172F50274DE67C4087C344F5D58E11DF761D90285B095060E0994FAA6BCDE271",

View File

@ -1,6 +1,7 @@
use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr};
use anyhow::{anyhow, Result};
use anyhow::Result;
use nssa::{address::HexString, Address};
use crate::{config::WalletConfig, HOME_DIR_ENV_VAR};
@ -19,8 +20,6 @@ pub fn fetch_config() -> Result<WalletConfig> {
}
//ToDo: Replace with structures conversion in future
pub fn produce_account_addr_from_hex(hex_str: String) -> Result<[u8; 32]> {
hex::decode(hex_str)?
.try_into()
.map_err(|_| anyhow!("Failed conversion to 32 bytes"))
pub fn produce_account_addr_from_hex(hex_str: String) -> Result<Address> {
Ok(HexString::try_from(hex_str.as_str())?.into())
}

View File

@ -5,11 +5,12 @@ use common::{
ExecutionFailureKind,
};
use accounts::account_core::{address::AccountAddress, Account};
use accounts::account_core::Account;
use anyhow::Result;
use chain_storage::WalletChainStore;
use config::WalletConfig;
use log::info;
use nssa::Address;
use tokio::sync::RwLock;
use clap::{Parser, Subcommand};
@ -47,7 +48,7 @@ impl WalletCore {
})
}
pub async fn create_new_account(&mut self) -> AccountAddress {
pub async fn create_new_account(&mut self) -> Address {
let account = Account::new();
account.log();
@ -64,9 +65,9 @@ impl WalletCore {
pub async fn send_public_native_token_transfer(
&self,
from: AccountAddress,
from: Address,
nonce: u128,
to: AccountAddress,
to: Address,
balance_to_move: u128,
) -> Result<SendTxResponse, ExecutionFailureKind> {
{
@ -75,7 +76,7 @@ impl WalletCore {
let account = read_guard.acc_map.get(&from);
if let Some(account) = account {
let addresses = vec![nssa::Address::new(from), nssa::Address::new(to)];
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(

View File

@ -24,6 +24,9 @@ path = "../utxo"
[dependencies.common]
path = "../common"
[dependencies.nssa]
path = "../nssa"
[features]
cuda = ["risc0-zkvm/cuda"]
default = []

View File

@ -1,5 +1,5 @@
use accounts::account_core::address::AccountAddress;
use common::ExecutionFailureKind;
use nssa::Address;
use rand::{rngs::OsRng, RngCore};
use risc0_zkvm::{default_executor, default_prover, sha::Digest, ExecutorEnv, Receipt};
use serde::Serialize;
@ -35,7 +35,7 @@ pub fn gas_limits_check<INP: Serialize>(
#[allow(clippy::result_large_err)]
pub fn prove_mint_utxo(
amount_to_mint: u128,
owner: AccountAddress,
owner: Address,
) -> Result<(UTXO, Receipt), ExecutionFailureKind> {
let mut builder = ExecutorEnv::builder();
@ -74,8 +74,8 @@ pub fn prove_mint_utxo(
#[allow(clippy::result_large_err)]
pub fn prove_send_utxo(
spent_utxo: UTXO,
owners_parts: Vec<(u128, AccountAddress)>,
) -> Result<(Vec<(UTXO, AccountAddress)>, Receipt), ExecutionFailureKind> {
owners_parts: Vec<(u128, Address)>,
) -> Result<(Vec<(UTXO, Address)>, Receipt), ExecutionFailureKind> {
let cumulative_spent = owners_parts.iter().fold(0, |acc, item| acc + item.0);
if cumulative_spent != spent_utxo.amount {
@ -113,7 +113,7 @@ pub fn prove_send_utxo(
.map_err(ExecutionFailureKind::prove_error)?
.receipt;
let digest: Vec<(UTXOPayload, AccountAddress)> = receipt
let digest: Vec<(UTXOPayload, Address)> = receipt
.journal
.decode()
.map_err(|e| ExecutionFailureKind::DecodeError(e.to_string()))?;
@ -131,7 +131,7 @@ pub fn prove_send_utxo(
pub fn prove_send_utxo_multiple_assets_one_receiver(
spent_utxos: Vec<UTXO>,
number_to_send: usize,
receiver: AccountAddress,
receiver: Address,
) -> Result<(Vec<UTXO>, Vec<UTXO>, Receipt), ExecutionFailureKind> {
if number_to_send > spent_utxos.len() {
return Err(ExecutionFailureKind::AmountMismatchError);
@ -186,17 +186,17 @@ pub fn prove_send_utxo_multiple_assets_one_receiver(
#[allow(clippy::result_large_err)]
pub fn prove_send_utxo_shielded(
owner: AccountAddress,
owner: Address,
amount: u128,
owners_parts: Vec<(u128, AccountAddress)>,
) -> Result<(Vec<(UTXO, AccountAddress)>, Receipt), ExecutionFailureKind> {
owners_parts: Vec<(u128, Address)>,
) -> Result<(Vec<(UTXO, Address)>, Receipt), ExecutionFailureKind> {
let cumulative_spent = owners_parts.iter().fold(0, |acc, item| acc + item.0);
if cumulative_spent != amount {
return Err(ExecutionFailureKind::AmountMismatchError);
}
let temp_utxo_to_spend = UTXO::new(owner, vec![], amount, true);
let temp_utxo_to_spend = UTXO::new(*owner.value(), vec![], amount, true);
let utxo_payload = temp_utxo_to_spend.into_payload();
let mut builder = ExecutorEnv::builder();
@ -229,7 +229,7 @@ pub fn prove_send_utxo_shielded(
.map_err(ExecutionFailureKind::prove_error)?
.receipt;
let digest: Vec<(UTXOPayload, AccountAddress)> = receipt
let digest: Vec<(UTXOPayload, Address)> = receipt
.journal
.decode()
.map_err(|e| ExecutionFailureKind::DecodeError(e.to_string()))?;
@ -246,8 +246,8 @@ pub fn prove_send_utxo_shielded(
#[allow(clippy::result_large_err)]
pub fn prove_send_utxo_deshielded(
spent_utxo: UTXO,
owners_parts: Vec<(u128, AccountAddress)>,
) -> Result<(Vec<(u128, AccountAddress)>, Receipt), ExecutionFailureKind> {
owners_parts: Vec<(u128, Address)>,
) -> Result<(Vec<(u128, Address)>, Receipt), ExecutionFailureKind> {
let cumulative_spent = owners_parts.iter().fold(0, |acc, item| acc + item.0);
if cumulative_spent != spent_utxo.amount {
@ -285,7 +285,7 @@ pub fn prove_send_utxo_deshielded(
.map_err(ExecutionFailureKind::prove_error)?
.receipt;
let digest: Vec<(UTXOPayload, AccountAddress)> = receipt
let digest: Vec<(UTXOPayload, Address)> = receipt
.journal
.decode()
.map_err(|e| ExecutionFailureKind::DecodeError(e.to_string()))?;
@ -303,7 +303,7 @@ pub fn prove_send_utxo_deshielded(
pub fn prove_mint_utxo_multiple_assets(
amount_to_mint: u128,
number_of_assets: usize,
owner: AccountAddress,
owner: Address,
) -> Result<(Vec<UTXO>, Receipt), ExecutionFailureKind> {
let mut builder = ExecutorEnv::builder();
@ -344,7 +344,7 @@ pub fn prove_mint_utxo_multiple_assets(
pub fn execute_mint_utxo(
amount_to_mint: u128,
owner: AccountAddress,
owner: Address,
randomness: [u8; 32],
) -> anyhow::Result<UTXO> {
let mut builder = ExecutorEnv::builder();
@ -366,8 +366,8 @@ pub fn execute_mint_utxo(
pub fn execute_send_utxo(
spent_utxo: UTXO,
owners_parts: Vec<(u128, AccountAddress)>,
) -> anyhow::Result<(UTXO, Vec<(UTXO, AccountAddress)>)> {
owners_parts: Vec<(u128, Address)>,
) -> anyhow::Result<(UTXO, Vec<(UTXO, Address)>)> {
let mut builder = ExecutorEnv::builder();
let utxo_payload = spent_utxo.into_payload();
@ -390,7 +390,7 @@ pub fn execute_send_utxo(
let receipt = executor.execute(env, test_methods::SEND_UTXO_ELF)?;
let digest: (UTXOPayload, Vec<(UTXOPayload, AccountAddress)>) = receipt.journal.decode()?;
let digest: (UTXOPayload, Vec<(UTXOPayload, Address)>) = receipt.journal.decode()?;
Ok((
UTXO::create_utxo_from_payload(digest.0),
@ -572,29 +572,29 @@ mod tests {
#[test]
fn test_execute_mint_utxo() {
let owner = AccountAddress::default();
let owner = Address::default();
let amount = 123456789;
let mut randomness = [0u8; 32];
OsRng.fill_bytes(&mut randomness);
let utxo_exec = execute_mint_utxo(amount, owner, randomness).expect("execution failed");
assert_eq!(utxo_exec.amount, amount);
assert_eq!(utxo_exec.owner, owner);
assert_eq!(utxo_exec.owner, *owner.value());
}
#[test]
fn test_prove_mint_utxo() {
let owner = AccountAddress::default();
let owner = Address::default();
let amount = 123456789;
let (utxo, _) = prove_mint_utxo(amount, owner).expect("proof failed");
assert_eq!(utxo.amount, amount);
assert_eq!(utxo.owner, owner);
assert_eq!(utxo.owner, *owner.value());
}
#[test]
fn test_prove_send_utxo() {
let owner = AccountAddress::default();
let owner = Address::default();
let amount = 100;
let (input_utxo, _) = prove_mint_utxo(amount, owner).expect("mint failed");
@ -608,7 +608,7 @@ mod tests {
#[test]
fn test_prove_send_utxo_deshielded() {
let owner = AccountAddress::default();
let owner = Address::default();
let amount = 100;
let (utxo, _) = prove_mint_utxo(amount, owner).unwrap();
let parts = vec![(60, owner), (40, owner)];
@ -622,7 +622,7 @@ mod tests {
#[test]
fn test_prove_send_utxo_shielded() {
let owner = AccountAddress::default();
let owner = Address::default();
let amount = 100;
let parts = vec![(60, owner), (40, owner)];
@ -635,8 +635,8 @@ mod tests {
#[test]
fn test_prove_send_utxo_multiple_assets_one_receiver() {
let owner = AccountAddress::default();
let receiver = AccountAddress::default();
let owner = Address::default();
let receiver = Address::default();
let utxos = vec![
prove_mint_utxo(100, owner).unwrap().0,