Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backporting commits for upcoming 0.19.1 #1099

Merged
merged 3 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: cargo test -F $FEATURE -F profiler --workspace --exclude doc-test
- run: cargo test -p risc0-r0vm -F $FEATURE -F disable-dev-mode
- run: cargo test -p risc0-zkvm -F $FEATURE -F fault-proof -F prove -- tests::memory_io tests::memory_access
if: matrix.device == 'cpu'
- run: cargo test -p risc0-zkvm -F $FEATURE -F fault-proof -F prove
- run: cargo test -p cargo-risczero -F experimental
if: matrix.device == 'cpu'
- run: cargo check -F $FEATURE --benches
Expand Down
130 changes: 119 additions & 11 deletions bonsai/sdk/src/alpha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use reqwest::{blocking::Client as BlockingClient, header};
use thiserror::Error;

use self::responses::{
CreateSessRes, ImgUploadRes, ProofReq, SessionStatusRes, SnarkReq, SnarkStatusRes, UploadRes,
VersionInfo,
CreateSessRes, ImgUploadRes, ProofReq, Quotas, SessionStatusRes, SnarkReq, SnarkStatusRes,
UploadRes, VersionInfo,
};
use crate::{API_KEY_HEADER, VERSION_HEADER};
use crate::{API_KEY_ENVVAR, API_KEY_HEADER, API_URL_ENVVAR, VERSION_HEADER};

/// Bonsai Alpha SDK error classes
#[derive(Debug, Error)]
Expand Down Expand Up @@ -178,6 +178,21 @@ pub mod responses {
/// Supported versions of the risc0-zkvm crate
pub risc0_zkvm: Vec<String>,
}

/// User quotas and cycle budgets
#[derive(Deserialize, Serialize)]
pub struct Quotas {
/// Executor cycle limit, in millions of cycles
pub exec_cycle_limit: u64,
/// Max parallel proving units
pub max_parallelism: u64,
/// Max concurrent proofs
pub concurrent_proofs: u64,
/// Current cycle budget remaining
pub cycle_budget: u64,
/// Lifetime cycles used
pub cycle_usage: u64,
}
}

/// Proof Session representation
Expand All @@ -204,6 +219,25 @@ impl SessionId {
}
Ok(res.json::<SessionStatusRes>()?)
}

/// Fetches the zkvm guest logs for a session
///
/// After the Execution phase of proving is completed, you can use this method
/// to download the logs of the zkvm guest. This is a merged log of stderr and stdout
/// <https://docs.rs/risc0-zkvm/latest/risc0_zkvm/struct.ExecutorEnvBuilder.html#method.stdout>
///
/// It should contain the output of all writes to those file descriptors. But does NOT include output
/// from `env::log`
pub fn logs(&self, client: &Client) -> Result<String, SdkErr> {
let url = format!("{}/sessions/logs/{}", client.url, self.uuid);
let res = client.client.get(url).send()?;

if !res.status().is_success() {
let body = res.text()?;
return Err(SdkErr::InternalServerErr(body));
}
Ok(res.text()?)
}
}

/// Stark2Snark Session representation
Expand Down Expand Up @@ -271,9 +305,9 @@ impl Client {
/// .expect("Failed to construct sdk client");
/// ```
pub fn from_env(risc0_version: &str) -> Result<Self, SdkErr> {
let api_url = std::env::var("BONSAI_API_URL").map_err(|_| SdkErr::MissingApiUrl)?;
let api_url = std::env::var(API_URL_ENVVAR).map_err(|_| SdkErr::MissingApiUrl)?;
let api_url = api_url.strip_suffix('/').unwrap_or(&api_url);
let api_key = std::env::var("BONSAI_API_KEY").map_err(|_| SdkErr::MissingApiKey)?;
let api_key = std::env::var(API_KEY_ENVVAR).map_err(|_| SdkErr::MissingApiKey)?;

let client = construct_req_client(&api_key, risc0_version)?;

Expand Down Expand Up @@ -476,6 +510,19 @@ impl Client {
.send()?
.json::<VersionInfo>()?)
}

// - /user

/// Fetches your current users quotas
///
/// Returns the [Quotas] structure with relevant data on cycle budget, quotas etc.
pub fn quotas(&self) -> Result<Quotas, SdkErr> {
Ok(self
.client
.get(format!("{}/user/quotas", self.url))
.send()?
.json::<Quotas>()?)
}
}

