fix: clearing and renaming

This commit is contained in:
Oleksandr Pravdyvyi 2025-08-15 14:27:36 +03:00
parent 74f0c983d3
commit 35b636a27d
No known key found for this signature in database
GPG Key ID: 9F8955C63C443871
22 changed files with 84 additions and 340 deletions

View File

@ -4,8 +4,7 @@ members = [
"integration_tests",
"sequencer_runner",
"storage",
"accounts",
"utxo",
"key_protocol",
"sequencer_rpc",
"mempool",
"wallet",

View File

@ -1,2 +0,0 @@
pub mod account_core;
pub mod key_management;

View File

@ -36,5 +36,5 @@ path = "../wallet"
[dependencies.common]
path = "../common"
[dependencies.accounts]
path = "../accounts"
[dependencies.key_protocol]
path = "../key_protocol"

View File

@ -1,5 +1,5 @@
[package]
name = "accounts"
name = "key_protocol"
version = "0.1.0"
edition = "2021"
@ -18,9 +18,6 @@ aes-gcm.workspace = true
lazy_static.workspace = true
tiny-keccak.workspace = true
[dependencies.utxo]
path = "../utxo"
[dependencies.common]
path = "../common"

View File

@ -7,7 +7,7 @@ use rand::{rngs::OsRng, Rng};
use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder};
use serde::{Deserialize, Serialize};
use crate::account_core::PublicKey;
use crate::key_protocol_core::PublicKey;
pub type PublicAccountSigningKey = [u8; 32];
use nssa::{self};
@ -17,7 +17,7 @@ pub mod secret_holders;
#[derive(Serialize, Deserialize, Clone, Debug)]
///Entrypoint to key management
pub struct AddressKeyHolder {
pub struct KeyChain {
top_secret_key_holder: TopSecretKeyHolder,
pub utxo_secret_key_holder: UTXOSecretKeyHolder,
pub_account_signing_key: nssa::PrivateKey,
@ -25,7 +25,7 @@ pub struct AddressKeyHolder {
pub viewing_public_key: PublicKey,
}
impl AddressKeyHolder {
impl KeyChain {
pub fn new_os_random() -> Self {
//Currently dropping SeedHolder at the end of initialization.
//Now entirely sure if we need it in the future.
@ -127,8 +127,8 @@ mod tests {
#[test]
fn test_new_os_random() {
// Ensure that a new AddressKeyHolder instance can be created without errors.
let address_key_holder = AddressKeyHolder::new_os_random();
// Ensure that a new KeyChain instance can be created without errors.
let address_key_holder = KeyChain::new_os_random();
// Check that key holder fields are initialized with expected types
assert!(!Into::<bool>::into(
@ -141,7 +141,7 @@ mod tests {
#[test]
fn test_calculate_shared_secret_receiver() {
let address_key_holder = AddressKeyHolder::new_os_random();
let address_key_holder = KeyChain::new_os_random();
// Generate a random ephemeral public key sender
let scalar = Scalar::random(&mut OsRng);
@ -157,7 +157,7 @@ mod tests {
#[test]
fn test_decrypt_data() {
let address_key_holder = AddressKeyHolder::new_os_random();
let address_key_holder = KeyChain::new_os_random();
// Generate an ephemeral key and shared secret
let ephemeral_public_key_sender =
@ -188,8 +188,8 @@ mod tests {
#[test]
fn test_new_os_random_initialization() {
// Ensure that AddressKeyHolder is initialized correctly
let address_key_holder = AddressKeyHolder::new_os_random();
// Ensure that KeyChain is initialized correctly
let address_key_holder = KeyChain::new_os_random();
// Check that key holder fields are initialized with expected types and values
assert!(!Into::<bool>::into(
@ -202,7 +202,7 @@ mod tests {
#[test]
fn test_calculate_shared_secret_with_identity_point() {
let address_key_holder = AddressKeyHolder::new_os_random();
let address_key_holder = KeyChain::new_os_random();
// Use identity point as ephemeral public key
let identity_point = AffinePoint::identity();
@ -217,7 +217,7 @@ mod tests {
#[test]
#[should_panic]
fn test_decrypt_data_with_incorrect_nonce() {
let address_key_holder = AddressKeyHolder::new_os_random();
let address_key_holder = KeyChain::new_os_random();
// Generate ephemeral public key and shared secret
let scalar = Scalar::random(OsRng);
@ -250,7 +250,7 @@ mod tests {
#[test]
#[should_panic]
fn test_decrypt_data_with_incorrect_ciphertext() {
let address_key_holder = AddressKeyHolder::new_os_random();
let address_key_holder = KeyChain::new_os_random();
// Generate ephemeral public key and shared secret
let scalar = Scalar::random(OsRng);
@ -285,7 +285,7 @@ mod tests {
#[test]
fn test_encryption_decryption_round_trip() {
let address_key_holder = AddressKeyHolder::new_os_random();
let address_key_holder = KeyChain::new_os_random();
// Generate ephemeral key and shared secret
let scalar = Scalar::random(OsRng);
@ -303,7 +303,7 @@ mod tests {
.encrypt(nonce, plaintext.as_ref())
.expect("encryption failure");
// Decrypt the data using the `AddressKeyHolder` instance
// Decrypt the data using the `KeyChain` instance
let decrypted_data = address_key_holder
.decrypt_data(
ephemeral_public_key_sender,
@ -318,7 +318,7 @@ mod tests {
#[test]
fn test_get_public_account_signing_key() {
let address_key_holder = AddressKeyHolder::new_os_random();
let address_key_holder = KeyChain::new_os_random();
let signing_key = address_key_holder.get_pub_account_signing_key();
assert_eq!(signing_key, &address_key_holder.pub_account_signing_key);
}

View File

@ -1,83 +1,68 @@
use std::collections::HashMap;
use anyhow::Result;
use common::{merkle_tree_public::TreeHashType, transaction::Tag};
use common::transaction::Tag;
use k256::AffinePoint;
use log::info;
use nssa::Address;
use serde::{Deserialize, Serialize};
use utxo::utxo_core::UTXO;
use crate::key_management::{
constants_types::{CipherText, Nonce},
ephemeral_key_holder::EphemeralKeyHolder,
AddressKeyHolder,
KeyChain,
};
pub type PublicKey = AffinePoint;
#[derive(Clone, Debug)]
pub struct Account {
pub key_holder: AddressKeyHolder,
pub struct NSSAUserData {
pub key_holder: KeyChain,
pub address: Address,
pub balance: u64,
pub utxos: HashMap<TreeHashType, UTXO>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AccountForSerialization {
pub key_holder: AddressKeyHolder,
pub struct NSSAUserDataForSerialization {
pub key_holder: KeyChain,
pub address: Address,
pub balance: u64,
pub utxos: HashMap<String, UTXO>,
}
impl From<Account> for AccountForSerialization {
fn from(value: Account) -> Self {
AccountForSerialization {
impl From<NSSAUserData> for NSSAUserDataForSerialization {
fn from(value: NSSAUserData) -> Self {
NSSAUserDataForSerialization {
key_holder: value.key_holder,
address: value.address,
balance: value.balance,
utxos: value
.utxos
.into_iter()
.map(|(key, val)| (hex::encode(key), val))
.collect(),
}
}
}
impl From<AccountForSerialization> for Account {
fn from(value: AccountForSerialization) -> Self {
Account {
impl From<NSSAUserDataForSerialization> for NSSAUserData {
fn from(value: NSSAUserDataForSerialization) -> Self {
NSSAUserData {
key_holder: value.key_holder,
address: value.address,
balance: value.balance,
utxos: value
.utxos
.into_iter()
.map(|(key, val)| (hex::decode(key).unwrap().try_into().unwrap(), val))
.collect(),
}
}
}
impl Serialize for Account {
impl Serialize for NSSAUserData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let account_for_serialization: AccountForSerialization = From::from(self.clone());
let account_for_serialization: NSSAUserDataForSerialization = From::from(self.clone());
account_for_serialization.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Account {
impl<'de> Deserialize<'de> for NSSAUserData {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let account_for_serialization = <AccountForSerialization>::deserialize(deserializer)?;
let account_for_serialization = <NSSAUserDataForSerialization>::deserialize(deserializer)?;
Ok(account_for_serialization.into())
}
}
@ -88,21 +73,21 @@ impl<'de> Deserialize<'de> for Account {
///
/// Main usage is to encode data for other account
#[derive(Serialize, Clone)]
pub struct AccountPublicMask {
pub struct NSSAUserDataPublicMask {
pub nullifier_public_key: AffinePoint,
pub viewing_public_key: AffinePoint,
pub address: Address,
pub balance: u64,
}
impl AccountPublicMask {
impl NSSAUserDataPublicMask {
pub fn encrypt_data(
ephemeral_key_holder: &EphemeralKeyHolder,
viewing_public_key_receiver: AffinePoint,
data: &[u8],
) -> (CipherText, Nonce) {
//Using of parent Account fuction
Account::encrypt_data(ephemeral_key_holder, viewing_public_key_receiver, data)
//Using of parent NSSAUserData fuction
NSSAUserData::encrypt_data(ephemeral_key_holder, viewing_public_key_receiver, data)
}
pub fn make_tag(&self) -> Tag {
@ -110,35 +95,31 @@ impl AccountPublicMask {
}
}
impl Account {
impl NSSAUserData {
pub fn new() -> Self {
let key_holder = AddressKeyHolder::new_os_random();
let key_holder = KeyChain::new_os_random();
let public_key =
nssa::PublicKey::new_from_private_key(key_holder.get_pub_account_signing_key());
let address = nssa::Address::from(&public_key);
let balance = 0;
let utxos = HashMap::new();
Self {
key_holder,
address,
balance,
utxos,
}
}
pub fn new_with_balance(balance: u64) -> Self {
let key_holder = AddressKeyHolder::new_os_random();
let key_holder = KeyChain::new_os_random();
let public_key =
nssa::PublicKey::new_from_private_key(key_holder.get_pub_account_signing_key());
let address = nssa::Address::from(&public_key);
let utxos = HashMap::new();
Self {
key_holder,
address,
balance,
utxos,
}
}
@ -160,42 +141,14 @@ impl Account {
.decrypt_data(ephemeral_public_key_sender, ciphertext, nonce)
}
pub fn add_new_utxo_outputs(&mut self, utxos: Vec<UTXO>) -> Result<()> {
for utxo in utxos {
if self.utxos.contains_key(&utxo.hash) {
return Err(anyhow::anyhow!("UTXO already exists"));
}
self.utxos.insert(utxo.hash, utxo);
}
Ok(())
}
pub fn update_public_balance(&mut self, new_balance: u64) {
self.balance = new_balance;
}
pub fn add_asset<Asset: Serialize>(
&mut self,
asset: Asset,
amount: u128,
privacy_flag: bool,
) -> Result<()> {
let asset_utxo = UTXO::new(
*self.address.value(),
serde_json::to_vec(&asset)?,
amount,
privacy_flag,
);
self.utxos.insert(asset_utxo.hash, asset_utxo);
Ok(())
}
pub fn log(&self) {
info!("Keys generated");
info!("Account address is {:?}", hex::encode(self.address));
info!("Account balance is {:?}", self.balance);
info!("NSSAUserData address is {:?}", hex::encode(self.address));
info!("NSSAUserData balance is {:?}", self.balance);
}
pub fn make_tag(&self) -> Tag {
@ -203,8 +156,8 @@ impl Account {
}
///Produce account public mask
pub fn make_account_public_mask(&self) -> AccountPublicMask {
AccountPublicMask {
pub fn make_account_public_mask(&self) -> NSSAUserDataPublicMask {
NSSAUserDataPublicMask {
nullifier_public_key: self.key_holder.nullifer_public_key,
viewing_public_key: self.key_holder.viewing_public_key,
address: self.address,
@ -213,7 +166,7 @@ impl Account {
}
}
impl Default for Account {
impl Default for NSSAUserData {
fn default() -> Self {
Self::new()
}
@ -223,52 +176,24 @@ impl Default for Account {
mod tests {
use super::*;
fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> UTXO {
UTXO::new(address, vec![], amount, false)
}
#[test]
fn test_new_account() {
let account = Account::new();
let account = NSSAUserData::new();
assert_eq!(account.balance, 0);
}
#[test]
fn test_add_new_utxo_outputs() {
let mut account = Account::new();
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()]);
assert!(result.is_ok());
assert_eq!(account.utxos.len(), 2);
}
#[test]
fn test_update_public_balance() {
let mut account = Account::new();
let mut account = NSSAUserData::new();
account.update_public_balance(500);
assert_eq!(account.balance, 500);
}
#[test]
fn test_add_asset() {
let mut account = Account::new();
let asset = "dummy_asset";
let amount = 1000u128;
let result = account.add_asset(asset, amount, false);
assert!(result.is_ok());
assert_eq!(account.utxos.len(), 1);
}
#[test]
fn accounts_accounts_mask_tag_consistency() {
let account = Account::new();
let account = NSSAUserData::new();
let account_mask = account.make_account_public_mask();

2
key_protocol/src/lib.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod key_protocol_core;
pub mod key_management;

View File

@ -22,8 +22,8 @@ path = "../storage"
[dependencies.mempool]
path = "../mempool"
[dependencies.accounts]
path = "../accounts"
[dependencies.key_protocol]
path = "../key_protocol"
[dependencies.common]
path = "../common"

View File

@ -22,8 +22,8 @@ tokio.workspace = true
[dependencies.mempool]
path = "../mempool"
[dependencies.accounts]
path = "../accounts"
[dependencies.key_protocol]
path = "../key_protocol"
[dependencies.sequencer_core]
path = "../sequencer_core"

View File

@ -1,17 +0,0 @@
[package]
name = "utxo"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow.workspace = true
serde_json.workspace = true
env_logger.workspace = true
log.workspace = true
serde.workspace = true
sha2.workspace = true
hex.workspace = true
rand.workspace = true
[dependencies.common]
path = "../common"

View File

@ -1 +0,0 @@
pub mod utxo_core;

View File

@ -1,162 +0,0 @@
use anyhow::Result;
use common::{merkle_tree_public::TreeHashType, AccountId};
use log::info;
use rand::{rngs::OsRng, RngCore};
use serde::{Deserialize, Serialize};
use sha2::{digest::FixedOutput, Digest};
///Raw asset data
pub type Asset = Vec<u8>;
pub type Randomness = [u8; 32];
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
///Container for raw utxo payload
pub struct UTXO {
pub hash: TreeHashType,
pub owner: AccountId,
pub asset: Asset,
// TODO: change to u256
pub amount: u128,
pub privacy_flag: bool,
pub randomness: Randomness,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UTXOPayload {
pub owner: AccountId,
pub asset: Asset,
// TODO: change to u256
pub amount: u128,
pub privacy_flag: bool,
pub randomness: Randomness,
}
impl UTXOPayload {
fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::new();
result.extend_from_slice(&self.owner);
result.extend_from_slice(&self.asset);
result.extend_from_slice(&self.amount.to_be_bytes());
result.push(self.privacy_flag as u8);
result.extend_from_slice(&self.randomness);
result
}
}
impl UTXO {
pub fn new(owner: AccountId, asset: Asset, amount: u128, privacy_flag: bool) -> Self {
let mut randomness = Randomness::default();
OsRng.fill_bytes(&mut randomness);
let payload = UTXOPayload {
owner,
asset,
amount,
privacy_flag,
randomness,
};
Self::create_utxo_from_payload(payload)
}
pub fn create_utxo_from_payload(payload_with_asset: UTXOPayload) -> Self {
let mut hasher = sha2::Sha256::new();
hasher.update(payload_with_asset.to_bytes());
let hash = <TreeHashType>::from(hasher.finalize_fixed());
Self {
hash,
owner: payload_with_asset.owner,
asset: payload_with_asset.asset,
amount: payload_with_asset.amount,
privacy_flag: payload_with_asset.privacy_flag,
randomness: payload_with_asset.randomness,
}
}
pub fn interpret_asset<'de, ToInterpret: Deserialize<'de>>(&'de self) -> Result<ToInterpret> {
Ok(serde_json::from_slice(&self.asset)?)
}
pub fn into_payload(&self) -> UTXOPayload {
UTXOPayload {
owner: self.owner,
asset: self.asset.clone(),
amount: self.amount,
privacy_flag: self.privacy_flag,
randomness: self.randomness,
}
}
pub fn log(&self) {
info!("UTXO hash is {:?}", hex::encode(self.hash));
info!("UTXO owner is {:?}", hex::encode(self.owner));
info!("UTXO asset is {:?}", hex::encode(self.asset.clone()));
info!("UTXO amount is {:?}", self.amount);
info!("UTXO privacy_flag is {:?}", self.privacy_flag);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct TestAsset {
id: u32,
name: String,
}
fn sample_account() -> AccountId {
AccountId::default()
}
fn sample_payload() -> UTXOPayload {
UTXOPayload {
owner: sample_account(),
asset: serde_json::to_vec(&TestAsset {
id: 1,
name: "Test".to_string(),
})
.unwrap(),
amount: 10,
privacy_flag: false,
randomness: Randomness::default(),
}
}
#[test]
fn test_create_utxo_from_payload() {
let payload = sample_payload();
let utxo = UTXO::create_utxo_from_payload(payload.clone());
// Ensure hash is created and the UTXO fields are correctly assigned
assert_eq!(utxo.owner, payload.owner);
assert_eq!(utxo.asset, payload.asset);
}
#[test]
fn test_interpret_asset() {
let payload = sample_payload();
let utxo = UTXO::create_utxo_from_payload(payload);
// Interpret asset as TestAsset
let interpreted: TestAsset = utxo.interpret_asset().unwrap();
assert_eq!(
interpreted,
TestAsset {
id: 1,
name: "Test".to_string()
}
);
}
#[test]
fn test_interpret_invalid_asset() {
let mut payload = sample_payload();
payload.asset = vec![0, 1, 2, 3]; // Invalid data for deserialization
let utxo = UTXO::create_utxo_from_payload(payload);
// This should fail because the asset is not valid JSON for TestAsset
let result: Result<TestAsset> = utxo.interpret_asset();
assert!(result.is_err());
}
}

View File

@ -23,11 +23,8 @@ hex.workspace = true
actix-rt.workspace = true
clap.workspace = true
[dependencies.accounts]
path = "../accounts"
[dependencies.utxo]
path = "../utxo"
[dependencies.key_protocol]
path = "../key_protocol"
[dependencies.nssa]
path = "../nssa"

View File

@ -1,9 +1,10 @@
use accounts::account_core::Account;
//TODO: NOT NSSA USER DATA, ACCOUNT
use key_protocol::key_protocol_core::NSSAUserData;
use nssa::Address;
use std::collections::HashMap;
pub struct WalletAccountsStore {
pub accounts: HashMap<Address, Account>,
pub accounts: HashMap<Address, NSSAUserData>,
}
impl WalletAccountsStore {
@ -13,7 +14,7 @@ impl WalletAccountsStore {
}
}
pub fn register_account(&mut self, account: Account) {
pub fn register_account(&mut self, account: NSSAUserData) {
self.accounts.insert(account.address, account);
}
@ -31,10 +32,10 @@ impl Default for WalletAccountsStore {
#[cfg(test)]
mod tests {
use super::*;
use accounts::account_core::Account;
use key_protocol::key_protocol_core::NSSAUserData;
/// Helper function to create a sample account
fn create_sample_account(balance: u64) -> Account {
Account::new_with_balance(balance)
fn create_sample_account(balance: u64) -> NSSAUserData {
NSSAUserData::new_with_balance(balance)
}
fn pad_to_32(slice: &[u8]) -> [u8; 32] {

View File

@ -1,6 +1,7 @@
use std::collections::HashMap;
use accounts::account_core::Account;
//TODO: NOT USER DATA, ACCOUNT
use key_protocol::key_protocol_core::NSSAUserData;
use anyhow::Result;
use common::merkle_tree_public::merkle_tree::UTXOCommitmentsMerkleTree;
use nssa::Address;
@ -12,11 +13,11 @@ pub mod accounts_store;
#[derive(Deserialize, Serialize)]
pub struct AccMap {
pub acc_map: HashMap<String, Account>,
pub acc_map: HashMap<String, NSSAUserData>,
}
impl From<HashMap<[u8; 32], Account>> for AccMap {
fn from(value: HashMap<[u8; 32], Account>) -> Self {
impl From<HashMap<[u8; 32], NSSAUserData>> for AccMap {
fn from(value: HashMap<[u8; 32], NSSAUserData>) -> Self {
AccMap {
acc_map: value
.into_iter()
@ -26,7 +27,7 @@ impl From<HashMap<[u8; 32], Account>> for AccMap {
}
}
impl From<AccMap> for HashMap<[u8; 32], Account> {
impl From<AccMap> for HashMap<[u8; 32], NSSAUserData> {
fn from(value: AccMap) -> Self {
value
.acc_map
@ -37,7 +38,7 @@ impl From<AccMap> for HashMap<[u8; 32], Account> {
}
pub struct WalletChainStore {
pub acc_map: HashMap<Address, Account>,
pub acc_map: HashMap<Address, NSSAUserData>,
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
pub wallet_config: WalletConfig,
}
@ -58,11 +59,11 @@ impl WalletChainStore {
#[cfg(test)]
mod tests {
use super::*;
use accounts::account_core::Account;
use key_protocol::key_protocol_core::NSSAUserData;
use std::path::PathBuf;
use tempfile::tempdir;
fn create_initial_accounts() -> Vec<Account> {
fn create_initial_accounts() -> Vec<NSSAUserData> {
let initial_acc1 = serde_json::from_str(r#"{
"address": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
"balance": 100,

View File

@ -1,6 +1,6 @@
use std::path::PathBuf;
use accounts::account_core::Account;
use key_protocol::key_protocol_core::NSSAUserData;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -32,5 +32,7 @@ pub struct WalletConfig {
///Sequencer polling duration for new blocks in seconds
pub seq_poll_timeout_secs: u64,
///Initial accounts for wallet
pub initial_accounts: Vec<Account>,
///
/// TODO: NOT USRE DATA, ACCOUNT
pub initial_accounts: Vec<NSSAUserData>,
}

View File

@ -1,6 +1,6 @@
use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr};
use accounts::account_core::Account;
use key_protocol::key_protocol_core::NSSAUserData;
use anyhow::Result;
use nssa::Address;
@ -28,7 +28,9 @@ 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<Account>> {
///
/// ToDo: NOT USER DATA, ACCOUNT
pub fn fetch_persistent_accounts() -> Result<Vec<NSSAUserData>> {
let home = get_home()?;
let accs_path = home.join("curr_accounts.json");

View File

@ -5,7 +5,7 @@ use common::{
ExecutionFailureKind,
};
use accounts::account_core::Account;
use key_protocol::key_protocol_core::NSSAUserData;
use anyhow::Result;
use chain_storage::WalletChainStore;
use config::WalletConfig;
@ -54,7 +54,7 @@ impl WalletCore {
}
pub async fn create_new_account(&mut self) -> Address {
let account = Account::new();
let account = NSSAUserData::new();
account.log();
let addr = account.address;