Skip to content

Commit

Permalink
Merge pull request stratum-mining#1346 from GPTechinno/codec_sv2_no_std
Browse files Browse the repository at this point in the history
`codec_sv2` with optional `no_std`
  • Loading branch information
plebhash authored Jan 20, 2025
2 parents a306512 + b1ac9ea commit ad01bdf
Show file tree
Hide file tree
Showing 17 changed files with 135 additions and 40 deletions.
9 changes: 7 additions & 2 deletions examples/ping-pong-with-noise/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ping_pong_with_noise"
version = "0.1.0"
version = "0.1.1"
authors = ["The Stratum V2 Developers"]
edition = "2018"
publish = false
Expand All @@ -14,9 +14,14 @@ async-channel = "1.5.1"
async-std="1.8.0"
bytes = "1.0.1"
binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary-sv2" }
codec_sv2 = { version = "^1.0.0", path = "../../protocols/v2/codec-sv2", features=["noise_sv2"] }
codec_sv2 = { version = "^2.0.0", path = "../../protocols/v2/codec-sv2", features=["noise_sv2"] }
network_helpers_sv2 = { version = "^2.0.0", path = "../../roles/roles-utils/network-helpers", features=["async_std"] }
key-utils = { version = "^1.0.0", path = "../../utils/key-utils" }
[profile.dev]
panic = "unwind"

[profile.release]
panic = "abort"

[features]
with_serde = ["binary_sv2/with_serde", "serde", "codec_sv2/with_serde", "network_helpers_sv2/with_serde"]
4 changes: 2 additions & 2 deletions examples/template-provider-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
name = "template-provider-test"
version = "0.1.0"
version = "0.1.1"
edition = "2018"
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
codec_sv2 = { version = "1.0", path = "../../protocols/v2/codec-sv2", features=["noise_sv2"] }
codec_sv2 = { version = "2.0", path = "../../protocols/v2/codec-sv2", features=["noise_sv2"] }
roles_logic_sv2 = { version = "^0.1.0", path = "../../protocols/v2/roles-logic-sv2" }
network_helpers_sv2 = { version = "^0.1.0", path = "../../roles/roles-utils/network-helpers", features=["async_std"] }
async-channel = "1.5.1"
Expand Down
4 changes: 2 additions & 2 deletions protocols/fuzz-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fuzz-tests"
version = "1.0.0"
version = "1.0.1"
edition = "2021"
authors = ["Automatically generated"]
publish = false
Expand All @@ -18,7 +18,7 @@ libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] }
arbitrary = { version = "1", features = ["derive"] }
rand = "0.8.3"
binary_codec_sv2 = { version = "1.0.0", path = "../v2/binary-sv2/no-serde-sv2/codec"}
codec_sv2 = { version = "1.0.0", path = "../v2/codec-sv2", features = ["noise_sv2"]}
codec_sv2 = { version = "2.0.0", path = "../v2/codec-sv2", features = ["noise_sv2"]}
roles_logic_sv2 = { version = "1.0.0", path = "../v2/roles-logic-sv2"}
affinity = "0.1.1"
threadpool = "1.8.1"
Expand Down
8 changes: 5 additions & 3 deletions protocols/v2/codec-sv2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "codec_sv2"
version = "1.3.1"
version = "2.0.0"
authors = ["The Stratum V2 Developers"]
edition = "2018"
readme = "README.md"
Expand All @@ -14,19 +14,21 @@ keywords = ["stratum", "mining", "bitcoin", "protocol"]
[dependencies]
serde = { version = "1.0.89", default-features = false, optional = true }
framing_sv2 = { version = "^3.0.0", path = "../../../protocols/v2/framing-sv2" }
noise_sv2 = { version = "1.0", path = "../../../protocols/v2/noise-sv2", optional=true}
noise_sv2 = { version = "1.0", path = "../../../protocols/v2/noise-sv2", default-features = false, optional = true }
binary_sv2 = { version = "1.0.0", path = "../../../protocols/v2/binary-sv2/binary-sv2" }
const_sv2 = { version = "3.0.0", path = "../../../protocols/v2/const-sv2"}
buffer_sv2 = { version = "1.0.0", path = "../../../utils/buffer"}
rand = {version = "0.8.5", default-features = false }
tracing = { version = "0.1"}

[dev-dependencies]
key-utils = { version = "^1.0.0", path = "../../../utils/key-utils" }

[features]
default = ["std"]
std = ["noise_sv2?/std", "rand/std", "rand/std_rng"]
with_serde = ["binary_sv2/with_serde", "serde", "framing_sv2/with_serde", "buffer_sv2/with_serde"]
with_buffer_pool = ["framing_sv2/with_buffer_pool"]
no_std = []

[package.metadata.docs.rs]
features = ["with_buffer_pool", "noise_sv2"]
3 changes: 3 additions & 0 deletions protocols/v2/codec-sv2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@ cargo add codec_sv2

This crate can be built with the following feature flags:

