Browse Source

fix misc. nits

al-gkr-basic-workflow
Al-Kindi-0 2 years ago
parent
commit
bbfddcfbd3
8 changed files with 683 additions and 672 deletions
  1. +4
    -13
      crypto/src/hash/mod.rs
  2. +31
    -31
      crypto/src/hash/rpo/digest.rs
  3. +587
    -574
      crypto/src/hash/rpo/mod.rs
  4. +34
    -36
      crypto/src/hash/rpo/tests.rs
  5. +13
    -0
      crypto/src/lib.rs
  6. +6
    -12
      crypto/src/merkle/merkle_path_set.rs
  7. +1
    -6
      crypto/src/merkle/merkle_tree.rs
  8. +7
    -0
      crypto/src/merkle/mod.rs

+ 4
- 13
crypto/src/hash/mod.rs

@ -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 = ::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)

+ 31
- 31
crypto/src/hash/rpo/digest.rs

@ -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 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);
}

+ 587
- 574
crypto/src/hash/rpo/mod.rs
File diff suppressed because it is too large
View File


+ 34
- 36
crypto/src/hash/rpo/tests.rs

@ -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);
}

+ 13
- 0
crypto/src/lib.rs

@ -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;

+ 6
- 12
crypto/src/merkle/merkle_path_set.rs

@ -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]
}
}

+ 1
- 6
crypto/src/merkle/merkle_tree.rs

@ -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]
}
}

+ 7
- 0
crypto/src/merkle/mod.rs

@ -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…
Cancel
Save