From 5a23fa22ea3fc8d7dc58d6a1b6a5ba63240a03d7 Mon Sep 17 00:00:00 2001 From: YeahNotSewerSide Date: Sun, 28 Apr 2024 19:05:13 +0300 Subject: [PATCH] fix pow function --- gen_test_data.py | 46 +++++++++++++++++++++++++++++++++++++++++++ src/blockchaintree.rs | 29 +++++++++++++++++++++++---- src/chain.rs | 11 ++++------- src/tools.rs | 37 ++++++++++++++++------------------ tests/chain_test.rs | 4 +++- tests/tools_test.rs | 4 ++++ 6 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 gen_test_data.py create mode 100644 tests/tools_test.rs diff --git a/gen_test_data.py b/gen_test_data.py new file mode 100644 index 0000000..12f555e --- /dev/null +++ b/gen_test_data.py @@ -0,0 +1,46 @@ +import hashlib +import os + + +def leading_zeros(num): + if num == 0: + return 8 + + leading_zeros = 0 + while num & 0b10000000 == 0: + leading_zeros += 1 + num = num << 1 + num = num & 0b11111111 + return leading_zeros + + +def total_leading_zeros(hash): + to_return = 0 + for byte in hash: + l_zeros = leading_zeros(byte) + to_return += l_zeros + if l_zeros < 8: + break + + return to_return + + +def gen(hash, difficulty): + difficulty = total_leading_zeros(difficulty) + for i in range(1000): + pow = b'' + os.urandom(10) + hasher = hashlib.sha256() + hasher.update(hash) + hasher.update(pow) + + generated_hash = hasher.digest() + ghash_leadin_zeros = total_leading_zeros(generated_hash) + + if ghash_leadin_zeros >= difficulty: + print(pow, True) + else: + print(pow, False) + + +gen(hashlib.sha256(b'text').digest(), + b'\x0F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF') diff --git a/src/blockchaintree.rs b/src/blockchaintree.rs index 67cf2d8..0235978 100644 --- a/src/blockchaintree.rs +++ b/src/blockchaintree.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, path::Path}; use crate::{ - block::TransactionBlock, + block::{BlockArc, TransactionBlock}, chain, errors::{BCTreeErrorKind, BlockChainTreeError}, tools, @@ -303,16 +303,37 @@ impl BlockChainTree { Ok(()) } - pub async fn new_block( + pub async fn add_new_block( &self, - block: TransactionBlock, + block: BlockArc, transactions: &[Transaction], ) -> Result<(), Report> { - self.main_chain.add_block(&block).await?; + self.main_chain.add_block(block).await?; self.main_chain.add_transactions(transactions).await } + pub async fn emmit_new_main_block( + &self, + pow: &[u8], + founder: [u8; 33], + ) -> Result<[u8; 33], Report> { + let last_block = self.main_chain.get_last_block().await?.unwrap(); // practically cannot fail + + if !tools::check_pow( + &last_block + .hash() + .change_context(BlockChainTreeError::BlockChainTree(BCTreeErrorKind::DumpDb)) + .attach_printable("failed to hash block")?, + &last_block.get_info().difficulty, + pow, + ) { + return Err(BlockChainTreeError::BlockChainTree(BCTreeErrorKind::WrongPow).into()); + }; + + todo!() + } + pub async fn flush(&self) -> Result<(), Report> { self.main_chain.flush().await?; self.summary_db diff --git a/src/chain.rs b/src/chain.rs index 5f5b036..0417324 100644 --- a/src/chain.rs +++ b/src/chain.rs @@ -6,7 +6,7 @@ use primitive_types::U256; use sled::Db; use tokio::{fs::OpenOptions, io::AsyncWriteExt, sync::RwLock}; -use crate::block::DerivativeBlock; +use crate::block::{BlockArc, DerivativeBlock}; use crate::dump_headers::Headers; use crate::{ block::{self, BasicInfo, Block, SummarizeBlock}, @@ -126,10 +126,10 @@ impl MainChain { let merkle_tree = MerkleTree::build_tree(&[tools::hash(&initial_amount)]); chain - .add_block(&SummarizeBlock { + .add_block(Arc::new(SummarizeBlock { default_info: info, merkle_tree_root: *merkle_tree.get_root(), - }) + })) .await .change_context(BlockChainTreeError::Chain(ChainErrorKind::Init)) .attach_printable("Failed to insert inception block")?; @@ -266,10 +266,7 @@ impl MainChain { /// Adds block and sets height reference for it /// /// Checks for blocks validity, adds it directly to the end of the chain - pub async fn add_block( - &self, - block: &(impl Block + Sync), - ) -> Result<(), Report> { + pub async fn add_block(&self, block: BlockArc) -> Result<(), Report> { let dump = block .dump() .change_context(BlockChainTreeError::Chain(ChainErrorKind::AddingBlock))?; diff --git a/src/tools.rs b/src/tools.rs index 40ac4ee..787a43e 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -183,30 +183,29 @@ pub fn decompress_from_file(filename: String) -> Result, ToolsError> { Ok(decoded_data) } +#[inline] +pub fn count_leading_zeros(data: &[u8]) -> u32 { + let mut to_return = 0u32; + for byte in data { + let leading_zeros = byte.leading_zeros(); + to_return += leading_zeros; + if leading_zeros < 8 { + break; + } + } + to_return +} + pub fn check_pow(hash: &[u8; 32], difficulty: &[u8; 32], pow: &[u8]) -> bool { let mut hasher = Sha256::new(); hasher.update(hash); hasher.update(pow); - let result: [u8; 32] = unsafe { hasher.finalize().as_slice().try_into().unwrap_unchecked() }; - let result: [u64; 4] = unsafe { transmute(result) }; - - let difficulty: &[u64; 4] = unsafe { transmute(difficulty) }; + let result: [u8; 32] = hasher.finalize().into(); - //println!("difficulty: {:?}", difficulty); - - for (r, d) in result.iter().zip(difficulty) { - match r.cmp(d) { - std::cmp::Ordering::Less => { - return true; - } - std::cmp::Ordering::Equal => {} - std::cmp::Ordering::Greater => { - return false; - } - } + if count_leading_zeros(difficulty) <= count_leading_zeros(&result) { + return true; } - - true + false } pub fn recalculate_difficulty(prev_timestamp: u64, timestamp: u64, prev_difficulty: &mut Hash) { @@ -242,8 +241,6 @@ mod tests { use primitive_types::U256; - - use super::{dump_u256, load_u256, recalculate_difficulty}; #[test] diff --git a/tests/chain_test.rs b/tests/chain_test.rs index 2ffbbb9..b9d5431 100644 --- a/tests/chain_test.rs +++ b/tests/chain_test.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use blockchaintree::{ block, chain, tools, transaction::{self, Transactionable}, @@ -32,7 +34,7 @@ async fn init_flush_get_block_by_height_chain_test() { vec![[0; 32], [1; 32]], ); - main_chain.add_block(&main_block).await.unwrap(); + main_chain.add_block(Arc::new(main_block)).await.unwrap(); let height = main_chain.get_height().await; let block = main_chain.find_by_height(&(height - 1)).await.unwrap(); diff --git a/tests/tools_test.rs b/tests/tools_test.rs new file mode 100644 index 0000000..70cf495 --- /dev/null +++ b/tests/tools_test.rs @@ -0,0 +1,4 @@ +use blockchaintree::tools; + +#[test] +fn pow_test() {}