Skip to content

Commit

Permalink
Poseidon merkle hasher
Browse files Browse the repository at this point in the history
  • Loading branch information
spapinistarkware committed May 6, 2024
1 parent f1b8d89 commit 955b3ae
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cairo-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ jobs:
- uses: actions/checkout@v3
- uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.6.4"
scarb-version: "nightly-2024-04-24"
- run: scarb fmt --check
- run: scarb test
1 change: 1 addition & 0 deletions stwo_cairo_verifier/.tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scarb nightly-2024-04-24
2 changes: 1 addition & 1 deletion stwo_cairo_verifier/src/fields/m31.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const P64NZ: NonZero<u64> = 0x7fffffff;

#[derive(Copy, Drop, Debug, PartialEq, Eq)]
pub struct M31 {
inner: u32
pub inner: u32
}

#[generate_trait]
Expand Down
3 changes: 3 additions & 0 deletions stwo_cairo_verifier/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
mod fields;
mod vcs;

pub type BaseField = fields::m31::M31;

fn main() {}
61 changes: 61 additions & 0 deletions stwo_cairo_verifier/src/vcs.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use core::array::ArrayTrait;
use core::option::OptionTrait;
use core::poseidon::poseidon_hash_span;
use stwo_cairo_verifier::BaseField;

pub trait MerkleHasher {
type Hash;
/// Hashes a single Merkle node. See [MerkleHasher] for more details.
fn hash_node(
children_hashes: Option<(Self::Hash, Self::Hash)>, column_values: Array<BaseField>,
) -> Self::Hash;
}

pub impl PoseidonMerkleHasher of MerkleHasher {
type Hash = felt252;

fn hash_node(
children_hashes: Option<(Self::Hash, Self::Hash)>, mut column_values: Array<BaseField>,
) -> Self::Hash {
let mut hash_array: Array<felt252> = Default::default();
if let Option::Some((x, y)) = children_hashes {
hash_array.append(x);
hash_array.append(y);
}

// Pad column_values to a multiple of 8.
let mut pad_len = 7 - ((column_values.len() + 7) % 8);
while pad_len > 0 {
column_values.append(core::num::traits::Zero::zero());
pad_len = 7 - ((column_values.len() + 7) % 8);
};

while !column_values.is_empty() {
let mut word = 0;
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
word = word * 0x80000000 + column_values.pop_front().unwrap().inner.into();
};

poseidon_hash_span(hash_array.span())
}
}

#[cfg(test)]
mod tests {
use super::PoseidonMerkleHasher;
use stwo_cairo_verifier::fields::m31::{m31};

#[test]
fn test_m31() {
assert_eq!(
PoseidonMerkleHasher::hash_node(Option::None, array![m31(0), m31(1)]),
973835572668429495915136902981656666590582180872133591629269551720657739196
);
}
}

0 comments on commit 955b3ae

Please sign in to comment.