diff --git a/README.md b/README.md index 86f323ca..bbbf4007 100644 --- a/README.md +++ b/README.md @@ -100,11 +100,11 @@ Your new project consists of: ## Develop Your Application -To build your application, you'll need to make changes in three folders: +To build your application using the RISC Zero Foundry Template, you’ll need to make changes in three main areas: -- write the code you want proven in the [methods/guest](./methods/guest/) folder. -- write the on-chain part of your project in the [contracts](./contracts/) folder. -- adjust the publisher example in the [apps](./apps/) folder. +- ***Guest Code***: Write the code you want proven in the [methods/guest](./methods/guest/) folder. This code runs off-chain within the RISC Zero zkVM and performs the actual computations. For example, the provided template includes a computation to check if a given number is even and generate a proof of this computation. +- ***Smart Contracts***: Write the on-chain part of your project in the [contracts](./contracts/) folder. The smart contract verifies zkVM proofs and updates the blockchain state based on the results of off-chain computations. For instance, in the [EvenNumber](./contracts/EvenNumber.sol) example, the smart contract verifies a proof that a number is even and stores that number on-chain if the proof is valid. +- ***Publisher Application***: Adjust the publisher example in the [apps](./apps/) folder. The publisher application bridges off-chain computation with on-chain verification by submitting proof requests, receiving proofs, and publishing them to the smart contract on Ethereum. ### Configuring Bonsai diff --git a/apps/src/bin/publisher.rs b/apps/src/bin/publisher.rs index b521a09e..5e21d7b4 100644 --- a/apps/src/bin/publisher.rs +++ b/apps/src/bin/publisher.rs @@ -57,9 +57,10 @@ struct Args { fn main() -> Result<()> { env_logger::init(); + // Parse CLI Arguments: The application starts by parsing command-line arguments provided by the user. let args = Args::parse(); - // Create a new `TxSender`. + // Create a new transaction sender using the parsed arguments. let tx_sender = TxSender::new( args.chain_id, &args.rpc_url, @@ -67,18 +68,22 @@ fn main() -> Result<()> { &args.contract, )?; - // ABI encode the input for the guest binary, to match what the `is_even` guest - // code expects. + // ABI encode input: Before sending the proof request to the Bonsai proving service, + // the input number is ABI-encoded to match the format expected by the guest code running in the zkVM. let input = args.input.abi_encode(); - // Send an off-chain proof request to the Bonsai proving service. + // Request proof from the Bonsai proving service: The application sends the encoded input to the + // Bonsai proving service, requesting it to execute the is_even computation off-chain and generate the necessary proof. let (journal, post_state_digest, seal) = BonsaiProver::prove(IS_EVEN_ELF, &input)?; - // Decode the journal. Must match what was written in the guest with - // `env::commit_slice`. + // Decode Journal: Upon receiving the proof, the application decodes the journal to extract + // the verified number. This ensures that the number being submitted to the blockchain matches + // the number that was verified off-chain. let x = U256::abi_decode(&journal, true).context("decoding journal data")?; - // Encode the function call for `IEvenNumber.set(x)`. + // Construct function call: Using the IEvenNumber interface, the application constructs + // the ABI-encoded function call for the set function of the EvenNumber contract. + // This call includes the verified number, the post-state digest, and the seal (proof). let calldata = IEvenNumber::IEvenNumberCalls::set(IEvenNumber::setCall { x, post_state_digest, @@ -86,8 +91,11 @@ fn main() -> Result<()> { }) .abi_encode(); - // Send the calldata to Ethereum. + // Initialize the async runtime environment to handle the transaction sending. let runtime = tokio::runtime::Runtime::new()?; + + // Send transaction: Finally, the TxSender component sends the transaction to the Ethereum blockchain, + // effectively calling the set function of the EvenNumber contract with the verified number and proof. runtime.block_on(tx_sender.send(calldata))?; Ok(()) diff --git a/contracts/EvenNumber.sol b/contracts/EvenNumber.sol index a528f603..de3209e2 100644 --- a/contracts/EvenNumber.sol +++ b/contracts/EvenNumber.sol @@ -27,6 +27,10 @@ contract EvenNumber { /// @notice RISC Zero verifier contract address. IRiscZeroVerifier public immutable verifier; /// @notice Image ID of the only zkVM binary to accept verification from. + /// The image ID is similar to the address of a smart contract. + /// It uniquely represents the logic of that guest program, + /// ensuring that only proofs generated from a pre-defined guest program + /// (in this case, checking if a number is even) are considered valid. bytes32 public constant imageId = ImageID.IS_EVEN_ID; /// @notice A number that is guaranteed, by the RISC Zero zkVM, to be even. diff --git a/deployment-guide.md b/deployment-guide.md deleted file mode 100644 index c5617f7d..00000000 --- a/deployment-guide.md +++ /dev/null @@ -1,172 +0,0 @@ -# RISC Zero Ethereum Deployment Guide - -> **Note: This software is not production ready. Do not use in production.** - -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] - -## Deploy your project on a local network - -You can deploy your contracts and run an end-to-end test or demo as follows: - -1. Start a local testnet with `anvil` by running: - - ```bash - anvil - ``` - - Once anvil is started, keep it running in the terminal, and switch to a new terminal. - -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. Build your project: - - ```bash - cargo build - ``` - -4. Deploy your contract by running: - - ```bash - forge script --rpc-url http://localhost:8545 --broadcast script/Deploy.s.sol - ``` - - This command should output something similar to: - - ```bash - ... - == Logs == - Deployed RiscZeroGroth16Verifier to 0x5FbDB2315678afecb367f032d93F642f64180aa3 - Deployed EvenNumber to 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 - ... - ``` - - 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`][jq] installed: - > - > ```bash - > export EVEN_NUMBER_ADDRESS=$(jq -re '.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 ${EVEN_NUMBER_ADDRESS:?} 'get()(uint256)' - ``` - -2. Publish a new state - - ```bash - cargo run --bin publisher -- \ - --chain-id=31337 \ - --rpc-url=http://localhost:8545 \ - --contract=${EVEN_NUMBER_ADDRESS:?} \ - --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 - export BONSAI_API_URL="BONSAI_API_URL" # provided with your api key - export ALCHEMY_API_KEY="YOUR_ALCHEMY_API_KEY" # the API_KEY provided with an alchemy account - export ETH_WALLET_PRIVATE_KEY="YOUR_WALLET_PRIVATE_KEY" # the private hex-encoded key of your Sepolia testnet wallet - ``` - -2. Build your project: - - ```bash - cargo build - ``` - -3. 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 == - Deployed RiscZeroGroth16Verifier to 0x5FbDB2315678afecb367f032d93F642f64180aa3 - Deployed EvenNumber to 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 - ... - ``` - - 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`][jq] installed: - > - > ```bash - > export EVEN_NUMBER_ADDRESS=$(jq -re '.transactions[] | select(.contractName == "EvenNumber") | .contractAddress' ./broadcast/Deploy.s.sol/11155111/run-latest.json) - > ``` - -### 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)' - ``` - -2. Publish a new state - - ```bash - cargo run --bin publisher -- \ - --chain-id=11155111 \ - --rpc-url=https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY:?} \ - --contract=${EVEN_NUMBER_ADDRESS:?} \ - --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)' - ``` - -[Deploy to a testnet]: #deploy-your-project-on-a-testnet -[Deploy your project to a local network]: #deploy-your-project-on-a-local-network -[RISC Zero]: https://www.risczero.com/ -[contracts]: ./contracts/ -[jq]: https://jqlang.github.io/jq/ -[methods]: ./methods/ -[tested]: ./README.md#run-the-tests