-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #63 from 0xPolygonMiden/next
v0.1.2 release
- Loading branch information
Showing
14 changed files
with
925 additions
and
552 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
use super::{Felt, MerkleError, RpoDigest, StarkField}; | ||
|
||
// NODE INDEX | ||
// ================================================================================================ | ||
|
||
/// A Merkle tree address to an arbitrary node. | ||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] | ||
pub struct NodeIndex { | ||
depth: u8, | ||
value: u64, | ||
} | ||
|
||
impl NodeIndex { | ||
// CONSTRUCTORS | ||
// -------------------------------------------------------------------------------------------- | ||
|
||
/// Creates a new node index. | ||
pub const fn new(depth: u8, value: u64) -> Self { | ||
Self { depth, value } | ||
} | ||
|
||
/// Creates a node index from a pair of field elements representing the depth and value. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Will error if the `u64` representation of the depth doesn't fit a `u8`. | ||
pub fn from_elements(depth: &Felt, value: &Felt) -> Result<Self, MerkleError> { | ||
let depth = depth.as_int(); | ||
let depth = u8::try_from(depth).map_err(|_| MerkleError::DepthTooBig(depth))?; | ||
let value = value.as_int(); | ||
Ok(Self::new(depth, value)) | ||
} | ||
|
||
/// Creates a new node index pointing to the root of the tree. | ||
pub const fn root() -> Self { | ||
Self { depth: 0, value: 0 } | ||
} | ||
|
||
/// Mutates the instance and returns it, replacing the depth. | ||
pub const fn with_depth(mut self, depth: u8) -> Self { | ||
self.depth = depth; | ||
self | ||
} | ||
|
||
/// Computes the value of the sibling of the current node. | ||
pub fn sibling(mut self) -> Self { | ||
self.value ^= 1; | ||
self | ||
} | ||
|
||
// PROVIDERS | ||
// -------------------------------------------------------------------------------------------- | ||
|
||
/// Builds a node to be used as input of a hash function when computing a Merkle path. | ||
/// | ||
/// Will evaluate the parity of the current instance to define the result. | ||
pub const fn build_node(&self, slf: RpoDigest, sibling: RpoDigest) -> [RpoDigest; 2] { | ||
if self.is_value_odd() { | ||
[sibling, slf] | ||
} else { | ||
[slf, sibling] | ||
} | ||
} | ||
|
||
/// Returns the scalar representation of the depth/value pair. | ||
/// | ||
/// It is computed as `2^depth + value`. | ||
pub const fn to_scalar_index(&self) -> u64 { | ||
(1 << self.depth as u64) + self.value | ||
} | ||
|
||
/// Returns the depth of the current instance. | ||
pub const fn depth(&self) -> u8 { | ||
self.depth | ||
} | ||
|
||
/// Returns the value of the current depth. | ||
pub const fn value(&self) -> u64 { | ||
self.value | ||
} | ||
|
||
/// Returns true if the current value fits the current depth for a binary tree. | ||
pub const fn is_valid(&self) -> bool { | ||
self.value < (1 << self.depth as u64) | ||
} | ||
|
||
/// Returns true if the current instance points to a right sibling node. | ||
pub const fn is_value_odd(&self) -> bool { | ||
(self.value & 1) == 1 | ||
} | ||
|
||
/// Returns `true` if the depth is `0`. | ||
pub const fn is_root(&self) -> bool { | ||
self.depth == 0 | ||
} | ||
|
||
// STATE MUTATORS | ||
// -------------------------------------------------------------------------------------------- | ||
|
||
/// Traverse one level towards the root, decrementing the depth by `1`. | ||
pub fn move_up(&mut self) -> &mut Self { | ||
self.depth = self.depth.saturating_sub(1); | ||
self.value >>= 1; | ||
self | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use proptest::prelude::*; | ||
|
||
proptest! { | ||
#[test] | ||
fn arbitrary_index_wont_panic_on_move_up( | ||
depth in prop::num::u8::ANY, | ||
value in prop::num::u64::ANY, | ||
count in prop::num::u8::ANY, | ||
) { | ||
let mut index = NodeIndex::new(depth, value); | ||
for _ in 0..count { | ||
index.move_up(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.