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

Add get_insert_witness() method to TSMT #211

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fd3888a
chore: update crate version to v0.8
bobbinth Oct 12, 2023
c2853a5
config: add .editorconfig
hackaugusto Oct 19, 2023
3830843
chore: update main readme
bobbinth Oct 19, 2023
ce4abe2
chore: bump winterfell release to .7
Al-Kindi-0 Oct 24, 2023
739febf
rpo: added conversions for digest
hackaugusto Oct 26, 2023
9f6c605
Merge pull request #202 from 0xPolygonMiden/hacka-rpo-digest-conversions
hackaugusto Oct 26, 2023
977638b
feat: RPX (xHash12) hash function implementation
Al-Kindi-0 Oct 24, 2023
f59b481
docs: added RPX benchmarks
Al-Kindi-0 Oct 26, 2023
539dbfa
Merge pull request #201 from 0xPolygonMiden/al-rpx-hash
bobbinth Oct 26, 2023
3a6d31d
docs: update changelog
bobbinth Oct 26, 2023
7038685
mmr: support arbitrary from/to delta updates
hackaugusto Oct 27, 2023
7d3aed0
mmr: support proofs with older forest versions
hackaugusto Oct 27, 2023
0f90589
mmr: publicly export MmrDelta
hackaugusto Oct 27, 2023
4812403
Merge pull request #207 from 0xPolygonMiden/hacka-export-mmr-delta
bobbinth Oct 27, 2023
6251453
Merge pull request #205 from 0xPolygonMiden/hacka-mmr-arbitrary-delta
bobbinth Oct 27, 2023
1c2cb1b
Merge pull request #206 from 0xPolygonMiden/hacka-mmr-proofs-for-olde…
bobbinth Oct 27, 2023
dc20a00
docs: update bench readme
bobbinth Oct 27, 2023
8683429
Merge pull request #200 from 0xPolygonMiden/al-new-winterfell
bobbinth Oct 29, 2023
806e48b
chore: update changelog
bobbinth Oct 29, 2023
f52104b
get_preinsert_pmt
plafer Nov 1, 2023
51d9119
add map
plafer Nov 1, 2023
e0072d6
Rename get_insert_witness
plafer Nov 1, 2023
d9a24d1
check if leaf exists for advice map
plafer Nov 1, 2023
96a8b04
remove outdated docstring
plafer Nov 2, 2023
8b3ab47
advice_map: hold multiple key/values per node
plafer Nov 2, 2023
88994a9
docstring
plafer Nov 2, 2023
e5c29e5
test 1
plafer Nov 2, 2023
a0f6adf
ValueStore: get_key_value_at_index
plafer Nov 2, 2023
c26256b
ValueStore::iter_leaf()
plafer Nov 2, 2023
7b1f732
use iter_leaf()
plafer Nov 2, 2023
2fad797
fix test
plafer Nov 2, 2023
e729a86
add debug_assert
plafer Nov 2, 2023
adb8bc2
fix iter_leaf
plafer Nov 2, 2023
a7528b1
fmt
plafer Nov 2, 2023
3214cfe
remove `ValueStore::iter_leaf()`
plafer Nov 3, 2023
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
20 changes: 20 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Documentation available at editorconfig.org

root=true

[*]
ident_style = space
ident_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.rs]
max_line_length = 100

[*.md]
trim_trailing_whitespace = false

[*.yml]
ident_size = 2
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.8.0 (TBD)

