Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 70 additions & 4 deletions crates/boundless-market/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use crate::{
StorageProviderConfig,
},
util::NotProvided,
GuestEnv,
};

/// Builder for the [Client] with standard implementations for the required components.
Expand Down Expand Up @@ -631,8 +632,73 @@ where
.context("Failed to upload program")?)
}

/// Upload input to the storage provider.
pub async fn upload_input(&self, input: &[u8]) -> Result<Url, ClientError>
/// Upload program input to the storage provider.
///
/// Boundless uses a structured input format for guest programs, defined by the [GuestEnv] struct.
///
/// ```rust
/// # use boundless_market::client::Client;
/// # use boundless_market::GuestEnv;
/// # |client: Client| {
/// let input_bytes = b"Hello, world!";
/// let guest_env = GuestEnv::from_stdin(input_bytes);
/// client.upload_input(&guest_env);
/// # };
/// ```
pub async fn upload_input(&self, guest_env: &GuestEnv) -> Result<Url, ClientError>
where
St: StorageProvider,
{
let input = guest_env.encode().context("Failed to encode guest env")?;
Ok(self
.storage_provider
.as_ref()
.context("Storage provider not set")?
.upload_input(&input)
.await
.map_err(|_| anyhow!("Failed to upload input"))?)
}

/// Upload program input, with stdin set to the provided bytes array, to the storage provider.
///
/// Boundless uses a structured input format for guest programs, defined by the [GuestEnv] struct.
///
/// This method is a convenience method that creates a [GuestEnv] struct, where the provided bytes
/// are set as the stdin, and uploads it to the storage provider.
///
/// ```rust
/// # use boundless_market::client::Client;
/// # use boundless_market::GuestEnv;
/// # |client: Client, stdin_bytes: &[u8]| {
/// client.upload_input_stdin(stdin_bytes);
/// # };
/// ```
pub async fn upload_input_stdin(&self, stdin_bytes: &[u8]) -> Result<Url, ClientError>
where
St: StorageProvider,
{
let guest_env = GuestEnv::from_stdin(stdin_bytes);
self.upload_input(&guest_env).await
}

/// Upload program input as the provided bytes array, to the storage provider.
///
/// The bytes array _must_ be encoded using the scheme defined in [GuestEnv] in
/// order for the input to be used on Boundless.
///
/// Note: Typically, you will want to use [`Self::upload_input`] or [`Self::upload_input_stdin`], which
/// handle encoding inputs into the structured format that is expected by Boundless provers.
///
/// Note:
///
/// ```rust
/// # use boundless_market::client::Client;
/// # use boundless_market::GuestEnv;
/// # |client: Client, input_bytes: &[u8]| {
/// client.upload_input_bytes(input_bytes);
/// # };
/// ```
pub async fn upload_input_bytes(&self, input_bytes: &[u8]) -> Result<Url, ClientError>
where
St: StorageProvider,
<St as StorageProvider>::Error: std::error::Error + Send + Sync + 'static,
Expand All @@ -641,12 +707,12 @@ where
.storage_provider
.as_ref()
.context("Storage provider not set")?
.upload_input(input)
.upload_input(input_bytes)
.await
.context("Failed to upload input")?)
}

/// Initial parameters that will be used to build a [ProofRequest] using the [RequestBuilder].
/// Create a new request builder.
pub fn new_request<Params>(&self) -> Params
where
R: RequestBuilder<Params>,
Expand Down
7 changes: 5 additions & 2 deletions documentation/site/pages/developers/tooling/sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ let client = Client::builder()

<StripRustCodeComments>
```rust
# use std::time::SystemTime;
# use boundless_market::{Client, storage::storage_provider_from_env};
# use alloy::signers::local::LocalSigner;
# use std::borrow::Cow;
# use url::Url;
# async fn upload_program_and_input(rpc_url: Url) -> anyhow::Result<()> {
# let client = Client::builder()
Expand All @@ -54,8 +56,9 @@ let client = Client::builder()
# .with_storage_provider(Some(storage_provider_from_env()?))
# .build()
# .await?;
let program_url = client.upload_program(&std::fs::read("guest.bin")?).await?;
let input_url = client.upload_input(&[0x41, 0x42, 0x43]).await?;
let input = format!("{:?}", SystemTime::now());
let program: Cow<'static, [u8]> = std::fs::read("guest.bin")?.into();
let request = client.new_request().with_program(program).with_stdin(input.as_bytes());
# Ok(())
# }
```
Expand Down
4 changes: 2 additions & 2 deletions documentation/site/pages/developers/tutorials/request.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,12 @@ Program inputs are uploaded to the same storage provider. This can be done manua
<StripRustCodeComments>
```rust
# use boundless_market::{Client, storage::storage_provider_from_env};
# async fn upload_input(input_bytes: Vec<u8>) -> Result<(), Box<dyn std::error::Error>> {
# async fn upload_input_bytes(input_bytes: Vec<u8>) -> Result<(), Box<dyn std::error::Error>> {
# let client = Client::builder()
# .with_storage_provider(Some(storage_provider_from_env()?))
# .build()
# .await?;
let input_url = client.upload_input(&input_bytes).await?;
let input_url = client.upload_input_bytes(&input_bytes).await?;
# Ok(())
# }
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ First we execute the guest program locally with our expected input, to generate
let input = days_since_epoch.to_be_bytes();
let guest_env = GuestEnv::from_stdin(input);
let input_url = client
.upload_input(&guest_env.encode()?)
.upload_input(&guest_env)
.await
.context("failed to upload input")?;

Expand Down
Loading