From 3f00ae37801a49a0b68081d8239e02f266d3d924 Mon Sep 17 00:00:00 2001 From: Victor Graf Date: Mon, 5 Feb 2024 15:34:51 -0800 Subject: [PATCH 1/4] edits on readthrough of readme --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 920e71d9..f8c14998 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,12 @@ Verifiable results are sent to your Ethereum contract. ## Overview -The picture below shows a simplified overview of how users can integrate [Bonsai] into their Ethereum smart contracts: +Here is a simplified overview of how devs can integrate RISC Zero, with [Bonsai] proving, into their Ethereum smart contracts: ![Bonsai Foundry Template Diagram](images/bonsai-foundry-template.png) -1. Run your application logic in the [RISC Zero zkVM]. The provided Command Line Interface (CLI) sends an off-chain proof request to the Bonsai proving service. -2. Bonsai generates the computation result, written to the [journal], and a SNARK proof of its correctness. +1. Run your application logic in the [RISC Zero zkVM]. The provided Command Line Interface (CLI) sends an off-chain proof request to the [Bonsai] proving service. +2. [Bonsai] generates the program result, written to the [journal], and a SNARK proof of its correctness. 3. The CLI submits this proof and journal on-chain to your app contract for validation. 4. Your app contract calls the [RISC Zero Verifier] to validate the proof. If the verification is successful, the journal is deemed trustworthy and can be safely used. @@ -51,7 +51,7 @@ Next we'll need to install the `risc0` toolchain with: cargo risczero install ``` -Now you have all the tools you need to develop and deploy an application with RISC Zero. +Now you have all the tools you need to develop and deploy an application with [RISC Zero]. [install Rust]: https://doc.rust-lang.org/cargo/getting-started/installation.html [Foundry]: https://getfoundry.sh/ @@ -73,7 +73,7 @@ Your new project consists of: - a [zkVM program] (written in Rust), which specifies a computation that will be proven; - a [app contract] (written in Solidity), which receives the response; -- a [guest interface] (written in Rust), which lets you define how to parse and serialize the guest input and calldata so that the [RISC Zero zkVM] and Bonsai can interact with your contract. +- a [guest interface] (written in Rust), which lets you define how to parse and serialize the guest input and calldata so that the [RISC Zero zkVM] can integrate with your contract. [instructions above]: #dependencies [zkVM program]: ./methods/guest/src/bin @@ -82,7 +82,7 @@ Your new project consists of: ### Run the Tests -- Use `cargo test` to run the tests in your zkVM program. +- Use `RISC0_DEV_MODE=true cargo test` to run the tests in your zkVM program. - Use `RISC0_DEV_MODE=true forge test -vvv` to test your Solidity contracts and their interaction with your zkVM program. ## Develop Your Application @@ -109,8 +109,7 @@ export BONSAI_API_KEY="YOUR_API_KEY" # see form linked above export BONSAI_API_URL="BONSAI_URL" # provided with your api key ``` - -Now if you run `forge test` with `RISC0_DEV_MODE=false`, the test will run as before, but will additionally use the fully verifying `RiscZeroGroth16Verifier` contract instead of `RiscZeroGroth16VerifierTest` and will request a SNARK receipt from Bonsai. +Now if you run `forge test` with `RISC0_DEV_MODE=false`, the test will run as before, but will additionally use the fully verifying `RiscZeroGroth16Verifier` contract instead of `MockRiscZeroVerifier` and will request a SNARK receipt from Bonsai. ```bash RISC0_DEV_MODE=false forge test -vvv From 7bcdd369d52dfd6c94be7fcf94bbc7e71ba1ffe4 Mon Sep 17 00:00:00 2001 From: Victor Graf Date: Mon, 5 Feb 2024 17:05:07 -0800 Subject: [PATCH 2/4] changes to deployment guide in the process of testing it out --- README.md | 6 ++-- deployment-guide.md | 83 +++++++++++++++++++++++++++++++-------------- script/Deploy.s.sol | 5 ++- 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index f8c14998..101e6558 100644 --- a/README.md +++ b/README.md @@ -93,9 +93,9 @@ To build your application, you'll need to make changes in three folders: - write the on-chain part of your project in the [contracts] folder - write the guest interface in the [cli] folder -[methods]: ./methods -[cli]: ./cli -[contracts]: ./contracts +[methods]: ./methods/ +[cli]: ./cli/ +[contracts]: ./contracts/ ### Configuring Bonsai diff --git a/deployment-guide.md b/deployment-guide.md index 13dfc6d7..44b897a7 100644 --- a/deployment-guide.md +++ b/deployment-guide.md @@ -1,11 +1,21 @@ # Bonsai Deployment Guide + > **Note: This software is not production ready. Do not use in production.** -Welcome to the [Bonsai] Deployment guide! +Welcome to the [RISC Zero] Ethereum Deployment guide! + +Once you've written your [contracts] and your [methods], and [tested] your program, you're ready to deploy your contract. + +You can either: + +- [Deploy your project to a local network] +- [Deploy to a testnet] -Once you've written your [contracts] and your [methods], and [tested] your program, you're ready to deploy your contract. You can either: -- Deploy your project to a local network -- Deploy to a testnet +[methods]: ./methods/ +[contracts]: ./contracts/ +[tested]: ./README.md#run-the-tests +[Deploy your project to a local network]: #deploy-your-project-on-a-local-network +[Deploy to a testnet]: #deploy-your-project-on-a-testnet ## Deploy your project on a local network @@ -19,21 +29,24 @@ You can deploy your contracts and run an end-to-end test or demo as follows: Once anvil is started, keep it running in the terminal, and switch to a new terminal. -2. Set your private key: +2. Set your environment variables: + > ***Note:*** *This requires having access to a Bonsai API Key. To request an API key [complete the form here](https://bonsai.xyz/apply).* ```bash + # Anvil sets up a number of default wallets, and this private key is one of them. export ETH_WALLET_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + export BONSAI_API_KEY="YOUR_API_KEY" # see form linked in the previous section + export BONSAI_API_URL="BONSAI_API_URL" # provided with your api key ``` 3. Deploy your contract by running: - > This requires that `ETH_WALLET_PRIVATE_KEY` be set. ```bash forge script --rpc-url http://localhost:8545 --broadcast script/Deploy.s.sol ``` This command should output something similar to: - + ```bash ... == Logs == @@ -42,30 +55,49 @@ You can deploy your contracts and run an end-to-end test or demo as follows: ... ``` -### Interact with your deployment: + Save the `EvenNumber` contract address to an env variable: + + ```bash + export EVEN_NUMBER_ADDRESS=#COPY EVEN NUMBER ADDRESS FROM DEPLOY LOGS + ``` + + You can also use the following command to set the contract address if you have `jq` installed: + + ```bash + export EVEN_NUMBER_ADDRESS=$(jq -r '.transactions[] | select(.contractName == "EvenNumber") | .contractAddress' ./broadcast/Deploy.s.sol/31337/run-latest.json) + ``` + +### Interact with your local deployment 1. Query the state: + ```bash - cast call --rpc-url http://localhost:8545 0xe7f1725e7734ce288f8367e1bb143e90bb3f0512 'get()(uint256)' + cast call --rpc-url http://localhost:8545 ${EVEN_NUMBER_ADDRESS:?} 'get()(uint256)' ``` 2. Publish a new state - > ***Note:*** *This requires having access to a Bonsai API Key. To request an API key [complete the form here](https://bonsai.xyz/apply).* ```bash - RISC0_DEV_MODE=false BONSAI_API_URL="BONSAI_API_URL" BONSAI_API_KEY="BONSAI_API_KEY" cargo run --release -- publish \ + cargo run --release -- publish \ --chain-id=31337 \ --rpc-url=http://localhost:8545 \ - --contract=e7f1725E7734CE288F8367e1Bb143E90bb3F0512 \ + --contract=${EVEN_NUMBER_ADDRESS:?} \ --guest-binary="IS_EVEN" \ --input=12345678 ``` +3. Query the state again to see the change: + + ```bash + cast call --rpc-url http://localhost:8545 ${EVEN_NUMBER_ADDRESS:?} 'get()(uint256)' + ``` + ## Deploy your project on a testnet You can deploy your contracts on a testnet such as `Sepolia` and run an end-to-end test or demo as follows: 1. Get access to Bonsai and an Ethereum node running on a given testnet, e.g., Sepolia (in this example, we will be using [alchemy](https://www.alchemy.com/) as our Ethereum node provider) and export the following environment variables: + > ***Note:*** *This requires having access to a Bonsai API Key. To request an API key [complete the form here](https://bonsai.xyz/apply).* ```bash export BONSAI_API_KEY="YOUR_API_KEY" # see form linked in the previous section @@ -74,14 +106,14 @@ You can deploy your contracts on a testnet such as `Sepolia` and run an end-to-e export ETH_WALLET_PRIVATE_KEY="YOUR_WALLET_PRIVATE_KEY" # the private key of your Ethereum testnet wallet e.g., Sepolia ``` -2. Deploy your contract by running: +2. Deploy your contract by running: ```bash forge script script/Deploy.s.sol --rpc-url https://eth-sepolia.g.alchemy.com/v2/$ALCHEMY_API_KEY --broadcast ``` This command should output something similar to: - + ```bash ... == Logs == @@ -93,31 +125,30 @@ You can deploy your contracts on a testnet such as `Sepolia` and run an end-to-e Save the `EvenNumber` contract address to an env variable: ```bash - export EVEN_NUMBER_ADDRESS=0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 + export EVEN_NUMBER_ADDRESS=#COPY EVEN NUMBER ADDRESS FROM DEPLOY LOGS ``` + You can also use the following command to set the contract address if you have `jq` installed: + + ```bash + export EVEN_NUMBER_ADDRESS=$(jq -r '.transactions[] | select(.contractName == "EvenNumber") | .contractAddress' ./broadcast/Deploy.s.sol/11155111/run-latest.json) + ``` -## Interact with your deployment: +### Interact with your testnet deployment 1. Query the state: + ```bash - cast call --rpc-url https://eth-sepolia.g.alchemy.com/v2/$ALCHEMY_API_KEY $EVEN_NUMBER_ADDRESS 'get()(uint256)' + cast call --rpc-url https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY:?} ${EVEN_NUMBER_ADDRESS:?} 'get()(uint256)' ``` 2. Publish a new state - > ***Note:*** *This requires having access to a Bonsai API Key. To request an API key [complete the form here](https://bonsai.xyz/apply).* ```bash RISC0_DEV_MODE=false cargo run --release -- publish \ --chain-id=11155111 \ - --rpc-url=https://eth-sepolia.g.alchemy.com/v2/$ALCHEMY_API_KEY \ - --contract=$EVEN_NUMBER_ADDRESS \ + --rpc-url=https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY:?} \ + --contract=${EVEN_NUMBER_ADDRESS:?} \ --guest-binary="IS_EVEN" \ --input=12345678 ``` - -[Bonsai]: https://risczero.com/bonsai -[contracts]: https://github.com/risc0/bonsai-foundry-template/tree/main/contracts -[methods]: https://github.com/risc0/bonsai-foundry-template/tree/main/methods -[tested]: https://github.com/risc0/bonsai-foundry-template/tree/main#test-your-project -[Groth16 SNARK proof]: https://www.risczero.com/news/on-chain-verification diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 39ad75c7..562a499f 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -27,9 +27,12 @@ import {EvenNumber} from "../contracts/EvenNumber.sol"; /// @notice Deployment script for the BonsaiStarter project. /// @dev Use the following environment variable to control the deployment: /// * ETH_WALLET_PRIVATE_KEY private key of the wallet to be used for deployment. +/// +/// See the Foundry documentation for more information about Solidity scripts. +/// https://book.getfoundry.sh/tutorials/solidity-scripting contract EvenNumberDeploy is Script, BonsaiCheats { function run() external { - uint256 deployerKey = vm.envOr("ETH_WALLET_PRIVATE_KEY", uint256(0)); + uint256 deployerKey = uint256(vm.envBytes32("ETH_WALLET_PRIVATE_KEY")); vm.startBroadcast(deployerKey); From da00d5d38b24201fbe5b55d74c3df25b1b892037 Mon Sep 17 00:00:00 2001 From: Victor Graf Date: Mon, 5 Feb 2024 17:15:34 -0800 Subject: [PATCH 3/4] fix error leftover from working on the guest interface --- cli/src/interface.rs | 4 ++-- sdk/src/cli.rs | 8 +++----- sdk/src/eth.rs | 5 +++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/cli/src/interface.rs b/cli/src/interface.rs index 6f2406e1..2ef3604c 100644 --- a/cli/src/interface.rs +++ b/cli/src/interface.rs @@ -16,7 +16,7 @@ use std::str::FromStr; use alloy_primitives::{FixedBytes, U256}; use alloy_sol_types::{sol, SolInterface, SolValue}; -use anyhow::Result; +use anyhow::{Context, Result}; use risc0_ethereum_sdk::cli::GuestInterface; // You can modify this file to implement the `GuestInterface` trait @@ -53,7 +53,7 @@ impl GuestInterface for EvenNumberInterface { seal: Vec, ) -> Result> { // Decode the journal. Must match what was written in the guest with `env::commit_slice` - let x = U256::abi_decode(&journal, true)?; + let x = U256::abi_decode(&journal, true).context("decoding journal data")?; // Encode the function call for `IEvenNumber.set(x)` Ok(IEvenNumber::IEvenNumberCalls::set(IEvenNumber::setCall { diff --git a/sdk/src/cli.rs b/sdk/src/cli.rs index 74371cf4..4ed8185b 100644 --- a/sdk/src/cli.rs +++ b/sdk/src/cli.rs @@ -103,6 +103,7 @@ pub fn query( // No input. Return the Ethereum ABI encoded bytes32 image ID. None => format!("0x{}", hex::encode(image_id)), }; + // Forge test FFI calls expect hex encoded bytes sent to stdout print!("{output}"); std::io::stdout() .flush() @@ -130,11 +131,8 @@ pub fn publish( post_state_digest, seal, } = prover::generate_proof(&elf, input)?; - let calldata = guest_interface.encode_calldata( - risc0_zkvm::serde::from_slice(journal.as_slice())?, - post_state_digest, - seal, - )?; + + let calldata = guest_interface.encode_calldata(journal, post_state_digest, seal)?; let runtime = tokio::runtime::Runtime::new()?; runtime.block_on(tx_sender.send(calldata))?; diff --git a/sdk/src/eth.rs b/sdk/src/eth.rs index 11eee9b6..ef5f1051 100644 --- a/sdk/src/eth.rs +++ b/sdk/src/eth.rs @@ -47,11 +47,12 @@ impl TxSender { .from(self.client.address()) .data(calldata); - eprintln!("Transaction request: {:?}", &tx); + // TODO: Add these back as proper log lines istead of print statements + //eprintln!("Transaction request: {:?}", &tx); let tx = self.client.send_transaction(tx, None).await?.await?; - eprintln!("Transaction receipt: {:?}", &tx); + //eprintln!("Transaction receipt: {:?}", &tx); Ok(tx) } From bcf8b483e91caed57ca15e2518d564f47ebf68fe Mon Sep 17 00:00:00 2001 From: Victor Graf Date: Mon, 5 Feb 2024 17:37:00 -0800 Subject: [PATCH 4/4] quick pass on other md files --- contracts/README.md | 9 ++++----- deployment-guide.md | 16 +++++++++++----- methods/README.md | 33 +++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/contracts/README.md b/contracts/README.md index ca883838..7ed739bc 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,8 +1,10 @@ -# Bonsai Solidity Contracts +# Solidity Contracts -This directory contains the Solidity contract for deploying a [Bonsai] application. +This directory contains the Solidity contract for deploying an application with [RISC Zero] on Ethereum. There are two primary starter template contracts included. + + The Solidity libraries for Bonsai can be found at [github.com/risc0/risc0](https://github.com/risc0/risc0/tree/main/bonsai/ethereum). Contracts are built and tested with [forge], which is part of the [Foundry] toolkit. @@ -10,7 +12,4 @@ Tests are defined in the `tests` directory in the root of this template. [Foundry]: https://getfoundry.sh/ [forge]: https://github.com/foundry-rs/foundry#forge -[Bonsai]: https://dev.bonsai.xyz -[offloading the computation]: https://twitter.com/RiscZero/status/1677316664772132864 [RISC Zero]: https://risczero.com -[guest]: https://github.com/risc0/bonsai-foundry-template/tree/main/methods/guest/src/bin diff --git a/deployment-guide.md b/deployment-guide.md index 44b897a7..75188cfe 100644 --- a/deployment-guide.md +++ b/deployment-guide.md @@ -64,7 +64,7 @@ You can deploy your contracts and run an end-to-end test or demo as follows: You can also use the following command to set the contract address if you have `jq` installed: ```bash - export EVEN_NUMBER_ADDRESS=$(jq -r '.transactions[] | select(.contractName == "EvenNumber") | .contractAddress' ./broadcast/Deploy.s.sol/31337/run-latest.json) + export EVEN_NUMBER_ADDRESS=$(jq -re '.transactions[] | select(.contractName == "EvenNumber") | .contractAddress' ./broadcast/Deploy.s.sol/31337/run-latest.json) ``` ### Interact with your local deployment @@ -96,7 +96,7 @@ You can deploy your contracts and run an end-to-end test or demo as follows: You can deploy your contracts on a testnet such as `Sepolia` and run an end-to-end test or demo as follows: -1. Get access to Bonsai and an Ethereum node running on a given testnet, e.g., Sepolia (in this example, we will be using [alchemy](https://www.alchemy.com/) as our Ethereum node provider) and export the following environment variables: +1. Get access to Bonsai and an Ethereum node running on a given testnet, e.g., Sepolia (in this example, we will be using [Alchemy](https://www.alchemy.com/) as our Ethereum node provider) and export the following environment variables: > ***Note:*** *This requires having access to a Bonsai API Key. To request an API key [complete the form here](https://bonsai.xyz/apply).* ```bash @@ -109,7 +109,7 @@ You can deploy your contracts on a testnet such as `Sepolia` and run an end-to-e 2. Deploy your contract by running: ```bash - forge script script/Deploy.s.sol --rpc-url https://eth-sepolia.g.alchemy.com/v2/$ALCHEMY_API_KEY --broadcast + forge script script/Deploy.s.sol --rpc-url https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY:?} --broadcast ``` This command should output something similar to: @@ -131,7 +131,7 @@ You can deploy your contracts on a testnet such as `Sepolia` and run an end-to-e You can also use the following command to set the contract address if you have `jq` installed: ```bash - export EVEN_NUMBER_ADDRESS=$(jq -r '.transactions[] | select(.contractName == "EvenNumber") | .contractAddress' ./broadcast/Deploy.s.sol/11155111/run-latest.json) + export EVEN_NUMBER_ADDRESS=$(jq -re '.transactions[] | select(.contractName == "EvenNumber") | .contractAddress' ./broadcast/Deploy.s.sol/11155111/run-latest.json) ``` ### Interact with your testnet deployment @@ -145,10 +145,16 @@ You can deploy your contracts on a testnet such as `Sepolia` and run an end-to-e 2. Publish a new state ```bash - RISC0_DEV_MODE=false cargo run --release -- publish \ + cargo run --release -- publish \ --chain-id=11155111 \ --rpc-url=https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY:?} \ --contract=${EVEN_NUMBER_ADDRESS:?} \ --guest-binary="IS_EVEN" \ --input=12345678 ``` + +3. Query the state again to see the change: + + ```bash + cast call --rpc-url https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY:?} ${EVEN_NUMBER_ADDRESS:?} 'get()(uint256)' + ``` diff --git a/methods/README.md b/methods/README.md index bec6d13b..cc2b8c27 100644 --- a/methods/README.md +++ b/methods/README.md @@ -1,33 +1,38 @@ -## zkVM Methods +# zkVM Methods -This directory contains the [zkVM] portion of your [Bonsai] application. +This directory contains the [zkVM] portion of your [RISC Zero] application. This is where you will define one or more [guest programs] to act as a coprocessor to your [on-chain logic]. -> In typical use cases, the only code in this directory that you will need to edit is inside [`guest/src/bin`]. +> In typical use cases, the only code in this directory that you will need to edit is inside [`guest/src/bin`]. + +[zkVM]: https://dev.risczero.com/zkvm +[RISC Zero]: https://www.risczero.com/ +[guest programs]: https://dev.risczero.com/terminology#guest-program +[on-chain logic]: ../contracts/ +[`guest/src/bin`]: ./guest/src/bin/ ### Writing Guest Code -To learn to write code for the zkVM, we recommend [Guest Code 101]. + +To learn to write code for the zkVM, we recommend [Guest Code 101]. Examples of what you can do in the guest can be found in the [RISC Zero examples]. +[Guest Code 101]: https://dev.risczero.com/zkvm/developer-guide/guest-code-101 +[RISC Zero examples]: https://github.com/risc0/tree/v0.18.0/examples + ### From Guest Code to Binary File -Code in the `methods/guest` directory will be compiled into one or more [RISC-V] binaries. +Code in the `methods/guest` directory will be compiled into one or more binaries. + Build configuration for the methods is included in `methods/build.rs`. Each will have a corresponding image ID, which is a hash identifying the program. ### Uploading Binary to Bonsai + + + When [deploying] your application, you will upload your binary to Bonsai where the guest will run when requested. The image ID will be included in the deployment of the smart contracts to reference your guest program living in Bonsai. [deploying]: ../deployment-guide -[RISC Zero examples]: https://github.com/risc0/tree/v0.18.0/examples -[Guest Code 101]: https://dev.risczero.com/zkvm/developer-guide/guest-code-101 -[on-chain logic]: ../contracts/readme -[`guest/src/bin`]: ./guest/src/bin/ -[guest program]: https://dev.risczero.com/terminology#guest-program -[guest programs]: https://dev.risczero.com/terminology#guest-program -[developer documentation]: https://dev.risczero.com -[zkVM]: https://dev.risczero.com/zkvm -[Bonsai]: https://dev.risczero.com/bonsai/