diff --git a/fuzz/fuzz_targets/end_to_end_serialization_for_datatypes.rs b/fuzz/fuzz_targets/end_to_end_serialization_for_datatypes.rs index 8ce0aa8c77..53bb09afb9 100644 --- a/fuzz/fuzz_targets/end_to_end_serialization_for_datatypes.rs +++ b/fuzz/fuzz_targets/end_to_end_serialization_for_datatypes.rs @@ -5,7 +5,7 @@ mod common; use binary_sv2::{ Decodable, Encodable, GetSize, PubKey, Seq0255, Seq064K, Signature, Str0255, Sv2Option, - U32AsRef, B016M, B0255, B032, B064K, U24, U256, + B016M, B0255, B032, B064K, U24, U256, }; use libfuzzer_sys::fuzz_target; @@ -14,7 +14,6 @@ enum FuzzInput { PubKey(Vec), Signature(Vec), Str0255(Vec), - U32AsRef(Vec), B016M(Vec), B0255(Vec), B032(Vec), @@ -77,7 +76,6 @@ fuzz_target!(|input: FuzzInput| { FuzzInput::PubKey(data) => test_datatype_roundtrip!(PubKey, data), FuzzInput::Signature(data) => test_datatype_roundtrip!(Signature, data), FuzzInput::Str0255(data) => test_datatype_roundtrip!(Str0255, data), - FuzzInput::U32AsRef(data) => test_datatype_roundtrip!(U32AsRef, data), FuzzInput::B016M(data) => test_datatype_roundtrip!(B016M, data), FuzzInput::B0255(data) => test_datatype_roundtrip!(B0255, data), FuzzInput::B032(data) => test_datatype_roundtrip!(B032, data), diff --git a/stratum-core/stratum-translation/src/sv2_to_sv1.rs b/stratum-core/stratum-translation/src/sv2_to_sv1.rs index d7d8d9ed60..4103b38e28 100644 --- a/stratum-core/stratum-translation/src/sv2_to_sv1.rs +++ b/stratum-core/stratum-translation/src/sv2_to_sv1.rs @@ -45,8 +45,8 @@ pub fn build_sv1_notify_from_sv2( clean_jobs: bool, ) -> Result> { let new_job = match try_strip_bip141( - new_job.coinbase_tx_prefix.inner_as_ref(), - new_job.coinbase_tx_suffix.inner_as_ref(), + new_job.coinbase_tx_prefix.as_bytes(), + new_job.coinbase_tx_suffix.as_bytes(), ) .map_err(StratumTranslationError::FailedToTryToStripBip141)? { @@ -66,9 +66,9 @@ pub fn build_sv1_notify_from_sv2( let job_id = new_job.job_id.to_string(); let prev_hash = PrevHash(new_prev_hash.prev_hash.clone()); - let coin_base1 = new_job.coinbase_tx_prefix.to_vec().into(); - let coin_base2 = new_job.coinbase_tx_suffix.to_vec().into(); - let merkle_path = new_job.merkle_path.clone().into_static().0; + let coin_base1 = new_job.coinbase_tx_prefix.to_owned_bytes().into(); + let coin_base2 = new_job.coinbase_tx_suffix.to_owned_bytes().into(); + let merkle_path = new_job.merkle_path.clone().into_static().into_inner(); let merkle_branch: Vec = merkle_path.into_iter().map(MerkleNode).collect(); let version = HexU32Be(new_job.version); let bits = HexU32Be(new_prev_hash.nbits); diff --git a/sv1/src/methods/client_to_server.rs b/sv1/src/methods/client_to_server.rs index 8977a06aed..0d709e8608 100644 --- a/sv1/src/methods/client_to_server.rs +++ b/sv1/src/methods/client_to_server.rs @@ -169,7 +169,7 @@ impl Submit<'_> { impl From> for Message { fn from(submit: Submit) -> Self { - let ex: String = submit.extra_nonce2.0.inner_as_ref().to_lower_hex_string(); + let ex: String = submit.extra_nonce2.0.as_bytes().to_lower_hex_string(); let mut params: Vec = vec![ submit.user_name.into(), submit.job_id.into(), @@ -335,7 +335,7 @@ impl<'a> TryFrom> for Message { fn try_from(subscribe: Subscribe) -> Result { let params = match (subscribe.agent_signature, subscribe.extranonce1) { - (a, Some(b)) => vec![a, b.0.inner_as_ref().to_lower_hex_string()], + (a, Some(b)) => vec![a, b.0.as_bytes().to_lower_hex_string()], (a, None) => vec![a], }; Ok(Message::StandardRequest(StandardRequest { @@ -800,7 +800,7 @@ fn test_subscribe_with_odd_length_extranonce() { assert_eq!(subscribe.agent_signature, "test-agent"); assert!(subscribe.extranonce1.is_some()); let extranonce = subscribe.extranonce1.unwrap(); - assert_eq!(extranonce.0.inner_as_ref(), &[0x0a, 0xbc]); // "0abc" -> [10, 188] + assert_eq!(extranonce.0.as_bytes(), &[0x0a, 0xbc]); // "0abc" -> [10, 188] } #[test] @@ -816,5 +816,5 @@ fn test_subscribe_with_even_length_extranonce() { assert_eq!(subscribe.agent_signature, "test-agent"); assert!(subscribe.extranonce1.is_some()); let extranonce = subscribe.extranonce1.unwrap(); - assert_eq!(extranonce.0.inner_as_ref(), &[0xab, 0xcd]); // "abcd" -> [171, 205] + assert_eq!(extranonce.0.as_bytes(), &[0xab, 0xcd]); // "abcd" -> [171, 205] } diff --git a/sv1/src/utils.rs b/sv1/src/utils.rs index 0dccec5d41..134f4a57d4 100644 --- a/sv1/src/utils.rs +++ b/sv1/src/utils.rs @@ -15,16 +15,16 @@ pub struct Extranonce<'a>(pub B032<'a>); impl fmt::Display for Extranonce<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0.inner_as_ref().to_lower_hex_string()) + f.write_str(&self.0.as_bytes().to_lower_hex_string()) } } impl Extranonce<'_> { pub fn len(&self) -> usize { - self.0.inner_as_ref().len() + self.0.len() } pub fn is_empty(&self) -> bool { - self.0.inner_as_ref().is_empty() + self.0.is_empty() } } @@ -37,7 +37,7 @@ impl<'a> TryFrom> for Extranonce<'a> { impl<'a> From> for Vec { fn from(v: Extranonce<'a>) -> Self { - v.0.to_vec() + v.0.into_bytes() } } @@ -81,7 +81,7 @@ impl<'a> TryFrom<&str> for Extranonce<'a> { impl<'a> From> for String { fn from(bytes: Extranonce<'a>) -> String { - bytes.0.inner_as_ref().to_lower_hex_string() + bytes.0.as_bytes().to_lower_hex_string() } } @@ -197,7 +197,7 @@ impl fmt::Display for PrevHash<'_> { impl<'a> From> for Vec { fn from(p_hash: PrevHash<'a>) -> Self { - p_hash.0.to_vec() + p_hash.0.into_bytes() } } @@ -226,9 +226,19 @@ impl<'a> TryFrom<&str> for PrevHash<'a> { } Ok(PrevHash(prev_hash_arr.into())) } - _ => Err(error::Error::BadBytesConvert( - binary_sv2::Error::InvalidU256(prev_hash_stratum_order.len()), - )), + _ => { + let len = prev_hash_stratum_order.len(); + Err(error::Error::BadBytesConvert( + binary_sv2::Error::ValueExceedsMaxSize( + true, + 32, + 0, + 0, + prev_hash_stratum_order, + len, + ), + )) + } } } } @@ -245,7 +255,7 @@ impl From> for String { fn from(v: PrevHash) -> Self { let mut prev_hash_stratum_cursor = std::io::Cursor::new(Vec::new()); // swap every u32 from little endian to big endian - for chunk in v.0.inner_as_ref().chunks(size_of::()) { + for chunk in v.0.as_bytes().chunks(size_of::()) { let prev_hash_word = LittleEndian::read_u32(chunk); prev_hash_stratum_cursor .write_u32::(prev_hash_word) @@ -258,7 +268,7 @@ impl From> for String { // / Referencing the internal part of hex bytes impl AsRef<[u8]> for PrevHash<'_> { fn as_ref(&self) -> &[u8] { - self.0.inner_as_ref() + self.0.as_bytes() } } @@ -272,7 +282,7 @@ impl<'a> AsRef> for PrevHash<'a> { /// Referencing the internal part of hex bytes impl AsRef<[u8]> for Extranonce<'_> { fn as_ref(&self) -> &[u8] { - self.0.inner_as_ref() + self.0.as_bytes() } } @@ -281,13 +291,13 @@ pub struct MerkleNode<'a>(pub U256<'a>); impl fmt::Display for MerkleNode<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.inner_as_ref().to_lower_hex_string()) + write!(f, "{}", self.0.as_bytes().to_lower_hex_string()) } } impl MerkleNode<'_> { pub fn is_empty(&self) -> bool { - self.0.inner_as_ref().is_empty() + self.0.is_empty() } } @@ -302,7 +312,7 @@ impl<'a> TryFrom> for MerkleNode<'a> { impl<'a> From> for Vec { fn from(v: MerkleNode<'a>) -> Self { - v.0.to_vec() + v.0.into_bytes() } } @@ -315,7 +325,7 @@ impl<'a> From> for Value { /// Referencing the internal part of hex bytes impl AsRef<[u8]> for MerkleNode<'_> { fn as_ref(&self) -> &[u8] { - self.0.inner_as_ref() + self.0.as_bytes() } } @@ -330,7 +340,7 @@ impl<'a> TryFrom<&str> for MerkleNode<'a> { impl<'a> From> for String { fn from(bytes: MerkleNode<'a>) -> String { - bytes.0.inner_as_ref().to_lower_hex_string() + bytes.0.as_bytes().to_lower_hex_string() } } @@ -432,8 +442,7 @@ mod tests { let value_to_string = back_to_hex_value.as_str().unwrap(); let chunk_size: usize = size_of::(); - let me_chunks = me.clone().0.to_vec(); - let me_chunks = me_chunks.chunks(chunk_size); + let me_chunks = me.0.as_bytes().chunks(chunk_size); for (be_chunk, le_chunk) in bytes.clone().chunks(chunk_size).zip(me_chunks) { let le_chunk = [le_chunk[0], le_chunk[1], le_chunk[2], le_chunk[3]]; let be_chunk = [be_chunk[0], be_chunk[1], be_chunk[2], be_chunk[3]]; diff --git a/sv2/binary-sv2/examples/encode_decode.rs b/sv2/binary-sv2/examples/encode_decode.rs index 8842a5cfd8..66169aceb4 100644 --- a/sv2/binary-sv2/examples/encode_decode.rs +++ b/sv2/binary-sv2/examples/encode_decode.rs @@ -1,7 +1,5 @@ -use binary_sv2::{from_bytes, to_bytes, U24}; -pub use binary_sv2::{Decodable as Deserialize, Encodable as Serialize}; +use binary_sv2::{from_bytes, to_bytes, Deserialize, Serialize, U24}; use core::convert::TryInto; -pub use derive_codec_sv2::{Decodable as Deserialize, Encodable as Serialize}; // The `Test` struct is expanded using the `Deserialize` and `Serialize` procedural macros. // These macros provide the necessary methods for serializing and deserializing the struct. diff --git a/sv2/binary-sv2/src/codec/decodable.rs b/sv2/binary-sv2/src/codec/decodable.rs index 81d928cf2a..c46d817172 100644 --- a/sv2/binary-sv2/src/codec/decodable.rs +++ b/sv2/binary-sv2/src/codec/decodable.rs @@ -1,6 +1,6 @@ use crate::{ codec::{GetSize, SizeHint}, - datatypes::{Signature, Sv2DataType, U32AsRef, B016M, B0255, B032, B064K, U24, U256}, + datatypes::{Mac, Signature, Sv2DataType, B016M, B0255, B032, B064K, U24, U256}, Error, }; use alloc::vec::Vec; @@ -54,9 +54,34 @@ pub trait Decodable<'a>: Sized { #[cfg(not(feature = "no_std"))] fn from_reader(reader: &mut impl Read) -> Result { let mut data = Vec::new(); - reader.read_to_end(&mut data)?; - let structure = Self::get_structure(&data[..])?; + let structure = loop { + match Self::get_structure(&data[..]) { + Ok(structure) => match structure.size_hint_(&data[..], 0) { + Ok(expected_len) => { + if data.len() < expected_len { + let missing = expected_len - data.len(); + let original_len = data.len(); + data.resize(expected_len, 0); + reader.read_exact(&mut data[original_len..original_len + missing])?; + } + break structure; + } + Err(Error::OutOfBound | Error::ReadError(_, _)) => { + let mut next = [0_u8; 1]; + reader.read_exact(&mut next)?; + data.push(next[0]); + } + Err(error) => return Err(error), + }, + Err(Error::OutOfBound | Error::ReadError(_, _)) => { + let mut next = [0_u8; 1]; + reader.read_exact(&mut next)?; + data.push(next[0]); + } + Err(error) => return Err(error), + } + }; let mut fields = Vec::new(); let mut reader = Cursor::new(data); @@ -68,6 +93,23 @@ pub trait Decodable<'a>: Sized { } } +pub(crate) fn from_bytes_owned>(data: Vec) -> Result { + let structure = T::get_structure(&data)?; + let mut fields = Vec::new(); + let mut tail = data.as_slice(); + + for field in structure { + let field_size = field.size_hint_(tail, 0)?; + if field_size > tail.len() { + return Err(Error::DecodableConversionError); + } + let (head, t) = tail.split_at(field_size); + tail = t; + fields.push(field.decode_owned(head)?); + } + T::from_decoded_fields(fields) +} + // Primitive data marker. // // Fundamental data types that can be passed to a decoder to define the structure of the type to be @@ -79,9 +121,9 @@ pub enum PrimitiveMarker { Bool, U24, U256, + Mac, Signature, U32, - U32AsRef, F32, U64, B032, @@ -122,9 +164,9 @@ pub enum DecodablePrimitive<'a> { Bool(bool), U24(U24), U256(U256<'a>), + Mac(Mac<'a>), Signature(Signature<'a>), U32(u32), - U32AsRef(U32AsRef<'a>), F32(f32), U64(u64), B032(B032<'a>), @@ -150,9 +192,9 @@ pub enum DecodableField<'a> { } impl SizeHint for PrimitiveMarker { - // PrimitiveMarker needs introspection to return a size hint. This method is not implementable. + // PrimitiveMarker requires a concrete marker instance to determine the size. fn size_hint(_data: &[u8], _offset: usize) -> Result { - unimplemented!() + Err(Error::UnInitializedDecoder) } fn size_hint_(&self, data: &[u8], offset: usize) -> Result { @@ -162,9 +204,9 @@ impl SizeHint for PrimitiveMarker { Self::Bool => bool::size_hint(data, offset), Self::U24 => U24::size_hint(data, offset), Self::U256 => U256::size_hint(data, offset), + Self::Mac => Mac::size_hint(data, offset), Self::Signature => Signature::size_hint(data, offset), Self::U32 => u32::size_hint(data, offset), - Self::U32AsRef => U32AsRef::size_hint(data, offset), Self::F32 => f32::size_hint(data, offset), Self::U64 => u64::size_hint(data, offset), Self::B032 => B032::size_hint(data, offset), @@ -176,9 +218,9 @@ impl SizeHint for PrimitiveMarker { } impl SizeHint for FieldMarker { - // FieldMarker need introspection to return a size hint. This method is not implementeable + // FieldMarker requires a concrete marker instance to determine the size. fn size_hint(_data: &[u8], _offset: usize) -> Result { - unimplemented!() + Err(Error::UnInitializedDecoder) } fn size_hint_(&self, data: &[u8], offset: usize) -> Result { @@ -196,9 +238,9 @@ impl SizeHint for FieldMarker { } impl SizeHint for Vec { - // FieldMarker need introspection to return a size hint. This method is not implementeable + // The structure must be initialized before its aggregate size can be calculated. fn size_hint(_data: &[u8], _offset: usize) -> Result { - unimplemented!() + Err(Error::UnInitializedDecoder) } fn size_hint_(&self, data: &[u8], offset: usize) -> Result { @@ -246,32 +288,107 @@ impl PrimitiveMarker { // Decodes a primitive value from a byte slice at the given offset, returning the corresponding // `DecodablePrimitive`. The specific decoding logic depends on the type of the primitive (e.g., // `u8`, `u16`, etc.). - fn decode<'a>(&self, data: &'a mut [u8], offset: usize) -> DecodablePrimitive<'a> { + fn decode<'a>( + &self, + data: &'a mut [u8], + offset: usize, + ) -> Result, Error> { match self { - Self::U8 => DecodablePrimitive::U8(u8::from_bytes_unchecked(&mut data[offset..])), - Self::U16 => DecodablePrimitive::U16(u16::from_bytes_unchecked(&mut data[offset..])), - Self::Bool => DecodablePrimitive::Bool(bool::from_bytes_unchecked(&mut data[offset..])), - Self::U24 => DecodablePrimitive::U24(U24::from_bytes_unchecked(&mut data[offset..])), - Self::U256 => DecodablePrimitive::U256(U256::from_bytes_unchecked(&mut data[offset..])), - Self::Signature => { - DecodablePrimitive::Signature(Signature::from_bytes_unchecked(&mut data[offset..])) - } - Self::U32 => DecodablePrimitive::U32(u32::from_bytes_unchecked(&mut data[offset..])), - Self::U32AsRef => { - DecodablePrimitive::U32AsRef(U32AsRef::from_bytes_unchecked(&mut data[offset..])) - } - Self::F32 => DecodablePrimitive::F32(f32::from_bytes_unchecked(&mut data[offset..])), - Self::U64 => DecodablePrimitive::U64(u64::from_bytes_unchecked(&mut data[offset..])), - Self::B032 => DecodablePrimitive::B032(B032::from_bytes_unchecked(&mut data[offset..])), - Self::B0255 => { - DecodablePrimitive::B0255(B0255::from_bytes_unchecked(&mut data[offset..])) - } - Self::B064K => { - DecodablePrimitive::B064K(B064K::from_bytes_unchecked(&mut data[offset..])) - } - Self::B016M => { - DecodablePrimitive::B016M(B016M::from_bytes_unchecked(&mut data[offset..])) - } + Self::U8 => Ok(DecodablePrimitive::U8(u8::from_bytes_( + &mut data[offset..], + )?)), + Self::U16 => Ok(DecodablePrimitive::U16(u16::from_bytes_( + &mut data[offset..], + )?)), + Self::Bool => Ok(DecodablePrimitive::Bool(bool::from_bytes_( + &mut data[offset..], + )?)), + Self::U24 => Ok(DecodablePrimitive::U24(U24::from_bytes_( + &mut data[offset..], + )?)), + Self::U256 => Ok(DecodablePrimitive::U256(U256::from_bytes_( + &mut data[offset..], + )?)), + Self::Mac => Ok(DecodablePrimitive::Mac(Mac::from_bytes_( + &mut data[offset..], + )?)), + Self::Signature => Ok(DecodablePrimitive::Signature(Signature::from_bytes_( + &mut data[offset..], + )?)), + Self::U32 => Ok(DecodablePrimitive::U32(u32::from_bytes_( + &mut data[offset..], + )?)), + Self::F32 => Ok(DecodablePrimitive::F32(f32::from_bytes_( + &mut data[offset..], + )?)), + Self::U64 => Ok(DecodablePrimitive::U64(u64::from_bytes_( + &mut data[offset..], + )?)), + Self::B032 => Ok(DecodablePrimitive::B032(B032::from_bytes_( + &mut data[offset..], + )?)), + Self::B0255 => Ok(DecodablePrimitive::B0255(B0255::from_bytes_( + &mut data[offset..], + )?)), + Self::B064K => Ok(DecodablePrimitive::B064K(B064K::from_bytes_( + &mut data[offset..], + )?)), + Self::B016M => Ok(DecodablePrimitive::B016M(B016M::from_bytes_( + &mut data[offset..], + )?)), + } + } + + fn decode_owned( + &self, + data: &[u8], + offset: usize, + ) -> Result, Error> { + macro_rules! decode_owned_copy { + ($ty:ty, $variant:ident) => {{ + let mut owned = data[offset..].to_vec(); + Ok(DecodablePrimitive::$variant(<$ty>::from_bytes_( + &mut owned, + )?)) + }}; + } + + macro_rules! decode_owned_fixed_inner { + ($ty:ty, $variant:ident) => {{ + let data = &data[offset..]; + let size = <$ty>::size_hint(data, 0)?; + Ok(DecodablePrimitive::$variant(<$ty>::try_from( + data[..size].to_vec(), + )?)) + }}; + } + + macro_rules! decode_owned_variable_inner { + ($ty:ty, $variant:ident, $header_size:expr) => {{ + let data = &data[offset..]; + let size = <$ty>::size_hint(data, 0)?; + let payload = &data[$header_size..size]; + Ok(DecodablePrimitive::$variant(<$ty>::try_from( + payload.to_vec(), + )?)) + }}; + } + + match self { + Self::U8 => decode_owned_copy!(u8, U8), + Self::U16 => decode_owned_copy!(u16, U16), + Self::Bool => decode_owned_copy!(bool, Bool), + Self::U24 => decode_owned_copy!(U24, U24), + Self::U256 => decode_owned_fixed_inner!(U256, U256), + Self::Mac => decode_owned_fixed_inner!(Mac, Mac), + Self::Signature => decode_owned_fixed_inner!(Signature, Signature), + Self::U32 => decode_owned_copy!(u32, U32), + Self::F32 => decode_owned_copy!(f32, F32), + Self::U64 => decode_owned_copy!(u64, U64), + Self::B032 => decode_owned_variable_inner!(B032, B032, 1), + Self::B0255 => decode_owned_variable_inner!(B0255, B0255, 1), + Self::B064K => decode_owned_variable_inner!(B064K, B064K, 2), + Self::B016M => decode_owned_variable_inner!(B016M, B016M, 3), } } @@ -287,13 +404,11 @@ impl PrimitiveMarker { Self::Bool => Ok(DecodablePrimitive::Bool(bool::from_reader_(reader)?)), Self::U24 => Ok(DecodablePrimitive::U24(U24::from_reader_(reader)?)), Self::U256 => Ok(DecodablePrimitive::U256(U256::from_reader_(reader)?)), + Self::Mac => Ok(DecodablePrimitive::Mac(Mac::from_reader_(reader)?)), Self::Signature => Ok(DecodablePrimitive::Signature(Signature::from_reader_( reader, )?)), Self::U32 => Ok(DecodablePrimitive::U32(u32::from_reader_(reader)?)), - Self::U32AsRef => Ok(DecodablePrimitive::U32AsRef(U32AsRef::from_reader_( - reader, - )?)), Self::F32 => Ok(DecodablePrimitive::F32(f32::from_reader_(reader)?)), Self::U64 => Ok(DecodablePrimitive::U64(u64::from_reader_(reader)?)), Self::B032 => Ok(DecodablePrimitive::B032(B032::from_reader_(reader)?)), @@ -312,9 +427,9 @@ impl GetSize for DecodablePrimitive<'_> { DecodablePrimitive::Bool(v) => v.get_size(), DecodablePrimitive::U24(v) => v.get_size(), DecodablePrimitive::U256(v) => v.get_size(), + DecodablePrimitive::Mac(v) => v.get_size(), DecodablePrimitive::Signature(v) => v.get_size(), DecodablePrimitive::U32(v) => v.get_size(), - DecodablePrimitive::U32AsRef(v) => v.get_size(), DecodablePrimitive::F32(v) => v.get_size(), DecodablePrimitive::U64(v) => v.get_size(), DecodablePrimitive::B032(v) => v.get_size(), @@ -332,7 +447,7 @@ impl FieldMarker { // and returns the resulting `DecodableField`. pub(crate) fn decode<'a>(&self, data: &'a mut [u8]) -> Result, Error> { match self { - Self::Primitive(p) => Ok(DecodableField::Primitive(p.decode(data, 0))), + Self::Primitive(p) => Ok(DecodableField::Primitive(p.decode(data, 0)?)), Self::Struct(ps) => { let mut decodeds = Vec::new(); let mut tail = data; @@ -347,6 +462,23 @@ impl FieldMarker { } } + pub(crate) fn decode_owned(&self, data: &[u8]) -> Result, Error> { + match self { + Self::Primitive(p) => Ok(DecodableField::Primitive(p.decode_owned(data, 0)?)), + Self::Struct(ps) => { + let mut decodeds = Vec::new(); + let mut tail = data; + for p in ps { + let field_size = p.size_hint_(tail, 0)?; + let (head, t) = tail.split_at(field_size); + tail = t; + decodeds.push(p.decode_owned(head)?); + } + Ok(DecodableField::Struct(decodeds)) + } + } + } + #[allow(clippy::wrong_self_convention)] #[cfg(not(feature = "no_std"))] #[allow(clippy::wrong_self_convention)] diff --git a/sv2/binary-sv2/src/codec/encodable.rs b/sv2/binary-sv2/src/codec/encodable.rs index eb2bc003af..c4b376c856 100644 --- a/sv2/binary-sv2/src/codec/encodable.rs +++ b/sv2/binary-sv2/src/codec/encodable.rs @@ -1,6 +1,6 @@ use crate::{ codec::GetSize, - datatypes::{Signature, Sv2DataType, U32AsRef, B016M, B0255, B032, B064K, U24, U256}, + datatypes::{Mac, Signature, Sv2DataType, B016M, B0255, B032, B064K, U24, U256}, Error, }; use alloc::vec::Vec; @@ -54,10 +54,10 @@ impl<'a, T: Into>> Encodable for T { } #[cfg(not(feature = "no_std"))] - #[allow(clippy::wrong_self_convention, unconditional_recursion)] + #[allow(clippy::wrong_self_convention)] fn to_writer(self, dst: &mut impl Write) -> Result<(), E> { let encoded_field = self.into(); - encoded_field.to_writer(dst) + EncodableField::to_writer(&encoded_field, dst) } } @@ -70,8 +70,6 @@ impl<'a, T: Into>> Encodable for T { pub enum EncodablePrimitive<'a> { /// U8 Primitive, representing a byte U8(u8), - /// Owned U8 Primitive, representing an owned byte - OwnedU8(u8), /// U16 Primitive, representing a u16 type U16(u16), /// Bool Primitive, representing a bool type @@ -80,12 +78,12 @@ pub enum EncodablePrimitive<'a> { U24(U24), /// U256 Primitive, representing a U256 type U256(U256<'a>), + /// Mac Primitive, representing a MAC type + Mac(Mac<'a>), /// Signature Primitive, representing a Signature type Signature(Signature<'a>), /// U32 Primitive, representing a u32 type U32(u32), - /// U32AsRef Primitive, representing a U32AsRef type - U32AsRef(U32AsRef<'a>), /// F32 Primitive, representing a f32 type F32(f32), /// U64 Primitive, representing a u64 type @@ -109,14 +107,13 @@ impl EncodablePrimitive<'_> { fn encode(&self, dst: &mut [u8]) -> Result { match self { Self::U8(v) => v.to_slice(dst), - Self::OwnedU8(v) => v.to_slice(dst), Self::U16(v) => v.to_slice(dst), Self::Bool(v) => v.to_slice(dst), Self::U24(v) => v.to_slice(dst), Self::U256(v) => v.to_slice(dst), + Self::Mac(v) => v.to_slice(dst), Self::Signature(v) => v.to_slice(dst), Self::U32(v) => v.to_slice(dst), - Self::U32AsRef(v) => v.to_slice(dst), Self::F32(v) => v.to_slice(dst), Self::U64(v) => v.to_slice(dst), Self::B032(v) => v.to_slice(dst), @@ -135,14 +132,13 @@ impl EncodablePrimitive<'_> { pub fn write(&self, writer: &mut impl Write) -> Result<(), E> { match self { Self::U8(v) => v.to_writer_(writer), - Self::OwnedU8(v) => v.to_writer_(writer), Self::U16(v) => v.to_writer_(writer), Self::Bool(v) => v.to_writer_(writer), Self::U24(v) => v.to_writer_(writer), Self::U256(v) => v.to_writer_(writer), + Self::Mac(v) => v.to_writer_(writer), Self::Signature(v) => v.to_writer_(writer), Self::U32(v) => v.to_writer_(writer), - Self::U32AsRef(v) => v.to_writer_(writer), Self::F32(v) => v.to_writer_(writer), Self::U64(v) => v.to_writer_(writer), Self::B032(v) => v.to_writer_(writer), @@ -158,14 +154,13 @@ impl GetSize for EncodablePrimitive<'_> { fn get_size(&self) -> usize { match self { Self::U8(v) => v.get_size(), - Self::OwnedU8(v) => v.get_size(), Self::U16(v) => v.get_size(), Self::Bool(v) => v.get_size(), Self::U24(v) => v.get_size(), Self::U256(v) => v.get_size(), + Self::Mac(v) => v.get_size(), Self::Signature(v) => v.get_size(), Self::U32(v) => v.get_size(), - Self::U32AsRef(v) => v.get_size(), Self::F32(v) => v.get_size(), Self::U64(v) => v.get_size(), Self::B032(v) => v.get_size(), diff --git a/sv2/binary-sv2/src/codec/impls.rs b/sv2/binary-sv2/src/codec/impls.rs index 1e98b1bc29..fca36478f7 100644 --- a/sv2/binary-sv2/src/codec/impls.rs +++ b/sv2/binary-sv2/src/codec/impls.rs @@ -9,789 +9,209 @@ use crate::{ Error, }; use alloc::vec::Vec; -use core::convert::{TryFrom, TryInto}; - -// IMPL GET MARKER FOR PRIMITIVES -impl GetMarker for bool { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::Bool) - } -} -impl GetMarker for u8 { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::U8) - } -} -impl GetMarker for u16 { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::U16) - } -} -impl GetMarker for U24 { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::U24) - } -} -impl GetMarker for u32 { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::U32) - } -} -impl GetMarker for f32 { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::F32) - } -} -impl GetMarker for u64 { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::U64) - } -} -impl GetMarker for U256<'_> { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::U256) - } -} -impl GetMarker for Signature<'_> { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::Signature) - } -} -impl GetMarker for B032<'_> { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::B032) - } -} -impl GetMarker for B0255<'_> { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::B0255) - } -} -impl GetMarker for B064K<'_> { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::B064K) - } -} -impl GetMarker for B016M<'_> { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::B016M) - } -} -impl GetMarker for U32AsRef<'_> { - fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::U32AsRef) - } -} - -// IMPL DECODABLE FOR PRIMITIVES - -impl<'a> Decodable<'a> for u8 { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::U8.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for u16 { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::U16.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for u32 { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::U32.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for f32 { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::F32.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for u64 { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::U64.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for bool { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::Bool.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for U24 { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::U24.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for U256<'a> { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::U256.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for Signature<'a> { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::Signature.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for B032<'a> { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::B032.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for B0255<'a> { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::B0255.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for B064K<'a> { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::B064K.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} -impl<'a> Decodable<'a> for B016M<'a> { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::B016M.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} - -impl<'a> Decodable<'a> for U32AsRef<'a> { - fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::U32AsRef.into()]) - } - - fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() - } -} - -// IMPL TRY_FROM PRIMITIVE FOR PRIMITIVEs - -impl<'a> TryFrom> for u8 { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::U8(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for u16 { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::U16(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for u32 { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::U32(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for f32 { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::F32(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for u64 { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::U64(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for bool { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::Bool(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} - -impl<'a> TryFrom> for U24 { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::U24(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for U256<'a> { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::U256(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for Signature<'a> { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::Signature(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for B032<'a> { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::B032(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for B0255<'a> { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::B0255(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for B064K<'a> { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::B064K(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for B016M<'a> { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::B016M(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} -impl<'a> TryFrom> for U32AsRef<'a> { - type Error = Error; - - fn try_from(value: DecodablePrimitive<'a>) -> Result { - match value { - DecodablePrimitive::U32AsRef(val) => Ok(val), - _ => Err(Error::PrimitiveConversionError), - } - } -} - -// IMPL TRY_FROM DECODEC FIELD FOR PRIMITIVES - -impl<'a> TryFrom> for u8 { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for u16 { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for u32 { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for f32 { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for u64 { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for bool { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for U24 { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for U256<'a> { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for Signature<'a> { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for B032<'a> { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for B0255<'a> { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for B064K<'a> { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for B016M<'a> { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} -impl<'a> TryFrom> for U32AsRef<'a> { - type Error = Error; - - fn try_from(value: DecodableField<'a>) -> Result { - match value { - DecodableField::Primitive(p) => p.try_into(), - _ => Err(Error::DecodableConversionError), - } - } -} - -// IMPL FROM PRIMITIVES FOR ENCODED FIELD - -impl From for EncodableField<'_> { - fn from(v: bool) -> Self { - EncodableField::Primitive(EncodablePrimitive::Bool(v)) - } -} -impl<'a> TryFrom> for bool { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::Bool(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl From for EncodableField<'_> { - fn from(v: u8) -> Self { - EncodableField::Primitive(EncodablePrimitive::U8(v)) - } -} -impl<'a> TryFrom> for u8 { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::U8(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl From for EncodableField<'_> { - fn from(v: u16) -> Self { - EncodableField::Primitive(EncodablePrimitive::U16(v)) - } -} -impl<'a> TryFrom> for u16 { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::U16(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl From for EncodableField<'_> { - fn from(v: U24) -> Self { - EncodableField::Primitive(EncodablePrimitive::U24(v)) - } -} -impl<'a> TryFrom> for U24 { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::U24(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl From for EncodableField<'_> { - fn from(v: u32) -> Self { - EncodableField::Primitive(EncodablePrimitive::U32(v)) - } -} -impl<'a> TryFrom> for u32 { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::U32(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl From for EncodableField<'_> { - fn from(v: f32) -> Self { - EncodableField::Primitive(EncodablePrimitive::F32(v)) - } -} -impl<'a> TryFrom> for f32 { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::F32(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl From for EncodableField<'_> { - fn from(v: u64) -> Self { - EncodableField::Primitive(EncodablePrimitive::U64(v)) - } -} -impl<'a> TryFrom> for u64 { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::U64(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl<'a> From> for EncodableField<'a> { - fn from(v: U256<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::U256(v)) - } -} -impl<'a> TryFrom> for U256<'a> { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::U256(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl<'a> From> for EncodableField<'a> { - fn from(v: Signature<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::Signature(v)) - } -} -impl<'a> TryFrom> for Signature<'a> { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::Signature(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl<'a> From> for EncodableField<'a> { - fn from(v: B032<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::B032(v)) - } -} -impl<'a> From> for EncodableField<'a> { - fn from(v: B0255<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::B0255(v)) - } -} -impl<'a> TryFrom> for B032<'a> { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::B032(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl<'a> TryFrom> for B0255<'a> { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::B0255(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl<'a> From> for EncodableField<'a> { - fn from(v: B064K<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::B064K(v)) - } -} -impl<'a> TryFrom> for B064K<'a> { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::B064K(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl<'a> From> for EncodableField<'a> { - fn from(v: B016M<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::B016M(v)) - } -} -impl<'a> TryFrom> for B016M<'a> { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::B016M(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} -impl<'a> From> for EncodableField<'a> { - fn from(v: U32AsRef<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::U32AsRef(v)) - } -} -impl<'a> TryFrom> for U32AsRef<'a> { - type Error = Error; - - fn try_from(value: EncodableField<'a>) -> Result { - match value { - EncodableField::Primitive(EncodablePrimitive::U32AsRef(v)) => Ok(v), - _ => Err(Error::NonPrimitiveTypeCannotBeEncoded), - } - } -} - -// IMPL INTO FIELD MARKER FOR PRIMITIVES -impl From for FieldMarker { - fn from(_: bool) -> Self { - FieldMarker::Primitive(PrimitiveMarker::Bool) - } -} -impl From for FieldMarker { - fn from(_: u8) -> Self { - FieldMarker::Primitive(PrimitiveMarker::U8) - } -} - -impl From for FieldMarker { - fn from(_: u16) -> Self { - FieldMarker::Primitive(PrimitiveMarker::U16) - } -} - -impl From for FieldMarker { - fn from(_: u32) -> Self { - FieldMarker::Primitive(PrimitiveMarker::U32) - } -} - -impl From for FieldMarker { - fn from(_: f32) -> Self { - FieldMarker::Primitive(PrimitiveMarker::F32) - } -} - -impl From for FieldMarker { - fn from(_: u64) -> Self { - FieldMarker::Primitive(PrimitiveMarker::U64) - } -} - -impl From for FieldMarker { - fn from(_: U24) -> Self { - FieldMarker::Primitive(PrimitiveMarker::U24) - } -} - -impl<'a> From> for FieldMarker { - fn from(_: Inner<'a, true, 32, 0, 0>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::U256) - } -} - -impl<'a> From> for FieldMarker { - fn from(_: Inner<'a, true, 64, 0, 0>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::Signature) - } -} - -impl<'a> From> for FieldMarker { - fn from(_: B032<'a>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::B032) - } -} - -impl<'a> From> for FieldMarker { - fn from(_: Inner<'a, false, 1, 1, 255>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::B0255) - } -} - -impl<'a> From> for FieldMarker { - fn from(_: Inner<'a, false, 1, 2, { 2_usize.pow(16) - 1 }>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::B064K) - } -} - -impl<'a> From> for FieldMarker { - fn from(_: Inner<'a, false, 1, 3, { 2_usize.pow(24) - 1 }>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::B016M) - } -} -impl<'a> From> for FieldMarker { - fn from(_: U32AsRef<'a>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::U32AsRef) - } -} +use core::convert::TryInto; + +macro_rules! impl_get_marker { + ($(($ty:ty, $marker:ident)),+ $(,)?) => { + $( + impl GetMarker for $ty { + fn get_marker() -> FieldMarker { + FieldMarker::Primitive(PrimitiveMarker::$marker) + } + } + )+ + }; +} + +macro_rules! impl_decodable { + ($(($ty:ty, $marker:ident)),+ $(,)?) => { + $( + impl<'a> Decodable<'a> for $ty { + fn get_structure(_: &[u8]) -> Result, Error> { + Ok(vec![PrimitiveMarker::$marker.into()]) + } + + fn from_decoded_fields( + mut data: Vec>, + ) -> Result { + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() + } + } + )+ + }; +} + +macro_rules! impl_try_from_decodable_primitive { + ($(($ty:ty, $variant:ident)),+ $(,)?) => { + $( + impl<'a> TryFrom> for $ty { + type Error = Error; + + fn try_from(value: DecodablePrimitive<'a>) -> Result { + match value { + DecodablePrimitive::$variant(val) => Ok(val), + _ => Err(Error::PrimitiveConversionError), + } + } + } + )+ + }; +} + +macro_rules! impl_try_from_decodable_field { + ($($ty:ty),+ $(,)?) => { + $( + impl<'a> TryFrom> for $ty { + type Error = Error; + + fn try_from(value: DecodableField<'a>) -> Result { + match value { + DecodableField::Primitive(p) => p.try_into(), + _ => Err(Error::DecodableConversionError), + } + } + } + )+ + }; +} + +macro_rules! impl_encodable_field_conversion { + ($(($ty:ty, $variant:ident)),+ $(,)?) => { + $( + impl<'a> From<$ty> for EncodableField<'a> { + fn from(v: $ty) -> Self { + EncodableField::Primitive(EncodablePrimitive::$variant(v)) + } + } + )+ + }; +} + +macro_rules! impl_field_marker_from_owned { + ($(($ty:ty, $marker:ident)),+ $(,)?) => { + $( + impl From<$ty> for FieldMarker { + fn from(_: $ty) -> Self { + FieldMarker::Primitive(PrimitiveMarker::$marker) + } + } + )+ + }; +} + +macro_rules! impl_field_marker_from_borrowed { + ($(($ty:ty, $marker:ident)),+ $(,)?) => { + $( + impl<'a> From<$ty> for FieldMarker { + fn from(_: $ty) -> Self { + FieldMarker::Primitive(PrimitiveMarker::$marker) + } + } + )+ + }; +} + +impl_get_marker!( + (bool, Bool), + (u8, U8), + (u16, U16), + (U24, U24), + (u32, U32), + (f32, F32), + (u64, U64), + (U256<'_>, U256), + (Mac<'_>, Mac), + (Signature<'_>, Signature), + (B032<'_>, B032), + (B0255<'_>, B0255), + (B064K<'_>, B064K), + (B016M<'_>, B016M), +); + +impl_decodable!( + (u8, U8), + (u16, U16), + (u32, U32), + (f32, F32), + (u64, U64), + (bool, Bool), + (U24, U24), + (U256<'a>, U256), + (Mac<'a>, Mac), + (Signature<'a>, Signature), + (B032<'a>, B032), + (B0255<'a>, B0255), + (B064K<'a>, B064K), + (B016M<'a>, B016M), +); + +impl_try_from_decodable_primitive!( + (u8, U8), + (u16, U16), + (u32, U32), + (f32, F32), + (u64, U64), + (bool, Bool), + (U24, U24), + (U256<'a>, U256), + (Mac<'a>, Mac), + (Signature<'a>, Signature), + (B032<'a>, B032), + (B0255<'a>, B0255), + (B064K<'a>, B064K), + (B016M<'a>, B016M), +); + +impl_try_from_decodable_field!( + u8, + u16, + u32, + f32, + u64, + bool, + U24, + U256<'a>, + Mac<'a>, + Signature<'a>, + B032<'a>, + B0255<'a>, + B064K<'a>, + B016M<'a>, +); + +impl_encodable_field_conversion!( + (bool, Bool), + (u8, U8), + (u16, U16), + (U24, U24), + (u32, U32), + (f32, F32), + (u64, U64), + (U256<'a>, U256), + (Mac<'a>, Mac), + (Signature<'a>, Signature), + (B032<'a>, B032), + (B0255<'a>, B0255), + (B064K<'a>, B064K), + (B016M<'a>, B016M), +); + +impl_field_marker_from_owned!( + (bool, Bool), + (u8, U8), + (u16, U16), + (u32, U32), + (f32, F32), + (u64, U64), + (U24, U24), +); + +impl_field_marker_from_borrowed!( + (Inner<'a, true, 16, 0, 0>, Mac), + (Inner<'a, true, 32, 0, 0>, U256), + (Inner<'a, true, 64, 0, 0>, Signature), + (B032<'a>, B032), + (Inner<'a, false, 1, 1, 255>, B0255), + (Inner<'a, false, 1, 2, { 2_usize.pow(16) - 1 }>, B064K), + (Inner<'a, false, 1, 3, { 2_usize.pow(24) - 1 }>, B016M), +); diff --git a/sv2/binary-sv2/src/codec/mod.rs b/sv2/binary-sv2/src/codec/mod.rs index 727d0bb6f4..7d4ec59fa5 100644 --- a/sv2/binary-sv2/src/codec/mod.rs +++ b/sv2/binary-sv2/src/codec/mod.rs @@ -104,12 +104,20 @@ pub trait Fixed { } impl SizeHint for T { - fn size_hint(_data: &[u8], _offset: usize) -> Result { - Ok(Self::SIZE) + fn size_hint(data: &[u8], offset: usize) -> Result { + let available = data + .len() + .checked_sub(offset) + .ok_or(Error::ReadError(data.len(), offset))?; + if available >= Self::SIZE { + Ok(Self::SIZE) + } else { + Err(Error::ReadError(data.len(), offset + Self::SIZE)) + } } - fn size_hint_(&self, _: &[u8], _offset: usize) -> Result { - Ok(Self::SIZE) + fn size_hint_(&self, data: &[u8], offset: usize) -> Result { + Self::size_hint(data, offset) } } diff --git a/sv2/binary-sv2/src/datatypes/copy_data_types.rs b/sv2/binary-sv2/src/datatypes/copy_data_types.rs index 56db4a79f5..44d7a995e6 100644 --- a/sv2/binary-sv2/src/datatypes/copy_data_types.rs +++ b/sv2/binary-sv2/src/datatypes/copy_data_types.rs @@ -12,8 +12,8 @@ // // ### `Sv2DataType` // The `Sv2DataType` trait is implemented for these data types, providing methods for encoding and -// decoding operations such as `from_bytes_unchecked`, `from_vec_`, `from_reader_` (if `std` is -// available), and `to_slice_unchecked`. The methods use little-endian byte order for consistency +// decoding operations such as `from_bytes_`, `from_reader_` (if `std` is available), and +// `to_slice`. The methods use little-endian byte order for consistency // across platforms. // // ## Special Types @@ -27,9 +27,11 @@ // The `impl_sv2_for_unsigned` macro streamlines the implementation of the `Sv2DataType` trait for // unsigned integer types, ensuring little-endian byte ordering for serialization and handling both // in-memory buffers and `std::io::Read`/`Write` interfaces when `std` is available. -use crate::{codec::Fixed, datatypes::Sv2DataType, Error}; - -use alloc::vec::Vec; +use crate::{ + codec::{Fixed, SizeHint}, + datatypes::Sv2DataType, + Error, +}; use core::convert::{TryFrom, TryInto}; #[cfg(not(feature = "no_std"))] @@ -42,27 +44,19 @@ impl Fixed for bool { } impl<'a> Sv2DataType<'a> for bool { - fn from_bytes_unchecked(data: &'a mut [u8]) -> Self { - match data + fn from_bytes_(data: &'a mut [u8]) -> Result { + bool::size_hint(data, 0)?; + let value = match data .first() .map(|x: &u8| x << 7) .map(|x: u8| x >> 7) - // This is an unchecked function is fine to panic .expect("Try to decode a bool from a buffer of len 0") { 0 => false, 1 => true, - // Below panic is impossible value is either 0 or 1 _ => panic!(), - } - } - - fn from_vec_(mut data: Vec) -> Result { - Self::from_bytes_(&mut data) - } - - fn from_vec_unchecked(mut data: Vec) -> Self { - Self::from_bytes_unchecked(&mut data) + }; + Ok(value) } #[cfg(not(feature = "no_std"))] @@ -72,11 +66,15 @@ impl<'a> Sv2DataType<'a> for bool { Self::from_bytes_(&mut dst) } - fn to_slice_unchecked(&'a self, dst: &mut [u8]) { + fn to_slice(&'a self, dst: &mut [u8]) -> Result { + if dst.len() < Self::SIZE { + return Err(Error::WriteError(Self::SIZE, dst.len())); + } match self { true => dst[0] = 1, false => dst[0] = 0, }; + Ok(Self::SIZE) } #[cfg(not(feature = "no_std"))] @@ -114,33 +112,29 @@ impl Fixed for u64 { macro_rules! impl_sv2_for_unsigned { ($a:ty) => { impl<'a> Sv2DataType<'a> for $a { - fn from_bytes_unchecked(data: &'a mut [u8]) -> Self { - // unchecked function is fine to panic + fn from_bytes_(data: &'a mut [u8]) -> Result { + Self::size_hint(data, 0)?; let a: &[u8; Self::SIZE] = data[0..Self::SIZE].try_into().expect( "Try to decode a copy data type from a buffer that do not have enough bytes", ); - Self::from_le_bytes(*a) - } - - fn from_vec_(mut data: Vec) -> Result { - Self::from_bytes_(&mut data) - } - - fn from_vec_unchecked(mut data: Vec) -> Self { - Self::from_bytes_unchecked(&mut data) + Ok(Self::from_le_bytes(*a)) } #[cfg(not(feature = "no_std"))] fn from_reader_(reader: &mut impl Read) -> Result { let mut dst = [0_u8; Self::SIZE]; reader.read_exact(&mut dst)?; - Ok(Self::from_bytes_unchecked(&mut dst)) + Ok(Self::from_le_bytes(dst)) } - fn to_slice_unchecked(&'a self, dst: &mut [u8]) { + fn to_slice(&'a self, dst: &mut [u8]) -> Result { + if dst.len() < Self::SIZE { + return Err(Error::WriteError(Self::SIZE, dst.len())); + } let dst = &mut dst[0..Self::SIZE]; let src = self.to_le_bytes(); dst.copy_from_slice(&src); + Ok(Self::SIZE) } #[cfg(not(feature = "no_std"))] diff --git a/sv2/binary-sv2/src/datatypes/mod.rs b/sv2/binary-sv2/src/datatypes/mod.rs index 86102ba67f..60ae1e4cfe 100644 --- a/sv2/binary-sv2/src/datatypes/mod.rs +++ b/sv2/binary-sv2/src/datatypes/mod.rs @@ -10,9 +10,7 @@ // - **Deserialize**: Convert byte slices or reader sources into Rust types. // - **Serialize**: Encode Rust types into byte slices or write them to I/O streams. // -// Supports both **checked** and **unchecked** variants for serialization and deserialization. -// Checked functions validate data lengths, while unchecked versions assume size correctness for -// optimized performance. +// Checked functions validate data lengths before decoding or encoding. // // ### Modules // - **`copy_data_types`**: Defines fixed-size types directly copied into or from byte slices, such @@ -21,8 +19,8 @@ // strings, requiring size handling logic for SV2 compatibility. // // ### Re-exports -// Re-exports common data types used in SV2 serialization, such as `PubKey`, `Signature`, `Seq0255`, -// and others, simplifying protocol data handling with concrete implementations of `Sv2DataType`. +// Re-exports common data types used in SV2 serialization, such as `Signature`, `Seq0255`, and +// others, simplifying protocol data handling with concrete implementations of `Sv2DataType`. // // The `Sv2DataType` trait and its implementations enable seamless conversion between in-memory // representations and serialized forms, ensuring efficient protocol communication and @@ -38,8 +36,8 @@ mod copy_data_types; use crate::codec::decodable::FieldMarker; pub use copy_data_types::U24; pub use non_copy_data_types::{ - Inner, PubKey, Seq0255, Seq064K, Signature, Str0255, Sv2Option, U32AsRef, B016M, B0255, B032, - B064K, U256, + Inner, Mac, PubKey, Seq0255, Seq064K, Signature, Str0255, Sv2Option, B016M, B0255, B032, B064K, + U256, }; use alloc::vec::Vec; @@ -55,43 +53,19 @@ use std::io::{Error as E, Read, Write}; /// - Deserialization: Converting byte slices or streams back into the in-memory representation of /// the data. /// -/// This trait includes functions for both checked and unchecked conversions, providing flexibility -/// in situations where error handling can be safely ignored. pub trait Sv2DataType<'a>: Sized + SizeHint + GetSize + TryInto { /// Creates an instance of the type from a mutable byte slice, checking for size constraints. /// /// This function verifies that the provided byte slice has the correct size according to the /// type's size hint. - fn from_bytes_(data: &'a mut [u8]) -> Result { - Self::size_hint(data, 0)?; - Ok(Self::from_bytes_unchecked(data)) - } - - /// Constructs an instance from a mutable byte slice without verifying size constraints. - fn from_bytes_unchecked(data: &'a mut [u8]) -> Self; - - /// Constructs an instance from a vector, checking for the correct size. - fn from_vec_(data: Vec) -> Result; - - /// Constructs an instance from a vector without validating its size. - fn from_vec_unchecked(data: Vec) -> Self; + fn from_bytes_(data: &'a mut [u8]) -> Result; // Constructs an instance from a reader source, checking for size constraints. #[cfg(not(feature = "no_std"))] fn from_reader_(reader: &mut impl Read) -> Result; /// Serializes the instance to a mutable slice, checking the destination size. - fn to_slice(&'a self, dst: &mut [u8]) -> Result { - if dst.len() >= self.get_size() { - self.to_slice_unchecked(dst); - Ok(self.get_size()) - } else { - Err(Error::WriteError(self.get_size(), dst.len())) - } - } - - /// Serializes the instance to a mutable slice without checking the destination size. - fn to_slice_unchecked(&'a self, dst: &mut [u8]); + fn to_slice(&'a self, dst: &mut [u8]) -> Result; // Serializes the instance to a writer destination, checking for I/O errors. #[cfg(not(feature = "no_std"))] diff --git a/sv2/binary-sv2/src/datatypes/non_copy_data_types/inner.rs b/sv2/binary-sv2/src/datatypes/non_copy_data_types/inner.rs index a492b52391..fa588dfc83 100644 --- a/sv2/binary-sv2/src/datatypes/non_copy_data_types/inner.rs +++ b/sv2/binary-sv2/src/datatypes/non_copy_data_types/inner.rs @@ -21,8 +21,9 @@ // // # Usage // `Inner` offers several methods for data manipulation, including: -// - `to_vec()`: Returns a `Vec`, cloning the slice or owned data. -// - `inner_as_ref()` and `inner_as_mut()`: Provide immutable or mutable access to the data. +// - `as_bytes()` and `as_mut_bytes()`: Provide immutable or mutable access to the data. +// - `to_owned_bytes()` and `into_bytes()`: Return owned payload bytes. +// - `len()` and `is_empty()`: Inspect payload size directly. // - `expected_length(data: &[u8])`: Computes the expected length, validating it against // constraints. // - `get_header()`: Returns the data's header based on `HEADERSIZE`. @@ -73,55 +74,6 @@ pub enum Inner< Owned(Vec), } -impl Inner<'_, true, SIZE, 0, 0> { - // Converts the inner data to a vector, either by cloning the referenced slice or - // returning a clone of the owned vector. - pub fn to_vec(&self) -> Vec { - match self { - Inner::Ref(ref_) => ref_.to_vec(), - Inner::Owned(v) => v.clone(), - } - } - // Returns an immutable reference to the inner data, whether it's a reference or - // an owned vector. - pub fn inner_as_ref(&self) -> &[u8] { - match self { - Inner::Ref(ref_) => ref_, - Inner::Owned(v) => v, - } - } - // Provides a mutable reference to the inner data, allowing modification if the - // data is being referenced. - pub fn inner_as_mut(&mut self) -> &mut [u8] { - match self { - Inner::Ref(ref_) => ref_, - Inner::Owned(v) => v, - } - } -} - -impl - Inner<'_, false, SIZE, HEADERSIZE, MAXSIZE> -{ - // Similar to the fixed-size variant, this method converts the inner data into a vector. - // The data is either cloned from the referenced slice or returned as a clone of the - // owned vector. - pub fn to_vec(&self) -> Vec { - match self { - Inner::Ref(ref_) => ref_[..].to_vec(), - Inner::Owned(v) => v[..].to_vec(), - } - } - // Returns an immutable reference to the inner data for variable-size types, either - // referencing a slice or an owned vector. - pub fn inner_as_ref(&self) -> &[u8] { - match self { - Inner::Ref(ref_) => &ref_[..], - Inner::Owned(v) => &v[..], - } - } -} - impl PartialEq for Inner<'_, ISFIXED, SIZE, HEADERSIZE, MAXSIZE> { @@ -204,7 +156,7 @@ impl unreachable!(), }; - if expected_length <= (MAXSIZE + HEADERSIZE) { + if expected_length <= MAXSIZE { Ok(expected_length) } else { Err(Error::ReadError(expected_length, MAXSIZE)) @@ -218,10 +170,15 @@ impl data.len(), (Inner::Owned(data), false) => data.len(), - (_, true) => 1, + (_, true) => SIZE, } } + /// Returns true when the payload has no bytes. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + // Retrieves the header as a byte vector. If `HEADERSIZE` is zero, an empty vector is // returned. Otherwise, the header is constructed from the length of the data. fn get_header(&self) -> Vec { @@ -333,23 +290,19 @@ impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const where Self: TryInto, { - fn from_bytes_unchecked(data: &'a mut [u8]) -> Self { + fn from_bytes_(data: &'a mut [u8]) -> Result { + let size = Self::size_hint(data, 0)?; + if size > data.len() { + return Err(Error::ReadError(data.len(), size)); + } + let (head, _) = data.split_at_mut(size); if ISFIXED { - Self::Ref(data) + Ok(Self::Ref(head)) } else { - Self::Ref(&mut data[HEADERSIZE..]) + Ok(Self::Ref(&mut head[HEADERSIZE..])) } } - fn from_vec_(data: Vec) -> Result { - Self::size_hint(&data, 0)?; - Ok(Self::Owned(data)) - } - - fn from_vec_unchecked(data: Vec) -> Self { - Self::Owned(data) - } - #[cfg(not(feature = "no_std"))] fn from_reader_(mut reader: &mut impl Read) -> Result { let size = Self::expected_length_for_reader(&mut reader)?; @@ -357,11 +310,14 @@ where let mut dst = vec![0; size]; reader.read_exact(&mut dst)?; - Ok(Self::from_vec_unchecked(dst)) + Ok(Self::Owned(dst)) } - fn to_slice_unchecked(&'a self, dst: &mut [u8]) { + fn to_slice(&'a self, dst: &mut [u8]) -> Result { let size = self.get_size(); + if dst.len() < size { + return Err(Error::WriteError(size, dst.len())); + } let header = self.get_header(); dst[0..HEADERSIZE].copy_from_slice(&header[..HEADERSIZE]); match self { @@ -374,10 +330,13 @@ where dst[HEADERSIZE..].copy_from_slice(data); } } + Ok(size) } #[cfg(not(feature = "no_std"))] fn to_writer_(&self, writer: &mut impl Write) -> Result<(), E> { + let header = self.get_header(); + writer.write_all(&header[..HEADERSIZE])?; match self { Inner::Ref(data) => { writer.write_all(data)?; @@ -393,6 +352,43 @@ where impl Inner<'_, ISFIXED, SIZE, HEADERSIZE, MAXSIZE> { + /// Returns the payload bytes without any SV2 length header. + pub fn as_bytes(&self) -> &[u8] { + match self { + Inner::Ref(data) => data, + Inner::Owned(data) => data, + } + } + + /// Returns the payload bytes mutably without any SV2 length header. + pub fn as_mut_bytes(&mut self) -> &mut [u8] { + match self { + Inner::Ref(data) => data, + Inner::Owned(data) => data, + } + } + + /// Clones the payload bytes into an owned vector. + pub fn to_owned_bytes(&self) -> Vec { + self.as_bytes().to_vec() + } + + /// Consumes the value and returns owned payload bytes. + pub fn into_bytes(self) -> Vec { + match self { + Inner::Ref(data) => data.to_vec(), + Inner::Owned(data) => data, + } + } + + /// Copies the payload bytes into an array of the requested size. + pub fn try_as_array(&self) -> Result<[u8; N], Error> { + self.as_bytes() + .try_into() + .map_err(|_| Error::ReadError(self.as_bytes().len(), N)) + } + + /// Converts the value into an owned static value. pub fn into_static(self) -> Inner<'static, ISFIXED, SIZE, HEADERSIZE, MAXSIZE> { match self { Inner::Ref(data) => { @@ -405,6 +401,32 @@ impl Inner<'_, true, SIZE, 0, 0> { + /// Returns the payload bytes as an array reference. + pub fn as_array(&self) -> &[u8; SIZE] { + self.as_bytes() + .try_into() + .expect("fixed-size SV2 byte wrapper must always match SIZE") + } + + /// Copies the payload bytes into an array. + pub fn to_array(&self) -> [u8; SIZE] { + *self.as_array() + } + + /// Consumes the value and returns the payload bytes as an array. + pub fn into_array(self) -> [u8; SIZE] { + match self { + Inner::Ref(data) => data + .try_into() + .expect("fixed-size SV2 byte wrapper must always match SIZE"), + Inner::Owned(data) => data + .try_into() + .expect("fixed-size SV2 byte wrapper must always match SIZE"), + } + } +} + impl Clone for Inner<'_, ISFIXED, SIZE, HEADERSIZE, MAXSIZE> { @@ -424,9 +446,32 @@ impl for Inner<'_, ISFIXED, SIZE, HEADERSIZE, MAXSIZE> { fn as_ref(&self) -> &[u8] { - match self { - Inner::Ref(r) => &r[..], - Inner::Owned(r) => &r[..], - } + self.as_bytes() + } +} + +impl + TryFrom<&[u8]> for Inner<'_, ISFIXED, SIZE, HEADERSIZE, MAXSIZE> +{ + type Error = Error; + + fn try_from(value: &[u8]) -> Result { + value.to_vec().try_into() + } +} + +impl From<[u8; SIZE]> for Inner<'_, true, SIZE, 0, 0> { + fn from(value: [u8; SIZE]) -> Self { + Inner::Owned(value.into()) + } +} + +impl + TryFrom<[u8; N]> for Inner<'_, false, SIZE, HEADERSIZE, MAXSIZE> +{ + type Error = Error; + + fn try_from(value: [u8; N]) -> Result { + value.to_vec().try_into() } } diff --git a/sv2/binary-sv2/src/datatypes/non_copy_data_types/mod.rs b/sv2/binary-sv2/src/datatypes/non_copy_data_types/mod.rs index 1a77b0a08c..9fcf8987bb 100644 --- a/sv2/binary-sv2/src/datatypes/non_copy_data_types/mod.rs +++ b/sv2/binary-sv2/src/datatypes/non_copy_data_types/mod.rs @@ -3,26 +3,27 @@ // // The core component is the [`Inner`] type, a wrapper for managing both fixed and variable-length // data slices or owned values. It offers aliases for commonly used data types like 32-byte hashes -// (`U256`), public keys (`PubKey`), cryptographic signatures (`Signature`), and dynamically-sized -// arrays (`B0255`, `B064K`). +// (`U256`), cryptographic signatures (`Signature`), and dynamically-sized arrays (`B0255`, +// `B064K`). // # Features -// - **Fixed-size Aliases**: Types like [`U32AsRef`], [`U256`], [`PubKey`], and [`Signature`] -// represent specific byte sizes, often used in cryptographic contexts or protocol identifiers. +// - **Fixed-size Aliases**: Types like [`U256`], [`Mac`], [`PubKey`], and [`Signature`] represent +// specific byte sizes, often used in cryptographic contexts or protocol identifiers. // - **Variable-size Aliases**: Types like [`B032`], [`B0255`], [`Str0255`], [`B064K`], and // [`B016M`] handle data with bounded sizes, providing flexibility for dynamic data. // - **Traits and Conversions**: Implements traits like `From`, `TryFrom`, and `Clone` for // seamless transformations between owned and reference-based values. // # Type Aliases -// - **[`U32AsRef`]**: 4-byte representation for small identifiers or integer values. // - **[`U256`]**: 32-byte cryptographic hash (e.g., SHA-256 or protocol IDs). -// - **[`PubKey`]**: 32-byte public key (e.g., Ed25519). +// - **[`Mac`]**: 16-byte message authentication code. +// - **[`PubKey`]**: 32-byte Secp256k1 public key x-coordinate. // - **[`Signature`]**: 64-byte cryptographic signature. // - **[`B032`], [`B0255`], [`Str0255`]**: Variable-size representations for optional fields or // protocol data. use alloc::{borrow::ToOwned, fmt, string::String}; +use core::fmt::Write as _; mod inner; mod seq_inner; @@ -30,14 +31,12 @@ mod seq_inner; pub use inner::Inner; pub use seq_inner::{Seq0255, Seq064K, Sv2Option}; -/// Type alias for a 4-byte slice or owned data represented using the `Inner` -/// type with fixed-size configuration. -pub type U32AsRef<'a> = Inner<'a, true, 4, 0, 0>; /// Type alias for a 32-byte slice or owned data (commonly used for cryptographic /// hashes or IDs) represented using the `Inner` type with fixed-size configuration. pub type U256<'a> = Inner<'a, true, 32, 0, 0>; -/// Type alias for a 32-byte public key represented using the `Inner` type -/// with fixed-size configuration. +/// Type alias for a 16-byte message authentication code. +pub type Mac<'a> = Inner<'a, true, 16, 0, 0>; +/// Type alias for a 32-byte Secp256k1 public key x-coordinate. pub type PubKey<'a> = Inner<'a, true, 32, 0, 0>; /// Type alias for a 64-byte cryptographic signature represented using the /// `Inner` type with fixed-size configuration. @@ -58,15 +57,12 @@ pub type B064K<'a> = Inner<'a, false, 1, 2, { u16::MAX as usize }>; /// represented using the `Inner` type with a 3-byte header. pub type B016M<'a> = Inner<'a, false, 1, 3, { 2_usize.pow(24) - 1 }>; -impl fmt::Display for U32AsRef<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let inner = self.inner_as_ref(); - write!( - f, - "U32AsRef({})", - u32::from_le_bytes([inner[0], inner[1], inner[2], inner[3]]) - ) +fn bytes_to_hex<'a>(bytes: impl IntoIterator) -> String { + let mut hex = String::new(); + for byte in bytes { + write!(&mut hex, "{byte:02x}").expect("writing to String cannot fail"); } + hex } impl fmt::Display for Sv2Option<'_, u32> { @@ -82,11 +78,7 @@ impl fmt::Display for Sv2Option<'_, u32> { impl B0255<'_> { pub fn as_hex(&self) -> String { - let inner = self - .inner_as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect::(); + let inner = bytes_to_hex(self.as_bytes()); format!("B0255({inner})") } } @@ -94,71 +86,50 @@ impl B0255<'_> { impl Str0255<'_> { /// Returns the value as a UTF-8 string if possible, otherwise as a hex string prefixed with 0x. pub fn as_utf8_or_hex(&self) -> String { - match core::str::from_utf8(self.inner_as_ref()) { + match core::str::from_utf8(self.as_bytes()) { Ok(s) => alloc::string::String::from(s), - Err(_) => format!( - "0x{}", - self.inner_as_ref() - .iter() - .map(|b| format!("{b:02x}")) - .collect::() - ), + Err(_) => format!("0x{}", bytes_to_hex(self.as_bytes())), } } } impl fmt::Display for B064K<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let inner = self - .inner_as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect::(); + let inner = bytes_to_hex(self.as_bytes()); write!(f, "B064K({inner})") } } impl fmt::Display for U256<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let inner = self - .inner_as_ref() - .iter() - .rev() - .map(|byte| format!("{byte:02x}")) - .collect::(); + let inner = bytes_to_hex(self.as_bytes().iter().rev()); write!(f, "U256({inner})") } } impl fmt::Display for Seq0255<'_, U256<'_>> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let len = self.0.len(); - let as_hex = |item: &U256<'_>| { - item.inner_as_ref() - .iter() - .rev() - .map(|byte| format!("{byte:02x}")) - .collect::() - }; + let len = self.len(); + let as_hex = |item: &U256<'_>| bytes_to_hex(item.as_bytes().iter().rev()); write!(f, "Seq0255 write!(f, "[]"), - 1 => write!(f, "{}]", as_hex(&self.0[0])), - 2 => write!(f, "{}, {}]", as_hex(&self.0[0]), as_hex(&self.0[1])), + 1 => write!(f, "[{}]", as_hex(&self[0])), + 2 => write!(f, "[{}, {}]", as_hex(&self[0]), as_hex(&self[1])), 3 => write!( f, "[{}, {}, {}]", - as_hex(&self.0[0]), - as_hex(&self.0[1]), - as_hex(&self.0[2]) + as_hex(&self[0]), + as_hex(&self[1]), + as_hex(&self[2]) ), _ => write!( f, "[{}, {}, ... , {}, {}]", - as_hex(&self.0[0]), - as_hex(&self.0[1]), - as_hex(&self.0[len - 2]), - as_hex(&self.0[len - 1]) + as_hex(&self[0]), + as_hex(&self[1]), + as_hex(&self[len - 2]), + as_hex(&self[len - 1]) ), } } @@ -166,14 +137,10 @@ impl fmt::Display for Seq0255<'_, U256<'_>> { impl fmt::Display for Seq064K<'_, B016M<'_>> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let len = self.0.len(); + let len = self.len(); let as_hex = |item: &B016M<'_>| { - let hex: String = item - .inner_as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect(); + let hex = bytes_to_hex(item.as_bytes()); if hex.len() > 500 { format!("{}…", &hex[..500], hex.len() - 500) @@ -185,22 +152,22 @@ impl fmt::Display for Seq064K<'_, B016M<'_>> { write!(f, "Seq064K write!(f, "[]"), - 1 => write!(f, "[{}]", as_hex(&self.0[0])), - 2 => write!(f, "[{}, {}]", as_hex(&self.0[0]), as_hex(&self.0[1])), + 1 => write!(f, "[{}]", as_hex(&self[0])), + 2 => write!(f, "[{}, {}]", as_hex(&self[0]), as_hex(&self[1])), 3 => write!( f, "[{}, {}, {}]", - as_hex(&self.0[0]), - as_hex(&self.0[1]), - as_hex(&self.0[2]) + as_hex(&self[0]), + as_hex(&self[1]), + as_hex(&self[2]) ), _ => write!( f, "[{}, {}, … , {}, {}]", - as_hex(&self.0[0]), - as_hex(&self.0[1]), - as_hex(&self.0[len - 2]), - as_hex(&self.0[len - 1]) + as_hex(&self[0]), + as_hex(&self[1]), + as_hex(&self[len - 2]), + as_hex(&self[len - 1]) ), } } @@ -208,32 +175,27 @@ impl fmt::Display for Seq064K<'_, B016M<'_>> { impl fmt::Display for Seq064K<'_, U256<'_>> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let len = self.0.len(); - let as_hex = |item: &U256<'_>| { - item.inner_as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect::() - }; + let len = self.len(); + let as_hex = |item: &U256<'_>| bytes_to_hex(item.as_bytes().iter().rev()); write!(f, "Seq064K write!(f, "[]"), - 1 => write!(f, "[{}]", as_hex(&self.0[0])), - 2 => write!(f, "[{}, {}]", as_hex(&self.0[0]), as_hex(&self.0[1])), + 1 => write!(f, "[{}]", as_hex(&self[0])), + 2 => write!(f, "[{}, {}]", as_hex(&self[0]), as_hex(&self[1])), 3 => write!( f, "[{}, {}, {}]", - as_hex(&self.0[0]), - as_hex(&self.0[1]), - as_hex(&self.0[2]) + as_hex(&self[0]), + as_hex(&self[1]), + as_hex(&self[2]) ), _ => write!( f, "[{}, {}, ... , {}, {}]", - as_hex(&self.0[0]), - as_hex(&self.0[1]), - as_hex(&self.0[len - 2]), - as_hex(&self.0[len - 1]) + as_hex(&self[0]), + as_hex(&self[1]), + as_hex(&self[len - 2]), + as_hex(&self[len - 1]) ), } } @@ -241,40 +203,40 @@ impl fmt::Display for Seq064K<'_, U256<'_>> { impl fmt::Display for Seq064K<'_, u16> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let len = self.0.len(); + let len = self.len(); write!(f, "Seq064K write!(f, "[]"), - 1 => write!(f, "[{}]", self.0[0]), - 2 => write!(f, "[{}, {}]", self.0[0], self.0[1]), - 3 => write!(f, "[{}, {}, {}]", self.0[0], self.0[1], self.0[2]), + 1 => write!(f, "[{}]", self[0]), + 2 => write!(f, "[{}, {}]", self[0], self[1]), + 3 => write!(f, "[{}, {}, {}]", self[0], self[1], self[2]), _ => write!( f, "[{}, {}, ... , {}, {}]", - self.0[0], - self.0[1], - self.0[len - 2], - self.0[len - 1] + self[0], + self[1], + self[len - 2], + self[len - 1] ), } } } impl fmt::Display for Seq064K<'_, u32> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let len = self.0.len(); + let len = self.len(); write!(f, "Seq064K write!(f, "[]"), - 1 => write!(f, "[{}]", self.0[0]), - 2 => write!(f, "[{}, {}]", self.0[0], self.0[1]), - 3 => write!(f, "[{}, {}, {}]", self.0[0], self.0[1], self.0[2]), + 1 => write!(f, "[{}]", self[0]), + 2 => write!(f, "[{}, {}]", self[0], self[1]), + 3 => write!(f, "[{}, {}, {}]", self[0], self[1], self[2]), _ => write!( f, "[{}, {}, ... , {}, {}]", - self.0[0], - self.0[1], - self.0[len - 2], - self.0[len - 1] + self[0], + self[1], + self[len - 2], + self[len - 1] ), } } @@ -282,21 +244,11 @@ impl fmt::Display for Seq064K<'_, u32> { impl fmt::Display for B032<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let item = self - .inner_as_ref() - .iter() - .map(|byte| format!("{byte:02x}")) - .collect::(); + let item = bytes_to_hex(self.as_bytes()); write!(f, "B032({item})") } } -impl From<[u8; 32]> for U256<'_> { - fn from(v: [u8; 32]) -> Self { - Inner::Owned(v.into()) - } -} - use core::convert::{TryFrom, TryInto}; // Attempts to convert a `String` into a `Str0255<'a>`. @@ -308,27 +260,11 @@ impl TryFrom for Str0255<'_> { } } -/// Represents a reference to a 32-bit unsigned integer (`u32`), -/// providing methods for convenient conversions. -impl U32AsRef<'_> { - /// Returns the `u32` value represented by this reference. - pub fn as_u32(&self) -> u32 { - let inner = self.inner_as_ref(); - u32::from_le_bytes([inner[0], inner[1], inner[2], inner[3]]) - } -} - -impl From for U32AsRef<'_> { - fn from(v: u32) -> Self { - let bytes = v.to_le_bytes(); - let inner = vec![bytes[0], bytes[1], bytes[2], bytes[3]]; - U32AsRef::Owned(inner) - } -} +// Attempts to convert a string slice into an owned `Str0255`. +impl TryFrom<&str> for Str0255<'_> { + type Error = crate::Error; -impl<'a> From<&'a U32AsRef<'a>> for u32 { - fn from(v: &'a U32AsRef<'a>) -> Self { - let b = v.inner_as_ref(); - u32::from_le_bytes([b[0], b[1], b[2], b[3]]) + fn try_from(value: &str) -> Result { + value.as_bytes().try_into() } } diff --git a/sv2/binary-sv2/src/datatypes/non_copy_data_types/seq_inner.rs b/sv2/binary-sv2/src/datatypes/non_copy_data_types/seq_inner.rs index 06c94c4560..d6b4f142c0 100644 --- a/sv2/binary-sv2/src/datatypes/non_copy_data_types/seq_inner.rs +++ b/sv2/binary-sv2/src/datatypes/non_copy_data_types/seq_inner.rs @@ -10,8 +10,7 @@ // ### `Seq0255` // - Represents a sequence of up to 255 elements. // - Includes utility methods such as: -// - `to_vec()`: Converts each element into its byte vector representation. -// - `inner_as_ref()`: Provides references to the inner data for each element. +// - `iter_bytes()`: Provides byte references for each element without allocating. // - `new()`: Creates a `Seq0255` instance, enforcing the maximum length constraint. // - Implements the `Decodable` trait for seamless deserialization, and `GetSize` to calculate the // encoded size, ensuring compatibility with various serialization formats. @@ -19,7 +18,7 @@ // ### `Seq064K` // - Represents a sequence of up to 65535 elements. // - Similar to `Seq0255`, it provides: -// - `to_vec()` and `inner_as_ref()` methods to convert or reference each element. +// - `iter_bytes()` to reference each element's bytes without allocating. // - `new()` enforces the maximum size limit, preventing excess memory usage. // - Like `Seq0255`, `Seq064K` is `Decodable` and implements `GetSize`, making it versatile for // serialization scenarios. @@ -50,59 +49,23 @@ use crate::{ datatypes::{Sv2DataType, *}, Error, }; -use core::marker::PhantomData; +use core::{marker::PhantomData, ops::Index, slice}; -// TODO add test for that -impl<'a, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> - Seq0255<'a, super::inner::Inner<'a, false, SIZE, HEADERSIZE, MAXSIZE>> +impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> + Seq0255<'a, Inner<'a, ISFIXED, SIZE, HEADERSIZE, MAXSIZE>> { - /// Converts the inner types to owned vector, and collects. - pub fn to_vec(&self) -> Vec> { - self.0.iter().map(|x| x.to_vec()).collect() - } - /// Converts the inner types to shared reference, and collects. - pub fn inner_as_ref(&self) -> Vec<&[u8]> { - self.0.iter().map(|x| x.inner_as_ref()).collect() + /// Iterates over element payload bytes without allocating. + pub fn iter_bytes(&self) -> impl Iterator { + self.0.iter().map(|x| x.as_bytes()) } } -// TODO add test for that -impl<'a, const SIZE: usize> Seq0255<'a, super::inner::Inner<'a, true, SIZE, 0, 0>> { - /// Converts the inner types to owned vector, and collects. - pub fn to_vec(&self) -> Vec> { - self.0.iter().map(|x| x.to_vec()).collect() - } - - /// Converts the inner types to shared reference, and collects. - pub fn inner_as_ref(&self) -> Vec<&[u8]> { - self.0.iter().map(|x| x.inner_as_ref()).collect() - } -} -// TODO add test for that -impl<'a, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> - Seq064K<'a, super::inner::Inner<'a, false, SIZE, HEADERSIZE, MAXSIZE>> +impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> + Seq064K<'a, Inner<'a, ISFIXED, SIZE, HEADERSIZE, MAXSIZE>> { - /// Converts the inner types to owned vector, and collects. - pub fn to_vec(&self) -> Vec> { - self.0.iter().map(|x| x.to_vec()).collect() - } - - /// Converts the inner types to shared reference, and collects. - pub fn inner_as_ref(&self) -> Vec<&[u8]> { - self.0.iter().map(|x| x.inner_as_ref()).collect() - } -} - -// TODO add test for that -impl<'a, const SIZE: usize> Seq064K<'a, super::inner::Inner<'a, true, SIZE, 0, 0>> { - /// Converts the inner types to owned vector, and collects. - pub fn to_vec(&self) -> Vec> { - self.0.iter().map(|x| x.to_vec()).collect() - } - - /// Converts the inner types to shared reference, and collects. - pub fn inner_as_ref(&self) -> Vec<&[u8]> { - self.0.iter().map(|x| x.inner_as_ref()).collect() + /// Iterates over element payload bytes without allocating. + pub fn iter_bytes(&self) -> impl Iterator { + self.0.iter().map(|x| x.as_bytes()) } } @@ -113,7 +76,14 @@ use std::io::Read; /// This structure uses a generic type `T` and a lifetime parameter `'a`. #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Seq0255<'a, T>(pub Vec, PhantomData<&'a T>); +pub struct Seq0255<'a, T>(Vec, PhantomData<&'a T>); + +impl<'a, T> Index for Seq0255<'a, T> { + type Output = T; + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} impl<'a, T: 'a> Seq0255<'a, T> { const HEADERSIZE: usize = 1; @@ -140,6 +110,26 @@ impl<'a, T: 'a> Seq0255<'a, T> { pub fn into_inner(self) -> Vec { self.0 } + + /// Returns the sequence as a slice. + pub fn as_slice(&self) -> &[T] { + &self.0 + } + + /// Iterates over the sequence by reference. + pub fn iter(&self) -> slice::Iter<'_, T> { + self.0.iter() + } + + /// Length of Seq0255 which is a list of bytes up-to 255 len + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns true when the sequence contains no elements. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } } impl GetSize for Seq0255<'_, T> { @@ -156,7 +146,14 @@ impl GetSize for Seq0255<'_, T> { /// [`Seq064K`] represents a sequence with a maximum length of 65535 elements. /// This structure uses a generic type `T` and a lifetime parameter `'a`. #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Seq064K<'a, T>(pub(crate) Vec, PhantomData<&'a T>); +pub struct Seq064K<'a, T>(Vec, PhantomData<&'a T>); + +impl<'a, T> Index for Seq064K<'a, T> { + type Output = T; + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} impl<'a, T: 'a> Seq064K<'a, T> { const HEADERSIZE: usize = 2; @@ -183,6 +180,26 @@ impl<'a, T: 'a> Seq064K<'a, T> { pub fn into_inner(self) -> Vec { self.0 } + + /// Returns the sequence as a slice. + pub fn as_slice(&self) -> &[T] { + &self.0 + } + + /// Iterates over the sequence by reference. + pub fn iter(&self) -> slice::Iter<'_, T> { + self.0.iter() + } + + /// Length of Seq0255 which is a list of bytes up-to 64k len + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns true when the sequence contains no elements. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } } impl GetSize for Seq064K<'_, T> { @@ -228,8 +245,10 @@ macro_rules! impl_codec_for_sequence { T::from_decoded_fields(vec![DecodableField::Primitive(p)]); inner.push(element?) } - // A struct always recursivly call decode until it reach a primitive - DecodableField::Struct(_) => unreachable!(), + DecodableField::Struct(fields) => { + let element = T::from_decoded_fields(fields); + inner.push(element?) + } } } i += 1; @@ -250,7 +269,7 @@ macro_rules! impl_codec_for_sequence { } let (head, t) = tail.split_at_mut(element_size); tail = t; - inner.push(T::from_bytes_unchecked(head)); + inner.push(T::from_bytes_(head)?); } Ok(Self(inner, PhantomData)) } @@ -288,10 +307,10 @@ macro_rules! impl_into_encodable_field_for_seq { let inner_len = v.0.len() as u16; let mut as_encodable: Vec = Vec::with_capacity(inner_len as usize + 2); - as_encodable.push(EncodableField::Primitive(EncodablePrimitive::OwnedU8( + as_encodable.push(EncodableField::Primitive(EncodablePrimitive::U8( inner_len.to_le_bytes()[0], ))); - as_encodable.push(EncodableField::Primitive(EncodablePrimitive::OwnedU8( + as_encodable.push(EncodableField::Primitive(EncodablePrimitive::U8( inner_len.to_le_bytes()[1], ))); for element in v.0 { @@ -306,9 +325,7 @@ macro_rules! impl_into_encodable_field_for_seq { let inner_len = v.0.len() as u8; let mut as_encodable: Vec = Vec::with_capacity((inner_len as usize) + 1); - as_encodable.push(EncodableField::Primitive(EncodablePrimitive::OwnedU8( - inner_len, - ))); + as_encodable.push(EncodableField::Primitive(EncodablePrimitive::U8(inner_len))); for element in v.0 { as_encodable.push(element.into()); } @@ -321,9 +338,7 @@ macro_rules! impl_into_encodable_field_for_seq { let inner_len = v.0.len() as u8; let mut as_encodable: Vec = Vec::with_capacity((inner_len as usize) + 1); - as_encodable.push(EncodableField::Primitive(EncodablePrimitive::OwnedU8( - inner_len, - ))); + as_encodable.push(EncodableField::Primitive(EncodablePrimitive::U8(inner_len))); for element in v.0 { as_encodable.push(element.into()); } @@ -340,20 +355,23 @@ impl_into_encodable_field_for_seq!(U24); impl_into_encodable_field_for_seq!(u32); impl_into_encodable_field_for_seq!(u64); impl_into_encodable_field_for_seq!(U256<'a>); +impl_into_encodable_field_for_seq!(Mac<'a>); impl_into_encodable_field_for_seq!(Signature<'a>); impl_into_encodable_field_for_seq!(B0255<'a>); impl_into_encodable_field_for_seq!(B064K<'a>); impl_into_encodable_field_for_seq!(B016M<'a>); -impl From> for Seq0255<'_, T> { - fn from(v: Vec) -> Self { - Seq0255(v, PhantomData) +impl TryFrom> for Seq0255<'_, T> { + type Error = Error; + fn try_from(value: Vec) -> Result { + Seq0255::new(value) } } -impl From> for Seq064K<'_, T> { - fn from(v: Vec) -> Self { - Seq064K(v, PhantomData) +impl TryFrom> for Seq064K<'_, T> { + type Error = Error; + fn try_from(value: Vec) -> Result { + Seq064K::new(value) } } @@ -423,26 +441,29 @@ impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const /// The lifetime 'a is defined. #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Sv2Option<'a, T>(pub Vec, PhantomData<&'a T>); +pub struct Sv2Option<'a, T>(Vec, PhantomData<&'a T>); // TODO add test for that impl<'a, const SIZE: usize> Sv2Option<'a, super::inner::Inner<'a, true, SIZE, 0, 0>> { /// Gets the owned first element of the sequence, if present pub fn to_option(&self) -> Option> { - let v: Vec> = self.0.iter().map(|x| x.to_vec()).collect(); - match v.len() { + match self.0.len() { 0 => None, - 1 => Some(v[0].clone()), + 1 => Some(self.0[0].to_owned_bytes()), // is impossible to deserialize Sv2Options with len bigger than 1 _ => unreachable!(), } } - /// Gets the reference to first element of the sequence, if present - pub fn inner_as_ref(&self) -> Option<&[u8]> { - let v: Vec<&[u8]> = self.0.iter().map(|x| x.inner_as_ref()).collect(); - match v.len() { +} + +impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> + Sv2Option<'a, Inner<'a, ISFIXED, SIZE, HEADERSIZE, MAXSIZE>> +{ + /// Gets the reference to the first element's payload bytes, if present. + pub fn as_option_bytes(&self) -> Option<&[u8]> { + match self.0.len() { 0 => None, - 1 => Some(v[0]), + 1 => Some(self.0[0].as_bytes()), // is impossible to deserialize Sv2Options with len bigger than 1 _ => unreachable!(), } diff --git a/sv2/binary-sv2/src/lib.rs b/sv2/binary-sv2/src/lib.rs index adac90f726..1a84a67ae6 100644 --- a/sv2/binary-sv2/src/lib.rs +++ b/sv2/binary-sv2/src/lib.rs @@ -20,13 +20,14 @@ //! u64 <-> U64 //! U256 <-> U256 //! Str0255 <-> STRO_255 +//! Mac <-> MAC +//! PubKey <-> PUBKEY //! Signature<-> SIGNATURE //! B032 <-> B0_32 //! B0255 <-> B0_255 //! B064K <-> B0_64K //! B016M <-> B0_16M //! [u8] <-> BYTES -//! Pubkey <-> PUBKEY //! Seq0255 <-> SEQ0_255[T] //! Seq064K <-> SEQ0_64K[T] //! ``` @@ -71,8 +72,8 @@ pub use encodable::Encodable as Serialize; mod codec; mod datatypes; pub use datatypes::{ - PubKey, Seq0255, Seq064K, Signature, Str0255, Sv2DataType, Sv2Option, U32AsRef, B016M, B0255, - B032, B064K, U24, U256, + Mac, PubKey, Seq0255, Seq064K, Signature, Str0255, Sv2DataType, Sv2Option, B016M, B0255, B032, + B064K, U24, U256, }; pub use crate::codec::{ @@ -137,6 +138,11 @@ pub fn from_bytes<'a, T: Decodable<'a>>(data: &'a mut [u8]) -> Result T::from_bytes(data) } +/// Decodes an SV2-encoded byte vector into owned/static values. +pub fn from_bytes_owned>(data: Vec) -> Result { + crate::codec::decodable::from_bytes_owned(data) +} + /// Provides an interface and implementation details for decoding complex data structures /// from raw bytes or I/O streams. Handles deserialization of nested and primitive data /// structures through traits, enums, and helper functions for managing the decoding process. @@ -164,7 +170,6 @@ pub fn from_bytes<'a, T: Decodable<'a>>(data: &'a mut [u8]) -> Result /// environments. pub mod decodable { pub use crate::codec::decodable::{Decodable, DecodableField, FieldMarker}; - //pub use crate::codec::decodable::PrimitiveMarker; } /// Provides an encoding framework for serializing various data types into bytes. @@ -238,40 +243,13 @@ pub enum Error { /// Indicates an attempt to read beyond a valid range. OutOfBound, - /// Raised when a non-binary value is interpreted as a boolean. - NotABool(u8), - /// Occurs when an unexpected size mismatch arises during a write operation, specifying /// expected and actual sizes. WriteError(usize, usize), - /// Signifies an overflow condition where a `u32` exceeds the maximum allowable `u24` value. - U24TooBig(u32), - - /// Reports a size mismatch for a signature, such as when it does not match the expected size. - InvalidSignatureSize(usize), - - /// Raised when a `u256` value is invalid, typically due to size discrepancies. - InvalidU256(usize), - /// Indicates an invalid `u24` representation. InvalidU24(u32), - /// Error indicating that a byte array exceeds the maximum allowed size for `B0255`. - InvalidB0255Size(usize), - - /// Error indicating that a byte array exceeds the maximum allowed size for `B064K`. - InvalidB064KSize(usize), - - /// Error indicating that a byte array exceeds the maximum allowed size for `B016M`. - InvalidB016MSize(usize), - - /// Raised when a sequence size exceeds `0255`. - InvalidSeq0255Size(usize), - - /// Error when trying to encode a non-primitive data type. - NonPrimitiveTypeCannotBeEncoded, - /// Generic conversion error related to primitive types. PrimitiveConversionError, @@ -310,9 +288,6 @@ pub enum Error { /// Error for protocol-specific invalid values. ValueIsNotAValidProtocol(u8), - /// Raised when an unsupported or unknown message type is encountered. - UnknownMessageType(u8), - /// Indicates a protocol constraint violation where `Sv2Option` unexpectedly contains multiple /// elements. Sv2OptionHaveMoreThenOneElement(u8), @@ -342,22 +317,8 @@ impl From> for EncodableField<'_> { } #[cfg(feature = "with_buffer_pool")] -impl From for EncodableField<'_> { - fn from(_v: buffer_sv2::Slice) -> Self { - unreachable!() - } -} - -/// Converts a value implementing the `Into` trait into a custom `U256` type. -pub fn u256_from_int>(value: V) -> U256<'static> { - // initialize u256 as a bytes vec of len 24 - let mut u256 = vec![0_u8; 24]; - let val: u64 = value.into(); - for v in &(val.to_le_bytes()) { - // add 8 bytes to u256 - u256.push(*v) +impl From for EncodableField<'static> { + fn from(v: buffer_sv2::Slice) -> Self { + EncodableField::Struct(v.as_ref().iter().copied().map(Into::into).collect()) } - // Always safe cause u256 is 24 + 8 (32) bytes - let u256: U256 = u256.try_into().unwrap(); - u256 } diff --git a/sv2/channels-sv2/src/client/extended.rs b/sv2/channels-sv2/src/client/extended.rs index f19afea9d0..11cc331bc9 100644 --- a/sv2/channels-sv2/src/client/extended.rs +++ b/sv2/channels-sv2/src/client/extended.rs @@ -292,8 +292,8 @@ impl<'a> ExtendedChannel<'a> { // try to strip bip141 bytes from coinbase_tx_prefix and coinbase_tx_suffix, if they are // present let new_extended_mining_job = match try_strip_bip141( - new_extended_mining_job.coinbase_tx_prefix.inner_as_ref(), - new_extended_mining_job.coinbase_tx_suffix.inner_as_ref(), + new_extended_mining_job.coinbase_tx_prefix.as_bytes(), + new_extended_mining_job.coinbase_tx_suffix.as_bytes(), ) .map_err(ExtendedChannelError::FailedToTryToStripBip141)? { @@ -368,14 +368,13 @@ impl<'a> ExtendedChannel<'a> { let deserialized_outputs = Vec::::consensus_decode( &mut set_custom_mining_job .coinbase_tx_outputs - .inner_as_ref() - .to_vec() + .to_owned_bytes() .as_slice(), ) .map_err(|_| ExtendedChannelError::FailedToDeserializeCoinbaseOutputs)?; let mut script_sig = vec![]; - script_sig.extend_from_slice(set_custom_mining_job.coinbase_prefix.inner_as_ref()); + script_sig.extend_from_slice(set_custom_mining_job.coinbase_prefix.as_bytes()); let full_extranonce_size = self.get_full_extranonce_size(); let full_extranonce = vec![0; full_extranonce_size]; script_sig.extend_from_slice(&full_extranonce); @@ -404,7 +403,7 @@ impl<'a> ExtendedChannel<'a> { + 32 // prev OutPoint + 4 // index + 1 // bytes in script - + set_custom_mining_job.coinbase_prefix.inner_as_ref().len(); + + set_custom_mining_job.coinbase_prefix.len(); let coinbase_tx_prefix = serialized_coinbase[0..prefix_index].to_vec(); @@ -551,7 +550,7 @@ impl<'a> ExtendedChannel<'a> { )); }; - let extranonce_size = share.extranonce.inner_as_ref().len(); + let extranonce_size = share.extranonce.len(); if extranonce_size != self.rollable_extranonce_size as usize { return Err(ShareValidationError::BadExtranonceSize( ERROR_CODE_SUBMIT_SHARES_BAD_EXTRANONCE_SIZE, @@ -560,7 +559,7 @@ impl<'a> ExtendedChannel<'a> { let mut full_extranonce = vec![]; full_extranonce.extend_from_slice(job.1.as_slice()); - full_extranonce.extend_from_slice(share.extranonce.inner_as_ref()); + full_extranonce.extend_from_slice(share.extranonce.as_bytes()); // calculate the merkle root from: // - job coinbase_tx_prefix @@ -568,10 +567,10 @@ impl<'a> ExtendedChannel<'a> { // - job coinbase_tx_suffix // - job merkle_path let merkle_root: [u8; 32] = merkle_root_from_path( - job.0.coinbase_tx_prefix.inner_as_ref(), - job.0.coinbase_tx_suffix.inner_as_ref(), + job.0.coinbase_tx_prefix.as_bytes(), + job.0.coinbase_tx_suffix.as_bytes(), full_extranonce.as_ref(), - &job.0.merkle_path.inner_as_ref(), + job.0.merkle_path.as_slice(), ) .ok_or(ShareValidationError::Invalid( ERROR_CODE_SUBMIT_SHARES_INVALID_SHARE, diff --git a/sv2/channels-sv2/src/client/standard.rs b/sv2/channels-sv2/src/client/standard.rs index dff74269fc..606c03dafc 100644 --- a/sv2/channels-sv2/src/client/standard.rs +++ b/sv2/channels-sv2/src/client/standard.rs @@ -238,10 +238,10 @@ impl<'a> StandardChannel<'a> { /// The new job is constructed using the current extranonce prefix. pub fn on_new_group_channel_job(&mut self, new_extended_mining_job: NewExtendedMiningJob<'a>) { let merkle_root = merkle_root_from_path( - new_extended_mining_job.coinbase_tx_prefix.inner_as_ref(), - new_extended_mining_job.coinbase_tx_suffix.inner_as_ref(), + new_extended_mining_job.coinbase_tx_prefix.as_bytes(), + new_extended_mining_job.coinbase_tx_suffix.as_bytes(), self.extranonce_prefix.as_bytes(), - &new_extended_mining_job.merkle_path.inner_as_ref(), + new_extended_mining_job.merkle_path.as_slice(), ) .expect("merkle root must be valid") .try_into() @@ -357,12 +357,7 @@ impl<'a> StandardChannel<'a> { )); }; - let merkle_root: [u8; 32] = job - .0 - .merkle_root - .inner_as_ref() - .try_into() - .expect("merkle root must be 32 bytes"); + let merkle_root = job.0.merkle_root.to_array(); let chain_tip = self .chain_tip diff --git a/sv2/channels-sv2/src/extranonce_manager/allocator.rs b/sv2/channels-sv2/src/extranonce_manager/allocator.rs index db13af052a..e31ebf0718 100644 --- a/sv2/channels-sv2/src/extranonce_manager/allocator.rs +++ b/sv2/channels-sv2/src/extranonce_manager/allocator.rs @@ -428,12 +428,12 @@ mod tests { assert_eq!(alloc.allocated_count(), 0); let ext = alloc.allocate_extended(16).unwrap(); - assert_eq!(ext.as_bytes().len(), 4); + assert_eq!(ext.len(), 4); assert_eq!(&ext.as_bytes()[0..2], &[0x00, 0x01]); assert_eq!(alloc.allocated_count(), 1); let std = alloc.allocate_standard().unwrap(); - assert_eq!(std.as_bytes().len(), 20); + assert_eq!(std.len(), 20); assert_eq!(&std.as_bytes()[0..2], &[0x00, 0x01]); assert_eq!(alloc.allocated_count(), 2); } @@ -459,7 +459,7 @@ mod tests { assert_eq!(alloc.rollable_extranonce_size(), 14); let ext = alloc.allocate_extended(14).unwrap(); - assert_eq!(ext.as_bytes().len(), 6); + assert_eq!(ext.len(), 6); assert_eq!(&ext.as_bytes()[0..4], &[0xAA, 0xBB, 0xCC, 0xDD]); } @@ -490,7 +490,7 @@ mod tests { let ext = alloc.allocate_extended(4).unwrap(); // Prefix bytes must be [upstream | local_prefix | local_index]. - assert_eq!(ext.as_bytes().len(), 16); + assert_eq!(ext.len(), 16); assert_eq!(&ext.as_bytes()[0..4], upstream_prefix.as_slice()); assert_eq!(&ext.as_bytes()[4..15], local_prefix_bytes.as_slice()); // local_index is 1 byte; first allocation index is 0. @@ -626,7 +626,7 @@ mod tests { let mut alloc = ExtranonceAllocator::new(vec![0x01], 20, 256).unwrap(); let std = alloc.allocate_standard().unwrap(); - assert_eq!(std.as_bytes().len(), 20); + assert_eq!(std.len(), 20); assert!(std.as_bytes()[2..].iter().all(|&b| b == 0)); } diff --git a/sv2/channels-sv2/src/server/extended.rs b/sv2/channels-sv2/src/server/extended.rs index ee178b64d8..26b5dcbc47 100644 --- a/sv2/channels-sv2/src/server/extended.rs +++ b/sv2/channels-sv2/src/server/extended.rs @@ -715,7 +715,7 @@ impl<'a> ExtendedChannel<'a> { )); }; - let extranonce_size = share.extranonce.inner_as_ref().len(); + let extranonce_size = share.extranonce.len(); if extranonce_size != self.rollable_extranonce_size as usize { self.share_accounting .increment_rejected_shares(ERROR_CODE_SUBMIT_SHARES_BAD_EXTRANONCE_SIZE); @@ -727,7 +727,7 @@ impl<'a> ExtendedChannel<'a> { let extranonce_prefix = job.get_extranonce_prefix(); let mut full_extranonce = vec![]; full_extranonce.extend_from_slice(extranonce_prefix); - full_extranonce.extend(share.extranonce.inner_as_ref()); + full_extranonce.extend(share.extranonce.as_bytes()); // calculate the merkle root from: // - job coinbase_tx_prefix @@ -738,7 +738,7 @@ impl<'a> ExtendedChannel<'a> { &job.get_coinbase_tx_prefix_without_bip141(), &job.get_coinbase_tx_suffix_without_bip141(), full_extranonce.as_ref(), - &job.get_merkle_path().inner_as_ref(), + job.get_merkle_path().as_slice(), ) .ok_or(ShareValidationError::Invalid( ERROR_CODE_SUBMIT_SHARES_INVALID_SHARE, diff --git a/sv2/channels-sv2/src/server/jobs/extended.rs b/sv2/channels-sv2/src/server/jobs/extended.rs index 0866f2070f..81216da937 100644 --- a/sv2/channels-sv2/src/server/jobs/extended.rs +++ b/sv2/channels-sv2/src/server/jobs/extended.rs @@ -57,7 +57,7 @@ impl<'a> ExtendedJob<'a> { job_message: NewExtendedMiningJob<'a>, ) -> Result { let template_coinbase_outputs = deserialize_template_outputs( - template.coinbase_tx_outputs.to_vec(), + template.coinbase_tx_outputs.to_owned_bytes(), template.coinbase_tx_outputs_count, ) .map_err(|_| ExtendedJobError::FailedToDeserializeCoinbaseOutputs)?; @@ -117,7 +117,7 @@ impl<'a> ExtendedJob<'a> { &self.get_coinbase_tx_prefix_without_bip141(), &self.get_coinbase_tx_suffix_without_bip141(), &extranonce_prefix, - &self.get_merkle_path().inner_as_ref(), + self.get_merkle_path().as_slice(), ) .ok_or(ExtendedJobError::FailedToCalculateMerkleRoot)? .try_into() @@ -154,12 +154,12 @@ impl<'a> ExtendedJob<'a> { /// Returns the coinbase transaction without for this job without BIP141 data. pub fn get_coinbase_tx_prefix_without_bip141(&self) -> Vec { - self.job_message.coinbase_tx_prefix.inner_as_ref().to_vec() + self.job_message.coinbase_tx_prefix.to_owned_bytes() } /// Returns the coinbase transaction suffix for this job without BIP141 data. pub fn get_coinbase_tx_suffix_without_bip141(&self) -> Vec { - self.job_message.coinbase_tx_suffix.inner_as_ref().to_vec() + self.job_message.coinbase_tx_suffix.to_owned_bytes() } /// Sets the extranonce prefix for this job. diff --git a/sv2/channels-sv2/src/server/jobs/factory.rs b/sv2/channels-sv2/src/server/jobs/factory.rs index 266555c3b2..7d3ee128f3 100644 --- a/sv2/channels-sv2/src/server/jobs/factory.rs +++ b/sv2/channels-sv2/src/server/jobs/factory.rs @@ -176,7 +176,7 @@ impl JobFactory { &coinbase_tx_prefix, &coinbase_tx_suffix, &extranonce_prefix, - &merkle_path.inner_as_ref(), + merkle_path.as_slice(), ) .expect("merkle root must be valid") .try_into() @@ -374,7 +374,7 @@ impl JobFactory { } let template_outputs = deserialize_template_outputs( - template.coinbase_tx_outputs.to_vec(), + template.coinbase_tx_outputs.to_owned_bytes(), template.coinbase_tx_outputs_count, ) .map_err(|_| JobFactoryError::DeserializeCoinbaseOutputsError)?; @@ -386,7 +386,7 @@ impl JobFactory { let serialized_outputs = serialize(&coinbase_tx_outputs); let mut coinbase_prefix = vec![]; - coinbase_prefix.extend_from_slice(&template.coinbase_prefix.to_vec()); + coinbase_prefix.extend_from_slice(template.coinbase_prefix.as_bytes()); coinbase_prefix.extend_from_slice(&self.op_pushbytes_pool_miner_tag()?); coinbase_prefix.push(full_extranonce_size as u8); // OP_PUSHBYTES_X (for the full extranonce) @@ -424,10 +424,7 @@ impl JobFactory { extranonce_prefix: Vec, full_extranonce_size: usize, ) -> Result, JobFactoryError> { - let serialized_outputs = set_custom_mining_job - .coinbase_tx_outputs - .inner_as_ref() - .to_vec(); + let serialized_outputs = set_custom_mining_job.coinbase_tx_outputs.to_owned_bytes(); let coinbase_outputs = Vec::::consensus_decode(&mut serialized_outputs.as_slice()) .map_err(|_| JobFactoryError::DeserializeCoinbaseOutputsError)?; @@ -489,13 +486,12 @@ impl JobFactory { m: SetCustomMiningJob<'_>, full_extranonce_size: usize, ) -> Result { - let deserialized_outputs = Vec::::consensus_decode( - &mut m.coinbase_tx_outputs.inner_as_ref().to_vec().as_slice(), - ) - .map_err(|_| JobFactoryError::DeserializeCoinbaseOutputsError)?; + let deserialized_outputs = + Vec::::consensus_decode(&mut m.coinbase_tx_outputs.to_owned_bytes().as_slice()) + .map_err(|_| JobFactoryError::DeserializeCoinbaseOutputsError)?; let mut script_sig = vec![]; - script_sig.extend_from_slice(m.coinbase_prefix.inner_as_ref()); + script_sig.extend_from_slice(m.coinbase_prefix.as_bytes()); script_sig.extend_from_slice(&vec![0; full_extranonce_size]); // Create transaction input @@ -530,7 +526,7 @@ impl JobFactory { + 32 // prev OutPoint + 4 // index + 1 // bytes in script - + m.coinbase_prefix.inner_as_ref().len(); + + m.coinbase_prefix.len(); let coinbase_tx_prefix = serialized_coinbase[0..index].to_vec(); @@ -551,7 +547,7 @@ impl JobFactory { + 32 // prev OutPoint + 4 // index + 1 // bytes in script - + m.coinbase_prefix.inner_as_ref().len() + + m.coinbase_prefix.len() + full_extranonce_size; let coinbase_tx_suffix = serialized_coinbase[index..].to_vec(); @@ -586,7 +582,7 @@ impl JobFactory { } let mut template_outputs = deserialize_template_outputs( - template.coinbase_tx_outputs.to_vec(), + template.coinbase_tx_outputs.to_owned_bytes(), template.coinbase_tx_outputs_count, ) .map_err(|_| JobFactoryError::DeserializeCoinbaseOutputsError)?; @@ -596,7 +592,7 @@ impl JobFactory { let op_pushbytes_pool_miner_tag = self.op_pushbytes_pool_miner_tag()?; let mut script_sig = vec![]; - script_sig.extend_from_slice(&template.coinbase_prefix.to_vec()); + script_sig.extend_from_slice(template.coinbase_prefix.as_bytes()); script_sig.extend_from_slice(&op_pushbytes_pool_miner_tag); script_sig.push(full_extranonce_size as u8); // OP_PUSHBYTES_X (for the full extranonce) script_sig.extend_from_slice(&vec![0; full_extranonce_size]); diff --git a/sv2/channels-sv2/src/server/jobs/standard.rs b/sv2/channels-sv2/src/server/jobs/standard.rs index d1d0e8b354..898ca628a7 100644 --- a/sv2/channels-sv2/src/server/jobs/standard.rs +++ b/sv2/channels-sv2/src/server/jobs/standard.rs @@ -65,7 +65,7 @@ impl<'a> StandardJob<'a> { job_message: NewMiningJob<'a>, ) -> Result { let template_coinbase_outputs = deserialize_template_outputs( - template.coinbase_tx_outputs.to_vec(), + template.coinbase_tx_outputs.to_owned_bytes(), template.coinbase_tx_outputs_count, ) .map_err(|_| StandardJobError::FailedToDeserializeCoinbaseOutputs)?; diff --git a/sv2/channels-sv2/src/server/standard.rs b/sv2/channels-sv2/src/server/standard.rs index 8fcf04caf2..dd3eca4a8f 100644 --- a/sv2/channels-sv2/src/server/standard.rs +++ b/sv2/channels-sv2/src/server/standard.rs @@ -63,7 +63,7 @@ use mining_sv2::{ ERROR_CODE_SUBMIT_SHARES_INVALID_JOB_ID, ERROR_CODE_SUBMIT_SHARES_STALE_SHARE, ERROR_CODE_UPDATE_CHANNEL_INVALID_NOMINAL_HASHRATE, }; -use std::{collections::HashMap, convert::TryInto, marker::PhantomData}; +use std::{collections::HashMap, marker::PhantomData}; use template_distribution_sv2::{NewTemplate, SetNewPrevHash}; use tracing::debug; @@ -615,11 +615,7 @@ impl<'a> StandardChannel<'a> { )); }; - let merkle_root: [u8; 32] = job - .get_merkle_root() - .inner_as_ref() - .try_into() - .expect("merkle root must be 32 bytes"); + let merkle_root = job.get_merkle_root().to_array(); let chain_tip = self .chain_tip @@ -682,7 +678,7 @@ impl<'a> StandardChannel<'a> { .op_pushbytes_pool_miner_tag() .map_err(|_| ShareValidationError::InvalidCoinbase)?; - let mut script_sig = job.get_template().coinbase_prefix.to_vec(); + let mut script_sig = job.get_template().coinbase_prefix.to_owned_bytes(); script_sig.extend(op_pushbytes_pool_miner_tag); script_sig.push(self.extranonce_prefix.len() as u8); // OP_PUSHBYTES_X (for the extranonce) script_sig.extend(job.get_extranonce_prefix()); diff --git a/sv2/channels-sv2/src/target.rs b/sv2/channels-sv2/src/target.rs index abd233df1b..08b8748c7f 100644 --- a/sv2/channels-sv2/src/target.rs +++ b/sv2/channels-sv2/src/target.rs @@ -9,7 +9,7 @@ use primitive_types::U256 as U256Primitive; /// Converts a `u256` to a [`BlockHash`] type. pub fn u256_to_block_hash(v: U256<'static>) -> BlockHash { - let hash: [u8; 32] = v.to_vec().try_into().unwrap(); + let hash = v.into_array(); let hash = Hash::from_slice(&hash).unwrap(); BlockHash::from_raw_hash(hash) } @@ -171,7 +171,7 @@ pub fn hash_rate_from_target(target: U256<'static>, share_per_min: f64) -> Resul } let mut target_arr: [u8; 32] = [0; 32]; let slice: &mut [u8] = &mut target_arr; - slice.copy_from_slice(target.inner_as_ref()); + slice.copy_from_slice(target.as_bytes()); target_arr.reverse(); let target = U256Primitive::from_big_endian(target_arr.as_ref()); // we calculate the numerator 2^256-t diff --git a/sv2/codec-sv2/benches/common.rs b/sv2/codec-sv2/benches/common.rs index 4f92bb2587..38f1eff172 100644 --- a/sv2/codec-sv2/benches/common.rs +++ b/sv2/codec-sv2/benches/common.rs @@ -36,11 +36,11 @@ impl OwnedMsg { #[allow(dead_code)] pub fn from_zc(msg: ZeroCopyMsg<'_>) -> Self { let mut merkle_root = [0u8; 32]; - merkle_root.copy_from_slice(msg.merkle_root.inner_as_ref()); + merkle_root.copy_from_slice(msg.merkle_root.as_bytes()); OwnedMsg { channel_id: msg.channel_id, merkle_root, - coinbase_suffix: msg.coinbase_suffix.inner_as_ref().to_vec(), + coinbase_suffix: msg.coinbase_suffix.to_owned_bytes(), } } } diff --git a/sv2/parsers-sv2/src/tlv_extensions/mod.rs b/sv2/parsers-sv2/src/tlv_extensions/mod.rs index 2a0d8d772a..511a5459f4 100644 --- a/sv2/parsers-sv2/src/tlv_extensions/mod.rs +++ b/sv2/parsers-sv2/src/tlv_extensions/mod.rs @@ -66,8 +66,8 @@ impl TlvField for UserIdentity { /// Converts this UserIdentity into a TLV structure. fn to_tlv(&self) -> Result { // Validate length - if self.as_bytes().len() > MAX_USER_IDENTITY_LENGTH { - return Err(UserIdentityError::TooLong(self.as_bytes().len()).into()); + if self.len() > MAX_USER_IDENTITY_LENGTH { + return Err(UserIdentityError::TooLong(self.len()).into()); } Ok(Tlv::new( diff --git a/sv2/subprotocols/common-messages/src/setup_connection.rs b/sv2/subprotocols/common-messages/src/setup_connection.rs index 463b262e4b..8c052d7d2a 100644 --- a/sv2/subprotocols/common-messages/src/setup_connection.rs +++ b/sv2/subprotocols/common-messages/src/setup_connection.rs @@ -344,8 +344,8 @@ mod test { assert!(result.is_err()); match result { - Err(binary_sv2::Error::OutOfBound) => (), - Err(e) => panic!("Expected OutOfBounds error, got {:?}", e), + Err(binary_sv2::Error::ReadError(0, 1)) => (), + Err(e) => panic!("Expected ReadError(0, 1), got {:?}", e), Ok(_) => panic!("Expected error, got Ok"), } } diff --git a/sv2/subprotocols/mining/src/new_mining_job.rs b/sv2/subprotocols/mining/src/new_mining_job.rs index c5afb2f8a2..af1aa1bd79 100644 --- a/sv2/subprotocols/mining/src/new_mining_job.rs +++ b/sv2/subprotocols/mining/src/new_mining_job.rs @@ -214,8 +214,7 @@ mod tests { job_id, min_ntime: Sv2Option::new(min_ntime), version, - merkle_root: U256::try_from(merkle_root.to_vec()) - .expect("NewMiningJob: failed to convert merkle_root to B032"), + merkle_root: U256::from(merkle_root), }; let static_nmj = nmj.clone().as_static(); static_nmj.channel_id == nmj.channel_id diff --git a/sv2/subprotocols/mining/src/open_channel.rs b/sv2/subprotocols/mining/src/open_channel.rs index 13544fbeef..ddc27f7bbe 100644 --- a/sv2/subprotocols/mining/src/open_channel.rs +++ b/sv2/subprotocols/mining/src/open_channel.rs @@ -1,5 +1,5 @@ use alloc::{string::ToString, vec::Vec}; -use binary_sv2::{Deserialize, Serialize, Str0255, U32AsRef, B032, U256}; +use binary_sv2::{Deserialize, Serialize, Str0255, B032, U256}; use core::{convert::TryInto, fmt}; /// Message used by a downstream to request opening a Standard Channel. /// @@ -13,7 +13,7 @@ pub struct OpenStandardMiningChannel<'decoder> { /// Used for matching responses from upstream. /// /// The value must be connection-wide unique and is not interpreted by the upstream. - pub request_id: U32AsRef<'decoder>, + pub request_id: u32, /// Unconstrained sequence of bytes. /// /// Whatever is needed by upstream role to identify/authenticate the downstream, e.g. @@ -51,16 +51,11 @@ impl fmt::Display for OpenStandardMiningChannel<'_> { impl OpenStandardMiningChannel<'_> { pub fn get_request_id_as_u32(&self) -> u32 { - (&self.request_id).into() + self.request_id } pub fn update_id(&mut self, new_id: u32) { - let bytes_new = new_id.to_le_bytes(); - let bytes_old = self.request_id.inner_as_mut(); - bytes_old[0] = bytes_new[0]; - bytes_old[1] = bytes_new[1]; - bytes_old[2] = bytes_new[2]; - bytes_old[3] = bytes_new[3]; + self.request_id = new_id; } } @@ -72,7 +67,7 @@ pub struct OpenStandardMiningChannelSuccess<'decoder> { /// /// Specified by downstream role and should be extracted from the corresponding /// [`OpenStandardMiningChannel`] message. - pub request_id: U32AsRef<'decoder>, + pub request_id: u32, /// Newly assigned identifier of the channel, stable for the whole lifetime of the connection. /// /// This will also be used for broadcasting new jobs by [`crate::NewMiningJob`]. @@ -102,16 +97,11 @@ impl fmt::Display for OpenStandardMiningChannelSuccess<'_> { impl OpenStandardMiningChannelSuccess<'_> { pub fn get_request_id_as_u32(&self) -> u32 { - (&self.request_id).into() + self.request_id } pub fn update_id(&mut self, new_id: u32) { - let bytes_new = new_id.to_le_bytes(); - let bytes_old = self.request_id.inner_as_mut(); - bytes_old[0] = bytes_new[0]; - bytes_old[1] = bytes_new[1]; - bytes_old[2] = bytes_new[2]; - bytes_old[3] = bytes_new[3]; + self.request_id = new_id; } } @@ -303,7 +293,7 @@ mod tests { ) -> bool { let max_target: [u8; 32] = from_arbitrary_vec_to_array(max_target); let mut osmc = OpenStandardMiningChannel { - request_id: U32AsRef::from(request_id), + request_id, user_identity: Str0255::try_from(user_identity.clone()) .expect("could not convert string to Str0255"), nominal_hash_rate, @@ -329,12 +319,10 @@ mod tests { let target = from_arbitrary_vec_to_array(target); let extranonce_prefix = from_arbitrary_vec_to_array(extranonce_prefix); let mut osmcs = OpenStandardMiningChannelSuccess { - request_id: U32AsRef::from(request_id), + request_id, channel_id, target: U256::from(target), - extranonce_prefix: B032::try_from(extranonce_prefix.to_vec()).expect( - "OpenStandardMiningChannelSuccess: failed to convert extranonce_prefix to B032", - ), + extranonce_prefix: B032::try_from(extranonce_prefix).unwrap(), group_channel_id, }; let test_request_id_1 = osmcs.get_request_id_as_u32();