Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion stratum-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ keywords = ["stratum", "mining", "bitcoin", "protocol"]
buffer_sv2 = { path = "../sv2/buffer-sv2", version = "^3.0.0" }
bitcoin = "0.32.5"
binary_sv2 = { path = "../sv2/binary-sv2", version = "^5.0.0" }
codec_sv2 = { path = "../sv2/codec-sv2", version = "^4.0.0", features = ["noise_sv2"]}
codec_sv2 = { path = "../sv2/codec-sv2", version = "^5.0.0", features = ["noise_sv2"]}
extensions_sv2 = { path = "../sv2/extensions-sv2", version = "^0.1.0" }
framing_sv2 = { path = "../sv2/framing-sv2", version = "^6.0.0" }
noise_sv2 = { path = "../sv2/noise-sv2", version = "^1.0.0" }
Expand Down
2 changes: 1 addition & 1 deletion sv2/codec-sv2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "codec_sv2"
version = "4.0.1"
version = "5.0.0"
authors = ["The Stratum V2 Developers"]
edition = "2021"
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion sv2/codec-sv2/examples/unencrypted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn sender_side(

// Send the encoded frame
stream_sender
.write_all(encoded_frame)
.write_all(encoded_frame.as_ref())
.expect("Failed to send the encoded frame");
}

Expand Down
87 changes: 40 additions & 47 deletions sv2/codec-sv2/src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
// - If the feature is not enabled, a system memory buffer [`binary_sv2::BufferFromSystemMemory`] is
// used for simpler applications where memory efficiency is less critical.

use alloc::vec::Vec;
use binary_sv2::{GetSize, Serialize};
#[cfg(feature = "noise_sv2")]
use core::convert::TryInto;
use core::marker::PhantomData;
use framing_sv2::framing::Sv2Frame;

#[cfg(feature = "noise_sv2")]
use buffer_sv2::AeadBuffer;
#[cfg(feature = "noise_sv2")]
use core::convert::TryInto;
#[cfg(feature = "noise_sv2")]
use framing_sv2::framing::{Frame, HandShakeFrame};
#[cfg(feature = "noise_sv2")]
Expand All @@ -40,11 +42,9 @@ use tracing::error;
#[cfg(feature = "noise_sv2")]
use crate::{Error, Result, State};

#[cfg(feature = "noise_sv2")]
#[cfg(not(feature = "with_buffer_pool"))]
use buffer_sv2::{Buffer as IsBuffer, BufferFromSystemMemory as Buffer};

#[cfg(feature = "noise_sv2")]
#[cfg(feature = "with_buffer_pool")]
use buffer_sv2::{Buffer as IsBuffer, BufferFromSystemMemory, BufferPool};

Expand All @@ -57,48 +57,40 @@ use buffer_sv2::{Buffer as IsBuffer, BufferFromSystemMemory, BufferPool};
//
// `Buffer` is utilized for storing both serialized Sv2 frames and encrypted Noise data during the
// encoding process, ensuring that all frames are correctly handled before transmission.
#[cfg(feature = "noise_sv2")]
#[cfg(feature = "with_buffer_pool")]
type Buffer = BufferPool<BufferFromSystemMemory>;

// A simple buffer slice for holding serialized Sv2 frame data before transmission.
//
// When the `with_buffer_pool` feature is disabled, [`Slice`] defaults to a `Vec<u8>`, which serves
// as a dynamically allocated array to hold the serialized bytes of Sv2 frames. This provides
// flexibility in managing the encoded data during transmission or further processing, though it
// may not offer the same memory efficiency as the pool-allocated version [`BufferPool`].
#[cfg(not(feature = "with_buffer_pool"))]
type Slice = Vec<u8>;
/// Standard Sv2 encoder with Noise protocol support.
///
/// Used for decoding generic message types (`T`) encoded in Sv2 frames.
#[cfg(feature = "noise_sv2")]
pub type NoiseEncoder<T> = WithNoise<Buffer, T>;

// A buffer slice used for holding serialized Sv2 frame data before transmission.
//
// When the `with_buffer_pool` feature is enabled, [`Slice`] defaults to a `buffer_sv2::Slice`,
// which serves as a slice of the `Buffer` that stores the encoded data. It holds the frame's
// serialized bytes temporarily, ensuring the data is ready for transmission or encryption,
// depending on whether Noise protocol support is enabled.
#[cfg(feature = "with_buffer_pool")]
type Slice = buffer_sv2::Slice;
/// Standard Sv2 encoder without Noise protocol support.
///
/// Used for decoding generic message types (`T`) encoded in Sv2 frames.
pub type Encoder<T> = WithoutNoise<Buffer, T>;

