From 5b856a8fdce778bb7062f657a75217cdfaea4b26 Mon Sep 17 00:00:00 2001 From: fi3 Date: Thu, 28 Mar 2024 19:20:04 +0100 Subject: [PATCH 01/39] Improve sv2 cpuminer Add a nicer user interface to the sv2 cpuminer with help messages. Add noise to the cpuminer. --- roles/Cargo.lock | 116 +++++++++++++++ roles/test-utils/mining-device/Cargo.toml | 4 + roles/test-utils/mining-device/src/main.rs | 158 +++++++++++++++++---- utils/key-utils/src/lib.rs | 2 + 4 files changed, 250 insertions(+), 30 deletions(-) diff --git a/roles/Cargo.lock b/roles/Cargo.lock index 67b803622..2289cf09a 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -78,6 +78,54 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "async-attributes" version = "1.1.2" @@ -506,6 +554,46 @@ dependencies = [ "zeroize", ] +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + [[package]] name = "codec_sv2" version = "1.0.1" @@ -519,6 +607,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "common_messages_sv2" version = "1.0.0" @@ -927,6 +1021,12 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1241,13 +1341,17 @@ dependencies = [ "async-std", "binary_sv2", "buffer_sv2", + "clap", "codec_sv2", "const_sv2", "futures", + "key-utils", "network_helpers_sv2", "rand", "roles_logic_sv2", "stratum-common", + "tracing", + "tracing-subscriber", ] [[package]] @@ -1917,6 +2021,12 @@ dependencies = [ "bitcoin", ] +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + [[package]] name = "subtle" version = "2.5.0" @@ -2200,6 +2310,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "valuable" version = "0.1.0" diff --git a/roles/test-utils/mining-device/Cargo.toml b/roles/test-utils/mining-device/Cargo.toml index f308cb146..263ddfbd4 100644 --- a/roles/test-utils/mining-device/Cargo.toml +++ b/roles/test-utils/mining-device/Cargo.toml @@ -19,3 +19,7 @@ buffer_sv2 = { version = "1.0.0", path = "../../../utils/buffer"} async-recursion = "0.3.2" rand = "0.8.4" futures = "0.3.5" +key-utils = { version = "^1.0.0", path = "../../../utils/key-utils" } +clap = { version = "^4.5.4", features = ["derive"] } +tracing = { version = "0.1" } +tracing-subscriber = "0.3" diff --git a/roles/test-utils/mining-device/src/main.rs b/roles/test-utils/mining-device/src/main.rs index a0cc047a2..13b941c95 100644 --- a/roles/test-utils/mining-device/src/main.rs +++ b/roles/test-utils/mining-device/src/main.rs @@ -1,35 +1,107 @@ use async_std::net::TcpStream; -use network_helpers_sv2::PlainConnection; +use key_utils::Secp256k1PublicKey; +use network_helpers_sv2::Connection; use roles_logic_sv2::utils::Id; -use std::{ - net::{IpAddr, Ipv4Addr, SocketAddr}, - sync::Arc, -}; +use std::{net::SocketAddr, sync::Arc, thread::sleep, time::Duration}; +use async_std::net::ToSocketAddrs; +use clap::Parser; use stratum_common::bitcoin::{ blockdata::block::BlockHeader, hash_types::BlockHash, hashes::Hash, util::uint::Uint256, }; +use tracing::{error, info}; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + #[arg( + short, + long, + help = "Pool pub key, when left empty the pool certificate is not checked" + )] + pubkey_pool: Option, + #[arg( + short, + long, + help = "Sometimes used by the pool to identify the device" + )] + id_device: Option, + #[arg( + short, + long, + help = "Address of the pool in this format ip:port or domain:port" + )] + address_pool: String, + #[arg( + long, + help = "This value is used to slow down the cpu miner, it rapresents the number of micro-seconds that are awaited between one hashes, default is 0", + default_value = "0" + )] + handicap: u32, +} -async fn connect(address: SocketAddr, handicap: u32) { - let stream = TcpStream::connect(address).await.unwrap(); +async fn connect( + address: String, + pub_key: Option, + device_id: Option, + handicap: u32, +) { + let address = address + .clone() + .to_socket_addrs() + .await + .expect("Invalid pool address, use one of this formats: ip:port, domain:port") + .next() + .expect("Invalid pool address, use one of this formats: ip:port, domain:port"); + info!("Connecting to pool at {}", address); + let socket = loop { + let pool = + async_std::future::timeout(Duration::from_secs(5), TcpStream::connect(address)).await; + match pool { + Ok(result) => match result { + Ok(socket) => break socket, + Err(e) => { + error!( + "Failed to connect to Upstream role at {}, retrying in 5s: {}", + address, e + ); + sleep(Duration::from_secs(5)); + } + }, + Err(_) => { + error!("Pool is unresponsive, terminating"); + std::process::exit(1); + } + } + }; + info!("Pool tcp connection established at {}", address); + let address = socket.peer_addr().unwrap(); + let initiator = Initiator::new(pub_key.map(|e| e.0)); let (receiver, sender): (Receiver, Sender) = - PlainConnection::new(stream, 10).await; - Device::start(receiver, sender, address, handicap).await + Connection::new(socket, codec_sv2::HandshakeRole::Initiator(initiator), 10) + .await + .unwrap(); + info!("Pool noise connection established at {}", address); + Device::start(receiver, sender, address, device_id, handicap).await } #[async_std::main] async fn main() { - let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 34255); - //task::spawn(async move { connect(socket, 10000).await }); - //task::spawn(async move { connect(socket, 11070).await }); - //task::spawn(async move { connect(socket, 7040).await }); - println!("start"); - connect(socket, 0).await + let args = Args::parse(); + tracing_subscriber::fmt::init(); + info!("start"); + connect( + args.address_pool, + args.pubkey_pool, + args.id_device, + args.handicap, + ) + .await } use async_channel::{Receiver, Sender}; use binary_sv2::u256_from_int; -use codec_sv2::{Frame, StandardEitherFrame, StandardSv2Frame}; +use codec_sv2::{Frame, Initiator, StandardEitherFrame, StandardSv2Frame}; use roles_logic_sv2::{ common_messages_sv2::{Protocol, SetupConnection, SetupConnectionSuccess}, common_properties::{IsMiningUpstream, IsUpstream}, @@ -56,12 +128,19 @@ impl SetupConnectionHandler { pub fn new() -> Self { SetupConnectionHandler {} } - fn get_setup_connection_message(address: SocketAddr) -> SetupConnection<'static> { + fn get_setup_connection_message( + address: SocketAddr, + device_id: Option, + ) -> SetupConnection<'static> { let endpoint_host = address.ip().to_string().into_bytes().try_into().unwrap(); let vendor = String::new().try_into().unwrap(); let hardware_version = String::new().try_into().unwrap(); let firmware = String::new().try_into().unwrap(); - let device_id = String::new().try_into().unwrap(); + let device_id = device_id.unwrap_or_default(); + info!( + "Creating SetupConnection message with device id: {:?}", + device_id + ); SetupConnection { protocol: Protocol::MiningProtocol, min_version: 2, @@ -72,22 +151,24 @@ impl SetupConnectionHandler { vendor, hardware_version, firmware, - device_id, + device_id: device_id.try_into().unwrap(), } } pub async fn setup( self_: Arc>, receiver: &mut Receiver, sender: &mut Sender, + device_id: Option, address: SocketAddr, ) { - let setup_connection = Self::get_setup_connection_message(address); + let setup_connection = Self::get_setup_connection_message(address, device_id); let sv2_frame: StdFrame = MiningDeviceMessages::Common(setup_connection.into()) .try_into() .unwrap(); let sv2_frame = sv2_frame.into(); sender.send(sv2_frame).await.unwrap(); + info!("Setup connection sent to {}", address); let mut incoming: StdFrame = receiver.recv().await.unwrap().try_into().unwrap(); let message_type = incoming.get_header().unwrap().msg_type(); @@ -108,6 +189,7 @@ impl ParseUpstreamCommonMessages for SetupConnectionHandler { _: SetupConnectionSuccess, ) -> Result { use roles_logic_sv2::handlers::common::SendTo; + info!("Setup connection success"); Ok(SendTo::None(None)) } @@ -115,6 +197,7 @@ impl ParseUpstreamCommonMessages for SetupConnectionHandler { &mut self, _: roles_logic_sv2::common_messages_sv2::SetupConnectionError, ) -> Result { + error!("Setup connection error"); todo!() } @@ -143,7 +226,7 @@ pub struct Device { fn open_channel() -> OpenStandardMiningChannel<'static> { let user_identity = "ABC".to_string().try_into().unwrap(); let id: u32 = 10; - println!("MINING DEVICE: send open channel with request id {}", id); + info!("MINING DEVICE: send open channel with request id {}", id); OpenStandardMiningChannel { request_id: id.into(), user_identity, @@ -157,11 +240,19 @@ impl Device { mut receiver: Receiver, mut sender: Sender, addr: SocketAddr, + device_id: Option, handicap: u32, ) { let setup_connection_handler = Arc::new(Mutex::new(SetupConnectionHandler::new())); - SetupConnectionHandler::setup(setup_connection_handler, &mut receiver, &mut sender, addr) - .await; + SetupConnectionHandler::setup( + setup_connection_handler, + &mut receiver, + &mut sender, + device_id, + addr, + ) + .await; + info!("Pool sv2 connection established at {}", addr); let miner = Arc::new(Mutex::new(Miner::new(handicap))); let self_ = Self { channel_opened: false, @@ -209,7 +300,7 @@ impl Device { loop { let mut incoming: StdFrame = receiver.recv().await.unwrap().try_into().unwrap(); - let message_type = incoming.get_header().unwrap().msg_type(); + let message_type = dbg!(incoming.get_header().unwrap().msg_type()); let payload = incoming.payload(); let next = Device::handle_message_mining( self_mutex.clone(), @@ -314,7 +405,7 @@ impl ParseUpstreamMiningMessages<(), NullDownstreamMiningSelector, NoRouting> fo self.channel_opened = true; self.channel_id = Some(m.channel_id); let req_id = m.get_request_id_as_u32(); - println!( + info!( "MINING DEVICE: channel opened with: group id {}, channel id {}, request id {}", m.group_channel_id, m.channel_id, req_id ); @@ -357,12 +448,12 @@ impl ParseUpstreamMiningMessages<(), NullDownstreamMiningSelector, NoRouting> fo &mut self, m: SubmitSharesSuccess, ) -> Result, Error> { - println!("SUCCESS {:?}", m); + info!("SUCCESS {:?}", m); Ok(SendTo::None(None)) } fn handle_submit_shares_error(&mut self, _: SubmitSharesError) -> Result, Error> { - println!("Submit shares error"); + info!("Submit shares error"); Ok(SendTo::None(None)) } @@ -425,8 +516,11 @@ impl ParseUpstreamMiningMessages<(), NullDownstreamMiningSelector, NoRouting> fo todo!() } - fn handle_set_target(&mut self, _: SetTarget) -> Result, Error> { - todo!() + fn handle_set_target(&mut self, m: SetTarget) -> Result, Error> { + self.miner + .safe_lock(|miner| miner.new_target(m.maximum_target.to_vec())) + .unwrap(); + Ok(SendTo::None(None)) } fn handle_reconnect(&mut self, _: Reconnect) -> Result, Error> { @@ -457,6 +551,10 @@ impl Miner { fn new_target(&mut self, mut target: Vec) { // target is sent in LE and comparisons in this file are done in BE target.reverse(); + let hex_string = target + .iter() + .fold("".to_string(), |acc, b| acc + format!("{:02x}", b).as_str()); + info!("Set target to {}", hex_string); self.target = Some(Uint256::from_be_bytes(target.try_into().unwrap())); } @@ -489,7 +587,7 @@ impl Miner { hash.reverse(); let hash = Uint256::from_be_bytes(hash); if hash < *self.target.as_ref().ok_or(())? { - println!( + info!( "Found share with nonce: {}, for target: {:?}, with hash: {:?}", header.nonce, self.target, hash, ); diff --git a/utils/key-utils/src/lib.rs b/utils/key-utils/src/lib.rs index fdfc0c7de..4cde25083 100644 --- a/utils/key-utils/src/lib.rs +++ b/utils/key-utils/src/lib.rs @@ -27,6 +27,8 @@ impl Display for Error { } } +impl std::error::Error for Error {} + impl From for Error { fn from(e: Bs58DecodeError) -> Self { Error::Bs58Decode(e) From 2c6fc333ad793917f51fcd95c27ad6b3e8c7ed45 Mon Sep 17 00:00:00 2001 From: fi3 Date: Fri, 29 Mar 2024 09:39:59 +0100 Subject: [PATCH 02/39] Add user identifier as cli arg --- roles/test-utils/mining-device/src/main.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/roles/test-utils/mining-device/src/main.rs b/roles/test-utils/mining-device/src/main.rs index 13b941c95..dcb36115f 100644 --- a/roles/test-utils/mining-device/src/main.rs +++ b/roles/test-utils/mining-device/src/main.rs @@ -34,16 +34,22 @@ struct Args { address_pool: String, #[arg( long, - help = "This value is used to slow down the cpu miner, it rapresents the number of micro-seconds that are awaited between one hashes, default is 0", + help = "This value is used to slow down the cpu miner, it rapresents the number of micro-seconds that are awaited between hashes", default_value = "0" )] handicap: u32, + #[arg( + long, + help = "User id, used when a new channel is opened, it can be used by the pool to identify the miner" + )] + id_user: Option, } async fn connect( address: String, pub_key: Option, device_id: Option, + user_id: Option, handicap: u32, ) { let address = address @@ -82,7 +88,7 @@ async fn connect( .await .unwrap(); info!("Pool noise connection established at {}", address); - Device::start(receiver, sender, address, device_id, handicap).await + Device::start(receiver, sender, address, device_id, user_id, handicap).await } #[async_std::main] @@ -94,6 +100,7 @@ async fn main() { args.address_pool, args.pubkey_pool, args.id_device, + args.id_user, args.handicap, ) .await @@ -223,8 +230,8 @@ pub struct Device { sequence_numbers: Id, } -fn open_channel() -> OpenStandardMiningChannel<'static> { - let user_identity = "ABC".to_string().try_into().unwrap(); +fn open_channel(device_id: Option) -> OpenStandardMiningChannel<'static> { + let user_identity = device_id.unwrap_or_default().try_into().unwrap(); let id: u32 = 10; info!("MINING DEVICE: send open channel with request id {}", id); OpenStandardMiningChannel { @@ -241,6 +248,7 @@ impl Device { mut sender: Sender, addr: SocketAddr, device_id: Option, + user_id: Option, handicap: u32, ) { let setup_connection_handler = Arc::new(Mutex::new(SetupConnectionHandler::new())); @@ -265,7 +273,7 @@ impl Device { sequence_numbers: Id::new(), }; let open_channel = - MiningDeviceMessages::Mining(Mining::OpenStandardMiningChannel(open_channel())); + MiningDeviceMessages::Mining(Mining::OpenStandardMiningChannel(open_channel(user_id))); let frame: StdFrame = open_channel.try_into().unwrap(); self_.sender.send(frame.into()).await.unwrap(); let self_mutex = std::sync::Arc::new(Mutex::new(self_)); From 9dd78b01d6c74432260951f0cb2faca9775c4650 Mon Sep 17 00:00:00 2001 From: fi3 Date: Tue, 2 Apr 2024 17:04:56 +0200 Subject: [PATCH 03/39] Add hashrate estimation for cpuminer --- roles/test-utils/mining-device/Cargo.toml | 1 + roles/test-utils/mining-device/src/main.rs | 51 ++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/roles/test-utils/mining-device/Cargo.toml b/roles/test-utils/mining-device/Cargo.toml index 263ddfbd4..41429d6a1 100644 --- a/roles/test-utils/mining-device/Cargo.toml +++ b/roles/test-utils/mining-device/Cargo.toml @@ -23,3 +23,4 @@ key-utils = { version = "^1.0.0", path = "../../../utils/key-utils" } clap = { version = "^4.5.4", features = ["derive"] } tracing = { version = "0.1" } tracing-subscriber = "0.3" +sha2 = "0.10.6" diff --git a/roles/test-utils/mining-device/src/main.rs b/roles/test-utils/mining-device/src/main.rs index dcb36115f..d2f9cfaf1 100644 --- a/roles/test-utils/mining-device/src/main.rs +++ b/roles/test-utils/mining-device/src/main.rs @@ -10,6 +10,9 @@ use stratum_common::bitcoin::{ blockdata::block::BlockHeader, hash_types::BlockHash, hashes::Hash, util::uint::Uint256, }; use tracing::{error, info}; +use std::time::Instant; +use rand::{Rng,thread_rng}; +use sha2::{Digest, Sha256}; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -107,7 +110,7 @@ async fn main() { } use async_channel::{Receiver, Sender}; -use binary_sv2::u256_from_int; +use binary_sv2::{u256_from_int, U256}; use codec_sv2::{Frame, Initiator, StandardEitherFrame, StandardSv2Frame}; use roles_logic_sv2::{ common_messages_sv2::{Protocol, SetupConnection, SetupConnectionSuccess}, @@ -233,11 +236,14 @@ pub struct Device { fn open_channel(device_id: Option) -> OpenStandardMiningChannel<'static> { let user_identity = device_id.unwrap_or_default().try_into().unwrap(); let id: u32 = 10; + info!("Misuring pc hashrate"); + let nominal_hash_rate = measure_hashrate(5) as f32; + info!("Pc hashrate is {}", nominal_hash_rate); info!("MINING DEVICE: send open channel with request id {}", id); OpenStandardMiningChannel { request_id: id.into(), user_identity, - nominal_hash_rate: 1000.0, // use 1000 or 10000 to test group channels + nominal_hash_rate, max_target: u256_from_int(567_u64), } } @@ -284,7 +290,9 @@ impl Device { let handicap = miner.safe_lock(|m| m.handicap).unwrap(); std::thread::spawn(move || loop { std::thread::sleep(std::time::Duration::from_micros(handicap.into())); - if miner.safe_lock(|m| m.next_share()).unwrap().is_ok() { + if miner.safe_lock(|m| { + m.next_share() + }).unwrap().is_ok() { let nonce = miner.safe_lock(|m| m.header.unwrap().nonce).unwrap(); let time = miner.safe_lock(|m| m.header.unwrap().time).unwrap(); let job_id = miner.safe_lock(|m| m.job_id).unwrap(); @@ -308,7 +316,7 @@ impl Device { loop { let mut incoming: StdFrame = receiver.recv().await.unwrap().try_into().unwrap(); - let message_type = dbg!(incoming.get_header().unwrap().msg_type()); + let message_type = incoming.get_header().unwrap().msg_type(); let payload = incoming.payload(); let next = Device::handle_message_mining( self_mutex.clone(), @@ -605,3 +613,38 @@ impl Miner { } } } + +// returns hashrate based on how fast the device hashes over the given duration +fn measure_hashrate(duration_secs: u64) -> f64 { + let mut share = generate_random_80_byte_array(); + let start_time = Instant::now(); + let mut hashes: u64 = 0; + let duration = Duration::from_secs(duration_secs); + + while start_time.elapsed() < duration { + for _ in 0..10000 { + hash(&mut share); + hashes += 1; + } + } + + let elapsed_secs = start_time.elapsed().as_secs_f64(); + let hashrate = hashes as f64 / elapsed_secs; + let nominal_hash_rate = hashrate; + nominal_hash_rate +} +fn generate_random_80_byte_array() -> [u8; 80] { + let mut rng = thread_rng(); + let mut arr = [0u8; 80]; + rng.fill(&mut arr[..]); + arr +} +fn hash(share: &mut [u8; 80]) -> Target { + let nonce: [u8; 8] = share[0..8].try_into().unwrap(); + let mut nonce = u64::from_le_bytes(nonce); + nonce += 1; + share[0..8].copy_from_slice(&nonce.to_le_bytes()); + let hash = Sha256::digest(&share).to_vec(); + let hash: U256<'static> = hash.try_into().unwrap(); + hash.into() +} From 8f1d8497aa5f21ec546f3bbcd1afb0bb5ead9504 Mon Sep 17 00:00:00 2001 From: fi3 Date: Fri, 5 Apr 2024 12:04:06 +0200 Subject: [PATCH 04/39] Fix fmt and clippy --- roles/Cargo.lock | 3 ++- roles/test-utils/mining-device/src/main.rs | 14 +++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/roles/Cargo.lock b/roles/Cargo.lock index 2289cf09a..ddd871240 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -585,7 +585,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -1349,6 +1349,7 @@ dependencies = [ "network_helpers_sv2", "rand", "roles_logic_sv2", + "sha2 0.10.8", "stratum-common", "tracing", "tracing-subscriber", diff --git a/roles/test-utils/mining-device/src/main.rs b/roles/test-utils/mining-device/src/main.rs index d2f9cfaf1..38a2f9a36 100644 --- a/roles/test-utils/mining-device/src/main.rs +++ b/roles/test-utils/mining-device/src/main.rs @@ -6,13 +6,13 @@ use std::{net::SocketAddr, sync::Arc, thread::sleep, time::Duration}; use async_std::net::ToSocketAddrs; use clap::Parser; +use rand::{thread_rng, Rng}; +use sha2::{Digest, Sha256}; +use std::time::Instant; use stratum_common::bitcoin::{ blockdata::block::BlockHeader, hash_types::BlockHash, hashes::Hash, util::uint::Uint256, }; use tracing::{error, info}; -use std::time::Instant; -use rand::{Rng,thread_rng}; -use sha2::{Digest, Sha256}; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -290,9 +290,7 @@ impl Device { let handicap = miner.safe_lock(|m| m.handicap).unwrap(); std::thread::spawn(move || loop { std::thread::sleep(std::time::Duration::from_micros(handicap.into())); - if miner.safe_lock(|m| { - m.next_share() - }).unwrap().is_ok() { + if miner.safe_lock(|m| m.next_share()).unwrap().is_ok() { let nonce = miner.safe_lock(|m| m.header.unwrap().nonce).unwrap(); let time = miner.safe_lock(|m| m.header.unwrap().time).unwrap(); let job_id = miner.safe_lock(|m| m.job_id).unwrap(); @@ -629,9 +627,7 @@ fn measure_hashrate(duration_secs: u64) -> f64 { } let elapsed_secs = start_time.elapsed().as_secs_f64(); - let hashrate = hashes as f64 / elapsed_secs; - let nominal_hash_rate = hashrate; - nominal_hash_rate + hashes as f64 / elapsed_secs } fn generate_random_80_byte_array() -> [u8; 80] { let mut rng = thread_rng(); From cd7d420854f4b71b398e12b613b18793b8a164cd Mon Sep 17 00:00:00 2001 From: Emmanuel chidera Date: Fri, 5 Apr 2024 12:51:26 +0100 Subject: [PATCH 05/39] Translators readme (#805) --- roles/translator/README.md | 41 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/roles/translator/README.md b/roles/translator/README.md index ce8a07582..e09e4fd30 100644 --- a/roles/translator/README.md +++ b/roles/translator/README.md @@ -1,4 +1,6 @@ + # SV1 to SV2 Translator Proxy + This proxy is designed to sit in between a SV1 Downstream role (most typically Mining Device(s) running SV1 firmware) and a SV2 Upstream role (most typically a SV2 Pool Server with Extended Channel support). @@ -20,36 +22,37 @@ The most typical high level configuration is: ``` ## Setup + ### Configuration File -The `proxy-config-example.toml` is a configuration example which can be copy/paste into `/conf` directory by the party that is running the Translator Proxy (most -typically the mining farm/miner hobbyist) to address the most preferred customization. + +`tproxy-config-local-jdc-example.toml` and `tproxy-config-local-pool-example.toml` are examples of configuration files for the Translator Proxy. The configuration file contains the following information: 1. The SV2 Upstream connection information which includes the SV2 Pool authority public key (`upstream_authority_pubkey`) and the SV2 Pool connection address (`upstream_address`) and port (`upstream_port`). -1. The SV1 Downstream connection information which includes the SV1 Mining Device address +2. The SV1 Downstream socket information which includes the listening IP address (`downstream_address`) and port (`downstream_port`). -1. The maximum and minimum SV2 versions (`max_supported_version` and `min_supported_version`) that +3. The maximum and minimum SRI versions (`max_supported_version` and `min_supported_version`) that the Translator Proxy implementer wants to support. Currently the only available version is `2`. -1. The desired minimum `extranonce2` size that the Translator Proxy implementer wants to use +4. The desired minimum `extranonce2` size that the Translator Proxy implementer wants to use (`min_extranonce2_size`). The `extranonce2` size is ultimately decided by the SV2 Upstream role, but if the specified size meets the SV2 Upstream role's requirements, the size specified in this configuration file should be favored. -1. The Job Declarator information which includes the Pool JD connection address (`jd_address`) and the Template Provider connection address to which to connect (`tp_address`). -1. The difficulty params such as the hashrate (hashes/s) of the weakest Mining Device that will be connecting to the Translator Proxy (`min_individual_miner_hashrate`), the number of shares needed before a mining.set_difficulty update (`miner_num_submits_before_update`) and the number of shares per minute that Mining Devices should be sending to the Translator Proxy (`shares_per_minute`). Ultimately, the estimated aggregate hashrate of all SV1 Downstream roles (Mining - Devices) (`channel_nominal_hashrate`), which is communicated to the SV2 Upstream to help it decide a proper difficulty target. +5. The downstream difficulty params such as: +- the hashrate (hashes/s) of the weakest Mining Device that will be connecting to the Translator Proxy (`min_individual_miner_hashrate`) +- the number of shares per minute that Mining Devices should be sending to the Translator Proxy (`shares_per_minute`). +6. The upstream difficulty params such as: +- the interval in seconds to elapse before updating channel hashrate with the pool (`channel_diff_update_interval`) +- the estimated aggregate hashrate of all SV1 Downstream roles (`channel_nominal_hashrate`) ### Run -1. Copy the `proxy-config-example.toml` into `conf/` directory. -2. Edit it with custom desired configuration and rename it `proxy-config.toml` -3. Point the SV1 Downstream Mining Device(s) to the Translator Proxy IP address and port. -4. Run the Translator Proxy: - - ``` - cd roles/translator - ``` - ``` - cargo run -p translator_sv2 -- -c conf/proxy-config.toml - ``` + +There are two files in `roles/translator/config-examples`: +- `tproxy-config-local-jdc-example.toml` which assumes the Job Declaration protocol is used and a JD Client is deployed locally +- `tproxy-config-local-pool-example.toml` which assumes Job Declaration protocol is NOT used, and a Pool is deployed locally + +```bash +cd roles/translator/config-examples/ +cargo run -- -c tproxy-config-local-jdc-example.toml \ No newline at end of file From a94ac3495e5fd84c0647910142e393067a65f09a Mon Sep 17 00:00:00 2001 From: Emmanuel chidera Date: Fri, 5 Apr 2024 14:21:38 +0100 Subject: [PATCH 06/39] modified the README in roles/pool dir (#802) --- roles/pool/README.md | 60 ++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/roles/pool/README.md b/roles/pool/README.md index 5d7bd5b50..1e608b80d 100644 --- a/roles/pool/README.md +++ b/roles/pool/README.md @@ -1,4 +1,6 @@ + # SRI Pool + SRI Pool is designed to communicate with Downstream role (most typically a Translator Proxy or a Mining Proxy) running SV2 protocol to exploit features introduced by its sub-protocols. The most typical high level configuration is: @@ -18,47 +20,35 @@ The most typical high level configuration is: ``` ## Setup + ### Configuration File -The `pool-config-example.toml` is a configuration example which can be copy/paste into `/conf` directory by the party that is running the SV2 Pool (most -typically the pool service provider) to address the most preferred customization. + +`pool-config-hosted-tp-example.toml` and `pool-config-local-tp-example.toml` are examples of configuration files. The configuration file contains the following information: -1. The SRI Pool information which includes the SRI Pool authority public key - (`authority_pubkey`), the SRI Pool authority secret key (`authority_secret_key`), along with its certificate validity (`cert_validity_sec`). In addition to this, it contains the address which it will use to listen to new connection from downstream roles (`listen_address`) and the list of uncompressed pubkeys for coinbase payout (`coinbase_outputs`). -2. The SRI Pool Job Negatiator information which includes the Template Provider address (`tp_address`) and the address it uses to listen new request from the downstream JDs (`jd_address`). -3. Optionally, you may want to verify that your TP connection is authentic. You may get `tp_authority_public_key` from the logs of your TP, for example: +1. The SRI Pool information which includes the SRI Pool authority public key + (`authority_public_key`), the SRI Pool authority secret key (`authority_secret_key`). +2. The address which it will use to listen to new connection from downstream roles (`listen_address`) +3. The list of uncompressed pubkeys for coinbase payout (`coinbase_outputs`) +4. A string that serves as signature on the coinbase tx (`pool_signature`). +5. The Template Provider address (`tp_address`). +6. Optionally, you may want to verify that your TP connection is authentic. You may get `tp_authority_public_key` from the logs of your TP, for example: + ``` # 2024-02-13T14:59:24Z Template Provider authority key: EguTM8URcZDQVeEBsM4B5vg9weqEUnufA8pm85fG4bZd ``` ### Run -1. Copy the `pool-config-example.toml` into `conf/` directory. -2. Edit it with custom desired configuration and rename it `pool-config.toml` - > **Warning**
- > If you want to mine spendable bitcoin on regtest, you can do it with bitcoin-cli: - > 1. Get a legacy Bitcoin address: - > ``` - > bitcoin-cli -regtest -rpcwallet="" getnewaddress "test" "legacy" - > ``` - > 2. Retrieve its corresponding public key: - > ``` - > bitcoin-cli -regtest getaddressinfo - > ``` - > 3. Copy the pubkey showed in the output - > 4. Paste it in the `coinbase_outputs` of `pool-config.toml`, after deleting the one which is already present - > 5. Mine a block - > 6. Generate 100 blocks - > ``` - > bitcoin-cli -regtest generatetoaddress 100 bcrt1qc5xss0cma0zldxfzzdpjxsayut7yy86e2lr6km - > ``` - > Now the mined bitcoin are spendable! - -3. Run the Pool: - - ``` - cd roles/v2/pool - ``` - ``` - cargo run -p pool_sv2 -- -c conf/pool-config.toml - ``` \ No newline at end of file + +There are two files found in `roles/pool/config-examples` + +1. `pool-config-hosted-tp-example.toml` runs on our community hosted server. +2. `pool-config-example-tp-example.toml` runs with your local config. + +Run the Pool: + +```bash +cd roles/pool/config-examples +cargo run -- -c pool-config-hosted-tp-example.toml +``` From 062edbc8b67db912b55d0925aa9a2495307a5b63 Mon Sep 17 00:00:00 2001 From: Emmanuel chidera Date: Fri, 5 Apr 2024 21:21:04 +0100 Subject: [PATCH 07/39] JD Client README file retouched (#800) --- roles/jd-client/README.md | 46 ++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/roles/jd-client/README.md b/roles/jd-client/README.md index efc5d8d2a..18ab95197 100644 --- a/roles/jd-client/README.md +++ b/roles/jd-client/README.md @@ -1,38 +1,34 @@ # JD Client -The JD Client is a Sv2 proxy that support one extended channel upstream and one extended channel -dowstream, and do job declaration. On start it will: + * connect to the jd-server * connect to the template-provider -* listen for and `OpenExtendedChannel` from downstream +The JD Client receives custom block templates from a Template Provider and declares use of the template with the pool using the Job Declaration Protocol. Further distributes the jobs to Mining Proxy (or Proxies) using the Job Distribution Protocol. ``` * transparently relay the `OpenExtendedChannel` to upstream -After the setup phase it will start to negotiate jobs with upstream and send the negotiated job -downstream, so that everything that is dowstream do not need to know that job is negotiated. ## Setup + ### Configuration File -The `proxy-config-example.toml` is a configuration example. The configuration file contains the following information: -1. The Upstream connection information which includes the SV2 Pool authority public key - (`upstream_authority_pubkey`) and the SV2 Pool connection address (`upstream_address`) and port - (`upstream_port`). -2. The maximum and minimum SV2 versions (`max_supported_version` and `min_supported_version`) -3. The Job Declarator information which includes the Pool JD connection address (`jd_address`) and the Template Provider connection address to which to connect (`tp_address`). -4. Optionally, you may want to verify that your TP connection is authentic. You may get `tp_authority_public_key` from the logs of your TP, for example: -``` +1. The downstream socket information, which includes the listening IP address (`downstream_address`) and port (`downstream_port`). +2. The maximum and minimum SRI versions (`max_supported_version` and `min_supported_version`) with size as (`min_extranonce2_size`) +3. The authentication keys for the downstream connection (`authority_public_key`, `authority_secret_key`) +4. A `retry` parameter which tells JDC the number of times to reinitialize itself after a failure. +6. The Template Provider address (`tp_address`). +7. Optionally, you may want to verify that your TP connection is authentic. You may get `tp_authority_public_key` from the logs of your TP, for example: + # 2024-02-13T14:59:24Z Template Provider authority key: EguTM8URcZDQVeEBsM4B5vg9weqEUnufA8pm85fG4bZd -``` ### Run -1. Copy the `jdc-config-example.toml` into `conf/` directory. -2. Edit it with custom desired configuration and rename it `jdc-config.toml` -3. Point the SV1 Downstream Mining Device(s) to the Translator Proxy IP address and port. -4. Run the Translator Proxy: - - ``` - cd roles/translator - ``` - ``` - cargo run -p translator_sv2 -- -c conf/jdc-config.toml - ``` + +Run the Job Declarator Client (JDC): +There are two files when you cd into roles/jd-client/config-examples/ + +1. `jdc-config-hosted-example.toml` connects to the community-hosted roles. +2. `jdc-config-local-example.toml` connects to self-hosted Job Declarator Client (JDC) and Translator Proxy + +``` bash +cd roles/jd-client/config-examples/ +cargo run -- -c jdc-config-hosted-example.toml +``` From 2ecc9cb03c6dbc828ef7080d5c6e9f112a905cd8 Mon Sep 17 00:00:00 2001 From: fi3 Date: Sat, 6 Apr 2024 11:37:24 +0200 Subject: [PATCH 08/39] Fix typo --- roles/test-utils/mining-device/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/test-utils/mining-device/src/main.rs b/roles/test-utils/mining-device/src/main.rs index 38a2f9a36..befd7edff 100644 --- a/roles/test-utils/mining-device/src/main.rs +++ b/roles/test-utils/mining-device/src/main.rs @@ -236,7 +236,7 @@ pub struct Device { fn open_channel(device_id: Option) -> OpenStandardMiningChannel<'static> { let user_identity = device_id.unwrap_or_default().try_into().unwrap(); let id: u32 = 10; - info!("Misuring pc hashrate"); + info!("Measuring pc hashrate"); let nominal_hash_rate = measure_hashrate(5) as f32; info!("Pc hashrate is {}", nominal_hash_rate); info!("MINING DEVICE: send open channel with request id {}", id); From 1e4552e201c5adb4c29d47fa408ebf4c0f642bb9 Mon Sep 17 00:00:00 2001 From: fi3 Date: Thu, 28 Mar 2024 19:20:04 +0100 Subject: [PATCH 09/39] Improve sv2 cpuminer Add a nicer user interface to the sv2 cpuminer with help messages. Add noise to the cpuminer. --- roles/Cargo.lock | 38 +++++++++++++++++++++++ roles/test-utils/mining-device/Cargo.toml | 1 - 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/roles/Cargo.lock b/roles/Cargo.lock index ddd871240..b77aa493b 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -576,6 +576,44 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "codec_sv2" +version = "1.0.0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + [[package]] name = "clap_derive" version = "4.5.4" diff --git a/roles/test-utils/mining-device/Cargo.toml b/roles/test-utils/mining-device/Cargo.toml index 41429d6a1..263ddfbd4 100644 --- a/roles/test-utils/mining-device/Cargo.toml +++ b/roles/test-utils/mining-device/Cargo.toml @@ -23,4 +23,3 @@ key-utils = { version = "^1.0.0", path = "../../../utils/key-utils" } clap = { version = "^4.5.4", features = ["derive"] } tracing = { version = "0.1" } tracing-subscriber = "0.3" -sha2 = "0.10.6" From 51e14f97f830a2cef5750ab8c03f48395efb4f12 Mon Sep 17 00:00:00 2001 From: fi3 Date: Fri, 5 Apr 2024 12:04:06 +0200 Subject: [PATCH 10/39] Fix fmt and clippy --- roles/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/Cargo.lock b/roles/Cargo.lock index b77aa493b..761115490 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -585,7 +585,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.55", ] [[package]] @@ -596,7 +596,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "codec_sv2" -version = "1.0.0" +version = "1.0.1" dependencies = [ "clap_builder", "clap_derive", From 71443c862ac517c2d3ffed9031faf988ea550dbb Mon Sep 17 00:00:00 2001 From: Vasu Khanna <117103753+star-gazer111@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:54:16 +0530 Subject: [PATCH 11/39] Update proxy-config-example.toml --- roles/mining-proxy/config-examples/proxy-config-example.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/mining-proxy/config-examples/proxy-config-example.toml b/roles/mining-proxy/config-examples/proxy-config-example.toml index 35d3917dd..6766f82d6 100644 --- a/roles/mining-proxy/config-examples/proxy-config-example.toml +++ b/roles/mining-proxy/config-examples/proxy-config-example.toml @@ -6,7 +6,6 @@ listen_mining_port = 34255 max_supported_version = 2 min_supported_version = 2 downstream_share_per_minute = 1 -coinbase_reward_sat = 5_000_000_000 # This value is used by the proxy to communicate to the pool the expected hash rate when we open an # extended channel, based on it the pool will set a target for the channel expected_total_downstream_hr = 10_000 From 7ca9fbce0b861e178907c2fe8c2b2c2a846a29dc Mon Sep 17 00:00:00 2001 From: Vasu Khanna <117103753+star-gazer111@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:54:37 +0530 Subject: [PATCH 12/39] Update pool-config-local-tp-example.toml --- roles/pool/config-examples/pool-config-local-tp-example.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/pool/config-examples/pool-config-local-tp-example.toml b/roles/pool/config-examples/pool-config-local-tp-example.toml index 016c372f5..edc69b3c1 100644 --- a/roles/pool/config-examples/pool-config-local-tp-example.toml +++ b/roles/pool/config-examples/pool-config-local-tp-example.toml @@ -1,7 +1,6 @@ # SRI Pool config authority_public_key = "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72" authority_secret_key = "mkDLTBBRxdBv998612qipDYoTK3YUrqLe8uWw7gu3iXbSrn2n" -#authority_secret_key = "7qbpUjScc865jyX2kiB4NVJANoC7GA7TAJupdzXWkc62" cert_validity_sec = 3600 test_only_listen_adress_plain = "0.0.0.0:34250" listen_address = "0.0.0.0:34254" From 821a0e07353e5d3d17a63f812ab223f98a8ce9ea Mon Sep 17 00:00:00 2001 From: Vasu Khanna <117103753+star-gazer111@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:54:56 +0530 Subject: [PATCH 13/39] Update tproxy-config-local-jdc-example.toml --- .../config-examples/tproxy-config-local-jdc-example.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/translator/config-examples/tproxy-config-local-jdc-example.toml b/roles/translator/config-examples/tproxy-config-local-jdc-example.toml index a8bc389aa..5fe4a8eeb 100644 --- a/roles/translator/config-examples/tproxy-config-local-jdc-example.toml +++ b/roles/translator/config-examples/tproxy-config-local-jdc-example.toml @@ -21,7 +21,6 @@ min_supported_version = 2 # Max value for CGminer: 8 # Min value: 2 min_extranonce2_size = 8 -coinbase_reward_sat = 5_000_000_000 # Difficulty params [downstream_difficulty_config] From 00a2038827da1d121525d5935360eebb6ea6b982 Mon Sep 17 00:00:00 2001 From: Vasu Khanna <117103753+star-gazer111@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:55:10 +0530 Subject: [PATCH 14/39] Update tproxy-config-local-pool-example.toml --- .../config-examples/tproxy-config-local-pool-example.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/translator/config-examples/tproxy-config-local-pool-example.toml b/roles/translator/config-examples/tproxy-config-local-pool-example.toml index d963ec945..b4359d5ab 100644 --- a/roles/translator/config-examples/tproxy-config-local-pool-example.toml +++ b/roles/translator/config-examples/tproxy-config-local-pool-example.toml @@ -21,7 +21,6 @@ min_supported_version = 2 # Max value for CGminer: 8 # Min value: 2 min_extranonce2_size = 8 -coinbase_reward_sat = 5_000_000_000 # Difficulty params [downstream_difficulty_config] From 8981a2544207ac1269c73c142df5b28af373fc63 Mon Sep 17 00:00:00 2001 From: fi3 Date: Fri, 3 May 2024 12:36:16 +0200 Subject: [PATCH 15/39] Fix roles add error en no config file --- roles/Cargo.lock | 318 ++++++++++++++++------------------- roles/jd-client/src/args.rs | 11 +- roles/translator/src/args.rs | 11 +- 3 files changed, 165 insertions(+), 175 deletions(-) diff --git a/roles/Cargo.lock b/roles/Cargo.lock index 761115490..2d2cf18a9 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -80,47 +80,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -149,13 +150,13 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" dependencies = [ "concurrent-queue", - "event-listener 5.2.0", - "event-listener-strategy 0.5.0", + "event-listener 5.3.0", + "event-listener-strategy 0.5.2", "futures-core", "pin-project-lite", ] @@ -175,14 +176,13 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-lite 2.3.0", "slab", ] @@ -193,7 +193,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.2.0", + "async-channel 2.2.1", "async-executor", "async-io 2.3.2", "async-lock 3.3.0", @@ -234,8 +234,8 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.6.0", - "rustix 0.38.32", + "polling 3.7.0", + "rustix 0.38.34", "slab", "tracing", "windows-sys 0.52.0", @@ -274,13 +274,13 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", ] [[package]] @@ -312,9 +312,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "atomic-waker" @@ -458,18 +458,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" dependencies = [ - "async-channel 2.2.0", + "async-channel 2.2.1", "async-lock 3.3.0", "async-task", - "fastrand 2.0.2", "futures-io", "futures-lite 2.3.0", "piper", - "tracing", ] [[package]] @@ -491,9 +489,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -509,9 +507,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.90" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" [[package]] name = "cfg-if" @@ -585,45 +583,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.55", -] - -[[package]] -name = "clap_lex" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" - -[[package]] -name = "codec_sv2" -version = "1.0.1" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.55", + "syn 2.0.60", ] [[package]] @@ -647,9 +607,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "common_messages_sv2" @@ -661,9 +621,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -788,9 +748,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" dependencies = [ "concurrent-queue", "parking", @@ -809,11 +769,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 5.2.0", + "event-listener 5.3.0", "pin-project-lite", ] @@ -828,9 +788,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fnv" @@ -917,7 +877,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-core", "futures-io", "parking", @@ -932,7 +892,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", ] [[package]] @@ -977,9 +937,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", @@ -1016,9 +976,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" dependencies = [ "bytes", "fnv", @@ -1055,9 +1015,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" @@ -1149,9 +1109,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -1181,7 +1141,7 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", "tower", "tower-service", @@ -1195,7 +1155,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1227,6 +1187,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itoa" version = "1.0.11" @@ -1329,9 +1295,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "linux-raw-sys" @@ -1347,9 +1313,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1387,7 +1353,6 @@ dependencies = [ "network_helpers_sv2", "rand", "roles_logic_sv2", - "sha2 0.10.8", "stratum-common", "tracing", "tracing-subscriber", @@ -1562,9 +1527,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -1572,15 +1537,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -1600,14 +1565,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1622,7 +1587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" dependencies = [ "atomic-waker", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-io", ] @@ -1644,15 +1609,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi 0.3.9", "pin-project-lite", - "rustix 0.38.32", + "rustix 0.38.34", "tracing", "windows-sys 0.52.0", ] @@ -1685,7 +1650,7 @@ name = "pool_sv2" version = "0.1.0" dependencies = [ "async-channel 1.9.0", - "async-recursion 1.1.0", + "async-recursion 1.1.1", "binary_sv2", "buffer_sv2", "codec_sv2", @@ -1725,9 +1690,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -1740,9 +1705,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1779,11 +1744,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] @@ -1869,9 +1834,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -1933,29 +1898,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -2005,9 +1970,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2045,9 +2010,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2062,9 +2027,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -2115,9 +2080,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.55" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -2165,7 +2130,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.6", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", ] @@ -2178,7 +2143,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", ] [[package]] @@ -2252,7 +2217,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", ] [[package]] @@ -2363,9 +2328,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74797339c3b98616c009c7c3eb53a0ce41e85c8ec66bd3db96ed132d20cfdee8" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" [[package]] name = "version_check" @@ -2415,7 +2380,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -2449,7 +2414,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2488,11 +2453,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2516,7 +2481,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -2536,17 +2501,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -2557,9 +2523,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -2569,9 +2535,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -2581,9 +2547,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -2593,9 +2565,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -2605,9 +2577,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -2617,9 +2589,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -2629,9 +2601,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "zeroize" diff --git a/roles/jd-client/src/args.rs b/roles/jd-client/src/args.rs index 65328de58..7802351c3 100644 --- a/roles/jd-client/src/args.rs +++ b/roles/jd-client/src/args.rs @@ -44,7 +44,16 @@ impl Args { Some(ArgsResult::None) } }, - ArgsState::ExpectPath => Some(ArgsResult::Config(PathBuf::from(item))), + ArgsState::ExpectPath => { + let path = PathBuf::from(item.clone()); + if !path.exists() { + return Some(ArgsResult::Help(format!( + "Error: File '{}' does not exist!", + path.display() + ))); + } + Some(ArgsResult::Config(path)) + } ArgsState::Done => None, } }) diff --git a/roles/translator/src/args.rs b/roles/translator/src/args.rs index e2f8d4df9..bf5e51c19 100644 --- a/roles/translator/src/args.rs +++ b/roles/translator/src/args.rs @@ -44,7 +44,16 @@ impl Args { Some(ArgsResult::None) } }, - ArgsState::ExpectPath => Some(ArgsResult::Config(PathBuf::from(item))), + ArgsState::ExpectPath => { + let path = PathBuf::from(item.clone()); + if !path.exists() { + return Some(ArgsResult::Help(format!( + "Error: File '{}' does not exist!", + path.display() + ))); + } + Some(ArgsResult::Config(path)) + } ArgsState::Done => None, } }) From f2913e8269f6d5c60164dcbf77f80e880a2c76b8 Mon Sep 17 00:00:00 2001 From: fi3 Date: Fri, 3 May 2024 12:38:54 +0200 Subject: [PATCH 16/39] Fix tproxy panic when no config --- roles/translator/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/translator/src/main.rs b/roles/translator/src/main.rs index 84acbdbba..c1307a5a2 100644 --- a/roles/translator/src/main.rs +++ b/roles/translator/src/main.rs @@ -41,7 +41,7 @@ async fn main() { let proxy_config = match process_cli_args() { Ok(p) => p, - Err(_) => return, + Err(e) => panic!("failed to load config: {}", e), }; info!("PC: {:?}", &proxy_config); From 214b227adeae56761bf5a78211d1629667f8700d Mon Sep 17 00:00:00 2001 From: fi3 Date: Fri, 3 May 2024 12:44:27 +0200 Subject: [PATCH 17/39] Add support for ARM binaries --- .github/workflows/release-bin.yaml | 149 ++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-bin.yaml b/.github/workflows/release-bin.yaml index 253554eb4..a6585a27f 100644 --- a/.github/workflows/release-bin.yaml +++ b/.github/workflows/release-bin.yaml @@ -20,10 +20,21 @@ jobs: with: toolchain: stable override: true - + - name: Compile Native run: cargo build --release --locked --manifest-path=roles/pool/Cargo.toml + - name: Install cross + run: cargo install cross + + - name: Compile Binaries for aarch64-unknown-linux-gnu + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/pool/Cargo.toml --target aarch64-unknown-linux-gnu + + - name: Compile Binaries for arm-unknown-linux-gnueabi + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/pool/Cargo.toml --target arm-unknown-linux-gnueabi + - name: Install aarch64-apple-darwin target if: matrix.os == 'macos-latest' run: rustup target add aarch64-apple-darwin @@ -49,6 +60,24 @@ jobs: file: roles/target/release/pool_sv2 asset_name: pool_sv2-x86_64-apple-darwin tag: ${{ github.ref }} + + - name: Upload Linux aarch64 binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/aarch64-unknown-linux-gnu/release/pool_sv2 + asset_name: pool_sv2-aarch64-linux-gnu + tag: ${{ github.ref }} + + - name: Upload Linux ARM binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/arm-unknown-linux-gnueabi/release/pool_sv2 + asset_name: pool_sv2-arm-linux-gnueabi + tag: ${{ github.ref }} - name: Upload MacOS ARM64 binaries to release if: matrix.os == 'macos-latest' @@ -73,6 +102,17 @@ jobs: - name: Compile Native run: cargo build --release --locked --manifest-path=roles/jd-client/Cargo.toml + + - name: Install cross + run: cargo install cross + + - name: Compile Binaries for aarch64-unknown-linux-gnu + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/jd-client/Cargo.toml --target aarch64-unknown-linux-gnu + + - name: Compile Binaries for arm-unknown-linux-gnueabi + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/jd-client/Cargo.toml --target arm-unknown-linux-gnueabi - name: Install aarch64-apple-darwin target if: matrix.os == 'macos-latest' @@ -90,6 +130,24 @@ jobs: file: roles/target/release/jd_client asset_name: jd_client-x86_64-linux-gnu tag: ${{ github.ref }} + + - name: Upload Linux aarch64 binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/aarch64-unknown-linux-gnu/release/jd_client + asset_name: jd_client-aarch64-linux-gnu + tag: ${{ github.ref }} + + - name: Upload Linux ARM binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/arm-unknown-linux-gnueabi/release/jd_client + asset_name: jd_client-arm-linux-gnueabi + tag: ${{ github.ref }} - name: Upload MacOS x86-64 binaries to release if: matrix.os == 'macos-latest' @@ -123,6 +181,17 @@ jobs: - name: Compile Native run: cargo build --release --locked --manifest-path=roles/jd-server/Cargo.toml + + - name: Install cross + run: cargo install cross + + - name: Compile Binaries for aarch64-unknown-linux-gnu + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/jd-server/Cargo.toml --target aarch64-unknown-linux-gnu + + - name: Compile Binaries for arm-unknown-linux-gnueabi + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/jd-server/Cargo.toml --target arm-unknown-linux-gnueabi - name: Install aarch64-apple-darwin target if: matrix.os == 'macos-latest' @@ -140,6 +209,24 @@ jobs: file: roles/target/release/jd_server asset_name: jd_server-x86_64-linux-gnu tag: ${{ github.ref }} + + - name: Upload Linux aarch64 binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/aarch64-unknown-linux-gnu/release/jd_server + asset_name: jd_server-aarch64-linux-gnu + tag: ${{ github.ref }} + + - name: Upload Linux ARM binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/arm-unknown-linux-gnueabi/release/jd_server + asset_name: jd_server-arm-linux-gnueabi + tag: ${{ github.ref }} - name: Upload MacOS x86-64 binaries to release if: matrix.os == 'macos-latest' @@ -173,6 +260,17 @@ jobs: - name: Compile Native run: cargo build --release --locked --manifest-path=roles/mining-proxy/Cargo.toml + + - name: Install cross + run: cargo install cross + + - name: Compile Binaries for aarch64-unknown-linux-gnu + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/mining-proxy/Cargo.toml --target aarch64-unknown-linux-gnu + + - name: Compile Binaries for arm-unknown-linux-gnueabi + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/mining-proxy/Cargo.toml --target arm-unknown-linux-gnueabi - name: Install aarch64-apple-darwin target if: matrix.os == 'macos-latest' @@ -190,6 +288,24 @@ jobs: file: roles/target/release/mining_proxy_sv2 asset_name: mining_proxy_sv2-x86_64-linux-gnu tag: ${{ github.ref }} + + - name: Upload Linux aarch64 binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/aarch64-unknown-linux-gnu/release/mining_proxy_sv2 + asset_name: mining_proxy_sv2-aarch64-linux-gnu + tag: ${{ github.ref }} + + - name: Upload Linux ARM binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/arm-unknown-linux-gnueabi/release/mining_proxy_sv2 + asset_name: mining_proxy_sv2-arm-linux-gnueabi + tag: ${{ github.ref }} - name: Upload MacOS x86-64 binaries to release if: matrix.os == 'macos-latest' @@ -223,6 +339,17 @@ jobs: - name: Compile Native run: cargo build --release --locked --manifest-path=roles/translator/Cargo.toml + + - name: Install cross + run: cargo install cross + + - name: Compile Binaries for aarch64-unknown-linux-gnu + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/translator/Cargo.toml --target aarch64-unknown-linux-gnu + + - name: Compile Binaries for arm-unknown-linux-gnueabi + if: matrix.os == 'ubuntu-20.04' + run: cross build --release --locked --manifest-path=roles/translator/Cargo.toml --target arm-unknown-linux-gnueabi - name: Install aarch64-apple-darwin target if: matrix.os == 'macos-latest' @@ -240,6 +367,24 @@ jobs: file: roles/target/release/translator_sv2 asset_name: translator_sv2-x86_64-linux-gnu tag: ${{ github.ref }} + + - name: Upload Linux aarch64 binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/aarch64-unknown-linux-gnu/release/translator_sv2 + asset_name: translator_sv2-aarch64-linux-gnu + tag: ${{ github.ref }} + + - name: Upload Linux ARM binaries to release + if: matrix.os == 'ubuntu-20.04' + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: roles/target/arm-unknown-linux-gnueabi/release/translator_sv2 + asset_name: translator_sv2-arm-linux-gnueabi + tag: ${{ github.ref }} - name: Upload MacOS x86-64 binaries to release if: matrix.os == 'macos-latest' @@ -257,4 +402,4 @@ jobs: repo_token: ${{ secrets.GITHUB_TOKEN }} file: roles/target/aarch64-apple-darwin/release/translator_sv2 asset_name: translator_sv2-aarch64-apple-darwin - tag: ${{ github.ref }} \ No newline at end of file + tag: ${{ github.ref }} From f951edde0b5b7fc1da6f579303745466c12b2344 Mon Sep 17 00:00:00 2001 From: fi3 Date: Fri, 3 May 2024 15:14:00 +0200 Subject: [PATCH 18/39] Add sha256 dep --- protocols/Cargo.lock | 219 +- roles/Cargo.lock | 1 + roles/test-utils/mining-device/Cargo.toml | 1 + utils/Cargo.lock | 2286 --------------------- 4 files changed, 150 insertions(+), 2357 deletions(-) delete mode 100644 utils/Cargo.lock diff --git a/protocols/Cargo.lock b/protocols/Cargo.lock index 9c408b52f..eff20eb55 100644 --- a/protocols/Cargo.lock +++ b/protocols/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -45,9 +45,9 @@ checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "bech32" @@ -106,10 +106,10 @@ dependencies = [ ] [[package]] -name = "bitcoin-private" -version = "0.1.0" +name = "bitcoin-internals" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" [[package]] name = "bitcoin_hashes" @@ -128,11 +128,12 @@ checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" [[package]] name = "bitcoin_hashes" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" dependencies = [ - "bitcoin-private", + "bitcoin-internals", + "hex-conservative", ] [[package]] @@ -151,12 +152,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" [[package]] name = "cfg-if" @@ -201,7 +199,7 @@ dependencies = [ [[package]] name = "codec_sv2" -version = "1.0.0" +version = "1.0.1" dependencies = [ "binary_sv2", "buffer_sv2", @@ -233,9 +231,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -312,9 +310,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", @@ -323,9 +321,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", @@ -356,6 +354,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" + [[package]] name = "humantime" version = "1.3.0" @@ -376,9 +380,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "job_declaration_sv2" @@ -391,21 +395,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.151" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mining_sv2" @@ -446,15 +450,15 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "poly1305" @@ -469,9 +473,9 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", @@ -497,9 +501,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -534,9 +538,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -573,9 +577,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -585,9 +589,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -596,9 +600,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "roles_logic_sv2" @@ -625,9 +629,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "secp256k1" @@ -645,7 +649,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "bitcoin_hashes 0.12.0", + "bitcoin_hashes 0.13.0", "rand", "secp256k1-sys 0.9.2", ] @@ -670,29 +674,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -701,13 +705,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.60", ] [[package]] @@ -720,9 +724,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "stratum-common" @@ -780,9 +784,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -802,9 +806,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -837,7 +841,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.60", ] [[package]] @@ -901,11 +905,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -914,6 +918,79 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "zeroize" version = "1.7.0" diff --git a/roles/Cargo.lock b/roles/Cargo.lock index 2d2cf18a9..d8ba9cd25 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -1353,6 +1353,7 @@ dependencies = [ "network_helpers_sv2", "rand", "roles_logic_sv2", + "sha2 0.10.8", "stratum-common", "tracing", "tracing-subscriber", diff --git a/roles/test-utils/mining-device/Cargo.toml b/roles/test-utils/mining-device/Cargo.toml index 263ddfbd4..41429d6a1 100644 --- a/roles/test-utils/mining-device/Cargo.toml +++ b/roles/test-utils/mining-device/Cargo.toml @@ -23,3 +23,4 @@ key-utils = { version = "^1.0.0", path = "../../../utils/key-utils" } clap = { version = "^4.5.4", features = ["derive"] } tracing = { version = "0.1" } tracing-subscriber = "0.3" +sha2 = "0.10.6" diff --git a/utils/Cargo.lock b/utils/Cargo.lock deleted file mode 100644 index 7e69edbaf..000000000 --- a/utils/Cargo.lock +++ /dev/null @@ -1,2286 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "amplify" -version = "3.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ec14f4fb838e9ddace42fa5944bb1ee4dff8477494ba48c5f874e16caf27a" -dependencies = [ - "amplify_derive", - "amplify_num", - "wasm-bindgen", -] - -[[package]] -name = "amplify_derive" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3de270e75f27a4468a7c344070109046656e85cb522141f7d40ab4b83803ac" -dependencies = [ - "amplify_syn", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "amplify_num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27d3d00d3d115395a7a8a4dc045feb7aa82b641e485f7e15f4e67ac16f4f56d" - -[[package]] -name = "amplify_syn" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da24db1445cc7bc3842fa072c2d51fe5b25b812b6a572d65842a4c72e87221ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" -dependencies = [ - "concurrent-queue", - "event-listener 5.0.0", - "event-listener-strategy 0.5.0", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" -dependencies = [ - "async-lock 3.3.0", - "async-task", - "concurrent-queue", - "fastrand 2.0.1", - "futures-lite 2.2.0", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.2.0", - "async-executor", - "async-io 2.3.1", - "async-lock 3.3.0", - "blocking", - "futures-lite 2.2.0", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" -dependencies = [ - "async-lock 3.3.0", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite 2.2.0", - "parking", - "polling 3.4.0", - "rustix 0.38.31", - "slab", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-lock" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" -dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", - "pin-project-lite", -] - -[[package]] -name = "async-std" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite 1.13.0", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - -[[package]] -name = "binary_codec_sv2" -version = "1.0.0" -dependencies = [ - "buffer_sv2", -] - -[[package]] -name = "binary_sv2" -version = "1.0.0" -dependencies = [ - "binary_codec_sv2", - "derive_codec_sv2", - "serde", - "serde_sv2", - "tracing", -] - -[[package]] -name = "bip32_derivation" -version = "1.0.0" -dependencies = [ - "slip132", - "stratum-common", - "toml", -] - -[[package]] -name = "bitcoin" -version = "0.29.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" -dependencies = [ - "bech32", - "bitcoin_hashes 0.11.0", - "secp256k1 0.24.3", -] - -[[package]] -name = "bitcoin-internals" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" - -[[package]] -name = "bitcoin_hashes" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" - -[[package]] -name = "bitcoin_hashes" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" -dependencies = [ - "bitcoin-internals", - "hex-conservative", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blocking" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" -dependencies = [ - "async-channel 2.2.0", - "async-lock 3.3.0", - "async-task", - "fastrand 2.0.1", - "futures-io", - "futures-lite 2.2.0", - "piper", - "tracing", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -dependencies = [ - "sha2", -] - -[[package]] -name = "buffer_sv2" -version = "1.0.0" -dependencies = [ - "aes-gcm", - "criterion", - "iai", - "rand", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags 1.3.2", - "textwrap", - "unicode-width", -] - -[[package]] -name = "codec_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "buffer_sv2", - "const_sv2", - "framing_sv2", - "noise_sv2", - "serde", - "tracing", -] - -[[package]] -name = "concurrent-queue" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const_sv2" -version = "1.0.0" -dependencies = [ - "secp256k1 0.28.2", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "criterion" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -dependencies = [ - "atty", - "cast", - "clap", - "criterion-plot", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "csv" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "derive_codec_sv2" -version = "1.0.0" -dependencies = [ - "binary_codec_sv2", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "either" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "error_handling" -version = "1.0.0" - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b72557800024fabbaa2449dd4bf24e37b93702d457a4d4f2b0dd1f0f039f20c1" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" -dependencies = [ - "event-listener 5.0.0", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "framing_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "buffer_sv2", - "const_sv2", - "serde", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-lite" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" -dependencies = [ - "fastrand 2.0.1", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "ghash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "h2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hashbrown" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" -dependencies = [ - "ahash", - "autocfg", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-conservative" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" - -[[package]] -name = "http" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "tokio", - "want", -] - -[[package]] -name = "hyper-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2 0.5.5", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "iai" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" - -[[package]] -name = "indexmap" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" -dependencies = [ - "equivalent", - "hashbrown 0.14.3", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.5", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "js-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "key-utils" -version = "1.0.0" -dependencies = [ - "bs58", - "secp256k1 0.28.2", - "serde", - "toml", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.153" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -dependencies = [ - "value-bag", -] - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "network_helpers" -version = "1.0.0" -dependencies = [ - "async-channel 1.9.0", - "async-std", - "binary_sv2", - "codec_sv2", - "const_sv2", - "futures", - "serde", - "tokio", - "tracing", -] - -[[package]] -name = "noise_sv2" -version = "1.1.0" -dependencies = [ - "aes-gcm", - "chacha20poly1305", - "const_sv2", - "rand", - "rand_chacha", - "secp256k1 0.28.2", -] - -[[package]] -name = "num-traits" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.5", - "libc", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "pin-project" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" -dependencies = [ - "atomic-waker", - "fastrand 2.0.1", - "futures-io", -] - -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "polling" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30054e72317ab98eddd8561db0f6524df3367636884b7b21b703e4b280a84a14" -dependencies = [ - "cfg-if", - "concurrent-queue", - "pin-project-lite", - "rustix 0.38.31", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rayon" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rpc" -version = "1.0.0" -dependencies = [ - "base64", - "hex", - "http-body-util", - "hyper", - "hyper-util", - "serde", - "serde_json", - "stratum-common", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustix" -version = "0.37.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" -dependencies = [ - "bitflags 2.4.2", - "errno", - "libc", - "linux-raw-sys 0.4.13", - "windows-sys 0.52.0", -] - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "secp256k1" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" -dependencies = [ - "bitcoin_hashes 0.11.0", - "secp256k1-sys 0.6.1", -] - -[[package]] -name = "secp256k1" -version = "0.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" -dependencies = [ - "bitcoin_hashes 0.13.0", - "rand", - "secp256k1-sys 0.9.2", -] - -[[package]] -name = "secp256k1-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" -dependencies = [ - "cc", -] - -[[package]] -name = "secp256k1-sys" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" -dependencies = [ - "cc", -] - -[[package]] -name = "serde" -version = "1.0.196" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.196" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "serde_json" -version = "1.0.113" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_sv2" -version = "1.0.0" -dependencies = [ - "buffer_sv2", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer", - "cfg-if", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "slip132" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "890b12cf298c4548739d6b1e53286576e43014ff1d3421751f2c26c80cc7a639" -dependencies = [ - "amplify", - "bitcoin", -] - -[[package]] -name = "smallvec" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "stratum-common" -version = "1.0.0" -dependencies = [ - "bitcoin", -] - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tokio" -version = "1.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.5", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.6" -source = "git+https://github.com/diondokter/toml-rs?rev=c4161aa#c4161aa70202b3992dbec79b76e7a8659713b604" -dependencies = [ - "hashbrown 0.7.2", - "serde", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "value-bag" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - -[[package]] -name = "walkdir" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.48", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" - -[[package]] -name = "web-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" From 54ba468c47db5f01f98f77d47328bfca0201bace Mon Sep 17 00:00:00 2001 From: fi3 Date: Tue, 7 May 2024 11:09:26 +0200 Subject: [PATCH 19/39] Fix network helper panic if peer close connection When the remote peer try to open an encrypted sv2 connection and then immediatly close the tcp connection, the helper for async std and tokio it panic, mostly of the time we don't want to panic in this situation. This commit add an error for this case and return it. --- roles/roles-utils/network-helpers/src/lib.rs | 2 ++ .../network-helpers/src/noise_connection_async_std.rs | 2 +- roles/roles-utils/network-helpers/src/noise_connection_tokio.rs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/roles/roles-utils/network-helpers/src/lib.rs b/roles/roles-utils/network-helpers/src/lib.rs index 2879e3ad6..3555c2056 100644 --- a/roles/roles-utils/network-helpers/src/lib.rs +++ b/roles/roles-utils/network-helpers/src/lib.rs @@ -30,6 +30,8 @@ pub enum Error { CodecError(CodecError), RecvError, SendError, + // This means that a socket that was supposed to be opened have been closed, likley by the peer + SocketClosed, } impl From for Error { diff --git a/roles/roles-utils/network-helpers/src/noise_connection_async_std.rs b/roles/roles-utils/network-helpers/src/noise_connection_async_std.rs index 0bfad7e9d..ae4052903 100644 --- a/roles/roles-utils/network-helpers/src/noise_connection_async_std.rs +++ b/roles/roles-utils/network-helpers/src/noise_connection_async_std.rs @@ -47,7 +47,7 @@ impl Connection { ), Error, > { - let address = stream.peer_addr().unwrap(); + let address = stream.peer_addr().map_err(|_| Error::SocketClosed)?; let (mut reader, writer) = (stream.clone(), stream.clone()); let (sender_incoming, receiver_incoming): ( diff --git a/roles/roles-utils/network-helpers/src/noise_connection_tokio.rs b/roles/roles-utils/network-helpers/src/noise_connection_tokio.rs index 06a4961be..2e2996365 100644 --- a/roles/roles-utils/network-helpers/src/noise_connection_tokio.rs +++ b/roles/roles-utils/network-helpers/src/noise_connection_tokio.rs @@ -48,7 +48,7 @@ impl Connection { ), Error, > { - let address = stream.peer_addr().unwrap(); + let address = stream.peer_addr().map_err(|_| Error::SocketClosed)?; let (mut reader, mut writer) = stream.into_split(); From c7cf4f57f249262c703614872833552f40d24ad8 Mon Sep 17 00:00:00 2001 From: fi3 Date: Tue, 7 May 2024 14:27:06 +0200 Subject: [PATCH 20/39] Bump network helpers version --- examples/ping-pong-with-noise/Cargo.toml | 2 +- roles/Cargo.lock | 74 ++++++++++---------- roles/jd-client/Cargo.toml | 4 +- roles/jd-server/Cargo.toml | 4 +- roles/mining-proxy/Cargo.toml | 4 +- roles/pool/Cargo.toml | 4 +- roles/roles-utils/network-helpers/Cargo.toml | 2 +- roles/test-utils/mining-device/Cargo.toml | 4 +- roles/translator/Cargo.toml | 4 +- utils/message-generator/Cargo.toml | 4 +- 10 files changed, 52 insertions(+), 54 deletions(-) diff --git a/examples/ping-pong-with-noise/Cargo.toml b/examples/ping-pong-with-noise/Cargo.toml index 0e984b0e5..b1220bce7 100644 --- a/examples/ping-pong-with-noise/Cargo.toml +++ b/examples/ping-pong-with-noise/Cargo.toml @@ -15,7 +15,7 @@ async-std="1.8.0" bytes = "1.0.1" binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary-sv2" } codec_sv2 = { version = "^1.0.0", path = "../../protocols/v2/codec-sv2", features=["noise_sv2"] } -network_helpers_sv2 = { version = "^1.0.0", path = "../../roles/roles-utils/network-helpers", features=["async_std"] } +network_helpers_sv2 = { version = "^2.0.0", path = "../../roles/roles-utils/network-helpers", features=["async_std"] } key-utils = { version = "^1.0.0", path = "../../utils/key-utils" } [features] diff --git a/roles/Cargo.lock b/roles/Cargo.lock index d8ba9cd25..d245c93d3 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -280,7 +280,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" @@ -507,9 +507,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cfg-if" @@ -583,7 +583,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -892,7 +892,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -937,9 +937,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1201,7 +1201,7 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jd_client" -version = "0.1.0" +version = "0.1.1" dependencies = [ "async-channel 1.9.0", "async-recursion 0.3.2", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "jd_server" -version = "0.1.0" +version = "0.1.1" dependencies = [ "async-channel 1.9.0", "binary_sv2", @@ -1338,7 +1338,7 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mining-device" -version = "0.1.0" +version = "0.1.1" dependencies = [ "async-channel 1.9.0", "async-recursion 0.3.2", @@ -1361,7 +1361,7 @@ dependencies = [ [[package]] name = "mining_proxy_sv2" -version = "0.1.0" +version = "0.1.1" dependencies = [ "async-channel 1.9.0", "async-recursion 0.3.2", @@ -1413,7 +1413,7 @@ dependencies = [ [[package]] name = "network_helpers_sv2" -version = "1.0.1" +version = "2.0.0" dependencies = [ "async-channel 1.9.0", "async-std", @@ -1456,11 +1456,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -1476,9 +1475,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1566,7 +1565,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -1648,7 +1647,7 @@ dependencies = [ [[package]] name = "pool_sv2" -version = "0.1.0" +version = "0.1.1" dependencies = [ "async-channel 1.9.0", "async-recursion 1.1.1", @@ -1691,9 +1690,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -1815,9 +1814,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" @@ -1848,9 +1847,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -1914,7 +1913,7 @@ checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -2081,9 +2080,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" dependencies = [ "proc-macro2", "quote", @@ -2144,21 +2143,20 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -2218,7 +2216,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", ] [[package]] @@ -2258,7 +2256,7 @@ dependencies = [ [[package]] name = "translator_sv2" -version = "0.1.0" +version = "0.1.1" dependencies = [ "async-channel 1.9.0", "async-compat", @@ -2381,7 +2379,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", "wasm-bindgen-shared", ] @@ -2415,7 +2413,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.61", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/roles/jd-client/Cargo.toml b/roles/jd-client/Cargo.toml index f7ccc5f77..d0693fdb2 100644 --- a/roles/jd-client/Cargo.toml +++ b/roles/jd-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jd_client" -version = "0.1.0" +version = "0.1.1" edition = "2021" description = "TODO" license = "MIT OR Apache-2.0" @@ -18,7 +18,7 @@ binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary- buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" } codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2", "with_buffer_pool"] } framing_sv2 = { version = "^1.0.0", path = "../../protocols/v2/framing-sv2" } -network_helpers_sv2 = { version = "1.0.0", path = "../roles-utils/network-helpers", features=["with_tokio", "with_buffer_pool"] } +network_helpers_sv2 = { version = "2.0.0", path = "../roles-utils/network-helpers", features=["with_tokio", "with_buffer_pool"] } roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" } serde = { version = "1.0.89", default-features = false, features = ["derive", "alloc"] } futures = "0.3.25" diff --git a/roles/jd-server/Cargo.toml b/roles/jd-server/Cargo.toml index b89c07023..83156cfcd 100644 --- a/roles/jd-server/Cargo.toml +++ b/roles/jd-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jd_server" -version = "0.1.0" +version = "0.1.1" edition = "2018" license = "MIT OR Apache-2.0" repository = "https://github.com/stratum-mining/stratum" @@ -16,7 +16,7 @@ binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary- buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" } codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2"] } const_sv2 = { version = "^1.0.0", path = "../../protocols/v2/const-sv2" } -network_helpers_sv2 = { version = "1.0.0", path = "../roles-utils/network-helpers", features = ["with_tokio"] } +network_helpers_sv2 = { version = "2.0.0", path = "../roles-utils/network-helpers", features = ["with_tokio"] } noise_sv2 = { version = "1.1.0", path = "../../protocols/v2/noise-sv2" } rand = "0.8.4" roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" } diff --git a/roles/mining-proxy/Cargo.toml b/roles/mining-proxy/Cargo.toml index 6e77ccc7e..951645fde 100644 --- a/roles/mining-proxy/Cargo.toml +++ b/roles/mining-proxy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mining_proxy_sv2" -version = "0.1.0" +version = "0.1.1" authors = ["user"] edition = "2018" description = "SV2 mining proxy role" @@ -20,7 +20,7 @@ buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" } codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2", "with_buffer_pool"] } const_sv2 = { version = "^1.0.0", path = "../../protocols/v2/const-sv2" } futures = "0.3.19" -network_helpers_sv2 = {version = "1.0.0", path = "../roles-utils/network-helpers", features = ["with_tokio","with_buffer_pool"] } +network_helpers_sv2 = {version = "2.0.0", path = "../roles-utils/network-helpers", features = ["with_tokio","with_buffer_pool"] } once_cell = "1.12.0" roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" } serde = { version = "1.0.89", features = ["derive", "alloc"], default-features = false } diff --git a/roles/pool/Cargo.toml b/roles/pool/Cargo.toml index a1da3a21f..61005f00b 100644 --- a/roles/pool/Cargo.toml +++ b/roles/pool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pool_sv2" -version = "0.1.0" +version = "0.1.1" edition = "2018" description = "SV2 pool role" license = "MIT OR Apache-2.0" @@ -17,7 +17,7 @@ binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary- buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" } codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2"] } const_sv2 = { version = "^1.0.0", path = "../../protocols/v2/const-sv2" } -network_helpers_sv2 = { version = "1.0.0", path = "../roles-utils/network-helpers", features =["with_tokio","with_buffer_pool"] } +network_helpers_sv2 = { version = "2.0.0", path = "../roles-utils/network-helpers", features =["with_tokio","with_buffer_pool"] } noise_sv2 = { version = "1.1.0", path = "../../protocols/v2/noise-sv2" } rand = "0.8.4" roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" } diff --git a/roles/roles-utils/network-helpers/Cargo.toml b/roles/roles-utils/network-helpers/Cargo.toml index 31de7a584..e2c69806a 100644 --- a/roles/roles-utils/network-helpers/Cargo.toml +++ b/roles/roles-utils/network-helpers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "network_helpers_sv2" -version = "1.0.1" +version = "2.0.0" authors = ["fi3 "] edition = "2018" description = "Networking utils for SV2 roles" diff --git a/roles/test-utils/mining-device/Cargo.toml b/roles/test-utils/mining-device/Cargo.toml index 41429d6a1..4ce6c5037 100644 --- a/roles/test-utils/mining-device/Cargo.toml +++ b/roles/test-utils/mining-device/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mining-device" -version = "0.1.0" +version = "0.1.1" edition = "2018" publish = false @@ -14,7 +14,7 @@ const_sv2 = { version = "1.0.0", path = "../../../protocols/v2/const-sv2" } async-channel = "1.5.1" async-std={version = "1.8.0", features = ["attributes"]} binary_sv2 = { version = "1.0.0", path = "../../../protocols/v2/binary-sv2/binary-sv2" } -network_helpers_sv2 = { version = "1.0.0", path = "../../roles-utils/network-helpers", features=["async_std"] } +network_helpers_sv2 = { version = "2.0.0", path = "../../roles-utils/network-helpers", features=["async_std"] } buffer_sv2 = { version = "1.0.0", path = "../../../utils/buffer"} async-recursion = "0.3.2" rand = "0.8.4" diff --git a/roles/translator/Cargo.toml b/roles/translator/Cargo.toml index 79d872019..bdba3cf11 100644 --- a/roles/translator/Cargo.toml +++ b/roles/translator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "translator_sv2" -version = "0.1.0" +version = "0.1.1" edition = "2021" description = "Server used to bridge SV1 miners to SV2 pools" license = "MIT OR Apache-2.0" @@ -19,7 +19,7 @@ binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary- buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" } codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2", "with_buffer_pool"] } framing_sv2 = { version = "^1.0.0", path = "../../protocols/v2/framing-sv2" } -network_helpers_sv2 = { version = "1.0.0", path = "../roles-utils/network-helpers", features=["async_std", "with_buffer_pool"] } +network_helpers_sv2 = { version = "2.0.0", path = "../roles-utils/network-helpers", features=["async_std", "with_buffer_pool"] } once_cell = "1.12.0" roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" } serde = { version = "1.0.89", default-features = false, features = ["derive", "alloc"] } diff --git a/utils/message-generator/Cargo.toml b/utils/message-generator/Cargo.toml index c6337be74..b1a8a119d 100644 --- a/utils/message-generator/Cargo.toml +++ b/utils/message-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "message_generator_sv2" -version = "1.0.0" +version = "1.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -11,7 +11,7 @@ binary_sv2 = { version = "1.0.0", path = "../../protocols/v2/binary-sv2/binary-s codec_sv2 = { version = "1.0.0", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2","with_buffer_pool","with_serde"] } const_sv2 = { version = "1.0.0", path = "../../protocols/v2/const-sv2" } load_file = "1.0.1" -network_helpers_sv2 = { version = "1.0.0", path = "../../roles/roles-utils/network-helpers", features = ["with_tokio","with_serde"] } +network_helpers_sv2 = { version = "2.0.0", path = "../../roles/roles-utils/network-helpers", features = ["with_tokio","with_serde"] } roles_logic_sv2 = { version = "1.0.0", path = "../../protocols/v2/roles-logic-sv2", features = ["with_serde"] } v1 = { version = "^1.0.0", path = "../../protocols/v1", package="sv1_api" } serde = { version = "*", features = ["derive", "alloc"], default-features = false } From fd485c2f28503a9461849b0204cc37fb114ebeaf Mon Sep 17 00:00:00 2001 From: Houdini Date: Fri, 3 May 2024 13:54:44 +0100 Subject: [PATCH 21/39] chore: refactor update_mempool function in the jds mempool --- roles/jd-server/src/lib/mempool/mod.rs | 62 ++++++++++++-------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/roles/jd-server/src/lib/mempool/mod.rs b/roles/jd-server/src/lib/mempool/mod.rs index f2b97fe4e..c168f814a 100644 --- a/roles/jd-server/src/lib/mempool/mod.rs +++ b/roles/jd-server/src/lib/mempool/mod.rs @@ -5,7 +5,7 @@ use async_channel::Receiver; use bitcoin::blockdata::transaction::Transaction; use hashbrown::HashMap; use roles_logic_sv2::utils::Mutex; -use rpc_sv2::mini_rpc_client; +use rpc_sv2::{mini_rpc_client, mini_rpc_client::RpcError}; use std::{convert::TryInto, str::FromStr, sync::Arc}; use stratum_common::{bitcoin, bitcoin::hash_types::Txid}; @@ -97,43 +97,37 @@ impl JDsMempool { pub async fn update_mempool(self_: Arc>) -> Result<(), JdsMempoolError> { let mut mempool_ordered: HashMap> = HashMap::new(); + let client = self_ .safe_lock(|x| x.get_client()) .map_err(|e| JdsMempoolError::PoisonLock(e.to_string()))? .ok_or(JdsMempoolError::NoClient)?; - let new_mempool: Result>, JdsMempoolError> = { - let self_ = self_.clone(); - tokio::task::spawn(async move { - let mempool: Vec = client - .get_raw_mempool() - .await - .map_err(JdsMempoolError::Rpc)?; - for id in &mempool { - let key_id = Txid::from_str(id).unwrap(); - let tx = self_.safe_lock(|x| match x.mempool.get(&key_id) { - Some(entry) => entry.clone(), - None => None, - }); - let id = Txid::from_str(id).unwrap(); - mempool_ordered.insert(id, tx.unwrap()); - } - if mempool_ordered.is_empty() { - Err(JdsMempoolError::EmptyMempool) - } else { - Ok(mempool_ordered) - } - }) - .await - .map_err(JdsMempoolError::TokioJoin)? - }; - match new_mempool { - Ok(new_mempool_) => { - let _ = self_.safe_lock(|x| { - x.mempool = new_mempool_; - }); - Ok(()) - } - Err(a) => Err(a), + + let mempool: Vec = client.get_raw_mempool().await.map_err(|err| { + let err_msg = format!("Error occurred during deserialization: {:?}", err); + JdsMempoolError::Rpc(RpcError::Deserialization(err_msg)) + })?; + for id in &mempool { + let key_id = Txid::from_str(id).map_err(|err| { + let err_msg = format!("Error occurred during deserialization: {:?}", err); + JdsMempoolError::Rpc(RpcError::Deserialization(err_msg)) + })?; + + let tx = self_ + .safe_lock(|x| match x.mempool.get(&key_id) { + Some(entry) => entry.clone(), + None => None, + }) + .map_err(|e| JdsMempoolError::PoisonLock(e.to_string()))?; + + mempool_ordered.insert(key_id, tx); + } + + if mempool_ordered.is_empty() { + Err(JdsMempoolError::EmptyMempool) + } else { + let _ = self_.safe_lock(|x| x.mempool = mempool_ordered); + Ok(()) } } From b46355b3a143d72687546cfe4d6bf777285bcc21 Mon Sep 17 00:00:00 2001 From: lorban Date: Tue, 7 May 2024 12:43:16 +0200 Subject: [PATCH 22/39] fix error handling --- benches/Cargo.lock | 4 +-- roles/jd-server/src/lib/mempool/error.rs | 19 +++++++++---- roles/jd-server/src/lib/mempool/mod.rs | 35 ++++++++---------------- roles/jd-server/src/main.rs | 4 --- 4 files changed, 27 insertions(+), 35 deletions(-) diff --git a/benches/Cargo.lock b/benches/Cargo.lock index 8221e73c7..230f266d7 100644 --- a/benches/Cargo.lock +++ b/benches/Cargo.lock @@ -497,7 +497,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "codec_sv2" -version = "1.0.0" +version = "1.0.1" dependencies = [ "binary_sv2", "buffer_sv2", @@ -1070,7 +1070,7 @@ dependencies = [ [[package]] name = "network_helpers_sv2" -version = "1.0.0" +version = "1.0.1" dependencies = [ "async-channel 1.9.0", "async-std", diff --git a/roles/jd-server/src/lib/mempool/error.rs b/roles/jd-server/src/lib/mempool/error.rs index e554a0b14..f2ce316e8 100644 --- a/roles/jd-server/src/lib/mempool/error.rs +++ b/roles/jd-server/src/lib/mempool/error.rs @@ -1,5 +1,5 @@ use rpc_sv2::mini_rpc_client::RpcError; -use tokio::task::JoinError; +use std::{convert::From, sync::PoisonError}; use tracing::{error, warn}; #[derive(Debug)] @@ -8,7 +8,18 @@ pub enum JdsMempoolError { NoClient, Rpc(RpcError), PoisonLock(String), - TokioJoin(JoinError), +} + +impl From for JdsMempoolError { + fn from(value: RpcError) -> Self { + JdsMempoolError::Rpc(value) + } +} + +impl From> for JdsMempoolError { + fn from(value: PoisonError) -> Self { + JdsMempoolError::PoisonLock(value.to_string()) + } } pub fn handle_error(err: &JdsMempoolError) { @@ -29,9 +40,5 @@ pub fn handle_error(err: &JdsMempoolError) { error!("{:?}", err); error!("Poison lock error)"); } - JdsMempoolError::TokioJoin(_) => { - error!("{:?}", err); - error!("Poison lock error)"); - } } } diff --git a/roles/jd-server/src/lib/mempool/mod.rs b/roles/jd-server/src/lib/mempool/mod.rs index c168f814a..a9aa8ecc9 100644 --- a/roles/jd-server/src/lib/mempool/mod.rs +++ b/roles/jd-server/src/lib/mempool/mod.rs @@ -69,8 +69,7 @@ impl JDsMempool { let txids = add_txs_to_mempool_inner.known_transactions; let transactions = add_txs_to_mempool_inner.unknown_transactions; let client = self_ - .safe_lock(|a| a.get_client()) - .map_err(|e| JdsMempoolError::PoisonLock(e.to_string()))? + .safe_lock(|a| a.get_client())? .ok_or(JdsMempoolError::NoClient)?; // fill in the mempool the transactions id in the mempool with the full transactions // retrieved from the jd client @@ -99,26 +98,18 @@ impl JDsMempool { let mut mempool_ordered: HashMap> = HashMap::new(); let client = self_ - .safe_lock(|x| x.get_client()) - .map_err(|e| JdsMempoolError::PoisonLock(e.to_string()))? + .safe_lock(|x| x.get_client())? .ok_or(JdsMempoolError::NoClient)?; - let mempool: Vec = client.get_raw_mempool().await.map_err(|err| { - let err_msg = format!("Error occurred during deserialization: {:?}", err); - JdsMempoolError::Rpc(RpcError::Deserialization(err_msg)) - })?; + let mempool: Vec = client.get_raw_mempool().await?; for id in &mempool { - let key_id = Txid::from_str(id).map_err(|err| { - let err_msg = format!("Error occurred during deserialization: {:?}", err); - JdsMempoolError::Rpc(RpcError::Deserialization(err_msg)) - })?; + let key_id = Txid::from_str(id) + .map_err(|err| JdsMempoolError::Rpc(RpcError::Deserialization(err.to_string())))?; - let tx = self_ - .safe_lock(|x| match x.mempool.get(&key_id) { - Some(entry) => entry.clone(), - None => None, - }) - .map_err(|e| JdsMempoolError::PoisonLock(e.to_string()))?; + let tx = self_.safe_lock(|x| match x.mempool.get(&key_id) { + Some(entry) => entry.clone(), + None => None, + })?; mempool_ordered.insert(key_id, tx); } @@ -132,12 +123,10 @@ impl JDsMempool { } pub async fn on_submit(self_: Arc>) -> Result<(), JdsMempoolError> { - let new_block_receiver: Receiver = self_ - .safe_lock(|x| x.new_block_receiver.clone()) - .map_err(|e| JdsMempoolError::PoisonLock(e.to_string()))?; + let new_block_receiver: Receiver = + self_.safe_lock(|x| x.new_block_receiver.clone())?; let client = self_ - .safe_lock(|x| x.get_client()) - .map_err(|e| JdsMempoolError::PoisonLock(e.to_string()))? + .safe_lock(|x| x.get_client())? .ok_or(JdsMempoolError::NoClient)?; while let Ok(block_hex) = new_block_receiver.recv().await { diff --git a/roles/jd-server/src/main.rs b/roles/jd-server/src/main.rs index 3391a93be..9d56b491f 100644 --- a/roles/jd-server/src/main.rs +++ b/roles/jd-server/src/main.rs @@ -146,10 +146,6 @@ async fn main() { mempool::error::handle_error(&err); handle_result!(sender_update_mempool, Err(err)); } - JdsMempoolError::TokioJoin(_) => { - mempool::error::handle_error(&err); - handle_result!(sender_update_mempool, Err(err)); - } JdsMempoolError::PoisonLock(_) => { mempool::error::handle_error(&err); handle_result!(sender_update_mempool, Err(err)); From 2aa71f1acb85f18c39abbc288a86dd3313d09743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=BE=D0=BB=D0=BB=D0=B8?= Date: Wed, 8 May 2024 19:17:07 +0300 Subject: [PATCH 23/39] Fix deprecation notice on CI (#879) --- .github/workflows/coverage.yaml | 14 +++++++------- .github/workflows/release-bin.yaml | 10 +++++----- .github/workflows/release-libs.yaml | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 252a77af1..3bc1af88b 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -33,14 +33,14 @@ jobs: options: --security-opt seccomp=unconfined steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Generate code coverage run: | ./tarpaulin.sh - name: Archive Tarpaulin code coverage results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: tarpaulin-report path: | @@ -56,7 +56,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: @@ -82,14 +82,14 @@ jobs: run: sh ./message-generator-tests.sh - name: Archive MG code coverage results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-report path: 'target/*.xml' - name: Archive log files if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: logs path: './utils/message-generator/*.log' @@ -103,10 +103,10 @@ jobs: # steps: # - name: Checkout repository - # uses: actions/checkout@v3 + # uses: actions/checkout@v4 # - name: Download all workflow run artifacts - # uses: actions/download-artifact@v3 + # uses: actions/download-artifact@v4 # - name: Display structure of downloaded files # run: ls -R diff --git a/.github/workflows/release-bin.yaml b/.github/workflows/release-bin.yaml index a6585a27f..1ff1b896a 100644 --- a/.github/workflows/release-bin.yaml +++ b/.github/workflows/release-bin.yaml @@ -15,7 +15,7 @@ jobs: matrix: os: [ubuntu-20.04, macos-latest] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -94,7 +94,7 @@ jobs: matrix: os: [ ubuntu-20.04, macos-latest ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -173,7 +173,7 @@ jobs: matrix: os: [ ubuntu-20.04, macos-latest ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -252,7 +252,7 @@ jobs: matrix: os: [ ubuntu-20.04, macos-latest ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -331,7 +331,7 @@ jobs: matrix: os: [ ubuntu-20.04, macos-latest ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: toolchain: stable diff --git a/.github/workflows/release-libs.yaml b/.github/workflows/release-libs.yaml index 9ab285ef4..ac7883dba 100644 --- a/.github/workflows/release-libs.yaml +++ b/.github/workflows/release-libs.yaml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run check-versioning-lib-release.sh run: | @@ -30,7 +30,7 @@ jobs: exit 1 fi - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: toolchain: stable From 5e4890405a90a2285eba661dfa1ef83836db494d Mon Sep 17 00:00:00 2001 From: Fi3 Date: Thu, 9 May 2024 18:37:38 +0200 Subject: [PATCH 24/39] Fix cpu miner hashrate measurement (#866) Co-authored-by: fi3 --- roles/test-utils/mining-device/src/main.rs | 71 ++++++++++++++-------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/roles/test-utils/mining-device/src/main.rs b/roles/test-utils/mining-device/src/main.rs index befd7edff..36dff2986 100644 --- a/roles/test-utils/mining-device/src/main.rs +++ b/roles/test-utils/mining-device/src/main.rs @@ -7,7 +7,6 @@ use std::{net::SocketAddr, sync::Arc, thread::sleep, time::Duration}; use async_std::net::ToSocketAddrs; use clap::Parser; use rand::{thread_rng, Rng}; -use sha2::{Digest, Sha256}; use std::time::Instant; use stratum_common::bitcoin::{ blockdata::block::BlockHeader, hash_types::BlockHash, hashes::Hash, util::uint::Uint256, @@ -110,7 +109,7 @@ async fn main() { } use async_channel::{Receiver, Sender}; -use binary_sv2::{u256_from_int, U256}; +use binary_sv2::u256_from_int; use codec_sv2::{Frame, Initiator, StandardEitherFrame, StandardSv2Frame}; use roles_logic_sv2::{ common_messages_sv2::{Protocol, SetupConnection, SetupConnectionSuccess}, @@ -236,7 +235,7 @@ pub struct Device { fn open_channel(device_id: Option) -> OpenStandardMiningChannel<'static> { let user_identity = device_id.unwrap_or_default().try_into().unwrap(); let id: u32 = 10; - info!("Measuring pc hashrate"); + info!("Measuring CPU hashrate"); let nominal_hash_rate = measure_hashrate(5) as f32; info!("Pc hashrate is {}", nominal_hash_rate); info!("MINING DEVICE: send open channel with request id {}", id); @@ -290,7 +289,7 @@ impl Device { let handicap = miner.safe_lock(|m| m.handicap).unwrap(); std::thread::spawn(move || loop { std::thread::sleep(std::time::Duration::from_micros(handicap.into())); - if miner.safe_lock(|m| m.next_share()).unwrap().is_ok() { + if miner.safe_lock(|m| m.next_share()).unwrap().is_valid() { let nonce = miner.safe_lock(|m| m.header.unwrap().nonce).unwrap(); let time = miner.safe_lock(|m| m.header.unwrap().time).unwrap(); let job_id = miner.safe_lock(|m| m.job_id).unwrap(); @@ -595,52 +594,74 @@ impl Miner { }; self.header = Some(header); } - pub fn next_share(&mut self) -> Result<(), ()> { - let header = self.header.as_ref().ok_or(())?; + pub fn next_share(&mut self) -> NextShareOutcome { + let header = self.header.as_ref().unwrap(); let mut hash = header.block_hash().as_hash().into_inner(); hash.reverse(); let hash = Uint256::from_be_bytes(hash); - if hash < *self.target.as_ref().ok_or(())? { + if hash < *self.target.as_ref().unwrap() { info!( "Found share with nonce: {}, for target: {:?}, with hash: {:?}", header.nonce, self.target, hash, ); - Ok(()) + NextShareOutcome::ValidShare } else { - Err(()) + NextShareOutcome::InvalidShare } } } +enum NextShareOutcome { + ValidShare, + InvalidShare, +} + +impl NextShareOutcome { + pub fn is_valid(&self) -> bool { + matches!(self, NextShareOutcome::ValidShare) + } +} + // returns hashrate based on how fast the device hashes over the given duration fn measure_hashrate(duration_secs: u64) -> f64 { - let mut share = generate_random_80_byte_array(); + let mut rng = thread_rng(); + let prev_hash: [u8; 32] = generate_random_32_byte_array().to_vec().try_into().unwrap(); + let prev_hash = Hash::from_inner(prev_hash); + // We create a random block that we can hash, we are only interested in knowing how many hashes + // per unit of time we can do + let merkle_root: [u8; 32] = generate_random_32_byte_array().to_vec().try_into().unwrap(); + let merkle_root = Hash::from_inner(merkle_root); + let header = BlockHeader { + version: rng.gen(), + prev_blockhash: BlockHash::from_hash(prev_hash), + merkle_root, + time: std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH - std::time::Duration::from_secs(60)) + .unwrap() + .as_secs() as u32, + bits: rng.gen(), + nonce: 0, + }; let start_time = Instant::now(); let mut hashes: u64 = 0; let duration = Duration::from_secs(duration_secs); + let mut miner = Miner::new(0); + // We put the target to 0 we are only interested in how many hashes per unit of time we can do + // and do not want to be botherd by messages about valid shares found. + miner.new_target(vec![0_u8; 32]); + miner.header = Some(header); while start_time.elapsed() < duration { - for _ in 0..10000 { - hash(&mut share); - hashes += 1; - } + miner.next_share(); + hashes += 1; } let elapsed_secs = start_time.elapsed().as_secs_f64(); hashes as f64 / elapsed_secs } -fn generate_random_80_byte_array() -> [u8; 80] { +fn generate_random_32_byte_array() -> [u8; 32] { let mut rng = thread_rng(); - let mut arr = [0u8; 80]; + let mut arr = [0u8; 32]; rng.fill(&mut arr[..]); arr } -fn hash(share: &mut [u8; 80]) -> Target { - let nonce: [u8; 8] = share[0..8].try_into().unwrap(); - let mut nonce = u64::from_le_bytes(nonce); - nonce += 1; - share[0..8].copy_from_slice(&nonce.to_le_bytes()); - let hash = Sha256::digest(&share).to_vec(); - let hash: U256<'static> = hash.try_into().unwrap(); - hash.into() -} From 0b131916f8bbc739a57b739c059fe887bc538931 Mon Sep 17 00:00:00 2001 From: Gabriele Vernetti <62447440+GitGab19@users.noreply.github.com> Date: Fri, 10 May 2024 12:56:34 +0200 Subject: [PATCH 25/39] run benchmarks on dev PRs (#898) --- .github/workflows/run-benchmarks.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run-benchmarks.yaml b/.github/workflows/run-benchmarks.yaml index feec5a5e6..150188218 100644 --- a/.github/workflows/run-benchmarks.yaml +++ b/.github/workflows/run-benchmarks.yaml @@ -4,6 +4,7 @@ on: pull_request: branches: - main + - dev jobs: benchmark_sv1_criterion: From a803f1a86e61961a48a9d7eb9b297f7435e9f4ec Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Fri, 10 May 2024 11:47:56 -0300 Subject: [PATCH 26/39] docs `framing_sv2` (#848) --- protocols/v2/codec-sv2/src/lib.rs | 4 +- protocols/v2/framing-sv2/src/framing2.rs | 139 +++++++++++++---------- protocols/v2/framing-sv2/src/header.rs | 8 ++ protocols/v2/framing-sv2/src/lib.rs | 42 ++++--- 4 files changed, 115 insertions(+), 78 deletions(-) diff --git a/protocols/v2/codec-sv2/src/lib.rs b/protocols/v2/codec-sv2/src/lib.rs index 01f1ee02b..f5cbc013d 100644 --- a/protocols/v2/codec-sv2/src/lib.rs +++ b/protocols/v2/codec-sv2/src/lib.rs @@ -21,9 +21,9 @@ pub use encoder::Encoder; #[cfg(feature = "noise_sv2")] pub use encoder::NoiseEncoder; -pub use framing_sv2::framing2::{Frame, Sv2Frame}; #[cfg(feature = "noise_sv2")] -pub use framing_sv2::framing2::{HandShakeFrame, NoiseFrame}; +pub use framing_sv2::framing2::HandShakeFrame; +pub use framing_sv2::framing2::{Frame, Sv2Frame}; #[cfg(feature = "noise_sv2")] pub use noise_sv2::{self, Initiator, NoiseCodec, Responder}; diff --git a/protocols/v2/framing-sv2/src/framing2.rs b/protocols/v2/framing-sv2/src/framing2.rs index 95afc617d..4ba896063 100644 --- a/protocols/v2/framing-sv2/src/framing2.rs +++ b/protocols/v2/framing-sv2/src/framing2.rs @@ -15,6 +15,8 @@ type Slice = Vec; type Slice = buffer_sv2::Slice; impl Sv2Frame { + /// Maps a `Sv2Frame` to `Sv2Frame` by applying `fun`, + /// which is assumed to be a closure that converts `A` to `C` pub fn map(self, fun: fn(A) -> C) -> Sv2Frame { let serialized = self.serialized; let header = self.header; @@ -31,31 +33,39 @@ pub trait Frame<'a, T: Serialize + GetSize>: Sized { type Buffer: AsMut<[u8]>; type Deserialized; - /// Serialize the frame into dst if the frame is already serialized it just swap dst with - /// itself + /// Write the serialized `Frame` into `dst`. fn serialize(self, dst: &mut [u8]) -> Result<(), Error>; - //fn deserialize(&'a mut self) -> Result; - + /// Get the payload fn payload(&'a mut self) -> &'a mut [u8]; - /// If is an Sv2 frame return the Some(header) if it is a noise frame return None + /// Returns `Some(self.header)` when the frame has a header (`Sv2Frame`), returns `None` where it doesn't (`HandShakeFrame`). fn get_header(&self) -> Option; - /// Try to build an Frame frame from raw bytes. - /// It return the frame or the number of the bytes needed to complete the frame - /// The resulting frame is just a header plus a payload with the right number of bytes nothing - /// is said about the correctness of the payload + /// Try to build a `Frame` from raw bytes. + /// Checks if the payload has the correct size (as stated in the `Header`). + /// Returns `Self` on success, or the number of the bytes needed to complete the frame + /// as an error. Nothing is assumed or checked about the correctness of the payload. fn from_bytes(bytes: Self::Buffer) -> Result; + /// Builds a `Frame` from raw bytes. + /// Does not check if the payload has the correct size (as stated in the `Header`). + /// Nothing is assumed or checked about the correctness of the payload. fn from_bytes_unchecked(bytes: Self::Buffer) -> Self; + /// Helps to determine if the frame size encoded in a byte array correctly representing the size of the frame. + /// - Returns `0` if the byte slice is of the expected size according to the header. + /// - Returns a negative value if the byte slice is smaller than a Noise Frame header; this value + /// represents how many bytes are missing. + /// - Returns a positive value if the byte slice is longer than expected; this value + /// indicates the surplus of bytes beyond the expected size. fn size_hint(bytes: &[u8]) -> isize; + /// Returns the size of the `Frame` payload. fn encoded_length(&self) -> usize; - /// Try to build an Frame frame from a serializable payload. - /// It return a Frame if the size of the payload fit in the frame, if not it return None + /// Try to build a `Frame` from a serializable payload. + /// Returns `Some(Self)` if the size of the payload fits in the frame, `None` otherwise. fn from_message( message: T, message_type: u8, @@ -64,11 +74,12 @@ pub trait Frame<'a, T: Serialize + GetSize>: Sized { ) -> Option; } +/// Abstraction for a SV2 Frame. #[derive(Debug, Clone)] pub struct Sv2Frame { header: Header, payload: Option, - /// Serializsed header + payload + /// Serialized header + payload serialized: Option, } @@ -82,20 +93,16 @@ impl Default for Sv2Frame { } } +/// Abstraction for a Noise Handshake Frame +/// Contains only a `Slice` payload with a fixed length +/// Only used during Noise Handshake process #[derive(Debug)] -pub struct NoiseFrame { +pub struct HandShakeFrame { payload: Slice, } -pub type HandShakeFrame = NoiseFrame; - -#[cfg(feature = "with_buffer_pool")] -impl From>> for Sv2Frame { - fn from(_: EitherFrame>) -> Self { - unreachable!() - } -} -impl NoiseFrame { +impl HandShakeFrame { + /// Returns payload of `HandShakeFrame` as a `Vec` pub fn get_payload_when_handshaking(&self) -> Vec { self.payload[0..].to_vec() } @@ -105,8 +112,9 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for type Buffer = B; type Deserialized = B; - /// Serialize the frame into dst if the frame is already serialized it just swap dst with - /// itself + /// Write the serialized `Sv2Frame` into `dst`. + /// This operation when called on an already serialized frame is very cheap. + /// When called on a non serialized frame, it is not so cheap (because it serializes it). #[inline] fn serialize(self, dst: &mut [u8]) -> Result<(), Error> { if let Some(mut serialized) = self.serialized { @@ -129,30 +137,28 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for } } - // self can be either serialized (it cointain an AsMut<[u8]> with the serialized data or - // deserialized it contain the rust type that represant the Sv2 message. If the type is - // deserialized self.paylos.is_some() is true. To get the serialized payload the inner type - // should be serialized and this function should never be used, cause is intended as a fast - // function that return a reference to an already serialized payload. For that the function - // panic. + /// `self` can be either serialized (`self.serialized` is `Some()`) or + /// deserialized (`self.serialized` is `None`, `self.payload` is `Some()`). + /// This function is only intended as a fast way to get a reference to an + /// already serialized payload. If the frame has not yet been + /// serialized, this function should never be used (it will panic). fn payload(&'a mut self) -> &'a mut [u8] { if let Some(serialized) = self.serialized.as_mut() { &mut serialized.as_mut()[Header::SIZE..] } else { // panic here is the expected behaviour - panic!() + panic!("Sv2Frame is not yet serialized.") } } - /// If is an Sv2 frame return the Some(header) if it is a noise frame return None + /// `Sv2Frame` always returns `Some(self.header)`. fn get_header(&self) -> Option { Some(self.header) } - /// Try to build a Frame frame from raw bytes. - /// It return the frame or the number of the bytes needed to complete the frame - /// The resulting frame is just a header plus a payload with the right number of bytes nothing - /// is said about the correctness of the payload + /// Tries to build a `Sv2Frame` from raw bytes, assuming they represent a serialized `Sv2Frame` frame (`Self.serialized`). + /// Returns a `Sv2Frame` on success, or the number of the bytes needed to complete the frame + /// as an error. `Self.serialized` is `Some`, but nothing is assumed or checked about the correctness of the payload. #[inline] fn from_bytes(mut bytes: Self::Buffer) -> Result { let hint = Self::size_hint(bytes.as_mut()); @@ -175,23 +181,34 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for } } + /// After parsing `bytes` into a `Header`, this function helps to determine if the `msg_length` + /// field is correctly representing the size of the frame. + /// - Returns `0` if the byte slice is of the expected size according to the header. + /// - Returns a negative value if the byte slice is shorter than expected; this value + /// represents how many bytes are missing. + /// - Returns a positive value if the byte slice is longer than expected; this value + /// indicates the surplus of bytes beyond the expected size. #[inline] fn size_hint(bytes: &[u8]) -> isize { match Header::from_bytes(bytes) { Err(_) => { - // Return incorrect header length + // Returns how many bytes are missing from the expected frame size (Header::SIZE - bytes.len()) as isize } Ok(header) => { if bytes.len() - Header::SIZE == header.len() { + // expected frame size confirmed 0 } else { + // Returns how many excess bytes are beyond the expected frame size (bytes.len() - Header::SIZE) as isize + header.len() as isize } } } } + /// If `Sv2Frame` is serialized, returns the length of `self.serialized`, + /// otherwise, returns the length of `self.payload`. #[inline] fn encoded_length(&self) -> usize { if let Some(serialized) = self.serialized.as_ref() { @@ -204,8 +221,8 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for } } - /// Try to build an Frame frame from a serializable payload. - /// It returns a Frame if the size of the payload fits in the frame, if not it returns None + /// Tries to build a `Sv2Frame` from a non-serialized payload. + /// Returns a `Sv2Frame` if the size of the payload fits in the frame, `None` otherwise. fn from_message( message: T, message_type: u8, @@ -222,35 +239,29 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for } } -#[inline] -pub fn build_noise_frame_header(frame: &mut [u8], len: u16) { - frame[0] = len.to_le_bytes()[0]; - frame[1] = len.to_le_bytes()[1]; -} - -impl<'a> Frame<'a, Slice> for NoiseFrame { +impl<'a> Frame<'a, Slice> for HandShakeFrame { type Buffer = Slice; type Deserialized = &'a mut [u8]; - /// Serialize the frame into dst if the frame is already serialized it just swap dst with - /// itself + /// Put the Noise Frame payload into `dst` #[inline] fn serialize(mut self, dst: &mut [u8]) -> Result<(), Error> { dst.swap_with_slice(self.payload.as_mut()); Ok(()) } + /// Get the Noise Frame payload #[inline] fn payload(&'a mut self) -> &'a mut [u8] { &mut self.payload[NoiseHeader::HEADER_SIZE..] } - /// If is an Sv2 frame return the Some(header) if it is a noise frame return None + /// `HandShakeFrame` always returns `None`. fn get_header(&self) -> Option { None } - // For a NoiseFrame from_bytes is the same of from_bytes_unchecked + /// Builds a `HandShakeFrame` from raw bytes. Nothing is assumed or checked about the correctness of the payload. fn from_bytes(bytes: Self::Buffer) -> Result { Ok(Self::from_bytes_unchecked(bytes)) } @@ -260,6 +271,13 @@ impl<'a> Frame<'a, Slice> for NoiseFrame { Self { payload: bytes } } + /// After parsing the expected `HandShakeFrame` size from `bytes`, this function helps to determine if this value + /// correctly representing the size of the frame. + /// - Returns `0` if the byte slice is of the expected size according to the header. + /// - Returns a negative value if the byte slice is smaller than a Noise Frame header; this value + /// represents how many bytes are missing. + /// - Returns a positive value if the byte slice is longer than expected; this value + /// indicates the surplus of bytes beyond the expected size. #[inline] fn size_hint(bytes: &[u8]) -> isize { if bytes.len() < NoiseHeader::HEADER_SIZE { @@ -276,15 +294,16 @@ impl<'a> Frame<'a, Slice> for NoiseFrame { } } + /// Returns the size of the `HandShakeFrame` payload. #[inline] fn encoded_length(&self) -> usize { self.payload.len() } - /// Try to build a `Frame` frame from a serializable payload. - /// It returns a Frame if the size of the payload fits in the frame, if not it returns None - /// Inneficient should be used only to build `HandShakeFrames` - /// TODO check if is used only to build `HandShakeFrames` + /// Tries to build a `HandShakeFrame` frame from a byte slice. + /// Returns a `HandShakeFrame` if the size of the payload fits in the frame, `None` otherwise. + /// This is quite inefficient, and should be used only to build `HandShakeFrames` + // TODO check if is used only to build `HandShakeFrames` #[allow(clippy::useless_conversion)] fn from_message( message: Slice, @@ -302,6 +321,7 @@ impl<'a> Frame<'a, Slice> for NoiseFrame { } } +/// Returns a `HandShakeFrame` from a generic byte array #[allow(clippy::useless_conversion)] pub fn handshake_message_to_frame>(message: T) -> HandShakeFrame { let mut payload = Vec::new(); @@ -311,6 +331,10 @@ pub fn handshake_message_to_frame>(message: T) -> HandShakeFrame } } +/// Basically a boolean bit filter for `extension_type`. +/// Takes an `extension_type` represented as a `u16` and a boolean flag (`channel_msg`). +/// If `channel_msg` is true, it sets the most significant bit of `extension_type` to 1, +/// otherwise, it clears the most significant bit to 0. fn update_extension_type(extension_type: u16, channel_msg: bool) -> u16 { if channel_msg { let mask = 0b1000_0000_0000_0000; @@ -321,11 +345,8 @@ fn update_extension_type(extension_type: u16, channel_msg: bool) -> u16 { } } -/// A frame can be either -/// 1: Sv2Frame -/// 2: NoiseFrame -/// 3: HandashakeFrame -/// +/// A wrapper to be used in a context we need a generic reference to a frame +/// but it doesn't matter which kind of frame it is (`Sv2Frame` or `HandShakeFrame`) #[derive(Debug)] pub enum EitherFrame { HandShake(HandShakeFrame), diff --git a/protocols/v2/framing-sv2/src/header.rs b/protocols/v2/framing-sv2/src/header.rs index 4262e90ad..05272b52a 100644 --- a/protocols/v2/framing-sv2/src/header.rs +++ b/protocols/v2/framing-sv2/src/header.rs @@ -7,6 +7,7 @@ use binary_sv2::{Deserialize, Serialize, U24}; use const_sv2::{AEAD_MAC_LEN, SV2_FRAME_CHUNK_SIZE}; use core::convert::TryInto; +/// Abstraction for a SV2 Frame Header. #[derive(Debug, Serialize, Deserialize, Copy, Clone)] pub struct Header { extension_type: u16, // TODO use specific type? @@ -32,6 +33,7 @@ impl Header { pub const SIZE: usize = const_sv2::SV2_FRAME_HEADER_SIZE; + /// Construct a `Header` from ray bytes #[inline] pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() < Self::SIZE { @@ -52,6 +54,7 @@ impl Header { }) } + /// Get the payload length #[allow(clippy::len_without_is_empty)] #[inline] pub fn len(&self) -> usize { @@ -59,6 +62,7 @@ impl Header { inner as usize } + /// Construct a `Header` from payload length, type and extension type. #[inline] pub fn from_len(len: u32, message_type: u8, extension_type: u16) -> Option
{ Some(Self { @@ -68,19 +72,23 @@ impl Header { }) } + /// Get the `Header` message type. pub fn msg_type(&self) -> u8 { self.msg_type } + /// Get the `Header` extension type. pub fn ext_type(&self) -> u16 { self.extension_type } + /// Check if `Header` represents a channel message pub fn channel_msg(&self) -> bool { let mask = 0b0000_0000_0000_0001; self.extension_type & mask == self.extension_type } + /// Calculate the length of the encrypted `Header` pub fn encrypted_len(&self) -> usize { let len = self.len(); let mut chunks = len / (SV2_FRAME_CHUNK_SIZE - AEAD_MAC_LEN); diff --git a/protocols/v2/framing-sv2/src/lib.rs b/protocols/v2/framing-sv2/src/lib.rs index 64fa5a7fd..34fe8708b 100644 --- a/protocols/v2/framing-sv2/src/lib.rs +++ b/protocols/v2/framing-sv2/src/lib.rs @@ -1,25 +1,33 @@ +//! The SV2 protocol is binary, with fixed message framing. +//! Each message begins with the extension type, message type, and message length (six bytes in total), followed by a variable length message. +//! +//! This crate provides primitives for framing of SV2 binary messages. +//! +//! The message framing is outlined below ([according to SV2 specs](https://stratumprotocol.org/specification/03-Protocol-Overview/#32-framing)): +//! +//! | Protocol Type | Byte Length | Description | +//! |----------------|-------------|-------------| +//! | `extension_type` | `U16` | Unique identifier of the extension describing this protocol message.

Most significant bit (i.e.bit `15`, `0`-indexed, aka `channel_msg`) indicates a message which is specific to a channel, whereas if the most significant bit is unset, the message is to be interpreted by the immediate receiving device.

Note that the `channel_msg` bit is ignored in the extension lookup, i.e.an `extension_type` of `0x8ABC` is for the same "extension" as `0x0ABC`.

If the `channel_msg` bit is set, the first four bytes of the payload field is a `U32` representing the `channel_id` this message is destined for (these bytes are repeated in the message framing descriptions below).

Note that for the Job Declaration and Template Distribution Protocols the `channel_msg` bit is always unset. | +//! | `msg_type` | `U8` | Unique identifier of the extension describing this protocol message. | +//! | `msg_length` | `U24` | Length of the protocol message, not including this header. | +//! | `payload` | `BYTES` | Message-specific payload of length `msg_length`. If the MSB in `extension_type` (the `channel_msg` bit) is set the first four bytes are defined as a `U32` `"channel_id"`, though this definition is repeated in the message definitions below and these 4 bytes are included in `msg_length`. | +//! +//! # Features +//! This crate can be built with the following features: +//! - `with_serde`: builds `binary_sv2` and `buffer_sv2` crates with `serde`-based encoding and decoding. +//! - `with_buffer_pool`: uses `buffer_sv2` to provide a more efficient allocation method for `non_std` environments. Please refer to `buffer_sv2` crate docs for more context. +//! +//! The `with_serde` feature flag is only used for the Message Generator, and deprecated for any other kind of usage. It will likely be fully deprecated in the future. + #![no_std] extern crate alloc; -/// -/// Sv2 messages are framed as -/// ```txt -/// extension type: u16 -/// msg type: u8 -/// msg length: u24 -/// payload: [u8; msg length] -/// ``` -/// -/// Sv2 messages can be encapsulated in noise messages, noise messages are framed as: -/// -/// ```txt -/// msg length: u16 -/// payload: [u8; msg length] -/// ``` -/// -/// +/// SV2 framing types pub mod framing2; +/// SV2 framing errors pub mod error; + +/// SV2 framing header pub mod header; pub use error::Error; From 73a78501db22fe3f05c7a76ce38963bab6a16013 Mon Sep 17 00:00:00 2001 From: Innocent Onyemaenu Date: Mon, 13 May 2024 18:42:35 +0100 Subject: [PATCH 27/39] better import for libsecp256k1 (#894) --- benches/Cargo.lock | 3 +- common/Cargo.lock | 88 +- common/Cargo.toml | 1 + common/src/lib.rs | 1 + protocols/Cargo.lock | 43 +- roles/Cargo.lock | 3 +- roles/jd-server/Cargo.toml | 1 - roles/jd-server/src/lib/job_declarator/mod.rs | 13 +- roles/pool/Cargo.toml | 1 - roles/pool/src/lib/mining_pool/mod.rs | 20 +- utils/Cargo.lock | 1050 +++++++++++++++++ utils/key-utils/src/lib.rs | 49 +- 12 files changed, 1218 insertions(+), 55 deletions(-) create mode 100644 utils/Cargo.lock diff --git a/benches/Cargo.lock b/benches/Cargo.lock index 230f266d7..adf916946 100644 --- a/benches/Cargo.lock +++ b/benches/Cargo.lock @@ -1070,7 +1070,7 @@ dependencies = [ [[package]] name = "network_helpers_sv2" -version = "1.0.1" +version = "2.0.0" dependencies = [ "async-channel 1.9.0", "async-std", @@ -1553,6 +1553,7 @@ name = "stratum-common" version = "1.0.0" dependencies = [ "bitcoin 0.29.2", + "secp256k1 0.28.2", ] [[package]] diff --git a/common/Cargo.lock b/common/Cargo.lock index ad03258e2..0d9e63408 100644 --- a/common/Cargo.lock +++ b/common/Cargo.lock @@ -16,7 +16,7 @@ checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" dependencies = [ "bech32", "bitcoin_hashes", - "secp256k1", + "secp256k1 0.24.3", ] [[package]] @@ -27,18 +27,68 @@ checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ + "cfg-if", "libc", + "wasi", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "secp256k1" @@ -47,7 +97,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ "bitcoin_hashes", - "secp256k1-sys", + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "rand", + "secp256k1-sys 0.9.2", ] [[package]] @@ -59,9 +119,25 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + [[package]] name = "stratum-common" version = "1.0.0" dependencies = [ "bitcoin", + "secp256k1 0.28.2", ] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/common/Cargo.toml b/common/Cargo.toml index 0ad48861f..3b9d7cc2c 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -8,3 +8,4 @@ repository = "https://github.com/stratum-mining/stratum" [dependencies] bitcoin = {version="0.29.1",optional=true} +secp256k1 = { version = "0.28.2", default-features = false, features =["alloc","rand","rand-std"] } diff --git a/common/src/lib.rs b/common/src/lib.rs index 74b0562c9..242c7acb3 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -4,3 +4,4 @@ //! and manage the shared dependencies and utils across stratum crates. #[cfg(feature = "bitcoin")] pub use bitcoin; +pub use secp256k1; diff --git a/protocols/Cargo.lock b/protocols/Cargo.lock index eff20eb55..0ed90a476 100644 --- a/protocols/Cargo.lock +++ b/protocols/Cargo.lock @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bech32" @@ -152,9 +152,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cfg-if" @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -501,9 +501,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -629,9 +629,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "secp256k1" @@ -674,29 +674,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.62", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -711,7 +711,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.62", ] [[package]] @@ -733,6 +733,7 @@ name = "stratum-common" version = "1.0.0" dependencies = [ "bitcoin", + "secp256k1 0.28.2", ] [[package]] @@ -784,9 +785,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "9f660c3bfcefb88c538776b6685a0c472e3128b51e74d48793dc2a488196e8eb" dependencies = [ "proc-macro2", "quote", @@ -841,7 +842,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.62", ] [[package]] diff --git a/roles/Cargo.lock b/roles/Cargo.lock index d245c93d3..1c0dc4d8f 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -1242,7 +1242,6 @@ dependencies = [ "rand", "roles_logic_sv2", "rpc_sv2", - "secp256k1 0.28.2", "serde", "serde_json", "stratum-common", @@ -1663,7 +1662,6 @@ dependencies = [ "noise_sv2", "rand", "roles_logic_sv2", - "secp256k1 0.28.2", "serde", "stratum-common", "tokio", @@ -2023,6 +2021,7 @@ name = "stratum-common" version = "1.0.0" dependencies = [ "bitcoin", + "secp256k1 0.28.2", ] [[package]] diff --git a/roles/jd-server/Cargo.toml b/roles/jd-server/Cargo.toml index 83156cfcd..6f55ece06 100644 --- a/roles/jd-server/Cargo.toml +++ b/roles/jd-server/Cargo.toml @@ -30,6 +30,5 @@ serde_json = { version = "1.0", default-features = false, features = ["alloc","r serde = { version = "1.0.89", features = ["derive", "alloc"], default-features = false } hashbrown = { version = "0.11", default-features = false, features = ["ahash", "serde"] } key-utils = { version = "^1.0.0", path = "../../utils/key-utils" } -secp256k1 = { version = "0.28.2", default-features = false, features =["alloc","rand","rand-std"] } rpc_sv2 = { version = "1.0.0", path = "../roles-utils/rpc" } hex = "0.4.3" diff --git a/roles/jd-server/src/lib/job_declarator/mod.rs b/roles/jd-server/src/lib/job_declarator/mod.rs index 3a3405cd7..56d56223c 100644 --- a/roles/jd-server/src/lib/job_declarator/mod.rs +++ b/roles/jd-server/src/lib/job_declarator/mod.rs @@ -4,7 +4,7 @@ use async_channel::{Receiver, Sender}; use binary_sv2::{B0255, U256}; use codec_sv2::{Frame, HandshakeRole, Responder}; use error_handling::handle_result; -use key_utils::{Secp256k1PublicKey, Secp256k1SecretKey}; +use key_utils::{Secp256k1PublicKey, Secp256k1SecretKey, SignatureService}; use network_helpers_sv2::noise_connection_tokio::Connection; use nohash_hasher::BuildNoHashHasher; use roles_logic_sv2::{ @@ -14,7 +14,6 @@ use roles_logic_sv2::{ parsers::{JobDeclaration, PoolMessages as JdsMessages}, utils::{Id, Mutex}, }; -use secp256k1::{Keypair, Message as SecpMessage, Secp256k1}; use std::{collections::HashMap, convert::TryInto, sync::Arc}; use tokio::{net::TcpListener, time::Duration}; use tracing::{debug, error, info}; @@ -395,15 +394,9 @@ pub fn signed_token( _pub_key: &Secp256k1PublicKey, prv_key: &Secp256k1SecretKey, ) -> B0255<'static> { - let secp = Secp256k1::signing_only(); + let secp = SignatureService::default(); - // Create the SecretKey and PublicKey instances - let secret_key = prv_key.0; - let kp = Keypair::from_secret_key(&secp, &secret_key); - - let message: Vec = tx_hash_list_hash.to_vec(); - - let signature = secp.sign_schnorr(&SecpMessage::from_digest_slice(&message).unwrap(), &kp); + let signature = secp.sign(tx_hash_list_hash.to_vec(), prv_key.0); // Sign message signature.as_ref().to_vec().try_into().unwrap() diff --git a/roles/pool/Cargo.toml b/roles/pool/Cargo.toml index 61005f00b..3b62c74e1 100644 --- a/roles/pool/Cargo.toml +++ b/roles/pool/Cargo.toml @@ -30,7 +30,6 @@ async-recursion = "1.0.0" error_handling = { version = "1.0.0", path = "../../utils/error-handling" } nohash-hasher = "0.2.0" key-utils = { version = "^1.0.0", path = "../../utils/key-utils" } -secp256k1 = { version = "0.28.2", default-features = false, features =["alloc","rand","rand-std"] } [dev-dependencies] hex = "0.4.3" diff --git a/roles/pool/src/lib/mining_pool/mod.rs b/roles/pool/src/lib/mining_pool/mod.rs index 6f2bec307..e189c5406 100644 --- a/roles/pool/src/lib/mining_pool/mod.rs +++ b/roles/pool/src/lib/mining_pool/mod.rs @@ -6,7 +6,7 @@ use async_channel::{Receiver, Sender}; use binary_sv2::U256; use codec_sv2::{Frame, HandshakeRole, Responder, StandardEitherFrame, StandardSv2Frame}; use error_handling::handle_result; -use key_utils::{Secp256k1PublicKey, Secp256k1SecretKey}; +use key_utils::{Secp256k1PublicKey, Secp256k1SecretKey, SignatureService}; use network_helpers_sv2::noise_connection_tokio::Connection; use nohash_hasher::BuildNoHashHasher; use roles_logic_sv2::{ @@ -28,7 +28,10 @@ use std::{ net::SocketAddr, sync::Arc, }; -use stratum_common::bitcoin::{Script, TxOut}; +use stratum_common::{ + bitcoin::{Script, TxOut}, + secp256k1, +}; use tokio::{net::TcpListener, task}; use tracing::{debug, error, info, warn}; @@ -283,18 +286,11 @@ pub fn verify_token( signature: secp256k1::schnorr::Signature, pub_key: key_utils::Secp256k1PublicKey, ) -> Result<(), secp256k1::Error> { - let secp = secp256k1::Secp256k1::verification_only(); - // Create PublicKey instance - let x_only_public_key = pub_key.0; - let message: Vec = tx_hash_list_hash.to_vec(); - // Verify signature - let is_verified = secp.verify_schnorr( - &signature, - &secp256k1::Message::from_digest_slice(&message)?, - &x_only_public_key, - ); + let secp = SignatureService::default(); + + let is_verified = secp.verify(tx_hash_list_hash.to_vec(), signature, pub_key.0); // debug debug!("Message: {}", std::str::from_utf8(&message).unwrap()); diff --git a/utils/Cargo.lock b/utils/Cargo.lock new file mode 100644 index 000000000..3c7e5d36c --- /dev/null +++ b/utils/Cargo.lock @@ -0,0 +1,1050 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "amplify" +version = "3.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2ec14f4fb838e9ddace42fa5944bb1ee4dff8477494ba48c5f874e16caf27a" +dependencies = [ + "amplify_derive", + "amplify_num", + "wasm-bindgen", +] + +[[package]] +name = "amplify_derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c3de270e75f27a4468a7c344070109046656e85cb522141f7d40ab4b83803ac" +dependencies = [ + "amplify_syn", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "amplify_num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27d3d00d3d115395a7a8a4dc045feb7aa82b641e485f7e15f4e67ac16f4f56d" + +[[package]] +name = "amplify_syn" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da24db1445cc7bc3842fa072c2d51fe5b25b812b6a572d65842a4c72e87221ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "bip32_derivation" +version = "1.0.0" +dependencies = [ + "slip132", + "stratum-common", + "toml", +] + +[[package]] +name = "bitcoin" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" +dependencies = [ + "bech32", + "bitcoin_hashes", + "secp256k1 0.24.3", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +dependencies = [ + "sha2", +] + +[[package]] +name = "buffer_sv2" +version = "1.0.0" +dependencies = [ + "aes-gcm", + "criterion", + "iai", + "rand", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags", + "textwrap", + "unicode-width", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "criterion" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "error_handling" +version = "1.0.0" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hashbrown" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" +dependencies = [ + "ahash", + "autocfg", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "iai" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "key-utils" +version = "1.0.0" +dependencies = [ + "bs58", + "secp256k1 0.28.2", + "serde", + "toml", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "rand", + "secp256k1-sys 0.9.2", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "serde" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.62", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "slip132" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbc5035a82511d65570e5731ad66fc69893ad0adc3fbbf1a0bb7aa534e89fb" +dependencies = [ + "amplify", + "bitcoin", +] + +[[package]] +name = "stratum-common" +version = "1.0.0" +dependencies = [ + "bitcoin", + "secp256k1 0.28.2", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f660c3bfcefb88c538776b6685a0c472e3128b51e74d48793dc2a488196e8eb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "toml" +version = "0.5.6" +source = "git+https://github.com/diondokter/toml-rs?rev=c4161aa#c4161aa70202b3992dbec79b76e7a8659713b604" +dependencies = [ + "hashbrown", + "serde", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.62", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.62", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/utils/key-utils/src/lib.rs b/utils/key-utils/src/lib.rs index 4cde25083..9643b060b 100644 --- a/utils/key-utils/src/lib.rs +++ b/utils/key-utils/src/lib.rs @@ -1,6 +1,9 @@ use bs58::{decode, decode::Error as Bs58DecodeError}; use core::convert::TryFrom; -use secp256k1::{SecretKey, XOnlyPublicKey}; +use secp256k1::{ + schnorr::Signature, Keypair, Message as SecpMessage, Secp256k1, SecretKey, SignOnly, + VerifyOnly, XOnlyPublicKey, +}; use serde::{Deserialize, Serialize}; use std::{fmt::Display, str::FromStr}; @@ -141,6 +144,50 @@ impl From for Secp256k1PublicKey { } } +pub struct SignatureService { + secp_sign: Secp256k1, + secp_verify: Secp256k1, +} + +impl SignatureService { + pub fn new() -> Self { + SignatureService { + secp_sign: Secp256k1::signing_only(), + secp_verify: Secp256k1::verification_only(), + } + } + + pub fn sign(&self, message: Vec, private_key: SecretKey) -> Signature { + let secret_key = private_key; + let kp = Keypair::from_secret_key(&self.secp_sign, &secret_key); + + self.secp_sign + .sign_schnorr(&SecpMessage::from_digest_slice(&message).unwrap(), &kp) + } + + pub fn verify( + &self, + message: Vec, + signature: secp256k1::schnorr::Signature, + public_key: XOnlyPublicKey, + ) -> Result<(), secp256k1::Error> { + let x_only_public_key = public_key; + + // Verify signature + self.secp_verify.verify_schnorr( + &signature, + &secp256k1::Message::from_digest_slice(&message)?, + &x_only_public_key, + ) + } +} + +impl Default for SignatureService { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod test { use super::*; From 7bbffd4db831b8aa9d9ba66983b9d26d9aae7268 Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Tue, 14 May 2024 11:53:26 -0300 Subject: [PATCH 28/39] tproxy-config-hosted-pool-example (#875) --- .../tproxy-config-hosted-pool-example.toml | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 roles/translator/config-examples/tproxy-config-hosted-pool-example.toml diff --git a/roles/translator/config-examples/tproxy-config-hosted-pool-example.toml b/roles/translator/config-examples/tproxy-config-hosted-pool-example.toml new file mode 100644 index 000000000..47d4ea875 --- /dev/null +++ b/roles/translator/config-examples/tproxy-config-hosted-pool-example.toml @@ -0,0 +1,36 @@ +# Braiins Pool Upstream Connection +# upstream_authority_pubkey = "u95GEReVMjK6k5YqiSFNqqTnKU4ypU2Wm8awa6tmbmDmk1bWt" +# upstream_address = "18.196.32.109" +# upstream_port = 3336 + +# Hosted SRI Pool Upstream Connection +upstream_address = "75.119.150.111" +upstream_port = 34254 +upstream_authority_pubkey = "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72" + +# Local Mining Device Downstream Connection +downstream_address = "0.0.0.0" +downstream_port = 34255 + +# Version support +max_supported_version = 2 +min_supported_version = 2 + +# Minimum extranonce2 size for downstream +# Max value: 16 (leaves 0 bytes for search space splitting of downstreams) +# Max value for CGminer: 8 +# Min value: 2 +min_extranonce2_size = 8 + +# Difficulty params +[downstream_difficulty_config] +# hashes/s of the weakest miner that will be connecting (e.g.: 10 Th/s = 10_000_000_000_000.0) +min_individual_miner_hashrate=10_000_000_000_000.0 +# target number of shares per minute the miner should be sending +shares_per_minute = 6.0 + +[upstream_difficulty_config] +# interval in seconds to elapse before updating channel hashrate with the pool +channel_diff_update_interval = 60 +# estimated accumulated hashrate of all downstream miners (e.g.: 10 Th/s = 10_000_000_000_000.0) +channel_nominal_hashrate = 10_000_000_000_000.0 From bd494af626bf75dbd8f21df21df74240c72d1550 Mon Sep 17 00:00:00 2001 From: Fi3 Date: Thu, 16 May 2024 23:38:43 +0200 Subject: [PATCH 29/39] Fix cpu miner panic when not header (#908) Co-authored-by: fi3 --- roles/test-utils/mining-device/src/main.rs | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/roles/test-utils/mining-device/src/main.rs b/roles/test-utils/mining-device/src/main.rs index 36dff2986..1bfbf6737 100644 --- a/roles/test-utils/mining-device/src/main.rs +++ b/roles/test-utils/mining-device/src/main.rs @@ -595,17 +595,21 @@ impl Miner { self.header = Some(header); } pub fn next_share(&mut self) -> NextShareOutcome { - let header = self.header.as_ref().unwrap(); - let mut hash = header.block_hash().as_hash().into_inner(); - hash.reverse(); - let hash = Uint256::from_be_bytes(hash); - if hash < *self.target.as_ref().unwrap() { - info!( - "Found share with nonce: {}, for target: {:?}, with hash: {:?}", - header.nonce, self.target, hash, - ); - NextShareOutcome::ValidShare + if let Some(header) = self.header.as_ref() { + let mut hash = header.block_hash().as_hash().into_inner(); + hash.reverse(); + let hash = Uint256::from_be_bytes(hash); + if hash < *self.target.as_ref().unwrap() { + info!( + "Found share with nonce: {}, for target: {:?}, with hash: {:?}", + header.nonce, self.target, hash, + ); + NextShareOutcome::ValidShare + } else { + NextShareOutcome::InvalidShare + } } else { + std::thread::yield_now(); NextShareOutcome::InvalidShare } } From eea5655f5b75b2edce1f94fe80c75f28858072c4 Mon Sep 17 00:00:00 2001 From: Gabriele Vernetti <62447440+GitGab19@users.noreply.github.com> Date: Fri, 17 May 2024 16:14:00 +0200 Subject: [PATCH 30/39] Discard old ProvideMissingTransactionsSuccess messages in JDS (#900) --- .../src/lib/job_declarator/message_handler.rs | 91 +++++++++++-------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/roles/jd-server/src/lib/job_declarator/message_handler.rs b/roles/jd-server/src/lib/job_declarator/message_handler.rs index 58a40fcba..96887bdd0 100644 --- a/roles/jd-server/src/lib/job_declarator/message_handler.rs +++ b/roles/jd-server/src/lib/job_declarator/message_handler.rs @@ -154,46 +154,63 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { &mut self, message: ProvideMissingTransactionsSuccess, ) -> Result { - let (_, ref mut transactions_with_state, missing_indexes) = &mut self.declared_mining_job; + let (declared_mining_job, ref mut transactions_with_state, missing_indexes) = + &mut self.declared_mining_job; let mut unknown_transactions: Vec = vec![]; - for (i, tx) in message.transaction_list.inner_as_ref().iter().enumerate() { - let mut cursor = Cursor::new(tx); - let transaction = Transaction::consensus_decode_from_finite_reader(&mut cursor) - .map_err(|e| Error::TxDecodingError(e.to_string()))?; - Vec::push(&mut unknown_transactions, transaction.clone()); - let index = *missing_indexes - .get(i) - .ok_or(Error::LogicErrorMessage(Box::new( - AllMessages::JobDeclaration(JobDeclaration::ProvideMissingTransactionsSuccess( - message.clone().into_static(), - )), - )))? as usize; - // insert the missing transactions in the mempool - transactions_with_state[index] = TransactionState::PresentInMempool(transaction.txid()); - } - self.add_txs_to_mempool - .add_txs_to_mempool_inner - .unknown_transactions - .append(&mut unknown_transactions); - // if there still a missing transaction return an error - for tx_with_state in transactions_with_state { - match tx_with_state { - TransactionState::PresentInMempool(_) => continue, - TransactionState::Missing => return Err(Error::JDSMissingTransactions), + match declared_mining_job { + Some(declared_job) => { + let id = declared_job.request_id; + // check request_id in order to ignore old ProvideMissingTransactionsSuccess (see issue #860) + if id == message.request_id { + for (i, tx) in message.transaction_list.inner_as_ref().iter().enumerate() { + let mut cursor = Cursor::new(tx); + let transaction = + Transaction::consensus_decode_from_finite_reader(&mut cursor) + .map_err(|e| Error::TxDecodingError(e.to_string()))?; + Vec::push(&mut unknown_transactions, transaction.clone()); + let index = + *missing_indexes + .get(i) + .ok_or(Error::LogicErrorMessage(Box::new( + AllMessages::JobDeclaration( + JobDeclaration::ProvideMissingTransactionsSuccess( + message.clone().into_static(), + ), + ), + )))? as usize; + // insert the missing transactions in the mempool + transactions_with_state[index] = + TransactionState::PresentInMempool(transaction.txid()); + } + self.add_txs_to_mempool + .add_txs_to_mempool_inner + .unknown_transactions + .append(&mut unknown_transactions); + // if there still a missing transaction return an error + for tx_with_state in transactions_with_state { + match tx_with_state { + TransactionState::PresentInMempool(_) => continue, + TransactionState::Missing => return Err(Error::JDSMissingTransactions), + } + } + // TODO check it + let tx_hash_list_hash = self.tx_hash_list_hash.clone().unwrap().into_static(); + let message_success = DeclareMiningJobSuccess { + request_id: message.request_id, + new_mining_job_token: signed_token( + tx_hash_list_hash, + &self.public_key.clone(), + &self.private_key.clone(), + ), + }; + let message_enum_success = + JobDeclaration::DeclareMiningJobSuccess(message_success); + return Ok(SendTo::Respond(message_enum_success)); + } } + None => return Err(Error::NoValidJob), } - // TODO check it - let tx_hash_list_hash = self.tx_hash_list_hash.clone().unwrap().into_static(); - let message_success = DeclareMiningJobSuccess { - request_id: message.request_id, - new_mining_job_token: signed_token( - tx_hash_list_hash, - &self.public_key.clone(), - &self.private_key.clone(), - ), - }; - let message_enum_success = JobDeclaration::DeclareMiningJobSuccess(message_success); - Ok(SendTo::Respond(message_enum_success)) + Ok(SendTo::None(None)) } fn handle_submit_solution(&mut self, message: SubmitSolutionJd<'_>) -> Result { From 93746072c66211c02dc0e3fff8a529a742ce1422 Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Sun, 19 May 2024 09:22:19 -0300 Subject: [PATCH 31/39] bump framing_sv2 version (#913) --- benches/Cargo.toml | 2 +- protocols/v2/codec-sv2/Cargo.toml | 2 +- protocols/v2/framing-sv2/Cargo.toml | 2 +- protocols/v2/roles-logic-sv2/Cargo.toml | 2 +- roles/jd-client/Cargo.toml | 2 +- roles/translator/Cargo.toml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/benches/Cargo.toml b/benches/Cargo.toml index f9adf44d6..ecba50ab8 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -12,7 +12,7 @@ serde_json = { version = "1.0.64", default-features = false, features = ["alloc" iai="0.1" mining_sv2 = { path = "../protocols/v2/subprotocols/mining", version = "^1.0.0" } roles_logic_sv2 = { path = "../protocols/v2/roles-logic-sv2", version = "^1.0.0" } -framing_sv2 = { version = "1.0.0", path = "../protocols/v2/framing-sv2" } +framing_sv2 = { version = "1.1.0", path = "../protocols/v2/framing-sv2" } serde = { version = "1.0.89", default-features = false, features = ["derive", "alloc"] } num-bigint = "0.4.3" num-traits = "0.2.15" diff --git a/protocols/v2/codec-sv2/Cargo.toml b/protocols/v2/codec-sv2/Cargo.toml index e7be2e3eb..7b5cbb36b 100644 --- a/protocols/v2/codec-sv2/Cargo.toml +++ b/protocols/v2/codec-sv2/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/stratum-mining/stratum" [dependencies] serde = { version = "1.0.89", default-features = false, optional = true } -framing_sv2 = { version = "1.0.0", path = "../../../protocols/v2/framing-sv2" } +framing_sv2 = { version = "1.1.0", path = "../../../protocols/v2/framing-sv2" } noise_sv2 = { version = "1.0", path = "../../../protocols/v2/noise-sv2", optional=true} binary_sv2 = { version = "1.0.0", path = "../../../protocols/v2/binary-sv2/binary-sv2" } const_sv2 = { version = "1.0.0", path = "../../../protocols/v2/const-sv2"} diff --git a/protocols/v2/framing-sv2/Cargo.toml b/protocols/v2/framing-sv2/Cargo.toml index 551eb4645..67465688d 100644 --- a/protocols/v2/framing-sv2/Cargo.toml +++ b/protocols/v2/framing-sv2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "framing_sv2" -version = "1.0.0" +version = "1.1.0" authors = ["fi3 "] edition = "2018" description = "Sv2 frames" diff --git a/protocols/v2/roles-logic-sv2/Cargo.toml b/protocols/v2/roles-logic-sv2/Cargo.toml index 526a13ed5..1fcacf0b2 100644 --- a/protocols/v2/roles-logic-sv2/Cargo.toml +++ b/protocols/v2/roles-logic-sv2/Cargo.toml @@ -17,7 +17,7 @@ mining_sv2 = { path = "../../../protocols/v2/subprotocols/mining", version = "^1 template_distribution_sv2 = { path = "../../../protocols/v2/subprotocols/template-distribution", version = "^1.0.0" } job_declaration_sv2 = { path = "../../../protocols/v2/subprotocols/job-declaration", version = "^1.0.0" } const_sv2 = { version = "^1.0.0", path = "../../../protocols/v2/const-sv2"} -framing_sv2 = { version = "^1.0.0", path = "../../../protocols/v2/framing-sv2" } +framing_sv2 = { version = "^1.1.0", path = "../../../protocols/v2/framing-sv2" } tracing = { version = "0.1"} chacha20poly1305 = { version = "0.10.1"} nohash-hasher = "0.2.0" diff --git a/roles/jd-client/Cargo.toml b/roles/jd-client/Cargo.toml index d0693fdb2..4c79016d0 100644 --- a/roles/jd-client/Cargo.toml +++ b/roles/jd-client/Cargo.toml @@ -17,7 +17,7 @@ async-recursion = "0.3.2" binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary-sv2" } buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" } codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2", "with_buffer_pool"] } -framing_sv2 = { version = "^1.0.0", path = "../../protocols/v2/framing-sv2" } +framing_sv2 = { version = "^1.1.0", path = "../../protocols/v2/framing-sv2" } network_helpers_sv2 = { version = "2.0.0", path = "../roles-utils/network-helpers", features=["with_tokio", "with_buffer_pool"] } roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" } serde = { version = "1.0.89", default-features = false, features = ["derive", "alloc"] } diff --git a/roles/translator/Cargo.toml b/roles/translator/Cargo.toml index bdba3cf11..182370cbd 100644 --- a/roles/translator/Cargo.toml +++ b/roles/translator/Cargo.toml @@ -18,7 +18,7 @@ async-std = { version = "1.12.0", features = ["attributes"] } binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary-sv2" } buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" } codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2", "with_buffer_pool"] } -framing_sv2 = { version = "^1.0.0", path = "../../protocols/v2/framing-sv2" } +framing_sv2 = { version = "^1.1.0", path = "../../protocols/v2/framing-sv2" } network_helpers_sv2 = { version = "2.0.0", path = "../roles-utils/network-helpers", features=["async_std", "with_buffer_pool"] } once_cell = "1.12.0" roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" } From 8ccc4d60aabc6ac470cde4377821bb24d54db807 Mon Sep 17 00:00:00 2001 From: lorban <84277969+lorbax@users.noreply.github.com> Date: Tue, 21 May 2024 00:01:36 +0200 Subject: [PATCH 32/39] Every MG test in a separate action (#905) --- .github/workflows/coverage.yaml | 63 +++++++++++++--- code-coverage-report.sh | 4 + message-generator-tests.sh | 21 ++---- .../bad-pool-config-test.json | 5 +- .../bad-pool-config-test.sh | 9 +++ .../interop-jd-translator.json | 0 .../interop-jd-translator.sh | 13 ++++ .../interop-jdc-change-upstream.json | 6 ++ .../interop-jdc-change-upstream.sh | 12 +++ ...interop-proxy-with-multi-ups-extended.json | 0 .../interop-proxy-with-multi-ups-extended.sh | 11 +++ .../interop-proxy-with-multi-ups.json | 0 .../interop-proxy-with-multi-ups.sh | 11 +++ .../jds-do-not-fail-on-wrong-tsdatasucc.json | 0 .../jds-do-not-fail-on-wrong-tsdatasucc.sh | 9 +++ ...-do-not-panic-if-jdc-close-connection.json | 0 ...ds-do-not-panic-if-jdc-close-connection.sh | 9 +++ ...ds-do-not-stackoverflow-when-no-token.json | 0 .../jds-do-not-stackoverflow-when-no-token.sh | 11 +++ .../pool-sri-test-1-standard.json | 73 +++++++------------ .../pool-sri-test-1-standard.sh | 9 +++ .../pool-sri-test-close-channel.json | 5 ++ .../pool-sri-test-close-channel.sh | 9 +++ .../pool-sri-test-extended_0.json | 0 .../pool-sri-test-extended_0.sh | 7 ++ .../pool-sri-test-extended_1.json | 0 .../pool-sri-test-extended_1.sh | 9 +++ .../pool-sri-test-reject-auth.json | 2 +- .../pool-sri-test-reject-auth.sh | 9 +++ .../standard-coverage-test.json | 21 ------ .../standard-coverage-test.sh | 9 +++ .../test/{ => sv1-test}/sv1-test.json | 11 +++ .../test/sv1-test/sv1-test.sh | 10 +++ .../translation-proxy-broke-pool.json | 6 ++ .../translation-proxy-broke-pool.sh | 9 +++ .../translation-proxy.json | 10 +++ .../translation-proxy/translation-proxy.sh | 10 +++ utils/message-generator/Cargo.lock | 11 +-- utils/message-generator/README.md | 1 + utils/message-generator/src/main.rs | 19 +++-- 40 files changed, 317 insertions(+), 107 deletions(-) create mode 100755 code-coverage-report.sh rename test/message-generator/test/{ => bad-pool-config-test}/bad-pool-config-test.json (98%) create mode 100755 test/message-generator/test/bad-pool-config-test/bad-pool-config-test.sh rename test/message-generator/test/{ => interop-jd-translator}/interop-jd-translator.json (100%) create mode 100755 test/message-generator/test/interop-jd-translator/interop-jd-translator.sh rename test/message-generator/test/{ => interop-jdc-change-upstream}/interop-jdc-change-upstream.json (97%) create mode 100755 test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.sh rename test/message-generator/test/{ => interop-proxy-with-multi-ups-extended}/interop-proxy-with-multi-ups-extended.json (100%) create mode 100755 test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.sh rename test/message-generator/test/{ => interop-proxy-with-multi-ups}/interop-proxy-with-multi-ups.json (100%) create mode 100755 test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.sh rename test/message-generator/test/{ => jds-do-not-fail-on-wrong-tsdatasucc}/jds-do-not-fail-on-wrong-tsdatasucc.json (100%) create mode 100755 test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.sh rename test/message-generator/test/{ => jds-do-not-panic-if-jdc-close-connection}/jds-do-not-panic-if-jdc-close-connection.json (100%) create mode 100755 test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.sh rename test/message-generator/test/{ => jds-do-not-stackoverflow-when-no-token}/jds-do-not-stackoverflow-when-no-token.json (100%) create mode 100755 test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.sh rename test/message-generator/test/{ => pool-sri-test-1-standard}/pool-sri-test-1-standard.json (78%) create mode 100755 test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.sh rename test/message-generator/test/{ => pool-sri-test-close-channel}/pool-sri-test-close-channel.json (96%) create mode 100755 test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.sh rename test/message-generator/test/{ => pool-sri-test-extended_0}/pool-sri-test-extended_0.json (100%) create mode 100755 test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.sh rename test/message-generator/test/{ => pool-sri-test-extended_1}/pool-sri-test-extended_1.json (100%) create mode 100755 test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.sh rename test/message-generator/test/{ => pool-sri-test-reject-auth}/pool-sri-test-reject-auth.json (98%) create mode 100755 test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.sh rename test/message-generator/test/{ => standard-coverage-test}/standard-coverage-test.json (89%) create mode 100755 test/message-generator/test/standard-coverage-test/standard-coverage-test.sh rename test/message-generator/test/{ => sv1-test}/sv1-test.json (94%) create mode 100755 test/message-generator/test/sv1-test/sv1-test.sh rename test/message-generator/test/{ => translation-proxy-broke-pool}/translation-proxy-broke-pool.json (95%) create mode 100755 test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.sh rename test/message-generator/test/{ => translation-proxy}/translation-proxy.json (96%) create mode 100755 test/message-generator/test/translation-proxy/translation-proxy.sh diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 3bc1af88b..b35d1974e 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -70,16 +70,59 @@ jobs: - name: Install cargo-llvm-cov uses: taiki-e/install-action@cargo-llvm-cov - - name: Pre build everything - run: | - cargo build --manifest-path=benches/Cargo.toml - cargo build --manifest-path=common/Cargo.toml - cargo build --manifest-path=protocols/Cargo.toml - cargo build --manifest-path=roles/Cargo.toml - cargo build --manifest-path=utils/Cargo.toml - - - name: Run message generator tests - run: sh ./message-generator-tests.sh + - name: Run bad-pool-config-test + run: sh ./test/message-generator/test/bad-pool-config-test/bad-pool-config-test.sh + + - name: Run interop-jd-translator + run: sh ./test/message-generator/test/interop-jd-translator/interop-jd-translator.sh + + #- name: Run interop-jdc-change-upstream + # run: sh ./test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.sh + + - name: Run interop-proxy-with-multi-ups + run: sh ./test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.sh + + - name: Run interop-proxy-with-multi-ups-extended + run: sh ./test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.sh + + - name: Run jds-do-not-fail-on-wrong-tsdatasucc + run: sh ./test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.sh + + - name: Run jds-do-not-panic-if-jdc-close-connection + run: sh ./test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.sh + + - name: Run jds-do-not-stackoverflow-when-no-token + run: sh ./test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.sh + + - name: Run pool-sri-test-1-standard + run: sh ./test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.sh + + - name: Run pool-sri-test-close-channel + run: sh ./test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.sh + + - name: Run pool-sri-test-extended_0 + run: sh ./test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.sh + + - name: Run pool-sri-test-extended_1 + run: sh ./test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.sh + + - name: Run pool-sri-test-reject-auth + run: sh ./test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.sh + + - name: Run standard-coverage + run: sh ./test/message-generator/test/standard-coverage-test/standard-coverage-test.sh + + - name: Run sv1-test + run: sh ./test/message-generator/test/sv1-test/sv1-test.sh + + - name: Run translation-proxy-broke-pool + run: sh ./test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.sh + + - name: Run translation-proxy + run: sh ./test/message-generator/test/translation-proxy/translation-proxy.sh + + - name: Coverage report + run: sh ./code-coverage-report.sh - name: Archive MG code coverage results uses: actions/upload-artifact@v4 diff --git a/code-coverage-report.sh b/code-coverage-report.sh new file mode 100755 index 000000000..f54828ce0 --- /dev/null +++ b/code-coverage-report.sh @@ -0,0 +1,4 @@ +#! /bin/sh + +cd roles +RUST_LOG=debug cargo llvm-cov --ignore-filename-regex "utils/message-generator/|experimental/|protocols/" --cobertura --output-path "target/mg_coverage.xml" report diff --git a/message-generator-tests.sh b/message-generator-tests.sh index 89accf677..01b3e919e 100755 --- a/message-generator-tests.sh +++ b/message-generator-tests.sh @@ -1,26 +1,17 @@ #! /bin/sh -if [ "$1" = "--short" ]; then - RUST_LOG="info" -else - RUST_LOG="debug" -fi - -search_dir="../../test/message-generator/test/" -message_generator_dir="./utils/message-generator/" - -cd $message_generator_dir -cargo llvm-cov clean +search_dir="test/message-generator/test/" for entry in `ls $search_dir`; do - if [ "$entry" = "interop-jdc-change-upstream.json" ]; then + if [ "$entry" = "interop-jdc-change-upstream" ]; then echo "Skipping $entry" continue fi echo $entry - RUST_LOG=$RUST_LOG cargo run -- $search_dir$entry || { echo 'mg test failed' ; exit 1; } + $search_dir$entry/$entry.sh done -cd ../../roles -RUST_LOG=$RUST_LOG cargo llvm-cov --ignore-filename-regex "utils/message-generator/|experimental/|protocols/" --cobertura --output-path "target/mg_coverage.xml" report +cd roles +RUST_LOG=debug cargo llvm-cov --ignore-filename-regex "utils/message-generator/|experimental/|protocols/" --cobertura --output-path "target/mg_coverage.xml" report + diff --git a/test/message-generator/test/bad-pool-config-test.json b/test/message-generator/test/bad-pool-config-test/bad-pool-config-test.json similarity index 98% rename from test/message-generator/test/bad-pool-config-test.json rename to test/message-generator/test/bad-pool-config-test/bad-pool-config-test.json index 32a0603ed..d5bbcb52d 100644 --- a/test/message-generator/test/bad-pool-config-test.json +++ b/test/message-generator/test/bad-pool-config-test/bad-pool-config-test.json @@ -17,8 +17,7 @@ "actions": [ ], "setup_commands": [ - { - "command": "cargo", + { "command": "cargo", "args": [ "run", "../../test/message-generator/mock/template-provider-mock0.json" @@ -175,7 +174,7 @@ "cleanup_commands": [ { "command": "pkill", - "args": ["pool", "-SIGINT"], + "args": ["-f", "pool_sv2", "-SIGINT"], "conditions": "None" } ], diff --git a/test/message-generator/test/bad-pool-config-test/bad-pool-config-test.sh b/test/message-generator/test/bad-pool-config-test/bad-pool-config-test.sh new file mode 100755 index 000000000..76f3342d7 --- /dev/null +++ b/test/message-generator/test/bad-pool-config-test/bad-pool-config-test.sh @@ -0,0 +1,9 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/bad-pool-config-test/bad-pool-config-test.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/interop-jd-translator.json b/test/message-generator/test/interop-jd-translator/interop-jd-translator.json similarity index 100% rename from test/message-generator/test/interop-jd-translator.json rename to test/message-generator/test/interop-jd-translator/interop-jd-translator.json diff --git a/test/message-generator/test/interop-jd-translator/interop-jd-translator.sh b/test/message-generator/test/interop-jd-translator/interop-jd-translator.sh new file mode 100755 index 000000000..3387c4018 --- /dev/null +++ b/test/message-generator/test/interop-jd-translator/interop-jd-translator.sh @@ -0,0 +1,13 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 +cargo llvm-cov --no-report -p jd_server +cargo llvm-cov --no-report -p jd_client +cargo llvm-cov --no-report -p translator_sv2 +cargo build -p sv1-mining-device + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/interop-jd-translator/interop-jd-translator.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/interop-jdc-change-upstream.json b/test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.json similarity index 97% rename from test/message-generator/test/interop-jdc-change-upstream.json rename to test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.json index eafc41c55..344b8d6ce 100644 --- a/test/message-generator/test/interop-jdc-change-upstream.json +++ b/test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.json @@ -169,6 +169,7 @@ { "output_string": "SUCCESS SubmitSharesSuccess", "output_location": "StdOut", + "late_condition": false, "condition": true } ], @@ -181,6 +182,11 @@ "execution_commands": [ ], "cleanup_commands": [ + { + "command": "pkill", + "args": ["-f", "mining_device", "-SIGINT"], + "conditions": "None" + }, { "command": "pkill", "args": ["-f", "jd_server", "-SIGINT"], diff --git a/test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.sh b/test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.sh new file mode 100755 index 000000000..514b2e79e --- /dev/null +++ b/test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.sh @@ -0,0 +1,12 @@ +cd roles +cargo llvm-cov --no-report -p jd_server +cargo llvm-cov --no-report -p jd_client +cargo llvm-cov --no-report -p mining_proxy_sv2 +cargo build -p --no-report mining-device + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/interop-jdc-change-upstream/interop-jdc-change-upstream.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/interop-proxy-with-multi-ups-extended.json b/test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.json similarity index 100% rename from test/message-generator/test/interop-proxy-with-multi-ups-extended.json rename to test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.json diff --git a/test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.sh b/test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.sh new file mode 100755 index 000000000..4173ac30c --- /dev/null +++ b/test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.sh @@ -0,0 +1,11 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 +cargo llvm-cov --no-report -p mining_proxy_sv2 +cargo build --no-report -p mining-device + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/interop-proxy-with-multi-ups-extended/interop-proxy-with-multi-ups-extended.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/interop-proxy-with-multi-ups.json b/test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.json similarity index 100% rename from test/message-generator/test/interop-proxy-with-multi-ups.json rename to test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.json diff --git a/test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.sh b/test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.sh new file mode 100755 index 000000000..080224419 --- /dev/null +++ b/test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.sh @@ -0,0 +1,11 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 +cargo llvm-cov --no-report -p mining_proxy_sv2 +cargo build -p mining-device + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/interop-proxy-with-multi-ups/interop-proxy-with-multi-ups.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc.json b/test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.json similarity index 100% rename from test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc.json rename to test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.json diff --git a/test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.sh b/test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.sh new file mode 100755 index 000000000..4957309d9 --- /dev/null +++ b/test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.sh @@ -0,0 +1,9 @@ +cd roles +cargo llvm-cov --no-report -p jd_server + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/jds-do-not-fail-on-wrong-tsdatasucc/jds-do-not-fail-on-wrong-tsdatasucc.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/jds-do-not-panic-if-jdc-close-connection.json b/test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.json similarity index 100% rename from test/message-generator/test/jds-do-not-panic-if-jdc-close-connection.json rename to test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.json diff --git a/test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.sh b/test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.sh new file mode 100755 index 000000000..706f13a75 --- /dev/null +++ b/test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.sh @@ -0,0 +1,9 @@ +cd roles +cargo llvm-cov --no-report -p jd_server + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/jds-do-not-panic-if-jdc-close-connection/jds-do-not-panic-if-jdc-close-connection.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/jds-do-not-stackoverflow-when-no-token.json b/test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.json similarity index 100% rename from test/message-generator/test/jds-do-not-stackoverflow-when-no-token.json rename to test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.json diff --git a/test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.sh b/test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.sh new file mode 100755 index 000000000..b3a253b51 --- /dev/null +++ b/test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.sh @@ -0,0 +1,11 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 +cargo llvm-cov --no-report -p jd_client +cargo llvm-cov --no-report -p mining_proxy_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/jds-do-not-stackoverflow-when-no-token/jds-do-not-stackoverflow-when-no-token.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/pool-sri-test-1-standard.json b/test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.json similarity index 78% rename from test/message-generator/test/pool-sri-test-1-standard.json rename to test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.json index 4f338cda2..24ae109c5 100644 --- a/test/message-generator/test/pool-sri-test-1-standard.json +++ b/test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.json @@ -145,53 +145,32 @@ } }, { - "command": "cargo", - "args": [ - "run", - "../../../test/message-generator/mock/template-provider-mock0.json" - ], - "conditions": { - "WithConditions": { - "conditions": [ - { - "output_string": "Running `target/debug/message_generator_sv2 ../../../test/message-generator/mock/template-provider-mock0.json`", - "output_location": "StdErr", - "late_condition": false, - "condition": true - } - ], - "timer_secs": 320, - "warn_no_panic": false - } - } - }, - { - "command": "cargo", - "args": [ - "llvm-cov", - "--no-report", - "run", - "-p", - "pool_sv2", - "--", - "-c", - "../test/config/pool-mock-tp.toml" - ], - "conditions": { - "WithConditions": { - "conditions": [ - { - "output_string": "Listening for encrypted connection on: 127.0.0.1:34254", - "output_location": "StdOut", - "late_condition": false, - "condition": true - } - ], - "timer_secs": 320, - "warn_no_panic": false - } - } - }, + "command": "cargo", + "args": [ + "llvm-cov", + "--no-report", + "run", + "-p", + "pool_sv2", + "--", + "-c", + "../test/config/pool-mock-tp.toml" + ], + "conditions": { + "WithConditions": { + "conditions": [ + { + "output_string": "Listening for encrypted connection on: 127.0.0.1:34254", + "output_location": "StdOut", + "late_condition": false, + "condition": true + } + ], + "timer_secs": 320, + "warn_no_panic": false + } + } + }, { "command": "cargo", "args": [ diff --git a/test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.sh b/test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.sh new file mode 100755 index 000000000..ca9ad3558 --- /dev/null +++ b/test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.sh @@ -0,0 +1,9 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/pool-sri-test-1-standard/pool-sri-test-1-standard.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/pool-sri-test-close-channel.json b/test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.json similarity index 96% rename from test/message-generator/test/pool-sri-test-close-channel.json rename to test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.json index a30f1b3c6..8529af950 100644 --- a/test/message-generator/test/pool-sri-test-close-channel.json +++ b/test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.json @@ -105,6 +105,11 @@ } ], "cleanup_commands": [ + { + "command": "pkill", + "args": ["-f", "translator_sv2", "-SIGINT"], + "conditions": "None" + } ], "role": "server", "upstream": { diff --git a/test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.sh b/test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.sh new file mode 100755 index 000000000..0b13c3c9b --- /dev/null +++ b/test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.sh @@ -0,0 +1,9 @@ +cd roles +cargo build -p translator_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/pool-sri-test-close-channel/pool-sri-test-close-channel.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/pool-sri-test-extended_0.json b/test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.json similarity index 100% rename from test/message-generator/test/pool-sri-test-extended_0.json rename to test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.json diff --git a/test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.sh b/test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.sh new file mode 100755 index 000000000..a5f3d7723 --- /dev/null +++ b/test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.sh @@ -0,0 +1,7 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/pool-sri-test-extended_0/pool-sri-test-extended_0.json || { echo 'mg test failed' ; exit 1; } diff --git a/test/message-generator/test/pool-sri-test-extended_1.json b/test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.json similarity index 100% rename from test/message-generator/test/pool-sri-test-extended_1.json rename to test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.json diff --git a/test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.sh b/test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.sh new file mode 100755 index 000000000..5a53a7509 --- /dev/null +++ b/test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.sh @@ -0,0 +1,9 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/pool-sri-test-extended_1/pool-sri-test-extended_1.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/pool-sri-test-reject-auth.json b/test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.json similarity index 98% rename from test/message-generator/test/pool-sri-test-reject-auth.json rename to test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.json index b12ec4424..f1e8cbc48 100644 --- a/test/message-generator/test/pool-sri-test-reject-auth.json +++ b/test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.json @@ -105,7 +105,7 @@ "utils/|experimental/|protocols/", "--cobertura", "--output-path", - "target/pool-sri-test-1-standard.xml", + "target/pool-sri-test-reject-auth.xml", "report" ], "conditions": { diff --git a/test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.sh b/test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.sh new file mode 100755 index 000000000..0e1662fb8 --- /dev/null +++ b/test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.sh @@ -0,0 +1,9 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/pool-sri-test-reject-auth/pool-sri-test-reject-auth.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/standard-coverage-test.json b/test/message-generator/test/standard-coverage-test/standard-coverage-test.json similarity index 89% rename from test/message-generator/test/standard-coverage-test.json rename to test/message-generator/test/standard-coverage-test/standard-coverage-test.json index 0e237b508..a9a8daa93 100644 --- a/test/message-generator/test/standard-coverage-test.json +++ b/test/message-generator/test/standard-coverage-test/standard-coverage-test.json @@ -181,27 +181,6 @@ } } }, - { - "command": "cargo", - "args": [ - "run", - "../../../test/message-generator/mock/template-provider-mock1.json" - ], - "conditions": { - "WithConditions": { - "conditions": [ - { - "output_string": "Running `target/debug/message_generator_sv2 ../../../test/message-generator/mock/template-provider-mock1.json`", - "output_location": "StdErr", - "late_condition": false, - "condition": true - } - ], - "timer_secs": 320, - "warn_no_panic": false - } - } - }, { "command": "cargo", "args": [ "llvm-cov", diff --git a/test/message-generator/test/standard-coverage-test/standard-coverage-test.sh b/test/message-generator/test/standard-coverage-test/standard-coverage-test.sh new file mode 100755 index 000000000..22befe8eb --- /dev/null +++ b/test/message-generator/test/standard-coverage-test/standard-coverage-test.sh @@ -0,0 +1,9 @@ +cd roles +cargo llvm-cov --no-report -p pool_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/standard-coverage-test/standard-coverage-test.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/sv1-test.json b/test/message-generator/test/sv1-test/sv1-test.json similarity index 94% rename from test/message-generator/test/sv1-test.json rename to test/message-generator/test/sv1-test/sv1-test.json index 90a1e3659..bd38929b3 100644 --- a/test/message-generator/test/sv1-test.json +++ b/test/message-generator/test/sv1-test/sv1-test.json @@ -136,6 +136,17 @@ } ], "execution_commands": [ + { + "command": "pkill", + "args": ["-f", "translator_sv2", "-SIGINT"], + "conditions": "None" + }, + { + "command": "pkill", + "args": ["-f", "pool_sv2", "-SIGINT"], + "conditions": "None" + } + ], "cleanup_commands": [ ], diff --git a/test/message-generator/test/sv1-test/sv1-test.sh b/test/message-generator/test/sv1-test/sv1-test.sh new file mode 100755 index 000000000..99ce8a4c7 --- /dev/null +++ b/test/message-generator/test/sv1-test/sv1-test.sh @@ -0,0 +1,10 @@ +cd roles +cargo build -p pool_sv2 +cargo build -p translator_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/sv1-test/sv1-test.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/translation-proxy-broke-pool.json b/test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.json similarity index 95% rename from test/message-generator/test/translation-proxy-broke-pool.json rename to test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.json index 2fb9026b0..caa1330b0 100644 --- a/test/message-generator/test/translation-proxy-broke-pool.json +++ b/test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.json @@ -91,6 +91,12 @@ "execution_commands": [ ], "cleanup_commands": [ + { + "command": "pkill", + "args": ["-f", "translator_sv2", "-SIGINT"], + "conditions": "None" + } + ], "role": "server", "upstream": { diff --git a/test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.sh b/test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.sh new file mode 100755 index 000000000..a2a9077c4 --- /dev/null +++ b/test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.sh @@ -0,0 +1,9 @@ +cd roles +cargo build -p translator_sv2 + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/translation-proxy-broke-pool/translation-proxy-broke-pool.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/test/message-generator/test/translation-proxy.json b/test/message-generator/test/translation-proxy/translation-proxy.json similarity index 96% rename from test/message-generator/test/translation-proxy.json rename to test/message-generator/test/translation-proxy/translation-proxy.json index abdc7e6c5..d529dd276 100644 --- a/test/message-generator/test/translation-proxy.json +++ b/test/message-generator/test/translation-proxy/translation-proxy.json @@ -192,6 +192,16 @@ } ], "cleanup_commands": [ + { + "command": "pkill", + "args": ["-f", "sv1-mining-device", "-SIGINT"], + "conditions": "None" + }, + { + "command": "pkill", + "args": ["-f", "translator_sv2", "-SIGINT"], + "conditions": "None" + } ], "role": "server", "upstream": { diff --git a/test/message-generator/test/translation-proxy/translation-proxy.sh b/test/message-generator/test/translation-proxy/translation-proxy.sh new file mode 100755 index 000000000..040fccfcc --- /dev/null +++ b/test/message-generator/test/translation-proxy/translation-proxy.sh @@ -0,0 +1,10 @@ +cd roles +cargo build -p translator_sv2 +cargo build -p sv1-mining-device + +cd ../utils/message-generator/ +cargo build + +RUST_LOG=debug cargo run ../../test/message-generator/test/translation-proxy/translation-proxy.json || { echo 'mg test failed' ; exit 1; } + +sleep 10 diff --git a/utils/message-generator/Cargo.lock b/utils/message-generator/Cargo.lock index c2279ee98..3a248ae70 100644 --- a/utils/message-generator/Cargo.lock +++ b/utils/message-generator/Cargo.lock @@ -272,7 +272,7 @@ dependencies = [ [[package]] name = "codec_sv2" -version = "1.0.0" +version = "1.0.1" dependencies = [ "binary_sv2", "buffer_sv2", @@ -646,7 +646,7 @@ checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "message_generator_sv2" -version = "1.0.0" +version = "1.0.1" dependencies = [ "arbitrary", "async-channel", @@ -655,7 +655,7 @@ dependencies = [ "const_sv2", "key-utils", "load_file", - "network_helpers", + "network_helpers_sv2", "rand", "roles_logic_sv2", "secp256k1 0.28.2", @@ -698,8 +698,8 @@ dependencies = [ ] [[package]] -name = "network_helpers" -version = "1.0.0" +name = "network_helpers_sv2" +version = "2.0.0" dependencies = [ "async-channel", "binary_sv2", @@ -1150,6 +1150,7 @@ name = "stratum-common" version = "1.0.0" dependencies = [ "bitcoin", + "secp256k1 0.28.2", ] [[package]] diff --git a/utils/message-generator/README.md b/utils/message-generator/README.md index 0f9361b31..e4d797ee2 100644 --- a/utils/message-generator/README.md +++ b/utils/message-generator/README.md @@ -1,5 +1,6 @@ # Message Generator + Little utility to execute interoperability tests between SRI and other Sv2 complaint software. ## Try it diff --git a/utils/message-generator/src/main.rs b/utils/message-generator/src/main.rs index b996c002e..695b3919c 100644 --- a/utils/message-generator/src/main.rs +++ b/utils/message-generator/src/main.rs @@ -26,7 +26,7 @@ use std::{ }, vec::Vec, }; -use tracing::info; +use tracing::{error, info}; use tracing_core::{Event, Subscriber}; use tracing_subscriber::{ filter::EnvFilter, @@ -371,6 +371,13 @@ where } } +fn load_file(path: &str) -> String { + std::fs::read_to_string(path).unwrap() +} +fn string_to_static_str(s: String) -> &'static str { + Box::leak(s.into_boxed_str()) +} + #[tokio::main] async fn main() { tracing_subscriber::fmt() @@ -383,11 +390,11 @@ async fn main() { info!("EXECUTING {}", test_path); info!(""); let mut _test_path = args[1].clone(); - _test_path.insert_str(0, "../"); + //_test_path.insert_str(0, "../"); let test_path_ = &_test_path; // Load contents of `test.json`, then parse - let test = load_str!(test_path_); - let test = parser::Parser::parse_test(test); + let test_static = string_to_static_str(load_file(test_path_)); + let test = parser::Parser::parse_test(test_static); let test_name: String = test_path .split('/') .collect::>() @@ -401,7 +408,8 @@ async fn main() { let pass = Arc::new(AtomicBool::new(false)); { let fail = fail.clone(); - std::panic::set_hook(Box::new(move |_| { + std::panic::set_hook(Box::new(move |info| { + error!("{:#?}", info); fail.store(true, Ordering::Relaxed); })); } @@ -423,6 +431,7 @@ async fn main() { }); } loop { + tokio::task::yield_now().await; if fail.load(Ordering::Relaxed) { clean_up(cleanup).await; let _ = std::panic::take_hook(); From 1f289e4b745e65c122e18dfb4023de8f6371eaab Mon Sep 17 00:00:00 2001 From: Gabriele Vernetti <62447440+GitGab19@users.noreply.github.com> Date: Tue, 21 May 2024 20:37:56 +0200 Subject: [PATCH 33/39] Better management of LastDeclareJobs - no more wrong fallback-system activations (#904) --- roles/jd-client/src/lib/downstream.rs | 16 ++++- .../src/lib/job_declarator/message_handler.rs | 4 +- roles/jd-client/src/lib/job_declarator/mod.rs | 68 ++++++++++++++----- 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/roles/jd-client/src/lib/downstream.rs b/roles/jd-client/src/lib/downstream.rs index fdac57a12..ddc6e5bd0 100644 --- a/roles/jd-client/src/lib/downstream.rs +++ b/roles/jd-client/src/lib/downstream.rs @@ -289,8 +289,14 @@ impl DownstreamMiningNode { // pool's job_id. The below return as soon as we have a pairable job id for the // template_id associated with this share. let last_template_id = self_mutex.safe_lock(|s| s.last_template_id).unwrap(); - let job_id = - UpstreamMiningNode::get_job_id(&upstream_mutex, last_template_id).await; + let job_id_future = + UpstreamMiningNode::get_job_id(&upstream_mutex, last_template_id); + let job_id = match timeout(Duration::from_secs(10), job_id_future).await { + Ok(job_id) => job_id, + Err(_) => { + return; + } + }; share.job_id = job_id; debug!( "Sending valid block solution upstream, with job_id {}", @@ -643,7 +649,11 @@ impl ParseDownstreamCommonMessages use network_helpers_sv2::noise_connection_tokio::Connection; use std::net::SocketAddr; -use tokio::{net::TcpListener, task::AbortHandle}; +use tokio::{ + net::TcpListener, + task::AbortHandle, + time::{timeout, Duration}, +}; /// Strat listen for downstream mining node. Return as soon as one downstream connect. #[allow(clippy::too_many_arguments)] diff --git a/roles/jd-client/src/lib/job_declarator/message_handler.rs b/roles/jd-client/src/lib/job_declarator/message_handler.rs index c05393c64..7516f24f9 100644 --- a/roles/jd-client/src/lib/job_declarator/message_handler.rs +++ b/roles/jd-client/src/lib/job_declarator/message_handler.rs @@ -54,7 +54,9 @@ impl ParseServerJobDeclarationMessages for JobDeclarator { message: ProvideMissingTransactions, ) -> Result { let tx_list = self - .last_declare_mining_job_sent + .last_declare_mining_jobs_sent + .get(&message.request_id) + .unwrap() .clone() .unwrap() .tx_list diff --git a/roles/jd-client/src/lib/job_declarator/mod.rs b/roles/jd-client/src/lib/job_declarator/mod.rs index c03959b75..abaf852ca 100644 --- a/roles/jd-client/src/lib/job_declarator/mod.rs +++ b/roles/jd-client/src/lib/job_declarator/mod.rs @@ -55,8 +55,9 @@ pub struct JobDeclarator { req_ids: Id, min_extranonce_size: u16, // (Sent DeclareMiningJob, is future, template id, merkle path) - last_declare_mining_job_sent: Option, + last_declare_mining_jobs_sent: HashMap>, last_set_new_prev_hash: Option>, + set_new_prev_hash_counter: u8, #[allow(clippy::type_complexity)] future_jobs: HashMap< u64, @@ -114,13 +115,14 @@ impl JobDeclarator { allocated_tokens: vec![], req_ids: Id::new(), min_extranonce_size, - last_declare_mining_job_sent: None, + last_declare_mining_jobs_sent: HashMap::with_capacity(10), last_set_new_prev_hash: None, future_jobs: HashMap::with_hasher(BuildNoHashHasher::default()), up, task_collector, coinbase_tx_prefix: vec![].try_into().unwrap(), coinbase_tx_suffix: vec![].try_into().unwrap(), + set_new_prev_hash_counter: 0, })); Self::allocate_tokens(&self_, 2).await; @@ -128,20 +130,35 @@ impl JobDeclarator { Ok(self_) } - fn get_last_declare_job_sent(self_mutex: &Arc>) -> LastDeclareJob { + fn get_last_declare_job_sent(self_mutex: &Arc>, request_id: u32) -> LastDeclareJob { self_mutex .safe_lock(|s| { - s.last_declare_mining_job_sent + s.last_declare_mining_jobs_sent + .get(&request_id) + .expect("LastDeclareJob not found") .clone() .expect("unreachable code") }) .unwrap() } - fn update_last_declare_job_sent(self_mutex: &Arc>, j: LastDeclareJob) { + fn update_last_declare_job_sent( + self_mutex: &Arc>, + request_id: u32, + j: LastDeclareJob, + ) { self_mutex - .safe_lock(|s| s.last_declare_mining_job_sent = Some(j)) - .unwrap() + .safe_lock(|s| { + //check hashmap size in order to not let it grow indefinetely + if s.last_declare_mining_jobs_sent.len() < 10 { + s.last_declare_mining_jobs_sent.insert(request_id, Some(j)); + } else if let Some(min_key) = s.last_declare_mining_jobs_sent.keys().min().cloned() + { + s.last_declare_mining_jobs_sent.remove(&min_key); + s.last_declare_mining_jobs_sent.insert(request_id, Some(j)); + } + }) + .unwrap(); } #[async_recursion] @@ -245,7 +262,7 @@ impl JobDeclarator { coinbase_pool_output, tx_list: tx_list_.clone(), }; - Self::update_last_declare_job_sent(self_mutex, last_declare); + Self::update_last_declare_job_sent(self_mutex, id, last_declare); let frame: StdFrame = PoolMessages::JobDeclaration(JobDeclaration::DeclareMiningJob(declare_job)) .try_into() @@ -272,7 +289,8 @@ impl JobDeclarator { match next_message_to_send { Ok(SendTo::None(Some(JobDeclaration::DeclareMiningJobSuccess(m)))) => { let new_token = m.new_mining_job_token; - let last_declare = Self::get_last_declare_job_sent(&self_mutex); + let last_declare = + Self::get_last_declare_job_sent(&self_mutex, m.request_id); let mut last_declare_mining_job_sent = last_declare.declare_job; let is_future = last_declare.template.future_template; let id = last_declare.template.template_id; @@ -355,21 +373,35 @@ impl JobDeclarator { ) { tokio::task::spawn(async move { let id = set_new_prev_hash.template_id; + let _ = self_mutex.safe_lock(|s| { + s.last_set_new_prev_hash = Some(set_new_prev_hash.clone()); + s.set_new_prev_hash_counter += 1; + }); let (job, up, merkle_path, template, mut pool_outs) = loop { - if let Some(future_job_tuple) = self_mutex + match self_mutex .safe_lock(|s| { - s.last_set_new_prev_hash = Some(set_new_prev_hash.clone()); - match s.future_jobs.remove(&id) { - Some((job, merkle_path, template, pool_outs)) => { - s.future_jobs = HashMap::with_hasher(BuildNoHashHasher::default()); - Some((job, s.up.clone(), merkle_path, template, pool_outs)) - } - None => None, + if s.set_new_prev_hash_counter > 1 + && s.last_set_new_prev_hash != Some(set_new_prev_hash.clone()) + //it means that a new prev_hash is arrived while the previous hasn't exited the loop yet + { + s.set_new_prev_hash_counter -= 1; + Some(None) + } else { + s.future_jobs.remove(&id).map( + |(job, merkle_path, template, pool_outs)| { + s.future_jobs = + HashMap::with_hasher(BuildNoHashHasher::default()); + s.set_new_prev_hash_counter -= 1; + Some((job, s.up.clone(), merkle_path, template, pool_outs)) + }, + ) } }) .unwrap() { - break future_job_tuple; + Some(Some(future_job_tuple)) => break future_job_tuple, + Some(None) => return, + None => {} }; tokio::task::yield_now().await; }; From c8424b614a35a0c84e97395c263d2ebd8f2d1674 Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Thu, 23 May 2024 07:02:22 -0300 Subject: [PATCH 34/39] patch RELEASE.md (#924) --- RELEASE.md | 12 ++++++------ git-branching.png | Bin 61654 -> 63551 bytes 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index ff0a187de..1dc101018 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -30,11 +30,11 @@ The SRI repo holds two principal branches with an infinite lifetime: - `main` - `dev` -We consider `main` to be the branch where the source code of `HEAD` always reflects a production-ready state. +We consider `main` to be the branch where the source code of `HEAD` always reflects the latest release. -We consider `dev` to be the branch where the source code of `HEAD` always reflects a state with the latest delivered development changes for the next release. +We consider `dev` to be the branch where the source code of `HEAD` always reflects the latest changes in the development cycle. -The SRI team will decide the appropriate time when the changes to `dev` are merged back into `main` and then tagged with a release number while bumping `MAJOR` and/or `MINOR`. +The SRI team will decide the appropriate time when the changes to `dev` are merged back into `main` and then tagged with a release number while bumping `MAJOR`, `MINOR`, or `PATCH`. ## Feature Branches @@ -48,8 +48,8 @@ New features are developed into separate branches that only live in the contribu Bugs are patched into separate branches that only live in the contributor's forks. -- branch off from: `main` -- merge back into: `main` + `dev` +- branch off from: `dev` +- merge back into: `dev` - naming convention: `patch-x`, where `x` describes the bug/patch # Releasing Roles Binaries @@ -72,7 +72,7 @@ If a crate is not updated successfully, the step will fail, but since all steps Since steps can fail, the output of the action must be manually checked. -Every PR to `main` (either coming from `dev`, or a patch) needs to increase the version of whatever crate it is touching. Otherwise, we will mess up the dependency chain of whoever is fetching from crates.io +Every PR to `main` needs to increase the version of whatever crate it is touching. Otherwise, we will mess up the dependency chain of whoever is fetching from crates.io Manually running `cargo release` in the various workspaces helps to prepare the version number before the releases are published. diff --git a/git-branching.png b/git-branching.png index 0312c7fb006fe2f1fdd2993c0072a4a797309d18..1337f45ea1d4b18a23d7fb665882b22cc286bf88 100644 GIT binary patch literal 63551 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
R8t8iV$E){6G{Vi=XX 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�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 D?6RHh From 296938a154a174d6bab1fe1fa31f15a0890f9e3c Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Thu, 23 May 2024 15:07:51 -0300 Subject: [PATCH 35/39] patch check-versioning-lib-release.sh (#926) --- check-versioning-lib-release.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/check-versioning-lib-release.sh b/check-versioning-lib-release.sh index 6d2bcc794..6cccb320e 100755 --- a/check-versioning-lib-release.sh +++ b/check-versioning-lib-release.sh @@ -1,7 +1,6 @@ #!/bin/bash -git fetch origin main -git fetch origin dev +git fetch --all crates=( "utils/buffer" @@ -36,6 +35,10 @@ crates=( for crate in "${crates[@]}"; do cd "$crate" + # Check if the branches exist locally, if not, create them + git show-ref --verify --quiet refs/remotes/origin/main || { echo "Branch 'main' not found."; exit 1; } + git show-ref --verify --quiet refs/remotes/origin/dev || { echo "Branch 'dev' not found."; exit 1; } + # Check if there were any changes between dev and main git diff --quiet "origin/dev" "origin/main" -- . if [ $? -ne 0 ]; then From d432fa8c2f0db3a8cfc166453ad9a1493ce78a40 Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Thu, 23 May 2024 15:59:35 -0300 Subject: [PATCH 36/39] bump codec_sv2 version (#927) --- protocols/v2/codec-sv2/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/v2/codec-sv2/Cargo.toml b/protocols/v2/codec-sv2/Cargo.toml index 7b5cbb36b..75645d56b 100644 --- a/protocols/v2/codec-sv2/Cargo.toml +++ b/protocols/v2/codec-sv2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codec_sv2" -version = "1.0.1" +version = "1.1.0" authors = ["fi3 "] edition = "2018" description = "Sv2 data format" From 87f60ec9bfc93fd14d1ee6613965de6477360f92 Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Fri, 24 May 2024 15:40:32 -0300 Subject: [PATCH 37/39] improve check-versioning-lib-release (#929) --- check-versioning-lib-release.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/check-versioning-lib-release.sh b/check-versioning-lib-release.sh index 6cccb320e..5fdf6eb91 100755 --- a/check-versioning-lib-release.sh +++ b/check-versioning-lib-release.sh @@ -47,8 +47,12 @@ for crate in "${crates[@]}"; do version_dev=$(git show origin/dev:./Cargo.toml | awk -F' = ' '$1 == "version" {gsub(/[ "]+/, "", $2); print $2}') version_main=$(git show origin/main:./Cargo.toml | awk -F' = ' '$1 == "version" {gsub(/[ "]+/, "", $2); print $2}') if [ "$version_dev" = "$version_main" ]; then + # this prevents the release PR from being merged, since we do `exit 1`, effectively stopping the Github CI echo "Changes detected in crate $crate between dev and main branches! Versions on dev and main branches are identical ($version_dev), so you should bump the crate version on dev before merging into main." exit 1 + else + # this creates a log of version changes, useful for release logs + echo "Changes detected in crate $crate between dev and main branches! Version in dev is: ($version_dev), while version in main is ($version_main)." fi fi From 5fef39ef5e6f4443fb21028374eeaaf271849c15 Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Fri, 24 May 2024 16:10:46 -0300 Subject: [PATCH 38/39] bump crate versions for release (#930) --- protocols/v2/roles-logic-sv2/Cargo.toml | 2 +- utils/key-utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/v2/roles-logic-sv2/Cargo.toml b/protocols/v2/roles-logic-sv2/Cargo.toml index 1fcacf0b2..4254d6a1f 100644 --- a/protocols/v2/roles-logic-sv2/Cargo.toml +++ b/protocols/v2/roles-logic-sv2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "roles_logic_sv2" -version = "1.0.0" +version = "1.1.0" edition = "2018" description = "Common handlers for use within SV2 roles" license = "MIT OR Apache-2.0" diff --git a/utils/key-utils/Cargo.toml b/utils/key-utils/Cargo.toml index 42fa67d8a..55c5bba15 100644 --- a/utils/key-utils/Cargo.toml +++ b/utils/key-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "key-utils" -version = "1.0.0" +version = "1.1.0" edition = "2021" description = "Key utils" license = "MIT OR Apache-2.0" From d61347346d9cb49be4aee1c7a51cdddb6f2dcdd8 Mon Sep 17 00:00:00 2001 From: plebhash <147345153+plebhash@users.noreply.github.com> Date: Mon, 27 May 2024 11:43:08 -0300 Subject: [PATCH 39/39] Update `Cargo.lock` files with version updates (#933) --- .gitignore | 4 +- benches/Cargo.lock | 6 +- protocols/Cargo.lock | 6 +- roles/Cargo.lock | 8 +- utils/message-generator/Cargo.lock | 1514 ---------------------------- 5 files changed, 13 insertions(+), 1525 deletions(-) delete mode 100644 utils/message-generator/Cargo.lock diff --git a/.gitignore b/.gitignore index 341e3cd47..6121487a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ .idea -*/target +*/**/target /protocols/guix-example/guix-example.h /ignore /vendor/ed25519-dalek/target /utils/buffer/target +/utils/message-generator/Cargo.lock /sv2.h /test/bitcoin_data/regtest lcov.info @@ -13,3 +14,4 @@ lcov.info **/conf/** cobertura.xml /roles/*/*-config.toml +/examples/*/Cargo.lock diff --git a/benches/Cargo.lock b/benches/Cargo.lock index adf916946..946b7c02b 100644 --- a/benches/Cargo.lock +++ b/benches/Cargo.lock @@ -497,7 +497,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "codec_sv2" -version = "1.0.1" +version = "1.1.0" dependencies = [ "binary_sv2", "buffer_sv2", @@ -728,7 +728,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "framing_sv2" -version = "1.0.0" +version = "1.1.0" dependencies = [ "binary_sv2", "const_sv2", @@ -1377,7 +1377,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "roles_logic_sv2" -version = "1.0.0" +version = "1.1.0" dependencies = [ "binary_sv2", "chacha20poly1305", diff --git a/protocols/Cargo.lock b/protocols/Cargo.lock index 0ed90a476..9fdf24f21 100644 --- a/protocols/Cargo.lock +++ b/protocols/Cargo.lock @@ -199,7 +199,7 @@ dependencies = [ [[package]] name = "codec_sv2" -version = "1.0.1" +version = "1.1.0" dependencies = [ "binary_sv2", "buffer_sv2", @@ -290,7 +290,7 @@ dependencies = [ [[package]] name = "framing_sv2" -version = "1.0.0" +version = "1.1.0" dependencies = [ "binary_sv2", "buffer_sv2", @@ -606,7 +606,7 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "roles_logic_sv2" -version = "1.0.0" +version = "1.1.0" dependencies = [ "binary_sv2", "chacha20poly1305", diff --git a/roles/Cargo.lock b/roles/Cargo.lock index 1c0dc4d8f..7b588075e 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -594,7 +594,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "codec_sv2" -version = "1.0.1" +version = "1.1.0" dependencies = [ "binary_sv2", "buffer_sv2", @@ -800,7 +800,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "framing_sv2" -version = "1.0.0" +version = "1.1.0" dependencies = [ "binary_sv2", "buffer_sv2", @@ -1270,7 +1270,7 @@ dependencies = [ [[package]] name = "key-utils" -version = "1.0.0" +version = "1.1.0" dependencies = [ "bs58", "secp256k1 0.28.2", @@ -1780,7 +1780,7 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "roles_logic_sv2" -version = "1.0.0" +version = "1.1.0" dependencies = [ "binary_sv2", "chacha20poly1305", diff --git a/utils/message-generator/Cargo.lock b/utils/message-generator/Cargo.lock deleted file mode 100644 index 3a248ae70..000000000 --- a/utils/message-generator/Cargo.lock +++ /dev/null @@ -1,1514 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "arbitrary" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" -dependencies = [ - "derive_arbitrary", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - -[[package]] -name = "binary_codec_sv2" -version = "1.0.0" -dependencies = [ - "buffer_sv2", -] - -[[package]] -name = "binary_sv2" -version = "1.0.0" -dependencies = [ - "binary_codec_sv2", - "derive_codec_sv2", - "serde", - "serde_sv2", - "tracing", -] - -[[package]] -name = "bitcoin" -version = "0.29.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" -dependencies = [ - "bech32", - "bitcoin_hashes 0.11.0", - "secp256k1 0.24.3", -] - -[[package]] -name = "bitcoin-internals" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" - -[[package]] -name = "bitcoin_hashes" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b7a2e9773ee7ae7f2560f0426c938f57902dcb9e39321b0cbd608f47ed579a4" -dependencies = [ - "byteorder", -] - -[[package]] -name = "bitcoin_hashes" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" - -[[package]] -name = "bitcoin_hashes" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" -dependencies = [ - "bitcoin-internals", - "hex-conservative", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -dependencies = [ - "sha2", -] - -[[package]] -name = "buffer_sv2" -version = "1.0.0" -dependencies = [ - "aes-gcm", - "serde", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "codec_sv2" -version = "1.0.1" -dependencies = [ - "binary_sv2", - "buffer_sv2", - "const_sv2", - "framing_sv2", - "noise_sv2", - "serde", - "tracing", -] - -[[package]] -name = "common_messages_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "const_sv2", - "serde", - "serde_repr", -] - -[[package]] -name = "concurrent-queue" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const_sv2" -version = "1.0.0" -dependencies = [ - "secp256k1 0.28.2", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "derive_arbitrary" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_codec_sv2" -version = "1.0.0" -dependencies = [ - "binary_codec_sv2", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "framing_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "buffer_sv2", - "const_sv2", - "serde", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "ghash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-conservative" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" - -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "job_declaration_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "const_sv2", - "serde", -] - -[[package]] -name = "key-utils" -version = "1.0.0" -dependencies = [ - "bs58", - "secp256k1 0.28.2", - "serde", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.153" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" - -[[package]] -name = "load_file" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31da4bce62428941030036a44d0d4b123f031b04080f8aeb44248b41de3e79cd" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "message_generator_sv2" -version = "1.0.1" -dependencies = [ - "arbitrary", - "async-channel", - "binary_sv2", - "codec_sv2", - "const_sv2", - "key-utils", - "load_file", - "network_helpers_sv2", - "rand", - "roles_logic_sv2", - "secp256k1 0.28.2", - "serde", - "serde_json", - "sv1_api", - "tokio", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "mining_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "const_sv2", - "serde", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "network_helpers_sv2" -version = "2.0.0" -dependencies = [ - "async-channel", - "binary_sv2", - "codec_sv2", - "const_sv2", - "futures", - "serde", - "tokio", - "tracing", -] - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "noise_sv2" -version = "1.1.0" -dependencies = [ - "aes-gcm", - "chacha20poly1305", - "const_sv2", - "rand", - "rand_chacha", - "secp256k1 0.28.2", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "pretty_env_logger" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" -dependencies = [ - "env_logger", - "log", -] - -[[package]] -name = "proc-macro2" -version = "1.0.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.5", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "roles_logic_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "chacha20poly1305", - "common_messages_sv2", - "const_sv2", - "framing_sv2", - "job_declaration_sv2", - "mining_sv2", - "nohash-hasher", - "serde", - "siphasher", - "stratum-common", - "template_distribution_sv2", - "tracing", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "ryu" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "secp256k1" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" -dependencies = [ - "bitcoin_hashes 0.11.0", - "secp256k1-sys 0.6.1", -] - -[[package]] -name = "secp256k1" -version = "0.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" -dependencies = [ - "bitcoin_hashes 0.13.0", - "rand", - "secp256k1-sys 0.9.2", -] - -[[package]] -name = "secp256k1-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" -dependencies = [ - "cc", -] - -[[package]] -name = "secp256k1-sys" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" -dependencies = [ - "cc", -] - -[[package]] -name = "serde" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_sv2" -version = "1.0.0" -dependencies = [ - "buffer_sv2", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer", - "cfg-if", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "siphasher" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" - -[[package]] -name = "socket2" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "stratum-common" -version = "1.0.0" -dependencies = [ - "bitcoin", - "secp256k1 0.28.2", -] - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "sv1_api" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "bitcoin_hashes 0.3.2", - "byteorder", - "hex", - "log", - "pretty_env_logger", - "serde", - "serde_json", - "tracing", -] - -[[package]] -name = "syn" -version = "2.0.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "template_distribution_sv2" -version = "1.0.0" -dependencies = [ - "binary_sv2", - "const_sv2", - "serde", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "tokio" -version = "1.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.4", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" -dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"