Bonsai on Ethereum
Warning: Bonsai is still in early development. Do not use in production.
Bonsai can be used as a zk coprocessor for Ethereum, allowing you to request verified proofs via an off-chain REST API interface or on-chain directly from your smart contract.
At a high level, here's how it works:
- Users can delegate their smart contract's logic to Bonsai via a
Request Callback
interface. This interface is accessible both off-chain through the HTTP REST API of theBonsai Relayer
and on-chain via the Bonsai Relay Contract. - The
Bonsai Relayer
sends the proof request to Bonsai. - Bonsai generates a Groth16 SNARK proof and its result, encapsulated in a journal.
- The
Bonsai Relayer
submits this proof and journal on-chain to the Bonsai Relay Contract for validation. - If validated, the journal is dispatched to the user's smart contract via the specified callback.
To integrate your application with Bonsai, you'll need to:
- Write the program you want proven and upload it to Bonsai
- Write the on-chain part of your application and deploy it
Interfaces
The Bonsai Ethereum Relay provides both an off-chain (vie the HTTP REST API of the Bonsai Relayer
) and an on-chain (via the Bonsai Relay Contract) interface to send Callback requests
.
Off-chain
A typical flow works as follows:
- Deploy the
Bonsai Relay Contract
to Ethereum using address0xB..
. - Launch the
Bonsai Relayer
, setting--contract-address
to0xB..
. - To delegate off-chain computation for a new Smart Contract
A
to Bonsai, register itsImage
orELF
(the binary executing the computation on RISC Zero ZKVM) with Bonsai. - Use the generated
Image ID
and theBonsai Relay Contract
address 0xB.. to deploy Smart ContractA
on Ethereum. - Initiate a
Callback request
through theBonsai Relayer
's off-chain REST API. This request is sent to Bonsai. - After Bonsai produces an execution proof, the
Bonsai Relayer
relays the proof and computation result to theBonsai Relay Contract
. - Ethereum verifies the proof on-chain. If validated, Smart Contract
A
receives the computation result via theinvoke_callback
function.
Example
The following example assumes that the Bonsai Relayer
is up and running with the server API enabled,
and that the memory image of your ELF
is already registered against Bonsai with a given IMAGE_ID
as its identifier.
/// Example code for sending a REST API request to the Bonsai relay service to
/// requests, execution, proving, and on-chain callback for a zkVM guest
/// application.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about)]
struct Args {
/// Adress for the BonsaiStarter application contract.
address: Address,
/// Input N for calculating the Nth Fibonacci number.
number: u32,
/// Bonsai Relay API URL.
#[arg(long, env, default_value = "http://localhost:8080")]
bonsai_relay_api_url: String,
/// Bonsai API key. Used by the relay to send requests to the Bonsai proving
/// service. Defaults to empty, providing no authentication.
#[arg(long, env, default_value = "")]
bonsai_api_key: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let args = Args::parse();
// initialize a relay client
let relay_client = Client::from_parts(
args.bonsai_relay_api_url.clone(), // Set BONSAI_API_URL or replace this line.
args.bonsai_api_key.clone(), // Set BONSAI_API_KEY or replace this line.
)
.context("Failed to initialize the relay client")?;
// Initialize the input for the FIBONACCI guest.
let input = U256::from(args.number).abi_encode();
// Set the function selector of the callback function.
let function_signature = "storeResult(uint256,uint256)";
let function_selector = id(function_signature);
// Create a CallbackRequest for your contract
// example: (contracts/BonsaiStarter.sol).
let request = CallbackRequest {
callback_contract: args.address.into(),
function_selector,
gas_limit: 3000000,
image_id: Digest::from(FIBONACCI_ID).into(),
input,
};
// Send the callback request to the Bonsai Relay.
relay_client
.callback_request(request)
.await
.context("Callback request failed")?;
Ok(())
}
On-chain
As an alternative to sending a Callback request
from the REST API as described by step 5 of the previous section, the request can be sent via the on-chain Callback request
interface provided by the Bonsai Relay Contract:
- Send a transaction to Smart Contract
A
to trigger aCallback request
event that the Bonsai Relay will catch and forward to Bonsai.
Example
Using cast
:
cast send --private-key 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d --gas-limit 100000 "$APP_ADDRESS" 'calculateFibonacci(uint256)' 5
where:
$APP_ADDRESS
is an env variable containing the address of your Smart ContractA
calculateFibonacci(uint256)
is the function selector of your Smart ContractA
triggering theCallback request
5
is the input for your FIBONACCI program
Getting Started
The Bonsai Foundry Template is the best place to get started building Bonsai applications for Ethereum. You may also want to check out our Bonsai Quick Start page.