* merkle: add parent() helper function on NodeIndex * smt: add pairs_to_leaf() to trait * smt: add sorted_pairs_to_leaves() and test for it * smt: implement single subtree-8 hashing, w/ benchmarks & tests This will be composed into depth-8-subtree-based computation of entire sparse Merkle trees. * merkle: add a benchmark for constructing 256-balanced trees This is intended for comparison with the benchmarks from the previous commit. This benchmark represents the theoretical perfect-efficiency performance we could possibly (but impractically) get for computing depth-8 sparse Merkle subtrees. * smt: test that SparseMerkleTree::build_subtree() is composable * smt: test that subtree logic can correctly construct an entire tree This commit ensures that `SparseMerkleTree::build_subtree()` can correctly compose into building an entire sparse Merkle tree, without yet getting into potential complications concurrency introduces. * smt: implement test for basic parallelized subtree computation w/ rayon Building on the previous commit, this commit implements a test proving that `SparseMerkleTree::build_subtree()` can be composed into itself not just concurrently, but in parallel, without issue. * smt: add from_raw_parts() to trait interface This commit adds a new required method to the SparseMerkleTree trait, to allow generic construction from pre-computed parts. This will be used to add a generic version of `with_entries()` in a later commit. * smt: add parallel constructors to Smt and SimpleSmt What the previous few commits have been leading up to: SparseMerkleTree now has a function to construct the tree from existing data in parallel. This is significantly faster than the singlethreaded equivalent. Benchmarks incoming! --------- Co-authored-by: krushimir <krushimir@reilabs.co> Co-authored-by: krushimir <kresimir.grofelnik@reilabs.io>
109 lines
6.7 KiB
Markdown
109 lines
6.7 KiB
Markdown
# Miden Crypto
|
|
|
|
[](https://github.com/0xPolygonMiden/crypto/blob/main/LICENSE)
|
|
[](https://github.com/0xPolygonMiden/crypto/actions/workflows/test.yml)
|
|
[](https://github.com/0xPolygonMiden/crypto/actions/workflows/build.yml)
|
|
[](https://www.rust-lang.org/tools/install)
|
|
[](https://crates.io/crates/miden-crypto)
|
|
|
|
This crate contains cryptographic primitives used in Polygon Miden.
|
|
|
|
## Hash
|
|
|
|
[Hash module](./src/hash) provides a set of cryptographic hash functions which are used by the Miden VM and the Miden rollup. Currently, these functions are:
|
|
|
|
- [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) hash function with 256-bit, 192-bit, or 160-bit output. The 192-bit and 160-bit outputs are obtained by truncating the 256-bit output of the standard BLAKE3.
|
|
- [RPO](https://eprint.iacr.org/2022/1577) hash function with 256-bit output. This hash function is an algebraic hash function suitable for recursive STARKs.
|
|
- [RPX](https://eprint.iacr.org/2023/1045) hash function with 256-bit output. Similar to RPO, this hash function is suitable for recursive STARKs but it is about 2x faster as compared to RPO.
|
|
|
|
For performance benchmarks of these hash functions and their comparison to other popular hash functions please see [here](./benches/).
|
|
|
|
## Merkle
|
|
|
|
[Merkle module](./src/merkle/) provides a set of data structures related to Merkle trees. All these data structures are implemented using the RPO hash function described above. The data structures are:
|
|
|
|
- `MerkleStore`: a collection of Merkle trees of different heights designed to efficiently store trees with common subtrees. When instantiated with `RecordingMap`, a Merkle store records all accesses to the original data.
|
|
- `MerkleTree`: a regular fully-balanced binary Merkle tree. The depth of this tree can be at most 64.
|
|
- `Mmr`: a Merkle mountain range structure designed to function as an append-only log.
|
|
- `PartialMerkleTree`: a partial view of a Merkle tree where some sub-trees may not be known. This is similar to a collection of Merkle paths all resolving to the same root. The length of the paths can be at most 64.
|
|
- `PartialMmr`: a partial view of a Merkle mountain range structure.
|
|
- `SimpleSmt`: a Sparse Merkle Tree (with no compaction), mapping 64-bit keys to 4-element values.
|
|
- `Smt`: a Sparse Merkle tree (with compaction at depth 64), mapping 4-element keys to 4-element values.
|
|
|
|
The module also contains additional supporting components such as `NodeIndex`, `MerklePath`, and `MerkleError` to assist with tree indexation, opening proofs, and reporting inconsistent arguments/state.
|
|
|
|
## Signatures
|
|
|
|
[DSA module](./src/dsa) provides a set of digital signature schemes supported by default in the Miden VM. Currently, these schemes are:
|
|
|
|
- `RPO Falcon512`: a variant of the [Falcon](https://falcon-sign.info/) signature scheme. This variant differs from the standard in that instead of using SHAKE256 hash function in the _hash-to-point_ algorithm we use RPO256. This makes the signature more efficient to verify in Miden VM.
|
|
|
|
For the above signatures, key generation, signing, and signature verification are available for both `std` and `no_std` contexts (see [crate features](#crate-features) below). However, in `no_std` context, the user is responsible for supplying the key generation and signing procedures with a random number generator.
|
|
|
|
## Pseudo-Random Element Generator
|
|
|
|
[Pseudo random element generator module](./src/rand/) provides a set of traits and data structures that facilitate generating pseudo-random elements in the context of Miden VM and Miden rollup. The module currently includes:
|
|
|
|
- `FeltRng`: a trait for generating random field elements and random 4 field elements.
|
|
- `RpoRandomCoin`: a struct implementing `FeltRng` as well as the [`RandomCoin`](https://github.com/facebook/winterfell/blob/main/crypto/src/random/mod.rs) trait using RPO hash function.
|
|
- `RpxRandomCoin`: a struct implementing `FeltRng` as well as the [`RandomCoin`](https://github.com/facebook/winterfell/blob/main/crypto/src/random/mod.rs) trait using RPX hash function.
|
|
|
|
## Make commands
|
|
|
|
We use `make` to automate building, testing, and other processes. In most cases, `make` commands are wrappers around `cargo` commands with specific arguments. You can view the list of available commands in the [Makefile](Makefile), or run the following command:
|
|
|
|
```shell
|
|
make
|
|
```
|
|
|
|
## Crate features
|
|
|
|
This crate can be compiled with the following features:
|
|
|
|
- `concurrent`- enabled by default; enables multi-threaded implementation of `Smt::with_entries()` which significantly improves performance on multi-core CPUs.
|
|
- `std` - enabled by default and relies on the Rust standard library.
|
|
- `no_std` does not rely on the Rust standard library and enables compilation to WebAssembly.
|
|
|
|
All of these features imply the use of [alloc](https://doc.rust-lang.org/alloc/) to support heap-allocated collections.
|
|
|
|
To compile with `no_std`, disable default features via `--no-default-features` flag or using the following command:
|
|
|
|
```shell
|
|
make build-no-std
|
|
```
|
|
|
|
### AVX2 acceleration
|
|
|
|
On platforms with [AVX2](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions) support, RPO and RPX hash function can be accelerated by using the vector processing unit. To enable AVX2 acceleration, the code needs to be compiled with the `avx2` target feature enabled. For example:
|
|
|
|
```shell
|
|
make build-avx2
|
|
```
|
|
|
|
### SVE acceleration
|
|
|
|
On platforms with [SVE](<https://en.wikipedia.org/wiki/AArch64#Scalable_Vector_Extension_(SVE)>) support, RPO and RPX hash function can be accelerated by using the vector processing unit. To enable SVE acceleration, the code needs to be compiled with the `sve` target feature enabled. For example:
|
|
|
|
```shell
|
|
make build-sve
|
|
```
|
|
|
|
## Testing
|
|
|
|
The best way to test the library is using our [Makefile](Makefile), this will enable you to use our pre-defined optimized testing commands:
|
|
|
|
```shell
|
|
make test
|
|
```
|
|
|
|
For example, some of the functions are heavy and might take a while for the tests to complete if using simply `cargo test`. In order to test in release and optimized mode, we have to replicate the test conditions of the development mode so all debug assertions can be verified.
|
|
|
|
We do that by enabling some special [flags](https://doc.rust-lang.org/cargo/reference/profiles.html) for the compilation (which we have set as a default in our [Makefile](Makefile)):
|
|
|
|
```shell
|
|
RUSTFLAGS="-C debug-assertions -C overflow-checks -C debuginfo=2" cargo test --release
|
|
```
|
|
|
|
## License
|
|
|
|
This project is [MIT licensed](./LICENSE).
|