Skip to content

Commit

Permalink
Add documentation for available accumulators,
Browse files Browse the repository at this point in the history
stores, hashers, and utils.
  • Loading branch information
beeinger committed Nov 10, 2023
1 parent 0152e19 commit 249cbcc
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 53 deletions.
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,43 @@

[![Cargo Test](https://github.com/HerodotusDev/rust-mmr/actions/workflows/ci.yml/badge.svg)](https://github.com/HerodotusDev/rust-mmr/actions/workflows/ci.yml)

## TODO: Description of available accumulators, stores, hashers, etc.
## Accumulators

## TODO: How to use with features, what features are available, etc.
### - [MMR](./src/mmr/README.md)

#### Requires: `features = ["mmr"]`

A Rust implementation of a Merkle Mountain Range (MMR) accumulator. With extensions.

[MMR's README.md](./src/mmr/README.md)

### - [Incremental Merkle Tree](./src/merkle_tree/README.md)

#### Requires: `features = ["incremental_merkle_tree"]`

A Rust implementation of an Incremental Merkle Tree accumulator.

[Incremental Merkle Tree's README.md](./src/merkle_tree/README.md)

## Utils

### Hashers:

Hashing functions used for hashing inside accumulators.

- keccak: `features = ["keccak"]`

- poseidon: `features = ["poseidon"]`

- pedersen: `features = ["pedersen"]`

### Stores:

Key value stores used for storing the accumulator data.

- memory: `features = ["memory"]`

- sqlite: `features = ["sqlite"]`

## Reference

Expand Down
34 changes: 19 additions & 15 deletions src/merkle_tree/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@

Incremental Merkle Tree is a structure that contains a constant amount of hashes, allows updating a given hash and proving efficiently. Time complexity of both operations is O(log tree_size).

#### Requires: `features = ["incremental_merkle_tree"]`

## Example

```rust
use accumulators::{
hasher::stark_poseidon::StarkPoseidonHasher, merkle_tree::incremental::IncrementalMerkleTree,
store::sqlite::SQLiteStore,
};
let store = SQLiteStore::new(":memory:").unwrap();
let hasher = StarkPoseidonHasher::new(Some(false));
store.init().expect("Failed to init store");
let tree = IncrementalMerkleTree::initialize(16, "0x0".to_string(), hasher, store, None);

let path = tree.get_inclusion_proof(10).unwrap();
let valid_proof = tree.verify_proof(10, "0x0", &path).unwrap();
assert_eq!(valid_proof, true);

let invalid_proof = tree.verify_proof(10, "0x1", &path).unwrap();
assert_eq!(invalid_proof, false);
use accumulators::{
hasher::stark_poseidon::StarkPoseidonHasher,
merkle_tree::incremental::IncrementalMerkleTree, store::memory::InMemoryStore,
};

let store = InMemoryStore::new();
let store = Rc::new(store);
let hasher = StarkPoseidonHasher::new(Some(false));

let tree = IncrementalMerkleTree::initialize(16, "0x0".to_string(), hasher, store, None);

let path = tree.get_inclusion_proof(10).unwrap();
let valid_proof = tree.verify_proof(10, "0x0", &path).unwrap();
assert!(valid_proof);

let invalid_proof = tree.verify_proof(10, "0x1", &path).unwrap();
assert!(!invalid_proof);
```

### Benchmark
Expand Down
160 changes: 124 additions & 36 deletions src/mmr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,138 @@

MMR is a structure that allows appending and proving efficiently. Time complexity of both operations is O(log tree_size).

## Example
#### Requires: `features = ["mmr"]`

## Basic Example

```rust
use accumulators::{
hasher::stark_poseidon::StarkPoseidonHasher, mmr::MMR, store::memory::InMemoryStore,
};

let store = InMemoryStore::default();
let store_rc = Rc::new(store);
let hasher = StarkPoseidonHasher::new(Some(false));

let mut mmr = MMR::new(store_rc, hasher, None);

mmr.append("1".to_string()).expect("Failed to append");
mmr.append("2".to_string()).expect("Failed to append");
mmr.append("3".to_string()).expect("Failed to append");
let example_value = "4".to_string();
let example_append = mmr.append(example_value.clone()).expect("Failed to append");

let proof = mmr
.get_proof(example_append.element_index, None)
.expect("Failed to get proof");

assert!(mmr
.verify_proof(proof, example_value, None)
.expect("Failed to verify proof"));
```

## MMR Types

### MMR

The regular MMR, see the example above.

#### Requires: `features = ["mmr"]`

### StackedMMR

An infinitely stackable MMR, used to reduce data duplication when handling multiple MMRs, or handling things like Precomputation and DraftMMRs

#### Requires: `features = ["stacked_mmr"]`

#### Example

```rust
use accumulators::{
hasher::stark_poseidon::StarkPoseidonHasher, mmr::MMR, store::memory::InMemoryStore,
};

let store = InMemoryStore::new();
let store = Rc::new(store);
let hasher = StarkPoseidonHasher::new(Some(false));

let mut mmr = MMR::new(store.clone(), hasher.clone(), None);

let example_value = "1".to_string();
let example_append = mmr.append(example_value.clone()).expect("Failed to append");

let sub_mmrs = vec![(mmr.elements_count.get(), mmr.get_metadata())];

let mut stacked_mmr = MMR::new_stacked(store.clone(), hasher.clone(), None, sub_mmrs.clone());
stacked_mmr
.append("2".to_string())
.expect("Failed to append");

let proof = stacked_mmr
.get_proof(example_append.element_index, None)
.expect("Failed to get proof");

assert!(stacked_mmr
.verify_proof(proof, example_value, None)
.unwrap());
```

### DraftMMR

A MMR built on the StackedMMR, that is used for precomputation of the MMR, which then can be either discarded or committed to the MMR it was made from.

#### Requires: `features = ["draft_mmr"]`

#### Example

```rust
use accumulators::{
hasher::{stark_poseidon::StarkPoseidonHasher, Hasher},
mmr::{
helpers::{AppendResult, Proof, ProofOptions},
MMR,
},
store::sqlite::SQLiteStore,
hasher::stark_poseidon::StarkPoseidonHasher, mmr::MMR, store::memory::InMemoryStore,
};

let store = SQLiteStore::new(":memory:").unwrap();
let store = InMemoryStore::new();
let store = Rc::new(store);
let hasher = StarkPoseidonHasher::new(Some(false));
store.init().expect("Failed to init store");

let mut mmr = MMR::new(store, hasher.clone(), None);

let _ = mmr.append("1".to_string()).unwrap();
let _ = mmr.append("2".to_string()).unwrap();
let _ = mmr.append("3".to_string()).unwrap();
let append_result = mmr.append("4".to_string()).unwrap();

let proof4 = mmr
.get_proof(append_result.element_index,
ProofOptions {
elements_count: None,
formatting_opts: None,
},
)
.unwrap();

mmr.verify_proof(
proof4,
"4".to_string(),
ProofOptions {
elements_count: None,
formatting_opts: None,
},
)
.unwrap(); //return true

let mut mmr = MMR::new(store.clone(), hasher.clone(), None);

mmr.append("1".to_string()).expect("Failed to append");
mmr.append("2".to_string()).expect("Failed to append");

let mut draft = mmr.start_draft();
draft.mmr.append("3".to_string()).expect("Failed to append");
draft.mmr.append("4".to_string()).expect("Failed to append");

let draft_bag = draft.mmr.bag_the_peaks(None).unwrap();
let draft_root = draft
.mmr
.calculate_root_hash(&draft_bag, draft.mmr.elements_count.get())
.expect("Failed to calculate root hash");

draft.commit();

let bag = mmr.bag_the_peaks(None).unwrap();
let root = mmr
.calculate_root_hash(&bag, mmr.elements_count.get())
.expect("Failed to calculate root hash");

assert_eq!(draft_root, root);

let mut draft = mmr.start_draft();
draft.mmr.append("5".to_string()).expect("Failed to append");
draft.mmr.append("6".to_string()).expect("Failed to append");

draft.discard();

let after_discard_bag = mmr.bag_the_peaks(None).unwrap();
let after_discard_root = mmr
.calculate_root_hash(&after_discard_bag, mmr.elements_count.get())
.expect("Failed to calculate root hash");

assert_eq!(after_discard_root, root);
```

### Benchmark
## Benchmarks

```sh
MMR insertion/times/10000
Expand Down

0 comments on commit 249cbcc

Please sign in to comment.