- `std`: Enable usage of rust `std` library, enabled by default.
- `noise_sv2`: Enables support for Noise protocol encryption and decryption.
- `with_buffer_pool`: Enables buffer pooling for more efficient memory management.
- `with_serde`: builds [`binary_sv2`](https://crates.io/crates/binary_sv2) and
[`buffer_sv2`](https://crates.io/crates/buffer_sv2) crates with `serde`-based encoding and
decoding. Note that this feature flag is only used for the Message Generator, and deprecated
for any other kind of usage. It will likely be fully deprecated in the future.

In order to use this crate in a `#![no_std]` environment, use the `--no-default-features` to remove the `std` feature.

### Examples

This crate provides two examples demonstrating how to encode and decode Sv2 frames:
Expand Down
34 changes: 34 additions & 0 deletions protocols/v2/codec-sv2/examples/encrypted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,29 @@ fn main() {
.try_into()
.expect("Failed to convert receiver private key to Secp256k1PublicKey");

#[cfg(feature = "std")]
let initiator = Initiator::from_raw_k(authority_public_k.into_bytes())
.expect("Failed to create initiator role from raw pub key");
#[cfg(not(feature = "std"))]
let initiator =
Initiator::from_raw_k_with_rng(authority_public_k.into_bytes(), &mut rand::thread_rng())
.expect("Failed to create initiator role from raw pub key");

#[cfg(feature = "std")]
let responder = Responder::from_authority_kp(
&authority_public_k.into_bytes(),
&authority_private_k.into_bytes(),
CERT_VALIDITY,
)
.expect("Failed to initialize responder from pub/key pair and/or cert");
#[cfg(not(feature = "std"))]
let responder = Responder::from_authority_kp_with_rng(
&authority_public_k.into_bytes(),
&authority_private_k.into_bytes(),
CERT_VALIDITY,
&mut rand::thread_rng(),
)
.expect("Failed to initialize responder from pub/key pair and/or cert");

let mut sender_state = State::initialized(HandshakeRole::Initiator(initiator));
let mut receiver_state = State::initialized(HandshakeRole::Responder(responder));
Expand All @@ -111,17 +125,37 @@ fn main() {
.try_into()
.expect("Handshake remote invlaid message");

#[cfg(feature = "std")]
let (second_message, receiver_state) = receiver_state
.step_1(first_message)
.expect("Responder failed second step of handshake");
#[cfg(not(feature = "std"))]
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() as u32;
#[cfg(not(feature = "std"))]
let (second_message, receiver_state) = receiver_state
.step_1_with_now_rng(first_message, now, &mut rand::thread_rng())
.expect("Responder failed second step of handshake");
let second_message: [u8; INITIATOR_EXPECTED_HANDSHAKE_MESSAGE_SIZE] = second_message
.get_payload_when_handshaking()
.try_into()
.expect("Handshake remote invlaid message");

#[cfg(feature = "std")]
let sender_state = sender_state
.step_2(second_message)
.expect("Initiator failed third step of handshake");
#[cfg(not(feature = "std"))]
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() as u32;
#[cfg(not(feature = "std"))]
let sender_state = sender_state
.step_2_with_now(second_message, now)
.expect("Initiator failed third step of handshake");

let mut sender_state = match sender_state {
State::Transport(c) => State::with_transport_mode(c),
Expand Down
60 changes: 55 additions & 5 deletions protocols/v2/codec-sv2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,24 @@
//!
//! This crate can be built with the following features:
//!
//! - `std`: Enable usage of rust `std` library, enabled by default.
//! - `noise_sv2`: Enables support for Noise protocol encryption and decryption.
//! - `with_buffer_pool`: Enables buffer pooling for more efficient memory management.
//! - `with_serde`: builds [`binary_sv2`] and [`buffer_sv2`] crates with `serde`-based encoding and
//! decoding. Note that this feature flag is only used for the Message Generator, and deprecated
//! for any other kind of usage. It will likely be fully deprecated in the future.
//!
//! In order to use this crate in a `#![no_std]` environment, use the `--no-default-features` to
//! remove the `std` feature.
//!
//! ## Examples
//!
//! See the examples for more information:
//!
//! - [Unencrypted Example](https://github.com/stratum-mining/stratum/blob/main/protocols/v2/codec-sv2/examples/unencrypted.rs)
//! - [Encrypted Example](https://github.com/stratum-mining/stratum/blob/main/protocols/v2/codec-sv2/examples/encrypted.rs)
#![cfg_attr(feature = "no_std", no_std)]
#![cfg_attr(not(feature = "std"), no_std)]

pub use framing_sv2::framing::Frame;

Expand Down Expand Up @@ -156,14 +160,38 @@ impl State {
/// nb: Returns a new state [`State::Transport`] but does not update the current state
/// (`self`). The caller is responsible for updating the state, allowing for more flexible
/// control over the handshake process as the caller decides what to do with this state.
#[cfg(feature = "std")]
pub fn step_1(
&mut self,
re_pub: [u8; const_sv2::RESPONDER_EXPECTED_HANDSHAKE_MESSAGE_SIZE],
) -> core::result::Result<(HandShakeFrame, Self), Error> {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() as u32;

self.step_1_with_now_rng(re_pub, now, &mut rand::thread_rng())
}

/// Processes the second step of the handshake process for the responder given
/// the current time and a custom random number generator.
///
/// See [`Self::step_1`] for more details.
///
/// The current time and the custom random number generatorshould be provided in order to not
/// implicitely rely on `std` and allow `no_std` environments to provide a hardware random
/// number generator for example.
#[inline]
pub fn step_1_with_now_rng<R: rand::Rng + rand::CryptoRng>(
&mut self,
re_pub: [u8; const_sv2::RESPONDER_EXPECTED_HANDSHAKE_MESSAGE_SIZE],
now: u32,
rng: &mut R,
) -> core::result::Result<(HandShakeFrame, Self), Error> {
match self {
Self::HandShake(h) => match h {
HandshakeRole::Responder(r) => {
let (message, codec) = r.step_1(re_pub)?;
let (message, codec) = r.step_1_with_now_rng(re_pub, now, rng)?;
Ok((h2f(message), Self::Transport(codec)))
}
HandshakeRole::Initiator(_) => Err(Error::InvalidStepForInitiator),
Expand All @@ -180,15 +208,37 @@ impl State {
///
/// nb: Directly updates the current state (`self`) to [`State::Transport`], completing the
/// handshake process.
#[cfg(feature = "std")]
pub fn step_2(
&mut self,
message: [u8; const_sv2::INITIATOR_EXPECTED_HANDSHAKE_MESSAGE_SIZE],
) -> core::result::Result<Self, Error> {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() as u32;
self.step_2_with_now(message, now)
}

/// Processes the final step of the handshake process for the initiator given the
/// current system time.
///
/// See [`Self::step_2`] for more details.
///
/// The current system time should be provided to avoid relying on `std` and allow `no_std`
/// environments to use another source of time.
#[inline]
pub fn step_2_with_now(
&mut self,
message: [u8; const_sv2::INITIATOR_EXPECTED_HANDSHAKE_MESSAGE_SIZE],
now: u32,
) -> core::result::Result<Self, Error> {
match self {
Self::HandShake(h) => match h {
HandshakeRole::Initiator(i) => {
i.step_2(message).map_err(|e| e.into()).map(Self::Transport)
}
HandshakeRole::Initiator(i) => i
.step_2_with_now(message, now)
.map_err(|e| e.into())
.map(Self::Transport),
HandshakeRole::Responder(_) => Err(Error::InvalidStepForResponder),
},
_ => Err(Error::NotInHandShakeState),
Expand Down
4 changes: 2 additions & 2 deletions protocols/v2/sv2-ffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sv2_ffi"
version = "1.0.1"
version = "1.0.2"
authors = ["The Stratum V2 Developers"]
edition = "2018"
description = "SV2 FFI"
Expand All @@ -14,7 +14,7 @@ keywords = ["stratum", "mining", "bitcoin", "protocol"]
crate-type = ["staticlib"]

[dependencies]
codec_sv2 = { path = "../../../protocols/v2/codec-sv2", version = "^1.0.0" }
codec_sv2 = { path = "../../../protocols/v2/codec-sv2", version = "^2.0.0" }
const_sv2 = { path = "../../../protocols/v2/const-sv2", version = "^3.0.0" }
binary_sv2 = { path = "../../../protocols/v2/binary-sv2/binary-sv2", version = "^1.0.0" }
common_messages_sv2 = { path = "../../../protocols/v2/subprotocols/common-messages", version = "^3.0.0" }
Expand Down
17 changes: 9 additions & 8 deletions roles/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions roles/jd-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jd_client"
version = "0.1.3"
version = "0.1.4"
authors = ["The Stratum V2 Developers"]
edition = "2021"
description = "Job Declarator Client (JDC) role"
Expand All @@ -21,7 +21,7 @@ async-channel = "1.5.1"
async-recursion = "0.3.2"
binary_sv2 = { version = "^1.0.0", path = "../../protocols/v2/binary-sv2/binary-sv2" }
buffer_sv2 = { version = "^1.0.0", path = "../../utils/buffer" }
codec_sv2 = { version = "^1.0.1", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2", "with_buffer_pool"] }
codec_sv2 = { version = "^2.0.0", path = "../../protocols/v2/codec-sv2", features = ["noise_sv2", "with_buffer_pool"] }
framing_sv2 = { version = "^3.0.0", path = "../../protocols/v2/framing-sv2" }
network_helpers_sv2 = { version = "2.0.0", path = "../roles-utils/network-helpers", features=["with_tokio", "with_buffer_pool"] }
roles_logic_sv2 = { version = "^1.0.0", path = "../../protocols/v2/roles-logic-sv2" }
Expand Down
Loading

0 comments on commit ad01bdf

Please sign in to comment.