├── client ├── target │ └── debug │ │ └── .cargo-lock ├── Cargo.toml ├── src │ └── lib.rs └── Cargo.lock ├── network_protocol ├── target │ └── debug │ │ └── .cargo-lock ├── Cargo.lock ├── examples │ └── main.rs ├── Cargo.toml └── src │ ├── client2node.rs │ ├── lib.rs │ └── p2p.rs ├── node ├── Cargo.lock ├── Cargo.toml └── src │ ├── receiver.rs │ ├── sender.rs │ ├── main.rs │ ├── storage.rs │ ├── node.rs │ ├── connector.rs │ └── miner.rs ├── state ├── Cargo.lock ├── Cargo.toml └── src │ └── lib.rs ├── Cargo.toml ├── errors ├── Cargo.toml └── src │ └── lib.rs ├── utils ├── Cargo.toml └── src │ └── lib.rs ├── crypto ├── Cargo.toml └── src │ └── lib.rs └── README.md /client/target/debug/.cargo-lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /network_protocol/target/debug/.cargo-lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /node/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "peer" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /state/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "state" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /network_protocol/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "network" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "client", 5 | "crypto", 6 | "network_protocol", 7 | "node", 8 | "state", 9 | "errors", 10 | "utils", 11 | "staff" 12 | ] 13 | -------------------------------------------------------------------------------- /errors/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "errors" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | thiserror = "1.0" -------------------------------------------------------------------------------- /utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "utils" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | chrono = "0.4.26" 10 | bincode = "1.3.3" 11 | -------------------------------------------------------------------------------- /crypto/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crypto" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | blake2 = "0.10.6" 10 | ursa = "0.3.7" 11 | sha2 = "0.10.6" -------------------------------------------------------------------------------- /network_protocol/examples/main.rs: -------------------------------------------------------------------------------- 1 | use tokio::net::{TcpListener, TcpStream}; 2 | 3 | #[tokio::main] 4 | async fn main() { 5 | } 6 | 7 | async fn receiver(listener: TcpListener) -> TcpStream { 8 | let listener = listener.accept().await.unwrap().0; 9 | println!("listener: {}", &listener.peer_addr().unwrap()); 10 | listener 11 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Blockchain implementation with PoW and network interaction with tokio 3 | 4 | 1. Build project `cargo build` 5 | 2. Start peer `run --package peer --bin peer` 6 | 3. Send transactions via client: `node::tests::send_transactions_to_network()` 7 | 4. Check transactions onchain `node::node::tests::receive_blockchain_request_and_response_ok()` 8 | 9 | -------------------------------------------------------------------------------- /state/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "state" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | chrono = "0.4.26" 10 | derive_more = "0.99.17" 11 | tightness = "1.0.1" 12 | 13 | serde = { version = "1.0.160", features = ["derive"] } 14 | bincode = "1.3.3" 15 | 16 | crypto = { path = "../crypto"} 17 | utils = { path = "../utils"} 18 | errors = { path = "../errors"} -------------------------------------------------------------------------------- /client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "client" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | tokio = { version = "1.28.0", features = ["net", "macros", "rt-multi-thread", "io-util", "test-util"] } 10 | tokio-io = { version = "0.1.13" } 11 | futures = "0.3.28" 12 | 13 | tracing = "0.1.37" 14 | 15 | state = { path = "../state" } 16 | network = { path = "../network_protocol" } 17 | crypto = { path = "../crypto"} 18 | errors = { path = "../errors"} 19 | utils = { path = "../utils"} -------------------------------------------------------------------------------- /network_protocol/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "network" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | tokio = { version = "1.28.0", features = ["net", "macros", "rt-multi-thread", "io-util", "test-util"] } # 10 | tokio-io = { version = "0.1.13" } 11 | futures = "0.3.28" 12 | num = "0.4.0" 13 | 14 | bytes = "1.4.0" 15 | bincode = "1.3.3" 16 | byteorder = "1.4.3" 17 | 18 | serde = { version = "1.0.160", features = ["derive"] } 19 | derive_more = "0.99.17" 20 | 21 | tracing = "0.1.37" 22 | 23 | errors = { path = "../errors"} 24 | state = { path = "../state" } 25 | utils = { path = "../utils"} -------------------------------------------------------------------------------- /node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "peer" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | tokio = { version = "1.28.0", features = ["net", "macros", "rt-multi-thread"] } # 8 | tokio-io = "0.1" 9 | futures = "0.3.28" 10 | 11 | tracing = "0.1.37" 12 | tracing-subscriber = "0.3.17" 13 | 14 | rand = "0.8.5" 15 | 16 | blake2 = "0.10.6" 17 | ursa = "0.3.7" 18 | sha2 = "0.10.6" 19 | 20 | chrono = "0.4.26" 21 | queues = "1.0.2" 22 | async-trait = "0.1.7" 23 | 24 | bytes = "1.4.0" 25 | bincode = "1.3.3" 26 | 27 | serde = { version = "1.0.160", features = ["derive"] } 28 | 29 | state = { path = "../state" } 30 | network = { path = "../network_protocol" } 31 | errors = { path = "../errors"} 32 | crypto = { path = "../crypto"} 33 | utils = { path = "../utils"} 34 | client = { path = "../client"} 35 | -------------------------------------------------------------------------------- /utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::net::SocketAddr; 3 | use std::str::FromStr; 4 | use chrono::prelude::*; 5 | 6 | pub const LOCAL_HOST: &str = "127.0.0.1:"; 7 | 8 | pub fn print_bytes(bytes: &[u8]) -> String { 9 | bytes.iter().map(|n| n.to_string()).fold(String::new(), |acc, s| acc + " " + s.as_str()) 10 | } 11 | 12 | pub fn string_to_hash(string: &str) -> Vec { 13 | string.as_bytes().to_vec() 14 | } 15 | 16 | pub fn socket_addr(port: &str) -> SocketAddr { 17 | SocketAddr::from_str((String::from(LOCAL_HOST) + port).as_str()).unwrap() 18 | } 19 | 20 | pub fn convert_timestamp_to_day_time(timestamp: i64) -> DateTime { 21 | let naive = NaiveDateTime::from_timestamp(timestamp, 0); 22 | let datetime: DateTime = DateTime::from_utc(naive, Utc); 23 | //let date = datetime.format("%Y-%m-%d %H:%M:%S"); 24 | datetime 25 | } 26 | -------------------------------------------------------------------------------- /errors/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use thiserror::Error; 3 | 4 | #[derive(Clone, Debug, Eq, Error, PartialEq)] 5 | pub enum LedgerError { 6 | #[error("Wrong command received")] 7 | WrongCommandError, 8 | #[error("Error while network_protocol interaction")] 9 | NetworkError, 10 | #[error("Serializing error")] 11 | SerializeError, 12 | #[error("Deserializing error")] 13 | DeserializationError, 14 | #[error("Error while processing block")] 15 | BlockError, 16 | #[error("Genesis block already exists")] 17 | GenesisBlockError, 18 | #[error("Synchronization error")] 19 | SyncError, 20 | #[error("Persistence error")] 21 | PersistenceError, 22 | #[error("API error")] 23 | ApiError, 24 | #[error("Insufficient funds")] 25 | InsufficientFunds, 26 | #[error("No such asset")] // TODO ugly name 27 | NoSuchAsset, 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /crypto/src/lib.rs: -------------------------------------------------------------------------------- 1 | use blake2::{ Blake2s256, Digest}; 2 | use sha2::Sha256; 3 | 4 | pub type Hash = Vec; 5 | pub const TARGET_HASH_PREFIX: &str = "00"; // TODO changing it depending on network size 6 | 7 | // pub fn hash(hash_data: &[u8]) -> Hash { 8 | // let mut hasher = Blake2s256::new(); 9 | // hasher.update(hash_data); //format!("{:?}", hash_data).as_bytes() 10 | // let res = hasher.finalize(); 11 | // let mut vector = Vec::new(); 12 | // vector.extend_from_slice(&res); 13 | // vector 14 | // } 15 | 16 | pub fn hash(hash_data: &[u8]) -> Hash { 17 | let mut hasher = Sha256::new(); 18 | hasher.update(hash_data); 19 | hasher.finalize().as_slice().to_owned() 20 | } 21 | 22 | // pub fn hasher() -> Blake2s { 23 | // Blake2s256::new() 24 | // } 25 | 26 | pub fn hasher() -> Sha256 { 27 | Sha256::new() 28 | } 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | 33 | use crate::hash; 34 | 35 | #[test] 36 | fn test_hash_function() { 37 | dbg!(hash(&generate_block())); 38 | } 39 | 40 | fn generate_block() -> Vec { 41 | String::from("ABRACADABRA!!!").as_bytes().to_vec() 42 | } 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /node/src/receiver.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | use std::sync::Arc; 3 | use tokio::net::{TcpListener, TcpStream}; 4 | use tokio::sync::Mutex; 5 | use tokio::sync::mpsc::{ 6 | channel, 7 | Receiver as Rx, 8 | Sender as Tx 9 | }; 10 | use async_trait::async_trait; 11 | use tracing::{error, trace}; 12 | use errors::LedgerError; 13 | use network::{p2p::process_incoming_data, Data}; 14 | use crate::connector::{Connect, Connector}; 15 | 16 | 17 | #[derive(Debug)] 18 | pub(crate) struct Receiver { 19 | address: SocketAddr, 20 | listener: TcpListener, 21 | pub(crate) connector_tx: Option> 22 | } 23 | 24 | impl Receiver { 25 | 26 | pub async fn new(address: SocketAddr) -> Self { 27 | Self { 28 | address, 29 | listener: TcpListener::bind(address).await.unwrap(), 30 | connector_tx: None 31 | } 32 | } 33 | 34 | pub async fn run(&mut self) { 35 | loop { 36 | while let Ok((mut socket, _)) = self.listener.accept().await { 37 | let processed = Self::process_incoming(self, &mut socket).await; 38 | if processed.is_err() { 39 | error!("error processing incoming data") 40 | } 41 | } 42 | } 43 | } 44 | 45 | async fn process_incoming(&mut self, socket: &mut TcpStream) 46 | -> Result<(), LedgerError> 47 | { 48 | let data = process_incoming_data(socket).await; 49 | if data.is_ok() { 50 | let tx = self.connector_tx.as_ref().unwrap(); 51 | let sent = tx.send(data.unwrap()).await; 52 | if sent.is_err() { 53 | error!("connector_tx: {}", sent.err().unwrap()); 54 | return Err(LedgerError::SyncError) 55 | } 56 | } else { 57 | error!("failed to receive data from network {}", data.err().unwrap()); 58 | return Err(LedgerError::NetworkError) 59 | } 60 | Ok(()) 61 | } 62 | } 63 | 64 | #[async_trait] 65 | impl Connect for Receiver { 66 | async fn connect(&mut self, connector: Arc>) { 67 | let mut connector = connector.lock().await; 68 | let (tx, rx): (Tx, Rx) = channel(10); 69 | self.connector_tx = Some(tx); 70 | connector.receiver_rx = Arc::new(Mutex::new(Some(rx))); 71 | } 72 | } -------------------------------------------------------------------------------- /client/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::net::{ SocketAddr}; 3 | use tokio::net::{TcpStream}; 4 | use tracing::{debug, error}; 5 | use errors::LedgerError; 6 | use network::{Data, p2p::process_incoming_data, p2p::send_data, p2p::SendEvent}; 7 | use network::client2node::RequestType; 8 | 9 | 10 | pub struct Client { 11 | peers: HashMap, 12 | } 13 | 14 | impl Client { 15 | 16 | pub fn new() -> Self { 17 | Self { peers: get_initial_peers() } 18 | } 19 | 20 | pub fn add_peer() { 21 | todo!() 22 | } 23 | 24 | pub async fn send_transaction_to_network(&mut self, transaction: Vec) { 25 | let mut addresses = Vec::new(); 26 | self.peers.values().for_each(|addr| addresses.push(addr.clone())); 27 | for (_, addr) in addresses.iter().enumerate() { 28 | let addr = addr.clone(); 29 | let transaction_clone = transaction.clone(); 30 | let a = tokio::spawn(async move { 31 | let stream = TcpStream::connect(addr.clone()).await; 32 | if let Ok(mut stream) = stream { 33 | let res = send_data( 34 | &mut stream, 35 | transaction_clone.as_slice(), 36 | SendEvent::SendTransaction) 37 | .await; 38 | if res.is_err() { 39 | error!("error while sending command to peers : {}", res.err().unwrap()); 40 | } 41 | } else { 42 | error!("could not connect to node"); 43 | } 44 | }) 45 | .await; 46 | error!("{}", a.is_err()); 47 | } 48 | } 49 | 50 | pub async fn client_request(node_addr: SocketAddr, request_type: RequestType) 51 | -> Result 52 | { 53 | let socket = TcpStream::connect(node_addr).await; 54 | return if let Ok(mut socket) = socket { 55 | match request_type { 56 | RequestType::Blockchain { .. } => { 57 | return if let Ok(response) = 58 | network::client2node::client_request(&mut socket, request_type).await { 59 | Ok(response) 60 | } else { 61 | Err(LedgerError::ApiError) 62 | } 63 | } 64 | RequestType::Block { .. } => { todo!() } 65 | RequestType::Transaction { .. } => { todo!() } 66 | } 67 | } else { 68 | error!("could not connect to node"); 69 | Err(LedgerError::NetworkError) 70 | } 71 | } 72 | } 73 | 74 | fn get_initial_peers() -> HashMap { 75 | HashMap::from([ 76 | (1, utils::socket_addr("1234")), 77 | (2, utils::socket_addr("1235")), 78 | (3, utils::socket_addr("1236")) 79 | ]) 80 | } 81 | 82 | #[cfg(test)] 83 | mod tests { 84 | use network::{ serialize_data}; 85 | use state::{Transaction}; 86 | use crate::Client; 87 | 88 | #[tokio::test] 89 | async fn send_transaction_would_return_success() { 90 | let transaction = create_account_transaction(); 91 | let mut client = Client::new(); 92 | client.send_transaction_to_network(serialize_data(&transaction)).await; 93 | } 94 | 95 | fn create_account_transaction() -> Transaction { 96 | Transaction { 97 | fee: 333, 98 | commands: vec![state::Command::CreateAccount { 99 | public_key: "12345".to_string(), 100 | }], 101 | } 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /node/src/sender.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::net::{IpAddr, Ipv4Addr, SocketAddr}; 3 | use std::sync::Arc; 4 | use tokio::net::TcpStream; 5 | use tokio::sync::Mutex; 6 | //use std::sync::Mutex; 7 | use network::{Data, p2p::SendEvent, serialize_data}; 8 | use state::Block; 9 | use crate::connector::{Connect, Connector}; 10 | use async_trait::async_trait; 11 | use tokio::sync::mpsc::{ 12 | channel, 13 | Receiver as Rx, 14 | Sender as Tx 15 | }; 16 | use tracing::{error, trace}; 17 | 18 | #[derive(Debug)] 19 | pub(crate) struct Sender { 20 | peer_address: SocketAddr, 21 | peers: Peers, 22 | pub(crate) connector_rx: Option>, 23 | } 24 | 25 | impl Sender { 26 | 27 | pub fn new(peer_address: SocketAddr) -> Self { 28 | Self { 29 | peer_address, 30 | peers: Peers::new(), 31 | connector_rx: None 32 | } 33 | } 34 | 35 | pub async fn run(&mut self) { 36 | loop { 37 | let peers = &self.peers; 38 | let address = &self.peer_address; 39 | if let Some(connector_rx) = self.connector_rx.as_mut() { 40 | while let Some(data) = connector_rx.recv().await { 41 | match data { 42 | Data::Block(block) => { 43 | //trace!("get block from connector: {}", &block); 44 | Self::send_block_to_network(address, peers, block).await; 45 | } 46 | Data::Transaction(_) => { 47 | error!("error: transaction is not intended to be sent by peer") 48 | } 49 | Data::Peer(peer) => { todo!() } 50 | Data::Peers(peers) => { todo!() } 51 | Data::Blockchain(blocks) => { todo!() } 52 | Data::NodeResponse(_) => todo!() 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | async fn send_block_to_network(peer_address: &SocketAddr, peers: &Peers, block: Block) { 60 | for (_, socket_addr) in peers.addresses.iter() { 61 | if socket_addr.eq(peer_address) { 62 | continue 63 | } 64 | let block = block.clone(); 65 | let socket = TcpStream::connect(socket_addr).await; 66 | if let Ok(mut socket) = socket { 67 | tokio::spawn(async move { 68 | let res = network::p2p::send_data( 69 | &mut socket, 70 | serialize_data(&block), SendEvent::SendBlock) 71 | .await; 72 | if res.is_err() { 73 | error!("error while sending block to peer: {}", res.err().unwrap()); 74 | } 75 | }); 76 | } else { 77 | error!("could not establish connection: {}", socket_addr) 78 | } 79 | } 80 | } 81 | } 82 | 83 | #[async_trait] 84 | impl Connect for Sender { 85 | async fn connect(&mut self, connector: Arc>) { 86 | let mut connector = connector.lock().await; 87 | let (tx, rx): (Tx, Rx) = channel(10); 88 | self.connector_rx = Some(rx); 89 | connector.sender_tx = Arc::new(Mutex::new(Some(tx))); 90 | } 91 | } 92 | 93 | #[derive(Debug)] 94 | struct Peers { 95 | addresses: HashMap, 96 | } 97 | 98 | impl Peers { 99 | fn new() -> Self { 100 | Self { 101 | addresses: HashMap::from([ 102 | (1, utils::socket_addr("1234")), 103 | (2, utils::socket_addr("1235")), 104 | (3, utils::socket_addr("1236")) 105 | ]) 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /network_protocol/src/client2node.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | use std::io::{Error, ErrorKind}; 3 | use std::sync::Arc; 4 | use tokio::net::TcpStream; 5 | use tokio::sync::Mutex; 6 | use tracing::error; 7 | use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; 8 | use crate::{Data, DATA_LENGTH, deserialize_data, read_exact_async, serialize_data, write_all_async}; 9 | 10 | pub enum RequestType { 11 | 12 | Blockchain { height: u64 }, 13 | 14 | Block { hash: Vec }, 15 | 16 | Transaction { hash: Vec }, 17 | 18 | } 19 | 20 | /// 1-st byte - request type, 2-nd byte = length of second value, 3-rd - second value, 21 | /// 4-th byte - length of 3-rd value, 5-th byte 3-rd value ... 22 | pub async fn client_request(mut socket: &mut TcpStream, request_type: RequestType) 23 | -> Result 24 | { 25 | match request_type { 26 | RequestType::Blockchain { height } => { 27 | let cmd_buf = [1u8]; 28 | write_all_async(socket, &cmd_buf).await?; 29 | let height_buf = height.to_be_bytes(); 30 | write_all_async(socket, &height_buf).await?; 31 | let data_buf = read_node_response(socket).await?; 32 | let response = deserialize_data(data_buf.as_slice()); 33 | return if let Ok(blockchain) = response { 34 | Ok(blockchain) 35 | } else { 36 | let err = response.err().unwrap(); 37 | error!("error response api: {}", &err); 38 | Err(Error::from(ErrorKind::InvalidInput)) 39 | } 40 | } 41 | RequestType::Block { hash } => { 42 | todo!() 43 | } 44 | RequestType::Transaction { hash } => { 45 | todo!() 46 | } 47 | } 48 | } 49 | 50 | async fn write_u32_to_buf(socket: &mut TcpStream, data: u32) -> Result<(), Error> 51 | { 52 | let mut buf = [0u8; 4]; 53 | ::write_u32(&mut buf.as_mut(), data); 54 | write_all_async(socket, buf.as_slice()).await?; 55 | Ok(()) 56 | } 57 | 58 | async fn write_string_to_buf(socket: &mut TcpStream, data: &str) -> Result<(), Error> 59 | { 60 | let data_buf = data.as_bytes(); 61 | let data_buf_len = (data_buf.len() as u32).to_be_bytes(); 62 | write_all_async(socket, &data_buf_len).await?; 63 | write_all_async(socket, data_buf).await?; 64 | Ok(()) 65 | } 66 | 67 | // TODO prevent copying bytes to vec 68 | async fn read_node_response(socket: &mut TcpStream) -> Result, Error> // , mut buf: &mut [u8] 69 | { 70 | let mut len_buf = DATA_LENGTH; 71 | read_exact_async(socket, &mut len_buf).await?; 72 | let len = u32::from_be_bytes(len_buf); 73 | let mut data_buf = vec![0; len as _]; 74 | read_exact_async(socket, &mut data_buf).await?; 75 | Ok(data_buf) 76 | } 77 | 78 | pub async fn node_response(socket: &mut TcpStream, 79 | miner: Arc>, 80 | fn_blockchain_data: Func) 81 | -> Result<(), Error> 82 | where Func: Fn(Arc>, Option) -> Fut, 83 | Fut: Future> 84 | { 85 | let mut cmd_buf = [0u8]; 86 | read_exact_async(socket, &mut cmd_buf).await?; 87 | match cmd_buf[0] { 88 | 1u8 => { 89 | let mut height_buf = [0u8; 8]; 90 | read_exact_async(socket, &mut height_buf).await?; 91 | let height = height_buf.as_slice().read_u64::(); 92 | return if let Ok(height) = height { 93 | let request_type = RequestType::Blockchain { height }; 94 | let response_buf = fn_blockchain_data(miner, Some(request_type)).await; 95 | let response_buf_len = (response_buf.len() as u32).to_be_bytes(); 96 | write_all_async(socket, &response_buf_len).await?; 97 | write_all_async(socket, response_buf.as_slice()).await?; 98 | Ok(()) 99 | } else { 100 | Err(Error::from(ErrorKind::InvalidInput)) 101 | } 102 | } 103 | 2u8 => { 104 | todo!() 105 | //Ok(()) 106 | } 107 | 3u8 => { 108 | todo!() 109 | //Ok(()) 110 | } 111 | _ => { 112 | error!("Api request error"); 113 | Err(Error::from(ErrorKind::InvalidInput)) 114 | } 115 | } 116 | } 117 | 118 | // MintTokens { 119 | // account_from_id: u32, 120 | // account_to_id: u32, 121 | // value: u32, 122 | // asset_id: String 123 | // }, 124 | 125 | // RequestType::MintTokens { account_from_id, account_to_id, value, asset_id } => { 126 | // let cmd_buf = [4u8]; 127 | // write_all_async(socket, &cmd_buf).await?; 128 | // write_u32_to_buf(&mut socket, account_from_id).await?; 129 | // write_u32_to_buf(&mut socket, account_to_id).await?; 130 | // write_u32_to_buf(&mut socket, value).await?; 131 | // write_string_to_buf(&mut socket,asset_id.as_str()).await?; 132 | // let response = read_node_response(&mut socket).await?; 133 | // let data = deserialize_data(&response).unwrap(); 134 | // Ok(data) 135 | // } 136 | -------------------------------------------------------------------------------- /node/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(async_closure)] 2 | #![feature(slice_pattern)] 3 | #![feature(let_chains)] 4 | extern crate core; 5 | 6 | mod storage; 7 | mod sender; 8 | mod receiver; 9 | mod miner; 10 | mod node; 11 | mod connector; 12 | 13 | use tracing_subscriber; 14 | use std::time::Duration; 15 | use crate::node::Node; 16 | 17 | 18 | fn main() { 19 | 20 | tracing_subscriber::fmt::init(); 21 | let runtime = tokio::runtime::Runtime::new().unwrap(); 22 | 23 | runtime.block_on( async { 24 | let node1 = Node::new(1, "1234").await; 25 | let node2 = Node::new(2,"1235").await; 26 | let node3 = Node::new(3,"1236").await; 27 | 28 | tokio::spawn(async move { node1.start().await }); 29 | tokio::spawn(async move { node2.start().await }); 30 | tokio::spawn(async move { node3.start().await }); 31 | loop { 32 | tokio::time::sleep(Duration::MAX).await; 33 | } 34 | }); 35 | } 36 | 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use std::thread; 41 | use std::time::Duration; 42 | use rand::{Rng, thread_rng}; 43 | use ursa::signatures::ed25519::Ed25519Sha512; 44 | use ursa::signatures::SignatureScheme; 45 | use client::Client; 46 | use network::serialize_data; 47 | use state::{Command, Transaction}; 48 | 49 | 50 | /// Assuming that nodes have started before this test performs 51 | #[tokio::test] 52 | async fn send_transactions_to_network() { 53 | 54 | let mut client1 = Client::new(); 55 | let mut client2 = Client::new(); 56 | let mut client3 = Client::new(); 57 | 58 | let mut transactions1 = Vec::with_capacity(10); 59 | for _ in 0..transactions1.capacity() { 60 | transactions1.push(generate_transaction()); 61 | }; 62 | 63 | let mut transactions2 = Vec::with_capacity(10); 64 | for _ in 0..transactions2.capacity() { 65 | transactions2.push(generate_transaction()); 66 | }; 67 | 68 | let mut transactions3 = Vec::with_capacity(10); 69 | for _ in 0..transactions3.capacity() { 70 | transactions3.push(generate_transaction()); 71 | }; 72 | 73 | let mut count = 0; 74 | tokio::spawn(async move { 75 | for i in 0..transactions1.len() { 76 | let transaction = transactions1.get(i).unwrap(); 77 | client1.send_transaction_to_network( 78 | serialize_data(transaction)) 79 | .await; 80 | tokio::time::sleep(Duration::from_secs(2)).await; 81 | count += 1; 82 | } 83 | }).await.expect("TODO: panic message 1");; 84 | 85 | let mut count = 0; 86 | tokio::spawn(async move { 87 | for i in 0..transactions2.len() { 88 | let transaction = transactions2.get(i).unwrap(); 89 | client2.send_transaction_to_network( 90 | serialize_data(transaction)) 91 | .await; 92 | tokio::time::sleep(Duration::from_secs(2)).await; 93 | count += 1; 94 | } 95 | }).await.expect("TODO: panic message 2");; 96 | 97 | let mut count = 0; 98 | tokio::spawn(async move { 99 | for i in 0..transactions3.len() { 100 | let transaction = transactions3.get(i).unwrap(); 101 | client3.send_transaction_to_network( 102 | serialize_data(transaction)) 103 | .await; 104 | tokio::time::sleep(Duration::from_secs(2)).await; 105 | count += 1; 106 | } 107 | }).await.expect("TODO: panic message 3"); 108 | } 109 | 110 | fn generate_transaction() -> Transaction { 111 | let mut rng = thread_rng(); 112 | let n1: u8 = rng.gen_range(0..2); // command variant 113 | let mut n2: u8 = rng.gen_range(2..4); // number of commands in transaction 114 | let mut commands = vec![]; 115 | 116 | while n2 > 0 { 117 | let command: Command; 118 | match n1 { 119 | 0 => { 120 | let (public_key, _) = Ed25519Sha512::new().keypair(None).unwrap(); 121 | command = Command::CreateAccount { public_key: public_key.to_string() } 122 | } 123 | 1 => { 124 | command = Command::AddFunds { 125 | account_id: rng.gen_range(0..100), 126 | value: rng.gen_range(0..1000), 127 | asset_id: "TEST".to_string() 128 | } 129 | } 130 | 2 => { 131 | command = Command::TransferFunds { 132 | account_from_id: rng.gen_range(0..100), 133 | account_to_id: rng.gen_range(0..100), 134 | value: rng.gen_range(0..1000), 135 | asset_id: "TEST2".to_string() 136 | } 137 | } 138 | _ => { unreachable!() } 139 | }; 140 | println!("command: {}", &command); 141 | commands.push(command); 142 | n2 -= 1; 143 | } 144 | 145 | Transaction { 146 | fee: 111, 147 | commands, 148 | } 149 | } 150 | } 151 | 152 | 153 | -------------------------------------------------------------------------------- /network_protocol/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(let_chains)] 2 | #![feature(io_error_more)] 3 | 4 | pub mod p2p; 5 | pub mod client2node; 6 | 7 | use std::collections::HashMap; 8 | use std::fmt::{Display, Formatter}; 9 | use std::io::ErrorKind; 10 | use bincode::{DefaultOptions, Options}; 11 | use tokio::io; 12 | use tokio::net::TcpStream; 13 | use tracing::error; 14 | use serde::{Deserialize, Serialize}; 15 | use errors::LedgerError; 16 | use errors::LedgerError::DeserializationError; 17 | use state::{Block, Transaction}; 18 | 19 | const DATA_LENGTH: [u8; 4] = [0, 0, 0, 0]; 20 | 21 | pub(crate) async fn read_exact_async(s: &TcpStream, buf: &mut [u8]) -> io::Result<()> { 22 | let mut red = 0; 23 | while red < buf.len() { 24 | s.readable().await?; 25 | match s.try_read(&mut buf[red..]) { 26 | Ok(0) => break, 27 | Ok(n) => { 28 | red += n; 29 | } 30 | Err(ref e) if e.kind() == ErrorKind::WouldBlock => { continue; } 31 | Err(e) => return Err(e), 32 | } 33 | } 34 | Ok(()) 35 | } 36 | 37 | pub(crate) async fn write_all_async(stream: &TcpStream, buf: &[u8]) -> io::Result<()> { 38 | let mut written = 0; 39 | while written < buf.len() { 40 | stream.writable().await?; 41 | match stream.try_write(&buf[written..]) { 42 | Ok(0) => break, 43 | Ok(n) => { 44 | written += n; 45 | } 46 | Err(ref e) if e.kind() == ErrorKind::WouldBlock => { continue; } 47 | Err(e) => return Err(e), 48 | } 49 | } 50 | Ok(()) 51 | } 52 | 53 | #[derive(Debug, Clone, Serialize, Deserialize)] 54 | #[repr(u8)] 55 | pub enum Data { 56 | Block(Block) = 1, 57 | Transaction(Transaction) = 2, 58 | Peer(String) = 3, 59 | Peers(HashMap) = 4, 60 | Blockchain(Vec) = 5, 61 | NodeResponse(HashMap) = 6, 62 | } 63 | 64 | impl Display for Data { 65 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 66 | match self { 67 | Data::Block(ref b) => { 68 | write!(f, "data (block) : {}", b) 69 | } 70 | Data::Transaction(ref t) => { 71 | write!(f, "data (transaction) : {}", t) 72 | } 73 | Data::Peer(ref p) => { 74 | write!(f, "data (node) : {}", p) 75 | } 76 | Data::Peers(ref p) => { 77 | write!(f, "data (peers) : {}", 78 | p.iter() 79 | .map(|p| p.0.clone() + " " + p.1.as_str()) 80 | .reduce(|acc, s| acc + ", " + s.as_str()) 81 | .unwrap()) 82 | } 83 | Data::Blockchain(ref b) => { 84 | write!(f, "data (blockchain) : {}", 85 | b.iter() 86 | .map(Block::to_string) 87 | .reduce(|acc, s| acc + ", " + s.as_str()) 88 | .unwrap()) 89 | } 90 | Data::NodeResponse(ref hashmap) => { 91 | // write!(f, "data (node response to client) : {}", 92 | // hashmap.iter() 93 | // .reduce(|acc, (k,v)| acc + "\nkey: " + k + "\nvalue: " + v) 94 | // .unwrap()) 95 | todo!() 96 | } 97 | } 98 | } 99 | } 100 | 101 | impl Data { 102 | 103 | pub fn data_type(&self) -> u8 { 104 | match self { 105 | Data::Block(_) => 1, 106 | Data::Transaction(_) => 2, 107 | Data::Peer(_) => 3, 108 | Data::Peers(_) => 4, 109 | Data::Blockchain(_) => 5, 110 | Data::NodeResponse(_) => 6 111 | } 112 | } 113 | } 114 | 115 | pub fn serialize_data(data: DATA) -> Vec { 116 | DefaultOptions::new() 117 | .with_varint_encoding() 118 | .serialize(&data).unwrap() 119 | } 120 | 121 | pub fn deserialize_data<'a, DATA: serde::de::Deserialize<'a>>(bytes: &'a [u8]) 122 | -> Result 123 | { 124 | let data = DefaultOptions::new() 125 | .with_varint_encoding() 126 | .deserialize::(&bytes[..]); 127 | if let Ok(data) = data { 128 | Ok(data) 129 | } else { 130 | let err = data.err().unwrap(); 131 | error!("network::deserialize_data() error: {}", err); 132 | Err(DeserializationError) 133 | } 134 | } 135 | 136 | #[cfg(test)] 137 | mod tests { 138 | 139 | use tokio::net::{TcpListener, TcpStream}; 140 | use state::{Block, Command, Transaction}; 141 | use crate::p2p::send_data; 142 | use crate::p2p::SendEvent::SendBlock; 143 | use crate::serialize_data; 144 | 145 | #[tokio::test] 146 | async fn transfer_block() { 147 | let block = generate_block(); 148 | let mut sender = TcpStream::connect("127.0.0.1:1234").await.unwrap(); 149 | let _ = send_data(&mut sender, serialize_data::<&Block>(&block).as_slice(), SendBlock).await; 150 | } 151 | 152 | fn generate_block() -> Block { 153 | Block { 154 | id: 1, 155 | timestamp: 0, 156 | transactions: vec![Transaction { 157 | fee: 555, 158 | commands: vec![Command::CreateAccount { 159 | public_key: "12345".to_string(), 160 | }], 161 | }], 162 | signature: vec![1, 2, 3, 4, 5], 163 | hash: vec![], 164 | previous_block_hash: None, 165 | nonce: 0 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /node/src/storage.rs: -------------------------------------------------------------------------------- 1 | use tracing::{debug, error, info}; 2 | use state::{Accounts, Asset, Assets, Block, MAX_TRANSACTIONS_IN_BLOCK, NATIVE_COIN}; 3 | 4 | use crypto; 5 | use crypto::hash; 6 | use errors::LedgerError; 7 | use utils::{print_bytes, convert_timestamp_to_day_time}; 8 | 9 | #[derive(Debug)] 10 | pub(crate) struct Storage { 11 | id: u64, 12 | blockchain: Vec, // TODO persistence 13 | accounts: Accounts, 14 | /// Key is a tuple of format (account_id, asset_id) 15 | assets: Assets 16 | } 17 | 18 | impl Storage { 19 | 20 | pub fn new(id: u64,) -> Self { 21 | Self { 22 | id, 23 | blockchain: Default::default(), 24 | accounts: Default::default(), 25 | assets: Default::default(), 26 | } 27 | } 28 | 29 | pub fn try_add_block(&mut self, block: Block) -> Result<(), LedgerError> { 30 | debug!("storage id: {}", &self.id); 31 | let previous_block = self.blockchain.last(); 32 | if previous_block.is_some() && &block.id != &0u64 { 33 | let previous_block = previous_block.unwrap(); 34 | return if Self::validate_block(self, &block, previous_block) { 35 | // TODO persistence < --- > state in memory??? 36 | for commands in block.transactions.iter().map(|transaction| &transaction.commands) { 37 | for command in commands { 38 | command.execute(&mut self.accounts, &mut self.assets)? 39 | } 40 | }; 41 | let block_id = block.id; 42 | self.blockchain.push(block); 43 | info!("Block with id {} added to node {} blockchain", block_id, self.id); 44 | Self::reward_for_mined_block(self); 45 | Ok(()) 46 | } else { 47 | Err(LedgerError::BlockError) 48 | } 49 | } else if previous_block.is_none() { 50 | Self::try_add_genesis_block(self, block)?; 51 | } 52 | Ok(()) 53 | } 54 | 55 | pub fn get_blockchain_by_ref(&self) -> &Vec { 56 | &self.blockchain 57 | } 58 | 59 | fn try_add_genesis_block(&mut self, block: Block) -> Result<(), LedgerError> { 60 | if block.previous_block_hash.is_some() { 61 | return Err(LedgerError::BlockError) 62 | } 63 | if block.id > 1 { 64 | error!("invalid block id: {}", &block.id); 65 | return Err(LedgerError::BlockError) 66 | } 67 | if block.previous_block_hash.is_some() { 68 | error!("this is not genesis block"); 69 | return Err(LedgerError::BlockError) 70 | } 71 | if block.transactions.len() > MAX_TRANSACTIONS_IN_BLOCK { 72 | error!("transactions count exceeded: {}", &block.transactions.len()); 73 | return Err(LedgerError::BlockError) 74 | } 75 | if !Self::validate_hash(&block) { 76 | error!("invalid block hash: {}", print_bytes(&block.hash)); 77 | return Err(LedgerError::BlockError) 78 | } 79 | let block_id = block.id; 80 | self.blockchain.push(block); 81 | info!("Genesis block with id {} added to node {} blockchain", block_id, self.id); 82 | Ok(()) 83 | } 84 | 85 | fn validate_block(&self, block: &Block, previous_block: &Block) -> bool { 86 | // if block.id != previous_block.id + 1 { 87 | // error!("invalid block id: {}", &block.id); 88 | // return false 89 | // } 90 | if &previous_block.hash != block.previous_block_hash.as_ref().unwrap() { 91 | error!("invalid previous block hash: {}", print_bytes(&previous_block.hash)); 92 | return false 93 | } 94 | if block.transactions.len() > MAX_TRANSACTIONS_IN_BLOCK { 95 | error!("transactions count exceeded: {}", &block.transactions.len()); 96 | return false 97 | } 98 | if convert_timestamp_to_day_time(block.timestamp) 99 | <= 100 | convert_timestamp_to_day_time(previous_block.timestamp) { 101 | error!("invalid block timestamp: {}", &block.timestamp); 102 | return false 103 | } 104 | if !Self::validate_hash(&block) { 105 | error!("invalid block hash: {}", print_bytes(&block.hash)); 106 | return false 107 | } 108 | 109 | true 110 | } 111 | 112 | fn validate_hash(block: &Block) -> bool { 113 | let mut block_to_validate = block.clone(); 114 | block_to_validate.hash = vec![]; 115 | block_to_validate.nonce -= 1; 116 | let hash_data = bincode::serialize::(&block_to_validate).unwrap(); 117 | let h = hash(hash_data.as_slice()); 118 | block_to_validate.hash.extend_from_slice(&h); 119 | block_to_validate.hash == block.hash 120 | } 121 | 122 | fn validate_chain(&self, remote_block_chain: Vec) -> bool { 123 | for (i, _) in remote_block_chain.iter().enumerate() { 124 | if i == 0 { 125 | continue 126 | } 127 | let previous_block = remote_block_chain.get(i-1).unwrap(); 128 | let current_block = remote_block_chain.get(i).unwrap(); 129 | if !Self::validate_block(self, current_block, previous_block) { 130 | return false 131 | } 132 | } 133 | true 134 | } 135 | 136 | fn reward_for_mined_block(&mut self) { 137 | self.assets.insert((1, String::from(NATIVE_COIN)), Asset::new_with_value(1)); 138 | } 139 | 140 | fn persist_block(block: &Block) { 141 | 142 | } 143 | } 144 | 145 | -------------------------------------------------------------------------------- /state/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | use std::collections::HashMap; 3 | use std::fmt::{Display, Formatter}; 4 | use crypto::Hash; 5 | use serde::{Deserialize, Serialize}; 6 | use derive_more::Display; 7 | use errors::LedgerError; 8 | use utils::print_bytes; 9 | 10 | pub const MAX_TRANSACTIONS_IN_BLOCK: usize = 100; // TODO constraint size of block 11 | pub const NATIVE_COIN: &str = "NATIVE"; 12 | 13 | #[derive(Debug, Clone)] 14 | pub struct Account { 15 | public_key: String, 16 | } 17 | 18 | pub type Accounts = HashMap; 19 | 20 | #[derive(Debug, Clone)] 21 | pub struct Asset { 22 | value: u32, 23 | } 24 | 25 | impl Asset { 26 | pub fn new_with_value(value: u32) -> Self { 27 | Self { value } 28 | } 29 | } 30 | 31 | pub type Assets = HashMap<(u32, String), Asset>; 32 | 33 | #[derive(Debug, Clone, Serialize, Deserialize)] 34 | pub struct Transaction { 35 | pub fee: u32, 36 | pub commands: Vec, 37 | } 38 | 39 | unsafe impl Send for Transaction {} 40 | unsafe impl Sync for Transaction {} 41 | 42 | impl Eq for Transaction {} 43 | 44 | impl PartialEq for Transaction { 45 | fn eq(&self, other: &Self) -> bool { 46 | self.fee == other.fee 47 | } 48 | } 49 | 50 | impl PartialOrd for Transaction { 51 | fn partial_cmp(&self, other: &Self) -> Option { 52 | Some(self.cmp(other)) 53 | } 54 | } 55 | 56 | impl Ord for Transaction { 57 | fn cmp(&self, other: &Self) -> Ordering { 58 | let difference = i64::from(self.fee.clone()) - i64::from(other.fee.clone()); 59 | match difference { 60 | d if d > 0 => Ordering::Greater, 61 | d if d < 0 => Ordering::Less, 62 | 0 => Ordering::Equal, 63 | _ => unreachable!() 64 | } 65 | } 66 | } 67 | 68 | impl Display for Transaction { 69 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 70 | write!(f, "transaction: fee : {}, commands: {}", self.fee, self.commands.iter() 71 | .map(|c| c.to_string()) 72 | .reduce(|acc, c| acc + " " + c.as_str()) 73 | .unwrap()) 74 | } 75 | } 76 | 77 | #[derive(Debug, Clone, Serialize, Deserialize, Display)] 78 | pub enum Command { 79 | CreateAccount { 80 | public_key: String, 81 | }, 82 | #[display(fmt = "account_id: {}, value: {}, asset_id: {}", 83 | account_id, value, asset_id)] 84 | AddFunds { 85 | account_id: u32, 86 | value: u32, 87 | asset_id: String, 88 | }, 89 | #[display(fmt = "account_from_id: {}, account_to_id: {} value: {}, asset_id: {}", 90 | account_from_id, account_to_id, value, asset_id)] 91 | TransferFunds { 92 | account_from_id: u32, 93 | account_to_id: u32, 94 | value: u32, 95 | asset_id: String, 96 | } 97 | } 98 | 99 | #[derive(Debug, Clone, Default, Serialize, Deserialize)] 100 | pub struct Block { 101 | pub id: u64, 102 | pub timestamp: i64, 103 | pub nonce: u32, 104 | pub signature: Vec, 105 | pub hash: Hash, 106 | pub previous_block_hash: Option, 107 | pub transactions: Vec 108 | } 109 | 110 | impl Display for Block { 111 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 112 | write!(f, "block: \n 113 | id: {}, \n 114 | timestamp: {}, \n 115 | nonce: {}, \n 116 | signature: {}, \n 117 | hash: {}, \n 118 | previous_block_hash: {}, \n 119 | transactions: {} \n", 120 | &self.id, 121 | &self.timestamp, 122 | &self.nonce, 123 | print_bytes(&self.signature), 124 | print_bytes(&self.hash), 125 | print_bytes(&self.previous_block_hash.clone().unwrap_or("None".as_bytes().to_vec())), 126 | self.transactions.iter() 127 | .map(|c| c.to_string()) 128 | .reduce(|acc, c| acc + " " + c.as_str()) 129 | .unwrap()) 130 | } 131 | } 132 | 133 | impl Command { 134 | pub fn execute(&self, 135 | accounts: &mut Accounts, 136 | assets: &mut Assets) 137 | -> Result<(), LedgerError> 138 | { 139 | match self { 140 | Self::CreateAccount { public_key } => { 141 | accounts.insert( 142 | (accounts.len() + 1) as u32, 143 | Account { 144 | public_key: public_key.clone(), 145 | }, 146 | ); 147 | Ok(()) 148 | } 149 | Self::AddFunds { 150 | account_id, 151 | value, 152 | asset_id, 153 | } => { 154 | assets.insert((account_id.clone(), asset_id.clone()), Asset { value: value.clone() }); 155 | Ok(()) 156 | }, 157 | 158 | Self::TransferFunds { 159 | account_from_id, 160 | account_to_id, 161 | value, 162 | asset_id 163 | } => { 164 | if let Some(account_asset) = assets.get(&(account_from_id.clone(), asset_id.clone())) { 165 | if account_asset.value < *value { 166 | return Err(LedgerError::InsufficientFunds) 167 | } 168 | assets.remove(&(account_from_id.clone(), asset_id.clone())); 169 | assets.insert((account_to_id.clone(), asset_id.clone()), Asset { value: value.clone() }); 170 | Ok(()) 171 | } else { 172 | Err(LedgerError::NoSuchAsset) 173 | } 174 | } 175 | } 176 | } 177 | } 178 | 179 | #[cfg(test)] 180 | mod tests { 181 | 182 | } -------------------------------------------------------------------------------- /node/src/node.rs: -------------------------------------------------------------------------------- 1 | use std::net::{SocketAddr}; 2 | use std::str::FromStr; 3 | use std::sync::{Arc}; 4 | //use std::sync::Mutex; 5 | use std::time::Duration; 6 | 7 | use tokio::net::TcpListener; 8 | use tokio::sync::{Mutex}; 9 | use tracing::{debug, error, event, info, Level, span}; 10 | 11 | use network::{Data, serialize_data}; 12 | use network::client2node::{RequestType, node_response}; 13 | use state::Block; 14 | 15 | use crate::connector::{Connect, Connector}; 16 | use crate::miner::Miner; 17 | use crate::receiver::Receiver; 18 | use crate::sender::Sender; 19 | 20 | const LOCAL_HOST: &str = "127.0.0.1:"; 21 | 22 | pub struct Node { 23 | node_id: u64, 24 | peer_address: SocketAddr, 25 | receiver: Arc>, 26 | sender: Arc>, 27 | miner: Arc>, 28 | } 29 | 30 | impl Node { 31 | 32 | pub async fn new(node_id: u64, local_port: &str) -> Self { 33 | let addr = utils::socket_addr(local_port); 34 | Self { 35 | node_id, 36 | peer_address: addr, 37 | receiver: Arc::new(Mutex::new(Receiver::new(addr).await)), 38 | sender: Arc::new(Mutex::new(Sender::new(addr))), 39 | miner: Arc::new(Mutex::new(Miner::new(local_port.parse().unwrap()))), 40 | } 41 | } 42 | 43 | pub async fn start(&self) { 44 | let port = self.peer_address.port(); 45 | let receiver = self.receiver.clone(); 46 | let sender = self.sender.clone(); 47 | let miner = self.miner.clone(); 48 | 49 | let receiver1 = receiver.clone(); 50 | let sender1 = sender.clone(); 51 | let miner1 = miner.clone(); 52 | let receiver2 = receiver.clone(); 53 | let sender2 = sender.clone(); 54 | let miner2 = miner.clone(); 55 | 56 | let connector = Arc::new(Mutex::new(Connector::new())); 57 | let c1 = connector.clone(); 58 | let c2 = connector.clone(); 59 | let c3 = connector.clone(); 60 | 61 | miner1.lock().await.connect(c1).await; 62 | sender1.lock().await.connect(c2).await; 63 | receiver1.lock().await.connect(c3).await; 64 | connector.lock().await.start().await; 65 | 66 | tokio::spawn(async move { 67 | let mut receiver = receiver2.lock().await; 68 | receiver.run().await 69 | }); 70 | tokio::spawn(async move { 71 | let mut sender = sender2.lock().await; 72 | sender.run().await 73 | }); 74 | tokio::spawn(async move { 75 | let miner = miner2.lock().await; 76 | miner.run().await; 77 | }); 78 | 79 | event!(Level::INFO, "node started on 127.0.0.1:{}", port); 80 | 81 | Self::listen_api_requests(&self, port).await; 82 | } 83 | 84 | async fn listen_api_requests(&self, mut port: u16) { 85 | port += 10; 86 | let addr = String::from(LOCAL_HOST) + port.to_string().as_str(); 87 | let listener = TcpListener::bind(addr.as_str()).await.unwrap(); 88 | let miner = self.miner.clone(); 89 | info!("listen_api_requests started on {}", &addr); 90 | loop { 91 | if let Ok((mut socket, _)) = listener.accept().await { 92 | if let Err(e) = node_response(&mut socket, 93 | miner.clone(), 94 | |m, r_t| blockchain_data(m, r_t)) 95 | .await { 96 | error!("api request error: {}", e); 97 | } 98 | continue 99 | } 100 | } 101 | } 102 | } 103 | 104 | /// This function requires Option = Some(request_type), otherwise - panic! 105 | async fn blockchain_data(miner: Arc>, request_type: Option) -> Vec 106 | { 107 | let miner = miner.lock().await; 108 | let storage = miner.storage.clone(); 109 | loop { 110 | match storage.try_lock() { 111 | Ok(storage) => { 112 | match request_type.unwrap() { 113 | RequestType::Blockchain { height } => { 114 | info!("requested height: {}", height); 115 | let blockchain = storage.get_blockchain_by_ref(); 116 | let blockchain_of_required_length = blockchain.iter().rev() 117 | .take(height as usize) 118 | .map(|item| {item.to_owned()}) 119 | .collect::>(); 120 | let data = Data::Blockchain(blockchain_of_required_length); 121 | return serialize_data(data) 122 | } 123 | RequestType::Block { ref hash } => { todo!() } 124 | RequestType::Transaction { ref hash } => { todo!() } 125 | } 126 | } 127 | Err(_) => { 128 | debug!("storage is locked yet"); 129 | tokio::time::sleep(Duration::from_millis(300)).await 130 | } 131 | } 132 | } 133 | } 134 | 135 | #[cfg(test)] 136 | mod tests { 137 | use tracing::{error, info}; 138 | use client::Client; 139 | use network::client2node::RequestType; 140 | use network::Data; 141 | 142 | #[tokio::test] 143 | async fn receive_blockchain_request_and_response_ok() { 144 | tracing_subscriber::fmt::init(); 145 | 146 | let request_type = RequestType::Blockchain { height: 3}; 147 | let socket_addr = utils::socket_addr("1244"); 148 | let blockchain_response = 149 | Client::client_request(socket_addr, request_type).await; 150 | if let Ok(blockchain_response) = blockchain_response { 151 | match blockchain_response { 152 | Data::Blockchain(blocks) => { 153 | assert_eq!(blocks.len(), 3); 154 | for block in blocks { 155 | info!{"block: {}", block} 156 | } 157 | }, 158 | _ => { unreachable![] } 159 | } 160 | } 161 | } 162 | } -------------------------------------------------------------------------------- /node/src/connector.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use tokio::sync::Mutex; 3 | use network::Data; 4 | use tokio::sync::mpsc::{ 5 | channel, 6 | Receiver as Rx, 7 | Sender as Tx 8 | }; 9 | use async_trait::async_trait; 10 | use tracing::{error, info, span, trace, Level}; 11 | use crate::sender::Sender; 12 | 13 | /// structure for connecting modules together 14 | #[derive(Debug)] 15 | pub struct Connector { 16 | pub(crate) receiver_rx: Arc>>>, 17 | pub(crate) sender_tx: Arc>>>, 18 | pub(crate) miner_rx: Arc>>>, 19 | pub(crate) miner_tx: Arc>>>, 20 | } 21 | 22 | impl Connector { 23 | 24 | pub fn new() -> Self { 25 | Self { 26 | receiver_rx: Arc::new(Mutex::new(None)), 27 | sender_tx: Arc::new(Mutex::new(None)), 28 | miner_rx: Arc::new(Mutex::new(None)), 29 | miner_tx: Arc::new(Mutex::new(None)), 30 | } 31 | } 32 | 33 | pub async fn start(&self) { 34 | let receiver_rx = self.receiver_rx.clone(); 35 | let sender_tx = self.sender_tx.clone(); 36 | let miner_rx = self.miner_rx.clone(); 37 | let miner_tx = self.miner_tx.clone(); 38 | let started = tokio::spawn(async { 39 | Self::process_incoming( 40 | receiver_rx, sender_tx, miner_rx, miner_tx).await; 41 | }) 42 | .await; 43 | if started.is_err() { 44 | error!("connector error: {}", started.err().unwrap()) 45 | } 46 | } 47 | 48 | async fn process_incoming( 49 | receiver_rx: Arc>>>, 50 | sender_tx: Arc>>>, 51 | miner_rx: Arc>>>, 52 | miner_tx: Arc>>>, 53 | ) 54 | { 55 | let sender_tx = sender_tx.clone(); 56 | let sender_tx1 = sender_tx.clone(); 57 | tokio::spawn(async move { 58 | loop { 59 | let mut miner_rx = miner_rx.lock().await; 60 | let miner_rx = miner_rx.as_mut(); 61 | if let Some(miner_rx) = miner_rx { 62 | while let Some(data) = miner_rx.recv().await { 63 | match data.data_type() { 64 | 1 => { 65 | //trace!("get block from miner: {}", &data); 66 | let sender_tx = sender_tx.clone(); 67 | Self::send_data(sender_tx, data).await; 68 | } 69 | _ => { error!("received wrong data type: {}", data) } 70 | } 71 | } 72 | } 73 | } 74 | }); 75 | let sender_tx1 = sender_tx1.clone(); 76 | tokio::spawn( async move { 77 | loop { 78 | let mut receiver_rx = receiver_rx.lock().await; 79 | let receiver_rx = receiver_rx.as_mut(); 80 | if let Some(receiver_rx) = receiver_rx { 81 | while let Some(data) = receiver_rx.recv().await { 82 | //trace!("get data from receiver: {}", &data); 83 | match data.data_type() { 84 | 1 | 2 => { 85 | let miner_tx = miner_tx.clone(); 86 | Self::send_data(miner_tx, data).await 87 | } 88 | 3 | 4 => { 89 | let sender_tx = sender_tx1.clone(); 90 | Self::send_data(sender_tx, data).await; 91 | } 92 | _ => { unreachable!() } 93 | } 94 | } 95 | } 96 | error!("listen_incoming() - there is no receiver") 97 | }; 98 | }); 99 | } 100 | 101 | // TODO retry 102 | async fn send_data(tx: Arc>>>, data: Data) { 103 | let mut tx = tx.lock().await; 104 | let tx = tx.as_mut(); 105 | if let Some(tx) = tx { 106 | if let Err(e) = tx.send(data).await { 107 | error!("send_data() error: {}", e) 108 | } else { 109 | //trace!("data sent successfully") 110 | } 111 | } 112 | } 113 | } 114 | 115 | #[async_trait] 116 | pub trait Connect { 117 | async fn connect(&mut self, connector: Arc>); 118 | } 119 | 120 | #[cfg(test)] 121 | mod tests { 122 | use std::net::SocketAddr; 123 | use std::str::FromStr; 124 | use std::sync::Arc; 125 | use tokio::sync::Mutex; 126 | use network::serialize_data; 127 | use state::Transaction; 128 | use utils::LOCAL_HOST; 129 | use client::Client; 130 | use crate::connector::{Connect, Connector}; 131 | 132 | 133 | #[tokio::test] 134 | async fn test_channel() { 135 | let address = utils::socket_addr("1234"); 136 | let mut receiver = crate::receiver::Receiver::new(address).await; 137 | let mut miner = crate::miner::Miner::new(1); 138 | //miner.run().await; 139 | let connector = Arc::new(Mutex::new(Connector::new())); 140 | let connector1 = connector.clone(); 141 | let connector2 = connector.clone(); 142 | receiver.connect(connector).await; 143 | tokio::spawn(async move { receiver.run().await }); 144 | miner.connect(connector2.clone()).await; //tokio::spawn(async move { 145 | connector1.lock().await.start().await; 146 | send_transaction_to_receiver().await; 147 | } 148 | 149 | 150 | 151 | async fn send_transaction_to_receiver() { 152 | let transaction = create_account_transaction(); 153 | let mut client = Client::new(); 154 | client.send_transaction_to_network(serialize_data(&transaction)).await; 155 | } 156 | 157 | fn create_account_transaction() -> Transaction { 158 | Transaction { 159 | fee: 333, 160 | commands: vec![state::Command::CreateAccount { 161 | public_key: "12345".to_string(), 162 | }], 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /network_protocol/src/p2p.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Error, ErrorKind}; 2 | use tokio::net::{TcpStream}; 3 | use std::convert::{TryFrom}; 4 | use derive_more::{Display}; 5 | use tracing::{error, trace}; 6 | use errors::LedgerError; 7 | use errors::LedgerError::*; 8 | use crate::{Data, DATA_LENGTH, deserialize_data, read_exact_async, write_all_async}; 9 | 10 | pub const NO_DATA: &str = "no data"; 11 | 12 | /// protocol : (byte1, byte2) = NetworkEvent(SendEvent/ReceiveEvent) 13 | #[derive(Display)] 14 | #[repr(u8)] 15 | pub enum NetworkEvent { 16 | Send(SendEvent) = 1, 17 | Receive(ReceiveEvent) = 2, 18 | } 19 | 20 | #[derive(Display)] 21 | #[repr(u8)] 22 | pub enum SendEvent { 23 | SendBlock = 1, 24 | SendTransaction = 2, 25 | InitPeer = 3, 26 | SendPeers = 4, 27 | SendChain = 5, 28 | //SendProveBlock, 29 | } 30 | 31 | impl SendEvent { 32 | pub fn value(&self) -> u8 { 33 | match self { 34 | SendEvent::SendBlock => 1, 35 | SendEvent::SendTransaction => 2, 36 | SendEvent::InitPeer => 3, 37 | SendEvent::SendPeers => 4, 38 | SendEvent::SendChain => 5, 39 | } 40 | } 41 | } 42 | 43 | #[derive(Display)] 44 | pub enum ReceiveEvent { 45 | ReceiveBlock = 1, 46 | ReceiveTransaction = 2, 47 | AddPeer = 3, 48 | ReceivePeers = 4, 49 | ReceiveChain = 5, 50 | //ReceiveProveBlock, 51 | } 52 | 53 | impl ReceiveEvent { 54 | pub fn from_value(value: u8) -> Result { 55 | match value { 56 | 1 => Ok(ReceiveEvent::ReceiveBlock), 57 | 2 => Ok(ReceiveEvent::ReceiveTransaction), 58 | 3 => Ok(ReceiveEvent::AddPeer), 59 | 4 => Ok(ReceiveEvent::ReceivePeers), 60 | 5 => Ok(ReceiveEvent::ReceiveChain), 61 | _ => Err(WrongCommandError) 62 | } 63 | } 64 | } 65 | 66 | impl TryFrom<(u8, u8)> for NetworkEvent { 67 | type Error = LedgerError; 68 | 69 | fn try_from(value: (u8, u8)) -> Result { 70 | match value.0 { 71 | 1u8 => { 72 | trace!("SendEvent"); 73 | let send_event = match value.1 { 74 | 1 => SendEvent::SendBlock, 75 | 2 => SendEvent::SendTransaction, 76 | 3 => SendEvent::InitPeer, 77 | 4 => SendEvent::SendPeers, 78 | 5 => SendEvent::SendChain, 79 | _ => { 80 | println!("NetworkEvent ERROR"); 81 | return Err(WrongCommandError) 82 | }, 83 | }; 84 | trace!("NetworkEvent = {}", &send_event); 85 | Ok(NetworkEvent::Send(send_event)) 86 | }, 87 | 2u8 => { 88 | trace!("ReceiveEvent"); 89 | let receive_event = match value.1 { 90 | 1 => ReceiveEvent::ReceiveBlock, 91 | 2 => ReceiveEvent::ReceiveTransaction, 92 | 3 => ReceiveEvent::AddPeer, 93 | 4 => ReceiveEvent::ReceivePeers, 94 | 5 => ReceiveEvent::ReceiveChain, 95 | _ => { 96 | println!("NetworkEvent ERROR"); 97 | return Err(WrongCommandError) 98 | }, 99 | }; 100 | trace!("NetworkEvent = {}", &receive_event); 101 | Ok(NetworkEvent::Receive(receive_event)) 102 | }, 103 | _ => { 104 | trace!("NetworkEvent ERROR"); 105 | Err(WrongCommandError) 106 | }, 107 | } 108 | } 109 | } 110 | 111 | /// 1 byte - event, 2 byte - len of data, 3..len bytes - data 112 | pub async fn send_data>( 113 | socket: &mut TcpStream, 114 | data: DATA, 115 | event: SendEvent) 116 | -> Result< (), Error> 117 | { 118 | let buf = data.as_ref(); 119 | match event { 120 | _ => { send_command_and_data(event, buf, socket).await? } 121 | } 122 | Ok(()) 123 | } 124 | 125 | async fn send_command_and_data( 126 | send_event: SendEvent, 127 | buf: &[u8], 128 | socket: &mut TcpStream) 129 | -> Result<(), Error> 130 | { 131 | let cmd_buf: [u8; 1] = [send_event.value()]; 132 | write_all_async(socket, &cmd_buf).await?; 133 | let buf_len = (buf.len() as u32).to_be_bytes(); 134 | write_all_async(socket, &buf_len).await?; 135 | write_all_async(socket, buf).await?; 136 | let mut buf: [u8; 1] = [0u8]; 137 | read_exact_async(socket, &mut buf).await?; 138 | return if buf[0] == 1 { 139 | Ok(()) 140 | } else { 141 | error!("sending data failure"); 142 | Err(Error::from(ErrorKind::NetworkDown)) 143 | }; 144 | } 145 | 146 | /// 1 byte - event, 2 byte - len of data, 3..len bytes - data 147 | pub async fn process_incoming_data(socket: &TcpStream) -> Result 148 | { 149 | let mut cmd_buf: [u8; 1] = [0u8]; 150 | let read = read_exact_async(socket, &mut cmd_buf).await; 151 | return if let Ok(_) = read { 152 | let event = ReceiveEvent::from_value(cmd_buf[0]); 153 | if event.is_err() { 154 | return Err(WrongCommandError) 155 | } 156 | let event = event.unwrap(); 157 | match event { 158 | _ => { 159 | let data = process_event(event, socket).await?; 160 | Ok(data) 161 | } 162 | } 163 | } else { 164 | Err(WrongCommandError) 165 | } 166 | } 167 | 168 | async fn process_event( 169 | event: ReceiveEvent, 170 | socket: &TcpStream) 171 | -> Result 172 | { 173 | let mut len_buf = DATA_LENGTH; 174 | if let Err(_) = read_exact_async(socket, &mut len_buf).await { 175 | return Err(WrongCommandError); 176 | } 177 | let len = u32::from_be_bytes(len_buf); 178 | let mut data_buf = vec![0; len as _]; 179 | if let Err(e) = read_exact_async(socket, &mut data_buf).await { 180 | error!("receive_event_and_data() data_buf error: {}", e); 181 | return Err(NetworkError); 182 | } 183 | let data; 184 | match event { 185 | ReceiveEvent::ReceiveBlock => { 186 | let block = deserialize_data(data_buf.as_slice()); 187 | if block.is_ok() { 188 | data = Data::Block(block.unwrap()); 189 | } else { 190 | return Err(DeserializationError); 191 | } 192 | } 193 | ReceiveEvent::ReceiveTransaction => { 194 | let transaction = deserialize_data(data_buf.as_slice()); 195 | if transaction.is_ok() { 196 | data = Data::Transaction(transaction.unwrap()); 197 | } else { 198 | return Err(DeserializationError); 199 | } 200 | } 201 | ReceiveEvent::AddPeer => { 202 | let peer = deserialize_data(data_buf.as_slice()); 203 | if peer.is_ok() { 204 | data = Data::Peer(peer.unwrap()); 205 | } else { 206 | return Err(DeserializationError); 207 | } 208 | } 209 | ReceiveEvent::ReceivePeers => { 210 | let peers = deserialize_data(data_buf.as_slice()); 211 | if peers.is_ok() { 212 | data = Data::Peers(peers.unwrap()); 213 | } else { 214 | return Err(DeserializationError); 215 | } 216 | } 217 | ReceiveEvent::ReceiveChain => { 218 | let blockchain = deserialize_data(data_buf.as_slice()); 219 | if blockchain.is_ok() { 220 | data = Data::Blockchain(blockchain.unwrap()); 221 | } else { 222 | let e = blockchain.err().unwrap(); 223 | error!("deserialization error: {}", e); 224 | return Err(DeserializationError); 225 | } 226 | } 227 | } 228 | if write_response(socket).await == false { 229 | return Err(SyncError); 230 | }; 231 | Ok(data) 232 | } 233 | 234 | async fn write_response(socket: &TcpStream) -> bool { 235 | let mut buf: [u8; 1] = [1u8]; 236 | let res = write_all_async(socket, &mut buf).await; 237 | if res.is_ok() { 238 | true 239 | } else { 240 | trace!("write_response failed"); 241 | false 242 | } 243 | } 244 | 245 | -------------------------------------------------------------------------------- /node/src/miner.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | use std::sync::{Arc}; 3 | use tokio::sync::mpsc::{ 4 | channel, 5 | Receiver as Rx, 6 | Sender as Tx 7 | }; 8 | use std::time::Duration; 9 | use tokio::sync::{Mutex}; 10 | use chrono::{Utc}; 11 | use ursa::keys::{PublicKey, PrivateKey}; 12 | use ursa::signatures::ed25519::Ed25519Sha512; 13 | use ursa::signatures::SignatureScheme; 14 | use crypto::Hash; 15 | use network::Data; 16 | use state::{Block, Transaction}; 17 | use utils::print_bytes; 18 | use async_trait::async_trait; 19 | use blake2::Digest; 20 | use tracing::{debug, error, info, trace, warn}; 21 | use crate::connector::{Connect, Connector}; 22 | use crate::storage::Storage; 23 | 24 | #[derive(Debug)] 25 | pub(crate) struct Miner { 26 | id: u64, 27 | public_key: PublicKey, 28 | private_key: PrivateKey, 29 | transaction_pool: Arc>>, 30 | pub(crate) storage: Arc>, 31 | pub(crate) connector_rx: Arc>>>, 32 | pub(crate) connector_tx: Arc>>>, 33 | } 34 | 35 | impl Miner { 36 | 37 | pub fn new(id: u64) -> Self { 38 | let (public_key, private_key) = Ed25519Sha512::new().keypair(None).unwrap(); 39 | Self { 40 | id, 41 | public_key, 42 | private_key, 43 | transaction_pool: Arc::new(Mutex::new(BinaryHeap::new())), 44 | storage: Arc::new(Mutex::new(Storage::new(id))), 45 | connector_rx: Arc::new(Mutex::new(None)), 46 | connector_tx: Arc::new(Mutex::new(None)), 47 | } 48 | } 49 | 50 | pub async fn run(&self) { 51 | let connector_tx = self.connector_tx.clone(); 52 | let connector_rx = self.connector_rx.clone(); 53 | let storage1 = self.storage.clone(); 54 | let storage2 = self.storage.clone(); 55 | let transaction_pool_1 = self.transaction_pool.clone(); 56 | let transaction_pool_2 = self.transaction_pool.clone(); 57 | let id = self.id; 58 | let private_key = self.private_key.clone(); 59 | tokio::spawn(async move { 60 | Self::run_listening( 61 | id, 62 | connector_rx, 63 | storage1, 64 | transaction_pool_1) 65 | .await 66 | }); 67 | tokio::spawn(async move { 68 | Self::run_mining( 69 | id, 70 | connector_tx, 71 | storage2, 72 | &private_key, 73 | transaction_pool_2) 74 | .await 75 | }); 76 | } 77 | 78 | async fn run_listening( 79 | id: u64, 80 | connector_rx: Arc>>>, 81 | storage: Arc>, 82 | transaction_pool: Arc>>) 83 | { 84 | loop { 85 | let connector_rx = connector_rx.clone(); 86 | let mut connector_rx = connector_rx.lock().await; 87 | let connector_rx = connector_rx.as_mut().unwrap(); 88 | while let Some(data) = connector_rx.recv().await { 89 | match data { 90 | // receive block from other node 91 | Data::Block(block) => { 92 | debug!("miner id: {}", id); 93 | info!("block has been received from another node, \ 94 | block id: {}, block hash: {}", &block.id, print_bytes(&block.hash)); 95 | let storage = storage.clone(); 96 | let mut storage = storage.lock().await; 97 | let added_block = storage.try_add_block(block); 98 | if added_block.is_err() { 99 | println!("error while adding block: {}", added_block.err().unwrap()) 100 | } 101 | } 102 | // receive transaction from client 103 | Data::Transaction(transaction) => { 104 | let mut transactions; 105 | loop { 106 | match transaction_pool.try_lock() { 107 | Ok(mutex_guard) => { 108 | transactions = mutex_guard; 109 | break; 110 | } 111 | Err(_) => { 112 | tokio::time::sleep(Duration::from_secs(3)).await; 113 | } 114 | } 115 | } 116 | transactions.push(transaction); 117 | } 118 | _ => { error!("received wrong data type") } 119 | } 120 | } 121 | } 122 | } 123 | 124 | async fn run_mining( 125 | id: u64, 126 | connector_tx: Arc>>>, 127 | storage: Arc>, 128 | private_key: &PrivateKey, 129 | transaction_pool: Arc>> 130 | ) { 131 | // mine block from received transactions 132 | loop { 133 | let storage = storage.clone(); 134 | let storage_lock = storage.lock().await; 135 | let previous_block = storage_lock.get_blockchain_by_ref().last(); 136 | if let Some(b) = previous_block.as_ref() { 137 | debug!("previous_block: {}", &b); 138 | } 139 | let previous_block_id; 140 | let previous_block_hash; 141 | match previous_block { 142 | None => { 143 | previous_block_id = None; 144 | previous_block_hash = None; 145 | }, 146 | Some(p_b) => { 147 | debug!("miner_id: {}, previous_block id: {}", id, &p_b.id); 148 | previous_block_id = Some(p_b.id); 149 | debug!("miner_id: {}, previous_block hash: {}", id, print_bytes(&p_b.hash)); 150 | previous_block_hash = Some(p_b.hash.clone()); 151 | } 152 | }; 153 | drop(storage_lock); 154 | let private_key = private_key.clone(); 155 | let transaction_pool = transaction_pool.clone(); 156 | let ready_to_mine = async move { 157 | let mut transactions; 158 | loop { 159 | match transaction_pool.try_lock() { 160 | Ok(mutex_guard) => { 161 | transactions = mutex_guard; 162 | if transactions.len() < 10 { 163 | drop(transactions); 164 | tokio::time::sleep(Duration::from_secs(5)).await; 165 | continue 166 | }; 167 | let mut ready_transactions = Vec::with_capacity(10); 168 | for _ in 0..10 { 169 | let transaction = transactions.pop().unwrap(); 170 | ready_transactions.push(transaction); 171 | } 172 | return ready_transactions 173 | } 174 | Err(_) => { 175 | tokio::time::sleep(Duration::from_secs(2)).await; 176 | } 177 | } 178 | } 179 | } 180 | .await; 181 | debug!("mining block started, miner_id: {}", id); 182 | let block = tokio::task::spawn_blocking(move || { 183 | Self::mine_block( 184 | private_key, 185 | 2, 186 | previous_block_hash, 187 | previous_block_id, 188 | ready_to_mine) 189 | }) 190 | .await 191 | .unwrap(); 192 | info!("miner_id: {}, block has been mined, block: \n {}", id, &block); 193 | let mut storage = storage.lock().await; 194 | let added_block = storage.try_add_block(block.clone()); 195 | drop(storage); 196 | if added_block.is_err() { 197 | let err = added_block.err().unwrap(); 198 | error!("miner_id: {id}, failed to add self-mined block: {}", err) 199 | } else { 200 | 201 | let connector_tx = connector_tx.clone(); 202 | let mut connector_tx = connector_tx.lock().await; 203 | let connector_tx = connector_tx.as_mut().unwrap(); 204 | let data = Data::Block(block); 205 | let sent_block = connector_tx.send(data).await; 206 | if sent_block.is_err() { 207 | error!("error while sending block to connector: {}", sent_block.err().unwrap()) 208 | } 209 | } 210 | } 211 | } 212 | 213 | /// FOR TEST ONLY 214 | async fn add_block_to_storage(&mut self, block: Block) { 215 | let mut storage = self.storage.lock().await; 216 | if let Err(_) = storage.try_add_block(block) { 217 | error!("could not add block to storage") 218 | }; 219 | } 220 | 221 | fn mine_block( 222 | private_key: PrivateKey, 223 | target_hash_zero_count: usize, 224 | previous_block_hash: Option, 225 | previous_block_id: Option, 226 | transactions: Vec) 227 | -> Block 228 | { 229 | let mut id = 0; 230 | if previous_block_id.is_some() { 231 | id = previous_block_id.unwrap() + 1; 232 | }; 233 | let timestamp = Utc::now().timestamp(); 234 | let signature = Ed25519Sha512::new() 235 | .sign(format!("{:?}", &transactions).as_bytes(), &private_key) 236 | .unwrap(); 237 | let mut nonce = 0; 238 | let mut hash = vec![]; 239 | let mut block = Default::default(); 240 | let start = Utc::now(); 241 | while !is_hash_valid(&hash, target_hash_zero_count) { // TODO concurrent calculation 242 | let mut hasher = crypto::hasher(); 243 | block = Block { 244 | id, 245 | timestamp, 246 | nonce, 247 | signature: signature.clone(), 248 | hash: vec![], 249 | previous_block_hash: previous_block_hash.clone(), 250 | transactions: transactions.clone() 251 | }; 252 | let hash_data = bincode::serialize(&block).unwrap(); 253 | hasher.update(hash_data.as_slice()); 254 | let h = hasher.finalize(); 255 | hash.clear(); 256 | hash.extend_from_slice(&h); 257 | nonce += 1; 258 | }; 259 | let finish = Utc::now(); 260 | //info!("valid block hash has been found, total time = {} sec", finish.second() - start.second()); 261 | info!("hash: {}, nonce: {}", print_bytes(&hash), &nonce); 262 | block.nonce = nonce; 263 | block.hash = hash; 264 | info!("block: {}", &block); 265 | block 266 | } 267 | } 268 | 269 | fn is_hash_valid(hash: &Hash, target_hash_zero_count: usize) -> bool { 270 | hash.iter().take_while(|n| **n == 0u8).count() >= target_hash_zero_count 271 | } 272 | 273 | #[async_trait] 274 | impl Connect for Miner { 275 | async fn connect(&mut self, connector: Arc>) { 276 | let mut connector = connector.lock().await; 277 | let (tx1, rx1): (Tx, Rx) = channel(10); 278 | let (tx2, rx2): (Tx, Rx) = channel(10); 279 | self.connector_rx = Arc::new(Mutex::new(Some(rx1))); 280 | connector.miner_tx = Arc::new(Mutex::new(Some(tx1))); 281 | self.connector_tx = Arc::new(Mutex::new(Some(tx2))); 282 | connector.miner_rx = Arc::new(Mutex::new(Some(rx2))); 283 | } 284 | } 285 | 286 | // fn hash_data(transactions: &Vec) -> Vec { 287 | // Vec::from(transactions.iter() 288 | // .map(|t| t.to_string()) 289 | // .reduce(|acc, t| acc + " " + t.as_str()) 290 | // .unwrap() 291 | // .as_bytes()) 292 | // 293 | // } 294 | 295 | #[cfg(test)] 296 | mod tests { 297 | use std::sync::Arc; 298 | use rand::prelude::*; 299 | use chrono::Utc; 300 | use crypto::hash; 301 | use state::{Block, Command, Transaction}; 302 | use ursa::signatures::ed25519::Ed25519Sha512; 303 | use ursa::signatures::SignatureScheme; 304 | use utils::{LOCAL_HOST, print_bytes}; 305 | use crate::miner::{ Miner}; 306 | use tracing::info; 307 | 308 | #[test] 309 | fn validate_block_hash() { 310 | for _ in 0..10 { 311 | let block = generate_block( 312 | 11134, 313 | vec![ 314 | generate_transaction(), 315 | generate_transaction(), 316 | generate_transaction() 317 | ]); 318 | let block_hash = hash(block.to_string().as_bytes()); 319 | info!("block hash is {}", print_bytes(&block_hash)); 320 | } 321 | 322 | let block = generate_block( 323 | 11134, 324 | vec![ 325 | generate_transaction(), 326 | generate_transaction(), 327 | generate_transaction() 328 | ]); 329 | let block_hash1 = hash(block.to_string().as_bytes()); 330 | info!("block hash1 is {}", print_bytes(&block_hash1)); 331 | let block_hash2 = hash(block.to_string().as_bytes()); 332 | info!("block hash2 is {}", print_bytes(&block_hash2)); 333 | 334 | // let mut block_to_check = block.clone(); 335 | // block_to_check.hash = vec![]; 336 | // let hash = hash(block_to_check.to_string().as_bytes()); 337 | // hash == block.hash; 338 | // assert_eq!(&block_hash, &block.hash) 339 | } 340 | 341 | #[tokio::test] 342 | async fn mine_block_succeed() { 343 | let miner = Miner::new(1); 344 | miner.run().await; 345 | let previous_block_transactions = vec![generate_transaction()]; 346 | let previous_block = generate_block(2, previous_block_transactions); 347 | let current_block_transactions = vec![generate_transaction()]; 348 | let private_key = miner.private_key.clone(); 349 | let block = Miner::mine_block( 350 | private_key, 351 | 2, 352 | Some(previous_block.hash), 353 | Some(previous_block.id), 354 | current_block_transactions); 355 | assert!(&block.hash.starts_with(&[0, 0])) 356 | } 357 | 358 | fn generate_block(nonce: u32, transactions: Vec) -> Block { 359 | let (_, private_key) = Ed25519Sha512::new().keypair(None).unwrap(); 360 | 361 | let signature = Ed25519Sha512::new() 362 | .sign(format!("{:?}", &transactions).as_bytes(), &private_key) 363 | .unwrap(); 364 | 365 | let mut block = Block { 366 | id: 7, 367 | timestamp: Utc::now().timestamp(), 368 | nonce, 369 | signature, 370 | hash: vec![], 371 | previous_block_hash: Some(String::from("0004f4544324323323").as_bytes().to_vec()), 372 | transactions, 373 | }; 374 | let hash_data = bincode::serialize::(&block).unwrap(); 375 | let hash = hash(hash_data.as_slice()); 376 | println!("block hash : {}", print_bytes(&hash)); 377 | block.hash = hash; 378 | block 379 | } 380 | 381 | fn generate_transaction() -> Transaction { 382 | let mut rng = thread_rng(); 383 | let n1: u8 = rng.gen_range(0..2); // command variant 384 | let mut n2: u8 = rng.gen_range(2..4); // number of commands in transaction 385 | let mut commands = vec![]; 386 | 387 | while n2 > 0 { 388 | let command: Command; 389 | match n1 { 390 | 0 => { 391 | let (public_key, _) = Ed25519Sha512::new().keypair(None).unwrap(); 392 | command = Command::CreateAccount { public_key: public_key.to_string() } 393 | } 394 | 1 => { 395 | command = Command::AddFunds { 396 | account_id: rng.gen_range(0..100), 397 | value: rng.gen_range(0..1000), 398 | asset_id: "TEST".to_string() } 399 | } 400 | 2 => { 401 | command = Command::TransferFunds { 402 | account_from_id: rng.gen_range(0..100), 403 | account_to_id: rng.gen_range(0..100), 404 | value: rng.gen_range(0..1000), 405 | asset_id: "TEST2".to_string() } 406 | } 407 | _ => { unreachable!() } 408 | }; 409 | println!("command: {}", &command); 410 | commands.push(command); 411 | n2 -= 1; 412 | } 413 | 414 | Transaction { 415 | fee: 111, 416 | commands, 417 | } 418 | } 419 | } 420 | 421 | -------------------------------------------------------------------------------- /client/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.20.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aead" 22 | version = "0.3.2" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" 25 | dependencies = [ 26 | "generic-array 0.14.7", 27 | ] 28 | 29 | [[package]] 30 | name = "aes" 31 | version = "0.6.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" 34 | dependencies = [ 35 | "aes-soft", 36 | "aesni", 37 | "cipher", 38 | ] 39 | 40 | [[package]] 41 | name = "aes-gcm" 42 | version = "0.8.0" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" 45 | dependencies = [ 46 | "aead", 47 | "aes", 48 | "cipher", 49 | "ctr", 50 | "ghash", 51 | "subtle", 52 | ] 53 | 54 | [[package]] 55 | name = "aes-soft" 56 | version = "0.6.4" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" 59 | dependencies = [ 60 | "cipher", 61 | "opaque-debug 0.3.0", 62 | ] 63 | 64 | [[package]] 65 | name = "aesni" 66 | version = "0.10.0" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" 69 | dependencies = [ 70 | "cipher", 71 | "opaque-debug 0.3.0", 72 | ] 73 | 74 | [[package]] 75 | name = "amcl" 76 | version = "0.2.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "ee5cca1ddc8b9dceb55b7f1272a9d1e643d73006f350a20ab4926d24e33f0f0d" 79 | 80 | [[package]] 81 | name = "amcl_wrapper" 82 | version = "0.4.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "8c7c7c7627444413f6a488bf9e6d352aea6fcfa281123cd92ecac0b3c9ef5ef2" 85 | dependencies = [ 86 | "byteorder", 87 | "lazy_static", 88 | "miracl_core", 89 | "rand 0.7.3", 90 | "rayon", 91 | "serde", 92 | "serde_bytes", 93 | "serde_json", 94 | "sha3 0.8.2", 95 | "subtle-encoding", 96 | "zeroize", 97 | ] 98 | 99 | [[package]] 100 | name = "arrayref" 101 | version = "0.3.7" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" 104 | 105 | [[package]] 106 | name = "autocfg" 107 | version = "0.1.8" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" 110 | dependencies = [ 111 | "autocfg 1.1.0", 112 | ] 113 | 114 | [[package]] 115 | name = "autocfg" 116 | version = "1.1.0" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 119 | 120 | [[package]] 121 | name = "backtrace" 122 | version = "0.3.68" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" 125 | dependencies = [ 126 | "addr2line", 127 | "cc", 128 | "cfg-if", 129 | "libc", 130 | "miniz_oxide", 131 | "object", 132 | "rustc-demangle", 133 | ] 134 | 135 | [[package]] 136 | name = "bincode" 137 | version = "1.3.3" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 140 | dependencies = [ 141 | "serde", 142 | ] 143 | 144 | [[package]] 145 | name = "bitflags" 146 | version = "1.3.2" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 149 | 150 | [[package]] 151 | name = "blake2" 152 | version = "0.9.2" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" 155 | dependencies = [ 156 | "crypto-mac 0.8.0", 157 | "digest 0.9.0", 158 | "opaque-debug 0.3.0", 159 | ] 160 | 161 | [[package]] 162 | name = "blake2" 163 | version = "0.10.6" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" 166 | dependencies = [ 167 | "digest 0.10.7", 168 | ] 169 | 170 | [[package]] 171 | name = "block-buffer" 172 | version = "0.7.3" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" 175 | dependencies = [ 176 | "block-padding 0.1.5", 177 | "byte-tools", 178 | "byteorder", 179 | "generic-array 0.12.4", 180 | ] 181 | 182 | [[package]] 183 | name = "block-buffer" 184 | version = "0.9.0" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 187 | dependencies = [ 188 | "block-padding 0.2.1", 189 | "generic-array 0.14.7", 190 | ] 191 | 192 | [[package]] 193 | name = "block-buffer" 194 | version = "0.10.4" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 197 | dependencies = [ 198 | "generic-array 0.14.7", 199 | ] 200 | 201 | [[package]] 202 | name = "block-modes" 203 | version = "0.7.0" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0" 206 | dependencies = [ 207 | "block-padding 0.2.1", 208 | "cipher", 209 | ] 210 | 211 | [[package]] 212 | name = "block-padding" 213 | version = "0.1.5" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" 216 | dependencies = [ 217 | "byte-tools", 218 | ] 219 | 220 | [[package]] 221 | name = "block-padding" 222 | version = "0.2.1" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" 225 | 226 | [[package]] 227 | name = "bumpalo" 228 | version = "3.13.0" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 231 | 232 | [[package]] 233 | name = "byte-tools" 234 | version = "0.3.1" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" 237 | 238 | [[package]] 239 | name = "byteorder" 240 | version = "1.4.3" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 243 | 244 | [[package]] 245 | name = "bytes" 246 | version = "0.4.12" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" 249 | dependencies = [ 250 | "byteorder", 251 | "iovec", 252 | ] 253 | 254 | [[package]] 255 | name = "bytes" 256 | version = "1.4.0" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 259 | 260 | [[package]] 261 | name = "c2-chacha" 262 | version = "0.2.4" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "217192c943108d8b13bac38a1d51df9ce8a407a3f5a71ab633980665e68fbd9a" 265 | dependencies = [ 266 | "ppv-lite86", 267 | ] 268 | 269 | [[package]] 270 | name = "cc" 271 | version = "1.0.79" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 274 | 275 | [[package]] 276 | name = "cfg-if" 277 | version = "1.0.0" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 280 | 281 | [[package]] 282 | name = "chacha20" 283 | version = "0.6.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "ed8738f14471a99f0e316c327e68fc82a3611cc2895fcb604b89eedaf8f39d95" 286 | dependencies = [ 287 | "cipher", 288 | "zeroize", 289 | ] 290 | 291 | [[package]] 292 | name = "chacha20poly1305" 293 | version = "0.7.1" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "af1fc18e6d90c40164bf6c317476f2a98f04661e310e79830366b7e914c58a8e" 296 | dependencies = [ 297 | "aead", 298 | "chacha20", 299 | "cipher", 300 | "poly1305", 301 | "zeroize", 302 | ] 303 | 304 | [[package]] 305 | name = "cipher" 306 | version = "0.2.5" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" 309 | dependencies = [ 310 | "generic-array 0.14.7", 311 | ] 312 | 313 | [[package]] 314 | name = "client" 315 | version = "0.1.0" 316 | dependencies = [ 317 | "futures 0.3.28", 318 | "network", 319 | "state", 320 | "tokio", 321 | "tokio-io", 322 | ] 323 | 324 | [[package]] 325 | name = "const-oid" 326 | version = "0.6.2" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" 329 | 330 | [[package]] 331 | name = "cpufeatures" 332 | version = "0.2.8" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" 335 | dependencies = [ 336 | "libc", 337 | ] 338 | 339 | [[package]] 340 | name = "cpuid-bool" 341 | version = "0.2.0" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" 344 | 345 | [[package]] 346 | name = "crossbeam-channel" 347 | version = "0.5.8" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" 350 | dependencies = [ 351 | "cfg-if", 352 | "crossbeam-utils", 353 | ] 354 | 355 | [[package]] 356 | name = "crossbeam-deque" 357 | version = "0.8.3" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" 360 | dependencies = [ 361 | "cfg-if", 362 | "crossbeam-epoch", 363 | "crossbeam-utils", 364 | ] 365 | 366 | [[package]] 367 | name = "crossbeam-epoch" 368 | version = "0.9.15" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" 371 | dependencies = [ 372 | "autocfg 1.1.0", 373 | "cfg-if", 374 | "crossbeam-utils", 375 | "memoffset", 376 | "scopeguard", 377 | ] 378 | 379 | [[package]] 380 | name = "crossbeam-utils" 381 | version = "0.8.16" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" 384 | dependencies = [ 385 | "cfg-if", 386 | ] 387 | 388 | [[package]] 389 | name = "crypto-bigint" 390 | version = "0.2.11" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" 393 | dependencies = [ 394 | "generic-array 0.14.7", 395 | "rand_core 0.6.4", 396 | "subtle", 397 | "zeroize", 398 | ] 399 | 400 | [[package]] 401 | name = "crypto-common" 402 | version = "0.1.6" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 405 | dependencies = [ 406 | "generic-array 0.14.7", 407 | "typenum", 408 | ] 409 | 410 | [[package]] 411 | name = "crypto-mac" 412 | version = "0.8.0" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" 415 | dependencies = [ 416 | "generic-array 0.14.7", 417 | "subtle", 418 | ] 419 | 420 | [[package]] 421 | name = "crypto-mac" 422 | version = "0.11.1" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" 425 | dependencies = [ 426 | "generic-array 0.14.7", 427 | "subtle", 428 | ] 429 | 430 | [[package]] 431 | name = "ctr" 432 | version = "0.6.0" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" 435 | dependencies = [ 436 | "cipher", 437 | ] 438 | 439 | [[package]] 440 | name = "curve25519-dalek" 441 | version = "3.2.1" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" 444 | dependencies = [ 445 | "byteorder", 446 | "digest 0.9.0", 447 | "rand_core 0.5.1", 448 | "subtle", 449 | "zeroize", 450 | ] 451 | 452 | [[package]] 453 | name = "der" 454 | version = "0.4.5" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" 457 | dependencies = [ 458 | "const-oid", 459 | ] 460 | 461 | [[package]] 462 | name = "digest" 463 | version = "0.8.1" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" 466 | dependencies = [ 467 | "generic-array 0.12.4", 468 | ] 469 | 470 | [[package]] 471 | name = "digest" 472 | version = "0.9.0" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 475 | dependencies = [ 476 | "generic-array 0.14.7", 477 | ] 478 | 479 | [[package]] 480 | name = "digest" 481 | version = "0.10.7" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 484 | dependencies = [ 485 | "block-buffer 0.10.4", 486 | "crypto-common", 487 | "subtle", 488 | ] 489 | 490 | [[package]] 491 | name = "ecdsa" 492 | version = "0.12.4" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" 495 | dependencies = [ 496 | "der", 497 | "elliptic-curve", 498 | "hmac", 499 | "signature", 500 | ] 501 | 502 | [[package]] 503 | name = "ed25519" 504 | version = "1.5.3" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" 507 | dependencies = [ 508 | "signature", 509 | ] 510 | 511 | [[package]] 512 | name = "ed25519-dalek" 513 | version = "1.0.1" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" 516 | dependencies = [ 517 | "curve25519-dalek", 518 | "ed25519", 519 | "rand 0.7.3", 520 | "serde", 521 | "sha2", 522 | "zeroize", 523 | ] 524 | 525 | [[package]] 526 | name = "either" 527 | version = "1.8.1" 528 | source = "registry+https://github.com/rust-lang/crates.io-index" 529 | checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" 530 | 531 | [[package]] 532 | name = "elliptic-curve" 533 | version = "0.10.6" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b" 536 | dependencies = [ 537 | "crypto-bigint", 538 | "ff", 539 | "generic-array 0.14.7", 540 | "group", 541 | "pkcs8", 542 | "rand_core 0.6.4", 543 | "subtle", 544 | "zeroize", 545 | ] 546 | 547 | [[package]] 548 | name = "errors" 549 | version = "0.1.0" 550 | dependencies = [ 551 | "thiserror", 552 | ] 553 | 554 | [[package]] 555 | name = "failure" 556 | version = "0.1.8" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" 559 | dependencies = [ 560 | "backtrace", 561 | "failure_derive", 562 | ] 563 | 564 | [[package]] 565 | name = "failure_derive" 566 | version = "0.1.8" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" 569 | dependencies = [ 570 | "proc-macro2", 571 | "quote", 572 | "syn 1.0.109", 573 | "synstructure", 574 | ] 575 | 576 | [[package]] 577 | name = "ff" 578 | version = "0.10.1" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" 581 | dependencies = [ 582 | "rand_core 0.6.4", 583 | "subtle", 584 | ] 585 | 586 | [[package]] 587 | name = "foreign-types" 588 | version = "0.3.2" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 591 | dependencies = [ 592 | "foreign-types-shared", 593 | ] 594 | 595 | [[package]] 596 | name = "foreign-types-shared" 597 | version = "0.1.1" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 600 | 601 | [[package]] 602 | name = "futures" 603 | version = "0.1.31" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" 606 | 607 | [[package]] 608 | name = "futures" 609 | version = "0.3.28" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" 612 | dependencies = [ 613 | "futures-channel", 614 | "futures-core", 615 | "futures-executor", 616 | "futures-io", 617 | "futures-sink", 618 | "futures-task", 619 | "futures-util", 620 | ] 621 | 622 | [[package]] 623 | name = "futures-channel" 624 | version = "0.3.28" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" 627 | dependencies = [ 628 | "futures-core", 629 | "futures-sink", 630 | ] 631 | 632 | [[package]] 633 | name = "futures-core" 634 | version = "0.3.28" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 637 | 638 | [[package]] 639 | name = "futures-executor" 640 | version = "0.3.28" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" 643 | dependencies = [ 644 | "futures-core", 645 | "futures-task", 646 | "futures-util", 647 | ] 648 | 649 | [[package]] 650 | name = "futures-io" 651 | version = "0.3.28" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" 654 | 655 | [[package]] 656 | name = "futures-macro" 657 | version = "0.3.28" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" 660 | dependencies = [ 661 | "proc-macro2", 662 | "quote", 663 | "syn 2.0.22", 664 | ] 665 | 666 | [[package]] 667 | name = "futures-sink" 668 | version = "0.3.28" 669 | source = "registry+https://github.com/rust-lang/crates.io-index" 670 | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" 671 | 672 | [[package]] 673 | name = "futures-task" 674 | version = "0.3.28" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" 677 | 678 | [[package]] 679 | name = "futures-util" 680 | version = "0.3.28" 681 | source = "registry+https://github.com/rust-lang/crates.io-index" 682 | checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" 683 | dependencies = [ 684 | "futures-channel", 685 | "futures-core", 686 | "futures-io", 687 | "futures-macro", 688 | "futures-sink", 689 | "futures-task", 690 | "memchr", 691 | "pin-project-lite", 692 | "pin-utils", 693 | "slab", 694 | ] 695 | 696 | [[package]] 697 | name = "generic-array" 698 | version = "0.12.4" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" 701 | dependencies = [ 702 | "typenum", 703 | ] 704 | 705 | [[package]] 706 | name = "generic-array" 707 | version = "0.14.7" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 710 | dependencies = [ 711 | "typenum", 712 | "version_check", 713 | ] 714 | 715 | [[package]] 716 | name = "getrandom" 717 | version = "0.1.16" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 720 | dependencies = [ 721 | "cfg-if", 722 | "js-sys", 723 | "libc", 724 | "wasi 0.9.0+wasi-snapshot-preview1", 725 | "wasm-bindgen", 726 | ] 727 | 728 | [[package]] 729 | name = "getrandom" 730 | version = "0.2.10" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" 733 | dependencies = [ 734 | "cfg-if", 735 | "libc", 736 | "wasi 0.11.0+wasi-snapshot-preview1", 737 | ] 738 | 739 | [[package]] 740 | name = "ghash" 741 | version = "0.3.1" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" 744 | dependencies = [ 745 | "opaque-debug 0.3.0", 746 | "polyval", 747 | ] 748 | 749 | [[package]] 750 | name = "gimli" 751 | version = "0.27.3" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" 754 | 755 | [[package]] 756 | name = "group" 757 | version = "0.10.0" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" 760 | dependencies = [ 761 | "ff", 762 | "rand_core 0.6.4", 763 | "subtle", 764 | ] 765 | 766 | [[package]] 767 | name = "hermit-abi" 768 | version = "0.3.1" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 771 | 772 | [[package]] 773 | name = "hex" 774 | version = "0.4.3" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 777 | 778 | [[package]] 779 | name = "hkdf" 780 | version = "0.11.0" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b" 783 | dependencies = [ 784 | "digest 0.9.0", 785 | "hmac", 786 | ] 787 | 788 | [[package]] 789 | name = "hmac" 790 | version = "0.11.0" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" 793 | dependencies = [ 794 | "crypto-mac 0.11.1", 795 | "digest 0.9.0", 796 | ] 797 | 798 | [[package]] 799 | name = "int_traits" 800 | version = "0.1.1" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "b33c9a5c599d67d051c4dc25eb1b6b4ef715d1763c20c85c688717a1734f204e" 803 | 804 | [[package]] 805 | name = "iovec" 806 | version = "0.1.4" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 809 | dependencies = [ 810 | "libc", 811 | ] 812 | 813 | [[package]] 814 | name = "itoa" 815 | version = "1.0.6" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" 818 | 819 | [[package]] 820 | name = "js-sys" 821 | version = "0.3.64" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 824 | dependencies = [ 825 | "wasm-bindgen", 826 | ] 827 | 828 | [[package]] 829 | name = "k256" 830 | version = "0.9.6" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea" 833 | dependencies = [ 834 | "cfg-if", 835 | "ecdsa", 836 | "elliptic-curve", 837 | "sha2", 838 | ] 839 | 840 | [[package]] 841 | name = "keccak" 842 | version = "0.1.4" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" 845 | dependencies = [ 846 | "cpufeatures", 847 | ] 848 | 849 | [[package]] 850 | name = "lazy_static" 851 | version = "1.4.0" 852 | source = "registry+https://github.com/rust-lang/crates.io-index" 853 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 854 | 855 | [[package]] 856 | name = "libc" 857 | version = "0.2.147" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 860 | 861 | [[package]] 862 | name = "log" 863 | version = "0.4.19" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 866 | 867 | [[package]] 868 | name = "memchr" 869 | version = "2.5.0" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 872 | 873 | [[package]] 874 | name = "memoffset" 875 | version = "0.9.0" 876 | source = "registry+https://github.com/rust-lang/crates.io-index" 877 | checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" 878 | dependencies = [ 879 | "autocfg 1.1.0", 880 | ] 881 | 882 | [[package]] 883 | name = "miniz_oxide" 884 | version = "0.7.1" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 887 | dependencies = [ 888 | "adler", 889 | ] 890 | 891 | [[package]] 892 | name = "mio" 893 | version = "0.8.8" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 896 | dependencies = [ 897 | "libc", 898 | "wasi 0.11.0+wasi-snapshot-preview1", 899 | "windows-sys", 900 | ] 901 | 902 | [[package]] 903 | name = "miracl_core" 904 | version = "1.0.0" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "4330eca86d39f2b52d0481aa1e90fe21bfa61f11b0bf9b48ab95595013cefe48" 907 | 908 | [[package]] 909 | name = "network" 910 | version = "0.1.0" 911 | dependencies = [ 912 | "bincode", 913 | "bytes 1.4.0", 914 | "errors", 915 | "futures 0.3.28", 916 | "serde", 917 | "state", 918 | "tokio", 919 | "tokio-io", 920 | ] 921 | 922 | [[package]] 923 | name = "num_cpus" 924 | version = "1.16.0" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 927 | dependencies = [ 928 | "hermit-abi", 929 | "libc", 930 | ] 931 | 932 | [[package]] 933 | name = "object" 934 | version = "0.31.1" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" 937 | dependencies = [ 938 | "memchr", 939 | ] 940 | 941 | [[package]] 942 | name = "once_cell" 943 | version = "1.18.0" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 946 | 947 | [[package]] 948 | name = "opaque-debug" 949 | version = "0.2.3" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" 952 | 953 | [[package]] 954 | name = "opaque-debug" 955 | version = "0.3.0" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 958 | 959 | [[package]] 960 | name = "openssl" 961 | version = "0.10.55" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" 964 | dependencies = [ 965 | "bitflags", 966 | "cfg-if", 967 | "foreign-types", 968 | "libc", 969 | "once_cell", 970 | "openssl-macros", 971 | "openssl-sys", 972 | ] 973 | 974 | [[package]] 975 | name = "openssl-macros" 976 | version = "0.1.1" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 979 | dependencies = [ 980 | "proc-macro2", 981 | "quote", 982 | "syn 2.0.22", 983 | ] 984 | 985 | [[package]] 986 | name = "openssl-sys" 987 | version = "0.9.90" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" 990 | dependencies = [ 991 | "cc", 992 | "libc", 993 | "pkg-config", 994 | "vcpkg", 995 | ] 996 | 997 | [[package]] 998 | name = "pin-project-lite" 999 | version = "0.2.9" 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" 1001 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1002 | 1003 | [[package]] 1004 | name = "pin-utils" 1005 | version = "0.1.0" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1008 | 1009 | [[package]] 1010 | name = "pkcs8" 1011 | version = "0.7.6" 1012 | source = "registry+https://github.com/rust-lang/crates.io-index" 1013 | checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" 1014 | dependencies = [ 1015 | "der", 1016 | "spki", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "pkg-config" 1021 | version = "0.3.27" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" 1024 | 1025 | [[package]] 1026 | name = "poly1305" 1027 | version = "0.6.2" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "4b7456bc1ad2d4cf82b3a016be4c2ac48daf11bf990c1603ebd447fe6f30fca8" 1030 | dependencies = [ 1031 | "cpuid-bool", 1032 | "universal-hash", 1033 | ] 1034 | 1035 | [[package]] 1036 | name = "polyval" 1037 | version = "0.4.5" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" 1040 | dependencies = [ 1041 | "cpuid-bool", 1042 | "opaque-debug 0.3.0", 1043 | "universal-hash", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "ppv-lite86" 1048 | version = "0.2.17" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1051 | 1052 | [[package]] 1053 | name = "proc-macro2" 1054 | version = "1.0.63" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" 1057 | dependencies = [ 1058 | "unicode-ident", 1059 | ] 1060 | 1061 | [[package]] 1062 | name = "quote" 1063 | version = "1.0.29" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" 1066 | dependencies = [ 1067 | "proc-macro2", 1068 | ] 1069 | 1070 | [[package]] 1071 | name = "rand" 1072 | version = "0.6.5" 1073 | source = "registry+https://github.com/rust-lang/crates.io-index" 1074 | checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 1075 | dependencies = [ 1076 | "autocfg 0.1.8", 1077 | "libc", 1078 | "rand_chacha 0.1.1", 1079 | "rand_core 0.4.2", 1080 | "rand_hc 0.1.0", 1081 | "rand_isaac", 1082 | "rand_jitter", 1083 | "rand_pcg", 1084 | "rand_xorshift", 1085 | "winapi", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "rand" 1090 | version = "0.7.3" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1093 | dependencies = [ 1094 | "getrandom 0.1.16", 1095 | "libc", 1096 | "rand_chacha 0.2.1", 1097 | "rand_core 0.5.1", 1098 | "rand_hc 0.2.0", 1099 | ] 1100 | 1101 | [[package]] 1102 | name = "rand_chacha" 1103 | version = "0.1.1" 1104 | source = "registry+https://github.com/rust-lang/crates.io-index" 1105 | checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 1106 | dependencies = [ 1107 | "autocfg 0.1.8", 1108 | "rand_core 0.3.1", 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "rand_chacha" 1113 | version = "0.2.1" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" 1116 | dependencies = [ 1117 | "c2-chacha", 1118 | "rand_core 0.5.1", 1119 | ] 1120 | 1121 | [[package]] 1122 | name = "rand_core" 1123 | version = "0.3.1" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 1126 | dependencies = [ 1127 | "rand_core 0.4.2", 1128 | ] 1129 | 1130 | [[package]] 1131 | name = "rand_core" 1132 | version = "0.4.2" 1133 | source = "registry+https://github.com/rust-lang/crates.io-index" 1134 | checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" 1135 | 1136 | [[package]] 1137 | name = "rand_core" 1138 | version = "0.5.1" 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" 1140 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1141 | dependencies = [ 1142 | "getrandom 0.1.16", 1143 | ] 1144 | 1145 | [[package]] 1146 | name = "rand_core" 1147 | version = "0.6.4" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1150 | dependencies = [ 1151 | "getrandom 0.2.10", 1152 | ] 1153 | 1154 | [[package]] 1155 | name = "rand_hc" 1156 | version = "0.1.0" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 1159 | dependencies = [ 1160 | "rand_core 0.3.1", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "rand_hc" 1165 | version = "0.2.0" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1168 | dependencies = [ 1169 | "rand_core 0.5.1", 1170 | ] 1171 | 1172 | [[package]] 1173 | name = "rand_isaac" 1174 | version = "0.1.1" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 1177 | dependencies = [ 1178 | "rand_core 0.3.1", 1179 | ] 1180 | 1181 | [[package]] 1182 | name = "rand_jitter" 1183 | version = "0.1.4" 1184 | source = "registry+https://github.com/rust-lang/crates.io-index" 1185 | checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" 1186 | dependencies = [ 1187 | "libc", 1188 | "rand_core 0.4.2", 1189 | "winapi", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "rand_pcg" 1194 | version = "0.1.2" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" 1197 | dependencies = [ 1198 | "autocfg 0.1.8", 1199 | "rand_core 0.4.2", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "rand_xorshift" 1204 | version = "0.1.1" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 1207 | dependencies = [ 1208 | "rand_core 0.3.1", 1209 | ] 1210 | 1211 | [[package]] 1212 | name = "rayon" 1213 | version = "1.7.0" 1214 | source = "registry+https://github.com/rust-lang/crates.io-index" 1215 | checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" 1216 | dependencies = [ 1217 | "either", 1218 | "rayon-core", 1219 | ] 1220 | 1221 | [[package]] 1222 | name = "rayon-core" 1223 | version = "1.11.0" 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" 1225 | checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" 1226 | dependencies = [ 1227 | "crossbeam-channel", 1228 | "crossbeam-deque", 1229 | "crossbeam-utils", 1230 | "num_cpus", 1231 | ] 1232 | 1233 | [[package]] 1234 | name = "rustc-demangle" 1235 | version = "0.1.23" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 1238 | 1239 | [[package]] 1240 | name = "ryu" 1241 | version = "1.0.13" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" 1244 | 1245 | [[package]] 1246 | name = "scopeguard" 1247 | version = "1.1.0" 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" 1249 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1250 | 1251 | [[package]] 1252 | name = "secp256k1" 1253 | version = "0.19.0" 1254 | source = "registry+https://github.com/rust-lang/crates.io-index" 1255 | checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb" 1256 | dependencies = [ 1257 | "rand 0.6.5", 1258 | "secp256k1-sys", 1259 | "serde", 1260 | ] 1261 | 1262 | [[package]] 1263 | name = "secp256k1-sys" 1264 | version = "0.3.0" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "11553d210db090930f4432bea123b31f70bbf693ace14504ea2a35e796c28dd2" 1267 | dependencies = [ 1268 | "cc", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "serde" 1273 | version = "1.0.164" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" 1276 | dependencies = [ 1277 | "serde_derive", 1278 | ] 1279 | 1280 | [[package]] 1281 | name = "serde_bytes" 1282 | version = "0.11.9" 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" 1284 | checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" 1285 | dependencies = [ 1286 | "serde", 1287 | ] 1288 | 1289 | [[package]] 1290 | name = "serde_derive" 1291 | version = "1.0.164" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" 1294 | dependencies = [ 1295 | "proc-macro2", 1296 | "quote", 1297 | "syn 2.0.22", 1298 | ] 1299 | 1300 | [[package]] 1301 | name = "serde_json" 1302 | version = "1.0.99" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" 1305 | dependencies = [ 1306 | "itoa", 1307 | "ryu", 1308 | "serde", 1309 | ] 1310 | 1311 | [[package]] 1312 | name = "sha2" 1313 | version = "0.9.9" 1314 | source = "registry+https://github.com/rust-lang/crates.io-index" 1315 | checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" 1316 | dependencies = [ 1317 | "block-buffer 0.9.0", 1318 | "cfg-if", 1319 | "cpufeatures", 1320 | "digest 0.9.0", 1321 | "opaque-debug 0.3.0", 1322 | ] 1323 | 1324 | [[package]] 1325 | name = "sha3" 1326 | version = "0.8.2" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" 1329 | dependencies = [ 1330 | "block-buffer 0.7.3", 1331 | "byte-tools", 1332 | "digest 0.8.1", 1333 | "keccak", 1334 | "opaque-debug 0.2.3", 1335 | ] 1336 | 1337 | [[package]] 1338 | name = "sha3" 1339 | version = "0.9.1" 1340 | source = "registry+https://github.com/rust-lang/crates.io-index" 1341 | checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" 1342 | dependencies = [ 1343 | "block-buffer 0.9.0", 1344 | "digest 0.9.0", 1345 | "keccak", 1346 | "opaque-debug 0.3.0", 1347 | ] 1348 | 1349 | [[package]] 1350 | name = "signature" 1351 | version = "1.3.2" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "f2807892cfa58e081aa1f1111391c7a0649d4fa127a4ffbe34bcbfb35a1171a4" 1354 | dependencies = [ 1355 | "digest 0.9.0", 1356 | "rand_core 0.6.4", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "slab" 1361 | version = "0.4.8" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" 1364 | dependencies = [ 1365 | "autocfg 1.1.0", 1366 | ] 1367 | 1368 | [[package]] 1369 | name = "socket2" 1370 | version = "0.4.9" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" 1373 | dependencies = [ 1374 | "libc", 1375 | "winapi", 1376 | ] 1377 | 1378 | [[package]] 1379 | name = "spki" 1380 | version = "0.4.1" 1381 | source = "registry+https://github.com/rust-lang/crates.io-index" 1382 | checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" 1383 | dependencies = [ 1384 | "der", 1385 | ] 1386 | 1387 | [[package]] 1388 | name = "state" 1389 | version = "0.1.0" 1390 | dependencies = [ 1391 | "blake2 0.10.6", 1392 | "serde", 1393 | "ursa", 1394 | ] 1395 | 1396 | [[package]] 1397 | name = "subtle" 1398 | version = "2.4.1" 1399 | source = "registry+https://github.com/rust-lang/crates.io-index" 1400 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" 1401 | 1402 | [[package]] 1403 | name = "subtle-encoding" 1404 | version = "0.5.1" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" 1407 | dependencies = [ 1408 | "zeroize", 1409 | ] 1410 | 1411 | [[package]] 1412 | name = "syn" 1413 | version = "1.0.109" 1414 | source = "registry+https://github.com/rust-lang/crates.io-index" 1415 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1416 | dependencies = [ 1417 | "proc-macro2", 1418 | "quote", 1419 | "unicode-ident", 1420 | ] 1421 | 1422 | [[package]] 1423 | name = "syn" 1424 | version = "2.0.22" 1425 | source = "registry+https://github.com/rust-lang/crates.io-index" 1426 | checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" 1427 | dependencies = [ 1428 | "proc-macro2", 1429 | "quote", 1430 | "unicode-ident", 1431 | ] 1432 | 1433 | [[package]] 1434 | name = "synstructure" 1435 | version = "0.12.6" 1436 | source = "registry+https://github.com/rust-lang/crates.io-index" 1437 | checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" 1438 | dependencies = [ 1439 | "proc-macro2", 1440 | "quote", 1441 | "syn 1.0.109", 1442 | "unicode-xid", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "thiserror" 1447 | version = "1.0.40" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" 1450 | dependencies = [ 1451 | "thiserror-impl", 1452 | ] 1453 | 1454 | [[package]] 1455 | name = "thiserror-impl" 1456 | version = "1.0.40" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" 1459 | dependencies = [ 1460 | "proc-macro2", 1461 | "quote", 1462 | "syn 2.0.22", 1463 | ] 1464 | 1465 | [[package]] 1466 | name = "time" 1467 | version = "0.1.45" 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" 1469 | checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" 1470 | dependencies = [ 1471 | "libc", 1472 | "wasi 0.10.0+wasi-snapshot-preview1", 1473 | "winapi", 1474 | ] 1475 | 1476 | [[package]] 1477 | name = "tokio" 1478 | version = "1.29.1" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" 1481 | dependencies = [ 1482 | "autocfg 1.1.0", 1483 | "backtrace", 1484 | "bytes 1.4.0", 1485 | "libc", 1486 | "mio", 1487 | "num_cpus", 1488 | "pin-project-lite", 1489 | "socket2", 1490 | "tokio-macros", 1491 | "windows-sys", 1492 | ] 1493 | 1494 | [[package]] 1495 | name = "tokio-io" 1496 | version = "0.1.13" 1497 | source = "registry+https://github.com/rust-lang/crates.io-index" 1498 | checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" 1499 | dependencies = [ 1500 | "bytes 0.4.12", 1501 | "futures 0.1.31", 1502 | "log", 1503 | ] 1504 | 1505 | [[package]] 1506 | name = "tokio-macros" 1507 | version = "2.1.0" 1508 | source = "registry+https://github.com/rust-lang/crates.io-index" 1509 | checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" 1510 | dependencies = [ 1511 | "proc-macro2", 1512 | "quote", 1513 | "syn 2.0.22", 1514 | ] 1515 | 1516 | [[package]] 1517 | name = "typenum" 1518 | version = "1.16.0" 1519 | source = "registry+https://github.com/rust-lang/crates.io-index" 1520 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1521 | 1522 | [[package]] 1523 | name = "unicode-ident" 1524 | version = "1.0.9" 1525 | source = "registry+https://github.com/rust-lang/crates.io-index" 1526 | checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" 1527 | 1528 | [[package]] 1529 | name = "unicode-xid" 1530 | version = "0.2.4" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 1533 | 1534 | [[package]] 1535 | name = "universal-hash" 1536 | version = "0.4.1" 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" 1538 | checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" 1539 | dependencies = [ 1540 | "generic-array 0.14.7", 1541 | "subtle", 1542 | ] 1543 | 1544 | [[package]] 1545 | name = "ursa" 1546 | version = "0.3.7" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "8760a62e18e4d3e3f599e15c09a9f9567fd9d4a90594d45166162be8d232e63b" 1549 | dependencies = [ 1550 | "aead", 1551 | "aes", 1552 | "aes-gcm", 1553 | "amcl", 1554 | "amcl_wrapper", 1555 | "arrayref", 1556 | "blake2 0.9.2", 1557 | "block-modes", 1558 | "block-padding 0.2.1", 1559 | "chacha20poly1305", 1560 | "curve25519-dalek", 1561 | "ed25519-dalek", 1562 | "failure", 1563 | "hex", 1564 | "hkdf", 1565 | "hmac", 1566 | "int_traits", 1567 | "k256", 1568 | "lazy_static", 1569 | "log", 1570 | "openssl", 1571 | "rand 0.7.3", 1572 | "rand_chacha 0.2.1", 1573 | "secp256k1", 1574 | "serde", 1575 | "sha2", 1576 | "sha3 0.9.1", 1577 | "subtle", 1578 | "time", 1579 | "x25519-dalek", 1580 | "zeroize", 1581 | ] 1582 | 1583 | [[package]] 1584 | name = "vcpkg" 1585 | version = "0.2.15" 1586 | source = "registry+https://github.com/rust-lang/crates.io-index" 1587 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1588 | 1589 | [[package]] 1590 | name = "version_check" 1591 | version = "0.9.4" 1592 | source = "registry+https://github.com/rust-lang/crates.io-index" 1593 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1594 | 1595 | [[package]] 1596 | name = "wasi" 1597 | version = "0.9.0+wasi-snapshot-preview1" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 1600 | 1601 | [[package]] 1602 | name = "wasi" 1603 | version = "0.10.0+wasi-snapshot-preview1" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 1606 | 1607 | [[package]] 1608 | name = "wasi" 1609 | version = "0.11.0+wasi-snapshot-preview1" 1610 | source = "registry+https://github.com/rust-lang/crates.io-index" 1611 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1612 | 1613 | [[package]] 1614 | name = "wasm-bindgen" 1615 | version = "0.2.87" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 1618 | dependencies = [ 1619 | "cfg-if", 1620 | "wasm-bindgen-macro", 1621 | ] 1622 | 1623 | [[package]] 1624 | name = "wasm-bindgen-backend" 1625 | version = "0.2.87" 1626 | source = "registry+https://github.com/rust-lang/crates.io-index" 1627 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 1628 | dependencies = [ 1629 | "bumpalo", 1630 | "log", 1631 | "once_cell", 1632 | "proc-macro2", 1633 | "quote", 1634 | "syn 2.0.22", 1635 | "wasm-bindgen-shared", 1636 | ] 1637 | 1638 | [[package]] 1639 | name = "wasm-bindgen-macro" 1640 | version = "0.2.87" 1641 | source = "registry+https://github.com/rust-lang/crates.io-index" 1642 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 1643 | dependencies = [ 1644 | "quote", 1645 | "wasm-bindgen-macro-support", 1646 | ] 1647 | 1648 | [[package]] 1649 | name = "wasm-bindgen-macro-support" 1650 | version = "0.2.87" 1651 | source = "registry+https://github.com/rust-lang/crates.io-index" 1652 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 1653 | dependencies = [ 1654 | "proc-macro2", 1655 | "quote", 1656 | "syn 2.0.22", 1657 | "wasm-bindgen-backend", 1658 | "wasm-bindgen-shared", 1659 | ] 1660 | 1661 | [[package]] 1662 | name = "wasm-bindgen-shared" 1663 | version = "0.2.87" 1664 | source = "registry+https://github.com/rust-lang/crates.io-index" 1665 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 1666 | 1667 | [[package]] 1668 | name = "winapi" 1669 | version = "0.3.9" 1670 | source = "registry+https://github.com/rust-lang/crates.io-index" 1671 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1672 | dependencies = [ 1673 | "winapi-i686-pc-windows-gnu", 1674 | "winapi-x86_64-pc-windows-gnu", 1675 | ] 1676 | 1677 | [[package]] 1678 | name = "winapi-i686-pc-windows-gnu" 1679 | version = "0.4.0" 1680 | source = "registry+https://github.com/rust-lang/crates.io-index" 1681 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1682 | 1683 | [[package]] 1684 | name = "winapi-x86_64-pc-windows-gnu" 1685 | version = "0.4.0" 1686 | source = "registry+https://github.com/rust-lang/crates.io-index" 1687 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1688 | 1689 | [[package]] 1690 | name = "windows-sys" 1691 | version = "0.48.0" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1694 | dependencies = [ 1695 | "windows-targets", 1696 | ] 1697 | 1698 | [[package]] 1699 | name = "windows-targets" 1700 | version = "0.48.1" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" 1703 | dependencies = [ 1704 | "windows_aarch64_gnullvm", 1705 | "windows_aarch64_msvc", 1706 | "windows_i686_gnu", 1707 | "windows_i686_msvc", 1708 | "windows_x86_64_gnu", 1709 | "windows_x86_64_gnullvm", 1710 | "windows_x86_64_msvc", 1711 | ] 1712 | 1713 | [[package]] 1714 | name = "windows_aarch64_gnullvm" 1715 | version = "0.48.0" 1716 | source = "registry+https://github.com/rust-lang/crates.io-index" 1717 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 1718 | 1719 | [[package]] 1720 | name = "windows_aarch64_msvc" 1721 | version = "0.48.0" 1722 | source = "registry+https://github.com/rust-lang/crates.io-index" 1723 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 1724 | 1725 | [[package]] 1726 | name = "windows_i686_gnu" 1727 | version = "0.48.0" 1728 | source = "registry+https://github.com/rust-lang/crates.io-index" 1729 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 1730 | 1731 | [[package]] 1732 | name = "windows_i686_msvc" 1733 | version = "0.48.0" 1734 | source = "registry+https://github.com/rust-lang/crates.io-index" 1735 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 1736 | 1737 | [[package]] 1738 | name = "windows_x86_64_gnu" 1739 | version = "0.48.0" 1740 | source = "registry+https://github.com/rust-lang/crates.io-index" 1741 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 1742 | 1743 | [[package]] 1744 | name = "windows_x86_64_gnullvm" 1745 | version = "0.48.0" 1746 | source = "registry+https://github.com/rust-lang/crates.io-index" 1747 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 1748 | 1749 | [[package]] 1750 | name = "windows_x86_64_msvc" 1751 | version = "0.48.0" 1752 | source = "registry+https://github.com/rust-lang/crates.io-index" 1753 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 1754 | 1755 | [[package]] 1756 | name = "x25519-dalek" 1757 | version = "1.2.0" 1758 | source = "registry+https://github.com/rust-lang/crates.io-index" 1759 | checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" 1760 | dependencies = [ 1761 | "curve25519-dalek", 1762 | "rand_core 0.5.1", 1763 | "zeroize", 1764 | ] 1765 | 1766 | [[package]] 1767 | name = "zeroize" 1768 | version = "1.3.0" 1769 | source = "registry+https://github.com/rust-lang/crates.io-index" 1770 | checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" 1771 | dependencies = [ 1772 | "zeroize_derive", 1773 | ] 1774 | 1775 | [[package]] 1776 | name = "zeroize_derive" 1777 | version = "1.4.2" 1778 | source = "registry+https://github.com/rust-lang/crates.io-index" 1779 | checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" 1780 | dependencies = [ 1781 | "proc-macro2", 1782 | "quote", 1783 | "syn 2.0.22", 1784 | ] 1785 | --------------------------------------------------------------------------------