Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/starknet_os/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod hint_processor;
pub mod hints;
pub mod io;
pub mod metrics;
pub mod proof_fact_fold;
pub mod runner;
pub mod syscall_handler_utils;
#[cfg(any(test, feature = "testing"))]
Expand Down
31 changes: 31 additions & 0 deletions crates/starknet_os/src/proof_fact_fold.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//! Reproduces the proving side's recursive proof-tree digests over privacy transactions'
//! proof facts. Matches the goldens from the `proving` crate `stwo_run_and_prove_recursive_tree`.

use blake2::{Blake2s256, Digest};
use starknet_types_core::felt::Felt;
use starknet_types_core::hash::Blake2Felt252;

#[cfg(test)]
#[path = "proof_fact_fold_test.rs"]
mod proof_fact_fold_test;

pub const BLAKE2S_DIGEST_N_WORDS: usize = 8;

/// A Blake2s-256 digest as little-endian u32 words.
pub type Blake2sDigestWords = [u32; BLAKE2S_DIGEST_N_WORDS];

/// Computes one transaction's leaf output digest:
/// blake2s(encode_felt252s_to_u32s(proof_facts[2..])). The preimage drops the two
/// version markers, keeping [program_hash, ...virtual OS output].
pub fn compute_leaf_output_digest(proof_facts: &[Felt]) -> Blake2sDigestWords {
assert!(proof_facts.len() >= 3, "proof facts must contain at least 3 felts");
blake2s_over_u32_words(&Blake2Felt252::encode_felts_to_u32s(&proof_facts[2..]))
}

pub fn blake2s_over_u32_words(words: &[u32]) -> Blake2sDigestWords {
let bytes: Vec<u8> = words.iter().flat_map(|word| word.to_le_bytes()).collect();
let digest_bytes: [u8; 32] = Blake2s256::digest(&bytes).into();
std::array::from_fn(|word_index| {
u32::from_le_bytes(digest_bytes[word_index * 4..(word_index + 1) * 4].try_into().unwrap())
})
}
23 changes: 23 additions & 0 deletions crates/starknet_os/src/proof_fact_fold_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use starknet_types_core::felt::Felt;

use super::{compute_leaf_output_digest, Blake2sDigestWords};

#[test]
fn test_leaf_output_digest_matches_proving_side_golden() {
let proving_side_preimage = [
Felt::from_dec_str(
"1433852663250257978909904594223798547176815246431631498282706690602142197827",
)
.unwrap(),
Felt::from(11),
Felt::from(13),
Felt::from(17),
];
let proof_facts: Vec<Felt> =
[Felt::ZERO, Felt::ZERO].into_iter().chain(proving_side_preimage).collect();
let expected_digest_words: Blake2sDigestWords = [
1603116091, 3258597502, 2711032228, 4175407283, 343882323, 1898618121, 1344732087,
1064799167,
];
assert_eq!(compute_leaf_output_digest(&proof_facts), expected_digest_words);
}
Loading