From 50dd6bda1970596f78558e3d4aa705958696e58f Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:16:27 +0100 Subject: [PATCH 1/6] fix: skip using the field element containing the proof-of-work (#343) --- CHANGELOG.md | 1 + src/rand/rpo.rs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc22853c..562dff6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.11.0 (2024-10-30) - [BREAKING] Updated Winterfell dependency to v0.10 (#338). +- Fixed a bug in the implementation of `draw_integers` for `RpoRandomCoin` (#343). ## 0.11.0 (2024-10-17) diff --git a/src/rand/rpo.rs b/src/rand/rpo.rs index a6add393..2669592f 100644 --- a/src/rand/rpo.rs +++ b/src/rand/rpo.rs @@ -145,8 +145,10 @@ impl RandomCoin for RpoRandomCoin { self.state[RATE_START] += nonce; Rpo256::apply_permutation(&mut self.state); - // reset the buffer - self.current = RATE_START; + // reset the buffer and move the next random element pointer to the second rate element. + // this is done as the first rate element will be "biased" via the provided `nonce` to + // contain some number of leading zeros. + self.current = RATE_START + 1; // determine how many bits are needed to represent valid values in the domain let v_mask = (domain_size - 1) as u64; From a27f9ad8280f4a926b5d85d9ea15dbb76ab9277d Mon Sep 17 00:00:00 2001 From: Philipp Gackstatter Date: Fri, 22 Nov 2024 00:52:20 +0100 Subject: [PATCH 2/6] refactor: use `thiserror` to derive errors and update error messages (#344) --- CHANGELOG.md | 8 +- Cargo.lock | 36 +++++++- Cargo.toml | 2 + src/hash/rescue/rpo/digest.rs | 85 ++++++++++++++----- src/hash/rescue/rpx/digest.rs | 85 ++++++++++++++----- src/merkle/error.rs | 81 ++++++------------ src/merkle/index.rs | 11 +-- src/merkle/mmr/error.rs | 56 +++++------- src/merkle/mmr/full.rs | 11 ++- src/merkle/mmr/partial.rs | 15 ++-- src/merkle/mmr/peaks.rs | 10 ++- src/merkle/partial_mt/mod.rs | 24 ++++-- src/merkle/path.rs | 5 +- src/merkle/smt/full/error.rs | 81 ++++-------------- src/merkle/smt/full/leaf.rs | 15 ++-- src/merkle/smt/full/proof.rs | 2 +- src/merkle/smt/mod.rs | 7 +- src/merkle/smt/simple/mod.rs | 4 +- src/merkle/smt/simple/tests.rs | 6 +- src/merkle/store/mod.rs | 10 ++- src/merkle/store/tests.rs | 151 +++++++++++++++++---------------- src/utils/mod.rs | 34 +++----- 22 files changed, 392 insertions(+), 347 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 562dff6d..832a19be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ -## 0.11.0 (2024-10-30) +## 0.13.0 (TBD) -- [BREAKING] Updated Winterfell dependency to v0.10 (#338). - Fixed a bug in the implementation of `draw_integers` for `RpoRandomCoin` (#343). +- [BREAKING] Refactor error messages and use `thiserror` to derive errors (#344). + +## 0.12.0 (2024-10-30) + +- [BREAKING] Updated Winterfell dependency to v0.10 (#338). ## 0.11.0 (2024-10-17) diff --git a/Cargo.lock b/Cargo.lock index 3e822fb3..ebb0da25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,6 +78,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "autocfg" version = "1.4.0" @@ -521,6 +527,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" name = "miden-crypto" version = "0.12.0" dependencies = [ + "assert_matches", "blake3", "cc", "clap", @@ -537,6 +544,7 @@ dependencies = [ "seq-macro", "serde", "sha3", + "thiserror", "winter-crypto", "winter-math", "winter-rand-utils", @@ -668,9 +676,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "307e3004becf10f5a6e0d59d20f3cd28231b0e0827a96cd3e0ce6d14bc1e4bb3" dependencies = [ "unicode-ident", ] @@ -900,9 +908,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.85" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -922,6 +930,26 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tinytemplate" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index 5d124c68..2ccfc3f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,11 +55,13 @@ rand_core = { version = "0.6", default-features = false } rand-utils = { version = "0.10", package = "winter-rand-utils", optional = true } serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } sha3 = { version = "0.10", default-features = false } +thiserror = { version = "2.0", default-features = false } winter-crypto = { version = "0.10", default-features = false } winter-math = { version = "0.10", default-features = false } winter-utils = { version = "0.10", default-features = false } [dev-dependencies] +assert_matches = { version = "1.5.0", default-features = false } criterion = { version = "0.5", features = ["html_reports"] } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4", default-features = false, features = ["alloc"] } diff --git a/src/hash/rescue/rpo/digest.rs b/src/hash/rescue/rpo/digest.rs index 67d73e31..44663691 100644 --- a/src/hash/rescue/rpo/digest.rs +++ b/src/hash/rescue/rpo/digest.rs @@ -1,6 +1,8 @@ use alloc::string::String; use core::{cmp::Ordering, fmt::Display, ops::Deref, slice}; +use thiserror::Error; + use super::{Digest, Felt, StarkField, DIGEST_BYTES, DIGEST_SIZE, ZERO}; use crate::{ rand::Randomizable, @@ -127,9 +129,12 @@ impl Randomizable for RpoDigest { // CONVERSIONS: FROM RPO DIGEST // ================================================================================================ -#[derive(Copy, Clone, Debug)] +#[derive(Debug, Error)] pub enum RpoDigestError { - InvalidInteger, + #[error("failed to convert digest field element to {0}")] + TypeConversion(&'static str), + #[error("failed to convert to field element: {0}")] + InvalidFieldElement(String), } impl TryFrom<&RpoDigest> for [bool; DIGEST_SIZE] { @@ -153,10 +158,10 @@ impl TryFrom for [bool; DIGEST_SIZE] { } Ok([ - to_bool(value.0[0].as_int()).ok_or(RpoDigestError::InvalidInteger)?, - to_bool(value.0[1].as_int()).ok_or(RpoDigestError::InvalidInteger)?, - to_bool(value.0[2].as_int()).ok_or(RpoDigestError::InvalidInteger)?, - to_bool(value.0[3].as_int()).ok_or(RpoDigestError::InvalidInteger)?, + to_bool(value.0[0].as_int()).ok_or(RpoDigestError::TypeConversion("bool"))?, + to_bool(value.0[1].as_int()).ok_or(RpoDigestError::TypeConversion("bool"))?, + to_bool(value.0[2].as_int()).ok_or(RpoDigestError::TypeConversion("bool"))?, + to_bool(value.0[3].as_int()).ok_or(RpoDigestError::TypeConversion("bool"))?, ]) } } @@ -174,10 +179,22 @@ impl TryFrom for [u8; DIGEST_SIZE] { fn try_from(value: RpoDigest) -> Result { Ok([ - value.0[0].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[1].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[2].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[3].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, + value.0[0] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u8"))?, + value.0[1] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u8"))?, + value.0[2] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u8"))?, + value.0[3] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u8"))?, ]) } } @@ -195,10 +212,22 @@ impl TryFrom for [u16; DIGEST_SIZE] { fn try_from(value: RpoDigest) -> Result { Ok([ - value.0[0].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[1].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[2].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[3].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, + value.0[0] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u16"))?, + value.0[1] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u16"))?, + value.0[2] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u16"))?, + value.0[3] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u16"))?, ]) } } @@ -216,10 +245,22 @@ impl TryFrom for [u32; DIGEST_SIZE] { fn try_from(value: RpoDigest) -> Result { Ok([ - value.0[0].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[1].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[2].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value.0[3].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?, + value.0[0] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u32"))?, + value.0[1] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u32"))?, + value.0[2] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u32"))?, + value.0[3] + .as_int() + .try_into() + .map_err(|_| RpoDigestError::TypeConversion("u32"))?, ]) } } @@ -343,10 +384,10 @@ impl TryFrom<[u64; DIGEST_SIZE]> for RpoDigest { fn try_from(value: [u64; DIGEST_SIZE]) -> Result { Ok(Self([ - value[0].try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value[1].try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value[2].try_into().map_err(|_| RpoDigestError::InvalidInteger)?, - value[3].try_into().map_err(|_| RpoDigestError::InvalidInteger)?, + value[0].try_into().map_err(RpoDigestError::InvalidFieldElement)?, + value[1].try_into().map_err(RpoDigestError::InvalidFieldElement)?, + value[2].try_into().map_err(RpoDigestError::InvalidFieldElement)?, + value[3].try_into().map_err(RpoDigestError::InvalidFieldElement)?, ])) } } diff --git a/src/hash/rescue/rpx/digest.rs b/src/hash/rescue/rpx/digest.rs index 8f953fc6..07ec3c66 100644 --- a/src/hash/rescue/rpx/digest.rs +++ b/src/hash/rescue/rpx/digest.rs @@ -1,6 +1,8 @@ use alloc::string::String; use core::{cmp::Ordering, fmt::Display, ops::Deref, slice}; +use thiserror::Error; + use super::{Digest, Felt, StarkField, DIGEST_BYTES, DIGEST_SIZE, ZERO}; use crate::{ rand::Randomizable, @@ -127,9 +129,12 @@ impl Randomizable for RpxDigest { // CONVERSIONS: FROM RPX DIGEST // ================================================================================================ -#[derive(Copy, Clone, Debug)] +#[derive(Debug, Error)] pub enum RpxDigestError { - InvalidInteger, + #[error("failed to convert digest field element to {0}")] + TypeConversion(&'static str), + #[error("failed to convert to field element: {0}")] + InvalidFieldElement(String), } impl TryFrom<&RpxDigest> for [bool; DIGEST_SIZE] { @@ -153,10 +158,10 @@ impl TryFrom for [bool; DIGEST_SIZE] { } Ok([ - to_bool(value.0[0].as_int()).ok_or(RpxDigestError::InvalidInteger)?, - to_bool(value.0[1].as_int()).ok_or(RpxDigestError::InvalidInteger)?, - to_bool(value.0[2].as_int()).ok_or(RpxDigestError::InvalidInteger)?, - to_bool(value.0[3].as_int()).ok_or(RpxDigestError::InvalidInteger)?, + to_bool(value.0[0].as_int()).ok_or(RpxDigestError::TypeConversion("bool"))?, + to_bool(value.0[1].as_int()).ok_or(RpxDigestError::TypeConversion("bool"))?, + to_bool(value.0[2].as_int()).ok_or(RpxDigestError::TypeConversion("bool"))?, + to_bool(value.0[3].as_int()).ok_or(RpxDigestError::TypeConversion("bool"))?, ]) } } @@ -174,10 +179,22 @@ impl TryFrom for [u8; DIGEST_SIZE] { fn try_from(value: RpxDigest) -> Result { Ok([ - value.0[0].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[1].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[2].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[3].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, + value.0[0] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u8"))?, + value.0[1] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u8"))?, + value.0[2] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u8"))?, + value.0[3] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u8"))?, ]) } } @@ -195,10 +212,22 @@ impl TryFrom for [u16; DIGEST_SIZE] { fn try_from(value: RpxDigest) -> Result { Ok([ - value.0[0].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[1].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[2].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[3].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, + value.0[0] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u16"))?, + value.0[1] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u16"))?, + value.0[2] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u16"))?, + value.0[3] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u16"))?, ]) } } @@ -216,10 +245,22 @@ impl TryFrom for [u32; DIGEST_SIZE] { fn try_from(value: RpxDigest) -> Result { Ok([ - value.0[0].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[1].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[2].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value.0[3].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?, + value.0[0] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u32"))?, + value.0[1] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u32"))?, + value.0[2] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u32"))?, + value.0[3] + .as_int() + .try_into() + .map_err(|_| RpxDigestError::TypeConversion("u32"))?, ]) } } @@ -343,10 +384,10 @@ impl TryFrom<[u64; DIGEST_SIZE]> for RpxDigest { fn try_from(value: [u64; DIGEST_SIZE]) -> Result { Ok(Self([ - value[0].try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value[1].try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value[2].try_into().map_err(|_| RpxDigestError::InvalidInteger)?, - value[3].try_into().map_err(|_| RpxDigestError::InvalidInteger)?, + value[0].try_into().map_err(RpxDigestError::InvalidFieldElement)?, + value[1].try_into().map_err(RpxDigestError::InvalidFieldElement)?, + value[2].try_into().map_err(RpxDigestError::InvalidFieldElement)?, + value[3].try_into().map_err(RpxDigestError::InvalidFieldElement)?, ])) } } diff --git a/src/merkle/error.rs b/src/merkle/error.rs index 68e531ba..c7eff709 100644 --- a/src/merkle/error.rs +++ b/src/merkle/error.rs @@ -1,65 +1,34 @@ -use alloc::vec::Vec; -use core::fmt; +use thiserror::Error; -use super::{smt::SmtLeafError, MerklePath, NodeIndex, RpoDigest}; +use super::{NodeIndex, RpoDigest}; -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Debug, Error)] pub enum MerkleError { - ConflictingRoots(Vec), + #[error("expected merkle root {expected_root} found {actual_root}")] + ConflictingRoots { + expected_root: RpoDigest, + actual_root: RpoDigest, + }, + #[error("provided merkle tree depth {0} is too small")] DepthTooSmall(u8), + #[error("provided merkle tree depth {0} is too big")] DepthTooBig(u64), + #[error("multiple values provided for merkle tree index {0}")] DuplicateValuesForIndex(u64), - DuplicateValuesForKey(RpoDigest), - InvalidIndex { depth: u8, value: u64 }, - InvalidDepth { expected: u8, provided: u8 }, - InvalidSubtreeDepth { subtree_depth: u8, tree_depth: u8 }, - InvalidPath(MerklePath), - InvalidNumEntries(usize), - NodeNotInSet(NodeIndex), - NodeNotInStore(RpoDigest, NodeIndex), + #[error("node index value {value} is not valid for depth {depth}")] + InvalidNodeIndex { depth: u8, value: u64 }, + #[error("provided node index depth {provided} does not match expected depth {expected}")] + InvalidNodeIndexDepth { expected: u8, provided: u8 }, + #[error("merkle subtree depth {subtree_depth} exceeds merkle tree depth {tree_depth}")] + SubtreeDepthExceedsDepth { subtree_depth: u8, tree_depth: u8 }, + #[error("number of entries in the merkle tree exceeds the maximum of {0}")] + TooManyEntries(usize), + #[error("node index `{0}` not found in the tree")] + NodeIndexNotFoundInTree(NodeIndex), + #[error("node {0:?} with index `{1}` not found in the store")] + NodeIndexNotFoundInStore(RpoDigest, NodeIndex), + #[error("number of provided merkle tree leaves {0} is not a power of two")] NumLeavesNotPowerOfTwo(usize), + #[error("root {0:?} is not in the store")] RootNotInStore(RpoDigest), - SmtLeaf(SmtLeafError), -} - -impl fmt::Display for MerkleError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use MerkleError::*; - match self { - ConflictingRoots(roots) => write!(f, "the merkle paths roots do not match {roots:?}"), - DepthTooSmall(depth) => write!(f, "the provided depth {depth} is too small"), - DepthTooBig(depth) => write!(f, "the provided depth {depth} is too big"), - DuplicateValuesForIndex(key) => write!(f, "multiple values provided for key {key}"), - DuplicateValuesForKey(key) => write!(f, "multiple values provided for key {key}"), - InvalidIndex { depth, value } => { - write!(f, "the index value {value} is not valid for the depth {depth}") - }, - InvalidDepth { expected, provided } => { - write!(f, "the provided depth {provided} is not valid for {expected}") - }, - InvalidSubtreeDepth { subtree_depth, tree_depth } => { - write!(f, "tried inserting a subtree of depth {subtree_depth} into a tree of depth {tree_depth}") - }, - InvalidPath(_path) => write!(f, "the provided path is not valid"), - InvalidNumEntries(max) => write!(f, "number of entries exceeded the maximum: {max}"), - NodeNotInSet(index) => write!(f, "the node with index ({index}) is not in the set"), - NodeNotInStore(hash, index) => { - write!(f, "the node {hash:?} with index ({index}) is not in the store") - }, - NumLeavesNotPowerOfTwo(leaves) => { - write!(f, "the leaves count {leaves} is not a power of 2") - }, - RootNotInStore(root) => write!(f, "the root {:?} is not in the store", root), - SmtLeaf(smt_leaf_error) => write!(f, "smt leaf error: {smt_leaf_error}"), - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for MerkleError {} - -impl From for MerkleError { - fn from(value: SmtLeafError) -> Self { - Self::SmtLeaf(value) - } } diff --git a/src/merkle/index.rs b/src/merkle/index.rs index 104ceb44..d4887b7d 100644 --- a/src/merkle/index.rs +++ b/src/merkle/index.rs @@ -38,7 +38,7 @@ impl NodeIndex { /// Returns an error if the `value` is greater than or equal to 2^{depth}. pub const fn new(depth: u8, value: u64) -> Result { if (64 - value.leading_zeros()) > depth as u32 { - Err(MerkleError::InvalidIndex { depth, value }) + Err(MerkleError::InvalidNodeIndex { depth, value }) } else { Ok(Self { depth, value }) } @@ -182,6 +182,7 @@ impl Deserializable for NodeIndex { #[cfg(test)] mod tests { + use assert_matches::assert_matches; use proptest::prelude::*; use super::*; @@ -190,19 +191,19 @@ mod tests { fn test_node_index_value_too_high() { assert_eq!(NodeIndex::new(0, 0).unwrap(), NodeIndex { depth: 0, value: 0 }); let err = NodeIndex::new(0, 1).unwrap_err(); - assert_eq!(err, MerkleError::InvalidIndex { depth: 0, value: 1 }); + assert_matches!(err, MerkleError::InvalidNodeIndex { depth: 0, value: 1 }); assert_eq!(NodeIndex::new(1, 1).unwrap(), NodeIndex { depth: 1, value: 1 }); let err = NodeIndex::new(1, 2).unwrap_err(); - assert_eq!(err, MerkleError::InvalidIndex { depth: 1, value: 2 }); + assert_matches!(err, MerkleError::InvalidNodeIndex { depth: 1, value: 2 }); assert_eq!(NodeIndex::new(2, 3).unwrap(), NodeIndex { depth: 2, value: 3 }); let err = NodeIndex::new(2, 4).unwrap_err(); - assert_eq!(err, MerkleError::InvalidIndex { depth: 2, value: 4 }); + assert_matches!(err, MerkleError::InvalidNodeIndex { depth: 2, value: 4 }); assert_eq!(NodeIndex::new(3, 7).unwrap(), NodeIndex { depth: 3, value: 7 }); let err = NodeIndex::new(3, 8).unwrap_err(); - assert_eq!(err, MerkleError::InvalidIndex { depth: 3, value: 8 }); + assert_matches!(err, MerkleError::InvalidNodeIndex { depth: 3, value: 8 }); } #[test] diff --git a/src/merkle/mmr/error.rs b/src/merkle/mmr/error.rs index 5bede2d3..f26cc5cb 100644 --- a/src/merkle/mmr/error.rs +++ b/src/merkle/mmr/error.rs @@ -1,41 +1,27 @@ -use core::fmt::{Display, Formatter}; -#[cfg(feature = "std")] -use std::error::Error; +use alloc::string::String; + +use thiserror::Error; use crate::merkle::MerkleError; -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Error)] pub enum MmrError { - InvalidPosition(usize), - InvalidPeaks, - InvalidPeak, - PeakOutOfBounds(usize, usize), + #[error("mmr does not contain position {0}")] + PositionNotFound(usize), + #[error("mmr peaks are invalid: {0}")] + InvalidPeaks(String), + #[error( + "mmr peak does not match the computed merkle root of the provided authentication path" + )] + PeakPathMismatch, + #[error("requested peak index is {peak_idx} but the number of peaks is {peaks_len}")] + PeakOutOfBounds { peak_idx: usize, peaks_len: usize }, + #[error("invalid mmr update")] InvalidUpdate, - UnknownPeak, - MerkleError(MerkleError), -} - -impl Display for MmrError { - fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { - match self { - MmrError::InvalidPosition(pos) => write!(fmt, "Mmr does not contain position {pos}"), - MmrError::InvalidPeaks => write!(fmt, "Invalid peaks count"), - MmrError::InvalidPeak => { - write!(fmt, "Peak values does not match merkle path computed root") - }, - MmrError::PeakOutOfBounds(peak_idx, peaks_len) => write!( - fmt, - "Requested peak index is {} but the number of peaks is {}", - peak_idx, peaks_len - ), - MmrError::InvalidUpdate => write!(fmt, "Invalid Mmr update"), - MmrError::UnknownPeak => { - write!(fmt, "Peak not in Mmr") - }, - MmrError::MerkleError(err) => write!(fmt, "{}", err), - } - } + #[error("mmr does not contain a peak with depth {0}")] + UnknownPeak(u8), + #[error("invalid merkle path")] + InvalidMerklePath(#[source] MerkleError), + #[error("merkle root computation failed")] + MerkleRootComputationFailed(#[source] MerkleError), } - -#[cfg(feature = "std")] -impl Error for MmrError {} diff --git a/src/merkle/mmr/full.rs b/src/merkle/mmr/full.rs index 036cd900..e381f5de 100644 --- a/src/merkle/mmr/full.rs +++ b/src/merkle/mmr/full.rs @@ -99,7 +99,7 @@ impl Mmr { pub fn open_at(&self, pos: usize, forest: usize) -> Result { // find the target tree responsible for the MMR position let tree_bit = - leaf_to_corresponding_tree(pos, forest).ok_or(MmrError::InvalidPosition(pos))?; + leaf_to_corresponding_tree(pos, forest).ok_or(MmrError::PositionNotFound(pos))?; // isolate the trees before the target let forest_before = forest & high_bitmask(tree_bit + 1); @@ -126,7 +126,7 @@ impl Mmr { pub fn get(&self, pos: usize) -> Result { // find the target tree responsible for the MMR position let tree_bit = - leaf_to_corresponding_tree(pos, self.forest).ok_or(MmrError::InvalidPosition(pos))?; + leaf_to_corresponding_tree(pos, self.forest).ok_or(MmrError::PositionNotFound(pos))?; // isolate the trees before the target let forest_before = self.forest & high_bitmask(tree_bit + 1); @@ -174,7 +174,10 @@ impl Mmr { /// Returns an error if the specified `forest` value is not valid for this MMR. pub fn peaks_at(&self, forest: usize) -> Result { if forest > self.forest { - return Err(MmrError::InvalidPeaks); + return Err(MmrError::InvalidPeaks(format!( + "requested forest {forest} exceeds current forest {}", + self.forest + ))); } let peaks: Vec = TrueBitPositionIterator::new(forest) @@ -199,7 +202,7 @@ impl Mmr { /// that have been merged together, followed by the new peaks of the [Mmr]. pub fn get_delta(&self, from_forest: usize, to_forest: usize) -> Result { if to_forest > self.forest || from_forest > to_forest { - return Err(MmrError::InvalidPeaks); + return Err(MmrError::InvalidPeaks(format!("to_forest {to_forest} exceeds the current forest {} or from_forest {from_forest} exceeds to_forest", self.forest))); } if from_forest == to_forest { diff --git a/src/merkle/mmr/partial.rs b/src/merkle/mmr/partial.rs index b2c49f92..5327548d 100644 --- a/src/merkle/mmr/partial.rs +++ b/src/merkle/mmr/partial.rs @@ -145,7 +145,7 @@ impl PartialMmr { /// in the underlying MMR. pub fn open(&self, pos: usize) -> Result, MmrError> { let tree_bit = - leaf_to_corresponding_tree(pos, self.forest).ok_or(MmrError::InvalidPosition(pos))?; + leaf_to_corresponding_tree(pos, self.forest).ok_or(MmrError::PositionNotFound(pos))?; let depth = tree_bit as usize; let mut nodes = Vec::with_capacity(depth); @@ -298,7 +298,7 @@ impl PartialMmr { // invalid. let tree = 1 << path.depth(); if tree & self.forest == 0 { - return Err(MmrError::UnknownPeak); + return Err(MmrError::UnknownPeak(path.depth())); }; if leaf_pos + 1 == self.forest @@ -319,9 +319,11 @@ impl PartialMmr { // Compute the root of the authentication path, and check it matches the current version of // the PartialMmr. - let computed = path.compute_root(path_idx as u64, leaf).map_err(MmrError::MerkleError)?; + let computed = path + .compute_root(path_idx as u64, leaf) + .map_err(MmrError::MerkleRootComputationFailed)?; if self.peaks[peak_pos] != computed { - return Err(MmrError::InvalidPeak); + return Err(MmrError::PeakPathMismatch); } let mut idx = InOrderIndex::from_leaf_pos(leaf_pos); @@ -356,7 +358,10 @@ impl PartialMmr { /// inserted into the partial MMR. pub fn apply(&mut self, delta: MmrDelta) -> Result, MmrError> { if delta.forest < self.forest { - return Err(MmrError::InvalidPeaks); + return Err(MmrError::InvalidPeaks(format!( + "forest of mmr delta {} is less than current forest {}", + delta.forest, self.forest + ))); } let mut inserted_nodes = Vec::new(); diff --git a/src/merkle/mmr/peaks.rs b/src/merkle/mmr/peaks.rs index ae39aafc..a640afda 100644 --- a/src/merkle/mmr/peaks.rs +++ b/src/merkle/mmr/peaks.rs @@ -45,7 +45,11 @@ impl MmrPeaks { /// Returns an error if the number of leaves and the number of peaks are inconsistent. pub fn new(num_leaves: usize, peaks: Vec) -> Result { if num_leaves.count_ones() as usize != peaks.len() { - return Err(MmrError::InvalidPeaks); + return Err(MmrError::InvalidPeaks(format!( + "number of one bits in leaves is {} which does not equal peak length {}", + num_leaves.count_ones(), + peaks.len() + ))); } Ok(Self { num_leaves, peaks }) @@ -77,7 +81,7 @@ impl MmrPeaks { pub fn get_peak(&self, peak_idx: usize) -> Result<&RpoDigest, MmrError> { self.peaks .get(peak_idx) - .ok_or(MmrError::PeakOutOfBounds(peak_idx, self.peaks.len())) + .ok_or(MmrError::PeakOutOfBounds { peak_idx, peaks_len: self.peaks.len() }) } /// Converts this [MmrPeaks] into its components: number of leaves and a vector of peaks of @@ -106,7 +110,7 @@ impl MmrPeaks { opening .merkle_path .verify(opening.relative_pos() as u64, value, root) - .map_err(MmrError::MerkleError) + .map_err(MmrError::InvalidMerklePath) } /// Flattens and pads the peaks to make hashing inside of the Miden VM easier. diff --git a/src/merkle/partial_mt/mod.rs b/src/merkle/partial_mt/mod.rs index ef464327..ae4a04ff 100644 --- a/src/merkle/partial_mt/mod.rs +++ b/src/merkle/partial_mt/mod.rs @@ -116,7 +116,7 @@ impl PartialMerkleTree { // depth of 63 because we consider passing in a vector of size 2^64 infeasible. let max = 2usize.pow(63); if layers.len() > max { - return Err(MerkleError::InvalidNumEntries(max)); + return Err(MerkleError::TooManyEntries(max)); } // Get maximum depth @@ -147,11 +147,12 @@ impl PartialMerkleTree { let index = NodeIndex::new(depth, index_value)?; // get hash of the current node - let node = nodes.get(&index).ok_or(MerkleError::NodeNotInSet(index))?; + let node = + nodes.get(&index).ok_or(MerkleError::NodeIndexNotFoundInTree(index))?; // get hash of the sibling node let sibling = nodes .get(&index.sibling()) - .ok_or(MerkleError::NodeNotInSet(index.sibling()))?; + .ok_or(MerkleError::NodeIndexNotFoundInTree(index.sibling()))?; // get parent hash let parent = Rpo256::merge(&index.build_node(*node, *sibling)); @@ -184,7 +185,10 @@ impl PartialMerkleTree { /// # Errors /// Returns an error if the specified NodeIndex is not contained in the nodes map. pub fn get_node(&self, index: NodeIndex) -> Result { - self.nodes.get(&index).ok_or(MerkleError::NodeNotInSet(index)).copied() + self.nodes + .get(&index) + .ok_or(MerkleError::NodeIndexNotFoundInTree(index)) + .copied() } /// Returns true if provided index contains in the leaves set, false otherwise. @@ -224,7 +228,7 @@ impl PartialMerkleTree { } if !self.nodes.contains_key(&index) { - return Err(MerkleError::NodeNotInSet(index)); + return Err(MerkleError::NodeIndexNotFoundInTree(index)); } let mut path = Vec::new(); @@ -335,15 +339,16 @@ impl PartialMerkleTree { if self.root() == EMPTY_DIGEST { self.nodes.insert(ROOT_INDEX, root); } else if self.root() != root { - return Err(MerkleError::ConflictingRoots([self.root(), root].to_vec())); + return Err(MerkleError::ConflictingRoots { + expected_root: self.root(), + actual_root: root, + }); } Ok(()) } /// Updates value of the leaf at the specified index returning the old leaf value. - /// By default the specified index is assumed to belong to the deepest layer. If the considered - /// node does not belong to the tree, the first node on the way to the root will be changed. /// /// By default the specified index is assumed to belong to the deepest layer. If the considered /// node does not belong to the tree, the first node on the way to the root will be changed. @@ -352,6 +357,7 @@ impl PartialMerkleTree { /// /// # Errors /// Returns an error if: + /// - No entry exists at the specified index. /// - The specified index is greater than the maximum number of nodes on the deepest layer. pub fn update_leaf(&mut self, index: u64, value: Word) -> Result { let mut node_index = NodeIndex::new(self.max_depth(), index)?; @@ -367,7 +373,7 @@ impl PartialMerkleTree { let old_value = self .nodes .insert(node_index, value.into()) - .ok_or(MerkleError::NodeNotInSet(node_index))?; + .ok_or(MerkleError::NodeIndexNotFoundInTree(node_index))?; // if the old value and new value are the same, there is nothing to update if value == *old_value { diff --git a/src/merkle/path.rs b/src/merkle/path.rs index 37dd66bc..7e3f02ea 100644 --- a/src/merkle/path.rs +++ b/src/merkle/path.rs @@ -61,7 +61,10 @@ impl MerklePath { pub fn verify(&self, index: u64, node: RpoDigest, root: &RpoDigest) -> Result<(), MerkleError> { let computed_root = self.compute_root(index, node)?; if &computed_root != root { - return Err(MerkleError::ConflictingRoots(vec![computed_root, *root])); + return Err(MerkleError::ConflictingRoots { + expected_root: *root, + actual_root: computed_root, + }); } Ok(()) diff --git a/src/merkle/smt/full/error.rs b/src/merkle/smt/full/error.rs index 805144a3..7144d45d 100644 --- a/src/merkle/smt/full/error.rs +++ b/src/merkle/smt/full/error.rs @@ -1,86 +1,39 @@ -use alloc::vec::Vec; -use core::fmt; +use thiserror::Error; use crate::{ hash::rpo::RpoDigest, merkle::{LeafIndex, SMT_DEPTH}, - Word, }; // SMT LEAF ERROR // ================================================================================================= -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Debug, Error)] pub enum SmtLeafError { - InconsistentKeys { - entries: Vec<(RpoDigest, Word)>, - key_1: RpoDigest, - key_2: RpoDigest, - }, - InvalidNumEntriesForMultiple(usize), - SingleKeyInconsistentWithLeafIndex { + #[error( + "multiple leaf requires all keys to map to the same leaf index but key1 {key_1} and key2 {key_2} map to different indices" + )] + InconsistentMultipleLeafKeys { key_1: RpoDigest, key_2: RpoDigest }, + #[error("single leaf key {key} maps to {actual_leaf_index:?} but was expected to map to {expected_leaf_index:?}")] + InconsistentSingleLeafIndices { key: RpoDigest, - leaf_index: LeafIndex, + expected_leaf_index: LeafIndex, + actual_leaf_index: LeafIndex, }, - MultipleKeysInconsistentWithLeafIndex { + #[error("supplied leaf index {leaf_index_supplied:?} does not match {leaf_index_from_keys:?} for multiple leaf")] + InconsistentMultipleLeafIndices { leaf_index_from_keys: LeafIndex, leaf_index_supplied: LeafIndex, }, -} - -#[cfg(feature = "std")] -impl std::error::Error for SmtLeafError {} - -impl fmt::Display for SmtLeafError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use SmtLeafError::*; - match self { - InvalidNumEntriesForMultiple(num_entries) => { - write!(f, "Multiple leaf requires 2 or more entries. Got: {num_entries}") - }, - InconsistentKeys { entries, key_1, key_2 } => { - write!(f, "Multiple leaf requires all keys to map to the same leaf index. Offending keys: {key_1} and {key_2}. Entries: {entries:?}.") - }, - SingleKeyInconsistentWithLeafIndex { key, leaf_index } => { - write!( - f, - "Single key in leaf inconsistent with leaf index. Key: {key}, leaf index: {}", - leaf_index.value() - ) - }, - MultipleKeysInconsistentWithLeafIndex { - leaf_index_from_keys, - leaf_index_supplied, - } => { - write!( - f, - "Keys in entries map to leaf index {}, but leaf index {} was supplied", - leaf_index_from_keys.value(), - leaf_index_supplied.value() - ) - }, - } - } + #[error("multiple leaf requires at least two entries but only {0} were given")] + MultipleLeafRequiresTwoEntries(usize), } // SMT PROOF ERROR // ================================================================================================= -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Debug, Error)] pub enum SmtProofError { - InvalidPathLength(usize), -} - -#[cfg(feature = "std")] -impl std::error::Error for SmtProofError {} - -impl fmt::Display for SmtProofError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use SmtProofError::*; - match self { - InvalidPathLength(path_length) => { - write!(f, "Invalid Merkle path length. Expected {SMT_DEPTH}, got {path_length}") - }, - } - } + #[error("merkle path length {0} does not match SMT depth {SMT_DEPTH}")] + InvalidMerklePathLength(usize), } diff --git a/src/merkle/smt/full/leaf.rs b/src/merkle/smt/full/leaf.rs index 585fc407..ed3e6b7d 100644 --- a/src/merkle/smt/full/leaf.rs +++ b/src/merkle/smt/full/leaf.rs @@ -31,10 +31,12 @@ impl SmtLeaf { 1 => { let (key, value) = entries[0]; - if LeafIndex::::from(key) != leaf_index { - return Err(SmtLeafError::SingleKeyInconsistentWithLeafIndex { + let computed_index = LeafIndex::::from(key); + if computed_index != leaf_index { + return Err(SmtLeafError::InconsistentSingleLeafIndices { key, - leaf_index, + expected_leaf_index: leaf_index, + actual_leaf_index: computed_index, }); } @@ -46,7 +48,7 @@ impl SmtLeaf { // `new_multiple()` checked that all keys map to the same leaf index. We still need // to ensure that that leaf index is `leaf_index`. if leaf.index() != leaf_index { - Err(SmtLeafError::MultipleKeysInconsistentWithLeafIndex { + Err(SmtLeafError::InconsistentMultipleLeafIndices { leaf_index_from_keys: leaf.index(), leaf_index_supplied: leaf_index, }) @@ -75,7 +77,7 @@ impl SmtLeaf { /// - Returns an error if 2 keys in `entries` map to a different leaf index pub fn new_multiple(entries: Vec<(RpoDigest, Word)>) -> Result { if entries.len() < 2 { - return Err(SmtLeafError::InvalidNumEntriesForMultiple(entries.len())); + return Err(SmtLeafError::MultipleLeafRequiresTwoEntries(entries.len())); } // Check that all keys map to the same leaf index @@ -89,8 +91,7 @@ impl SmtLeaf { let next_leaf_index: LeafIndex = next_key.into(); if next_leaf_index != first_leaf_index { - return Err(SmtLeafError::InconsistentKeys { - entries, + return Err(SmtLeafError::InconsistentMultipleLeafKeys { key_1: first_key, key_2: next_key, }); diff --git a/src/merkle/smt/full/proof.rs b/src/merkle/smt/full/proof.rs index c23b8b4a..84554885 100644 --- a/src/merkle/smt/full/proof.rs +++ b/src/merkle/smt/full/proof.rs @@ -25,7 +25,7 @@ impl SmtProof { pub fn new(path: MerklePath, leaf: SmtLeaf) -> Result { let depth: usize = SMT_DEPTH.into(); if path.len() != depth { - return Err(SmtProofError::InvalidPathLength(path.len())); + return Err(SmtProofError::InvalidMerklePathLength(path.len())); } Ok(Self { path, leaf }) diff --git a/src/merkle/smt/mod.rs b/src/merkle/smt/mod.rs index 056c221c..71d68667 100644 --- a/src/merkle/smt/mod.rs +++ b/src/merkle/smt/mod.rs @@ -267,7 +267,10 @@ pub(crate) trait SparseMerkleTree { // Guard against accidentally trying to apply mutations that were computed against a // different tree, including a stale version of this tree. if old_root != self.root() { - return Err(MerkleError::ConflictingRoots(vec![old_root, self.root()])); + return Err(MerkleError::ConflictingRoots { + expected_root: self.root(), + actual_root: old_root, + }); } for (index, mutation) in node_mutations { @@ -403,7 +406,7 @@ impl TryFrom for LeafIndex { fn try_from(node_index: NodeIndex) -> Result { if node_index.depth() != DEPTH { - return Err(MerkleError::InvalidDepth { + return Err(MerkleError::InvalidNodeIndexDepth { expected: DEPTH, provided: node_index.depth(), }); diff --git a/src/merkle/smt/simple/mod.rs b/src/merkle/smt/simple/mod.rs index 6229ac25..b52aac4b 100644 --- a/src/merkle/smt/simple/mod.rs +++ b/src/merkle/smt/simple/mod.rs @@ -81,7 +81,7 @@ impl SimpleSmt { for (idx, (key, value)) in entries.into_iter().enumerate() { if idx >= max_num_entries { - return Err(MerkleError::InvalidNumEntries(max_num_entries)); + return Err(MerkleError::TooManyEntries(max_num_entries)); } let old_value = tree.insert(LeafIndex::::new(key)?, value); @@ -246,7 +246,7 @@ impl SimpleSmt { subtree: SimpleSmt, ) -> Result { if SUBTREE_DEPTH > DEPTH { - return Err(MerkleError::InvalidSubtreeDepth { + return Err(MerkleError::SubtreeDepthExceedsDepth { subtree_depth: SUBTREE_DEPTH, tree_depth: DEPTH, }); diff --git a/src/merkle/smt/simple/tests.rs b/src/merkle/smt/simple/tests.rs index b1dd28d7..84bad47f 100644 --- a/src/merkle/smt/simple/tests.rs +++ b/src/merkle/smt/simple/tests.rs @@ -1,5 +1,7 @@ use alloc::vec::Vec; +use assert_matches::assert_matches; + use super::{ super::{MerkleError, RpoDigest, SimpleSmt}, NodeIndex, @@ -257,12 +259,12 @@ fn test_simplesmt_fail_on_duplicates() { // consecutive let entries = [(1, *first), (1, *second)]; let smt = SimpleSmt::<64>::with_leaves(entries); - assert_eq!(smt.unwrap_err(), MerkleError::DuplicateValuesForIndex(1)); + assert_matches!(smt.unwrap_err(), MerkleError::DuplicateValuesForIndex(1)); // not consecutive let entries = [(1, *first), (5, int_to_leaf(5)), (1, *second)]; let smt = SimpleSmt::<64>::with_leaves(entries); - assert_eq!(smt.unwrap_err(), MerkleError::DuplicateValuesForIndex(1)); + assert_matches!(smt.unwrap_err(), MerkleError::DuplicateValuesForIndex(1)); } } diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index bc7a63f2..f89f7398 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -136,7 +136,10 @@ impl> MerkleStore { self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash))?; for i in (0..index.depth()).rev() { - let node = self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash, index))?; + let node = self + .nodes + .get(&hash) + .ok_or(MerkleError::NodeIndexNotFoundInStore(hash, index))?; let bit = (index.value() >> i) & 1; hash = if bit == 0 { node.left } else { node.right } @@ -162,7 +165,10 @@ impl> MerkleStore { self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash))?; for i in (0..index.depth()).rev() { - let node = self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash, index))?; + let node = self + .nodes + .get(&hash) + .ok_or(MerkleError::NodeIndexNotFoundInStore(hash, index))?; let bit = (index.value() >> i) & 1; hash = if bit == 0 { diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index fe9ee0f0..3c94dc0a 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -1,3 +1,4 @@ +use assert_matches::assert_matches; use seq_macro::seq; #[cfg(feature = "std")] use { @@ -42,14 +43,14 @@ const VALUES8: [RpoDigest; 8] = [ fn test_root_not_in_store() -> Result<(), MerkleError> { let mtree = MerkleTree::new(digests_to_words(&VALUES4))?; let store = MerkleStore::from(&mtree); - assert_eq!( + assert_matches!( store.get_node(VALUES4[0], NodeIndex::make(mtree.depth(), 0)), - Err(MerkleError::RootNotInStore(VALUES4[0])), + Err(MerkleError::RootNotInStore(root)) if root == VALUES4[0], "Leaf 0 is not a root" ); - assert_eq!( + assert_matches!( store.get_path(VALUES4[0], NodeIndex::make(mtree.depth(), 0)), - Err(MerkleError::RootNotInStore(VALUES4[0])), + Err(MerkleError::RootNotInStore(root)) if root == VALUES4[0], "Leaf 0 is not a root" ); @@ -64,46 +65,46 @@ fn test_merkle_tree() -> Result<(), MerkleError> { // STORE LEAVES ARE CORRECT ------------------------------------------------------------------- // checks the leaves in the store corresponds to the expected values assert_eq!( - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 0)), - Ok(VALUES4[0]), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 0)).unwrap(), + VALUES4[0], "node 0 must be in the tree" ); assert_eq!( - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 1)), - Ok(VALUES4[1]), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 1)).unwrap(), + VALUES4[1], "node 1 must be in the tree" ); assert_eq!( - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 2)), - Ok(VALUES4[2]), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 2)).unwrap(), + VALUES4[2], "node 2 must be in the tree" ); assert_eq!( - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)), - Ok(VALUES4[3]), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)).unwrap(), + VALUES4[3], "node 3 must be in the tree" ); // STORE LEAVES MATCH TREE -------------------------------------------------------------------- // sanity check the values returned by the store and the tree assert_eq!( - mtree.get_node(NodeIndex::make(mtree.depth(), 0)), - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 0)), + mtree.get_node(NodeIndex::make(mtree.depth(), 0)).unwrap(), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 0)).unwrap(), "node 0 must be the same for both MerkleTree and MerkleStore" ); assert_eq!( - mtree.get_node(NodeIndex::make(mtree.depth(), 1)), - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 1)), + mtree.get_node(NodeIndex::make(mtree.depth(), 1)).unwrap(), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 1)).unwrap(), "node 1 must be the same for both MerkleTree and MerkleStore" ); assert_eq!( - mtree.get_node(NodeIndex::make(mtree.depth(), 2)), - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 2)), + mtree.get_node(NodeIndex::make(mtree.depth(), 2)).unwrap(), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 2)).unwrap(), "node 2 must be the same for both MerkleTree and MerkleStore" ); assert_eq!( - mtree.get_node(NodeIndex::make(mtree.depth(), 3)), - store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)), + mtree.get_node(NodeIndex::make(mtree.depth(), 3)).unwrap(), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)).unwrap(), "node 3 must be the same for both MerkleTree and MerkleStore" ); @@ -115,8 +116,8 @@ fn test_merkle_tree() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::make(mtree.depth(), 0)), - Ok(result.path), + mtree.get_path(NodeIndex::make(mtree.depth(), 0)).unwrap(), + result.path, "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -126,8 +127,8 @@ fn test_merkle_tree() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::make(mtree.depth(), 1)), - Ok(result.path), + mtree.get_path(NodeIndex::make(mtree.depth(), 1)).unwrap(), + result.path, "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); @@ -137,8 +138,8 @@ fn test_merkle_tree() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::make(mtree.depth(), 2)), - Ok(result.path), + mtree.get_path(NodeIndex::make(mtree.depth(), 2)).unwrap(), + result.path, "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -148,8 +149,8 @@ fn test_merkle_tree() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::make(mtree.depth(), 3)), - Ok(result.path), + mtree.get_path(NodeIndex::make(mtree.depth(), 3)).unwrap(), + result.path, "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -240,56 +241,56 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values assert_eq!( - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 0)), - Ok(VALUES4[0]), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 0)).unwrap(), + VALUES4[0], "node 0 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 1)), - Ok(VALUES4[1]), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 1)).unwrap(), + VALUES4[1], "node 1 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 2)), - Ok(VALUES4[2]), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 2)).unwrap(), + VALUES4[2], "node 2 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 3)), - Ok(VALUES4[3]), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 3)).unwrap(), + VALUES4[3], "node 3 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 4)), - Ok(RpoDigest::default()), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 4)).unwrap(), + RpoDigest::default(), "unmodified node 4 must be ZERO" ); // STORE LEAVES MATCH TREE =============================================================== // sanity check the values returned by the store and the tree assert_eq!( - smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 0)), - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 0)), + smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 0)).unwrap(), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 0)).unwrap(), "node 0 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 1)), - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 1)), + smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 1)).unwrap(), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 1)).unwrap(), "node 1 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 2)), - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 2)), + smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 2)).unwrap(), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 2)).unwrap(), "node 2 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 3)), - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 3)), + smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 3)).unwrap(), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 3)).unwrap(), "node 3 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 4)), - store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 4)), + smt.get_node(NodeIndex::make(SMT_MAX_DEPTH, 4)).unwrap(), + store.get_node(smt.root(), NodeIndex::make(SMT_MAX_DEPTH, 4)).unwrap(), "node 4 must be the same for both SparseMerkleTree and MerkleStore" ); @@ -385,46 +386,46 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values assert_eq!( - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 0)), - Ok(VALUES4[0]), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 0)).unwrap(), + VALUES4[0], "node 0 must be in the pmt" ); assert_eq!( - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 1)), - Ok(VALUES4[1]), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 1)).unwrap(), + VALUES4[1], "node 1 must be in the pmt" ); assert_eq!( - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 2)), - Ok(VALUES4[2]), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 2)).unwrap(), + VALUES4[2], "node 2 must be in the pmt" ); assert_eq!( - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 3)), - Ok(VALUES4[3]), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 3)).unwrap(), + VALUES4[3], "node 3 must be in the pmt" ); // STORE LEAVES MATCH PMT ================================================================ // sanity check the values returned by the store and the pmt assert_eq!( - pmt.get_node(NodeIndex::make(pmt.max_depth(), 0)), - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 0)), + pmt.get_node(NodeIndex::make(pmt.max_depth(), 0)).unwrap(), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 0)).unwrap(), "node 0 must be the same for both PartialMerkleTree and MerkleStore" ); assert_eq!( - pmt.get_node(NodeIndex::make(pmt.max_depth(), 1)), - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 1)), + pmt.get_node(NodeIndex::make(pmt.max_depth(), 1)).unwrap(), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 1)).unwrap(), "node 1 must be the same for both PartialMerkleTree and MerkleStore" ); assert_eq!( - pmt.get_node(NodeIndex::make(pmt.max_depth(), 2)), - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 2)), + pmt.get_node(NodeIndex::make(pmt.max_depth(), 2)).unwrap(), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 2)).unwrap(), "node 2 must be the same for both PartialMerkleTree and MerkleStore" ); assert_eq!( - pmt.get_node(NodeIndex::make(pmt.max_depth(), 3)), - store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 3)), + pmt.get_node(NodeIndex::make(pmt.max_depth(), 3)).unwrap(), + store.get_node(pmt.root(), NodeIndex::make(pmt.max_depth(), 3)).unwrap(), "node 3 must be the same for both PartialMerkleTree and MerkleStore" ); @@ -436,8 +437,8 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - pmt.get_path(NodeIndex::make(pmt.max_depth(), 0)), - Ok(result.path), + pmt.get_path(NodeIndex::make(pmt.max_depth(), 0)).unwrap(), + result.path, "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -447,8 +448,8 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - pmt.get_path(NodeIndex::make(pmt.max_depth(), 1)), - Ok(result.path), + pmt.get_path(NodeIndex::make(pmt.max_depth(), 1)).unwrap(), + result.path, "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); @@ -458,8 +459,8 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - pmt.get_path(NodeIndex::make(pmt.max_depth(), 2)), - Ok(result.path), + pmt.get_path(NodeIndex::make(pmt.max_depth(), 2)).unwrap(), + result.path, "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -469,8 +470,8 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - pmt.get_path(NodeIndex::make(pmt.max_depth(), 3)), - Ok(result.path), + pmt.get_path(NodeIndex::make(pmt.max_depth(), 3)).unwrap(), + result.path, "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -498,7 +499,7 @@ fn wont_open_to_different_depth_root() { let store = MerkleStore::from(&mtree); let index = NodeIndex::root(); let err = store.get_node(root, index).err().unwrap(); - assert_eq!(err, MerkleError::RootNotInStore(root)); + assert_matches!(err, MerkleError::RootNotInStore(err_root) if err_root == root); } #[test] @@ -537,7 +538,7 @@ fn test_set_node() -> Result<(), MerkleError> { let value = int_to_node(42); let index = NodeIndex::make(mtree.depth(), 0); let new_root = store.set_node(mtree.root(), index, value)?.root; - assert_eq!(store.get_node(new_root, index), Ok(value), "Value must have changed"); + assert_eq!(store.get_node(new_root, index).unwrap(), value, "value must have changed"); Ok(()) } @@ -745,7 +746,7 @@ fn get_leaf_depth_works_with_depth_8() { // duplicate the tree on `a` and assert the depth is short-circuited by such sub-tree let index = NodeIndex::new(8, a).unwrap(); root = store.set_node(root, index, root).unwrap().root; - assert_eq!(Err(MerkleError::DepthTooBig(9)), store.get_leaf_depth(root, 8, a)); + assert_matches!(store.get_leaf_depth(root, 8, a).unwrap_err(), MerkleError::DepthTooBig(9)); } #[test] diff --git a/src/utils/mod.rs b/src/utils/mod.rs index bf72ef9c..f9da5610 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,7 +1,9 @@ //! Utilities used in this crate which can also be generally useful downstream. use alloc::string::String; -use core::fmt::{self, Display, Write}; +use core::fmt::{self, Write}; + +use thiserror::Error; use super::Word; @@ -46,36 +48,20 @@ pub fn bytes_to_hex_string(data: [u8; N]) -> String { } /// Defines errors which can occur during parsing of hexadecimal strings. -#[derive(Debug)] +#[derive(Debug, Error)] pub enum HexParseError { + #[error( + "expected hex data to have length {expected}, including the 0x prefix, found {actual}" + )] InvalidLength { expected: usize, actual: usize }, + #[error("hex encoded data must start with 0x prefix")] MissingPrefix, + #[error("hex encoded data must contain only characters [a-zA-Z0-9]")] InvalidChar, + #[error("hex encoded values of a Digest must be inside the field modulus")] OutOfRange, } -impl Display for HexParseError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - HexParseError::InvalidLength { expected, actual } => { - write!(f, "Expected hex data to have length {expected}, including the 0x prefix. Got {actual}") - }, - HexParseError::MissingPrefix => { - write!(f, "Hex encoded data must start with 0x prefix") - }, - HexParseError::InvalidChar => { - write!(f, "Hex encoded data must contain characters [a-zA-Z0-9]") - }, - HexParseError::OutOfRange => { - write!(f, "Hex encoded values of an RpoDigest must be inside the field modulus") - }, - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for HexParseError {} - /// Parses a hex string into an array of bytes of known size. pub fn hex_to_bytes(value: &str) -> Result<[u8; N], HexParseError> { let expected: usize = (N * 2) + 2; From 063ad49afdf5f1add557f2dff4885d005f5c4cea Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Thu, 21 Nov 2024 15:56:55 -0800 Subject: [PATCH 3/6] chore: update crate version to v0.13.0 --- Cargo.lock | 86 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 8 ++--- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebb0da25..b5aa284c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -153,9 +153,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -207,9 +207,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" @@ -249,9 +249,9 @@ checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -361,9 +361,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fnv" @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" [[package]] name = "jobserver" @@ -495,9 +495,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libm" @@ -525,7 +525,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miden-crypto" -version = "0.12.0" +version = "0.13.0" dependencies = [ "assert_matches", "blake3", @@ -676,9 +676,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307e3004becf10f5a6e0d59d20f3cd28231b0e0827a96cd3e0ce6d14bc1e4bb3" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -791,9 +791,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -808,9 +808,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags", "errno", @@ -854,18 +854,18 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -874,9 +874,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -919,9 +919,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -974,9 +974,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "utf8parse" @@ -1173,9 +1173,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winter-crypto" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "163da45f1d4d65cac361b8df4835a6daa95b3399154e16eb0305c178c6f6c1f4" +checksum = "3fcae1ada055aa10554910ecffc106cb116a19dba11ac91390ef982f94adb9c5" dependencies = [ "blake3", "sha3", @@ -1185,9 +1185,9 @@ dependencies = [ [[package]] name = "winter-math" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8ba832121679e79b004b0003018c85873956d742a39c348c247f680fe15e00" +checksum = "82479f94efc0b5374a93e2074ba46ef404384fb1ea6e35a847febec53096509b" dependencies = [ "serde", "winter-utils", @@ -1205,9 +1205,9 @@ dependencies = [ [[package]] name = "winter-utils" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b116c8ade0172506f8bda32dc674cf6b230adc8516e5138a0173ae69158a4f" +checksum = "1f948e71ffd482aa13d0ec3349047f81ecdb89f3b3287577973dcbf092a25fb4" [[package]] name = "zerocopy" diff --git a/Cargo.toml b/Cargo.toml index 2ccfc3f2..83280128 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "miden-crypto" -version = "0.12.0" +version = "0.13.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.12.0" +documentation = "https://docs.rs/miden-crypto/0.13.0" categories = ["cryptography", "no-std"] keywords = ["miden", "crypto", "hash", "merkle"] edition = "2021" @@ -61,7 +61,7 @@ winter-math = { version = "0.10", default-features = false } winter-utils = { version = "0.10", default-features = false } [dev-dependencies] -assert_matches = { version = "1.5.0", default-features = false } +assert_matches = { version = "1.5", default-features = false } criterion = { version = "0.5", features = ["html_reports"] } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4", default-features = false, features = ["alloc"] } @@ -71,5 +71,5 @@ rand-utils = { version = "0.10", package = "winter-rand-utils" } seq-macro = { version = "0.3" } [build-dependencies] -cc = { version = "1.1", optional = true, features = ["parallel"] } +cc = { version = "1.2", optional = true, features = ["parallel"] } glob = "0.3" From e1072ecc7f2dab7faa190d250a7836b6c1edf8f0 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:20:19 +0100 Subject: [PATCH 4/6] chore: update to winterfell dependencies to 0.11 (#346) --- CHANGELOG.md | 1 + Cargo.lock | 20 ++++++++++---------- Cargo.toml | 10 +++++----- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 832a19be..3917ae26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Fixed a bug in the implementation of `draw_integers` for `RpoRandomCoin` (#343). - [BREAKING] Refactor error messages and use `thiserror` to derive errors (#344). +- [BREAKING] Updated Winterfell dependency to v0.11 (#346). ## 0.12.0 (2024-10-30) diff --git a/Cargo.lock b/Cargo.lock index b5aa284c..160a2e7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -249,9 +249,9 @@ checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1173,9 +1173,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winter-crypto" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcae1ada055aa10554910ecffc106cb116a19dba11ac91390ef982f94adb9c5" +checksum = "67c57748fd2da77742be601f03eda639ff6046879738fd1faae86e80018263cb" dependencies = [ "blake3", "sha3", @@ -1185,9 +1185,9 @@ dependencies = [ [[package]] name = "winter-math" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82479f94efc0b5374a93e2074ba46ef404384fb1ea6e35a847febec53096509b" +checksum = "6020c17839fa107ce4a7cc178e407ebbc24adfac1980f4fa2111198e052700ab" dependencies = [ "serde", "winter-utils", @@ -1195,9 +1195,9 @@ dependencies = [ [[package]] name = "winter-rand-utils" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a7616d11fcc26552dada45c803a884ac97c253218835b83a2c63e1c2a988639" +checksum = "226e4c455f6eb72f64ac6eeb7642df25e21ff2280a4f6b09db75392ad6b390ef" dependencies = [ "rand", "winter-utils", @@ -1205,9 +1205,9 @@ dependencies = [ [[package]] name = "winter-utils" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f948e71ffd482aa13d0ec3349047f81ecdb89f3b3287577973dcbf092a25fb4" +checksum = "1507ef312ea5569d54c2c7446a18b82143eb2a2e21f5c3ec7cfbe8200c03bd7c" [[package]] name = "zerocopy" diff --git a/Cargo.toml b/Cargo.toml index 83280128..b9a05ef5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,13 +52,13 @@ num = { version = "0.4", default-features = false, features = ["alloc", "libm"] num-complex = { version = "0.4", default-features = false } rand = { version = "0.8", default-features = false } rand_core = { version = "0.6", default-features = false } -rand-utils = { version = "0.10", package = "winter-rand-utils", optional = true } +rand-utils = { version = "0.11", package = "winter-rand-utils", optional = true } serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } sha3 = { version = "0.10", default-features = false } thiserror = { version = "2.0", default-features = false } -winter-crypto = { version = "0.10", default-features = false } -winter-math = { version = "0.10", default-features = false } -winter-utils = { version = "0.10", default-features = false } +winter-crypto = { version = "0.11", default-features = false } +winter-math = { version = "0.11", default-features = false } +winter-utils = { version = "0.11", default-features = false } [dev-dependencies] assert_matches = { version = "1.5", default-features = false } @@ -67,7 +67,7 @@ getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4", default-features = false, features = ["alloc"] } proptest = "1.5" rand_chacha = { version = "0.3", default-features = false } -rand-utils = { version = "0.10", package = "winter-rand-utils" } +rand-utils = { version = "0.11", package = "winter-rand-utils" } seq-macro = { version = "0.3" } [build-dependencies] From 1867f842d33ca655a614d9053dc7e989000b1acb Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Sun, 24 Nov 2024 22:26:51 -0800 Subject: [PATCH 5/6] chore: update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3917ae26..6231ccbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.13.0 (TBD) +## 0.13.0 (2024-11-24) - Fixed a bug in the implementation of `draw_integers` for `RpoRandomCoin` (#343). - [BREAKING] Refactor error messages and use `thiserror` to derive errors (#344). From 1444bbc0f21db18f562e3fe1f2d8bbc0d599dfda Mon Sep 17 00:00:00 2001 From: crStiv Date: Mon, 16 Dec 2024 19:27:51 +0100 Subject: [PATCH 6/6] fix: typos of different importance (#359) --- scripts/check-changelog.sh | 2 +- src/merkle/smt/mod.rs | 4 ++-- src/merkle/store/tests.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/check-changelog.sh b/scripts/check-changelog.sh index dbf14cdb..7d7529da 100755 --- a/scripts/check-changelog.sh +++ b/scripts/check-changelog.sh @@ -13,7 +13,7 @@ else if git diff --exit-code "origin/${BASE_REF}" -- "${CHANGELOG_FILE}"; then >&2 echo "Changes should come with an entry in the \"CHANGELOG.md\" file. This behavior can be overridden by using the \"no changelog\" label, which is used for changes -that are trivial / explicitely stated not to require a changelog entry." +that are trivial / explicitly stated not to require a changelog entry." exit 1 fi diff --git a/src/merkle/smt/mod.rs b/src/merkle/smt/mod.rs index 71d68667..02eb9b36 100644 --- a/src/merkle/smt/mod.rs +++ b/src/merkle/smt/mod.rs @@ -40,7 +40,7 @@ pub const SMT_MAX_DEPTH: u8 = 64; /// Every key maps to one leaf. If there are as many keys as there are leaves, then /// [Self::Leaf] should be the same type as [Self::Value], as is the case with /// [crate::merkle::SimpleSmt]. However, if there are more keys than leaves, then [`Self::Leaf`] -/// must accomodate all keys that map to the same leaf. +/// must accommodate all keys that map to the same leaf. /// /// [SparseMerkleTree] currently doesn't support optimizations that compress Merkle proofs. pub(crate) trait SparseMerkleTree { @@ -133,7 +133,7 @@ pub(crate) trait SparseMerkleTree { node_hash = Rpo256::merge(&[left, right]); if node_hash == *EmptySubtreeRoots::entry(DEPTH, node_depth) { - // If a subtree is empty, when can remove the inner node, since it's equal to the + // If a subtree is empty, then can remove the inner node, since it's equal to the // default value self.remove_inner_node(index) } else { diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index 3c94dc0a..c00b6da4 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -725,7 +725,7 @@ fn get_leaf_depth_works_with_depth_8() { assert_eq!(8, store.get_leaf_depth(root, 8, k).unwrap()); } - // flip last bit of a and expect it to return the the same depth, but for an empty node + // flip last bit of a and expect it to return the same depth, but for an empty node assert_eq!(8, store.get_leaf_depth(root, 8, 0b01101000_u64).unwrap()); // flip fourth bit of a and expect an empty node on depth 4