-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prover service trait and SHARP client implementation
- Loading branch information
Showing
41 changed files
with
5,564 additions
and
631 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
Large diffs are not rendered by default.
Oops, something went wrong.
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,8 @@ | ||
use alloy::sol; | ||
|
||
sol!( | ||
#[allow(missing_docs)] | ||
#[sol(rpc)] | ||
FactRegistry, | ||
"src/contracts/artifacts/FactRegistry.json" | ||
); |
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,49 @@ | ||
use cairo_vm::program_hash::ProgramHashError; | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum FactCheckerError { | ||
#[error("Fact registry call failed: {0}")] | ||
FactRegistry(#[source] alloy::contract::Error), | ||
#[error("Failed to compute program hash: {0}")] | ||
ProgramHashCompute(#[from] ProgramHashError), | ||
#[error("Tree structure length is not even")] | ||
TreeStructureLenOdd, | ||
#[error("Tree structure is empty")] | ||
TreeStructureEmpty, | ||
#[error("Tree structure is too large")] | ||
TreeStructureTooLarge, | ||
#[error("Tree structure contains invalid values")] | ||
TreeStructureInvalid, | ||
#[error("Output pages length is unexpected")] | ||
OutputPagesLenUnexpected, | ||
#[error("Output page {0} has invalid start {1} (expected 0 < x < {2})")] | ||
OutputPagesInvalidStart(usize, usize, usize), | ||
#[error("Output page {0} has expected start {1} (expected{2})")] | ||
OutputPagesUnexpectedStart(usize, usize, usize), | ||
#[error("Output page {0} has invalid size {1} (expected 0 < x < {2})")] | ||
OutputPagesInvalidSize(usize, usize, usize), | ||
#[error("Output page {0} has unexpected id (expected {1})")] | ||
OutputPagesUnexpectedId(usize, usize), | ||
#[error("Output pages cover only {0} out of {1} output elements")] | ||
OutputPagesUncoveredOutput(usize, usize), | ||
#[error("Output segment is not found in the memory")] | ||
OutputSegmentNotFound, | ||
#[error("Output segment does not fit into the memory")] | ||
OutputSegmentInvalidRange, | ||
#[error("Output segment contains inconsistent offset {0} (expected {1})")] | ||
OutputSegmentInconsistentOffset(usize, usize), | ||
#[error("Output segment contains unexpected relocatable at position {0}")] | ||
OutputSegmentUnexpectedRelocatable(usize), | ||
#[error("Tree structure: pages count {0} is in invalid range (expected <= {1})")] | ||
TreeStructurePagesCountOutOfRange(usize, usize), | ||
#[error("Tree structure: nodes count {0} is in invalid range (expected <= {1})")] | ||
TreeStructureNodesCountOutOfRange(usize, usize), | ||
#[error("Tree structure: node stack contains more than one node")] | ||
TreeStructureRootInvalid, | ||
#[error("Tree structure: {0} pages were not processed")] | ||
TreeStructurePagesNotProcessed(usize), | ||
#[error("Tree structure: end offset {0} does not match the output length {1}")] | ||
TreeStructureEndOffsetInvalid(usize, usize), | ||
#[error("Tree structure: root offset {0} does not match the output length {1}")] | ||
TreeStructureRootOffsetInvalid(usize, usize), | ||
} |
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,72 @@ | ||
//! Fact info structure and helpers. | ||
//! | ||
//! Port of https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/bootloaders/generate_fact.py | ||
use alloy::primitives::{keccak256, B256}; | ||
use cairo_vm::{ | ||
program_hash::compute_program_hash_chain, | ||
types::{builtin_name::BuiltinName, relocatable::MaybeRelocatable}, | ||
vm::runners::cairo_pie::CairoPie, | ||
Felt252, | ||
}; | ||
use starknet::core::types::FieldElement; | ||
|
||
use super::{ | ||
error::FactCheckerError, | ||
fact_node::generate_merkle_root, | ||
fact_topology::{get_fact_topology, FactTopology}, | ||
}; | ||
|
||
pub const BOOTLOADER_VERSION: usize = 1; | ||
|
||
pub struct FactInfo { | ||
pub program_output: Vec<Felt252>, | ||
pub fact_topology: FactTopology, | ||
pub fact: B256, | ||
} | ||
|
||
pub fn get_fact_info(cairo_pie: &CairoPie, program_hash: Option<FieldElement>) -> Result<FactInfo, FactCheckerError> { | ||
let program_output = get_program_output(cairo_pie)?; | ||
let fact_topology = get_fact_topology(cairo_pie, program_output.len())?; | ||
let program_hash = match program_hash { | ||
Some(hash) => hash, | ||
None => compute_program_hash_chain(&cairo_pie.metadata.program, BOOTLOADER_VERSION)?, | ||
}; | ||
let output_root = generate_merkle_root(&program_output, &fact_topology)?; | ||
let fact = keccak256([program_hash.to_bytes_be(), *output_root.node_hash].concat()); | ||
Ok(FactInfo { program_output, fact_topology, fact }) | ||
} | ||
|
||
pub fn get_program_output(cairo_pie: &CairoPie) -> Result<Vec<Felt252>, FactCheckerError> { | ||
let segment_info = cairo_pie.metadata.builtin_segments.get(&BuiltinName::output).unwrap(); | ||
|
||
let segment_start = cairo_pie | ||
.memory | ||
.0 | ||
.iter() | ||
.enumerate() | ||
.find_map(|(ptr, ((index, _), _))| if *index == segment_info.index as usize { Some(ptr) } else { None }) | ||
.ok_or(FactCheckerError::OutputSegmentNotFound)?; | ||
|
||
let mut output = Vec::with_capacity(segment_info.size); | ||
let mut expected_offset = 0; | ||
|
||
for i in segment_start..segment_start + segment_info.size { | ||
let ((_, offset), value) = cairo_pie.memory.0.get(i).ok_or(FactCheckerError::OutputSegmentInvalidRange)?; | ||
|
||
if *offset != expected_offset { | ||
return Err(FactCheckerError::OutputSegmentInconsistentOffset(*offset, expected_offset)); | ||
} | ||
|
||
match value { | ||
MaybeRelocatable::Int(felt) => output.push(felt.clone()), | ||
MaybeRelocatable::RelocatableValue(_) => { | ||
return Err(FactCheckerError::OutputSegmentUnexpectedRelocatable(*offset)) | ||
} | ||
} | ||
|
||
expected_offset += 1; | ||
} | ||
|
||
Ok(output) | ||
} |
Oops, something went wrong.