Skip to content

Commit

Permalink
Encrypted + unencrypted codec examples
Browse files Browse the repository at this point in the history
  • Loading branch information
RJ Rybarczyk committed Oct 3, 2024
1 parent b820b23 commit 0af6182
Show file tree
Hide file tree
Showing 3 changed files with 293 additions and 2 deletions.
5 changes: 3 additions & 2 deletions protocols/v2/codec-sv2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ const_sv2 = { version = "2.0.0", path = "../../../protocols/v2/const-sv2"}
buffer_sv2 = { version = "1.0.0", path = "../../../utils/buffer"}
tracing = { version = "0.1"}


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

[features]
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 = []
no_std = []
167 changes: 167 additions & 0 deletions protocols/v2/codec-sv2/examples/encrypted.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
use binary_sv2::{binary_codec_sv2, Deserialize, Serialize};
use codec_sv2::{
HandshakeRole, Initiator, NoiseEncoder, Responder, StandardEitherFrame, StandardNoiseDecoder,
State, Sv2Frame,
};
use const_sv2::{
INITIATOR_EXPECTED_HANDSHAKE_MESSAGE_SIZE, RESPONDER_EXPECTED_HANDSHAKE_MESSAGE_SIZE,
};
use key_utils::{Secp256k1PublicKey, Secp256k1SecretKey};
use std::{
convert::TryInto,
io::{Read, Write},
net::{TcpListener, TcpStream},
};

// Arbitrary message type.
// Supported Sv2 message types are listed in the [Sv2 Spec Message
// Types](https://github.com/stratum-mining/sv2-spec/blob/main/08-Message-Types.md).
const CUSTOM_MSG_TYPE: u8 = 0xff;

// Emulate a TCP connection
const TCP_ADDR: &str = "127.0.0.1:3333";
const RECEIVER_PUBLIC_K: &str = "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72";
const RECEIVER_PRIVATE_K: &str = "mkDLTBBRxdBv998612qipDYoTK3YUrqLe8uWw7gu3iXbSrn2n";
const RECEIVER_CERT_VALIDITY: std::time::Duration = std::time::Duration::from_secs(3600);

// Example message type.
// In practice, all Sv2 messages are defined in the following crates:
// * `common_messages_sv2`
// * `mining_sv2`
// * `job_declaration_sv2`
// * `template_distribution_sv2`
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CustomMessage {
nonce: u16,
}

fn main() {
// Start a receiving listener
let listener_receiver = TcpListener::bind(TCP_ADDR).expect("Failed to bind TCP listener");

// Start a sender stream
let mut stream_sender: TcpStream =
TcpStream::connect(TCP_ADDR).expect("Failed to connect to TCP stream");

// Start a receiver stream
let mut stream_receiver: TcpStream = listener_receiver
.incoming()
.next()
.expect("Failed to accept incoming TCP stream")
.expect("Failed to connect to incoming TCP stream");

// Handshake
let receiver_public_k: Secp256k1PublicKey = RECEIVER_PUBLIC_K
.to_string()
.try_into()
.expect("Failed to convert receiver public key to Secp256k1PublicKey");

let receiver_private_k: Secp256k1SecretKey = RECEIVER_PRIVATE_K
.to_string()
.try_into()
.expect("Failed to convert receiver private key to Secp256k1PublicKey");

let initiator = Initiator::from_raw_k(receiver_public_k.into_bytes())
.expect("Failed to create initiator role from raw pub key");

let responder = Responder::from_authority_kp(
&receiver_public_k.into_bytes(),
&receiver_private_k.into_bytes(),
RECEIVER_CERT_VALIDITY,
)
.expect("Failed to initialize responder from pub/key pair and/or cert");

let mut sender_state = codec_sv2::State::initialized(HandshakeRole::Initiator(initiator));
let mut receiver_state = codec_sv2::State::initialized(HandshakeRole::Responder(responder));

let first_message = sender_state
.step_0()
.expect("Initiator failed first step of handshake");
let first_message: [u8; RESPONDER_EXPECTED_HANDSHAKE_MESSAGE_SIZE] = first_message
.get_payload_when_handshaking()
.try_into()
.expect("Handshake remote invlaid message");

let (second_message, receiver_state) = receiver_state
.step_1(first_message)
.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");

let sender_state = sender_state
.step_2(second_message)
.expect("Initiator failed third step of handshake");

let mut sender_state = match sender_state {
State::Transport(c) => State::with_transport_mode(c),
_ => panic!("todo"),
};

let mut receiver_state = match receiver_state {
State::Transport(c) => State::with_transport_mode(c),
_ => panic!("todo"),
};

// Create a message
let nonce = 1337;
let msg = CustomMessage { nonce };
let msg_type = CUSTOM_MSG_TYPE;
// Unique identifier of the extension describing the protocol message, as defined by Sv2 Framing
let extension_type = 0;
// This message is intended for the receiver, so set to false
let channel_msg = false;

let frame = StandardEitherFrame::<CustomMessage>::Sv2(
Sv2Frame::from_message(msg, msg_type, extension_type, channel_msg)
.expect("Failed to create the frame"),
);

let mut encoder = NoiseEncoder::<CustomMessage>::new();
let encoded_frame = encoder
.encode(frame, &mut sender_state)
.expect("Failed to encode the frame");

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

// Receiver side
let mut decoder = StandardNoiseDecoder::<CustomMessage>::new();
let decoder_buf = decoder.writable();
// Read the frame header into the decoder buffer
stream_receiver
.read_exact(decoder_buf)
.expect("Failed to read the encoded frame header");

// This returns a `MissingBytes` error because it only reads the header as there is no payload
// in memory yet. Therefore, we safely ignore the error as the important thing here is that we
// loaded the `decoder.missing_b` with the expected frame payload size
let _ = decoder.next_frame(&mut receiver_state);

// Now the decoder buffer has the expected size of the frame payload
let decoder_buf = decoder.writable();

// Read the payload into the decoder buffer
stream_receiver
.read_exact(decoder_buf)
.expect("Failed to read the encoded frame payload");

// INCORRECT PANIC HERE (DO NOT MERGE):
// Decode the frame
let _decoded_frame = decoder
.next_frame(&mut receiver_state)
.expect("Failed to decode the frame");

// let decoded_frame_header = decoded_frame
// .get_header()
// .expect("Failed to get the frame header");
// let decoded_msg: CustomMessage = binary_sv2::from_bytes(decoded_frame.payload())
// .expect("Failed to extract the message from the payload");
//
// // Assert that the decoded message is as expected
// assert_eq!(decoded_frame_header.msg_type(), CUSTOM_MSG_TYPE);
// assert_eq!(decoded_msg.nonce, nonce);
}
123 changes: 123 additions & 0 deletions protocols/v2/codec-sv2/examples/unencrypted.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use binary_sv2::{binary_codec_sv2, Deserialize, Serialize};
use codec_sv2::{Encoder, StandardDecoder, StandardSv2Frame, Sv2Frame};
use std::{
convert::TryInto,
io::{Read, Write},
net::{TcpListener, TcpStream},
};

