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

Update Dev docs for Poseidon2 #710

Closed
wants to merge 4 commits into from
Closed
Changes from 3 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
79 changes: 79 additions & 0 deletions docs/docs/icicle/primitives/hash.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,85 @@ The S box power alpha, number of full rounds and partial rounds, rounds constant

In the current version the padding is not supported and should be performed by the user.

#### Supported Bindings

[`Rust`](https://github.com/ingonyama-zk/icicle/tree/main/wrappers/rust/icicle-core/src/poseidon2)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go also supports Poseidon2, although it is per curve/field, for example for bn254

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

[`Go`](https://github.com/ingonyama-zk/icicle/blob/main/wrappers/golang/curves/bn254/poseidon2/poseidon2.go)


#### Rust API
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont understand what this should be here. Maybe in the rust page as a poseidon2 example below.
https://github.com/ingonyama-zk/icicle/blob/main/docs/docs/icicle/rust-bindings/hash.md


This is the most basic way to use the Poseidon2 API. See the [examples/poseidon2](https://github.com/ingonyama-zk/icicle/tree/b12d83e6bcb8ee598409de78015bd118458a55d0/examples/rust/poseidon2) folder for the relevant code
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this commit? is it merged to main?


```rust
let test_size = 4;
let poseidon = Poseidon2::new::<F>(test_size,None).unwrap();
let config = HashConfig::default();
let inputs = vec![F::one(); test_size];
let input_slice = HostSlice::from_slice(&inputs);
//digest is a single element
let out_init:F = F::zero();
let mut binding = [out_init];
let out_init_slice = HostSlice::from_mut_slice(&mut binding);

poseidon.hash(input_slice, &config, out_init_slice).unwrap();
println!("computed digest: {:?} ",out_init_slice.as_slice().to_vec()[0]);
```

#### Merkle Tree Builder

You can use Poseidon2 in a Merkle tree builder. See the [examples/poseidon2](https://github.com/ingonyama-zk/icicle/tree/b12d83e6bcb8ee598409de78015bd118458a55d0/examples/rust/poseidon2) folder for the relevant code.

```rust
pub fn compute_binary_tree<F:FieldImpl>(
mut test_vec: Vec<F>,
leaf_size: u64,
hasher: Hasher,
compress: Hasher,
mut tree_config: MerkleTreeConfig,
) -> MerkleTree
{
let tree_height: usize = test_vec.len().ilog2() as usize;
//just to be safe
tree_config.padding_policy = PaddingPolicy::ZeroPadding;
let layer_hashes: Vec<&Hasher> = std::iter::once(&hasher)
.chain(std::iter::repeat(&compress).take(tree_height))
.collect();
let vec_slice: &mut HostSlice<F> = HostSlice::from_mut_slice(&mut test_vec[..]);
let merkle_tree: MerkleTree = MerkleTree::new(&layer_hashes, leaf_size, 0).unwrap();

let _ = merkle_tree
.build(vec_slice,&tree_config);
merkle_tree
}

//poseidon2 supports t=2,3,4,8,12,16,20,24. In this example we build a binary tree with Poseidon2 t=2.
let poseidon_state_size = 2;
let leaf_size:u64 = 4;// each leaf is a 32 bit element 32/8 = 4 bytes

let mut test_vec = vec![F::from_u32(random::<u32>()); 1024* (poseidon_state_size as usize)];
println!("Generated random vector of size {:?}", 1024* (poseidon_state_size as usize));
//to use later for merkle proof
let mut binding = test_vec.clone();
let test_vec_slice = HostSlice::from_mut_slice(&mut binding);
//define hash and compression functions (You can use different hashes here)
//note:"None" does not work with generics, use F= Fm31, Fbabybear etc
let hasher :Hasher = Poseidon2::new::<F>(poseidon_state_size.try_into().unwrap(),None).unwrap();
let compress: Hasher = Poseidon2::new::<F>((hasher.output_size()*2).try_into().unwrap(),None).unwrap();
//tree config
let tree_config = MerkleTreeConfig::default();
let merk_tree = compute_binary_tree(test_vec.clone(), leaf_size, hasher, compress,tree_config.clone());
println!("computed Merkle root {:?}", merk_tree.get_root::<F>().unwrap());

let random_test_index = rand::thread_rng().gen_range(0..1024*(poseidon_state_size as usize));
print!("Generating proof for element {:?} at random test index {:?} ",test_vec[random_test_index], random_test_index);
let merkle_proof = merk_tree.get_proof::<F>(test_vec_slice, random_test_index.try_into().unwrap(), false, &tree_config).unwrap();

//actually should construct verifier tree :)
assert!(merk_tree.verify(&merkle_proof).unwrap());
println!("\n Merkle proof verified successfully!");
```

## Using Hash API

### 1. Creating a Hasher Object
Expand Down
Loading