Skip to content

Commit

Permalink
feat: removing sp1-sdk dependency for lightclient (#193)
Browse files Browse the repository at this point in the history
* feat: removing sp1-sdk dependency for lightclient

* removing dep

* review fixes

* rebase fixes
  • Loading branch information
distractedm1nd authored Jan 13, 2025
1 parent c674e55 commit 3e7ba32
Show file tree
Hide file tree
Showing 9 changed files with 453 additions and 317 deletions.
646 changes: 362 additions & 284 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ dotenvy = "0.15.7"

# zk
rand = "0.8.5"
sp1-zkvm = { version = "3.0.0-rc1" }
sp1-sdk = { version = "3.0.0-rc1" }
sp1-zkvm = { version = "3.2.1" }
sp1-sdk = { version = "3.2.1" }
sp1-verifier = { version = "3.2.1", default-features = false }

# curves
ed25519-consensus = "2.1.0"
Expand Down
1 change: 1 addition & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dirs = { workspace = true }
anyhow = { workspace = true }
prism-storage = { workspace = true }
prism-errors = { workspace = true }
sp1-sdk = { workspace = true }
prism-prover = { workspace = true }
prism-lightclient = { workspace = true }
prism-da = { workspace = true }
Expand Down
26 changes: 23 additions & 3 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use cfg::{initialize_da_layer, load_config, Cli, Commands};
use clap::Parser;
use keystore_rs::{KeyChain, KeyStore, KeyStoreType};
use prism_keys::{CryptoAlgorithm, SigningKey, VerifyingKey};
use sp1_sdk::{HashableKey, ProverClient};
use std::io::{Error, ErrorKind};

use node_types::NodeType;
use prism_lightclient::LightClient;
use prism_prover::Prover;
use prism_storage::RedisConnection;
use std::{str::FromStr, sync::Arc};

#[macro_use]
extern crate log;

Expand Down Expand Up @@ -47,7 +49,15 @@ async fn main() -> std::io::Result<()> {
)
.map_err(|e| Error::new(ErrorKind::InvalidInput, e.to_string()))?;

Arc::new(LightClient::new(da, celestia_config, Some(prover_vk)))
let client = ProverClient::mock();
let (_, vk) = client.setup(PRISM_ELF);

Arc::new(LightClient::new(
da,
celestia_config,
Some(prover_vk),
vk.bytes32(),
))
}
Commands::Prover(args) => {
let config = load_config(args.clone())
Expand Down Expand Up @@ -79,7 +89,12 @@ async fn main() -> std::io::Result<()> {
verifying_key_algorithm,
signing_key_chain.as_bytes(),
)
.map_err(|e| Error::new(ErrorKind::InvalidInput, format!("Invalid signing key: {}", e)))?;
.map_err(|e| {
Error::new(
ErrorKind::InvalidInput,
format!("Invalid signing key: {}", e),
)
})?;
let verifying_key = signing_key.verifying_key();

let prover_cfg = prism_prover::Config {
Expand Down Expand Up @@ -130,7 +145,12 @@ async fn main() -> std::io::Result<()> {
verifying_key_algorithm,
signing_key_chain.as_bytes(),
)
.map_err(|e| Error::new(ErrorKind::InvalidInput, format!("Invalid signing key: {}", e)))?;
.map_err(|e| {
Error::new(
ErrorKind::InvalidInput,
format!("Invalid signing key: {}", e),
)
})?;

let prover_vk = config
.verifying_key
Expand Down
2 changes: 1 addition & 1 deletion crates/node_types/lightclient/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ prism-common = { workspace = true, features = ["test_utils"] }
prism-errors = { workspace = true }
prism-da = { workspace = true }
prism-keys = { workspace = true }
sp1-sdk = { workspace = true }
sp1-verifier = { workspace = true }
73 changes: 48 additions & 25 deletions crates/node_types/lightclient/src/lightclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ use prism_common::digest::Digest;
use prism_da::{celestia::CelestiaConfig, DataAvailabilityLayer};
use prism_errors::{DataAvailabilityError, GeneralError};
use prism_keys::VerifyingKey;
use sp1_sdk::{ProverClient, SP1VerifyingKey};
use std::{self, sync::Arc};
use tokio::{sync::broadcast, task::spawn};

pub const PRISM_ELF: &[u8] = include_bytes!("../../../../elf/riscv32im-succinct-zkvm-elf");
#[allow(unused_imports)]
use sp1_verifier::Groth16Verifier;

#[allow(dead_code)]
pub struct LightClient {
pub da: Arc<dyn DataAvailabilityLayer>,
/// The public key of the prover, used for verifying the signature of the epochs.
pub prover_pubkey: Option<VerifyingKey>,
pub client: ProverClient,
pub verifying_key: SP1VerifyingKey,
/// The verification key for the SP1 program, generated by `vk.bytes32()`.
pub sp1_vkey: String,
/// The height to start syncing from.
pub start_height: u64,
}

Expand All @@ -24,17 +26,11 @@ impl LightClient {
da: Arc<dyn DataAvailabilityLayer>,
cfg: CelestiaConfig,
prover_pubkey: Option<VerifyingKey>,
sp1_vkey: String,
) -> LightClient {
#[cfg(feature = "mock_prover")]
let client = ProverClient::mock();
#[cfg(not(feature = "mock_prover"))]
let client = ProverClient::local();
let (_, verifying_key) = client.setup(PRISM_ELF);

LightClient {
da,
verifying_key,
client,
sp1_vkey,
prover_pubkey,
start_height: cfg.start_height,
}
Expand Down Expand Up @@ -73,18 +69,31 @@ impl LightClient {
// TODO: Issue #144
if let Some(pubkey) = &self.prover_pubkey {
match finalized_epoch.verify_signature(pubkey.clone()) {
Ok(_) => trace!("valid signature for epoch {}", finalized_epoch.height),
Err(e) => panic!("invalid signature in epoch {}: {:?}", i, e),
Ok(_) => trace!(
"valid signature for epoch {}",
finalized_epoch.height
),
Err(e) => {
panic!("invalid signature in epoch {}: {:?}", i, e)
}
}
}

// Commitment verification
let prev_commitment = &finalized_epoch.prev_commitment;
let current_commitment = &finalized_epoch.current_commitment;
let mut public_values = finalized_epoch.proof.public_values.clone();
let proof_prev_commitment: Digest = public_values.read();
let proof_current_commitment: Digest = public_values.read();
let public_values = finalized_epoch.proof.public_values.clone();

if public_values.as_slice().len() < 64 {
panic!("public_values length is less than 64 bytes in epoch {}", finalized_epoch.height);
}

let mut slice = [0u8; 32];
slice.copy_from_slice(&public_values.as_slice()[..32]);
let proof_prev_commitment: Digest = Digest::from(slice);
let mut slice = [0u8; 32];
slice.copy_from_slice(&public_values.to_vec()[32..64]);
let proof_current_commitment: Digest = Digest::from(slice);
if prev_commitment != &proof_prev_commitment
|| current_commitment != &proof_current_commitment
{
Expand All @@ -99,26 +108,40 @@ impl LightClient {
}

// SNARK verification
match self.client.verify(&finalized_epoch.proof, &self.verifying_key) {
Ok(_) => info!("zkSNARK for epoch {} was validated successfully", finalized_epoch.height),
Err(err) => panic!("failed to validate epoch at height {}: {:?}", finalized_epoch.height, err),
#[cfg(feature = "mock_prover")]
info!("mock_prover is activated, skipping proof verification");
#[cfg(not(feature = "mock_prover"))]
match Groth16Verifier::verify(
&finalized_epoch.proof.bytes(),
public_values.as_slice(),
&self.sp1_vkey,
&sp1_verifier::GROTH16_VK_BYTES,
) {
Ok(_) => info!(
"zkSNARK for epoch {} was validated successfully",
finalized_epoch.height
),
Err(err) => panic!(
"failed to validate epoch at height {}: {:?}",
finalized_epoch.height, err
),
}
},
}
Ok(None) => {
debug!("no finalized epoch found at height: {}", i + 1);
},
}
Err(e) => debug!("light client: getting epoch: {}", e),
};
}
current_position = target;
},
}
Err(broadcast::error::RecvError::Closed) => {
error!("Height channel closed unexpectedly");
break;
},
}
Err(broadcast::error::RecvError::Lagged(skipped)) => {
warn!("Lagged behind by {} messages", skipped);
},
}
}
}
})
Expand Down
3 changes: 2 additions & 1 deletion crates/tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ prism-common = { workspace = true, features = ["test_utils"] }
prism-storage.workspace = true
prism-prover = { workspace = true, features = ["mock_prover"] }
prism-keys = { workspace = true }
prism-lightclient.workspace = true
prism-lightclient = { workspace = true, features = ["mock_prover"] }
sp1-sdk.workspace = true
prism-da.workspace = true
rand.workspace = true
tokio.workspace = true
Expand Down
14 changes: 13 additions & 1 deletion crates/tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ use prism_lightclient::LightClient;
use prism_prover::Prover;
use prism_storage::{rocksdb::RocksDBConnection, Database};
use rand::{rngs::StdRng, Rng, SeedableRng};
use sp1_sdk::{HashableKey, ProverClient};
use std::sync::Arc;
use tokio::{spawn, time::Duration};