#[cfg(test)]
Expand Down Expand Up @@ -504,8 +551,8 @@ mod tests {
let apikey = TEST_KEY.to_string();
temp_env::with_vars(
vec![
("BONSAI_API_URL", Some(url.clone())),
("BONSAI_API_KEY", Some(apikey)),
(API_URL_ENVVAR, Some(url.clone())),
(API_KEY_ENVVAR, Some(apikey)),
],
|| {
let client = super::Client::from_env(TEST_VERSION).unwrap();
Expand All @@ -519,10 +566,7 @@ mod tests {
let url = "http://127.0.0.1/".to_string();
let apikey = TEST_KEY.to_string();
temp_env::with_vars(
vec![
("BONSAI_API_URL", Some(url)),
("BONSAI_API_KEY", Some(apikey)),
],
vec![(API_URL_ENVVAR, Some(url)), (API_KEY_ENVVAR, Some(apikey))],
|| {
let client = super::Client::from_env(TEST_VERSION).unwrap();
assert_eq!(client.url, "http://127.0.0.1");
Expand Down Expand Up @@ -702,6 +746,35 @@ mod tests {
create_mock.assert();
}

#[test]
fn session_logs() {
let server = MockServer::start();

let uuid = Uuid::new_v4().to_string();
let session_id = SessionId::new(uuid);
let response = "Hello\nWorld";

let create_mock = server.mock(|when, then| {
when.method(GET)
.path(format!("/sessions/logs/{}", session_id.uuid))
.header(API_KEY_HEADER, TEST_KEY)
.header(VERSION_HEADER, TEST_VERSION);
then.status(200)
.header("content-type", "text/plain")
.json_body_obj(&response);
});

let server_url = format!("http://{}", server.address());
let client =
super::Client::from_parts(server_url, TEST_KEY.to_string(), TEST_VERSION).unwrap();

let logs = session_id.logs(&client).unwrap();

assert_eq!(logs, "\"Hello\\nWorld\"");

create_mock.assert();
}

#[test]
fn snark_create() {
let server = MockServer::start();
Expand Down Expand Up @@ -793,4 +866,39 @@ mod tests {
assert_eq!(&info.risc0_zkvm[0], TEST_VERSION);
get_mock.assert();
}

#[test]
fn quotas() {
let server = MockServer::start();

let response = Quotas {
concurrent_proofs: 10,
cycle_budget: 100000,
cycle_usage: 1000000,
exec_cycle_limit: 500,
max_parallelism: 2,
};

let get_mock = server.mock(|when, then| {
when.method(GET)
.path("/user/quotas")
.header(API_KEY_HEADER, TEST_KEY)
.header(VERSION_HEADER, TEST_VERSION);
then.status(200)
.header("content-type", "application/json")
.json_body_obj(&response);
});

let server_url = format!("http://{}", server.address());
let client = super::Client::from_parts(server_url, TEST_KEY.to_string(), TEST_VERSION)
.expect("Failed to construct client");
let quota = client.quotas().expect("Failed to fetch version route");
assert_eq!(quota.concurrent_proofs, response.concurrent_proofs);
assert_eq!(quota.cycle_budget, response.cycle_budget);
assert_eq!(quota.cycle_usage, response.cycle_usage);
assert_eq!(quota.exec_cycle_limit, response.exec_cycle_limit);
assert_eq!(quota.max_parallelism, response.max_parallelism);

get_mock.assert();
}
}
25 changes: 24 additions & 1 deletion bonsai/sdk/src/alpha_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

use crate::alpha::{
responses::{SessionStatusRes, SnarkStatusRes},
responses::{Quotas, SessionStatusRes, SnarkStatusRes},
Client, SdkErr, SessionId, SnarkId,
};

Expand Down Expand Up @@ -86,6 +86,20 @@ pub async fn session_status(
.map_err(|err| SdkErr::InternalServerErr(format!("{err}")))?
}

/// Fetches the zkvm guest logs for a session
///
/// After the Execution phase of proving is completed, you can use this method
/// to download the logs of the zkvm guest. This is a merged log of stderr and stdout
/// <https://docs.rs/risc0-zkvm/latest/risc0_zkvm/struct.ExecutorEnvBuilder.html#method.stdout>
///
/// It should contain the output of all writes to those file descriptors. But does NOT include output
/// from `env::log`
pub async fn session_logs(bonsai_client: Client, session: SessionId) -> Result<String, SdkErr> {
tokio::task::spawn_blocking(move || session.logs(&bonsai_client))
.await
.map_err(|err| SdkErr::InternalServerErr(format!("{err}")))?
}

/// Requests a SNARK proof be created from a existing sessionId
///
/// Supply a completed sessionId to convert the risc0 STARK proof into
Expand All @@ -111,3 +125,12 @@ pub async fn download(bonsai_client: Client, url: String) -> Result<Vec<u8>, Sdk
.await
.map_err(|err| SdkErr::InternalServerErr(format!("{err}")))?
}

/// Fetches your current users quotas
///
/// Returns the [Quotas] structure with relevant data on cycle budget, quotas etc.
pub async fn quotas(bonsai_client: Client) -> Result<Quotas, SdkErr> {
tokio::task::spawn_blocking(move || bonsai_client.quotas())
.await
.map_err(|err| SdkErr::InternalServerErr(format!("{err}")))?
}
4 changes: 4 additions & 0 deletions bonsai/sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ pub mod alpha_async;
pub const API_KEY_HEADER: &str = "x-api-key";
/// HTTP header for the risc0 version string
pub const VERSION_HEADER: &str = "x-risc0-version";
/// Environment variable name for the API url
pub const API_URL_ENVVAR: &str = "BONSAI_API_URL";
/// Environment variable name for the API key
pub const API_KEY_ENVVAR: &str = "BONSAI_API_KEY";
2 changes: 1 addition & 1 deletion risc0/build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ fn detect_toolchain(name: &str) {
eprintln!("The 'risc0' toolchain could not be found.");
eprintln!("To install the risc0 toolchain, use cargo-risczero.");
eprintln!("For example:");
eprintln!(" cargo install cargo-risczero");
eprintln!(" cargo binstall cargo-risczero");
eprintln!(" cargo risczero install");
std::process::exit(-1);
}
Expand Down
3 changes: 2 additions & 1 deletion risc0/zkvm/src/guest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
//! [`cargo-risczero`](https://crates.io/crates/cargo-risczero) tool:
//!
//! ```sh
//! cargo install cargo-risczero
//! cargo install cargo-binstall
//! cargo binstall cargo-risczero
//! cargo risczero install
//! ```
//!
Expand Down