From d8d96d99620c9d595c499e1b2a8d4a565bc558b4 Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 2 May 2024 12:01:17 -0300 Subject: [PATCH 1/2] Rust bindings --- Makefile | 7 ++++ README.md | 17 +++++++- rust_bindings/.gitignore | 2 + rust_bindings/Cargo.toml | 18 ++++++++ rust_bindings/README.md | 15 +++++++ rust_bindings/build.rs | 18 ++++++++ rust_bindings/examples/basic_usage.rs | 16 ++++++++ rust_bindings/src/lib.rs | 59 +++++++++++++++++++++++++++ src/.gitignore | 4 ++ 9 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 rust_bindings/.gitignore create mode 100644 rust_bindings/Cargo.toml create mode 100644 rust_bindings/README.md create mode 100644 rust_bindings/build.rs create mode 100644 rust_bindings/examples/basic_usage.rs create mode 100644 rust_bindings/src/lib.rs create mode 100644 src/.gitignore diff --git a/Makefile b/Makefile index 99b05ab..201dc05 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ libhashtree: clean: $(MAKE) -C src clean + cd rust_bindings && cargo clean test: $(MAKE) -C src test @@ -10,6 +11,12 @@ test: bench: $(MAKE) -C src bench +.PHONY: rust_bindings rust_tests +rust_bindings: + cd rust_bindings && cargo build --release +rust_tests: + cd rust_bindings && cargo test + all: $(MAKE) -C src all diff --git a/README.md b/README.md index 6ccddc3..151215e 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,6 @@ BenchmarkHashBalancePrysm-4 10 103716714 ns/op PASS ``` - ## Nim bindings The library offers low-level bindings for Nim that can be installed using: @@ -195,3 +194,19 @@ or used in a package with: ```nim requires "https://github.com/prysmaticlabs/hashtree/" ``` + +## Rust bindings + +At the top directory you can run + +``` +$ make rust_bindings +``` + +To run tests: + +``` +$ make rust_tests +``` + +See the `examples` directory for examples on how to use the library diff --git a/rust_bindings/.gitignore b/rust_bindings/.gitignore new file mode 100644 index 0000000..fa8d85a --- /dev/null +++ b/rust_bindings/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target diff --git a/rust_bindings/Cargo.toml b/rust_bindings/Cargo.toml new file mode 100644 index 0000000..5a4a1f5 --- /dev/null +++ b/rust_bindings/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "hashtree-rs" +version = "0.1.0" +authors = ["Potuz "] +edition = "2021" +description = "Rust bindings for the hashtree library" +license = "MIT" +build = "build.rs" +keywords = ["hash", "crypto", "sha256", "merkle"] + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +libc = "0.2" + +[build-dependencies] +cc = "1.0" diff --git a/rust_bindings/README.md b/rust_bindings/README.md new file mode 100644 index 0000000..2965eea --- /dev/null +++ b/rust_bindings/README.md @@ -0,0 +1,15 @@ +# Rust bindings for Hashstree + +At the top directory you can run + +``` +$ make rust_bindings +``` + +To run tests: + +``` +$ make rust_tests +``` + +See the `examples` directory for examples on how to use the library diff --git a/rust_bindings/build.rs b/rust_bindings/build.rs new file mode 100644 index 0000000..9a804a5 --- /dev/null +++ b/rust_bindings/build.rs @@ -0,0 +1,18 @@ +use std::env; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + let root_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join(".."); + + Command::new("make") + .current_dir(&root_path) + .output() + .expect("Failed to build hashtree"); + + println!( + "cargo:rustc-link-search=native={}", + root_path.join("src").display() + ); + println!("cargo:rustc-link-lib=static=hashtree"); +} diff --git a/rust_bindings/examples/basic_usage.rs b/rust_bindings/examples/basic_usage.rs new file mode 100644 index 0000000..45539f1 --- /dev/null +++ b/rust_bindings/examples/basic_usage.rs @@ -0,0 +1,16 @@ +extern crate hashtree_rs; + +fn main() { + println!("Initializing hashtree..."); + hashtree_rs::init(); + println!("Hashtree initialized."); + + let chunks: [u8; 64] = [0xAB; 64]; + let mut out = [0u8; 32]; + + hashtree_rs::hash(&mut out, &chunks, 1); + + let hex_string: String = out.iter().map(|byte| format!("{:02x}", byte)).collect(); + + println!("Computed hash: 0x{}", hex_string); +} diff --git a/rust_bindings/src/lib.rs b/rust_bindings/src/lib.rs new file mode 100644 index 0000000..acefb70 --- /dev/null +++ b/rust_bindings/src/lib.rs @@ -0,0 +1,59 @@ +//! Hasthree rust bindings +//! +//! hashtree is a SHA256 library highly optimized for Merkle tree computations. It is based on +//! Intel's implementation (intel-ipsec-mb) with a few modifications like hardcoding the scheduled +//! words. This library exposes a single function that takes an input slice of bytes to be +//! considered as chunks of 64 bytes each, and another slice where the digests of each chunk will +//! be written consecutively +//! +extern crate libc; +use libc::c_int; +use std::ptr; + +type HashFunction = extern "C" fn(*mut u8, *const u8, u64); + +extern "C" { + fn hashtree_init(override_: *const HashFunction) -> c_int; + fn hashtree_hash(output: *mut u8, input: *const u8, count: u64); +} + +/// init is used to initialize the hashtree library. It automatically chooses the best +/// implementation. +pub fn init() -> i32 { + unsafe { hashtree_init(ptr::null()) } +} + +/// hash takes a mutable slice where the digests will be stored (overwritten), a slice with the +/// chunks to merkleize and the number of chunks to merkleize +pub fn hash(out: &mut [u8], chunks: &[u8], count: usize) { + unsafe { hashtree_hash(out.as_mut_ptr(), chunks.as_ptr(), count as u64) } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_init() { + assert_eq!(init(), 1); + } + + #[test] + fn test_hash() { + let chunks: [u8; 64] = [0xAB; 64]; + let mut out = [0u8; 32]; + + hash(&mut out, &chunks, 1); + + let expected_hash: [u8; 32] = [ + 0xec, 0x65, 0xc8, 0x79, 0x8e, 0xcf, 0x95, 0x90, 0x24, 0x13, 0xc4, 0x0f, 0x7b, 0x9e, + 0x6d, 0x4b, 0x00, 0x68, 0x88, 0x5f, 0x5f, 0x32, 0x4a, 0xba, 0x1f, 0x9b, 0xa1, 0xc8, + 0xe1, 0x4a, 0xea, 0x61, + ]; + + assert_eq!( + out, expected_hash, + "The generated hash did not match the expected hash." + ); + } +} diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..6cb0424 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,4 @@ +*.o +hashtree.pc +libhashtree.a +libhashtree.lib From 654ac9b1d5ef93d0fd625f3bc672f9451cd300f9 Mon Sep 17 00:00:00 2001 From: Raul Jordan Date: Thu, 2 May 2024 10:07:16 -0500 Subject: [PATCH 2/2] add ci --- .github/workflows/test.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7ca9c6e..63cf44a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,29 @@ jobs: - name: Run tests run: ./src/test + rust-bindings: + runs-on: ubuntu-latest + name: (${{ matrix.target }}) + strategy: + matrix: + target: [ + x86_64-unknown-linux-gnu, + aarch64-unknown-linux-gnu, + ] + steps: + - name: checkout + uses: actions/checkout@v3 + - name: install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + rustup target add ${{ matrix.target }} + - name: Build and Test + run: | + cd rust_bindings + cargo build --release + cargo test + nim: name: nim runs-on: ubuntu-latest