use std::env::consts::OS;
use std::sync::{Arc, Mutex};
use tokio_util::codec::{Framed};
use futures::{StreamExt, SinkExt};
use coin::block::*;
use coin::tx::*;
use coin::frametype::*;
use ClientFrame::*;
use tokio_tungstenite::*;
use tungstenite::*;
use bytes::Bytes;
use std::fs;
use tokio::{join, net::TcpListener};
#[tokio::main]
async fn main() {
println!("Starting server");
let serialized = fs::read("state.bin").expect("Error reading file");
let mut state: State = bincode::deserialize(&serialized).expect("Error deserializing");
state.utxo_set = state.verify_all_blocks().unwrap();
state.old_utxo_set = state.utxo_set.clone();
let state = Arc::new(Mutex::new(state));
let new_txs = Arc::new(Mutex::new(Vec::<Vec::<Tx>>::new()));
let listener = TcpListener::bind(format!("0.0.0.0:{PORT}")).await.unwrap();
loop {
let (stream, addr) = listener.accept().await.unwrap();
println!("New connection from: {addr}");
let new_txs = new_txs.clone();
let state = state.clone();
let new_task = tokio::spawn(async move {
let mut ws_stream = tokio_tungstenite::accept_async(stream).await.unwrap();
while let Some(Ok(protocol::Message::Binary(msg))) = ws_stream.next().await {
let mut frame = bincode::deserialize(&msg).unwrap();
match frame {
TxFrame(txs) => {
println!("New txs received");
let mut new_txs = { new_txs.lock().unwrap() };
new_txs.push(txs);
},
Mined(block) => {
let mut state = state.lock().unwrap();
let num_txs = block.txs.len();
if state.add_block_if_valid(block).is_ok() {
println!("New block accepted");
let mut new_txs = new_txs.lock().unwrap();
new_txs.clear();
assert!(state.verify_all_blocks().is_ok());
} else {
println!("New block rejected");
}
},
GetNewTxpool => {
let new_txs = { new_txs.lock().unwrap().clone() };
let serialized = bincode::serialize(&ServerFrame::NewTxPool(new_txs)).unwrap();
ws_stream.send(Message::Binary(Bytes::from(serialized))).await.unwrap();
},
GetVersion => {
let serialized = bincode::serialize(&ServerFrame::Version(env!("CARGO_PKG_VERSION").to_string())).unwrap();
ws_stream.send(Message::Binary(Bytes::from(serialized))).await;
},
GetLastHash => {
println!("Last hash requested");
let last_hash = {
let blocks = state.lock().unwrap().blocks.clone();
blocks.last().unwrap().get_hash()
};
let serialized = bincode::serialize(&ServerFrame::LastBlockHash(last_hash)).unwrap();
ws_stream.send(Message::Binary(Bytes::from(serialized))).await;
},
GetBlockchain => {
println!("Blockchain requested");
let block_chain = { state.lock().unwrap().blocks.clone() };
let serialized = bincode::serialize(&ServerFrame::BlockChain(block_chain)).unwrap();
ws_stream.send(Message::Binary(Bytes::from(serialized))).await;
}
}
}
});
}
}