diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..87fa24d
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,95 @@
+on: [push, pull_request]
+
+name: Rust CI
+
+jobs:
+ check:
+ name: Check
+ runs-on: ubuntu-latest
+ env:
+ CARGO_TERM_COLOR: always
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: stable
+ override: true
+ - uses: actions-rs/cargo@v1
+ with:
+ command: check
+ args: --manifest-path Cargo.toml
+
+ test:
+ name: Test Suite
+ runs-on: ubuntu-latest
+ env:
+ CARGO_TERM_COLOR: always
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: stable
+ override: true
+ - uses: actions-rs/cargo@v1
+ with:
+ command: test
+ args: --manifest-path Cargo.toml
+
+ fmt:
+ name: Rustfmt
+ runs-on: ubuntu-latest
+ env:
+ CARGO_TERM_COLOR: always
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: stable
+ override: true
+ - run: rustup component add rustfmt
+ - uses: actions-rs/cargo@v1
+ with:
+ command: fmt
+ args: --manifest-path Cargo.toml --all -- --check
+
+ coverage:
+ runs-on: ubuntu-latest
+ env:
+ CARGO_TERM_COLOR: always
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Rust
+ run: rustup update stable
+ - name: Install cargo-llvm-cov
+ uses: taiki-e/install-action@cargo-llvm-cov
+ - name: Generate code coverage
+ run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
+ env:
+ RUST_LOG: debug
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
+ files: lcov.info
+ fail_ci_if_error: true
+ verbose: true
+
+
+ # clippy:
+ # name: Clippy
+ # runs-on: ubuntu-latest
+ # steps:
+ # - uses: actions/checkout@v4
+ # - uses: actions-rs/toolchain@v1
+ # with:
+ # profile: minimal
+ # toolchain: stable
+ # override: true
+ # - run: rustup component add clippy
+ # - uses: actions-rs/cargo@v1
+ # with:
+ # command: clippy
+ # args: -- -D warnings
diff --git a/src/node/connection_reader.rs b/src/node/connection_reader.rs
deleted file mode 100644
index d67e083..0000000
--- a/src/node/connection_reader.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2024 Kulpreet Singh
-
-// This file is part of Frost-Federation
-
-// Frost-Federation is free software: you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-
-// Frost-Federation is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Frost-Federation. If not, see
-// .
-
-use tokio::net::tcp::OwnedReadHalf;
-use tokio::sync::mpsc;
-use tokio_util::bytes::Bytes;
-use tokio_util::codec::{FramedRead, LengthDelimitedCodec};
-use tokio_util::sync::CancellationToken;
-
-// Bring StreamExt in scope for access to `next` calls
-use tokio_stream::StreamExt;
-
-/// Read messages from the framed reader and enqueue it for noise and
-/// higher layers to process.
-pub struct ConnectionReader {
- pub send_channel: mpsc::Sender,
- pub framed_reader: FramedRead,
- pub cancel_token: CancellationToken,
-}
-
-impl ConnectionReader {
- pub async fn start(&mut self) {
- loop {
- tokio::select! {
- data = self.framed_reader.next() => {
- if let Some(message) = data {
- match message {
- Ok(message) => {
- log::debug!("Received from network ... {:?}", message);
- if let Err(e) = self.send_channel.send(message.freeze()).await {
- log::debug!("Error en-queuing message: {:?}", e);
- }
- }
- Err(e) => {
- log::debug!("Error reading from channel {:?}", e);
- self.cancel_token.cancel();
- return;
- }
- }
-
- }
- else {
- self.cancel_token.cancel();
- return;
- }
- },
- _ = self.cancel_token.cancelled() => {
- log::info!("Connection closed");
- return
- }
- }
- }
- }
-}
diff --git a/src/node/connection_writer.rs b/src/node/connection_writer.rs
deleted file mode 100644
index a3fcede..0000000
--- a/src/node/connection_writer.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2024 Kulpreet Singh
-
-// This file is part of Frost-Federation
-
-// Frost-Federation is free software: you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-
-// Frost-Federation is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Frost-Federation. If not, see
-// .
-
-use tokio::net::tcp::OwnedWriteHalf;
-use tokio::sync::mpsc;
-use tokio_util::bytes::Bytes;
-use tokio_util::codec::{FramedWrite, LengthDelimitedCodec};
-use tokio_util::sync::CancellationToken;
-
-// Bring SinkExt in scope for access to `send` calls
-use futures::sink::SinkExt;
-
-/// Send message over the noise connection
-pub struct ConnectionWriter {
- pub receive_channel: mpsc::Receiver,
- pub framed_writer: FramedWrite,
- pub cancel_token: CancellationToken,
-}
-
-impl ConnectionWriter {
- pub async fn start(&mut self) {
- loop {
- tokio::select! {
- Some(message) = self.receive_channel.recv() => {
- log::debug!("Sending using framed writer {:?}", message);
- if self.framed_writer.send(message).await.is_err() {
- log::info!("Closing connection");
- self.cancel_token.cancel();
- }
- },
- _ = self.cancel_token.cancelled() => {
- log::info!("Connection closed");
- return;
- }
- }
- }
- }
-}
diff --git a/src/node/noise_handler.rs b/src/node/noise_handler.rs
index 60258d8..cadad93 100644
--- a/src/node/noise_handler.rs
+++ b/src/node/noise_handler.rs
@@ -30,9 +30,7 @@ use tokio_util::{
//
// We use 25519 instead of LN's choice of secp256k1 as
// rust Noise implementation doesn't yet support secp256k1
-// noise_params: "Noise_XX_25519_ChaChaPoly_SHA256".parse().unwrap(),
-// static PATTERN: &str = "Noise_NN_25519_ChaChaPoly_BLAKE2s";
static PATTERN: &str = "Noise_XX_25519_ChaChaPoly_SHA256";
const NOISE_MAX_MSG_LENGTH: usize = 65535;
@@ -197,3 +195,38 @@ impl NoiseHandler {
(reader, writer)
}
}
+
+#[cfg(test)]
+mod tests {
+
+ use super::NoiseHandler;
+ use tokio_util::bytes::Bytes;
+
+ static TEST_KEY: &str = "
+-----BEGIN PRIVATE KEY-----
+MFECAQEwBQYDK2VwBCIEIJ7pILqR7yBPsVuysfGyofjOEm19skmtqcJYWiVwjKH1
+gSEA68zeZuy7PMMQC9ECPmWqDl5AOFj5bi243F823ZVWtXY=
+-----END PRIVATE KEY-----
+";
+
+ #[test]
+ fn it_builds_noise_handler() {
+ let handler = NoiseHandler::new(true, TEST_KEY.to_string());
+ assert!(handler.initiator);
+ assert!(handler.handshake_state.is_some());
+ assert!(handler.transport_state.is_none());
+ }
+
+ #[test]
+ fn it_builds_initiator_noise_handler() {
+ let mut handler = NoiseHandler::new(true, TEST_KEY.to_string());
+ let noise_message: Bytes = handler.build_handshake_message(b"test bytes");
+ let len = noise_message.len();
+ assert_eq!(&noise_message[(len - 10)..], b"test bytes");
+
+ let mut responder = NoiseHandler::new(false, TEST_KEY.to_string());
+ let read_message: Bytes = responder.read_handshake_message(noise_message);
+ let len = read_message.len();
+ assert_eq!(&read_message[(len - 10)..], b"test bytes");
+ }
+}
diff --git a/src/node/protocol.rs b/src/node/protocol.rs
index b36fea6..6a60103 100644
--- a/src/node/protocol.rs
+++ b/src/node/protocol.rs
@@ -24,12 +24,10 @@ use serde::{Deserialize, Serialize};
mod handshake;
mod heartbeat;
-mod noise_handshake;
mod ping;
pub use handshake::HandshakeMessage;
pub use heartbeat::HeartbeatMessage;
-pub use noise_handshake::NoiseHandshakeMessage;
pub use ping::PingMessage;
use super::reliable_sender::ReliableSenderHandle;
@@ -39,30 +37,16 @@ pub enum Message {
Handshake(HandshakeMessage),
Heartbeat(HeartbeatMessage),
Ping(PingMessage),
- NoiseHandshake(NoiseHandshakeMessage),
}
/// Methods for all protocol messages
impl Message {
- /// Return the message as bytes
- pub fn as_bytes(&self) -> Option {
- let mut s = flexbuffers::FlexbufferSerializer::new();
- self.serialize(&mut s).unwrap();
- Some(Bytes::from(s.take_buffer()))
- }
-
- /// Build message from bytes
- pub fn from_bytes(b: &[u8]) -> Result> {
- Ok(flexbuffers::from_slice(b)?)
- }
-
/// Generates the response to send for a message received
pub fn response_for_received(&self) -> Result