Skip to content

Commit

Permalink
Rust bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
potuz committed May 2, 2024
1 parent 6319c40 commit d8d96d9
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 1 deletion.
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 <potuz@prysmaticlabs.com>"]
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

0 comments on commit d8d96d9

Please sign in to comment.