fix misc. nits
This commit is contained in:
parent
2ad8495bc2
commit
bbfddcfbd3
8 changed files with 611 additions and 600 deletions
|
@ -1,6 +1,7 @@
|
|||
use crate::StarkField;
|
||||
pub use winterfell::crypto::hashers::Rp64_256 as Hasher;
|
||||
pub use winterfell::crypto::{ElementHasher, Hasher as HashFn};
|
||||
use crate::{ElementHasher, HashFn};
|
||||
|
||||
mod rpo;
|
||||
pub use rpo::Rpo as Hasher;
|
||||
|
||||
// TYPE ALIASES
|
||||
// ================================================================================================
|
||||
|
@ -10,16 +11,6 @@ pub type Digest = <Hasher as HashFn>::Digest;
|
|||
// HELPER FUNCTIONS
|
||||
// ================================================================================================
|
||||
|
||||
#[inline(always)]
|
||||
fn _exp_acc<B: StarkField, const N: usize, const M: usize>(base: [B; N], tail: [B; N]) -> [B; N] {
|
||||
let mut result = base;
|
||||
for _ in 0..M {
|
||||
result.iter_mut().for_each(|r| *r = r.square());
|
||||
}
|
||||
result.iter_mut().zip(tail).for_each(|(r, t)| *r *= t);
|
||||
result
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn merge(values: &[Digest; 2]) -> Digest {
|
||||
Hasher::merge(values)
|
||||
|
|
|
@ -1,32 +1,31 @@
|
|||
use super::DIGEST_SIZE;
|
||||
use crate::{Digest, Felt, StarkField};
|
||||
use core::slice;
|
||||
use winterfell::crypto::Digest;
|
||||
use winterfell::math::{fields::f64::BaseElement, StarkField};
|
||||
use winterfell::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
|
||||
|
||||
// DIGEST TRAIT IMPLEMENTATIONS
|
||||
// ================================================================================================
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct ElementDigest([BaseElement; DIGEST_SIZE]);
|
||||
pub struct RpoDigest256([Felt; DIGEST_SIZE]);
|
||||
|
||||
impl ElementDigest {
|
||||
pub fn new(value: [BaseElement; DIGEST_SIZE]) -> Self {
|
||||
impl RpoDigest256 {
|
||||
pub fn new(value: [Felt; DIGEST_SIZE]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
|
||||
pub fn as_elements(&self) -> &[BaseElement] {
|
||||
pub fn as_elements(&self) -> &[Felt] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn digests_as_elements(digests: &[Self]) -> &[BaseElement] {
|
||||
pub fn digests_as_elements(digests: &[Self]) -> &[Felt] {
|
||||
let p = digests.as_ptr();
|
||||
let len = digests.len() * DIGEST_SIZE;
|
||||
unsafe { slice::from_raw_parts(p as *const BaseElement, len) }
|
||||
unsafe { slice::from_raw_parts(p as *const Felt, len) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for ElementDigest {
|
||||
impl Digest for RpoDigest256 {
|
||||
fn as_bytes(&self) -> [u8; 32] {
|
||||
let mut result = [0; 32];
|
||||
|
||||
|
@ -39,44 +38,44 @@ impl Digest for ElementDigest {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for ElementDigest {
|
||||
impl Default for RpoDigest256 {
|
||||
fn default() -> Self {
|
||||
ElementDigest([BaseElement::default(); DIGEST_SIZE])
|
||||
RpoDigest256([Felt::default(); DIGEST_SIZE])
|
||||
}
|
||||
}
|
||||
|
||||
impl Serializable for ElementDigest {
|
||||
impl Serializable for RpoDigest256 {
|
||||
fn write_into<W: ByteWriter>(&self, target: &mut W) {
|
||||
target.write_u8_slice(&self.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserializable for ElementDigest {
|
||||
impl Deserializable for RpoDigest256 {
|
||||
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
|
||||
// TODO: check if the field elements are valid?
|
||||
let e1 = BaseElement::new(source.read_u64()?);
|
||||
let e2 = BaseElement::new(source.read_u64()?);
|
||||
let e3 = BaseElement::new(source.read_u64()?);
|
||||
let e4 = BaseElement::new(source.read_u64()?);
|
||||
let e1 = Felt::new(source.read_u64()?);
|
||||
let e2 = Felt::new(source.read_u64()?);
|
||||
let e3 = Felt::new(source.read_u64()?);
|
||||
let e4 = Felt::new(source.read_u64()?);
|
||||
|
||||
Ok(Self([e1, e2, e3, e4]))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[BaseElement; DIGEST_SIZE]> for ElementDigest {
|
||||
fn from(value: [BaseElement; DIGEST_SIZE]) -> Self {
|
||||
impl From<[Felt; DIGEST_SIZE]> for RpoDigest256 {
|
||||
fn from(value: [Felt; DIGEST_SIZE]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ElementDigest> for [BaseElement; DIGEST_SIZE] {
|
||||
fn from(value: ElementDigest) -> Self {
|
||||
impl From<RpoDigest256> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: RpoDigest256) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ElementDigest> for [u8; 32] {
|
||||
fn from(value: ElementDigest) -> Self {
|
||||
impl From<RpoDigest256> for [u8; 32] {
|
||||
fn from(value: RpoDigest256) -> Self {
|
||||
value.as_bytes()
|
||||
}
|
||||
}
|
||||
|
@ -87,25 +86,26 @@ impl From<ElementDigest> for [u8; 32] {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::ElementDigest;
|
||||
use super::RpoDigest256;
|
||||
use crate::Felt;
|
||||
use rand_utils::rand_value;
|
||||
use winterfell::{math::fields::f64::BaseElement, Deserializable, Serializable, SliceReader};
|
||||
use winterfell::{Deserializable, Serializable, SliceReader};
|
||||
|
||||
#[test]
|
||||
fn digest_serialization() {
|
||||
let e1 = BaseElement::new(rand_value());
|
||||
let e2 = BaseElement::new(rand_value());
|
||||
let e3 = BaseElement::new(rand_value());
|
||||
let e4 = BaseElement::new(rand_value());
|
||||
let e1 = Felt::new(rand_value());
|
||||
let e2 = Felt::new(rand_value());
|
||||
let e3 = Felt::new(rand_value());
|
||||
let e4 = Felt::new(rand_value());
|
||||
|
||||
let d1 = ElementDigest([e1, e2, e3, e4]);
|
||||
let d1 = RpoDigest256([e1, e2, e3, e4]);
|
||||
|
||||
let mut bytes = vec![];
|
||||
d1.write_into(&mut bytes);
|
||||
assert_eq!(32, bytes.len());
|
||||
|
||||
let mut reader = SliceReader::new(&bytes);
|
||||
let d2 = ElementDigest::read_from(&mut reader).unwrap();
|
||||
let d2 = RpoDigest256::read_from(&mut reader).unwrap();
|
||||
|
||||
assert_eq!(d1, d2);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
BaseElement, ElementDigest, ElementHasher, FieldElement, HashFn, Rpo, StarkField, ALPHA,
|
||||
INV_ALPHA, INV_MDS, MDS, STATE_WIDTH,
|
||||
ElementHasher, Felt, FieldElement, HashFn, Rpo, RpoDigest256, StarkField, ALPHA, INV_ALPHA,
|
||||
INV_MDS, MDS, STATE_WIDTH, ZERO,
|
||||
};
|
||||
|
||||
use core::convert::TryInto;
|
||||
|
@ -9,11 +9,11 @@ use rand_utils::rand_value;
|
|||
|
||||
#[test]
|
||||
fn mds_inv_test() {
|
||||
let mut mul_result = [[BaseElement::new(0); STATE_WIDTH]; STATE_WIDTH];
|
||||
let mut mul_result = [[Felt::new(0); STATE_WIDTH]; STATE_WIDTH];
|
||||
for i in 0..STATE_WIDTH {
|
||||
for j in 0..STATE_WIDTH {
|
||||
let result = {
|
||||
let mut result = BaseElement::new(0);
|
||||
let mut result = Felt::new(0);
|
||||
for k in 0..STATE_WIDTH {
|
||||
result += MDS[i][k] * INV_MDS[k][j]
|
||||
}
|
||||
|
@ -21,23 +21,23 @@ fn mds_inv_test() {
|
|||
};
|
||||
mul_result[i][j] = result;
|
||||
if i == j {
|
||||
assert_eq!(result, BaseElement::new(1));
|
||||
assert_eq!(result, Felt::new(1));
|
||||
} else {
|
||||
assert_eq!(result, BaseElement::new(0));
|
||||
assert_eq!(result, Felt::new(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_alphas() {
|
||||
let e: BaseElement = BaseElement::new(rand_value());
|
||||
let e: Felt = Felt::new(rand_value());
|
||||
let e_exp = e.exp(ALPHA.into());
|
||||
assert_eq!(e, e_exp.exp(INV_ALPHA));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sbox() {
|
||||
let state = [BaseElement::new(rand_value()); STATE_WIDTH];
|
||||
let state = [Felt::new(rand_value()); STATE_WIDTH];
|
||||
|
||||
let mut expected = state;
|
||||
expected.iter_mut().for_each(|v| *v = v.exp(ALPHA));
|
||||
|
@ -50,7 +50,7 @@ fn test_sbox() {
|
|||
|
||||
#[test]
|
||||
fn test_inv_sbox() {
|
||||
let state = [BaseElement::new(rand_value()); STATE_WIDTH];
|
||||
let state = [Felt::new(rand_value()); STATE_WIDTH];
|
||||
|
||||
let mut expected = state;
|
||||
expected.iter_mut().for_each(|v| *v = v.exp(INV_ALPHA));
|
||||
|
@ -63,11 +63,11 @@ fn test_inv_sbox() {
|
|||
|
||||
#[test]
|
||||
fn hash_elements_vs_merge() {
|
||||
let elements = [BaseElement::new(rand_value()); 8];
|
||||
let elements = [Felt::new(rand_value()); 8];
|
||||
|
||||
let digests: [ElementDigest; 2] = [
|
||||
ElementDigest::new(elements[..4].try_into().unwrap()),
|
||||
ElementDigest::new(elements[4..].try_into().unwrap()),
|
||||
let digests: [RpoDigest256; 2] = [
|
||||
RpoDigest256::new(elements[..4].try_into().unwrap()),
|
||||
RpoDigest256::new(elements[4..].try_into().unwrap()),
|
||||
];
|
||||
|
||||
let m_result = Rpo::merge(&digests);
|
||||
|
@ -77,11 +77,11 @@ fn hash_elements_vs_merge() {
|
|||
|
||||
#[test]
|
||||
fn hash_elements_vs_merge_with_int() {
|
||||
let tmp = [BaseElement::new(rand_value()); 4];
|
||||
let seed = ElementDigest::new(tmp);
|
||||
let tmp = [Felt::new(rand_value()); 4];
|
||||
let seed = RpoDigest256::new(tmp);
|
||||
|
||||
// ----- value fits into a field element ------------------------------------------------------
|
||||
let val: BaseElement = BaseElement::new(rand_value());
|
||||
let val: Felt = Felt::new(rand_value());
|
||||
let m_result = Rpo::merge_with_int(seed, val.as_int());
|
||||
|
||||
let mut elements = seed.as_elements().to_vec();
|
||||
|
@ -91,12 +91,12 @@ fn hash_elements_vs_merge_with_int() {
|
|||
assert_eq!(m_result, h_result);
|
||||
|
||||
// ----- value does not fit into a field element ----------------------------------------------
|
||||
let val = BaseElement::MODULUS + 2;
|
||||
let val = Felt::MODULUS + 2;
|
||||
let m_result = Rpo::merge_with_int(seed, val);
|
||||
|
||||
let mut elements = seed.as_elements().to_vec();
|
||||
elements.push(BaseElement::new(val));
|
||||
elements.push(BaseElement::new(1));
|
||||
elements.push(Felt::new(val));
|
||||
elements.push(Felt::new(1));
|
||||
let h_result = Rpo::hash_elements(&elements);
|
||||
|
||||
assert_eq!(m_result, h_result);
|
||||
|
@ -127,8 +127,8 @@ fn hash_padding() {
|
|||
|
||||
#[test]
|
||||
fn hash_elements_padding() {
|
||||
let e1 = [BaseElement::new(rand_value()); 2];
|
||||
let e2 = [e1[0], e1[1], BaseElement::ZERO];
|
||||
let e1 = [Felt::new(rand_value()); 2];
|
||||
let e2 = [e1[0], e1[1], ZERO];
|
||||
|
||||
let r1 = Rpo::hash_elements(&e1);
|
||||
let r2 = Rpo::hash_elements(&e2);
|
||||
|
@ -138,24 +138,22 @@ fn hash_elements_padding() {
|
|||
#[test]
|
||||
fn hash_elements() {
|
||||
let elements = [
|
||||
BaseElement::new(0),
|
||||
BaseElement::new(1),
|
||||
BaseElement::new(2),
|
||||
BaseElement::new(3),
|
||||
BaseElement::new(4),
|
||||
BaseElement::new(5),
|
||||
BaseElement::new(6),
|
||||
BaseElement::new(7)
|
||||
Felt::new(0),
|
||||
Felt::new(1),
|
||||
Felt::new(2),
|
||||
Felt::new(3),
|
||||
Felt::new(4),
|
||||
Felt::new(5),
|
||||
Felt::new(6),
|
||||
Felt::new(7),
|
||||
];
|
||||
|
||||
let digests: [ElementDigest; 2] = [
|
||||
ElementDigest::new(elements[..4].try_into().unwrap()),
|
||||
ElementDigest::new(elements[4..8].try_into().unwrap()),
|
||||
let digests: [RpoDigest256; 2] = [
|
||||
RpoDigest256::new(elements[..4].try_into().unwrap()),
|
||||
RpoDigest256::new(elements[4..8].try_into().unwrap()),
|
||||
];
|
||||
|
||||
let m_result = Rpo::merge(&digests);
|
||||
let h_result = Rpo::hash_elements(&elements);
|
||||
let m_elements :Vec<u64> = m_result.as_elements().iter().map(|a| {a.as_int()}).collect();
|
||||
let h_elements :Vec<u64> = h_result.as_elements().iter().map(|a| {a.as_int()}).collect();
|
||||
assert_eq!(m_elements, h_elements);
|
||||
}
|
||||
assert_eq!(m_result, h_result);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
pub use winter_utils::{
|
||||
ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
|
||||
};
|
||||
pub use winterfell::crypto::{Digest, ElementHasher, Hasher as HashFn};
|
||||
pub use winterfell::math::{
|
||||
fields::{f64::BaseElement as Felt, QuadExtension},
|
||||
ExtensionOf, FieldElement, StarkField,
|
||||
|
@ -10,3 +14,12 @@ pub mod merkle;
|
|||
// ================================================================================================
|
||||
|
||||
pub type Word = [Felt; 4];
|
||||
|
||||
// CONSTANTS
|
||||
// ================================================================================================
|
||||
|
||||
/// Field element representing ZERO in the base field of the VM.
|
||||
pub const ZERO: Felt = Felt::ZERO;
|
||||
|
||||
/// Field element representing ONE in the base field of the VM.
|
||||
pub const ONE: Felt = Felt::ONE;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Felt, FieldElement, MerkleError, Word};
|
||||
use crate::hash::merge;
|
||||
use super::{MerkleError, Word};
|
||||
use crate::{hash::merge, ZERO};
|
||||
use winter_utils::collections::{BTreeMap, Vec};
|
||||
|
||||
// MERKLE PATH SET
|
||||
|
@ -21,7 +21,7 @@ impl MerklePathSet {
|
|||
|
||||
/// Returns an empty MerklePathSet.
|
||||
pub fn new(depth: u32) -> Result<Self, MerkleError> {
|
||||
let root = [Felt::ZERO; 4];
|
||||
let root = [ZERO; 4];
|
||||
let paths = BTreeMap::<u64, Vec<Word>>::new();
|
||||
|
||||
Ok(Self {
|
||||
|
@ -68,7 +68,7 @@ impl MerklePathSet {
|
|||
}
|
||||
|
||||
let root_of_current_path = compute_path_root(&extended_path, depth, index);
|
||||
if self.root == [Felt::ZERO; 4] {
|
||||
if self.root == [ZERO; 4] {
|
||||
self.root = root_of_current_path;
|
||||
} else if self.root != root_of_current_path {
|
||||
return Err(MerkleError::InvalidPath(extended_path));
|
||||
|
@ -254,7 +254,8 @@ fn compute_path_root(path: &[Word], depth: u32, index: u64) -> Word {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{calculate_parent_hash, Felt, FieldElement, Word};
|
||||
use super::calculate_parent_hash;
|
||||
use crate::merkle::int_to_node;
|
||||
|
||||
#[test]
|
||||
fn get_root() {
|
||||
|
@ -344,11 +345,4 @@ mod tests {
|
|||
assert_eq!(new_hash_45, new_path_6[1]);
|
||||
assert_eq!(new_hash_5, new_path_4[0]);
|
||||
}
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
const fn int_to_node(value: u64) -> Word {
|
||||
[Felt::new(value), Felt::ZERO, Felt::ZERO, Felt::ZERO]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,8 +145,7 @@ impl MerkleTree {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Felt, FieldElement, Word};
|
||||
use crate::hash::{ElementHasher, HashFn, Hasher};
|
||||
use crate::{hash::Hasher, merkle::int_to_node, ElementHasher, HashFn, Word};
|
||||
|
||||
const LEAVES4: [Word; 4] = [
|
||||
int_to_node(1),
|
||||
|
@ -253,8 +252,4 @@ mod tests {
|
|||
|
||||
(root.into(), node2.into(), node3.into())
|
||||
}
|
||||
|
||||
const fn int_to_node(value: u64) -> Word {
|
||||
[Felt::new(value), Felt::ZERO, Felt::ZERO, Felt::ZERO]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,3 +16,10 @@ pub enum MerkleError {
|
|||
InvalidPath(Vec<Word>),
|
||||
NodeNotInSet(u64),
|
||||
}
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
// ================================================================================================
|
||||
|
||||
const fn int_to_node(value: u64) -> Word {
|
||||
[Felt::new(value), Felt::ZERO, Felt::ZERO, Felt::ZERO]
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue