Merge pull request #14 from vacp2p/Pravdyvy/utxo-core

UTXO core added
This commit is contained in:
tyshko-rostyslav 2024-10-22 19:11:57 -04:00 committed by GitHub
commit 76ba2640c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 144 additions and 2 deletions

3
Cargo.lock generated
View File

@ -2030,8 +2030,11 @@ dependencies = [
"anyhow",
"env_logger",
"log",
"monotree",
"serde",
"serde_json",
"sha2 0.10.8",
"storage",
]
[[package]]

View File

@ -3,6 +3,7 @@ use std::{path::Path, sync::Arc};
use block::Block;
use error::DbError;
use log::warn;
use merkle_tree_public::TreeHashType;
use rocksdb::{
BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options,
};
@ -15,6 +16,9 @@ pub mod nullifier_sparse_merkle_tree;
pub mod transaction;
pub mod utxo_commitment;
///Account id on blockchain
pub type AccountId = TreeHashType;
///Maximal size of stored blocks in base
///
///Used to control db size

View File

@ -8,4 +8,9 @@ anyhow.workspace = true
serde_json.workspace = true
env_logger.workspace = true
log.workspace = true
serde.workspace = true
serde.workspace = true
monotree.workspace = true
sha2.workspace = true
[dependencies.storage]
path = "../storage"

View File

@ -1 +1,2 @@
//ToDo: Add utxo module
pub mod utxo_core;
pub mod utxo_tree;

55
utxo/src/utxo_core.rs Normal file
View File

@ -0,0 +1,55 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
use sha2::{digest::FixedOutput, Digest};
use storage::{merkle_tree_public::TreeHashType, nullifier::UTXONullifier, AccountId};
///Raw asset data
pub type Asset = Vec<u8>;
#[derive(Debug)]
///Container for raw utxo payload
pub struct UTXO {
pub hash: TreeHashType,
pub owner: AccountId,
pub nullifier: Option<UTXONullifier>,
pub asset: Asset,
}
#[derive(Debug, Clone, Serialize)]
pub struct UTXOPayload {
pub owner: AccountId,
pub asset: Asset,
}
impl UTXO {
pub fn create_utxo_from_payload(payload_with_asset: UTXOPayload) -> Self {
let raw_payload = serde_json::to_vec(&payload_with_asset).unwrap();
let mut hasher = sha2::Sha256::new();
hasher.update(&raw_payload);
let hash = <TreeHashType>::from(hasher.finalize_fixed());
Self {
hash,
owner: payload_with_asset.owner,
nullifier: None,
asset: payload_with_asset.asset,
}
}
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> {
Ok(serde_json::from_slice(&self.asset)?)
}
}

74
utxo/src/utxo_tree.rs Normal file
View File

@ -0,0 +1,74 @@
use std::collections::HashMap;
use monotree::database::MemoryDB;
use monotree::hasher::Blake3;
use monotree::{Hasher, Monotree, Proof};
use storage::merkle_tree_public::TreeHashType;
use crate::utxo_core::UTXO;
pub struct UTXOSparseMerkleTree {
pub curr_root: Option<TreeHashType>,
pub tree: Monotree<MemoryDB, Blake3>,
pub hasher: Blake3,
pub store: HashMap<TreeHashType, UTXO>,
}
impl UTXOSparseMerkleTree {
pub fn new() -> Self {
UTXOSparseMerkleTree {
curr_root: None,
tree: Monotree::default(),
hasher: Blake3::new(),
store: HashMap::new(),
}
}
pub fn insert_item(&mut self, utxo: UTXO) -> Result<(), monotree::Errors> {
let root = self.curr_root.as_ref();
let new_root = self.tree.insert(root, &utxo.hash, &utxo.hash)?;
self.store.insert(utxo.hash, utxo);
self.curr_root = new_root;
Ok(())
}
pub fn insert_items(&mut self, utxos: Vec<UTXO>) -> Result<(), monotree::Errors> {
let root = self.curr_root.as_ref();
let hashes: Vec<TreeHashType> = utxos.iter().map(|item| item.hash).collect();
let new_root = self.tree.inserts(root, &hashes, &hashes)?;
for utxo in utxos {
self.store.insert(utxo.hash, utxo);
}
self.curr_root = new_root;
Ok(())
}
pub fn get_item(&mut self, hash: TreeHashType) -> Result<Option<&UTXO>, monotree::Errors> {
let hash = self.tree.get(self.curr_root.as_ref(), &hash)?;
Ok(hash.and_then(|hash| self.store.get(&hash)))
}
pub fn get_membership_proof(
&mut self,
nullifier_hash: TreeHashType,
) -> Result<Option<Proof>, monotree::Errors> {
self.tree
.get_merkle_proof(self.curr_root.as_ref(), &nullifier_hash)
}
}
impl Default for UTXOSparseMerkleTree {
fn default() -> Self {
Self::new()
}
}