From 89e436053f099b2d5d7eb5e5039998fdbec56269 Mon Sep 17 00:00:00 2001 From: lorban Date: Sat, 1 Jun 2024 17:46:02 +0200 Subject: [PATCH] fix serialization of primitives with serde some tests in main.rs of Message Generator are not passing or are commented. This is because serialization and/or deserialization of Sv2 primitives was broken. into_static for serde_sv2 primitives these functions were panicking if the seq field of sequences (Seq or Sv2Option) were Some(...). most rust tests for MG are fixed, one is added --- protocols/Cargo.lock | 2 +- .../serde-sv2/src/primitives/sequences/mod.rs | 30 ++ .../src/primitives/sequences/option.rs | 87 ++++-- .../src/primitives/sequences/seq0255.rs | 84 ++++-- .../src/primitives/sequences/seq064k.rs | 212 ++++++++++--- roles/Cargo.lock | 2 +- utils/message-generator/src/main.rs | 281 ++++++++++-------- .../src/parser/sv1_messages.rs | 1 + utils/message-generator/test.json | 20 +- 9 files changed, 502 insertions(+), 217 deletions(-) diff --git a/protocols/Cargo.lock b/protocols/Cargo.lock index fbe5ddceac..31450eea42 100644 --- a/protocols/Cargo.lock +++ b/protocols/Cargo.lock @@ -744,7 +744,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "sv1_api" -version = "1.0.0" +version = "1.0.1" dependencies = [ "binary_sv2", "bitcoin_hashes 0.3.2", diff --git a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/mod.rs b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/mod.rs index cfcf1b9d56..8600ee5085 100644 --- a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/mod.rs +++ b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/mod.rs @@ -1,5 +1,6 @@ use super::{ShortTxId, Signature, B016M, B0255, B064K, U24, U256}; use crate::Error; +use alloc::vec::Vec; use core::convert::TryInto; use serde::{de::Visitor, Serialize}; @@ -22,6 +23,23 @@ struct Seq<'s, T: Clone + Serialize + TryFromBSlice<'s>> { _a: core::marker::PhantomData, } +impl<'s, T: Clone + Serialize + TryFromBSlice<'s>> Seq<'s, T> { + pub fn parse(self) -> Result, ()> { + let mut ret = Vec::with_capacity(self.size as usize); + let elem_len = self.size as usize; + let mut first = 0; + let mut last = elem_len; + while last <= self.data.len() { + let slice = &self.data[first..last]; + let elem = T::try_from_slice(slice).map_err(|_| ())?; + ret.push(elem); + first += elem_len; + last += elem_len; + } + Ok(ret) + } +} + struct SeqVisitor { inner_type_size: u8, max_len: SeqMaxLen, @@ -81,6 +99,18 @@ impl<'a> TryFromBSlice<'a> for bool { } } +impl<'a> TryFromBSlice<'a> for u8 { + type Error = Error; + + #[inline] + fn try_from_slice(val: &'a [u8]) -> Result { + if val.len() != 1 { + return Err(Error::InvalidU16Size(val.len())); + } + Ok(u8::from_le_bytes([val[0]])) + } +} + impl<'a> TryFromBSlice<'a> for u16 { type Error = Error; diff --git a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/option.rs b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/option.rs index 6a6949a907..d67969f3a1 100644 --- a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/option.rs +++ b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/option.rs @@ -4,7 +4,11 @@ use super::{ }; use crate::primitives::{FixedSize, GetSize}; use alloc::vec::Vec; -use serde::{ser, ser::SerializeTuple, Deserialize, Deserializer, Serialize}; +use debug_assert; +use serde::{ + ser::{self, SerializeSeq, SerializeTuple}, + Deserialize, Deserializer, Serialize, +}; #[derive(Debug, Clone)] pub struct Sv2Option<'s, T: Serialize + TryFromBSlice<'s> + Clone> { @@ -65,13 +69,28 @@ impl<'s, T: Clone + Serialize + TryFromBSlice<'s>> Serialize for Sv2Option<'s, T seq.end() } (None, Some(data)) => { - let tuple = (data.len() as u8, &data[..]); - let mut seq = serializer.serialize_tuple(2)?; - seq.serialize_element(&tuple.0)?; - seq.serialize_element(tuple.1)?; - seq.end() + if serializer.is_human_readable() { + let data_ = data.clone(); + let mut seq = serializer.serialize_seq(Some(data_.len()))?; + for item in data_ { + seq.serialize_element(&item)?; + } + seq.end() + } else { + let tuple = (data.len() as u8, &data[..]); + let mut seq = serializer.serialize_tuple(2)?; + seq.serialize_element(&tuple.0)?; + seq.serialize_element(tuple.1)?; + seq.end() + } + } + _ => { + debug_assert!( + false, + "sv2option can never have boh fields of the same type" + ); + panic!() } - _ => panic!(), } } } @@ -219,15 +238,30 @@ impl<'a, T: Clone + FixedSize + Serialize + TryFromBSlice<'a>> GetSize for Sv2Op } impl<'s> Sv2Option<'s, U256<'s>> { pub fn into_static(self) -> Sv2Option<'static, U256<'static>> { - if let Some(inner) = self.data { - let inner = inner.clone(); - let data = inner.into_iter().map(|i| i.into_static()).collect(); - Sv2Option { - seq: None, - data: Some(data), + match (self.data, self.seq) { + (None, Some(seq)) => { + let data = seq.parse().unwrap(); + let data = data.into_iter().map(|i| i.into_static()).collect(); + Sv2Option { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => { + let inner = inner.clone(); + let data = inner.into_iter().map(|i| i.into_static()).collect(); + Sv2Option { + seq: None, + data: Some(data), + } + } + _ => { + debug_assert!( + false, + "sv2option can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } pub fn inner_as_ref(&self) -> &[&[u8]] { @@ -236,13 +270,28 @@ impl<'s> Sv2Option<'s, U256<'s>> { } impl<'s> Sv2Option<'s, u32> { pub fn into_static(self) -> Sv2Option<'static, u32> { - if let Some(inner) = self.data { - Sv2Option { + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + Sv2Option { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => Sv2Option { seq: None, data: Some(inner), + }, + _ => { + debug_assert!( + false, + "sv2option can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } } diff --git a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq0255.rs b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq0255.rs index 2f01bce3ce..de2e27f15b 100644 --- a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq0255.rs +++ b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq0255.rs @@ -7,7 +7,11 @@ use crate::{ Error, }; use alloc::vec::Vec; -use serde::{ser, ser::SerializeTuple, Deserialize, Deserializer, Serialize}; +use serde::{ + ser, + ser::{SerializeSeq, SerializeTuple}, + Deserialize, Deserializer, Serialize, +}; #[derive(Debug, Clone)] pub struct Seq0255<'s, T: Serialize + TryFromBSlice<'s> + Clone> { @@ -68,11 +72,20 @@ impl<'s, T: Clone + Serialize + TryFromBSlice<'s>> Serialize for Seq0255<'s, T> seq.end() } (None, Some(data)) => { - let tuple = (data.len() as u8, &data[..]); - let mut seq = serializer.serialize_tuple(2)?; - seq.serialize_element(&tuple.0)?; - seq.serialize_element(tuple.1)?; - seq.end() + if serializer.is_human_readable() { + let data_ = data.clone(); + let mut seq = serializer.serialize_seq(Some(data_.len()))?; + for item in data_ { + seq.serialize_element(&item)?; + } + seq.end() + } else { + let tuple = (data.len() as u8, &data[..]); + let mut seq = serializer.serialize_tuple(2)?; + seq.serialize_element(&tuple.0)?; + seq.serialize_element(tuple.1)?; + seq.end() + } } _ => panic!(), } @@ -222,15 +235,33 @@ impl<'a, T: Clone + FixedSize + Serialize + TryFromBSlice<'a>> GetSize for Seq02 } impl<'s> Seq0255<'s, U256<'s>> { pub fn into_static(self) -> Seq0255<'static, U256<'static>> { - if let Some(inner) = self.data { - let inner = inner.clone(); - let data = inner.into_iter().map(|i| i.into_static()).collect(); - Seq0255 { - seq: None, - data: Some(data), + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + let data = data.into_iter().map(|i| i.into_static()).collect(); + Seq0255 { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => { + let inner = inner.clone(); + let data = inner.into_iter().map(|i| i.into_static()).collect(); + Seq0255 { + seq: None, + data: Some(data), + } + } + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } pub fn inner_as_ref(&self) -> &[&[u8]] { @@ -239,13 +270,28 @@ impl<'s> Seq0255<'s, U256<'s>> { } impl<'s> Seq0255<'s, u32> { pub fn into_static(self) -> Seq0255<'static, u32> { - if let Some(inner) = self.data { - Seq0255 { + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + Seq0255 { + seq: None, + data: Some(data), + } + } + (Some(data), None) => Seq0255 { seq: None, - data: Some(inner), + data: Some(data), + }, + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } } diff --git a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq064k.rs b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq064k.rs index 8c2428d913..a7b2a610c2 100644 --- a/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq064k.rs +++ b/protocols/v2/binary-sv2/serde-sv2/src/primitives/sequences/seq064k.rs @@ -7,7 +7,11 @@ use crate::{ Error, ShortTxId, }; use alloc::vec::Vec; -use serde::{ser, ser::SerializeTuple, Deserialize, Deserializer, Serialize}; +use serde::{ + ser, + ser::{SerializeSeq, SerializeTuple}, + Deserialize, Deserializer, Serialize, +}; #[derive(Debug, Clone)] pub struct Seq064K<'s, T: Clone + Serialize + TryFromBSlice<'s>> { @@ -101,11 +105,20 @@ impl<'s, T: Clone + FixedSize + Serialize + TryFromBSlice<'s>> Serialize for Seq seq.end() } (None, Some(data)) => { - let tuple = (data.len() as u16, &data[..]); - let mut seq = serializer.serialize_tuple(2)?; - seq.serialize_element(&tuple.0)?; - seq.serialize_element(tuple.1)?; - seq.end() + if serializer.is_human_readable() { + let data_ = self.data.clone().unwrap(); + let mut seq = serializer.serialize_seq(Some(data_.len()))?; + for item in data_ { + seq.serialize_element(&item)?; + } + seq.end() + } else { + let tuple = (data.len() as u16, &data[..]); + let mut seq = serializer.serialize_tuple(2)?; + seq.serialize_element(&tuple.0)?; + seq.serialize_element(tuple.1)?; + seq.end() + } } _ => panic!(), } @@ -431,29 +444,67 @@ impl<'a> GetSize for Seq064K<'a, B064K<'a>> { } impl<'s> Seq064K<'s, B064K<'s>> { pub fn into_static(self) -> Seq064K<'static, B064K<'static>> { - if let Some(inner) = self.data { - let inner = inner.clone(); - let data: Vec> = inner.into_iter().map(|i| i.into_static()).collect(); - Seq064K { - seq: None, - data: Some(data), + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + let data = data.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => { + let inner = inner.clone(); + let data: Vec> = + inner.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } } impl<'s> Seq064K<'s, B016M<'s>> { pub fn into_static(self) -> Seq064K<'static, B016M<'static>> { - if let Some(inner) = self.data { - let inner = inner.clone(); - let data: Vec> = inner.into_iter().map(|i| i.into_static()).collect(); - Seq064K { - seq: None, - data: Some(data), + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + let data = data.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => { + let inner = inner.clone(); + let data: Vec> = + inner.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } pub fn to_vec(&self) -> Vec> { @@ -467,40 +518,89 @@ impl<'s> Seq064K<'s, B016M<'s>> { } impl<'s> Seq064K<'s, u32> { pub fn into_static(self) -> Seq064K<'static, u32> { - if let Some(inner) = self.data { - Seq064K { + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + Seq064K { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => Seq064K { seq: None, data: Some(inner), + }, + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } } impl<'s> Seq064K<'s, u16> { pub fn into_static(self) -> Seq064K<'static, u16> { - if let Some(inner) = self.data { - Seq064K { + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + Seq064K { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => Seq064K { seq: None, data: Some(inner), + }, + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } } +// AAAAAA da qui impl<'s> Seq064K<'s, ShortTxId<'s>> { pub fn into_static(self) -> Seq064K<'static, ShortTxId<'static>> { - if let Some(inner) = self.data { - let inner = inner.clone(); - let data: Vec> = - inner.into_iter().map(|i| i.into_static()).collect(); - Seq064K { - seq: None, - data: Some(data), + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + let data = data.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => { + let inner = inner.clone(); + let data: Vec> = + inner.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } pub fn to_vec(&self) -> Vec> { @@ -514,15 +614,33 @@ impl<'s> Seq064K<'s, ShortTxId<'s>> { } impl<'s> Seq064K<'s, U256<'s>> { pub fn into_static(self) -> Seq064K<'static, U256<'static>> { - if let Some(inner) = self.data { - let inner = inner.clone(); - let data: Vec> = inner.into_iter().map(|i| i.into_static()).collect(); - Seq064K { - seq: None, - data: Some(data), + match (self.data, self.seq) { + (None, Some(seq)) => { + // this is an already valid seq should be safe to call the unwraps. + // also this library shouldn't be used for priduction envs so is ok do thigs like this + // one + let data = seq.parse().unwrap(); + let data = data.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + (Some(inner), None) => { + let inner = inner.clone(); + let data: Vec> = inner.into_iter().map(|i| i.into_static()).collect(); + Seq064K { + seq: None, + data: Some(data), + } + } + _ => { + debug_assert!( + false, + "sequences can never have boh fields of the same type" + ); + panic!() } - } else { - panic!() } } } diff --git a/roles/Cargo.lock b/roles/Cargo.lock index fbaeadc6da..50dee08b42 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -2053,7 +2053,7 @@ dependencies = [ [[package]] name = "sv1_api" -version = "1.0.0" +version = "1.0.1" dependencies = [ "binary_sv2", "bitcoin_hashes 0.3.2", diff --git a/utils/message-generator/src/main.rs b/utils/message-generator/src/main.rs index e2633ed23a..597f619a47 100644 --- a/utils/message-generator/src/main.rs +++ b/utils/message-generator/src/main.rs @@ -452,14 +452,17 @@ mod test { net::{setup_as_downstream, setup_as_upstream}, }; use codec_sv2::Sv2Frame; + use key_utils::Secp256k1PublicKey; use roles_logic_sv2::{ + common_messages_sv2::{Protocol, SetupConnection}, + job_declaration_sv2::DeclareMiningJob, mining_sv2::{ - CloseChannel, NewExtendedMiningJob, OpenExtendedMiningChannel, + CloseChannel, NewExtendedMiningJob, NewMiningJob, OpenExtendedMiningChannel, OpenExtendedMiningChannelSuccess, SetCustomMiningJob, SetTarget, }, - parsers::Mining, + parsers::{CommonMessages, Mining}, }; - use std::convert::TryInto; + use std::{convert::TryInto, io::Write}; use tokio::join; // The following test see that the composition serialise fist and deserialize @@ -472,7 +475,6 @@ mod test { let message_as_string = serde_json::to_string(&message_as_serde_value).unwrap(); let message: AnyMessage<'_> = serde_json::from_str(&message_as_string).unwrap(); let m_ = into_static(message); - let message_as_string_ = serde_json::to_string(&m_).unwrap(); let message_ = match message_ { AnyMessage::Mining(m) => m, @@ -572,6 +574,7 @@ mod test { assert!(message_new == message); } + #[test] fn test_serialize_and_deserialize_5_scmj() { let message = SetCustomMiningJob { channel_id: 1, @@ -597,33 +600,53 @@ mod test { assert!(message_new == message); } - //DeclareMiningJob in Declaration Protocol - // TODO! MAKE THIS TEST COMPILE AND PASS! - //fn test_serialize_and_deserialize_6_dmj() { - // let message = DeclareMiningJob { - // request_id: 1, - // mining_job_token: binary_sv2::B0255::try_from(vec![3, 0, 0, 0]).unwrap(), - // version: 2, - // coinbase_tx_version: 2, - // coinbase_prefix: todo!(), - // coinbase_tx_input_n_sequence: 1, - // coinbase_tx_value_remaining: 1, - // coinbase_tx_outputs: binary_sv2::B064K::try_from(vec![0, 1, 1]).unwrap(), - // coinbase_tx_locktime: 1, - // min_extranonce_size: 1, - // tx_short_hash_nonce: 1, - // tx_short_hash_list: binary_sv2::Seq064K::new(vec![binary_sv2::ShortTxId::try_from( - // [1; 32], - // )]), - // tx_hash_list_hash: todo!(), - // excess_data: todo!(), - // }; - // let message_as_serde_value = serde_json::to_value(message.clone()).unwrap(); - // let message_as_string = serde_json::to_string(&message_as_serde_value).unwrap(); - // let message_new: DeclareMiningJob = serde_json::from_str(&message_as_string).unwrap(); + #[test] + fn test_serialize_and_deserialize_6_dmj() { + let short_tx_id_inner_: Vec = vec![0, 1, 2, 3, 4, 5]; + let short_tx_id_inner = short_tx_id_inner_.as_slice(); + let short_tx_id = binary_sv2::ShortTxId::try_from(short_tx_id_inner).unwrap(); + let prefix_inner = vec![0_u8; 32]; + let prefix_inner_as_ref = prefix_inner.as_slice(); + let message = DeclareMiningJob { + request_id: 1, + mining_job_token: binary_sv2::B0255::try_from(vec![3, 0, 0, 0]).unwrap(), + version: 2, + coinbase_prefix: binary_sv2::B064K::try_from(prefix_inner_as_ref).unwrap(), + coinbase_suffix: binary_sv2::B064K::try_from(prefix_inner_as_ref).unwrap(), + tx_short_hash_nonce: 1, + tx_short_hash_list: binary_sv2::Seq064K::new(vec![short_tx_id]).unwrap(), + tx_hash_list_hash: binary_sv2::U256::try_from(vec![1_u8; 32]).unwrap(), + excess_data: binary_sv2::B064K::try_from(prefix_inner_as_ref).unwrap(), + }; + let message_as_serde_value = serde_json::to_value(message.clone()).unwrap(); + dbg!(&message_as_serde_value); + let message_as_string = serde_json::to_string(&message_as_serde_value).unwrap(); + let message_new: DeclareMiningJob = serde_json::from_str(&message_as_string).unwrap(); - // assert!(message_new == message); - //} + assert!(message_new == message); + } + + //{"Mining":{"NewMiningJob":{"channel_id":1,"job_id":2,"min_ntime":[0,[]],"version":536870912,"merkle_root":[141,193,6,239,151,79,49,202,237,183,207,121,56,40,107,153,235,208,66,215,81,186,3,16,215,110,130,182,37,198,98,251]}}} + + #[test] + fn test_serialize_and_deserialize_7_nmj() { + let inner_: Vec = vec![ + 141, 193, 6, 239, 151, 79, 49, 202, 237, 183, 207, 121, 56, 40, 107, 153, 235, 208, 66, + 215, 81, 186, 3, 16, 215, 110, 130, 182, 37, 198, 98, 251, + ]; + let inner = inner_.as_slice(); + let message = NewMiningJob { + channel_id: 1, + job_id: 2, + min_ntime: binary_sv2::Sv2Option::try_from(vec![]).unwrap(), + version: 536870912, + merkle_root: binary_sv2::B032::try_from(inner).unwrap(), + }; + let message_as_serde_value = serde_json::to_value(message.clone()).unwrap(); + let message_as_string = serde_json::to_string(&message_as_serde_value).unwrap(); + let message_new: NewMiningJob = serde_json::from_str(&message_as_string).unwrap(); + assert!(message_new == message); + } #[tokio::test] async fn it_send_and_receive() { @@ -710,111 +733,123 @@ mod test { assert!(true) } - //#[tokio::test] - //async fn it_initialize_a_pool_and_connect_to_it() { - // //let mut bitcoind = os_command( - // // "./test/bin/bitcoind", - // // vec!["--regtest", "--datadir=./test/appdata/bitcoin_data/"], - // // ExternalCommandConditions::new_with_timer_secs(10) - // // .continue_if_std_out_have("sv2 thread start") - // // .fail_if_anything_on_std_err(), - // //) - // //.await; - // //let mut child = os_command( - // // "./test/bin/bitcoin-cli", - // // vec![ - // // "--regtest", - // // "--datadir=./test/appdata/bitcoin_data/", - // // "generatetoaddress", - // // "16", - // // "bcrt1qttuwhmpa7a0ls5kr3ye6pjc24ng685jvdrksxx", - // // ], - // // ExternalCommandConditions::None, - // //) - // //.await; - // //child.unwrap().wait().await.unwrap(); - // let mut pool = os_command( - // "cargo", - // vec![ - // "llvm-cov", - // "--no-report", - // "run", - // "-p", - // "pool_sv2", - // "--", - // "-c", - // "./test/config/pool-config-sri-tp.toml", - // ], - // ExternalCommandConditions::new_with_timer_secs(60) - // .continue_if_std_out_have("Listening for encrypted connection on: 127.0.0.1:34254"), - // ) - // .await; + #[tokio::test] + // for testing purposes, it may be useful to leave the code for running bitcoind + async fn it_initialize_a_pool_and_connect_to_it() { + //dont clean the following commented code + /* + let mut bitcoind = os_command( + "./test/bin/bitcoind", + vec!["--regtest", "--datadir=./test/appdata/bitcoin_data/"], + ExternalCommandConditions::new_with_timer_secs(10) + .continue_if_std_out_have("sv2 thread start") + .fail_if_anything_on_std_err(), + ) + .await; + let mut child = os_command( + "./test/bin/bitcoin-cli", + vec![ + "--regtest", + "--datadir=./test/appdata/bitcoin_data/", + "generatetoaddress", + "16", + "bcrt1qttuwhmpa7a0ls5kr3ye6pjc24ng685jvdrksxx", + ], + ExternalCommandConditions::None, + ) + .await; + child.unwrap().wait().await.unwrap(); + */ + let pool = os_command( + "cargo", + vec![ + "llvm-cov", + "--no-report", + "run", + "-p", + "pool_sv2", + "--", + "-c", + "../test/config/pool-config-sri-tp.toml", + ], + ExternalCommandConditions::new_with_timer_secs(60) + .continue_if_std_out_have("Listening for encrypted connection on: 127.0.0.1:34254"), + ) + .await; + //wait that the pool initializes + tokio::time::sleep(std::time::Duration::from_secs(4)).await; + + let setup_connection = CommonMessages::SetupConnection(SetupConnection { + protocol: Protocol::MiningProtocol, + min_version: 2, + max_version: 2, + flags: 0, + endpoint_host: "".to_string().try_into().unwrap(), + endpoint_port: 0, + vendor: "".to_string().try_into().unwrap(), + hardware_version: "".to_string().try_into().unwrap(), + firmware: "".to_string().try_into().unwrap(), + device_id: "".to_string().try_into().unwrap(), + }); - // let setup_connection = CommonMessages::SetupConnection(SetupConnection { - // protocol: Protocol::MiningProtocol, - // min_version: 2, - // max_version: 2, - // flags: 0, - // endpoint_host: "".to_string().try_into().unwrap(), - // endpoint_port: 0, - // vendor: "".to_string().try_into().unwrap(), - // hardware_version: "".to_string().try_into().unwrap(), - // firmware: "".to_string().try_into().unwrap(), - // device_id: "".to_string().try_into().unwrap(), - // }); - - // let frame = Sv2Frame::from_message( - // setup_connection.clone(), - // const_sv2::MESSAGE_TYPE_SETUP_CONNECTION, - // 0, - // true, - // ) - // .unwrap(); - - // let frame = EitherFrame::Sv2(frame); - - // let pool_address = SocketAddr::new("127.0.0.1".parse().unwrap(), 34254); - // let pub_key: EncodedEd25519PublicKey = "2di19GHYQnAZJmEpoUeP7C3Eg9TCcksHr23rZCC83dvUiZgiDL" - // .to_string() - // .try_into() - // .unwrap(); - // tokio::time::sleep(std::time::Duration::from_secs(1)).await; - // let (recv_from_pool, send_to_pool) = setup_as_downstream(pool_address, Some(pub_key)).await; - // send_to_pool.send(frame.try_into().unwrap()).await.unwrap(); - // match recv_from_pool.recv().await.unwrap() { - // EitherFrame::Sv2(a) => { - // assert!(true) - // } - // _ => assert!(false), - // } - // let mut child = os_command( - // "rm", - // vec!["-rf", "./test/appdata/bitcoin_data/regtest"], - // ExternalCommandConditions::None, - // ) - // .await; - // child.unwrap().wait().await.unwrap(); + let frame = Sv2Frame::from_message( + setup_connection.clone(), + const_sv2::MESSAGE_TYPE_SETUP_CONNECTION, + 0, + true, + ) + .unwrap(); - // // TODO not panic in network utils but return an handler - // //pool.kill().unwrap(); - // //bitcoind.kill().await.unwrap(); - // assert!(true) - //} + let frame = EitherFrame::Sv2(frame); + + let pool_address = SocketAddr::new("127.0.0.1".parse().unwrap(), 34254); + let pub_key: Secp256k1PublicKey = "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72" + .to_string() + .try_into() + .unwrap(); + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + let (recv_from_pool, send_to_pool) = setup_as_downstream(pool_address, Some(pub_key)).await; + send_to_pool.send(frame.try_into().unwrap()).await.unwrap(); + match recv_from_pool.recv().await.unwrap() { + EitherFrame::Sv2(_a) => { + assert!(true) + } + _ => assert!(false), + } + // dont clean the following commented code + /* + let mut child = os_command( + "rm", + vec!["-rf", "./test/appdata/bitcoin_data/regtest"], + ExternalCommandConditions::None, + ) + .await; + child.unwrap().wait().await.unwrap(); + */ + + // TODO not panic in network utils but return an handler + pool.unwrap().kill().await.unwrap(); + //bitcoind.kill().await.unwrap(); + assert!(true) + } + //// the previous version of this test used mining-proxy, which is currently broken. Possibly + //// this is due to the lack of elligator swift supporto for the mining-proxy, and in general the + //// handshake needs maintainance //#[tokio::test] //async fn it_test_against_remote_endpoint() { - // let proxy = match os_command( + // let _proxy = match os_command( // "cargo", // vec![ // "run", // "-p", - // "mining-proxy", + // "translator_sv2", // "--", // "-c", - // "./test/config/ant-pool-config.toml", + // "translator/config-examples/tproxy-config-hosted-pool-example.toml", // ], // ExternalCommandConditions::new_with_timer_secs(10) - // .continue_if_std_out_have("PROXY INITIALIZED") + // .continue_if_std_out_have("Connected to upstream!j") // .warn_no_panic(), // ) // .await @@ -832,7 +867,7 @@ mod test { // //loop {} // let _ = os_command( // "cargo", - // vec!["run", "-p", "mining-device"], + // vec!["run", "-p", "sv1-mining-device"], // ExternalCommandConditions::new_with_timer_secs(10) // .continue_if_std_out_have("channel opened with"), // ) diff --git a/utils/message-generator/src/parser/sv1_messages.rs b/utils/message-generator/src/parser/sv1_messages.rs index c80f15950a..83d4eee44c 100644 --- a/utils/message-generator/src/parser/sv1_messages.rs +++ b/utils/message-generator/src/parser/sv1_messages.rs @@ -67,6 +67,7 @@ mod test { params: json!(["username", "password"]), }, id: "authorize".to_string(), + replace_fields: Some(vec![]), }; assert_eq!(m1.message.params, m2.message.params); diff --git a/utils/message-generator/test.json b/utils/message-generator/test.json index d3e376a05d..7c422b8a5a 100644 --- a/utils/message-generator/test.json +++ b/utils/message-generator/test.json @@ -91,18 +91,18 @@ ], [ "extranonce_prefix", - {"B032": [[32], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]]} + {"B032": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]} ] ] ] }, { "type": "match_message_type", - "value": "0x20" + "value": "0x1f" }, { "type": "match_message_type", - "value": "0x1f" + "value": "0x20" } ], "actiondoc": "" @@ -115,17 +115,18 @@ "args": [ "run", "-p", - "pool", + "pool_sv2", "--", "-c", - "./test/config/pool-config-sri-tp.toml" + "../test/config/pool-config-sri-tp.toml" ], "conditions": { "WithConditions": { "conditions": [ { - "output_string": "Listening for encrypted connection on: 0.0.0.0:34254", + "output_string": "Listening for encrypted connection on: 127.0.0.1:34254", "output_location": "StdOut", + "late_condition": false, "condition": true } ], @@ -136,6 +137,11 @@ } ], "execution_commands": [ + { + "command": "pkill", + "args": ["-f", "pool_sv2", "-SIGINT"], + "conditions": "None" + } ], "cleanup_commands": [ ], @@ -143,6 +149,6 @@ "downstream": { "ip": "0.0.0.0", "port": 34254, - "pub_key": "2di19GHYQnAZJmEpoUeP7C3Eg9TCcksHr23rZCC83dvUiZgiDL" + "pub_key": "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72" } }