* Implemented the `PartialMmr` data structure (#195).
* Updated Winterfell dependency to v0.7 (#200)
* Implemented RPX hash function (#201).

## 0.7.1 (2023-10-10)

* Fixed RPO Falcon signature build on Windows.
Expand All @@ -12,7 +18,6 @@
* Implemented benchmarking for `TieredSmt` (#182).
* Added more leaf traversal methods for `MerkleStore` (#185).
* Added SVE acceleration for RPO hash function (#189).
* Implemented the `PartialMmr` datastructure (#195).

## 0.6.0 (2023-06-25)

Expand Down
14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[package]
name = "miden-crypto"
version = "0.7.1"
version = "0.8.0"
description = "Miden Cryptographic primitives"
authors = ["miden contributors"]
readme = "README.md"
license = "MIT"
repository = "https://github.com/0xPolygonMiden/crypto"
documentation = "https://docs.rs/miden-crypto/0.7.1"
documentation = "https://docs.rs/miden-crypto/0.8.0"
categories = ["cryptography", "no-std"]
keywords = ["miden", "crypto", "hash", "merkle"]
edition = "2021"
Expand Down Expand Up @@ -42,16 +42,16 @@ sve = ["std"]
blake3 = { version = "1.5", default-features = false }
clap = { version = "4.4", features = ["derive"], optional = true }
libc = { version = "0.2", default-features = false, optional = true }
rand_utils = { version = "0.6", package = "winter-rand-utils", optional = true }
rand_utils = { version = "0.7", package = "winter-rand-utils", optional = true }
serde = { version = "1.0", features = [ "derive" ], default-features = false, optional = true }
winter_crypto = { version = "0.6", package = "winter-crypto", default-features = false }
winter_math = { version = "0.6", package = "winter-math", default-features = false }
winter_utils = { version = "0.6", package = "winter-utils", default-features = false }
winter_crypto = { version = "0.7", package = "winter-crypto", default-features = false }
winter_math = { version = "0.7", package = "winter-math", default-features = false }
winter_utils = { version = "0.7", package = "winter-utils", default-features = false }

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
proptest = "1.3"
rand_utils = { version = "0.6", package = "winter-rand-utils" }
rand_utils = { version = "0.7", package = "winter-rand-utils" }

[build-dependencies]
cc = { version = "1.0", features = ["parallel"], optional = true }
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This crate contains cryptographic primitives used in Polygon Miden.

* [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/).

Expand All @@ -16,6 +17,7 @@ For performance benchmarks of these hash functions and their comparison to other
* `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.
* `TieredSmt`: a Sparse Merkle tree (with compaction), mapping 4-element keys to 4-element values.

Expand Down
35 changes: 18 additions & 17 deletions benches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ In the Miden VM, we make use of different hash functions. Some of these are "tra
* **Poseidon** as specified [here](https://eprint.iacr.org/2019/458.pdf) and implemented [here](https://github.com/mir-protocol/plonky2/blob/806b88d7d6e69a30dc0b4775f7ba275c45e8b63b/plonky2/src/hash/poseidon_goldilocks.rs) (but in pure Rust, without vectorized instructions).
* **Rescue Prime (RP)** as specified [here](https://eprint.iacr.org/2020/1143) and implemented [here](https://github.com/novifinancial/winterfell/blob/46dce1adf0/crypto/src/hash/rescue/rp64_256/mod.rs).
* **Rescue Prime Optimized (RPO)** as specified [here](https://eprint.iacr.org/2022/1577) and implemented in this crate.
* **Rescue Prime Extended (RPX)** a variant of the [xHash](https://eprint.iacr.org/2023/1045) hash function as implemented in this crate.

## Comparison and Instructions

Expand All @@ -15,28 +16,28 @@ The second scenario is that of sequential hashing where we take a sequence of le

#### Scenario 1: 2-to-1 hashing `h(a,b)`

| Function | BLAKE3 | SHA3 | Poseidon | Rp64_256 | RPO_256 |
| ------------------- | ------ | --------| --------- | --------- | ------- |
| Apple M1 Pro | 80 ns | 245 ns | 1.5 us | 9.1 us | 5.4 us |
| Apple M2 | 76 ns | 233 ns | 1.3 us | 7.9 us | 5.0 us |
| Amazon Graviton 3 | 108 ns | | | | 5.3 us |
| AMD Ryzen 9 5950X | 64 ns | 273 ns | 1.2 us | 9.1 us | 5.5 us |
| Intel Core i5-8279U | 80 ns | | | | 8.7 us |
| Intel Xeon 8375C | 67 ns | | | | 8.2 us |
| Function | BLAKE3 | SHA3 | Poseidon | Rp64_256 | RPO_256 | RPX_256 |
| ------------------- | ------ | ------- | --------- | --------- | ------- | ------- |
| Apple M1 Pro | 76 ns | 245 ns | 1.5 µs | 9.1 µs | 5.2 µs | 2.7 µs |
| Apple M2 Max | 71 ns | 233 ns | 1.3 µs | 7.9 µs | 4.6 µs | 2.4 µs |
| Amazon Graviton 3 | 108 ns | | | | 5.3 µs | 3.1 µs |
| AMD Ryzen 9 5950X | 64 ns | 273 ns | 1.2 µs | 9.1 µs | 5.5 µs | |
| Intel Core i5-8279U | 68 ns | 536 ns | 2.0 µs | 13.6 µs | 8.5 µs | 4.4 µs |
| Intel Xeon 8375C | 67 ns | | | | 8.2 µs | |

#### Scenario 2: Sequential hashing of 100 elements `h([a_0,...,a_99])`

| Function | BLAKE3 | SHA3 | Poseidon | Rp64_256 | RPO_256 |
| ------------------- | -------| ------- | --------- | --------- | ------- |
| Apple M1 Pro | 1.0 us | 1.5 us | 19.4 us | 118 us | 70 us |
| Apple M2 | 1.0 us | 1.5 us | 17.4 us | 103 us | 65 us |
| Amazon Graviton 3 | 1.4 us | | | | 69 us |
| AMD Ryzen 9 5950X | 0.8 us | 1.7 us | 15.7 us | 120 us | 72 us |
| Intel Core i5-8279U | 1.0 us | | | | 116 us |
| Intel Xeon 8375C | 0.8 ns | | | | 110 us |
| Function | BLAKE3 | SHA3 | Poseidon | Rp64_256 | RPO_256 | RPX_256 |
| ------------------- | -------| ------- | --------- | --------- | ------- | ------- |
| Apple M1 Pro | 1.0 µs | 1.5 µs | 19.4 µs | 118 µs | 69 µs | 35 µs |
| Apple M2 Max | 0.9 µs | 1.5 µs | 17.4 µs | 103 µs | 60 µs | 31 µs |
| Amazon Graviton 3 | 1.4 µs | | | | 69 µs | 41 µs |
| AMD Ryzen 9 5950X | 0.8 µs | 1.7 µs | 15.7 µs | 120 µs | 72 µs | |
| Intel Core i5-8279U | 0.9 µs | | | | 107 µs | 56 µs |
| Intel Xeon 8375C | 0.8 µs | | | | 110 µs | |

Notes:
- On Graviton 3, RPO256 is run with SVE acceleration enabled.
- On Graviton 3, RPO256 and RPX256 are run with SVE acceleration enabled.

### Instructions
Before you can run the benchmarks, you'll need to make sure you have Rust [installed](https://www.rust-lang.org/tools/install). After that, to run the benchmarks for RPO and BLAKE3, clone the current repository, and from the root directory of the repo run the following:
Expand Down
59 changes: 58 additions & 1 deletion benches/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use miden_crypto::{
hash::{
blake::Blake3_256,
rpo::{Rpo256, RpoDigest},
rpx::{Rpx256, RpxDigest},
},
Felt,
};
Expand Down Expand Up @@ -57,6 +58,54 @@ fn rpo256_sequential(c: &mut Criterion) {
});
}

fn rpx256_2to1(c: &mut Criterion) {
let v: [RpxDigest; 2] = [Rpx256::hash(&[1_u8]), Rpx256::hash(&[2_u8])];
c.bench_function("RPX256 2-to-1 hashing (cached)", |bench| {
bench.iter(|| Rpx256::merge(black_box(&v)))
});

c.bench_function("RPX256 2-to-1 hashing (random)", |bench| {
bench.iter_batched(
|| {
[
Rpx256::hash(&rand_value::<u64>().to_le_bytes()),
Rpx256::hash(&rand_value::<u64>().to_le_bytes()),
]
},
|state| Rpx256::merge(&state),
BatchSize::SmallInput,
)
});
}

fn rpx256_sequential(c: &mut Criterion) {
let v: [Felt; 100] = (0..100)
.into_iter()
.map(Felt::new)
.collect::<Vec<Felt>>()
.try_into()
.expect("should not fail");
c.bench_function("RPX256 sequential hashing (cached)", |bench| {
bench.iter(|| Rpx256::hash_elements(black_box(&v)))
});

c.bench_function("RPX256 sequential hashing (random)", |bench| {
bench.iter_batched(
|| {
let v: [Felt; 100] = (0..100)
.into_iter()
.map(|_| Felt::new(rand_value()))
.collect::<Vec<Felt>>()
.try_into()
.expect("should not fail");
v
},
|state| Rpx256::hash_elements(&state),
BatchSize::SmallInput,
)
});
}

fn blake3_2to1(c: &mut Criterion) {
let v: [<Blake3_256 as Hasher>::Digest; 2] =
[Blake3_256::hash(&[1_u8]), Blake3_256::hash(&[2_u8])];
Expand Down Expand Up @@ -106,5 +155,13 @@ fn blake3_sequential(c: &mut Criterion) {
});
}

criterion_group!(hash_group, rpo256_2to1, rpo256_sequential, blake3_2to1, blake3_sequential);
criterion_group!(
hash_group,
rpx256_2to1,
rpx256_sequential,
rpo256_2to1,
rpo256_sequential,
blake3_2to1,
blake3_sequential
);
criterion_main!(hash_group);
12 changes: 10 additions & 2 deletions src/hash/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
//! Cryptographic hash functions used by the Miden VM and the Miden rollup.

use super::{Felt, FieldElement, StarkField, ONE, ZERO};
use super::{CubeExtension, Felt, FieldElement, StarkField, ONE, ZERO};

pub mod blake;
pub mod rpo;

mod rescue;
pub mod rpo {
pub use super::rescue::{Rpo256, RpoDigest};
}

pub mod rpx {
pub use super::rescue::{Rpx256, RpxDigest};
}

// RE-EXPORTS
// ================================================================================================
Expand Down
9 changes: 5 additions & 4 deletions src/hash/rpo/mds_freq.rs → src/hash/rescue/mds/freq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
/// divisions by 2 and repeated modular reductions. This is because of our explicit choice of
/// an MDS matrix that has small powers of 2 entries in frequency domain.
/// The following implementation has benefited greatly from the discussions and insights of
/// Hamish Ivey-Law and Jacqueline Nabaglo of Polygon Zero.
/// Hamish Ivey-Law and Jacqueline Nabaglo of Polygon Zero and is base on Nabaglo's Plonky2
/// implementation.

// Rescue MDS matrix in frequency domain.
// More precisely, this is the output of the three 4-point (real) FFTs of the first column of
Expand All @@ -26,7 +27,7 @@ const MDS_FREQ_BLOCK_THREE: [i64; 3] = [-8, 1, 1];

// We use split 3 x 4 FFT transform in order to transform our vectors into the frequency domain.
#[inline(always)]
pub(crate) const fn mds_multiply_freq(state: [u64; 12]) -> [u64; 12] {
pub const fn mds_multiply_freq(state: [u64; 12]) -> [u64; 12] {
let [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11] = state;

let (u0, u1, u2) = fft4_real([s0, s3, s6, s9]);
Expand Down Expand Up @@ -156,7 +157,7 @@ const fn block3(x: [i64; 3], y: [i64; 3]) -> [i64; 3] {

#[cfg(test)]
mod tests {
use super::super::{Felt, Rpo256, MDS, ZERO};
use super::super::{apply_mds, Felt, MDS, ZERO};
use proptest::prelude::*;

const STATE_WIDTH: usize = 12;
Expand Down Expand Up @@ -185,7 +186,7 @@ mod tests {
v2 = v1;

apply_mds_naive(&mut v1);
Rpo256::apply_mds(&mut v2);
apply_mds(&mut v2);

prop_assert_eq!(v1, v2);
}
Expand Down
Loading
Loading