diff --git a/protocols/v2/binary-sv2/binary-sv2/src/lib.rs b/protocols/v2/binary-sv2/binary-sv2/src/lib.rs index daa4ec055..4fe4ecd05 100644 --- a/protocols/v2/binary-sv2/binary-sv2/src/lib.rs +++ b/protocols/v2/binary-sv2/binary-sv2/src/lib.rs @@ -18,11 +18,14 @@ pub fn clone_message(_: T) -> T { #[cfg(not(feature = "with_serde"))] 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) } + // Always safe cause u256 is 24 + 8 (32) bytes let u256: U256 = u256.try_into().unwrap(); u256 } @@ -31,33 +34,6 @@ pub fn u256_from_int>(value: V) -> U256<'static> { mod test { use super::*; - mod test_bytes { - use super::*; - use core::convert::TryInto; - - #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)] - struct Test<'decoder> { - #[cfg_attr(feature = "with_serde", serde(borrow))] - a: Bytes<'decoder>, - } - - #[test] - fn test_struct() { - let mut bytes = [98; 890]; - let a: Bytes = (&mut bytes[..]).try_into().unwrap(); - let expected = Test { a }; - - #[cfg(not(feature = "with_serde"))] - let mut bytes = to_bytes(expected.clone()).unwrap(); - #[cfg(feature = "with_serde")] - let mut bytes = to_bytes(&expected.clone()).unwrap(); - - let deserialized: Test = from_bytes(&mut bytes[..]).unwrap(); - - assert_eq!(deserialized, expected); - } - } - mod test_struct { use super::*; use core::convert::TryInto; diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/decodable.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/decodable.rs index 06bc13263..ede92be5a 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/decodable.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/decodable.rs @@ -1,9 +1,10 @@ use crate::{ codec::{GetSize, SizeHint}, - datatypes::{Bytes, Signature, Sv2DataType, B016M, B0255, B032, B064K, U24, U256}, + datatypes::{Signature, Sv2DataType, U32AsRef, B016M, B0255, B032, B064K, U24, U256}, Error, }; use alloc::vec::Vec; +use std::convert::TryFrom; #[cfg(not(feature = "no_std"))] use std::io::{Cursor, Read}; @@ -55,13 +56,13 @@ pub enum PrimitiveMarker { U256, Signature, U32, + U32AsRef, F32, U64, B032, B0255, B064K, B016M, - Bytes, } /// Passed to a decoder to define the structure of the data to be decoded @@ -84,13 +85,13 @@ pub enum DecodablePrimitive<'a> { U256(U256<'a>), Signature(Signature<'a>), U32(u32), + U32AsRef(U32AsRef<'a>), F32(f32), U64(u64), B032(B032<'a>), B0255(B0255<'a>), B064K(B064K<'a>), B016M(B016M<'a>), - Bytes(Bytes<'a>), } /// Used to contrustuct messages is returned by the decoder @@ -101,6 +102,7 @@ pub enum DecodableField<'a> { } impl SizeHint for PrimitiveMarker { + // PrimitiveMarker need introspection to return a size hint. This method is not implementeable fn size_hint(_data: &[u8], _offset: usize) -> Result { unimplemented!() } @@ -114,18 +116,19 @@ impl SizeHint for PrimitiveMarker { Self::U256 => U256::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), Self::B0255 => B0255::size_hint(data, offset), Self::B064K => B064K::size_hint(data, offset), Self::B016M => B016M::size_hint(data, offset), - Self::Bytes => Bytes::size_hint(data, offset), } } } impl SizeHint for FieldMarker { + // FieldMarker need introspection to return a size hint. This method is not implementeable fn size_hint(_data: &[u8], _offset: usize) -> Result { unimplemented!() } @@ -145,6 +148,7 @@ impl SizeHint for FieldMarker { } impl SizeHint for Vec { + // FieldMarker need introspection to return a size hint. This method is not implementeable fn size_hint(_data: &[u8], _offset: usize) -> Result { unimplemented!() } @@ -165,12 +169,18 @@ impl From for FieldMarker { } } -impl From> for FieldMarker { - fn from(mut v: Vec) -> Self { +impl TryFrom> for FieldMarker { + type Error = crate::Error; + + fn try_from(mut v: Vec) -> Result { match v.len() { - 0 => panic!("TODO"), - 1 => v.pop().unwrap(), - _ => FieldMarker::Struct(v), + // It shouldn't be possible to call this function with a void Vec but for safety + // reasons it is implemented with TryFrom and not From if needed should be possible + // to use From and just panic + 0 => Err(crate::Error::VoidFieldMarker), + // This is always safe: if v.len is 1 pop can not fail + 1 => Ok(v.pop().unwrap()), + _ => Ok(FieldMarker::Struct(v)), } } } @@ -196,6 +206,9 @@ impl PrimitiveMarker { 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..])), @@ -208,9 +221,6 @@ impl PrimitiveMarker { Self::B016M => { DecodablePrimitive::B016M(B016M::from_bytes_unchecked(&mut data[offset..])) } - Self::Bytes => { - DecodablePrimitive::Bytes(Bytes::from_bytes_unchecked(&mut data[offset..])) - } } } @@ -226,13 +236,15 @@ impl PrimitiveMarker { 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)?)), Self::B0255 => Ok(DecodablePrimitive::B0255(B0255::from_reader_(reader)?)), Self::B064K => Ok(DecodablePrimitive::B064K(B064K::from_reader_(reader)?)), Self::B016M => Ok(DecodablePrimitive::B016M(B016M::from_reader_(reader)?)), - Self::Bytes => Ok(DecodablePrimitive::Bytes(Bytes::from_reader_(reader)?)), } } } @@ -247,13 +259,13 @@ impl<'a> GetSize for DecodablePrimitive<'a> { DecodablePrimitive::U256(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(), DecodablePrimitive::B0255(v) => v.get_size(), DecodablePrimitive::B064K(v) => v.get_size(), DecodablePrimitive::B016M(v) => v.get_size(), - DecodablePrimitive::Bytes(v) => v.get_size(), } } } diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/encodable.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/encodable.rs index cb5e4d4c7..b54e317bb 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/encodable.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/encodable.rs @@ -1,6 +1,6 @@ use crate::{ codec::GetSize, - datatypes::{Bytes, Signature, Sv2DataType, B016M, B0255, B032, B064K, U24, U256}, + datatypes::{Signature, Sv2DataType, U32AsRef, B016M, B0255, B032, B064K, U24, U256}, Error, }; use alloc::vec::Vec; @@ -42,13 +42,13 @@ pub enum EncodablePrimitive<'a> { U256(U256<'a>), Signature(Signature<'a>), U32(u32), + U32AsRef(U32AsRef<'a>), F32(f32), U64(u64), B032(B032<'a>), B0255(B0255<'a>), B064K(B064K<'a>), B016M(B016M<'a>), - Bytes(Bytes<'a>), } impl<'a> EncodablePrimitive<'a> { @@ -62,13 +62,13 @@ impl<'a> EncodablePrimitive<'a> { Self::U256(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), Self::B0255(v) => v.to_slice(dst), Self::B064K(v) => v.to_slice(dst), Self::B016M(v) => v.to_slice(dst), - Self::Bytes(v) => v.to_slice(dst), } } @@ -83,13 +83,13 @@ impl<'a> EncodablePrimitive<'a> { Self::U256(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), Self::B0255(v) => v.to_writer_(writer), Self::B064K(v) => v.to_writer_(writer), Self::B016M(v) => v.to_writer_(writer), - Self::Bytes(v) => v.to_writer_(writer), } } } @@ -105,13 +105,13 @@ impl<'a> GetSize for EncodablePrimitive<'a> { Self::U256(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(), Self::B0255(v) => v.get_size(), Self::B064K(v) => v.get_size(), Self::B016M(v) => v.get_size(), - Self::Bytes(v) => v.get_size(), } } } diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/impls.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/impls.rs index 2145c5b31..5d21f2d79 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/impls.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/impls.rs @@ -77,9 +77,9 @@ impl<'a> GetMarker for B016M<'a> { FieldMarker::Primitive(PrimitiveMarker::B016M) } } -impl<'a> GetMarker for Bytes<'a> { +impl<'a> GetMarker for U32AsRef<'a> { fn get_marker() -> FieldMarker { - FieldMarker::Primitive(PrimitiveMarker::Bytes) + FieldMarker::Primitive(PrimitiveMarker::U32AsRef) } } @@ -91,7 +91,7 @@ impl<'a> Decodable<'a> for u8 { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for u16 { @@ -100,7 +100,7 @@ impl<'a> Decodable<'a> for u16 { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for u32 { @@ -109,7 +109,7 @@ impl<'a> Decodable<'a> for u32 { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for f32 { @@ -118,7 +118,7 @@ impl<'a> Decodable<'a> for f32 { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for u64 { @@ -127,7 +127,7 @@ impl<'a> Decodable<'a> for u64 { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for bool { @@ -136,7 +136,7 @@ impl<'a> Decodable<'a> for bool { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for U24 { @@ -145,7 +145,7 @@ impl<'a> Decodable<'a> for U24 { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for U256<'a> { @@ -154,7 +154,7 @@ impl<'a> Decodable<'a> for U256<'a> { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for Signature<'a> { @@ -163,7 +163,7 @@ impl<'a> Decodable<'a> for Signature<'a> { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for B032<'a> { @@ -172,7 +172,7 @@ impl<'a> Decodable<'a> for B032<'a> { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for B0255<'a> { @@ -181,7 +181,7 @@ impl<'a> Decodable<'a> for B0255<'a> { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for B064K<'a> { @@ -190,7 +190,7 @@ impl<'a> Decodable<'a> for B064K<'a> { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } impl<'a> Decodable<'a> for B016M<'a> { @@ -199,17 +199,17 @@ impl<'a> Decodable<'a> for B016M<'a> { } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } -impl<'a> Decodable<'a> for Bytes<'a> { +impl<'a> Decodable<'a> for U32AsRef<'a> { fn get_structure(_: &[u8]) -> Result, Error> { - Ok(vec![PrimitiveMarker::Bytes.into()]) + Ok(vec![PrimitiveMarker::U32AsRef.into()]) } fn from_decoded_fields(mut data: Vec>) -> Result { - data.pop().unwrap().try_into() + data.pop().ok_or(Error::NoDecodableFieldPassed)?.try_into() } } @@ -346,12 +346,12 @@ impl<'a> TryFrom> for B016M<'a> { } } } -impl<'a> TryFrom> for Bytes<'a> { +impl<'a> TryFrom> for U32AsRef<'a> { type Error = Error; fn try_from(value: DecodablePrimitive<'a>) -> Result { match value { - DecodablePrimitive::Bytes(val) => Ok(val), + DecodablePrimitive::U32AsRef(val) => Ok(val), _ => Err(Error::PrimitiveConversionError), } } @@ -489,7 +489,7 @@ impl<'a> TryFrom> for B016M<'a> { } } } -impl<'a> TryFrom> for Bytes<'a> { +impl<'a> TryFrom> for U32AsRef<'a> { type Error = Error; fn try_from(value: DecodableField<'a>) -> Result { @@ -697,26 +697,26 @@ impl<'a> TryFrom> for B016M<'a> { } } } -impl<'a> From> for EncodableField<'a> { - fn from(v: Bytes<'a>) -> Self { - EncodableField::Primitive(EncodablePrimitive::Bytes(v)) +//impl<'a> From<&'a Seq0255<'a, U24>> for EncodableField<'a> { +// fn from(v: &'a Seq0255<'a, U24>) -> Self { +// EncodableField::Primitive(EncodablePrimitive::Seq0255u24(v)) +// } +//} +impl<'a> From> for EncodableField<'a> { + fn from(v: U32AsRef<'a>) -> Self { + EncodableField::Primitive(EncodablePrimitive::U32AsRef(v)) } } -impl<'a> TryFrom> for Bytes<'a> { +impl<'a> TryFrom> for U32AsRef<'a> { type Error = Error; fn try_from(value: EncodableField<'a>) -> Result { match value { - EncodableField::Primitive(EncodablePrimitive::Bytes(v)) => Ok(v), + EncodableField::Primitive(EncodablePrimitive::U32AsRef(v)) => Ok(v), _ => Err(Error::Todo), } } } -//impl<'a> From<&'a Seq0255<'a, U24>> for EncodableField<'a> { -// fn from(v: &'a Seq0255<'a, U24>) -> Self { -// EncodableField::Primitive(EncodablePrimitive::Seq0255u24(v)) -// } -//} // IMPL INTO FIELD MARKER FOR PRIMITIVES impl From for FieldMarker { @@ -795,8 +795,8 @@ impl<'a> From> for FieldMarker { FieldMarker::Primitive(PrimitiveMarker::B016M) } } -impl<'a> From> for FieldMarker { - fn from(_: Inner<'a, false, 0, 0, { ((2_usize.pow(63) - 1) * 2) + 1 }>) -> Self { - FieldMarker::Primitive(PrimitiveMarker::Bytes) +impl<'a> From> for FieldMarker { + fn from(_: U32AsRef<'a>) -> Self { + FieldMarker::Primitive(PrimitiveMarker::U32AsRef) } } diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/mod.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/mod.rs index 91bef226d..57db70339 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/mod.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/codec/mod.rs @@ -32,7 +32,7 @@ pub trait Variable { fn inner_size(&self) -> usize; - // TODO use [u8; HEADER_SIZE] instead of Vec + // That could be [u8; Self::HEADER_SIZE] but rust do not allow it fn get_header(&self) -> Vec; } diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/copy_data_types.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/copy_data_types.rs index a825cd9ce..359b40a7f 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/copy_data_types.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/copy_data_types.rs @@ -26,10 +26,12 @@ impl<'a> Sv2DataType<'a> for bool { .get(0) .map(|x: &u8| x << 7) .map(|x: u8| x >> 7) - .unwrap() + // 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!(), } } @@ -79,7 +81,6 @@ impl Fixed for u32 { const SIZE: usize = 4; } -// TODO fix not in the specs impl Fixed for u64 { const SIZE: usize = 8; } @@ -88,7 +89,10 @@ macro_rules! impl_sv2_for_unsigned { ($a:ty) => { impl<'a> Sv2DataType<'a> for $a { fn from_bytes_unchecked(data: &'a mut [u8]) -> Self { - let a: &[u8; Self::SIZE] = data[0..Self::SIZE].try_into().unwrap(); + // unchecked function is fine to panic + 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) } diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/mod.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/mod.rs index 573b7cd60..7a20fb498 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/mod.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/mod.rs @@ -8,14 +8,16 @@ mod copy_data_types; use crate::codec::decodable::FieldMarker; pub use copy_data_types::U24; pub use non_copy_data_types::{ - Bytes, Inner, PubKey, Seq0255, Seq064K, Signature, Str0255, Str032, B016M, B0255, B032, B064K, - U256, + Inner, PubKey, Seq0255, Seq064K, Signature, Str0255, Str032, U32AsRef, B016M, B0255, B032, + B064K, U256, }; #[cfg(not(feature = "no_std"))] use std::io::{Error as E, Read, Write}; -pub trait Sv2DataType<'a>: Sized + SizeHint + GetSize + Into { +use std::convert::TryInto; + +pub trait Sv2DataType<'a>: Sized + SizeHint + GetSize + TryInto { fn from_bytes_(data: &'a mut [u8]) -> Result { Self::size_hint(data, 0)?; Ok(Self::from_bytes_unchecked(data)) diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/inner.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/inner.rs index 9af5174ed..bacf3cda6 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/inner.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/inner.rs @@ -5,6 +5,7 @@ use crate::{ Error, }; use core::convert::TryFrom; +use std::convert::TryInto; #[cfg(not(feature = "no_std"))] use std::io::{Error as E, Read, Write}; @@ -22,7 +23,7 @@ pub enum Inner< Owned(Vec), } -// TODO add test for that implement also with serde!!!! +// TODO add test for that and implement it also with serde!!!! impl<'a, const SIZE: usize> Inner<'a, true, SIZE, 0, 0> { pub fn to_vec(&self) -> Vec { match self { @@ -33,11 +34,17 @@ impl<'a, const SIZE: usize> Inner<'a, true, SIZE, 0, 0> { pub fn inner_as_ref(&self) -> &[u8] { match self { Inner::Ref(ref_) => ref_, - Inner::Owned(v) => &v, + Inner::Owned(v) => v, + } + } + pub fn inner_as_mut(&mut self) -> &mut [u8] { + match self { + Inner::Ref(ref_) => ref_, + Inner::Owned(v) => v, } } } -// TODO add test for that implement also with serde!!!! +// TODO add test for that and implement it also with serde!!!! impl<'a, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> Inner<'a, false, SIZE, HEADERSIZE, MAXSIZE> { @@ -95,11 +102,13 @@ impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const fn expected_length_variable(data: &[u8]) -> Result { if data.len() >= HEADERSIZE { let size = match HEADERSIZE { - 0 => Ok(data.len()), 1 => Ok(data[0] as usize), 2 => Ok(u16::from_le_bytes([data[0], data[1]]) as usize), 3 => Ok(u32::from_le_bytes([data[0], data[1], data[2], 0]) as usize), - _ => unimplemented!(), + // HEADERSIZE for Sv2 datatypes is at maximum 3 bytes + // When HEADERSIZE is 0 datatypes ISFIXED only exception is Bytes datatypes but is + // not used + _ => unreachable!(), }; size.map(|x| x + HEADERSIZE) } else { @@ -118,7 +127,10 @@ impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const 1 => header[0] as usize, 2 => u16::from_le_bytes([header[0], header[1]]) as usize, 3 => u32::from_le_bytes([header[0], header[1], header[2], 0]) as usize, - _ => unimplemented!(), + // HEADERSIZE for Sv2 datatypes is at maximum 3 bytes + // When HEADERSIZE is 0 datatypes ISFIXED only exception is Bytes datatypes but is + // not used + _ => unreachable!(), }; if expected_length <= (MAXSIZE + HEADERSIZE) { Ok(expected_length) @@ -209,7 +221,7 @@ use crate::codec::decodable::FieldMarker; impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> Sv2DataType<'a> for Inner<'a, ISFIXED, SIZE, HEADERSIZE, MAXSIZE> where - Self: Into, + Self: TryInto, { fn from_bytes_unchecked(data: &'a mut [u8]) -> Self { if ISFIXED { diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/mod.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/mod.rs index 7de25a681..78f99412a 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/mod.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/mod.rs @@ -1,6 +1,4 @@ #[cfg(feature = "prop_test")] -use core::convert::TryInto; -#[cfg(feature = "prop_test")] use quickcheck::{Arbitrary, Gen}; mod inner; @@ -13,6 +11,7 @@ trait IntoOwned { pub use inner::Inner; pub use seq_inner::{Seq0255, Seq064K}; +pub type U32AsRef<'a> = Inner<'a, true, 4, 0, 0>; pub type U256<'a> = Inner<'a, true, 32, 0, 0>; pub type PubKey<'a> = Inner<'a, true, 32, 0, 0>; pub type Signature<'a> = Inner<'a, true, 64, 0, 0>; @@ -22,7 +21,6 @@ pub type Str032<'a> = Inner<'a, false, 1, 1, 32>; pub type Str0255<'a> = Inner<'a, false, 1, 1, 255>; pub type B064K<'a> = Inner<'a, false, 1, 2, { u16::MAX as usize }>; pub type B016M<'a> = Inner<'a, false, 1, 3, { 2_usize.pow(24) - 1 }>; -pub type Bytes<'a> = Inner<'a, false, 0, 0, { usize::MAX }>; impl<'decoder> From<[u8; 32]> for U256<'decoder> { fn from(v: [u8; 32]) -> Self { @@ -36,6 +34,7 @@ impl<'a> U256<'a> { pub fn from_gen(g: &mut Gen) -> Self { let mut inner = Vec::::arbitrary(g); inner.resize(32, 0); + // 32 Bytes arrays are always converted into U256 unwrap never panic let inner: [u8; 32] = inner.try_into().unwrap(); inner.into() } @@ -45,6 +44,7 @@ impl<'a> U256<'a> { #[cfg(feature = "prop_test")] impl<'a> B016M<'a> { pub fn from_gen(g: &mut Gen) -> Self { + // This can fail but is used only for tests purposes Vec::::arbitrary(g).try_into().unwrap() } } @@ -66,3 +66,25 @@ impl<'a> TryFrom for Str032<'a> { value.into_bytes().try_into() } } + +impl<'a> U32AsRef<'a> { + 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<'a> From for U32AsRef<'a> { + 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) + } +} + +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]]) + } +} diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/seq_inner.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/seq_inner.rs index 5eca306f5..cd4511f59 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/seq_inner.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/datatypes/non_copy_data_types/seq_inner.rs @@ -9,7 +9,7 @@ use crate::{ }; use core::marker::PhantomData; -// TODO add test for that implement also with serde!!!! +// TODO add test for that and implement it also with serde!!!! impl<'a, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> Seq0255<'a, super::inner::Inner<'a, false, SIZE, HEADERSIZE, MAXSIZE>> { @@ -21,7 +21,7 @@ impl<'a, const SIZE: usize, const HEADERSIZE: usize, const MAXSIZE: usize> } } -// TODO add test for that implement also with serde!!!! +// TODO add test for that and implement it also with serde!!!! impl<'a, const SIZE: usize> Seq0255<'a, super::inner::Inner<'a, true, SIZE, 0, 0>> { pub fn to_vec(&self) -> Vec> { self.0.iter().map(|x| x.to_vec()).collect() @@ -148,7 +148,8 @@ macro_rules! impl_codec_for_sequence { T::from_decoded_fields(vec![DecodableField::Primitive(p)]); inner.push(element?) } - DecodableField::Struct(_) => unimplemented!(), + // A struct always recursivly call decode until it reach a primitive + DecodableField::Struct(_) => unreachable!(), } } i += 1; diff --git a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/lib.rs b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/lib.rs index 97fb6b22f..e912ccc32 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/codec/src/lib.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/codec/src/lib.rs @@ -5,13 +5,13 @@ //! u16 <-> U16 //! U24 <-> U24 //! u32 <-> u32 -//! f32 <-> f32 // todo not in the spec but used -//! u64 <-> u64 // todo not in the spec but used +//! f32 <-> f32 // not in the spec but used +//! u64 <-> u64 // not in the spec but used //! U256 <-> U256 //! Str0255 <-> STRO_255 -//! Str032 <-> STRO_32 // todo not in the spec but used +//! Str032 <-> STRO_32 // not in the spec but used //! Signature<-> SIGNATURE -//! B032 <-> B0_32 // todo not in the spec but used +//! B032 <-> B0_32 // not in the spec but used //! B0255 <-> B0_255 //! B064K <-> B0_64K //! B016M <-> B0_16M @@ -20,16 +20,13 @@ //! Seq0255 <-> SEQ0_255[T] //! Seq064K <-> SEQ0_64K[T] //! ``` -#![cfg_attr(feature = "no_std", no_std)] -use core::convert::TryInto; - #[cfg(not(feature = "no_std"))] use std::io::{Error as E, ErrorKind}; mod codec; mod datatypes; pub use datatypes::{ - Bytes, PubKey, Seq0255, Seq064K, Signature, Str0255, Str032, B016M, B0255, B032, B064K, U24, + PubKey, Seq0255, Seq064K, Signature, Str0255, Str032, U32AsRef, B016M, B0255, B032, B064K, U24, U256, }; @@ -88,6 +85,10 @@ pub enum Error { #[cfg(not(feature = "no_std"))] IoError(E), ReadError(usize, usize), + VoidFieldMarker, + NoDecodableFieldPassed, + ValueIsNotAValidProtocol(u8), + UnknownMessageType(u8), Todo, } @@ -108,12 +109,10 @@ impl GetSize for Vec { } } +// Only needed for implement encodable for Frame never called impl<'a> From> for EncodableField<'a> { - fn from(v: Vec) -> Self { - let bytes: Bytes = v.try_into().unwrap(); - crate::encodable::EncodableField::Primitive( - crate::codec::encodable::EncodablePrimitive::Bytes(bytes), - ) + fn from(_v: Vec) -> Self { + unreachable!() } } @@ -169,7 +168,6 @@ impl From<&[u8]> for CVec { /// /// # Safety /// -/// TODO #[no_mangle] pub unsafe extern "C" fn cvec_from_buffer(data: *const u8, len: usize) -> CVec { let input = std::slice::from_raw_parts(data, len); @@ -257,7 +255,6 @@ impl<'a, const A: bool, const B: usize, const C: usize, const D: usize> /// # Safety /// -/// TODO #[no_mangle] pub unsafe extern "C" fn init_cvec2() -> CVec2 { let mut buffer = Vec::::new(); @@ -278,7 +275,6 @@ pub unsafe extern "C" fn init_cvec2() -> CVec2 { /// as this can lead to double free errors when the message is dropped. /// # Safety /// -/// TODO #[no_mangle] pub unsafe extern "C" fn cvec2_push(cvec2: &mut CVec2, cvec: CVec) { let mut buffer: Vec = Vec::from_raw_parts(cvec2.data, cvec2.len, cvec2.capacity); diff --git a/protocols/v2/binary-sv2/no-serde-sv2/derive_codec/src/lib.rs b/protocols/v2/binary-sv2/no-serde-sv2/derive_codec/src/lib.rs index 44dd9681b..d154da0d6 100644 --- a/protocols/v2/binary-sv2/no-serde-sv2/derive_codec/src/lib.rs +++ b/protocols/v2/binary-sv2/no-serde-sv2/derive_codec/src/lib.rs @@ -65,6 +65,7 @@ fn parse_struct_fields(group: Vec) -> Vec { if p.to_string() == ":" { field_parser_state = ParserState::Type } else { + // Never executed at runtime it ok to panic panic!("Unexpected token '{}' in parsing {:#?}", p, field_); } } @@ -78,6 +79,7 @@ fn parse_struct_fields(group: Vec) -> Vec { field_.generics = "<".to_string(); field_parser_state = ParserState::Generics(0); } + // Never executed at runtime it ok to panic _ => panic!("Unexpected token '{}' in parsing {:#?}", p, field_), }, (TokenTree::Punct(p), ParserState::Generics(open_brackets)) => { @@ -102,6 +104,7 @@ fn parse_struct_fields(group: Vec) -> Vec { } } } + // Never executed at runtime it ok to panic _ => panic!("Unexpected token"), } } @@ -169,6 +172,7 @@ fn get_struct_properties(item: TokenStream) -> ParsedStruct { // Get the struct name let struct_name = match stream.next().expect("Struct has no name") { TokenTree::Ident(i) => i.to_string(), + // Never executed at runtime it ok to panic _ => panic!("Strcut has no name"), }; @@ -179,6 +183,7 @@ fn get_struct_properties(item: TokenStream) -> ParsedStruct { loop { match stream .next() + // Never executed at runtime it ok to panic .unwrap_or_else(|| panic!("Struct {} has no fields", struct_name)) { TokenTree::Group(g) => { @@ -191,6 +196,7 @@ fn get_struct_properties(item: TokenStream) -> ParsedStruct { TokenTree::Ident(i) => { struct_generics = format!("{}{}", struct_generics, i); } + // Never executed at runtime it ok to panic _ => panic!("Struct {} has no fields", struct_name), }; } @@ -215,7 +221,7 @@ pub fn decodable(item: TokenStream) -> TokenStream { " let {}: Vec = {}{}::get_structure(& data[offset..])?; offset += {}.size_hint_(&data, offset)?; - let {} = {}.into(); + let {} = {}.try_into()?; fields.push({}); ", f.name, @@ -240,7 +246,7 @@ pub fn decodable(item: TokenStream) -> TokenStream { for f in fields.clone() { let field = format!( " - {}: {}{}::from_decoded_fields(data.pop().unwrap().into())?, + {}: {}{}::from_decoded_fields(data.pop().ok_or(Error::NoDecodableFieldPassed)?.into())?, ", f.name, f.type_, @@ -285,8 +291,8 @@ pub fn decodable(item: TokenStream) -> TokenStream { derive_fields, derive_decoded_fields, ); - //println!("{}", result); + // Never executed at runtime it ok to panic result.parse().unwrap() } @@ -375,5 +381,6 @@ pub fn encodable(item: TokenStream) -> TokenStream { ); //println!("{}", result); + // Never executed at runtime it ok to panic result.parse().unwrap() } diff --git a/protocols/v2/codec-sv2/src/decoder.rs b/protocols/v2/codec-sv2/src/decoder.rs index 5ba7cb5da..3838eaee1 100644 --- a/protocols/v2/codec-sv2/src/decoder.rs +++ b/protocols/v2/codec-sv2/src/decoder.rs @@ -66,7 +66,7 @@ impl<'a, T: Serialize + GetSize + Deserialize<'a>, B: Buffer> WithNoise { let src = noise_frame.payload(); // DECRYPT THE ENCRYPTED PAYLOAD - let len = TransportMode::size_hint_decrypt(src.len()); + let len = TransportMode::size_hint_decrypt(src.len()).ok_or(())?; let decrypted = self.sv2_buffer.get_writable(len); transport_mode.read(src, decrypted).map_err(|_| ())?; diff --git a/protocols/v2/codec-sv2/src/encoder.rs b/protocols/v2/codec-sv2/src/encoder.rs index 055c45a7a..92814cbcd 100644 --- a/protocols/v2/codec-sv2/src/encoder.rs +++ b/protocols/v2/codec-sv2/src/encoder.rs @@ -149,7 +149,6 @@ impl NoiseEncoder { impl NoiseEncoder { pub fn new() -> Self { Self { - // TODO which capacity?? sv2_buffer: Vec::with_capacity(512), noise_buffer: Vec::with_capacity(512), frame: core::marker::PhantomData, @@ -183,7 +182,6 @@ impl Encoder { pub fn new() -> Self { Self { - // TODO which capacity?? buffer: Vec::with_capacity(512), frame: core::marker::PhantomData, } diff --git a/protocols/v2/codec-sv2/src/error.rs b/protocols/v2/codec-sv2/src/error.rs index 9a7a24c04..2e689b515 100644 --- a/protocols/v2/codec-sv2/src/error.rs +++ b/protocols/v2/codec-sv2/src/error.rs @@ -6,13 +6,6 @@ pub enum Error { pub type Result = core::result::Result; -//#[cfg(not(feature = "no_std"))] -//impl From for Error { -// fn from(_: core::io::Error) -> Self { -// todo!() -// } -//} - impl From<()> for Error { fn from(_: ()) -> Self { Error::Todo diff --git a/protocols/v2/const-sv2/src/lib.rs b/protocols/v2/const-sv2/src/lib.rs index e44077217..d19f5d923 100644 --- a/protocols/v2/const-sv2/src/lib.rs +++ b/protocols/v2/const-sv2/src/lib.rs @@ -37,13 +37,13 @@ pub const MESSAGE_TYPE_SUBMIT_SOLUTION: u8 = 0x76; // JOB NEGOTIATION PROTOCOL MESSAGES TYPES pub const MESSAGE_TYPE_ALLOCATE_MINING_JOB_TOKEN: u8 = 0x50; pub const MESSAGE_TYPE_ALLOCATE_MINING_JOB_SUCCESS: u8 = 0x51; -// pub const MESSAGE_TYPE_ALLOCATE_MINING_JOB_ERROR: u8 = 0x52; // TODO is on the message type +// pub const MESSAGE_TYPE_ALLOCATE_MINING_JOB_ERROR: u8 = 0x52; is on the message type // table but is not defined as message pub const MESSAGE_TYPE_IDENTIFY_TRANSACTIONS: u8 = 0x53; pub const MESSAGE_TYPE_IDENTIFY_TRANSACTIONS_SUCCESS: u8 = 0x54; pub const MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTION: u8 = 0x55; pub const MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTION_SUCCESS: u8 = 0x56; -// TODO not in messages type table !!! +// not in messages type table !!! pub const MESSAGE_TYPE_COMMIT_MINING_JOB: u8 = 0x57; pub const MESSAGE_TYPE_COMMIT_MINING_JOB_SUCCESS: u8 = 0x58; pub const MESSAGE_TYPE_COMMIT_MINING_JOB_ERROR: u8 = 0x59; @@ -53,7 +53,7 @@ pub const MESSAGE_TYPE_NEW_EXTENDED_MINING_JOB: u8 = 0x1f; pub const MESSAGE_TYPE_NEW_MINING_JOB: u8 = 0x1e; pub const MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL: u8 = 0x13; pub const MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL_SUCCES: u8 = 0x14; -// TODO in the spec page 21 is defined OpenMiningChannelError valid for both extended and standard +// in the spec page 21 is defined OpenMiningChannelError valid for both extended and standard // messages but in the spec page 40 are defined two different message types for // OpenStandardMiningChannelError and OpenExtendedMiningChannelError pub const MESSAGE_TYPE_OPEN_MINING_CHANNEL_ERROR: u8 = 0x12; @@ -90,13 +90,13 @@ pub const CHANNEL_BIT_SUBMIT_SOLUTION: bool = false; // JOB NEGOTIATION PROTOCOL MESSAGES CHANNEL BIT pub const CHANNEL_BIT_ALLOCATE_MINING_JOB_TOKEN: bool = false; pub const CHANNEL_BIT_ALLOCATE_MINING_JOB_SUCCESS: bool = false; -pub const CHANNEL_BIT_ALLOCATE_MINING_JOB_ERROR: bool = false; // TODO is on the message type +pub const CHANNEL_BIT_ALLOCATE_MINING_JOB_ERROR: bool = false; // is on the message type // table but is not defined as message pub const CHANNEL_BIT_IDENTIFY_TRANSACTIONS: bool = false; pub const CHANNEL_BIT_IDENTIFY_TRANSACTIONS_SUCCESS: bool = false; pub const CHANNEL_BIT_PROVIDE_MISSING_TRANSACTION: bool = false; pub const CHANNEL_BIT_PROVIDE_MISSING_TRANSACTION_SUCCESS: bool = false; -// TODO not in messages type table !!! +// Not in messages type table !!! pub const CHANNEL_BIT_COMMIT_MINING_JOB: bool = false; pub const CHANNEL_BIT_COMMIT_MINING_JOB_SUCCESS: bool = false; pub const CHANNEL_BIT_COMMIT_MINING_JOB_ERROR: bool = false; @@ -106,7 +106,7 @@ pub const CHANNEL_BIT_NEW_EXTENDED_MINING_JOB: bool = true; pub const CHANNEL_BIT_NEW_MINING_JOB: bool = true; pub const CHANNEL_BIT_OPEN_EXTENDED_MINING_CHANNEL: bool = false; pub const CHANNEL_BIT_OPEN_EXTENDED_MINING_CHANNEL_SUCCES: bool = false; -// TODO in the spec page 21 is defined OpenMiningChannelError valid for both extended and standard +// in the spec page 21 is defined OpenMiningChannelError valid for both extended and standard // messages but in the spec page 40 are defined two different message types for // OpenStandardMiningChannelError and OpenExtendedMiningChannelError pub const CHANNEL_BIT_OPEN_MINING_CHANNEL_ERROR: bool = false; diff --git a/protocols/v2/framing-sv2/src/framing2.rs b/protocols/v2/framing-sv2/src/framing2.rs index 4fc63655b..581920f0e 100644 --- a/protocols/v2/framing-sv2/src/framing2.rs +++ b/protocols/v2/framing-sv2/src/framing2.rs @@ -59,7 +59,7 @@ pub trait Frame<'a, T: Serialize + GetSize>: Sized { pub struct Sv2Frame { header: Header, payload: Option, - /// Serializsed header + payload (TODO check if this is correct) + /// Serializsed header + payload serialized: Option, } @@ -75,6 +75,7 @@ impl Default for Sv2Frame { #[derive(Debug)] pub struct NoiseFrame { + #[allow(dead_code)] header: u16, payload: Vec, } @@ -89,19 +90,22 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for /// itself #[inline] fn serialize(self, dst: &mut Self::Buffer) -> Result<(), binary_sv2::Error> { - if self.serialized.is_some() { - *dst = self.serialized.unwrap(); + if let Some(serialized) = self.serialized { + *dst = serialized; Ok(()) - } else { + } else if let Some(payload) = self.payload { #[cfg(not(feature = "with_serde"))] to_writer(self.header, dst.as_mut())?; #[cfg(not(feature = "with_serde"))] - to_writer(self.payload.unwrap(), &mut dst.as_mut()[Header::SIZE..])?; + to_writer(payload, &mut dst.as_mut()[Header::SIZE..])?; #[cfg(feature = "with_serde")] to_writer(&self.header, dst.as_mut())?; #[cfg(feature = "with_serde")] - to_writer(&self.payload.unwrap(), &mut dst.as_mut()[Header::SIZE..])?; + to_writer(payload, &mut dst.as_mut()[Header::SIZE..])?; Ok(()) + } else { + // Sv2Frame always has a payload or a serialized payload + panic!("Impossible state") } } @@ -109,12 +113,14 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for // deserialized it contain the rust type that represant the Sv2 message. If the type is // deserialized self.paylos.is_some() is true. To get the serialized payload the inner type // should be serialized and this function should never be used, cause is intended as a fast - // function that return a reference to an already serialized payload. For that for now is a todo. + // function that return a reference to an already serialized payload. For that the function + // panic. fn payload(&'a mut self) -> &'a mut [u8] { - if self.payload.is_some() { - todo!() + if let Some(serialized) = self.serialized.as_mut() { + &mut serialized.as_mut()[Header::SIZE..] } else { - &mut self.serialized.as_mut().unwrap().as_mut()[Header::SIZE..] + // panic here is the expected behaviour + panic!() } } @@ -140,7 +146,8 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for #[inline] fn from_bytes_unchecked(mut bytes: Self::Buffer) -> Self { - let header = Header::from_bytes(bytes.as_mut()).unwrap(); + // Unchecked function caller is supposed to already know that the passed bytes are valid + let header = Header::from_bytes(bytes.as_mut()).expect("Invalid header"); Self { header, payload: None, @@ -164,10 +171,13 @@ impl<'a, T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<'a, T> for #[inline] fn encoded_length(&self) -> usize { - if self.serialized.is_some() { - self.serialized.as_ref().unwrap().as_ref().len() + if let Some(serialized) = self.serialized.as_ref() { + serialized.as_ref().len() + } else if let Some(payload) = self.payload.as_ref() { + payload.get_size() + Header::SIZE } else { - self.payload.as_ref().unwrap().get_size() + Header::SIZE + // Sv2Frame always has a payload or a serialized payload + panic!("Impossible state") } } @@ -219,12 +229,9 @@ impl<'a> Frame<'a, Vec> for NoiseFrame { None } - /// Try to build a Frame frame from raw bytes. - /// It return the frame or the number of the bytes needed to complete the frame - /// The resulting frame is just a header plus a payload with the right number of bytes nothing - /// is said about the correctness of the payload - fn from_bytes(_bytes: Self::Buffer) -> Result { - unimplemented!() + // For a NoiseFrame from_bytes is the same of from_bytes_unchecked + fn from_bytes(bytes: Self::Buffer) -> Result { + Ok(Self::from_bytes_unchecked(bytes)) } #[inline] @@ -299,16 +306,7 @@ pub enum EitherFrame { Sv2(Sv2Frame), } -//impl - impl + AsRef<[u8]>> EitherFrame { - //pub fn serialize(mut self, dst: &mut B) -> Result<(), serde_sv2::Error> { - // match self { - // Self::HandShake(frame) => todo!(), - // Self::Sv2(frame) => frame.serialize(dst), - // } - //} - pub fn encoded_length(&self) -> usize { match &self { Self::HandShake(frame) => frame.encoded_length(), diff --git a/protocols/v2/framing-sv2/src/header.rs b/protocols/v2/framing-sv2/src/header.rs index c47c12ea8..391a8b459 100644 --- a/protocols/v2/framing-sv2/src/header.rs +++ b/protocols/v2/framing-sv2/src/header.rs @@ -7,16 +7,17 @@ use core::convert::TryInto; #[derive(Debug, Serialize, Deserialize, Copy, Clone)] pub struct Header { - extesion_type: u16, // TODO use specific type? - msg_type: u8, // TODO use specific type? + extension_type: u16, // TODO use specific type? + msg_type: u8, // TODO use specific type? msg_length: U24, } impl Default for Header { fn default() -> Self { Header { - extesion_type: 0, + extension_type: 0, msg_type: 0, + // converting 0_32 into a U24 never panic msg_length: 0_u32.try_into().unwrap(), } } @@ -35,35 +36,31 @@ impl Header { return Err((Self::SIZE - bytes.len()) as isize); }; - // TODO remove hardcoded - let extesion_type = u16::from_le_bytes([bytes[0], bytes[1]]); + let extension_type = u16::from_le_bytes([bytes[0], bytes[1]]); let msg_type = bytes[2]; let msg_length = u32::from_le_bytes([bytes[3], bytes[4], bytes[5], 0]); Ok(Self { - extesion_type, + extension_type, msg_type, - // TODO + // Converting and u32 with the most significant byte set to 0 to and U24 never panic msg_length: msg_length.try_into().unwrap(), }) } + #[allow(clippy::len_without_is_empty)] #[inline] pub fn len(&self) -> usize { let inner: u32 = self.msg_length.into(); inner as usize } - pub fn is_empty(&self) -> bool { - unimplemented!() - } - #[inline] pub fn from_len(len: u32, message_type: u8, extension_type: u16) -> Option
{ Some(Self { - extesion_type: extension_type, + extension_type, msg_type: message_type, - msg_length: len.try_into().unwrap(), + msg_length: len.try_into().ok()?, }) } @@ -73,7 +70,7 @@ impl Header { pub fn channel_msg(&self) -> bool { let mask = 0b0000_0000_0000_0001; - self.extesion_type & mask == self.extesion_type + self.extension_type & mask == self.extension_type } } diff --git a/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs b/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs index 67ac86c4e..5812dba81 100644 --- a/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs +++ b/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs @@ -3,10 +3,11 @@ use alloc::vec::Vec; #[cfg(not(feature = "with_serde"))] use binary_sv2::binary_codec_sv2; use binary_sv2::{Deserialize, Serialize}; +use core::convert::TryInto; /// ## ChannelEndpointChanged (Server -> Client) /// When a channel’s upstream or downstream endpoint changes and that channel had previously -/// sent messages with [channel_msg](TODO) bitset of unknown extension_type, the intermediate proxy +/// sent messages with [channel_msg] bitset of unknown extension_type, the intermediate proxy /// MUST send a [`ChannelEndpointChanged`] message. Upon receipt thereof, any extension state /// (including version negotiation and the presence of support for a given extension) MUST be /// reset and version/presence negotiation must begin again. diff --git a/protocols/v2/subprotocols/common-messages/src/lib.rs b/protocols/v2/subprotocols/common-messages/src/lib.rs index c900182c9..33b2baf2b 100644 --- a/protocols/v2/subprotocols/common-messages/src/lib.rs +++ b/protocols/v2/subprotocols/common-messages/src/lib.rs @@ -42,10 +42,6 @@ impl ChannelEndpointChanged { impl SetupConnection<'static> { pub fn from_gen(g: &mut Gen) -> Self { let protocol = setup_connection::Protocol::MiningProtocol; - // TODO: test each Protocol variant - // let protocol = setup_connection::Protocol::JobDistributionProtocol; - // let protocol = setup_connection::Protocol::TemplateDistributionProtocol; - // let protocol = setup_connection::Protocol::JobNegotiationProtocol; let mut endpoint_host_gen = Gen::new(255); let mut endpoint_host: vec::Vec = vec::Vec::new(); diff --git a/protocols/v2/subprotocols/common-messages/src/setup_connection.rs b/protocols/v2/subprotocols/common-messages/src/setup_connection.rs index 0f38b83c4..9791e6478 100644 --- a/protocols/v2/subprotocols/common-messages/src/setup_connection.rs +++ b/protocols/v2/subprotocols/common-messages/src/setup_connection.rs @@ -76,6 +76,7 @@ impl<'decoder> SetupConnection<'decoder> { work_selection && version_rolling } + // TODO _ => todo!(), } } @@ -216,7 +217,7 @@ pub struct SetupConnectionSuccess { pub struct SetupConnectionError<'decoder> { /// Flags indicating features causing an error. pub flags: u32, - /// Human-readable error code(s). See Error Codes section, [link](TODO). + /// Human-readable error code(s). See Error Codes section, [link]. /// ### Possible error codes: /// * ‘unsupported-feature-flags’ /// * ‘unsupported-protocol’ @@ -304,9 +305,10 @@ impl<'decoder> binary_sv2::Decodable<'decoder> for Protocol { fn from_decoded_fields( mut v: alloc::vec::Vec>, ) -> core::result::Result { - let val = v.pop().unwrap(); - let val: u8 = val.try_into().unwrap(); - Ok(val.try_into().unwrap()) + let val = v.pop().ok_or(binary_sv2::Error::NoDecodableFieldPassed)?; + let val: u8 = val.try_into()?; + val.try_into() + .map_err(|_| binary_sv2::Error::ValueIsNotAValidProtocol(val)) } } diff --git a/protocols/v2/subprotocols/template-distribution/src/coinbase_output_data_size.rs b/protocols/v2/subprotocols/template-distribution/src/coinbase_output_data_size.rs index d82cabc30..ec2fda89e 100644 --- a/protocols/v2/subprotocols/template-distribution/src/coinbase_output_data_size.rs +++ b/protocols/v2/subprotocols/template-distribution/src/coinbase_output_data_size.rs @@ -3,6 +3,7 @@ use alloc::vec::Vec; #[cfg(not(feature = "with_serde"))] use binary_sv2::binary_codec_sv2; use binary_sv2::{Deserialize, Serialize}; +use core::convert::TryInto; /// ## CoinbaseOutputDataSize (Client -> Server) /// Ultimately, the pool is responsible for adding coinbase transaction outputs for payouts and diff --git a/protocols/v2/subprotocols/template-distribution/src/lib.rs b/protocols/v2/subprotocols/template-distribution/src/lib.rs index 1b5c237f0..b0fc4646e 100644 --- a/protocols/v2/subprotocols/template-distribution/src/lib.rs +++ b/protocols/v2/subprotocols/template-distribution/src/lib.rs @@ -2,13 +2,13 @@ //! # Template Distribution Protocol //! The Template Distribution protocol is used to receive updates of the block template to use in -//! mining the next block. It effectively replaces BIPs [22](TODO) and [23](TODO) (getblocktemplate) and provides +//! mining the next block. It effectively replaces BIPs [22] and [23] (getblocktemplate) and provides //! a much more efficient API which allows Bitcoin Core (or some other full node software) to push //! template updates at more appropriate times as well as provide a template which may be //! mined on quickly for the block-after-next. While not recommended, the template update //! protocol can be a remote server, and is thus authenticated and signed in the same way as all -//! other protocols ([using the same SetupConnection handshake][TODO]). -//! Like the [Job Negotiation](TODO) and [Job Distribution](TODO) (sub)protocols, all Template Distribution messages +//! other protocols ([using the same SetupConnection handshake]). +//! Like the [Job Negotiation] and [Job Distribution] (sub)protocols, all Template Distribution messages //! have the channel_msg bit unset, and there is no concept of channels. After the initial common //! handshake, the client MUST immediately send a [`CoinbaseOutputDataSize`] message to indicate //! the space it requires for coinbase output addition, to which the server MUST immediately reply diff --git a/protocols/v2/subprotocols/template-distribution/src/new_template.rs b/protocols/v2/subprotocols/template-distribution/src/new_template.rs index 03ee81720..bf24db80a 100644 --- a/protocols/v2/subprotocols/template-distribution/src/new_template.rs +++ b/protocols/v2/subprotocols/template-distribution/src/new_template.rs @@ -22,7 +22,7 @@ pub struct NewTemplate<'decoder> { /// should start to work on the job immediately. pub future_template: bool, /// Valid header version field that reflects the current network - /// consensus. The general purpose bits (as specified in [BIP320](TODO link)) can + /// consensus. The general purpose bits (as specified in [BIP320]) can /// be freely manipulated by the downstream node. The downstream /// node MUST NOT rely on the upstream node to set the BIP320 bits /// to any particular value. diff --git a/protocols/v2/subprotocols/template-distribution/src/request_transaction_data.rs b/protocols/v2/subprotocols/template-distribution/src/request_transaction_data.rs index d2a3a82e1..f0727d8bb 100644 --- a/protocols/v2/subprotocols/template-distribution/src/request_transaction_data.rs +++ b/protocols/v2/subprotocols/template-distribution/src/request_transaction_data.rs @@ -12,7 +12,7 @@ use core::convert::TryInto; /// A request sent by the Job Negotiator to the Template Provider which requests the set of /// transaction data for all transactions (excluding the coinbase transaction) included in a block, as /// well as any additional data which may be required by the Pool to validate the work. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Copy)] #[repr(C)] pub struct RequestTransactionData { /// The template_id corresponding to a NewTemplate message. @@ -45,7 +45,7 @@ pub struct RequestTransactionData { /// changed in non-compatible ways at the time a fork activates, given sufficient time from /// code-release to activation (as any sane fork would have to have) and there being some /// in-Template Negotiation Protocol signaling of support for the new fork (e.g. for soft-forks -/// activated using [BIP 9](TODO link)). +/// activated using [BIP 9]). #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct RequestTransactionDataSuccess<'decoder> { /// The template_id corresponding to a NewTemplate/RequestTransactionData message. diff --git a/protocols/v2/subprotocols/template-distribution/src/set_new_prev_hash.rs b/protocols/v2/subprotocols/template-distribution/src/set_new_prev_hash.rs index 7f28ba0b9..ece65c9c5 100644 --- a/protocols/v2/subprotocols/template-distribution/src/set_new_prev_hash.rs +++ b/protocols/v2/subprotocols/template-distribution/src/set_new_prev_hash.rs @@ -10,8 +10,8 @@ use core::convert::TryInto; /// ## SetNewPrevHash (Server -> Client) /// Upon successful validation of a new best block, the server MUST immediately provide a -/// SetNewPrevHash message. If a [NewWork](TODO link) message has previously been sent with the -/// [future_job](TODO link) flag set, which is valid work based on the prev_hash contained in this message, the +/// SetNewPrevHash message. If a [NewWork] message has previously been sent with the +/// [future_job] flag set, which is valid work based on the prev_hash contained in this message, the /// template_id field SHOULD be set to the job_id present in that NewTemplate message /// indicating the client MUST begin mining on that template as soon as possible. /// TODO: Define how many previous works the client has to track (2? 3?), and require that the diff --git a/protocols/v2/subprotocols/template-distribution/src/submit_solution.rs b/protocols/v2/subprotocols/template-distribution/src/submit_solution.rs index f011a3b76..5acbfd2e2 100644 --- a/protocols/v2/subprotocols/template-distribution/src/submit_solution.rs +++ b/protocols/v2/subprotocols/template-distribution/src/submit_solution.rs @@ -17,8 +17,8 @@ use core::convert::TryInto; pub struct SubmitSolution<'decoder> { /// The template_id field as it appeared in NewTemplate. pub template_id: u64, - /// The version field in the block header. Bits not defined by [BIP320](TODO link) as - /// additional nonce MUST be the same as they appear in the [NewWork](TODO link) + /// The version field in the block header. Bits not defined by [BIP320] as + /// additional nonce MUST be the same as they appear in the [NewWork] /// message, other bits may be set to any value. pub version: u32, /// The nTime field in the block header. This MUST be greater than or equal diff --git a/protocols/v2/sv2-ffi/src/lib.rs b/protocols/v2/sv2-ffi/src/lib.rs index a0323477d..f8dcc0118 100644 --- a/protocols/v2/sv2-ffi/src/lib.rs +++ b/protocols/v2/sv2-ffi/src/lib.rs @@ -111,7 +111,7 @@ pub extern "C" fn drop_sv2_message(s: CSv2Message) { match s { CSv2Message::CoinbaseOutputDataSize(_) => (), CSv2Message::NewTemplate(a) => drop(a), - CSv2Message::RequestTransactionData(a) => drop(a), + CSv2Message::RequestTransactionData(_) => (), CSv2Message::RequestTransactionDataError(a) => drop(a), CSv2Message::RequestTransactionDataSuccess(a) => drop(a), CSv2Message::SetNewPrevHash(a) => drop(a), @@ -156,7 +156,18 @@ impl<'a> CSv2Message { Ok(Sv2Message::SetupConnectionError(v.to_rust_rep_mut()?)) } CSv2Message::SetupConnectionSuccess(v) => Ok(Sv2Message::SetupConnectionSuccess(*v)), - _ => todo!(), + CSv2Message::CoinbaseOutputDataSize(v) => Ok(Sv2Message::CoinbaseOutputDataSize(*v)), + CSv2Message::RequestTransactionData(v) => Ok(Sv2Message::RequestTransactionData(*v)), + CSv2Message::RequestTransactionDataError(v) => Ok( + Sv2Message::RequestTransactionDataError(v.to_rust_rep_mut()?), + ), + CSv2Message::RequestTransactionDataSuccess(v) => Ok( + Sv2Message::RequestTransactionDataSuccess(v.to_rust_rep_mut()?), + ), + CSv2Message::ChannelEndpointChanged(v) => Ok(Sv2Message::ChannelEndpointChanged(*v)), + CSv2Message::SetupConnection(v) => { + Ok(Sv2Message::SetupConnection(v.to_rust_rep_mut()?)) + } } } } @@ -258,7 +269,7 @@ impl<'a> TryFrom<(u8, &'a mut [u8])> for Sv2Message<'a> { let message: SubmitSolution = from_bytes(v.1)?; Ok(Sv2Message::SubmitSolution(message)) } - _ => panic!(), + _ => Err(Error::UnknownMessageType(msg_type)), } } } @@ -275,6 +286,7 @@ pub enum Sv2Error { EncoderBusy, Todo, Unknown, + InvalidSv2Frame, } #[no_mangle] @@ -346,7 +358,6 @@ pub extern "C" fn free_decoder(decoder: *mut DecoderWrapper) { /// # Safety /// -/// TODO #[no_mangle] pub unsafe extern "C" fn encode( message: &'static mut CSv2Message, @@ -391,7 +402,10 @@ pub extern "C" fn next_frame(decoder: *mut DecoderWrapper) -> CResult { - let msg_type = f.get_header().unwrap().msg_type(); + let msg_type = match f.get_header() { + Some(header) => header.msg_type(), + None => return CResult::Err(Sv2Error::InvalidSv2Frame), + }; let payload = f.payload(); let len = payload.len(); let ptr = payload.as_mut_ptr(); diff --git a/protocols/v2/sv2-ffi/sv2.h b/protocols/v2/sv2-ffi/sv2.h index 47503aa8f..f9e559a9c 100644 --- a/protocols/v2/sv2-ffi/sv2.h +++ b/protocols/v2/sv2-ffi/sv2.h @@ -227,19 +227,16 @@ extern "C" { /// /// # Safety /// -/// TODO CVec cvec_from_buffer(const uint8_t *data, uintptr_t len); /// # Safety /// -/// TODO CVec2 init_cvec2(); /// The caller is reponsible for NOT adding duplicate cvecs to the cvec2 structure, /// as this can lead to double free errors when the message is dropped. /// # Safety /// -/// TODO void cvec2_push(CVec2 *cvec2, CVec cvec); void _c_export_u24(U24 _a); @@ -268,7 +265,7 @@ enum class Protocol : uint8_t { /// ## ChannelEndpointChanged (Server -> Client) /// When a channel’s upstream or downstream endpoint changes and that channel had previously -/// sent messages with [channel_msg](TODO) bitset of unknown extension_type, the intermediate proxy +/// sent messages with [channel_msg] bitset of unknown extension_type, the intermediate proxy /// MUST send a [`ChannelEndpointChanged`] message. Upon receipt thereof, any extension state /// (including version negotiation and the presence of support for a given extension) MUST be /// reset and version/presence negotiation must begin again. @@ -424,6 +421,7 @@ enum class Sv2Error { EncoderBusy, Todo, Unknown, + InvalidSv2Frame, }; struct DecoderWrapper; @@ -541,7 +539,6 @@ void free_decoder(DecoderWrapper *decoder); /// # Safety /// -/// TODO CResult encode(CSv2Message *message, EncoderWrapper *encoder); DecoderWrapper *new_decoder();