Skip to content

Commit

Permalink
Support Cairo 1
Browse files Browse the repository at this point in the history
  • Loading branch information
delaaxe committed Jun 6, 2024
1 parent a29acce commit 4155dda
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
scarb nightly-2024-03-16
scarb 2.6.3
starknet-foundry 0.20.1
12 changes: 8 additions & 4 deletions runner/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use std::{
#[command(author, version, about, long_about = None)]
struct Cli {
/// Path to compiled sierra file
target: String,
program: String,
/// Cairo version
cairo_version: u8,
}

fn main() -> anyhow::Result<()> {
Expand All @@ -25,7 +27,6 @@ fn main() -> anyhow::Result<()> {
stdin().read_to_string(&mut input)?;
let parsed = parse(input)?;

let target = cli.target;
let function = "main";

let config: VecFelt252 = serde_json::from_str(&parsed.config.to_string()).unwrap();
Expand All @@ -45,7 +46,7 @@ fn main() -> anyhow::Result<()> {
println!("proof size: {} felts", proof.len());

let sierra_program =
serde_json::from_str::<VersionedProgram>(&fs::read_to_string(target)?)?.into_v1()?;
serde_json::from_str::<VersionedProgram>(&fs::read_to_string(cli.program)?)?.into_v1()?;

let runner = SierraCasmRunner::new(
sierra_program.program.clone(),
Expand All @@ -54,11 +55,14 @@ fn main() -> anyhow::Result<()> {
Some(ProfilingInfoCollectionConfig::default()),
)
.unwrap();

let func = runner.find_function(function).unwrap();
let proof_arg = Arg::Array(proof.into_iter().map(Arg::Value).collect_vec());
let cairo_version_arg = Arg::Value(cli.cairo_version.into());
let result = runner
.run_function_with_starknet_context(
func,
&[Arg::Array(proof.into_iter().map(Arg::Value).collect_vec())],
&[proof_arg, cairo_version_arg],
Some(u32::MAX as usize),
Default::default(),
)
Expand Down
115 changes: 61 additions & 54 deletions src/air/layouts/recursive/public_input.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use cairo_verifier::{
segments, get_builtins, CPU_COMPONENT_HEIGHT, CPU_COMPONENT_STEP, LAYOUT_CODE,
PEDERSEN_BUILTIN_ROW_RATIO, RANGE_CHECK_BUILTIN_ROW_RATIO, BITWISE_ROW_RATIO
},
public_input::{PublicInput, PublicInputTrait}
public_input::{CairoVersion, PublicInput, PublicInputTrait}
},
domains::StarkDomains
};
Expand All @@ -19,7 +19,7 @@ use core::{pedersen::PedersenTrait, hash::{HashStateTrait, HashStateExTrait, Has
use poseidon::poseidon_hash_span;

impl RecursivePublicInputImpl of PublicInputTrait {
fn verify(self: @PublicInput) -> (felt252, felt252) {
fn verify(self: @PublicInput, cairo_version: CairoVersion) -> (felt252, felt252) {
let public_segments = self.segments;

let initial_pc = *public_segments.at(segments::PROGRAM).begin_addr;
Expand All @@ -39,77 +39,84 @@ impl RecursivePublicInputImpl of PublicInputTrait {
let builtins = get_builtins();
let memory = self.main_page;

let offset = match cairo_version {
CairoVersion::Cairo0 => 0,
CairoVersion::Cairo1 => 1,
};

// 1. Program segment
assert(initial_pc == INITIAL_PC, 'Invalid initial_pc');
assert(final_pc == INITIAL_PC + 4, 'Invalid final_pc');
assert(final_pc == INITIAL_PC + 4 + offset, 'Invalid final_pc');

let mut memory_index: usize = 0;

let program_end_pc = initial_fp - 2;
let program_end_pc = initial_fp - (2 + offset);
let program_len = program_end_pc - initial_pc;
let program = memory
.extract_range(
initial_pc.try_into().unwrap(), program_len.try_into().unwrap(), ref memory_index
);

assert(
*program[0] == 0x40780017fff7fff, 'Invalid program'
); // Instruction: ap += N_BUILTINS.
assert(*program[1] == builtins.len().into(), 'Invalid program');
assert(*program[2] == 0x1104800180018000, 'Invalid program'); // Instruction: call rel ?.
assert(*program[4] == 0x10780017fff7fff, 'Invalid program'); // Instruction: jmp rel 0.
assert(*program[5] == 0x0, 'Invalid program');

let program_hash = poseidon_hash_span(program);

// 2. Execution segment
// 2.1 Initial_fp, initial_pc
let fp2 = *memory.at(memory_index);
assert(fp2.address == initial_fp - 2, 'Invalid fp2 addr');
assert(fp2.value == initial_fp, 'Invalid fp2 val');

let fp1 = *memory.at(memory_index + 1);
assert(fp1.address == initial_fp - 1, 'Invalid fp1 addr');
assert(fp1.value == 0, 'Invalid fp1 val');
memory_index += 2;

// 2.2 Main arguments and return values
let mut begin_addresses = ArrayTrait::new();
let mut stop_addresses = ArrayTrait::new();
let mut i = 0;
let builtins_len = builtins.len();
loop {
if i == builtins_len {
break;
}

begin_addresses.append(*public_segments.at(2 + i).begin_addr);
stop_addresses.append(*public_segments.at(2 + i).stop_ptr);

i += 1;
};
memory.verify_stack(initial_ap, begin_addresses.span(), builtins_len, ref memory_index);
memory
.verify_stack(
final_ap - builtins_len.into(),
stop_addresses.span(),
builtins_len,
ref memory_index
);
if cairo_version == CairoVersion::Cairo0 {
// Instruction: ap += N_BUILTINS.
assert(*program[0] == 0x40780017fff7fff, 'Invalid program');
assert(*program[1] == builtins.len().into(), 'Invalid program');
// Instruction: call rel ?.
assert(*program[2] == 0x1104800180018000, 'Invalid program');
// Instruction: jmp rel 0.
assert(*program[4] == 0x10780017fff7fff, 'Invalid program');
assert(*program[5] == 0x0, 'Invalid program');

// 2. Execution segment
// 2.1 Initial_fp, initial_pc
let fp2 = *memory.at(memory_index);
assert(fp2.address == initial_fp - 2, 'Invalid fp2 addr');
assert(fp2.value == initial_fp, 'Invalid fp2 val');

let fp1 = *memory.at(memory_index + 1);
assert(fp1.address == initial_fp - 1, 'Invalid fp1 addr');
assert(fp1.value == 0, 'Invalid fp1 val');
memory_index += 2;

// 2.2 Main arguments and return values
let mut begin_addresses = array![];
let mut stop_addresses = array![];
let mut i = 0;
let builtins_len = builtins.len();
while i != builtins_len {
let segment = *public_segments.at(2 + i);
begin_addresses.append(segment.begin_addr);
stop_addresses.append(segment.stop_ptr);
i += 1;
};

memory.verify_stack(initial_ap, begin_addresses.span(), builtins_len, ref memory_index);
memory
.verify_stack(
final_ap - builtins_len.into(),
stop_addresses.span(),
builtins_len,
ref memory_index
);
}

// 3. Output segment
let output_len = output_stop - output_start;
let output = memory
.extract_range(
output_start.try_into().unwrap(), output_len.try_into().unwrap(), ref memory_index
);
let output_hash = poseidon_hash_span(output);

// Check main page len
assert(
*memory.at(memory_index - 1) == *self.main_page.at(self.main_page.len() - 1),
'Invalid main page len'
);
if cairo_version == CairoVersion::Cairo0 {
// Check main page len
assert(
*memory.at(memory_index - 1) == *memory.at(memory.len() - 1),
'Invalid main page len'
);
}

let program_hash = poseidon_hash_span(program);
let output_hash = poseidon_hash_span(output);

(program_hash, output_hash)
}
Expand Down
8 changes: 7 additions & 1 deletion src/air/public_input.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ struct PublicInput {
continuous_page_headers: Array<ContinuousPageHeader>
}

#[derive(Drop, Copy, PartialEq, Serde)]
enum CairoVersion {
Cairo0,
Cairo1,
}

trait PublicInputTrait {
fn verify(self: @PublicInput) -> (felt252, felt252);
fn verify(self: @PublicInput, cairo_version: CairoVersion) -> (felt252, felt252);
fn validate(self: @PublicInput, stark_domains: @StarkDomains);
}

Expand Down
15 changes: 6 additions & 9 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ mod tests;
// === RECURSIVE END ===

use cairo_verifier::{
deserialization::stark::StarkProofWithSerde, stark::{StarkProof, StarkProofImpl},
air::public_input::CairoVersion, deserialization::stark::StarkProofWithSerde,
stark::{StarkProof, StarkProofImpl},
// === DEX BEGIN ===
// air::layouts::dex::public_input::DexPublicInputImpl as PublicInputImpl,
// === DEX END ===
Expand All @@ -42,16 +43,12 @@ use cairo_verifier::{

const SECURITY_BITS: felt252 = 50;

fn main(serialized_proof: Array<felt252>) -> (felt252, felt252) {
let mut serialized_proof_span = serialized_proof.span();
let stark_proof: StarkProof = Serde::<
StarkProofWithSerde
>::deserialize(ref serialized_proof_span)
.unwrap()
.into();
fn main(mut serialized: Span<felt252>, cairo_version: CairoVersion) -> (felt252, felt252) {
let stark_proof_serde = Serde::<StarkProofWithSerde>::deserialize(ref serialized).unwrap();
let stark_proof: StarkProof = stark_proof_serde.into();

stark_proof.verify(SECURITY_BITS);
let (program_hash, output_hash) = stark_proof.public_input.verify();
let (program_hash, output_hash) = stark_proof.public_input.verify(cairo_version);

(program_hash, output_hash)
}

0 comments on commit 4155dda

Please sign in to comment.