Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
glihm committed Feb 20, 2025
2 parents a9090ef + 35d0bc6 commit 40bfd1d
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 290 deletions.
321 changes: 169 additions & 152 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ hex = { version = "0.4.3", default-features = false }
integrity = { version = "0.1.0", default-features = false, features = ["recursive_with_poseidon", "keccak_160_lsb", "stone6"] }
log = "0.4.22"
num-traits = { version = "0.2.19", default-features = false }
prove_block = { git = "https://github.com/cartridge-gg/snos", rev = "7183af4" }
prove_block = { git = "https://github.com/cartridge-gg/snos", rev = "03f07963" }
reqwest = { version = "0.12.12", default-features = false, features = ["json", "multipart", "rustls-tls"] }
serde = { version = "1.0.217", default-features = false, features = ["derive"] }
serde_json = { version = "1.0.134", default-features = false }
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,13 @@ saya persistent start \
```

By doing so, Saya will mock the layout bridge proof and call the `update_state` function of the settlement contract.

In order to also mock the SNOS proof, you can use the following command:

```
saya persistent start \
--mock-layout-bridge-program-hash 0x193641eb151b0f41674641089952e60bc3aded26e3cf42793655c562b8c3aa0 \
--mock-snos-from-pie
```

This will generates the SNOS's PIE, and mock the proof from it.
2 changes: 1 addition & 1 deletion bin/saya/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async fn main() -> Result<()> {
if std::env::var("RUST_LOG").is_err() {
std::env::set_var(
"RUST_LOG",
"info,saya=debug,saya_core=debug,rpc_client=off,prove_block=off",
"info,saya=trace,saya_core=trace,rpc_client=info,prove_block=off",
);
}
env_logger::init();
Expand Down
5 changes: 4 additions & 1 deletion bin/saya/src/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ struct Start {
/// Path to the compiled Starknet OS program
#[clap(long, env)]
snos_program: PathBuf,
/// Whether to mock the SNOS proof by extracting the output from the PIE and using it from a proof.
#[clap(long)]
mock_snos_from_pie: bool,
/// Path to the compiled Cairo verifier program
#[clap(long, env)]
layout_bridge_program: Option<PathBuf>,
Expand Down Expand Up @@ -133,7 +136,7 @@ impl Start {
let block_ingestor_builder =
PollingBlockIngestorBuilder::new(self.rollup_rpc, snos, pie_gen);
let prover_builder = RecursiveProverBuilder::new(
AtlanticSnosProverBuilder::new(self.atlantic_key),
AtlanticSnosProverBuilder::new(self.atlantic_key, self.mock_snos_from_pie),
layout_bridge_prover_builder,
);
let da_builder = NoopDataAvailabilityBackendBuilder::new();
Expand Down
5 changes: 4 additions & 1 deletion bin/saya/src/sovereign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ struct Start {
/// Path to the compiled Starknet OS program
#[clap(long, env)]
snos_program: PathBuf,
/// Whether to mock the SNOS proof by extracting the output from the PIE and using it from a proof.
#[clap(long)]
mock_snos_from_pie: bool,
/// Atlantic prover API key
#[clap(long, env)]
atlantic_key: String,
Expand Down Expand Up @@ -108,7 +111,7 @@ impl Start {
let pie_gen: SnosPieGenerator = self.pie_mode.into();
let block_ingestor_builder =
PollingBlockIngestorBuilder::new(self.starknet_rpc, snos, pie_gen);
let prover_builder = AtlanticSnosProverBuilder::new(self.atlantic_key);
let prover_builder = AtlanticSnosProverBuilder::new(self.atlantic_key, self.mock_snos_from_pie);
let da_builder =
CelestiaDataAvailabilityBackendBuilder::new(self.celestia_rpc, self.celestia_token);
let storage = InMemoryStorageBackend::new();
Expand Down
61 changes: 55 additions & 6 deletions saya/core/src/prover/atlantic/snos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ use std::{io::Write, sync::Arc, time::Duration};

use anyhow::Result;
use cairo_vm::vm::runners::cairo_pie::CairoPie;
use log::{debug, info};
use log::{debug, info, trace};
use tokio::{
sync::{
mpsc::{Receiver, Sender},
Mutex,
},
task,
time::sleep,
};
use zip::{write::FileOptions, ZipWriter};
use starknet::core::types::Felt;

use crate::{
block_ingestor::NewBlock,
Expand All @@ -23,6 +23,7 @@ use crate::{
Prover, ProverBuilder, SnosProof,
},
service::{Daemon, FinishHandle, ShutdownHandle},
utils::{compute_program_hash_from_pie, extract_pie_output, stark_proof_mock},
};

const PROOF_STATUS_POLL_INTERVAL: Duration = Duration::from_secs(10);
Expand All @@ -35,13 +36,16 @@ pub struct AtlanticSnosProver<P> {
statement_channel: Receiver<NewBlock>,
proof_channel: Sender<SnosProof<P>>,
finish_handle: FinishHandle,
/// Whether to extract the output and compute the program hash from the PIE or use the one from the SHARP bootloader returned by the prover service.
mock_snos_from_pie: bool,
}

#[derive(Debug)]
pub struct AtlanticSnosProverBuilder<P> {
api_key: String,
statement_channel: Option<Receiver<NewBlock>>,
proof_channel: Option<Sender<SnosProof<P>>>,
mock_snos_from_pie: bool,
}

impl<P> AtlanticSnosProver<P>
Expand All @@ -53,6 +57,7 @@ where
task_tx: Sender<SnosProof<P>>,
client: AtlanticClient,
finish_handle: FinishHandle,
mock_snos_from_pie: bool,
) where
P: AtlanticProof,
{
Expand All @@ -62,11 +67,32 @@ where
} else {
break;
};
if new_block.number % 2 == 0 {
sleep(Duration::from_secs(10)).await;

// TODO: move this to a separate MockSnosProver.
if mock_snos_from_pie {
let output = bootloader_snos_output(&new_block.pie);
let mock_proof = stark_proof_mock(&output);

info!(
"Mock proof generated from PIE for block #{}",
new_block.number
);

let new_proof = SnosProof {
block_number: new_block.number,
proof: P::parse(serde_json::to_string(&mock_proof).unwrap()).unwrap(),
};

let _ = task_tx.send(new_proof).await;

continue;
}
debug!("Compressing PIE for block #{}", new_block.number);

trace!("Compressing PIE for block #{}", new_block.number);

// TODO: error handling
let compressed_pie = compress_pie(new_block.pie).await.unwrap();

debug!(
"Compressed PIE size for block #{}: {} bytes",
new_block.number,
Expand Down Expand Up @@ -141,6 +167,7 @@ where
worker_task_tx,
self.client.clone(),
self.finish_handle.clone(),
self.mock_snos_from_pie,
)));
}
futures_util::future::join_all(workers).await;
Expand All @@ -150,11 +177,12 @@ where
}

impl<P> AtlanticSnosProverBuilder<P> {
pub fn new(api_key: String) -> Self {
pub fn new(api_key: String, mock_snos_from_pie: bool) -> Self {
Self {
api_key,
statement_channel: None,
proof_channel: None,
mock_snos_from_pie,
}
}
}
Expand All @@ -175,6 +203,7 @@ where
.proof_channel
.ok_or_else(|| anyhow::anyhow!("`proof_channel` not set"))?,
finish_handle: FinishHandle::new(),
mock_snos_from_pie: self.mock_snos_from_pie,
})
}

Expand Down Expand Up @@ -237,3 +266,23 @@ pub async fn compress_pie(pie: CairoPie) -> std::result::Result<Vec<u8>, std::io
})
.await?
}

/// Mocks a bootloaded execution of SNOS.
fn bootloader_snos_output(pie: &CairoPie) -> Vec<Felt> {
let snos_program_hash =
compute_program_hash_from_pie(pie).expect("Failed to compute program hash from PIE");
debug!("SNOS program hash from PIE: {:x}", snos_program_hash);

let snos_output = extract_pie_output(pie);

let mut bootloader_output = vec![
// Bootloader config (not checked by piltover, set to 0)
Felt::ZERO,
// bootloader output len (not checked by piltover, set to 0)
Felt::ZERO,
snos_program_hash,
];

bootloader_output.extend(snos_output);
bootloader_output
}
145 changes: 17 additions & 128 deletions saya/core/src/prover/mock/layout_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use integrity::Felt;
use log::{debug, info};
use starknet_crypto::poseidon_hash_many;
use swiftness::TransformTo;
use swiftness_air::types::SegmentInfo;
use swiftness_stark::types::StarkProof;
use tokio::sync::mpsc::{Receiver, Sender};

Expand Down Expand Up @@ -48,125 +47,25 @@ impl MockLayoutBridgeProver {
);

// TODO: error handling
let parsed_snos_proof: StarkProof = swiftness::parse(&new_snos_proof.proof)
.unwrap()
.transform_to();
let parsed_snos_proof: StarkProof = match swiftness::parse(&new_snos_proof.proof) {
Ok(proof) => proof.transform_to(),
Err(_) => {
// If the proof is sent by a mocked SNOS, it's already in the correct format.
serde_json::from_str::<StarkProof>(&new_snos_proof.proof).unwrap()
}
};

let snos_output = calculate_output(&parsed_snos_proof);

// This proof is mocked but calling `calculate_output` on it correctly yieids the
// expected output.
//
// This spaghetti is needed because `StarkProof` does not implement `Default`.
let mock_proof = StarkProof {
config: swiftness::config::StarkConfig {
traces: swiftness_air::trace::config::Config {
original: default_table_commitment_config(),
interaction: default_table_commitment_config(),
},
composition: default_table_commitment_config(),
fri: swiftness_fri::config::Config {
log_input_size: Default::default(),
n_layers: Default::default(),
inner_layers: Default::default(),
fri_step_sizes: Default::default(),
log_last_layer_degree_bound: Default::default(),
},
proof_of_work: swiftness_pow::config::Config {
n_bits: Default::default(),
},
log_trace_domain_size: Default::default(),
n_queries: Default::default(),
log_n_cosets: Default::default(),
n_verifier_friendly_commitment_layers: Default::default(),
},
public_input: swiftness_air::public_memory::PublicInput {
log_n_steps: Default::default(),
range_check_min: Default::default(),
range_check_max: Default::default(),
layout: Default::default(),
dynamic_params: Default::default(),
segments: vec![
SegmentInfo {
begin_addr: Default::default(),
stop_ptr: Default::default(),
},
SegmentInfo {
begin_addr: Default::default(),
stop_ptr: Default::default(),
},
SegmentInfo {
begin_addr: Felt::ZERO,
stop_ptr: Felt::from(5),
},
],
padding_addr: Default::default(),
padding_value: Default::default(),
main_page: swiftness_air::types::Page(
[
Felt::ZERO,
Felt::ZERO,
self.layout_bridge_program_hash,
Felt::ZERO,
poseidon_hash_many(&snos_output),
]
.into_iter()
.map(|value| swiftness_air::types::AddrValue {
address: Default::default(),
value,
})
.collect(),
),
continuous_page_headers: Default::default(),
},
unsent_commitment: swiftness::types::StarkUnsentCommitment {
traces: swiftness_air::trace::UnsentCommitment {
original: Default::default(),
interaction: Default::default(),
},
composition: Default::default(),
oods_values: Default::default(),
fri: swiftness_fri::types::UnsentCommitment {
inner_layers: Default::default(),
last_layer_coefficients: Default::default(),
},
proof_of_work: swiftness_pow::pow::UnsentCommitment {
nonce: Default::default(),
},
},
witness: swiftness_stark::types::StarkWitness {
traces_decommitment: swiftness_air::trace::Decommitment {
original: swiftness_commitment::table::types::Decommitment {
values: Default::default(),
},
interaction: swiftness_commitment::table::types::Decommitment {
values: Default::default(),
},
},
traces_witness: swiftness_air::trace::Witness {
original: swiftness_commitment::table::types::Witness {
vector: swiftness_commitment::vector::types::Witness {
authentications: Default::default(),
},
},
interaction: swiftness_commitment::table::types::Witness {
vector: swiftness_commitment::vector::types::Witness {
authentications: Default::default(),
},
},
},
composition_decommitment: swiftness_commitment::table::types::Decommitment {
values: Default::default(),
},
composition_witness: swiftness_commitment::table::types::Witness {
vector: swiftness_commitment::vector::types::Witness {
authentications: Default::default(),
},
},
fri_witness: swiftness_fri::types::Witness {
layers: Default::default(),
},
},
};
let bootloader_output = [
Felt::ZERO,
Felt::ZERO,
self.layout_bridge_program_hash,
Felt::ZERO,
poseidon_hash_many(&snos_output),
];

let mock_proof = crate::utils::stark_proof_mock(&bootloader_output);

let new_proof = RecursiveProof {
block_number: new_snos_proof.block_number,
Expand Down Expand Up @@ -241,13 +140,3 @@ impl Daemon for MockLayoutBridgeProver {
tokio::spawn(self.run());
}
}

fn default_table_commitment_config() -> swiftness_commitment::table::config::Config {
swiftness_commitment::table::config::Config {
n_columns: Default::default(),
vector: swiftness_commitment::vector::config::Config {
height: Default::default(),
n_verifier_friendly_commitment_layers: Default::default(),
},
}
}
Loading

0 comments on commit 40bfd1d

Please sign in to comment.