use tempfile::TempDir;

pub const PRISM_ELF: &[u8] = include_bytes!("../../../elf/riscv32im-succinct-zkvm-elf");

fn setup_db() -> Arc<Box<dyn Database>> {
let temp_dir = TempDir::new().unwrap();
let db = RocksDBConnection::new(temp_dir.path().to_str().unwrap()).unwrap();
Expand All @@ -33,6 +36,10 @@ async fn test_light_client_prover_talking() -> Result<()> {
);
pretty_env_logger::init();

let prover_client = ProverClient::mock();

let (_, vk) = prover_client.setup(PRISM_ELF);

let bridge_cfg = CelestiaConfig {
connection_string: "ws://localhost:26658".to_string(),
..CelestiaConfig::default()
Expand Down Expand Up @@ -64,7 +71,12 @@ async fn test_light_client_prover_talking() -> Result<()> {
&prover_cfg,
)?);

let lightclient = Arc::new(LightClient::new(lc_da_layer.clone(), lc_cfg, Some(pubkey)));
let lightclient = Arc::new(LightClient::new(
lc_da_layer.clone(),
lc_cfg,
Some(pubkey),
vk.bytes32(),
));

let prover_clone = prover.clone();
spawn(async move {
Expand Down
Binary file modified elf/riscv32im-succinct-zkvm-elf
Binary file not shown.

0 comments on commit 3e7ba32

Please sign in to comment.