use coin::tx::TxPredicate;
use k256::elliptic_curve::PublicKey;
use tokio_tungstenite::connect_async;
use tokio_tungstenite::tungstenite::client::IntoClientRequest;
use tokio_tungstenite::tungstenite::Message;
use tokio_tungstenite::tungstenite::Bytes;
use url::Url;
use bincode::deserialize;
use futures::{SinkExt, StreamExt};
use k256::{SecretKey, ecdsa::Signature};
use std::collections::HashSet;
use std::env::consts::OS;
use std::time::{SystemTime, UNIX_EPOCH};
use coin::block::*;
use coin::frametype::*;
use coin::tx::*;
use coin::user::*;
use serde::*;
use std::collections::HashMap;
use std::fs;
use std::sync::{Arc, Mutex};
use tokio::net::{TcpListener, TcpStream};
use tokio_util::codec::Framed;
#[tokio::main]
async fn main() {
let reward_address = PublicKey::from_sec1_bytes(&hex::decode("04B0B5D59947A744C8ED5032F8B5EC77F56BFF09A724466397E8261ABE15BB1F1EC90871F5034A7B2BBF43F33C99225EF70C6F463B393973C55E85382F90F2935E").unwrap()).unwrap();
let url = format!("ws://{SERVER_IP}:{PORT}");
let request = url.into_client_request().unwrap();
let (ws_stream, _) = connect_async(request).await.unwrap();
let (mut ws_sender, mut ws_receiver) = ws_stream.split();
let frame = ClientFrame::GetVersion;
let serialized = bincode::serialize(&frame).unwrap();
ws_sender.send(Message::Binary(Bytes::from(serialized))).await.unwrap();
if let Some(Ok(Message::Binary(data))) = ws_receiver.next().await {
if let Ok(ServerFrame::Version(version)) = bincode::deserialize(&data) {
println!("Server version: {}", version);
}
}
let serialized = bincode::serialize(&ClientFrame::GetBlockchain).unwrap();
ws_sender.send(Message::Binary(Bytes::from(serialized))).await.unwrap();
let mut blockchain = Vec::new();
while let Some(Ok(Message::Binary(data))) = ws_receiver.next().await {
if let Ok(ServerFrame::BlockChain(data)) = bincode::deserialize(&data) {
blockchain = data;
break;
}
}
let mut state = State {
blocks: blockchain,
utxo_set: HashMap::new(),
old_utxo_set: HashMap::new(),
};
if state.verify_all_and_update().is_err() {
panic!("ur fucked lmao");
}
loop {
let mut tx_groups = Vec::new();
let frame = ClientFrame::GetLastHash;
let serialized = bincode::serialize(&frame).unwrap();
ws_sender.send(Message::Binary(Bytes::from(serialized))).await.unwrap();
let mut last_hash = BLANK_BLOCK_HASH;
while let Some(Ok(Message::Binary(data))) = ws_receiver.next().await {
if let Ok(ServerFrame::LastBlockHash(hash)) = bincode::deserialize(&data) {
last_hash = hash;
break;
}
}
if last_hash != state.blocks.last().unwrap().get_hash() {
state.blocks.pop();
}
let frame = ClientFrame::GetNewTxpool;
let serialized_bytes = Bytes::from(bincode::serialize(&frame).unwrap());
ws_sender.send(Message::Binary(serialized_bytes.clone())).await.unwrap();
println!("Requesting new txpool");
ws_sender.send(Message::Binary(Bytes::from(serialized_bytes.clone()))).await.unwrap();
while let Some(Ok(Message::Binary(data))) = ws_receiver.next().await {
if let Ok(ServerFrame::NewTxPool(txs)) = bincode::deserialize(&data) {
if !txs.is_empty() {
tx_groups = txs;
break;
} else {
tokio::time::sleep(tokio::time::Duration::from_millis(200)).await;
ws_sender.send(Message::Binary(serialized_bytes.clone())).await.unwrap();
}
}
}
let mut new_block = Block::new();
new_block.prev_hash = state.blocks.last().unwrap().get_hash();
let prev_block = &state.blocks.last().unwrap();
new_block.time_stamp = SystemTime::now()
.duration_since(UNIX_EPOCH).unwrap().as_secs();
let mut utxo_set = state.old_utxo_set.clone();
for group in tx_groups {
new_block.txs.extend(group.clone());
if let Ok(new_utxo_set) = state.verify_block(&utxo_set, &prev_block, &new_block, state.median_time_stamp(None), true) {
utxo_set = new_utxo_set;
} else {
new_block.txs.truncate(new_block.txs.len() - group.len());
}
}
let mut reward_tx = Tx::new();
reward_tx.outputs = vec![TxOutput {
spender: TxPredicate::Pubkey(reward_address),
amount: Block::MINING_REWARD,
recipient: reward_address,
}];
reward_tx.txid = reward_tx.get_txid();
new_block.txs.push(reward_tx);
println!("Mininig...");
new_block.nonce = new_block.mine();
assert!(state.add_block_if_valid(new_block.clone()).is_ok());
println!("Sending {} transactions", new_block.txs.len());
let frame = ClientFrame::Mined(new_block);
let serialized = bincode::serialize(&frame).unwrap();
ws_sender.send(Message::Binary(Bytes::from(serialized))).await.unwrap();
}
}