Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rust bindings #23

Merged
merged 2 commits into from
May 2, 2024
Merged
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
23 changes: 23 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@ libhashtree:

clean:
$(MAKE) -C src clean
cd rust_bindings && cargo clean

test:
$(MAKE) -C src 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

Expand Down
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
2 changes: 2 additions & 0 deletions rust_bindings/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cargo.lock
target
18 changes: 18 additions & 0 deletions rust_bindings/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "hashtree-rs"
version = "0.1.0"
authors = ["Potuz <[email protected]>"]
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"
15 changes: 15 additions & 0 deletions rust_bindings/README.md
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions rust_bindings/build.rs
Original file line number Diff line number Diff line change
@@ -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");
}
16 changes: 16 additions & 0 deletions rust_bindings/examples/basic_usage.rs
Original file line number Diff line number Diff line change
@@ -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);
}
59 changes: 59 additions & 0 deletions rust_bindings/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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."
);
}
}
4 changes: 4 additions & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.o
hashtree.pc
libhashtree.a
libhashtree.lib
Loading