Merge branch 'main' into next
@@ -5,6 +5,11 @@ - Added `Mmr::open()` and `Mmr::peaks()` which rely on `Mmr::open_at()` and `Mmr::peaks()` respectively (#234).
- Standardised CI and Makefile across Miden repos (#323). - Added `Smt::compute_mutations()` and `Smt::apply_mutations()` for validation-checked insertions (#327). +## 0.10.1 (2024-09-13) + +* Added `Serializable` and `Deserializable` implementations for `PartialMmr` and `InOrderIndex` (#329). + + ## 0.10.0 (2024-08-06) - Added more `RpoDigest` and `RpxDigest` conversions (#311).
@@ -518,7 +518,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]] name = "miden-crypto" -version = "0.10.0" +version = "0.10.1" dependencies = [ "blake3", "cc",
@@ -1,12 +1,12 @@
[package] name = "miden-crypto" -version = "0.10.0" +version = "0.10.1" 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.10.0" +documentation = "https://docs.rs/miden-crypto/0.10.1" categories = ["cryptography", "no-std"] keywords = ["miden", "crypto", "hash", "merkle"] edition = "2021"
@@ -28,13 +28,14 @@
// SECRET KEY // ================================================================================================ -/// The secret key is a quadruple [[g, -f], [G, -F]] of polynomials with integer coefficients. Each -/// polynomial is of degree at most N = 512 and computations with these polynomials is done modulo -/// the monic irreducible polynomial ϕ = x^N + 1. The secret key is a basis for a lattice and has -/// the property of being short with respect to a certain norm and an upper bound appropriate for -/// a given security parameter. The public key on the other hand is another basis for the same -/// lattice and can be described by a single polynomial h with integer coefficients modulo ϕ. -/// The two keys are related by the following relation: +/// The secret key is a quadruple [[g, -f], [G, -F]] of polynomials with integer coefficients. +/// +/// Each polynomial is of degree at most N = 512 and computations with these polynomials are done +/// modulo the monic irreducible polynomial ϕ = x^N + 1. The secret key is a basis for a lattice +/// and has the property of being short with respect to a certain norm and an upper bound +/// appropriate for a given security parameter. The public key on the other hand is another basis +/// for the same lattice and can be described by a single polynomial h with integer coefficients +/// modulo ϕ. The two keys are related by the following relation: /// /// 1. h = g /f [mod ϕ][mod p] /// 2. f.G - g.F = p [mod ϕ]
@@ -44,7 +44,7 @@ /// Falcon signature.
/// 2. 40 bytes for the nonce. /// 4. 625 bytes encoding the `s2` polynomial above. /// -/// The total size of the signature is (including the extended public key) is 1563 bytes. +/// The total size of the signature (including the extended public key) is 1563 bytes. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Signature { header: SignatureHeader,
@@ -7,7 +7,7 @@ //! of 2 with both children set.
//! //! Additionally the structure only supports adding leaves to the right-most tree, the one with the //! least number of leaves. The structure preserves the invariant that each tree has different -//! depths, i.e. as part of adding adding a new element to the forest the trees with same depth are +//! depths, i.e. as part of adding a new element to the forest the trees with same depth are //! merged, creating a new tree with depth d+1, this process is continued until the property is //! reestablished. use alloc::vec::Vec;
@@ -6,6 +6,8 @@ //! This property makes it is easy to compute changes to the index by adding or subtracting the
//! leaves count. use core::num::NonZeroUsize; +use winter_utils::{Deserializable, Serializable}; + // IN-ORDER INDEX // ================================================================================================@@ -112,6 +114,21 @@ self.idx as u64
} } +impl Serializable for InOrderIndex { + fn write_into<W: winter_utils::ByteWriter>(&self, target: &mut W) { + target.write_usize(self.idx); + } +} + +impl Deserializable for InOrderIndex { + fn read_from<R: winter_utils::ByteReader>( + source: &mut R, + ) -> Result<Self, winter_utils::DeserializationError> { + let idx = source.read_usize()?; + Ok(InOrderIndex { idx }) + } +} + // CONVERSIONS FROM IN-ORDER INDEX // ------------------------------------------------------------------------------------------------@@ -127,6 +144,7 @@
#[cfg(test)] mod test { use proptest::prelude::*; + use winter_utils::{Deserializable, Serializable}; use super::InOrderIndex;@@ -161,5 +179,13 @@ assert_eq!(left.parent().right_child(), right);
assert_eq!(left, right.parent().left_child()); assert_eq!(left.sibling(), right); assert_eq!(left, right.sibling()); + } + + #[test] + fn test_inorder_index_serialization() { + let index = InOrderIndex::from_leaf_pos(5); + let bytes = index.to_bytes(); + let index2 = InOrderIndex::read_from_bytes(&bytes).unwrap(); + assert_eq!(index, index2); } }
@@ -3,6 +3,8 @@ collections::{BTreeMap, BTreeSet},
vec::Vec, }; +use winter_utils::{Deserializable, Serializable}; + use super::{MmrDelta, MmrProof, Rpo256, RpoDigest}; use crate::merkle::{ mmr::{leaf_to_corresponding_tree, nodes_in_forest},@@ -184,7 +186,7 @@ /// is silently ignored.
pub fn inner_nodes<'a, I: Iterator<Item = (usize, RpoDigest)> + 'a>( &'a self, mut leaves: I, - ) -> impl Iterator<Item = InnerNodeInfo> + '_ { + ) -> impl Iterator<Item = InnerNodeInfo> + 'a { let stack = if let Some((pos, leaf)) = leaves.next() { let idx = InOrderIndex::from_leaf_pos(pos); vec![(idx, leaf)]@@ -573,6 +575,28 @@ None
} } +impl Serializable for PartialMmr { + fn write_into<W: winter_utils::ByteWriter>(&self, target: &mut W) { + self.forest.write_into(target); + self.peaks.write_into(target); + self.nodes.write_into(target); + target.write_bool(self.track_latest); + } +} + +impl Deserializable for PartialMmr { + fn read_from<R: winter_utils::ByteReader>( + source: &mut R, + ) -> Result<Self, winter_utils::DeserializationError> { + let forest = usize::read_from(source)?; + let peaks = Vec::<RpoDigest>::read_from(source)?; + let nodes = NodeMap::read_from(source)?; + let track_latest = source.read_bool()?; + + Ok(Self { forest, peaks, nodes, track_latest }) + } +} + // UTILS // ================================================================================================@@ -615,6 +639,8 @@
#[cfg(test)] mod tests { use alloc::{collections::BTreeSet, vec::Vec}; + + use winter_utils::{Deserializable, Serializable}; use super::{ forest_to_rightmost_index, forest_to_root_index, InOrderIndex, MmrPeaks, PartialMmr,@@ -906,5 +932,17 @@ partial_mmr.add(leaf_at_7, false);
// the openings should be the same assert_eq!(mmr.open(5).unwrap(), partial_mmr.open(5).unwrap().unwrap()); + } + + #[test] + fn test_partial_mmr_serialization() { + let mmr = Mmr::from((0..7).map(int_to_node)); + let forest_size = mmr.forest(); + let partial_mmr = PartialMmr::from_peaks(mmr.peaks(forest_size).unwrap()); + + let bytes = partial_mmr.to_bytes(); + let decoded = PartialMmr::read_from_bytes(&bytes).unwrap(); + + assert_eq!(partial_mmr, decoded); } }