From 7a154ab83d5ccccb206b89d9a12fc5eaef3bfdea Mon Sep 17 00:00:00 2001 From: YeahNotSewerSide Date: Sat, 27 Apr 2024 21:51:57 +0300 Subject: [PATCH] started blockchain tree --- src/blockchaintree.rs | 149 +++++++++++++++++++++++++++++++++++++++++- src/chain.rs | 10 ++- 2 files changed, 155 insertions(+), 4 deletions(-) diff --git a/src/blockchaintree.rs b/src/blockchaintree.rs index f45340e..d4e76b2 100644 --- a/src/blockchaintree.rs +++ b/src/blockchaintree.rs @@ -1,12 +1,23 @@ -use crate::txpool; +use std::{collections::HashMap, path::Path}; + +use crate::{ + chain, + errors::{BCTreeErrorKind, BlockChainTreeError}, + tools, txpool, +}; +use error_stack::{Report, ResultExt}; use lazy_static::lazy_static; use primitive_types::U256; +use sled::Db; static BLOCKCHAIN_DIRECTORY: &str = "./BlockChainTree/"; static AMMOUNT_SUMMARY: &str = "./BlockChainTree/SUMMARY/"; static OLD_AMMOUNT_SUMMARY: &str = "./BlockChainTree/SUMMARYOLD/"; +static GAS_SUMMARY: &str = "./BlockChainTree/GASSUMMARY/"; +static OLD_GAS_SUMMARY: &str = "./BlockChainTree/GASSUMMARYOLD/"; + static MAIN_CHAIN_DIRECTORY: &str = "./BlockChainTree/MAIN/"; static DERIVATIVE_CHAINS_DIRECTORY: &str = "./BlockChainTree/DERIVATIVES/"; @@ -36,3 +47,139 @@ pub static ROOT_PUBLIC_ADDRESS: [u8; 33] = [ ]; pub static INCEPTION_TIMESTAMP: u64 = 1597924800; + +pub struct BlockChainTree { + main_chain: chain::MainChain, + derivative_chains: HashMap<[u8; 32], chain::DerivativeChain>, + summary_db: Db, + old_summary_db: Db, + gas_db: Db, + old_gas_db: Db, +} + +impl BlockChainTree { + pub async fn new() -> Result> { + let path_summary = Path::new(AMMOUNT_SUMMARY); + let path_summary_old = Path::new(OLD_AMMOUNT_SUMMARY); + let path_gas = Path::new(GAS_SUMMARY); + let path_gas_old = Path::new(OLD_GAS_SUMMARY); + + // open summary DB + let summary_db = sled::open(path_summary) + .change_context(BlockChainTreeError::BlockChainTree(BCTreeErrorKind::Init)) + .attach_printable("failed to open summary db")?; + + // open old summary DB + let old_summary_db = sled::open(path_summary_old) + .change_context(BlockChainTreeError::BlockChainTree(BCTreeErrorKind::Init)) + .attach_printable("failed to open old summary db")?; + + // open gas DB + let gas_db = sled::open(path_gas) + .change_context(BlockChainTreeError::BlockChainTree(BCTreeErrorKind::Init)) + .attach_printable("failed to open gas db")?; + + let old_gas_db = sled::open(path_gas_old) + .change_context(BlockChainTreeError::BlockChainTree(BCTreeErrorKind::Init)) + .attach_printable("failed to open old gas db")?; + + Ok(Self { + main_chain: chain::MainChain::new().await?, + derivative_chains: HashMap::new(), + summary_db, + old_summary_db, + gas_db, + old_gas_db, + }) + } + + pub async fn add_amount( + &self, + owner: &[u8; 32], + amount: U256, + ) -> Result<(), Report> { + self.summary_db + .transaction( + |db| -> Result<(), sled::transaction::ConflictableTransactionError<()>> { + let prev_amount = match db.get(owner)? { + Some(v) => tools::load_u256(&v).unwrap().0, + None => U256::zero(), + }; + let new_amount = prev_amount + amount; + let mut buf: Vec = Vec::with_capacity(tools::u256_size(&new_amount)); + tools::dump_u256(&new_amount, &mut buf).unwrap(); + db.insert(owner, buf)?; + Ok(()) + }, + ) + .unwrap(); + + Ok(()) + } + + pub async fn sub_amount( + &self, + owner: &[u8; 32], + amount: U256, + ) -> Result<(), Report> { + self.summary_db + .transaction( + |db| -> Result<(), sled::transaction::ConflictableTransactionError<()>> { + let prev_amount = match db.get(owner)? { + Some(v) => tools::load_u256(&v).unwrap().0, + None => U256::zero(), + }; + if prev_amount < amount { + return Err(sled::transaction::ConflictableTransactionError::Abort(())); + } + let new_amount = prev_amount + amount; + let mut buf: Vec = Vec::with_capacity(tools::u256_size(&new_amount)); + tools::dump_u256(&new_amount, &mut buf).unwrap(); + db.insert(owner, buf)?; + Ok(()) + }, + ) + .unwrap(); + + Ok(()) + } + + pub async fn send_amount( + &self, + from: &[u8; 32], + to: &[u8; 32], + amount: U256, + ) -> Result<(), Report> { + self.summary_db + .transaction( + |db| -> Result<(), sled::transaction::ConflictableTransactionError<()>> { + let mut from_amount = match db.get(from)? { + Some(v) => tools::load_u256(&v).unwrap().0, + None => U256::zero(), + }; + let mut to_amount = match db.get(to)? { + Some(v) => tools::load_u256(&v).unwrap().0, + None => U256::zero(), + }; + if from_amount < amount { + return Err(sled::transaction::ConflictableTransactionError::Abort(())); + } + + from_amount -= amount; + to_amount += amount; + + let mut buf: Vec = Vec::with_capacity(tools::u256_size(&from_amount)); + tools::dump_u256(&from_amount, &mut buf).unwrap(); + db.insert(from, buf)?; + + let mut buf: Vec = Vec::with_capacity(tools::u256_size(&to_amount)); + tools::dump_u256(&from_amount, &mut buf).unwrap(); + db.insert(to, buf)?; + Ok(()) + }, + ) + .unwrap(); + + Ok(()) + } +} diff --git a/src/chain.rs b/src/chain.rs index d11703c..183cfc7 100644 --- a/src/chain.rs +++ b/src/chain.rs @@ -620,9 +620,13 @@ impl DerivativeChain { let raw_transaction = self.get_transaction_raw(transaction_hash)?; if let Some(tr) = raw_transaction { - return Ok(Some(transaction::Transaction::parse(&tr).change_context( - BlockChainTreeError::Chain(ChainErrorKind::FindByHashE), - )?)); + if !tr.get(0).unwrap_or(&10).eq(&(Headers::Transaction as u8)) { + return Err(BlockChainTreeError::Chain(ChainErrorKind::FindByHashE).into()); + } + return Ok(Some( + transaction::Transaction::parse(&tr[1..]) + .change_context(BlockChainTreeError::Chain(ChainErrorKind::FindByHashE))?, + )); } Ok(None)