feat: limbo block

This commit is contained in:
Ahmet Kaan GÜMÜŞ 2024-06-06 01:23:29 +03:00
parent a244fb2e6d
commit a3b1675bc3
4 changed files with 48 additions and 32 deletions

View file

@ -36,11 +36,15 @@ async fn sync(
Some((ws_stream_receiver, block)) => (ws_stream_receiver, block), Some((ws_stream_receiver, block)) => (ws_stream_receiver, block),
None => return, None => return,
}; };
if block.hash == String::new() {
let block = blockchain.add_block(block); let block = blockchain.add_block(block);
ws_stream_sender = match send_block(ws_stream_sender, block).await { ws_stream_sender = match send_block(ws_stream_sender, block).await {
Some(ws_stream_sender) => ws_stream_sender, Some(ws_stream_sender) => ws_stream_sender,
None => return, None => return,
} }
} else {
blockchain.push_block(block);
}
} }
} }

View file

@ -1,21 +1,24 @@
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::{broadcast::Sender, Mutex};
use crate::{blockchain::BlockChain, BlockReceiver}; use crate::{block::Block, blockchain::BlockChain, BlockReceiver};
pub async fn accept_agreement( pub async fn accept_agreement(
blockchain_thread_safe: Arc<Mutex<BlockChain>>, blockchain_thread_safe: Arc<Mutex<BlockChain>>,
consensus_data_channels: Arc<Mutex<Vec<BlockReceiver>>>, consensus_data_channels: Arc<Mutex<Vec<BlockReceiver>>>,
block_data_channel_sender: Sender<Block>,
limbo_block: Arc<Mutex<Block>>,
) { ) {
let mut received_blocks = vec![]; let mut received_blocks = vec![];
loop { loop {
//notify consensus
for channel in consensus_data_channels.lock().await.iter_mut() { for channel in consensus_data_channels.lock().await.iter_mut() {
match channel.block_receiver.try_recv() { match channel.block_receiver.try_recv() {
Ok(block) => { Ok(block) => {
if block.previous_hash == limbo_block.lock().await.previous_hash {
received_blocks.push(block); received_blocks.push(block);
} }
}
Err(_) => {} Err(_) => {}
} }
} }
@ -23,25 +26,16 @@ pub async fn accept_agreement(
if received_blocks.len() > consensus_data_channels.lock().await.len() / 2 { if received_blocks.len() > consensus_data_channels.lock().await.len() / 2 {
let mut block_hashes: Vec<(String, u128)> = vec![]; let mut block_hashes: Vec<(String, u128)> = vec![];
for block in received_blocks.iter() { for block in received_blocks.iter() {
block_hashes.sort(); block_hashes.sort_by_key(|(hash, _counter)| hash.to_string());
match block_hashes.binary_search_by_key(&block.hash, |(hash, _)| hash.to_string()) { match block_hashes.binary_search_by_key(&block.hash, |(hash, _)| hash.to_string()) {
Ok(index) => block_hashes[index].1 += 1, Ok(index) => block_hashes[index].1 += 1,
Err(_) => block_hashes.push((block.hash.clone(), 1)), Err(_) => block_hashes.push((block.hash.clone(), 1)),
} }
} }
let mut max_pair = (String::new(), 0); block_hashes.sort_by_key(|(_hash, counter)| *counter);
for element in block_hashes.iter() { let max_pair = block_hashes[0].clone();
if element.1 > max_pair.1 {
max_pair.0 = element.0.clone();
max_pair.1 = element.1;
}
}
//it's a bit strange, since we add first one that we find.
//first of what ?
//you know we can binary search ?
//03.46 right now.
for block in received_blocks.iter() { for block in received_blocks.iter() {
if max_pair.0 == block.hash { if max_pair.0 == block.hash {
match blockchain_thread_safe match blockchain_thread_safe
@ -50,8 +44,13 @@ pub async fn accept_agreement(
.push_block(block.clone()) .push_block(block.clone())
{ {
Some(successfully_added_block) => { Some(successfully_added_block) => {
println!("{:#?}", successfully_added_block); match block_data_channel_sender.send(successfully_added_block) {
todo!("Notify Whole Network, Reward First Founder or Else") Ok(_) => {
*limbo_block.lock().await =
blockchain_thread_safe.lock().await.genesis_block.clone()
}
Err(_) => {}
}
} }
None => todo!(), None => todo!(),
} }

View file

@ -19,8 +19,6 @@ async fn main() {
}, },
None => return, None => return,
}; };
//todo!("Limbo Block: Not in chain, but processing by others or none. Sync it also");
//todo!("Consensus should be notified for new block, should forget old blocks");
} }
async fn server() { async fn server() {
@ -30,6 +28,7 @@ async fn server() {
}; };
let blockchain = BlockChain::new(server_config.difficulty.into()); let blockchain = BlockChain::new(server_config.difficulty.into());
let limbo_block = Arc::new(Mutex::new(blockchain.genesis_block.clone()));
let blockchain_thread_safe = Arc::new(Mutex::new(blockchain)); let blockchain_thread_safe = Arc::new(Mutex::new(blockchain));
let block_data_channel_sender = broadcast::channel(1).0; let block_data_channel_sender = broadcast::channel(1).0;
@ -37,7 +36,8 @@ async fn server() {
server_network::start_network( server_network::start_network(
server_config, server_config,
blockchain_thread_safe, blockchain_thread_safe,
block_data_channel_sender.subscribe(), block_data_channel_sender,
limbo_block,
) )
.await; .await;
} }

View file

@ -19,8 +19,10 @@ use crate::{block::Block, blockchain::BlockChain, consensus, BlockReceiver, Serv
pub async fn start_network( pub async fn start_network(
server_config: ServerConfig, server_config: ServerConfig,
blockchain_thread_safe: Arc<Mutex<BlockChain>>, blockchain_thread_safe: Arc<Mutex<BlockChain>>,
block_data_channel_receiver: Receiver<Block>, block_data_channel_sender: Sender<Block>,
limbo_block: Arc<Mutex<Block>>,
) { ) {
let block_data_channel_receiver = block_data_channel_sender.subscribe();
let listener_socket = match TcpListener::bind(format!( let listener_socket = match TcpListener::bind(format!(
"{}:{}", "{}:{}",
server_config.server_address, server_config.port server_config.server_address, server_config.port
@ -34,6 +36,8 @@ pub async fn start_network(
tokio::spawn(consensus::accept_agreement( tokio::spawn(consensus::accept_agreement(
blockchain_thread_safe.clone(), blockchain_thread_safe.clone(),
consensus_data_channels.clone(), consensus_data_channels.clone(),
block_data_channel_sender,
limbo_block.clone(),
)); ));
loop { loop {
if let Ok(connection) = listener_socket.accept().await { if let Ok(connection) = listener_socket.accept().await {
@ -55,12 +59,14 @@ pub async fn start_network(
consensus_data_channels.lock().await.push(block_receiver); consensus_data_channels.lock().await.push(block_receiver);
let consensus_data_channels = consensus_data_channels.clone(); let consensus_data_channels = consensus_data_channels.clone();
let limbo_block = limbo_block.clone();
tokio::spawn(async move { tokio::spawn(async move {
tokio::select! { tokio::select! {
_ = sync_client( _ = sync_client(
ws_stream_sender, ws_stream_sender,
blockchain_thread_safe, blockchain_thread_safe,
block_data_channel_receiver, block_data_channel_receiver,
limbo_block,
) => { ) => {
let mut consensus_data_channels = consensus_data_channels.lock().await; let mut consensus_data_channels = consensus_data_channels.lock().await;
consensus_data_channels.sort(); consensus_data_channels.sort();
@ -128,13 +134,20 @@ async fn sync_client(
ws_stream_sender: SplitSink<WebSocketStream<TcpStream>, Message>, ws_stream_sender: SplitSink<WebSocketStream<TcpStream>, Message>,
blockchain_thread_safe: Arc<Mutex<BlockChain>>, blockchain_thread_safe: Arc<Mutex<BlockChain>>,
mut block_data_channel_receiver: Receiver<Block>, mut block_data_channel_receiver: Receiver<Block>,
limbo_block: Arc<Mutex<Block>>,
) { ) {
let mut ws_stream_sender = match send_blockchain(ws_stream_sender, blockchain_thread_safe).await let mut ws_stream_sender =
{ match send_blockchain(ws_stream_sender, blockchain_thread_safe.clone()).await {
Some(ws_stream_sender) => ws_stream_sender, Some(ws_stream_sender) => ws_stream_sender,
None => return, None => return,
}; };
let limbo_block = limbo_block.lock().await;
if limbo_block.timestamp != blockchain_thread_safe.lock().await.genesis_block.timestamp {
ws_stream_sender = match send_block(ws_stream_sender, limbo_block.clone()).await {
Some(ws_stream_sender) => ws_stream_sender,
None => return,
}
}
loop { loop {
let block = match block_data_channel_receiver.recv().await { let block = match block_data_channel_receiver.recv().await {
Ok(block) => block, Ok(block) => block,