Skip to content

Commit

Permalink
feat: versioned execution
Browse files Browse the repository at this point in the history
  • Loading branch information
jac18281828 committed Oct 31, 2024
1 parent 0bae4fc commit 4d9d976
Show file tree
Hide file tree
Showing 20 changed files with 255 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ NodeDragon.toml
images/**/manifest.json
stark
*_generated.rs
.pnpm-store
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ risc0-circuit-recursion = { git = "https://github.com/anagrambuild/risc0", branc
risc0-sys = { git = "https:m//github.com/anagrambuild/risc0", branch = "v1.0.1-bonsai-fix" }
tokio-test = "0.4.3"

bonsol-interface = { path = "./onchain/interface" }
bonsol-schema = { path = "./schemas-rust" }

[workspace.lints.clippy]
clone_on_ref_ptr = "deny"
missing_const_for_fn = "deny"
Expand Down
2 changes: 2 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ solana-rpc-client = { workspace = true }
solana-sdk = { workspace = true }
tera = "1.17.1"
tokio = { version = "1.38.0", features = ["full"] }

bonsol-interface.workspace = true
4 changes: 3 additions & 1 deletion cli/src/execute.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::common::*;
use anyhow::Result;
use bonsol_interface::prover_version::ProverVersion;
use bonsol_prover::input_resolver::{DefaultInputResolver, InputResolver, ProgramInput};
use bonsol_sdk::instructions::CallbackConfig;
use bonsol_sdk::{BonsolClient, ExecutionAccountStatus, InputType};
use indicatif::ProgressBar;
use sha2::{Digest, Sha256};
Expand Down Expand Up @@ -151,6 +151,7 @@ pub async fn execute(
println!("Execution expiry {}", expiry);
println!("current block {}", current_block);
indicator.set_message("Building transaction");
let prover_version = ProverVersion::default();
let ixs = sdk
.execute_v1(
&signer,
Expand All @@ -161,6 +162,7 @@ pub async fn execute(
expiry,
execution_config,
callback_config.map(|c| c.into()),
Some(prover_version),
)
.await?;
indicator.finish_with_message("Sending transaction");
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/contributing/contributing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ cargo run -p bonsol-cli build -z images/simple
```
5. Use the bonsol cli to deploy a zkprogram (here is a example already uploaded for you)
```bash
cargo run -p bonsol-cli deploy -m images/simple/manifest.json -t url --url https://bonsol-public-images.s3.amazonaws.com/simple-68f4b0c5f9ce034aa60ceb264a18d6c410a3af68fafd931bcfd9ebe7c1e42960
cargo run -p bonsol-cli deploy -m images/simple/manifest.json -t url --url https://bonsol-public-images.s3.us-east-1.amazonaws.com/simple-058530737d1b86e43ed2529f114b85195c27290fcf0844623b1ccb14934e8218
```
6. Use the bonsol cli to execute a zkprogram
```bash
Expand Down
3 changes: 2 additions & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ ark-relations = { version = "0.4.0" }
ark-serialize = "0.4.0"
ark-std = { version = "0.4.0" }
async-trait = "0.1.80"
bonsol-interface = { path = "../onchain/interface" }
bonsol-prover = { path = "../prover" }
bytemuck = "1.15.0"
byteorder = "1.5.0"
Expand Down Expand Up @@ -81,6 +80,8 @@ tracing-subscriber = { version = "0.3.18", features = [
yellowstone-grpc-client = { workspace = true }
yellowstone-grpc-proto = { workspace = true }

bonsol-interface.workspace = true

[dev-dependencies]
expect-test = "1.5.0"

Expand Down
2 changes: 1 addition & 1 deletion node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use {
rlimit::Resource,
solana_rpc_client::nonblocking::rpc_client::RpcClient,
solana_sdk::{pubkey::Pubkey, signature::read_keypair_file, signer::Signer},
std::{path::Path, str::FromStr, sync::Arc},
std::{str::FromStr, sync::Arc},
thiserror::Error,
tokio::{select, signal},
tracing::{error, info},
Expand Down
1 change: 1 addition & 0 deletions node/src/observe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub enum MetricEvents {
ProofSegments,
BonsolStartup,
SignaturesInFlight,
IncompatibleProverVersion,
}

macro_rules! emit_event {
Expand Down
40 changes: 36 additions & 4 deletions node/src/prover/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
mod utils;
pub mod verify_prover_version;

use {solana_sdk::instruction::AccountMeta, utils::check_stark_compression_tools_path};

use {
Expand All @@ -9,9 +11,11 @@ use {
prover::utils::async_to_json,
MissingImageStrategy,
},
bonsol_interface::bonsol_schema::{ClaimV1, DeployV1, ExecutionRequestV1, ProgramInputType},
bonsol_interface::{
bonsol_schema::{ClaimV1, DeployV1, ExecutionRequestV1},
prover_version::{ProverVersion, VERSION_V1_0_1},
},
dashmap::DashMap,
reqwest::Url,
risc0_binfmt::MemoryImage,
risc0_zkvm::{ExitCode, Journal, SuccinctReceipt},
solana_sdk::{pubkey::Pubkey, signature::Signature},
Expand All @@ -28,7 +32,7 @@ use {

use {
crate::types::{BonsolInstruction, ProgramExec},
anyhow::{anyhow, Result},
anyhow::Result,
bonsol_interface::bonsol_schema::{parse_ix_data, root_as_deploy_v1, ChannelInstructionIxType},
bonsol_prover::{
image::Image,
Expand All @@ -47,9 +51,13 @@ use {
tokio::{
fs::File, io::AsyncReadExt, process::Command, sync::mpsc::UnboundedSender, task::JoinHandle,
},
tracing::{error, info},
tracing::{error, info, warn},
};

use verify_prover_version::verify_prover_version;

const REQUIRED_PROVER: ProverVersion = VERSION_V1_0_1;

#[derive(Debug, Error)]
pub enum Risc0RunnerError {
#[error("Empty instruction")]
Expand Down Expand Up @@ -144,6 +152,8 @@ impl Risc0Runner {
// Break into Image handling, Input handling, Execution Request
// Inputs and Image should be service used by this prover.
pub fn start(&mut self) -> Result<UnboundedSender<BonsolInstruction>> {
verify_prover_version(REQUIRED_PROVER)
.expect("Bonsol build conflict: prover version is not supported");
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<BonsolInstruction>();
let loaded_images = self.loaded_images.clone();
// TODO: move image handling out of prover
Expand Down Expand Up @@ -403,6 +413,15 @@ async fn handle_execution_request<'a>(
exec: ExecutionRequestV1<'a>,
accounts: &[Pubkey],
) -> Result<()> {
if !can_execute(exec) {
warn!(
"Execution request for incompatible prover version: {:?}",
exec.prover_version()
);
emit_event!(MetricEvents::IncompatibleProverVersion, execution_id => exec.execution_id().unwrap_or_default());
return Ok(());
}

// current naive implementation is to accept everything we have pending capacity for on this node, but this needs work
let inflight = in_flight_proofs.len();
emit_event!(MetricEvents::ExecutionRequest, execution_id => exec.execution_id().unwrap_or_default());
Expand Down Expand Up @@ -686,3 +705,16 @@ async fn risc0_compress_proof(
Err(Risc0RunnerError::ProofCompressionError.into())
}
}

fn can_execute(exec: ExecutionRequestV1) -> bool {
let version = exec.prover_version().try_into();
if version.is_ok() {
let is_matching = match version.unwrap() {
REQUIRED_PROVER => true,
_ => false,
};
is_matching
} else {
false
}
}
54 changes: 54 additions & 0 deletions node/src/prover/verify_prover_version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use {anyhow::Result, tracing::info};

use risc0_zkvm::{sha::Digestible, Groth16ReceiptVerifierParameters};

use bonsol_interface::prover_version::ProverVersion;

pub fn verify_prover_version(required: ProverVersion) -> Result<()> {
let actual_digest = Groth16ReceiptVerifierParameters::default().digest();
let prover_digest = actual_digest.to_string();

match required {
ProverVersion::V1_0_1 {
verifier_digest, ..
} => {
if verifier_digest != prover_digest {
return Err(anyhow::anyhow!(
"Prover version mismatch, expected: {}, got: {}",
verifier_digest,
prover_digest
));
}
info!("Risc0 Prover with digest {}", verifier_digest);
}
_ => {
return Err(anyhow::anyhow!("Unsupported prover version"));
}
}
Ok(())
}

#[cfg(test)]
mod tests {
use {super::*, bonsol_interface::prover_version::VERSION_V1_0_1};

#[test]
fn test_verify_prover_version() {
assert!(verify_prover_version(VERSION_V1_0_1).is_ok());
}

#[test]
fn test_verify_prover_version_fail() {
let version_malade = ProverVersion::V1_0_1 {
verifier_digest: "malade",
};
let result = verify_prover_version(version_malade);
assert!(result.is_err());
}

#[test]
fn test_verify_default_prover_version_is_supported() {
let result = verify_prover_version(ProverVersion::default());
assert!(result.is_ok());
}
}
3 changes: 2 additions & 1 deletion onchain/interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ idl-build = ["anchor-lang/idl-build"]
[dependencies]
arrayref = "0.3.6"
base64 = "0.21.2"
bonsol-schema = { path = "../../schemas-rust", version = "0.2.1" }
bytemuck = { version = "1.15.0", features = ["derive"] }
flatbuffers = { workspace = true }
hex = "0.4.3"
Expand All @@ -24,6 +23,8 @@ solana-program = { workspace = true, optional = true }
solana-sdk = { workspace = true, optional = true }
thiserror = { workspace = true }

bonsol-schema.workspace = true

[dependencies.anchor-lang]
optional = true
version = ">=0.28"
Expand Down
10 changes: 8 additions & 2 deletions onchain/interface/src/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bonsol_schema::{
Account, ChannelInstruction, ChannelInstructionArgs, ChannelInstructionIxType, DeployV1,
DeployV1Args, ExecutionRequestV1, ExecutionRequestV1Args, ExecutionRequestV1T, InputBuilder,
InputT, InputType, ProgramInputType,
DeployV1Args, ExecutionRequestV1, ExecutionRequestV1Args, InputBuilder, InputT, InputType,
ProgramInputType, ProverVersion,
};
use flatbuffers::{FlatBufferBuilder, WIPOffset};

Expand Down Expand Up @@ -209,6 +209,7 @@ pub fn execute_v1(
expiration: u64,
config: ExecutionConfig,
callback: Option<CallbackConfig>,
prover_version: Option<ProverVersion>,
) -> Result<Instruction, ClientError> {
config.validate()?;
let (execution_account, _) = execution_address(signer, execution_id.as_bytes());
Expand Down Expand Up @@ -279,6 +280,10 @@ pub fn execute_v1(
} else {
None
};

let prover_version = prover_version.or(Some(ProverVersion::default()));
let prover_version = prover_version.unwrap();

let fbb_execute = ExecutionRequestV1::create(
&mut fbb,
&ExecutionRequestV1Args {
Expand All @@ -293,6 +298,7 @@ pub fn execute_v1(
max_block_height: expiration,
input_digest,
callback_extra_accounts: extra_accounts,
prover_version,
},
);
fbb.finish(fbb_execute, None);
Expand Down
1 change: 1 addition & 0 deletions onchain/interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod callback;
pub mod claim_state;
pub mod error;
pub mod instructions;
pub mod prover_version;
pub mod util;

pub use bonsol_schema;
Expand Down
Loading

0 comments on commit 4d9d976

Please sign in to comment.