diff --git a/crates/boundless-market/src/client.rs b/crates/boundless-market/src/client.rs index a719509cb..ad9e24359 100644 --- a/crates/boundless-market/src/client.rs +++ b/crates/boundless-market/src/client.rs @@ -50,6 +50,7 @@ use crate::{ StorageProviderConfig, }, util::NotProvided, + GuestEnv, }; /// Builder for the [Client] with standard implementations for the required components. @@ -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 + /// 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 + 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 + 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 where St: StorageProvider, ::Error: std::error::Error + Send + Sync + 'static, @@ -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(&self) -> Params where R: RequestBuilder, diff --git a/documentation/site/pages/developers/tooling/sdk.mdx b/documentation/site/pages/developers/tooling/sdk.mdx index 690e9b67c..d33c8924a 100644 --- a/documentation/site/pages/developers/tooling/sdk.mdx +++ b/documentation/site/pages/developers/tooling/sdk.mdx @@ -44,8 +44,10 @@ let client = Client::builder() ```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() @@ -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(()) # } ``` diff --git a/documentation/site/pages/developers/tutorials/request.mdx b/documentation/site/pages/developers/tutorials/request.mdx index 2d10cc3e9..4c060e88b 100644 --- a/documentation/site/pages/developers/tutorials/request.mdx +++ b/documentation/site/pages/developers/tutorials/request.mdx @@ -287,12 +287,12 @@ Program inputs are uploaded to the same storage provider. This can be done manua ```rust # use boundless_market::{Client, storage::storage_provider_from_env}; -# async fn upload_input(input_bytes: Vec) -> Result<(), Box> { +# async fn upload_input_bytes(input_bytes: Vec) -> Result<(), Box> { # 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(()) # } ``` diff --git a/documentation/site/pages/developers/tutorials/smart-contract-requestor.mdx b/documentation/site/pages/developers/tutorials/smart-contract-requestor.mdx index a05816783..21871179b 100644 --- a/documentation/site/pages/developers/tutorials/smart-contract-requestor.mdx +++ b/documentation/site/pages/developers/tutorials/smart-contract-requestor.mdx @@ -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")?;