203 lines
5.2 KiB
Rust
Raw Normal View History

2025-05-16 22:23:35 -03:00
use std::collections::HashMap;
2024-10-30 12:32:36 +02:00
use anyhow::Result;
2025-05-16 22:33:38 -03:00
use common::{merkle_tree_public::TreeHashType, transaction::Tag};
2024-10-30 12:32:36 +02:00
use k256::AffinePoint;
use log::info;
2025-01-31 17:01:50 -05:00
use serde::Serialize;
2025-05-16 22:06:06 -03:00
use utxo::utxo_core::{UTXOPayload, UTXO};
2024-10-30 12:32:36 +02:00
use crate::key_management::{
constants_types::{CipherText, Nonce},
ephemeral_key_holder::EphemeralKeyHolder,
AddressKeyHolder,
};
2024-11-25 07:26:16 +02:00
pub type PublicKey = AffinePoint;
pub type AccountAddress = TreeHashType;
2025-05-29 12:00:50 +03:00
#[derive(Debug, Serialize)]
2024-10-30 12:32:36 +02:00
pub struct Account {
pub key_holder: AddressKeyHolder,
2024-11-25 07:26:16 +02:00
pub address: AccountAddress,
2024-10-30 12:32:36 +02:00
pub balance: u64,
2025-05-16 19:59:51 -03:00
pub utxos: HashMap<TreeHashType, UTXO>,
2024-10-30 12:32:36 +02:00
}
2025-04-04 12:11:54 +03:00
///A strucure, which represents all the visible(public) information
///
/// known to each node about account `address`
#[derive(Serialize, Clone)]
2025-04-04 12:11:54 +03:00
pub struct AccountPublicMask {
pub nullifier_public_key: AffinePoint,
pub viewing_public_key: AffinePoint,
pub address: AccountAddress,
pub balance: u64,
}
2024-10-30 12:32:36 +02:00
impl Account {
pub fn new() -> Self {
let key_holder = AddressKeyHolder::new_os_random();
let address = key_holder.address;
let balance = 0;
2025-05-16 19:59:51 -03:00
let utxos = HashMap::new();
2024-10-30 12:32:36 +02:00
Self {
key_holder,
address,
balance,
2025-05-16 19:59:51 -03:00
utxos,
2024-10-30 12:32:36 +02:00
}
}
2024-12-09 04:02:31 +01:00
pub fn new_with_balance(balance: u64) -> Self {
let key_holder = AddressKeyHolder::new_os_random();
let address = key_holder.address;
2025-05-16 19:59:51 -03:00
let utxos = HashMap::new();
2024-12-09 04:02:31 +01:00
Self {
key_holder,
address,
balance,
2025-05-16 19:59:51 -03:00
utxos,
2024-12-09 04:02:31 +01:00
}
}
2024-10-30 12:32:36 +02:00
pub fn produce_ephemeral_key_holder(&self) -> EphemeralKeyHolder {
self.key_holder.produce_ephemeral_key_holder()
}
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,
2024-12-30 09:10:04 +02:00
) -> Result<Vec<u8>, aes_gcm::Error> {
2024-10-30 12:32:36 +02:00
self.key_holder
.decrypt_data(ephemeral_public_key_sender, ciphertext, nonce)
}
pub fn add_new_utxo_outputs(&mut self, utxos: Vec<UTXO>) -> Result<()> {
2025-05-16 19:59:51 -03:00
for utxo in utxos {
if self.utxos.contains_key(&utxo.hash) {
return Err(anyhow::anyhow!("UTXO already exists"));
}
self.utxos.insert(utxo.hash, utxo);
}
return Ok(());
2024-10-30 12:32:36 +02:00
}
pub fn update_public_balance(&mut self, new_balance: u64) {
self.balance = new_balance;
}
2024-12-02 01:20:08 +01:00
pub fn add_asset<Asset: Serialize>(
&mut self,
asset: Asset,
amount: u128,
privacy_flag: bool,
) -> Result<()> {
2024-10-30 12:32:36 +02:00
let payload_with_asset = UTXOPayload {
owner: self.address,
asset: serde_json::to_vec(&asset)?,
2024-12-02 00:55:11 +01:00
amount,
privacy_flag,
2024-10-30 12:32:36 +02:00
};
2025-02-07 15:17:20 -05:00
let asset_utxo = UTXO::create_utxo_from_payload(payload_with_asset)?;
2024-10-30 12:32:36 +02:00
2025-05-16 19:59:51 -03:00
self.utxos.insert(asset_utxo.hash, asset_utxo);
2024-10-30 12:32:36 +02:00
Ok(())
}
pub fn log(&self) {
2025-01-03 08:13:59 +02:00
info!("Keys generated");
info!("Account address is {:?}", hex::encode(self.address));
info!("Account balance is {:?}", self.balance);
}
pub fn make_tag(&self) -> Tag {
self.address[0]
}
2025-04-04 12:11:54 +03:00
///Produce account public mask
pub fn make_account_public_mask(&self) -> AccountPublicMask {
AccountPublicMask {
nullifier_public_key: self.key_holder.nullifer_public_key,
viewing_public_key: self.key_holder.viewing_public_key,
address: self.address,
balance: self.balance,
}
}
2024-10-30 12:32:36 +02:00
}
impl Default for Account {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
2025-02-07 15:17:20 -05:00
fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> anyhow::Result<UTXO> {
let payload = UTXOPayload {
owner: address,
asset: vec![],
amount,
privacy_flag: false,
};
UTXO::create_utxo_from_payload(payload)
}
#[test]
fn test_new_account() {
let account = Account::new();
assert_eq!(account.balance, 0);
assert!(account.key_holder.address != [0u8; 32]); // Check if the address is not empty
}
#[test]
fn test_add_new_utxo_outputs() {
let mut account = Account::new();
2025-02-07 15:17:20 -05:00
let utxo1 = generate_dummy_utxo(account.address, 100).unwrap();
let utxo2 = generate_dummy_utxo(account.address, 200).unwrap();
let result = account.add_new_utxo_outputs(vec![utxo1.clone(), utxo2.clone()]);
assert!(result.is_ok());
2025-05-16 20:25:23 -03:00
assert_eq!(account.utxos.len(), 2);
}
#[test]
fn test_update_public_balance() {
let mut account = Account::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());
2025-05-16 20:25:23 -03:00
assert_eq!(account.utxos.len(), 1);
}
}