mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-07 15:53:14 +00:00
Merge pull request #76 from vacp2p/schouhy/update-utxo-crate-2-remove-nullifier-attribute
2/3 Update utxo crate: Remove nullifier attribute from UTXO
This commit is contained in:
commit
895c6490bb
@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use common::{merkle_tree_public::TreeHashType, nullifier::UTXONullifier, transaction::Tag};
|
use common::{merkle_tree_public::TreeHashType, transaction::Tag};
|
||||||
use k256::AffinePoint;
|
use k256::AffinePoint;
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -84,19 +84,6 @@ impl Account {
|
|||||||
.decrypt_data(ephemeral_public_key_sender, ciphertext, nonce)
|
.decrypt_data(ephemeral_public_key_sender, ciphertext, nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_spent_utxo(
|
|
||||||
&mut self,
|
|
||||||
utxo_nullifier_map: HashMap<TreeHashType, UTXONullifier>,
|
|
||||||
) -> Result<()> {
|
|
||||||
for (hash, nullifier) in utxo_nullifier_map {
|
|
||||||
if let Some(utxo_entry) = self.utxos.get_mut(&hash) {
|
|
||||||
utxo_entry.consume_utxo(nullifier)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_new_utxo_outputs(&mut self, utxos: Vec<UTXO>) -> Result<()> {
|
pub fn add_new_utxo_outputs(&mut self, utxos: Vec<UTXO>) -> Result<()> {
|
||||||
for utxo in utxos {
|
for utxo in utxos {
|
||||||
if self.utxos.contains_key(&utxo.hash) {
|
if self.utxos.contains_key(&utxo.hash) {
|
||||||
@ -162,10 +149,6 @@ impl Default for Account {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn generate_dummy_utxo_nullifier() -> UTXONullifier {
|
|
||||||
UTXONullifier::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> anyhow::Result<UTXO> {
|
fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> anyhow::Result<UTXO> {
|
||||||
let payload = UTXOPayload {
|
let payload = UTXOPayload {
|
||||||
owner: address,
|
owner: address,
|
||||||
@ -184,20 +167,6 @@ mod tests {
|
|||||||
assert!(account.key_holder.address != [0u8; 32]); // Check if the address is not empty
|
assert!(account.key_holder.address != [0u8; 32]); // Check if the address is not empty
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mark_spent_utxo() {
|
|
||||||
let mut account = Account::new();
|
|
||||||
let utxo = generate_dummy_utxo(account.address, 100).unwrap();
|
|
||||||
account.add_new_utxo_outputs(vec![utxo]).unwrap();
|
|
||||||
|
|
||||||
let mut utxo_nullifier_map = HashMap::new();
|
|
||||||
utxo_nullifier_map.insert(account.address, generate_dummy_utxo_nullifier());
|
|
||||||
|
|
||||||
let result = account.mark_spent_utxo(utxo_nullifier_map);
|
|
||||||
|
|
||||||
assert!(result.is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_new_utxo_outputs() {
|
fn test_add_new_utxo_outputs() {
|
||||||
let mut account = Account::new();
|
let mut account = Account::new();
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
pub mod cryptography;
|
pub mod cryptography;
|
||||||
pub mod proofs_circuits;
|
pub mod proofs_circuits;
|
||||||
pub mod transaction_payloads_tools;
|
pub mod transaction_payloads_tools;
|
||||||
pub mod utxo_manipulator;
|
|
||||||
|
|||||||
@ -1,110 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use common::nullifier::UTXONullifier;
|
|
||||||
use utxo::utxo_core::{UTXOPayload, UTXO};
|
|
||||||
|
|
||||||
pub fn utxo_change_owner(
|
|
||||||
utxo: &mut UTXO,
|
|
||||||
nullifier: UTXONullifier,
|
|
||||||
new_owner: [u8; 32],
|
|
||||||
) -> Result<UTXO> {
|
|
||||||
let new_payload = UTXOPayload {
|
|
||||||
owner: new_owner,
|
|
||||||
asset: utxo.asset.clone(),
|
|
||||||
amount: utxo.amount,
|
|
||||||
privacy_flag: utxo.privacy_flag,
|
|
||||||
};
|
|
||||||
|
|
||||||
utxo.consume_utxo(nullifier)?;
|
|
||||||
|
|
||||||
Ok(UTXO::create_utxo_from_payload(new_payload)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn utxo_substact_part_another_owner(
|
|
||||||
utxo: &mut UTXO,
|
|
||||||
nullifier: UTXONullifier,
|
|
||||||
amount: u128,
|
|
||||||
new_owner: [u8; 32],
|
|
||||||
) -> Result<(UTXO, UTXO)> {
|
|
||||||
if amount > utxo.amount {
|
|
||||||
anyhow::bail!("Amount too big");
|
|
||||||
}
|
|
||||||
|
|
||||||
let diff = utxo.amount - amount;
|
|
||||||
|
|
||||||
let new_payload1 = UTXOPayload {
|
|
||||||
owner: utxo.owner,
|
|
||||||
asset: utxo.asset.clone(),
|
|
||||||
amount: diff,
|
|
||||||
privacy_flag: utxo.privacy_flag,
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_payload2 = UTXOPayload {
|
|
||||||
owner: new_owner,
|
|
||||||
asset: utxo.asset.clone(),
|
|
||||||
amount,
|
|
||||||
privacy_flag: utxo.privacy_flag,
|
|
||||||
};
|
|
||||||
|
|
||||||
utxo.consume_utxo(nullifier)?;
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
UTXO::create_utxo_from_payload(new_payload1)?,
|
|
||||||
UTXO::create_utxo_from_payload(new_payload2)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn utxo_substract_part(
|
|
||||||
utxo: &mut UTXO,
|
|
||||||
nullifier: UTXONullifier,
|
|
||||||
amount: u128,
|
|
||||||
) -> Result<(UTXO, UTXO)> {
|
|
||||||
let new_owner = utxo.owner;
|
|
||||||
|
|
||||||
utxo_substact_part_another_owner(utxo, nullifier, amount, new_owner)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn utxo_split_n_users(
|
|
||||||
utxo: &mut UTXO,
|
|
||||||
nullifier: UTXONullifier,
|
|
||||||
users_amounts: Vec<([u8; 32], u128)>,
|
|
||||||
) -> Result<Vec<UTXO>> {
|
|
||||||
let cumulative_diff = users_amounts
|
|
||||||
.iter()
|
|
||||||
.fold(0, |acc, (_, amount)| acc + *amount);
|
|
||||||
|
|
||||||
if cumulative_diff > utxo.amount {
|
|
||||||
anyhow::bail!("Amount too big");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut utxo_res = vec![];
|
|
||||||
|
|
||||||
for (new_owner, amount) in users_amounts {
|
|
||||||
let new_payload = UTXOPayload {
|
|
||||||
owner: new_owner,
|
|
||||||
asset: utxo.asset.clone(),
|
|
||||||
amount,
|
|
||||||
privacy_flag: utxo.privacy_flag,
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_utxo = UTXO::create_utxo_from_payload(new_payload)?;
|
|
||||||
|
|
||||||
utxo_res.push(new_utxo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if cumulative_diff != utxo.amount {
|
|
||||||
let new_payload = UTXOPayload {
|
|
||||||
owner: utxo.owner,
|
|
||||||
asset: utxo.asset.clone(),
|
|
||||||
amount: utxo.amount - cumulative_diff,
|
|
||||||
privacy_flag: utxo.privacy_flag,
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_utxo = UTXO::create_utxo_from_payload(new_payload)?;
|
|
||||||
|
|
||||||
utxo_res.push(new_utxo);
|
|
||||||
}
|
|
||||||
|
|
||||||
utxo.consume_utxo(nullifier)?;
|
|
||||||
|
|
||||||
Ok(utxo_res)
|
|
||||||
}
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use common::{merkle_tree_public::TreeHashType, nullifier::UTXONullifier, AccountId};
|
use common::{merkle_tree_public::TreeHashType, AccountId};
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{digest::FixedOutput, Digest};
|
use sha2::{digest::FixedOutput, Digest};
|
||||||
@ -12,7 +12,6 @@ pub type Asset = Vec<u8>;
|
|||||||
pub struct UTXO {
|
pub struct UTXO {
|
||||||
pub hash: TreeHashType,
|
pub hash: TreeHashType,
|
||||||
pub owner: AccountId,
|
pub owner: AccountId,
|
||||||
pub nullifier: Option<UTXONullifier>,
|
|
||||||
pub asset: Asset,
|
pub asset: Asset,
|
||||||
// TODO: change to u256
|
// TODO: change to u256
|
||||||
pub amount: u128,
|
pub amount: u128,
|
||||||
@ -41,23 +40,12 @@ impl UTXO {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
hash,
|
hash,
|
||||||
owner: payload_with_asset.owner,
|
owner: payload_with_asset.owner,
|
||||||
nullifier: None,
|
|
||||||
asset: payload_with_asset.asset,
|
asset: payload_with_asset.asset,
|
||||||
amount: payload_with_asset.amount,
|
amount: payload_with_asset.amount,
|
||||||
privacy_flag: payload_with_asset.privacy_flag,
|
privacy_flag: payload_with_asset.privacy_flag,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn consume_utxo(&mut self, nullifier: UTXONullifier) -> Result<()> {
|
|
||||||
if self.nullifier.is_some() {
|
|
||||||
anyhow::bail!("UTXO already consumed");
|
|
||||||
} else {
|
|
||||||
self.nullifier = Some(nullifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn interpret_asset<'de, ToInterpret: Deserialize<'de>>(&'de self) -> Result<ToInterpret> {
|
pub fn interpret_asset<'de, ToInterpret: Deserialize<'de>>(&'de self) -> Result<ToInterpret> {
|
||||||
Ok(serde_json::from_slice(&self.asset)?)
|
Ok(serde_json::from_slice(&self.asset)?)
|
||||||
}
|
}
|
||||||
@ -74,10 +62,6 @@ impl UTXO {
|
|||||||
pub fn log(&self) {
|
pub fn log(&self) {
|
||||||
info!("UTXO hash is {:?}", hex::encode(self.hash));
|
info!("UTXO hash is {:?}", hex::encode(self.hash));
|
||||||
info!("UTXO owner is {:?}", hex::encode(self.owner));
|
info!("UTXO owner is {:?}", hex::encode(self.owner));
|
||||||
info!(
|
|
||||||
"UTXO nullifier is {:?}",
|
|
||||||
self.nullifier.clone().map(|val| hex::encode(val.utxo_hash))
|
|
||||||
);
|
|
||||||
info!("UTXO asset is {:?}", hex::encode(self.asset.clone()));
|
info!("UTXO asset is {:?}", hex::encode(self.asset.clone()));
|
||||||
info!("UTXO amount is {:?}", self.amount);
|
info!("UTXO amount is {:?}", self.amount);
|
||||||
info!("UTXO privacy_flag is {:?}", self.privacy_flag);
|
info!("UTXO privacy_flag is {:?}", self.privacy_flag);
|
||||||
@ -98,14 +82,6 @@ mod tests {
|
|||||||
AccountId::default()
|
AccountId::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_nullifier() -> UTXONullifier {
|
|
||||||
UTXONullifier::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sample_tree_hash() -> TreeHashType {
|
|
||||||
TreeHashType::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sample_payload() -> UTXOPayload {
|
fn sample_payload() -> UTXOPayload {
|
||||||
UTXOPayload {
|
UTXOPayload {
|
||||||
owner: sample_account(),
|
owner: sample_account(),
|
||||||
@ -127,23 +103,6 @@ mod tests {
|
|||||||
// Ensure hash is created and the UTXO fields are correctly assigned
|
// Ensure hash is created and the UTXO fields are correctly assigned
|
||||||
assert_eq!(utxo.owner, payload.owner);
|
assert_eq!(utxo.owner, payload.owner);
|
||||||
assert_eq!(utxo.asset, payload.asset);
|
assert_eq!(utxo.asset, payload.asset);
|
||||||
assert!(utxo.nullifier.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_consume_utxo() {
|
|
||||||
let payload = sample_payload();
|
|
||||||
let mut utxo = UTXO::create_utxo_from_payload(payload).unwrap();
|
|
||||||
|
|
||||||
let nullifier = sample_nullifier();
|
|
||||||
|
|
||||||
// First consumption should succeed
|
|
||||||
assert!(utxo.consume_utxo(nullifier.clone()).is_ok());
|
|
||||||
assert_eq!(utxo.nullifier, Some(nullifier));
|
|
||||||
|
|
||||||
// Second consumption should fail
|
|
||||||
let result = utxo.consume_utxo(sample_nullifier());
|
|
||||||
assert!(result.is_err());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user