/// Encoder for Sv2 frames with Noise protocol encryption.
///
/// Serializes the Sv2 frame into a dedicated buffer. Encrypts this serialized data using the Noise
/// protocol, storing it into another dedicated buffer. Encodes the serialized and encrypted data,
/// such that it is ready for transmission.
#[cfg(feature = "noise_sv2")]
pub struct NoiseEncoder<T: Serialize + binary_sv2::GetSize> {
pub struct WithNoise<B: IsBuffer, T: Serialize + binary_sv2::GetSize> {
// Buffer for holding encrypted Noise data to be transmitted.
//
// Stores the encrypted data after the Sv2 frame has been processed by the Noise protocol
// and is ready for transmission. This buffer holds the outgoing encrypted data, ensuring
// that the full frame is correctly prepared before being sent.
noise_buffer: Buffer,
noise_buffer: B,

// Buffer for holding serialized Sv2 data before encryption.
//
// Stores the data after it has been serialized into an Sv2 frame but before it is encrypted
// by the Noise protocol. The buffer accumulates the frame's serialized bytes before they are
// encrypted and then encoded for transmission.
sv2_buffer: Buffer,
sv2_buffer: B,

// Marker for the type of frame being encoded.
//
Expand All @@ -117,10 +109,10 @@ pub struct NoiseEncoder<T: Serialize + binary_sv2::GetSize> {
// which either processes it for normal transmission or applies Noise encryption, depending on the
// codec's state.
#[cfg(feature = "noise_sv2")]
type Item<T> = Frame<T, Slice>;
type Item<T, B> = Frame<T, <B as IsBuffer>::Slice>;

#[cfg(feature = "noise_sv2")]
impl<T: Serialize + GetSize> NoiseEncoder<T> {
impl<B: IsBuffer + AeadBuffer, T: Serialize + GetSize> WithNoise<B, T> {
/// Encodes an Sv2 frame and encrypts it using the Noise protocol.
///
/// Takes an `item`, which is an Sv2 frame containing a payload of type `T`, and encodes it for
Expand All @@ -136,14 +128,14 @@ impl<T: Serialize + GetSize> NoiseEncoder<T> {
/// On success, the method returns an encrypted (`Slice`) (buffer) ready for transmission.
/// Otherwise, errors on an encryption or serialization failure.
#[inline]
pub fn encode(&mut self, item: Item<T>, state: &mut State) -> Result<Slice> {
pub fn encode(&mut self, item: Item<T, B>, state: &mut State) -> Result<B::Slice> {
match state {
State::Transport(noise_codec) => {
let len = item.encoded_length();
let writable = self.sv2_buffer.get_writable(len);

// ENCODE THE SV2 FRAME
let i: Sv2Frame<T, Slice> = item.try_into().map_err(|e| {
let i: Sv2Frame<T, B::Slice> = item.try_into().map_err(|e| {
#[cfg(feature = "tracing")]
error!("Error while encoding 1 frame: {:?}", e);
Error::FramingError(e)
Expand Down Expand Up @@ -196,7 +188,7 @@ impl<T: Serialize + GetSize> NoiseEncoder<T> {
// and set up the Noise encryption state before transitioning to the transport phase, where
// full frames are encrypted and transmitted.
#[inline(never)]
fn while_handshaking(&mut self, item: Item<T>) -> Result<()> {
fn while_handshaking(&mut self, item: Item<T, B>) -> Result<()> {
// ENCODE THE SV2 FRAME
let i: HandShakeFrame = item.try_into().map_err(|e| {
#[cfg(feature = "tracing")]
Expand All @@ -218,7 +210,7 @@ impl<T: Serialize + GetSize> NoiseEncoder<T> {
}

#[cfg(feature = "noise_sv2")]
impl<T: Serialize + binary_sv2::GetSize> NoiseEncoder<T> {
impl<T: Serialize + binary_sv2::GetSize> WithNoise<Buffer, T> {
/// Creates a new `NoiseEncoder` with default buffer sizes.
pub fn new() -> Self {
#[cfg(not(feature = "with_buffer_pool"))]
Expand All @@ -234,7 +226,7 @@ impl<T: Serialize + binary_sv2::GetSize> NoiseEncoder<T> {
}

#[cfg(feature = "noise_sv2")]
impl<T: Serialize + GetSize> Default for NoiseEncoder<T> {
impl<T: Serialize + GetSize> Default for WithNoise<Buffer, T> {
fn default() -> Self {
Self::new()
}
Expand All @@ -245,13 +237,13 @@ impl<T: Serialize + GetSize> Default for NoiseEncoder<T> {
/// Serializes the Sv2 frame into a dedicated buffer then encodes it, such that it is ready for
/// transmission.
#[derive(Debug)]
pub struct Encoder<T> {
pub struct WithoutNoise<B: IsBuffer, T> {
// Buffer for holding serialized Sv2 data.
//
// Stores the serialized bytes of the Sv2 frame after it has been encoded. Once the frame is
// serialized, the resulting bytes are stored in this buffer to be transmitted. The buffer is
// dynamically resized to accommodate the size of the encoded frame.
buffer: Vec<u8>,
buffer: B,

// Marker for the type of frame being encoded.
//
Expand All @@ -263,7 +255,7 @@ pub struct Encoder<T> {
frame: PhantomData<T>,
}

impl<T: Serialize + GetSize> Encoder<T> {
impl<B: IsBuffer, T: Serialize + GetSize> WithoutNoise<B, T> {
/// Encodes a standard Sv2 frame for transmission.
///
/// Takes a standard Sv2 frame containing a payload of type `T` and serializes it into a byte
Expand All @@ -272,28 +264,29 @@ impl<T: Serialize + GetSize> Encoder<T> {
/// stored in the internal buffer. Otherwise, errors on a serialization failure.
pub fn encode(
&mut self,
item: Sv2Frame<T, Slice>,
) -> core::result::Result<&[u8], crate::Error> {
item: Sv2Frame<T, B::Slice>,
) -> core::result::Result<B::Slice, crate::Error> {
let len = item.encoded_length();
let writable = self.buffer.get_writable(len);

self.buffer.resize(len, 0);
item.serialize(writable)?;

item.serialize(&mut self.buffer)?;
Ok(self.buffer.get_data_owned())
}
}

Ok(&self.buffer[..])
impl<T: Serialize + GetSize> Default for WithoutNoise<Buffer, T> {
fn default() -> Self {
Self::new()
}
}

impl<T: Serialize + GetSize> WithoutNoise<Buffer, T> {
/// Creates a new `Encoder` with a buffer of default size.
pub fn new() -> Self {
Self {
buffer: Vec::with_capacity(512),
buffer: Buffer::new(512),
frame: core::marker::PhantomData,
}
}
}

impl<T: Serialize + GetSize> Default for Encoder<T> {
fn default() -> Self {
Self::new()
}
}
Loading