2 Commits

Author SHA1 Message Date
Bobbin Threadbare
e34900c7d8 chore: update version to v0.10.1 2024-09-13 10:58:06 -07:00
Santiago Pittella
2b184cd4ca feat: add de/serialization to InOrderIndex and PartialMmr (#329) 2024-09-13 08:47:46 -07:00
6 changed files with 87 additions and 16 deletions

View File

@@ -1,3 +1,7 @@
## 0.10.1 (2024-09-13)
* Added `Serializable` and `Deserializable` implementations for `PartialMmr` and `InOrderIndex` (#329).
## 0.10.0 (2024-08-06) ## 0.10.0 (2024-08-06)
* Added more `RpoDigest` and `RpxDigest` conversions (#311). * Added more `RpoDigest` and `RpxDigest` conversions (#311).

2
Cargo.lock generated
View File

@@ -518,7 +518,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]] [[package]]
name = "miden-crypto" name = "miden-crypto"
version = "0.10.0" version = "0.10.1"
dependencies = [ dependencies = [
"blake3", "blake3",
"cc", "cc",

View File

@@ -1,12 +1,12 @@
[package] [package]
name = "miden-crypto" name = "miden-crypto"
version = "0.10.0" version = "0.10.1"
description = "Miden Cryptographic primitives" description = "Miden Cryptographic primitives"
authors = ["miden contributors"] authors = ["miden contributors"]
readme = "README.md" readme = "README.md"
license = "MIT" license = "MIT"
repository = "https://github.com/0xPolygonMiden/crypto" 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"] categories = ["cryptography", "no-std"]
keywords = ["miden", "crypto", "hash", "merkle"] keywords = ["miden", "crypto", "hash", "merkle"]
edition = "2021" edition = "2021"

View File

@@ -27,13 +27,14 @@ const WIDTH_SMALL_POLY_COEFFICIENT: usize = 6;
// SECRET KEY // SECRET KEY
// ================================================================================================ // ================================================================================================
/// The secret key is a quadruple [[g, -f], [G, -F]] of polynomials with integer coefficients. Each /// The secret key is a quadruple [[g, -f], [G, -F]] of polynomials with integer coefficients.
/// 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 /// Each polynomial is of degree at most N = 512 and computations with these polynomials are done
/// the property of being short with respect to a certain norm and an upper bound appropriate for /// modulo the monic irreducible polynomial ϕ = x^N + 1. The secret key is a basis for a lattice
/// a given security parameter. The public key on the other hand is another basis for the same /// and has the property of being short with respect to a certain norm and an upper bound
/// lattice and can be described by a single polynomial h with integer coefficients modulo ϕ. /// appropriate for a given security parameter. The public key on the other hand is another basis
/// The two keys are related by the following relation: /// 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] /// 1. h = g /f [mod ϕ][mod p]
/// 2. f.G - g.F = p [mod ϕ] /// 2. f.G - g.F = p [mod ϕ]

View File

@@ -6,6 +6,8 @@
//! leaves count. //! leaves count.
use core::num::NonZeroUsize; use core::num::NonZeroUsize;
use winter_utils::{Deserializable, Serializable};
// IN-ORDER INDEX // IN-ORDER INDEX
// ================================================================================================ // ================================================================================================
@@ -112,6 +114,21 @@ impl InOrderIndex {
} }
} }
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 // CONVERSIONS FROM IN-ORDER INDEX
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@@ -127,6 +144,7 @@ impl From<InOrderIndex> for u64 {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use proptest::prelude::*; use proptest::prelude::*;
use winter_utils::{Deserializable, Serializable};
use super::InOrderIndex; use super::InOrderIndex;
@@ -162,4 +180,12 @@ mod test {
assert_eq!(left.sibling(), right); assert_eq!(left.sibling(), right);
assert_eq!(left, right.sibling()); 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);
}
} }

View File

@@ -1,12 +1,15 @@
use alloc::{
collections::{BTreeMap, BTreeSet},
vec::Vec,
};
use winter_utils::{Deserializable, Serializable};
use super::{MmrDelta, MmrProof, Rpo256, RpoDigest}; use super::{MmrDelta, MmrProof, Rpo256, RpoDigest};
use crate::merkle::{ use crate::merkle::{
mmr::{leaf_to_corresponding_tree, nodes_in_forest}, mmr::{leaf_to_corresponding_tree, nodes_in_forest},
InOrderIndex, InnerNodeInfo, MerklePath, MmrError, MmrPeaks, InOrderIndex, InnerNodeInfo, MerklePath, MmrError, MmrPeaks,
}; };
use alloc::{
collections::{BTreeMap, BTreeSet},
vec::Vec,
};
// TYPE ALIASES // TYPE ALIASES
// ================================================================================================ // ================================================================================================
@@ -183,7 +186,7 @@ impl PartialMmr {
pub fn inner_nodes<'a, I: Iterator<Item = (usize, RpoDigest)> + 'a>( pub fn inner_nodes<'a, I: Iterator<Item = (usize, RpoDigest)> + 'a>(
&'a self, &'a self,
mut leaves: I, mut leaves: I,
) -> impl Iterator<Item = InnerNodeInfo> + '_ { ) -> impl Iterator<Item = InnerNodeInfo> + 'a {
let stack = if let Some((pos, leaf)) = leaves.next() { let stack = if let Some((pos, leaf)) = leaves.next() {
let idx = InOrderIndex::from_leaf_pos(pos); let idx = InOrderIndex::from_leaf_pos(pos);
vec![(idx, leaf)] vec![(idx, leaf)]
@@ -572,6 +575,28 @@ impl<'a, I: Iterator<Item = (usize, RpoDigest)>> Iterator for InnerNodeIterator<
} }
} }
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 // UTILS
// ================================================================================================ // ================================================================================================
@@ -613,12 +638,15 @@ fn forest_to_rightmost_index(forest: usize) -> InOrderIndex {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use alloc::{collections::BTreeSet, vec::Vec};
use winter_utils::{Deserializable, Serializable};
use super::{ use super::{
forest_to_rightmost_index, forest_to_root_index, InOrderIndex, MmrPeaks, PartialMmr, forest_to_rightmost_index, forest_to_root_index, InOrderIndex, MmrPeaks, PartialMmr,
RpoDigest, RpoDigest,
}; };
use crate::merkle::{int_to_node, MerkleStore, Mmr, NodeIndex}; use crate::merkle::{int_to_node, MerkleStore, Mmr, NodeIndex};
use alloc::{collections::BTreeSet, vec::Vec};
const LEAVES: [RpoDigest; 7] = [ const LEAVES: [RpoDigest; 7] = [
int_to_node(0), int_to_node(0),
@@ -907,4 +935,16 @@ mod tests {
// the openings should be the same // the openings should be the same
assert_eq!(mmr.open(5, mmr.forest()).unwrap(), partial_mmr.open(5).unwrap().unwrap()); assert_eq!(mmr.open(5, mmr.forest()).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);
}
} }