// Arbitrary message type.
// Supported Sv2 message types are listed in the [Sv2 Spec Message
// Types](https://github.com/stratum-mining/sv2-spec/blob/main/08-Message-Types.md).
const CUSTOM_MSG_TYPE: u8 = 0xff;

// Emulate a TCP connection
const TCP_ADDR: &str = "127.0.0.1:3333";

// Example message type.
// In practice, all Sv2 messages are defined in the following crates:
// * `common_messages_sv2`
// * `mining_sv2`
// * `job_declaration_sv2`
// * `template_distribution_sv2`
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CustomMessage {
nonce: u16,
}

fn main() {
// Start a receiving listener
let listener_receiver = TcpListener::bind(TCP_ADDR).expect("Failed to bind TCP listener");

// Start a sender stream
let stream_sender: TcpStream =
TcpStream::connect(TCP_ADDR).expect("Failed to connect to TCP stream");

// Start a receiver stream
let stream_receiver: TcpStream = listener_receiver
.incoming()
.next()
.expect("Failed to accept incoming TCP stream")
.expect("Failed to connect to incoming TCP stream");

// Server Side

// Create a message
let nonce = 1337;
let msg = CustomMessage { nonce };
let msg_type = CUSTOM_MSG_TYPE;
// Unique identifier of the extension describing the protocol message, as defined by Sv2 Framing
let extension_type = 0;
// This message is intended for the receiver, so set to false
let channel_msg = false;
sender_side(stream_sender, msg, msg_type, extension_type, channel_msg);

// Receiver Side
let mut decoded_frame = receiver_side(stream_receiver);

let decoded_frame_header = decoded_frame
.get_header()
.expect("Failed to get the frame header");
let decoded_msg: CustomMessage = binary_sv2::from_bytes(decoded_frame.payload())
.expect("Failed to extract the message from the payload");

// Assert that the decoded message is as expected
assert_eq!(decoded_frame_header.msg_type(), CUSTOM_MSG_TYPE);
assert_eq!(decoded_msg.nonce, nonce);
}

fn sender_side(
mut stream_sender: TcpStream,
msg: CustomMessage,
msg_type: u8,
extension_type: u16,
channel_msg: bool,
) {
// Create the frame
let frame =
StandardSv2Frame::<CustomMessage>::from_message(msg, msg_type, extension_type, channel_msg)
.expect("Failed to create the frame");

// Encode the frame
let mut encoder = Encoder::<CustomMessage>::new();
let encoded_frame = encoder
.encode(frame.clone())
.expect("Failed to encode the frame");

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

fn receiver_side(mut stream_receiver: TcpStream) -> Sv2Frame<CustomMessage, Vec<u8>> {
// Initialize the decoder
let mut decoder = StandardDecoder::<CustomMessage>::new();

// At this point, the decoder buffer can only read a frame header because the
// decoder.missing_b is initialized with a header size
let decoder_buf = decoder.writable();

// Read the frame header into the decoder buffer
stream_receiver
.read_exact(decoder_buf)
.expect("Failed to read the encoded frame header");

// This returns a `MissingBytes` error because it only reads the header as there is no payload
// in memory yet. Therefore, we safely ignore the error as the important thing here is that we
// loaded the `decoder.missing_b` with the expected frame payload size
let _ = decoder.next_frame();

// Now the decoder buffer has the expected size of the frame payload
let decoder_buf = decoder.writable();

// Read the payload into the decoder buffer
stream_receiver
.read_exact(decoder_buf)
.expect("Failed to read the encoded frame payload");

// Decode the frame
let decoded_frame = decoder.next_frame().expect("Failed to decode the frame");

return decoded_frame;
}

0 comments on commit 0af6182

Please sign in to comment.