Skip to content

Commit

Permalink
updated README file
Browse files Browse the repository at this point in the history
  • Loading branch information
yshekel committed Oct 14, 2024
1 parent d6561e6 commit ff8bd49
Showing 1 changed file with 50 additions and 17 deletions.
67 changes: 50 additions & 17 deletions examples/rust/hash-and-merkle/README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@

# ICICLE Example: Keccak-256 Hashing and Merkle-Tree

## Key Takeaway

This example demonstrates how to perform Keccak-256 hashing on both the CPU and CUDA backends using the ICICLE framework. The example includes hashing string data, Babybear field elements, and batched field elements, showcasing how to efficiently use the ICICLE runtime to process data on different devices.
The examples cover:
- **String Hashing** using Keccak-256.
- **Field Element Hashing** with Babybear and Keccak-256.
- **Merkle Tree Construction** using Keccak-256 and Blake2s.

> [!NOTE]
> This example uses the Keccak-256 hash function, but you can easily substitute it with other hash algorithms supported by ICICLE (e.g., SHA3, Blake2s, Poseidon). Just replace the Keccak256 type in the example with your desired hashing algorithm.
> While Keccak-256 and blake2s are used here, other supported hash functions (e.g., SHA3, Poseidon and others) can be substituted.
## What's in this Example

1. **Backend Setup**: Configure ICICLE to use either the **CPU** or **CUDA** backend.
2. **String Hashing**: Demonstrates hashing strings using Keccak-256.
3. **Field Element Hashing**: Hash Babybear field elements using Keccak-256.
4. **Merkle Tree Construction**: Build, prove, and verify a Merkle tree using Keccak-256 and blake2s.

## Batch Size and Input Flexibility
## Hashing Example

This example hashes both strings and field elements using **Keccak-256**, commonly used in cryptographic systems.

The **batch size** for hashing is automatically derived from the size of the output buffer, meaning it scales according to the size of the output you need.
This design also allows the same hashing function to efficiently handle any input type, whether it’s simple strings, scalar field elements, or elliptic curve points.

## Usage

```rust
// Initialize the Keccak-256 hasher
let keccak_hasher = Keccak256::new(0).unwrap();

// Hash a simple string
let input_str = "I like ICICLE! it's so fast and easy";
let mut output = vec![0u8; 32]; // Output buffer for hash result
let mut output = vec![0u8; 2*32]; // Output buffer for batch=2
keccak_hasher.hash(
HostSlice::from_slice(input_str.as_bytes()),
&HashConfig::default(),
Expand All @@ -29,27 +40,51 @@ keccak_hasher.hash(

// Hash Babybear field elements
let input_field_elements = BabybearCfg::generate_random(128);
let mut output = vec![0u8; 32]; // Output buffer for hash result
let mut output = vec![0u8; 1*32]; // Output buffer for batch=1
keccak_hasher.hash(
HostSlice::from_slice(&input_field_elements),
&HashConfig::default(),
HostSlice::from_mut_slice(&mut output),
).unwrap();
```

This example demonstrates how to hash both simple strings and field elements using the Keccak-256 hashing algorithm, which is commonly used in cryptographic applications.
### 2. Merkle Tree Example

## What's in this example
The Merkle tree example demonstrates **building a binary Merkle tree**, committing to string data, and generating **Merkle proofs**.

```rust
fn merkle_tree_example() {
let input_string = String::from(
"Hello, this is an ICICLE example to commit to a string and open specific parts +Add optional Pad",
);
let input = input_string.as_bytes();

// define tree with Keccak-256 and blake2s hashers
let hasher = Keccak256::new(leaf_size).unwrap();
let compress = Blake2s::new(hasher.output_size() * 2).unwrap();
let layer_hashes: Vec<&Hasher> = std::iter::once(&hasher)
.chain(std::iter::repeat(&compress).take(tree_height))
.collect();
let merkle_tree = MerkleTree::new(&layer_hashes, leaf_size, 0).unwrap();

// 1. commit
merkle_tree.build(HostSlice::from_slice(&input), &config).unwrap();
let commitment = merkle_tree.get_root().unwrap();
// 2. open leaf #3
let merkle_proof = merkle_tree
.get_proof(HostSlice::from_slice(&input), 3, tru /*=pruned path*/, &config)

Check failure on line 75 in examples/rust/hash-and-merkle/README.md

View workflow job for this annotation

GitHub Actions / Check Spelling

tru ==> through, true
.unwrap();
// 3. verify
let proof_is_valid = merkle_tree.verify(&merkle_proof).unwrap();
}
```

This example demonstrates **building and verifying Merkle trees** using the ICICLE framework. The tree uses **Keccak-256** for leaf hashing and **Blake2s** for internal nodes.

1. Set up the ICICLE backend (CPU or CUDA).
2. String Hashing: Demonstrates hashing of basic strings using Keccak-256.
3. Field Element Hashing: Hash Babybear field elements.
4. Batch Hashing: Hash a large batch of field elements and measure the performance.
5. (TODO merkle tree)

## Running the Example

To run the example, use the following commands based on your backend setup:
Use the following commands to run the example based on your backend:

```sh
# For CPU
Expand All @@ -58,5 +93,3 @@ To run the example, use the following commands based on your backend setup:
# For CUDA
./run.sh -d CUDA -b /path/to/cuda/backend/install/dir
```

This will execute the example using either the CPU or CUDA backend, allowing you to test the conversion and computation process between Arkworks and ICICLE.

0 comments on commit ff8bd49

Please sign in to comment.