From 24bb1930df778492d9b747c6be3a3c13f925d7b7 Mon Sep 17 00:00:00 2001 From: Alex Sirac Date: Thu, 26 Dec 2024 15:49:10 +0100 Subject: [PATCH 1/6] instruction --- docs/developers/getting-started/your-first-erc20.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/developers/getting-started/your-first-erc20.md b/docs/developers/getting-started/your-first-erc20.md index 7a29ed5..e9cafc3 100644 --- a/docs/developers/getting-started/your-first-erc20.md +++ b/docs/developers/getting-started/your-first-erc20.md @@ -75,6 +75,7 @@ cargo run -- balance faucet.simple_token cargo run -- balance bob.simple_token ``` + This example does not compose with an identity contract, thus no identity verification is made. This is the reason of the suffix `.simple_token` on the "from" & "to" transfer fields. More info on identity management will come in the documentation. ## Detailed explanation From 4e9036f8d173be4e67d2bf284fbd0d3dd68fb229 Mon Sep 17 00:00:00 2001 From: Alex Sirac Date: Thu, 26 Dec 2024 16:17:13 +0100 Subject: [PATCH 2/6] annotated code --- .../getting-started/your-first-erc20.md | 280 ++++++++++++++---- 1 file changed, 221 insertions(+), 59 deletions(-) diff --git a/docs/developers/getting-started/your-first-erc20.md b/docs/developers/getting-started/your-first-erc20.md index e9cafc3..9babf0f 100644 --- a/docs/developers/getting-started/your-first-erc20.md +++ b/docs/developers/getting-started/your-first-erc20.md @@ -76,7 +76,19 @@ cargo run -- balance bob.simple_token ``` -This example does not compose with an identity contract, thus no identity verification is made. This is the reason of the suffix `.simple_token` on the "from" & "to" transfer fields. More info on identity management will come in the documentation. +In this example, we do not verify the identity of the person who initiates the transaction. We use `.simple_token` as a suffix for the "from" and "to" transfer fields: usually, we'd use the identity scheme as the suffix. + +!!! note + More information about identity management will be added to the documentation in January 2025. + +### Verifying your contract's state + +Your contract's state digest is visible at: `https://hyleou.hyle.eu/contract/$CONTRACT_NAME` + +After Hylé verifies your proof, your transaction is settled, updating the state of the contract. + +You can see your transaction on Hylé's explorer: `https://hyleou.hyle.eu/transaction/$TX_HASH` + ## Detailed explanation @@ -94,83 +106,233 @@ RUST_LOG="[executor]=info" RISC0_DEV_MODE=1 cargo run ### Content of the contract - -Hylé will now verify your proof. After verification, your transaction is settled, updating the state of the contract. +Now that the contract input is built, you can generate your zero-knowledge proof using Risc0: -You can see your transaction on Hylé's explorer: `https://hyleou.hyle.eu/transaction/$TX_HASH` +```rs + // Generate the zk proof + let receipt = prove(cli.reproducible, inputs).unwrap(); -### Verifying your contract's state + let proof_tx = ProofTransaction { + blob_tx_hash, + proof: ProofData::Bytes(borsh::to_vec(&receipt).expect("Unable to encode receipt")), + contract_name: contract_name.clone().into(), + }; +``` -Your contract's state digest is visible at: `https://hyleou.hyle.eu/contract/$CONTRACT_NAME` \ No newline at end of file +Finally, send the proof transaction to Hylé for verification and settlement. + +```rs + // Send the proof transaction + let proof_tx_hash = client + .send_tx_proof(&proof_tx) + .await + .unwrap() + .text() + .await + .unwrap(); + println!("✅ Proof tx sent. Tx hash: {}", proof_tx_hash); + } + } +} +``` \ No newline at end of file From 7ee33193e9c6f5bb5b25dec9a74ac85f0d03c097 Mon Sep 17 00:00:00 2001 From: Alex Sirac Date: Thu, 26 Dec 2024 16:20:25 +0100 Subject: [PATCH 3/6] removed a comment --- docs/developers/getting-started/your-first-erc20.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/developers/getting-started/your-first-erc20.md b/docs/developers/getting-started/your-first-erc20.md index 9babf0f..c0197ac 100644 --- a/docs/developers/getting-started/your-first-erc20.md +++ b/docs/developers/getting-started/your-first-erc20.md @@ -23,10 +23,6 @@ Hylé smart contracts include: Read more about the [anatomy of smart contracts on Hylé](../general-doc/anatomy-smart-contracts.md). - - ## Quick start: Register your contract on your local node To build all methods and register the smart contract on the local node [from the source](https://github.com/Hyle-org/examples/blob/simple_erc20/simple-erc20/host/src/main.rs), run: From c4c69333a74dc6f2f4056373a488b58e8567aa5d Mon Sep 17 00:00:00 2001 From: Alex Sirac Date: Thu, 26 Dec 2024 16:33:01 +0100 Subject: [PATCH 4/6] removed irrelevant parts of the code --- .../getting-started/your-first-erc20.md | 334 ------------------ .../your-first-smart-contract.md | 255 +++++++++---- 2 files changed, 180 insertions(+), 409 deletions(-) delete mode 100644 docs/developers/getting-started/your-first-erc20.md diff --git a/docs/developers/getting-started/your-first-erc20.md b/docs/developers/getting-started/your-first-erc20.md deleted file mode 100644 index c0197ac..0000000 --- a/docs/developers/getting-started/your-first-erc20.md +++ /dev/null @@ -1,334 +0,0 @@ -# Your first smart contract - -We'll use [our sample token transfer example](https://github.com/Hyle-org/examples/tree/simple_erc20/simple-erc20) as the basis for this tutorial. - -Read more in our [anatomy of a smart contract](../general-doc/anatomy-smart-contracts.md). - -## Prerequisites - -- A working knowledge of zkVM basics. -- [Install Rust](https://www.rust-lang.org/tools/install) (you'll need `rustup` and Cargo). -- [Start a single-node devnet](./devnet.md). We recommend activating [dev-mode](https://dev.risczero.com/api/generating-proofs/dev-mode) during your early development phase for faster iteration upon code changes with `-e RISC0_DEV_MODE=1`. -- For our example, you'll need to [install RISC Zero](https://dev.risczero.com/api/zkvm/install). - -## Content of a smart contract - -Hylé smart contracts include: - -- **Owner**: put anything you like. This field is currently not leveraged but will be in future versions. -- **Verifier**: the proof system (e.g. "risc0" or "gnark-groth16-te-BN254"). -- **Program ID**: the unique identifier for your program in that proof system. -- **Contract name**: the unique identifier for your contract. -- **State digest**: current state commitment of the contract, usually a MerkleRootHash of the contract's state. - -Read more about the [anatomy of smart contracts on Hylé](../general-doc/anatomy-smart-contracts.md). - -## Quick start: Register your contract on your local node - -To build all methods and register the smart contract on the local node [from the source](https://github.com/Hyle-org/examples/blob/simple_erc20/simple-erc20/host/src/main.rs), run: - -```bash -cargo run -- register 1000 -``` - -On the node's logs, you should see a line stating: `📝 Registering new contract simple_token`. - -To send 2 tokens to *Bob*, sending a blob transaction and a proof transaction associated with that, you can run: - -```bash -cargo run -- transfer faucet.simple_token bob.simple_token 2 -``` - -This will: - -1. Send a blob transaction to transfer 2 tokens from `faucet` to `bob` -2. Generate a ZK proof of that transfer -3. Send the proof to the devnet. - -Your node will then: - -1. Verify the proof -1. Settle the blob transaction -1. Update the contract State - -On node's logs you should see: - -```bash -INFO hyle::data_availability::node_state::verifiers: ✅ Risc0 proof verified. -INFO hyle::data_availability::node_state::verifiers: 🔎 Program outputs: Transferred 2 to bob.simple_token -``` - -And after a slot: - -```bash -INFO hyle::data_availability::node_state: Settle tx TxHash("[..]") -``` - -You can check onchain balance: - -```bash -cargo run -- balance faucet.simple_token -cargo run -- balance bob.simple_token -``` - - -In this example, we do not verify the identity of the person who initiates the transaction. We use `.simple_token` as a suffix for the "from" and "to" transfer fields: usually, we'd use the identity scheme as the suffix. - -!!! note - More information about identity management will be added to the documentation in January 2025. - -### Verifying your contract's state - -Your contract's state digest is visible at: `https://hyleou.hyle.eu/contract/$CONTRACT_NAME` - -After Hylé verifies your proof, your transaction is settled, updating the state of the contract. - -You can see your transaction on Hylé's explorer: `https://hyleou.hyle.eu/transaction/$TX_HASH` - - -## Detailed explanation - -### Execute your project locally in development mode - -We recommend activating [dev-mode](https://dev.risczero.com/api/generating-proofs/dev-mode) during your early development phase for faster iteration upon code changes with `-e RISC0_DEV_MODE=1`. - -You may also want to get insights into the execution statistics of your project: add the environment variable `RUST_LOG="[executor]=info"` before running your project. - -The full command to run your project in development mode while getting execution statistics is: - -```bash -RUST_LOG="[executor]=info" RISC0_DEV_MODE=1 cargo run -``` - -### Content of the contract - -Find the full code in [our examples repository](https://github.com/Hyle-org/examples/blob/simple_erc20/simple-erc20/host/src/main.rs). - -Initial setup: - -```rs -use anyhow::bail; -use anyhow::Result; -use clap::{Parser, Subcommand}; -use contract::Token; -use contract::TokenContract; -use hyle::model::BlobTransaction; -use hyle::model::ProofData; -use hyle::model::ProofTransaction; -use hyle::model::RegisterContractTransaction; -use risc0_zkvm::Receipt; -use risc0_zkvm::{default_prover, ExecutorEnv}; -use sdk::erc20::ERC20; -use sdk::HyleOutput; -use sdk::{ContractInput, Digestable}; - -// These constants represent the RISC-V ELF and the image ID generated by risc0-build. -// The ELF is used for proving and the ID is used for verification. -use methods::{GUEST_ELF, GUEST_ID}; -``` - -Set up commands and CLI. You need a unique `contract_name`.. Here, we use `"simple_token"`. - -```rs -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -#[command(propagate_version = true)] -struct Cli { - #[command(subcommand)] - command: Commands, - - #[clap(long, short)] - reproducible: bool, - - #[arg(long, default_value = "http://localhost:4321")] - pub host: String, - - #[arg(long, default_value = "simple_token")] - pub contract_name: String, -} - -#[derive(Subcommand)] -enum Commands { - Register { - supply: u128, - }, - Transfer { - from: String, - to: String, - amount: u128, - }, - Balance { - of: String, - }, -} -``` - -Set up information about your contract. To register the contract, you'll need: - -- `owner`: we put "examples" as the `owner`, but you can put anything you like. This field is currently not leveraged; it will be in future versions. -- `verifier`: for this example, the verifier is `risc0` -- `program_id`: RISC Zero programs are identified by their image ID, without a prefix. -- `state_digest`: usually a MerkleRootHash of the contract's initial state. For this example, we use a hexadecimal representation of the state encoded in binary format. The state digest cannot be empty, even if your app is stateless. -- `contract_name` as set up above. - -Then, send a transaction that will register the contract. - -```rs -#[tokio::main] -async fn main() { - // Initialize tracing. In order to view logs, run `RUST_LOG=info cargo run` - tracing_subscriber::fmt() - .with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env()) - .init(); - - let cli = Cli::parse(); - - let client = hyle::tools::rest_api_client::ApiHttpClient::new(cli.host); - - let contract_name = &cli.contract_name; - - match cli.command { - Commands::Register { supply } => { - // Build initial state of contract - let initial_state = Token::new(supply, format!("faucet.{}", contract_name).into()); - println!("Initial state: {:?}", initial_state); - - // Send the transaction to register the contract - let register_tx = RegisterContractTransaction { - owner: "examples".to_string(), - verifier: "risc0".into(), - program_id: sdk::ProgramId(sdk::to_u8_array(&GUEST_ID).to_vec()), - state_digest: initial_state.as_digest(), - contract_name: contract_name.clone().into(), - }; - let res = client - .send_tx_register_contract(®ister_tx) - .await - .unwrap() - .text() - .await - .unwrap(); - - println!("✅ Register contract tx sent. Tx hash: {}", res); - } - Commands::Balance { of } => { - // Fetch the state from the node - let state: Token = client - .get_contract(&contract_name.clone().into()) - .await - .unwrap() - .state - .into(); - - let contract = TokenContract::init(state, "".into()); - let balance = contract.balance_of(&of).unwrap(); - println!("Balance of {}: {}", of, balance); - } - Commands::Transfer { from, to, amount } => { - // Fetch the initial state from the node - let initial_state: Token = client - .get_contract(&contract_name.clone().into()) - .await - .unwrap() - .state - .into(); -``` - -In [the explorer](https://hyleou.hyle.eu/), this will look like this: - -```rs -{ - "tx_hash": "321b7a4b2228904fc92979117e7c2aa6740648e339c97986141e53d967e08097", - "owner": "examples", - "verifier": "risc0", - "program_id":"e085fa46f2e62d69897fc77f379c0ba1d252d7285f84dbcc017957567d1e812f", - "state_digest": "fd00e876481700000001106661756365742e687964656e74697479fd00e876481700000000", - "contract_name": "simple_token" -} -``` - -Now, let's build the blob transaction. - -```rs - // ---- - // Build the blob transaction - // ---- - - let action = sdk::erc20::ERC20Action::Transfer { - recipient: to.clone(), - amount, - }; - let blobs = vec![sdk::Blob { - contract_name: contract_name.clone().into(), - data: sdk::BlobData( - bincode::encode_to_vec(action, bincode::config::standard()) - .expect("failed to encode BlobData"), - ), - }]; - let blob_tx = BlobTransaction { - identity: from.into(), - blobs, - }; - - // Send the blob transaction - let blob_tx_hash = client.send_tx_blob(&blob_tx).await.unwrap(); - println!("✅ Blob tx sent. Tx hash: {}", blob_tx_hash); -``` - -Hylé transactions are settled in two steps, following [pipelined proving principles](../general-doc/pipelined-proving.md). After this step, your transaction is sequenced, but not settled. - -For the transaction to be settled, it needs to be proven. You'll start with building the contract input, specifying: - -- the initial state as set above -- the identity of the transaction initiator -- the transaction hash, which can be found in the explorer after sequencing (currently, this can be ignored; it will be necessary after an upcoming update) -- information about the blobs. - - private input for proof generation in `private_blob` - - `blobs`: full list of blobs in the transaction (must match the blob transaction) - - `index`: each blob of a transaction must be proven separately for now, so you need to specify the index of the blob you're proving. - -```rs - // ---- - // Prove the state transition - // ---- - - // Build the contract input - let inputs = ContractInput:: { - initial_state, - identity: from.clone().into(), - tx_hash: "".into(), - private_blob: sdk::BlobData(vec![]), - blobs: blobs.clone(), - index: sdk::BlobIndex(0), - }; -``` - -Now that the contract input is built, you can generate your zero-knowledge proof using Risc0: - -```rs - // Generate the zk proof - let receipt = prove(cli.reproducible, inputs).unwrap(); - - let proof_tx = ProofTransaction { - blob_tx_hash, - proof: ProofData::Bytes(borsh::to_vec(&receipt).expect("Unable to encode receipt")), - contract_name: contract_name.clone().into(), - }; -``` - -Finally, send the proof transaction to Hylé for verification and settlement. - -```rs - // Send the proof transaction - let proof_tx_hash = client - .send_tx_proof(&proof_tx) - .await - .unwrap() - .text() - .await - .unwrap(); - println!("✅ Proof tx sent. Tx hash: {}", proof_tx_hash); - } - } -} -``` \ No newline at end of file diff --git a/docs/developers/getting-started/your-first-smart-contract.md b/docs/developers/getting-started/your-first-smart-contract.md index 3a1f8b2..4d5cf79 100644 --- a/docs/developers/getting-started/your-first-smart-contract.md +++ b/docs/developers/getting-started/your-first-smart-contract.md @@ -1,131 +1,236 @@ # Your first smart contract -You can use [any zkVM or proving scheme supported by Hylé](../general-doc/supported-proving-schemes.md). +This guide will walk you through creating and deploying your first token transfer contract using Hylé's tools and infrastructure. We'll use [our sample token transfer example](https://github.com/Hyle-org/examples/tree/simple_erc20/simple-erc20) as the basis for this tutorial. -We'll use [the Collatz example](https://github.com/Hyle-org/examples/tree/main/collatz-conjecture-rust) as an example throughout this tutorial. See the [Collatz page](../examples/collatz-example-in-depth.md) page for more information. - -Read more in our [anatomy of a smart contract](../general-doc/anatomy-smart-contracts.md). +For an in-depth understanding of smart contracts, check out our [anatomy of a smart contract](../general-doc/anatomy-smart-contracts.md). ## Prerequisites -- A working knowledge of zkVM basics. - [Install Rust](https://www.rust-lang.org/tools/install) (you'll need `rustup` and Cargo). -- [Connect to devnet](./devnet.md) -- [Follow the CLI installation instructions](user-tooling.md). We are currently building utilities that will make it easier and faster to use our explorer, [Hyléou](../explorer.md). -- For our example, you'll need to [install RISC Zero](https://dev.risczero.com/api/zkvm/install). +- For our example, [install RISC Zero](https://dev.risczero.com/api/zkvm/install). +- [Start a single-node devnet](./devnet.md). We recommend using [dev-mode](https://dev.risczero.com/api/generating-proofs/dev-mode) with `-e RISC0_DEV_MODE=1` for faster iterations during development. -## Registering your smart contract +## Quickstart -### Content of a smart contract +### Build and register the contract -Hylé smart contracts include: +To build all methods and register the smart contract on the local node [from the source](https://github.com/Hyle-org/examples/blob/simple_erc20/simple-erc20/host/src/main.rs), run: -- **Owner**: put anything you like. This field is currently not leveraged but will be in future versions. -- **Verifier**: the proof system (e.g. "risc0" or "gnark-groth16-te-BN254"). -- **Program ID**: the unique identifier for your program in that proof system. -- **Contract name**: the unique identifier for your contract. -- **State digest**: current state commitment of the contract, usually a MerkleRootHash of the contract's state. +```bash +cargo run -- register 1000 +``` -Read more about the [anatomy of smart contracts on Hylé](../general-doc/anatomy-smart-contracts.md). +The expected output is `📝 Registering new contract simple_token`. -### Register your contract +### Transfer tokens -To register a contract on Hylé, run the following command: +To transfer 2 tokens from `faucet` to `Bob`: ```bash -# Owner is currently unused, but could be used in the future to manage contract permissions -hyled contract [owner] [verifier] [program_id] [contract_name] [state_digest] +cargo run -- transfer faucet.simple_token bob.simple_token 2 ``` -Replace `[owner], [verifier], [program_id], [contract_name]`, and `[state_digest]` with your specific details. +This command will: -#### For Collatz +1. Send a blob transaction to transfer 2 tokens from `faucet` to `bob`. +2. Generate a ZK proof of that transfer. +3. Send the proof to the devnet. -In the case of the Collatz Conjecture example, as RISC Zero programs are identified by their image ID, without a prefix, we use the number `0xb48e70c79688b41fc8f0daf8370d1ddb3f44ada934c10c6e0b0f5915102a363b`. This will change every time the contract logic is modified. +### Verify settled state -The initial state is set to "1", so that it can be reset to any number. This is encoded in base 64 as `AAAAAQ==` because of the Rust library used to decode the state. +Upon reception of the proof, the node will: -Note that you need a unique `contract_name`. If you try to test this example on the public devnet, we recommend putting a name that's not « collatz ». +1. Verify the proof +1. Settle the blob transaction +1. Update the contract's state -For our example, the bash command looks like this: +The node's logs will display: ```bash -hyled contract default risc0 b48e70c79688b41fc8f0daf8370d1ddb3f44ada934c10c6e0b0f5915102a363b collatz AAAAAQ== +INFO hyle::data_availability::node_state::verifiers: ✅ Risc0 proof verified. +INFO hyle::data_availability::node_state::verifiers: 🔎 Program outputs: Transferred 2 to bob.simple_token ``` -(We put « default » as the `owner`, but you can put anything you like. This field is currently not leveraged; it will be in future versions.) +And on the following slot: -#### Checking your contract +```bash +INFO hyle::data_availability::node_state: Settle tx TxHash("[..]") +``` -In the explorer, this will look like this: +#### Check onchain balance -```rust -{ - "tx_hash": "ebecbf7458370d656772369df4a76c343b050e3fdbe4c1ceb7d54175ce290b60", - "owner": "default", - "verifier": "risc0", - "program_id": [ - b48e70c79688b41fc8f0daf8370d1ddb3f44ada934c10c6e0b0f5915102a363b - ], - "state_digest": [ - AAAAAQ== - ], - "contract_name": "collatz" -} +Verify onchain balances: + +```bash +cargo run -- balance faucet.simple_token +cargo run -- balance bob.simple_token ``` -## Interacting with Hylé +!!! note + In this example, we do not verify the identity of the person who initiates the transaction. We use `.simple_token` as a suffix for the "from" and "to" transfer fields: usually, we'd use the identity scheme as the suffix. **More information about identity management will be added to the documentation in January 2025.** + +See your contract's state digest at: `https://hyleou.hyle.eu/contract/$CONTRACT_NAME`. -Hylé transactions are settled in two steps, following [pipelined proving principles](https://blog.hyle.eu/an-introduction-to-delayed-proving/). +See your transaction on Hylé's explorer: `https://hyleou.hyle.eu/transaction/$TX_HASH`. -1. **Publishing payloads**: send the input of your program to the network. -2. **Posting proof of your payload**: generate and submit proofs validating your payload so Hylé will settle your transaction. +## Detailed information -### Publishing payloads +### Development mode -The content of the payload is app-specific: it's the input of your program. +We recommend activating [dev-mode](https://dev.risczero.com/api/generating-proofs/dev-mode) during your early development phase for faster iteration upon code changes with `-e RISC0_DEV_MODE=1`. -For the Collatz conjecture, this is a number encoded as a big-endian 32-bit integer. +You may also want to get insights into the execution statistics of your project: add the environment variable `RUST_LOG="[executor]=info"` before running your project. + +The full command to run your project in development mode while getting execution statistics is: ```bash -payload='\x00\x00\x00\x05' -# Generate the proof in 'collatz-contract' -cargo run reset $payload -hyled blobs "" collatz $(echo $payload | base64) -# the "" is a placeholder for identity: it's empty, as Collatz doesn't handle identity +RUST_LOG="[executor]=info" RISC0_DEV_MODE=1 cargo run ``` -You can see your transaction on Hylé's explorer: `https://hyleou.hyle.eu/transaction/$TX_HASH` +### Code snippets -At this point, your transaction has been sequenced, but not settled. +Find the full annotated code in [our examples repository](https://github.com/Hyle-org/examples/blob/simple_erc20/simple-erc20/host/src/main.rs). -### Posting proofs of your payload to settle it +#### Setup commands and CLI -Hylé requires specific variables in the output of the proof to process the transaction. Check the [smart contract ABI](../general-doc/smart-contract-abi.md) for more details. +Set up commands and CLI. You need a unique `contract_name`: here, we use `"simple_token"`. -Once your program conforms to the ABI, you can generate proofs and send them to Hylé. +```rs +struct Cli { + #[command(subcommand)] + command: Commands, -Each payload of a transaction must be proven separately for now, so you need to specify the index of the payload you're proving. + #[clap(long, short)] + reproducible: bool, -```bash -hyled proof [tx_hash] [contract_name] [proof] -``` + #[arg(long, default_value = "http://localhost:4321")] + pub host: String, -In the case of the Collatz Conjecture program, we can now prove our state transition from 1 to 5. + #[arg(long, default_value = "simple_token")] + pub contract_name: String, +} -```bash -# Make sure the name matches the contract you registered -hyled proof [tx_hash] collatz [path_to_proof] +#[derive(Subcommand)] +enum Commands { + Register { + supply: u128, + }, + Transfer { + from: String, + to: String, + amount: u128, + }, + Balance { + of: String, + }, +} ``` -Hylé will now verify your proof. After verification, your transaction is settled, updating the state of the contract. +#### Registering the contract + +Set up information about your contract. To register the contract, you'll need: + +- `owner`: we put "examples" as the `owner`, but you can put anything you like. This field is currently not leveraged; it will be in future versions. +- `verifier`: for this example, the verifier is `risc0` +- `program_id`: RISC Zero programs are identified by their image ID, without a prefix. +- `state_digest`: usually a MerkleRootHash of the contract's initial state. For this example, we use a hexadecimal representation of the state encoded in binary format. The state digest cannot be empty, even if your app is stateless. +- `contract_name` as set up above. + +```rs +Commands::Register { supply } => { + // Build initial state of contract + let initial_state = Token::new(supply, format!("faucet.{}", contract_name).into()); + println!("Initial state: {:?}", initial_state); + + // Send the transaction to register the contract + let register_tx = RegisterContractTransaction { + owner: "examples".to_string(), + verifier: "risc0".into(), + program_id: sdk::ProgramId(sdk::to_u8_array(&GUEST_ID).to_vec()), + state_digest: initial_state.as_digest(), + contract_name: contract_name.clone().into(), + }; + let res = client + .send_tx_register_contract(®ister_tx) + .await + .unwrap() + .text() + .await + .unwrap(); + + println!("✅ Register contract tx sent. Tx hash: {}", res); + } +``` -### Verifying your contract's state +In [the explorer](https://hyleou.hyle.eu/), this will look like this: -Your contract's state digest is visible at: `https://hyleou.hyle.eu/contract/$CONTRACT_NAME` +```rs +{ + "tx_hash": "321b7a4b2228904fc92979117e7c2aa6740648e339c97986141e53d967e08097", + "owner": "examples", + "verifier": "risc0", + "program_id":"e085fa46f2e62d69897fc77f379c0ba1d252d7285f84dbcc017957567d1e812f", + "state_digest": "fd00e876481700000001106661756365742e687964656e74697479fd00e876481700000000", + "contract_name": "simple_token" +} +``` -You can choose to run the command below instead: +#### Create blob transaction -```bash -hyled state collatz +```rs + let blob_tx = BlobTransaction { + identity: from.into(), + blobs, + }; + + // Send the blob transaction + let blob_tx_hash = client.send_tx_blob(&blob_tx).await.unwrap(); + println!("✅ Blob tx sent. Tx hash: {}", blob_tx_hash); ``` + +#### Prove the transaction + +Hylé transactions are settled in two steps, following [pipelined proving principles](../general-doc/pipelined-proving.md). After this step, your transaction is sequenced, but not settled. + +For the transaction to be settled, it needs to be proven. You'll start with building the contract input, specifying: + +- the initial state as set above +- the identity of the transaction initiator +- the transaction hash, which can be found in the explorer after sequencing (currently, this can be ignored; it will be necessary after an upcoming update) +- information about the blobs. + - private input for proof generation in `private_blob` + - `blobs`: full list of blobs in the transaction (must match the blob transaction) + - `index`: each blob of a transaction must be proven separately for now, so you need to specify the index of the blob you're proving. + +```rs + // Build the contract input + let inputs = ContractInput:: { + initial_state, + identity: from.clone().into(), + tx_hash: "".into(), + private_blob: sdk::BlobData(vec![]), + blobs: blobs.clone(), + index: sdk::BlobIndex(0), + }; + + // Generate the zk proof + let receipt = prove(cli.reproducible, inputs).unwrap(); + + let proof_tx = ProofTransaction { + blob_tx_hash, + proof: ProofData::Bytes(borsh::to_vec(&receipt).expect("Unable to encode receipt")), + contract_name: contract_name.clone().into(), + }; + + // Send the proof transaction + let proof_tx_hash = client + .send_tx_proof(&proof_tx) + .await + .unwrap() + .text() + .await + .unwrap(); + println!("✅ Proof tx sent. Tx hash: {}", proof_tx_hash); +``` + +Check the full annotated code in [our GitHub example](https://github.com/Hyle-org/examples/blob/simple_erc20/simple-erc20/host/src/main.rs). \ No newline at end of file From 39cfedcbdd2c35a2afd0df5ecf3acb01613906f7 Mon Sep 17 00:00:00 2001 From: Alex Sirac Date: Thu, 26 Dec 2024 18:07:10 +0100 Subject: [PATCH 5/6] note to update links when PR is approved --- docs/developers/getting-started/your-first-smart-contract.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/developers/getting-started/your-first-smart-contract.md b/docs/developers/getting-started/your-first-smart-contract.md index 4d5cf79..3dff3c6 100644 --- a/docs/developers/getting-started/your-first-smart-contract.md +++ b/docs/developers/getting-started/your-first-smart-contract.md @@ -1,5 +1,6 @@ # Your first smart contract + This guide will walk you through creating and deploying your first token transfer contract using Hylé's tools and infrastructure. We'll use [our sample token transfer example](https://github.com/Hyle-org/examples/tree/simple_erc20/simple-erc20) as the basis for this tutorial. For an in-depth understanding of smart contracts, check out our [anatomy of a smart contract](../general-doc/anatomy-smart-contracts.md). From 2e3effbae3897dc2d0a0550243f3717517e04c6b Mon Sep 17 00:00:00 2001 From: Alex Sirac Date: Fri, 27 Dec 2024 09:51:18 +0100 Subject: [PATCH 6/6] live testing --- docs/developers/getting-started/devnet.md | 2 +- docs/developers/getting-started/your-first-smart-contract.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developers/getting-started/devnet.md b/docs/developers/getting-started/devnet.md index f16f088..538f4bc 100644 --- a/docs/developers/getting-started/devnet.md +++ b/docs/developers/getting-started/devnet.md @@ -24,7 +24,7 @@ docker run -v ./db:/hyle/data -e HYLE_RUN_INDEXER=false -e HYLE_REST=0.0.0.0:432 If you run into an error, you may want to add the `--privileged` flag: ```bash -docker run --privileged -v ./db:/hyle/data -e HYLE_RUN_INDEXER=false -p 4321:4321 -p 1234:1234 ghcr.io/hyle-org/hyle:latest +docker run --privileged -v ./db:/hyle/data -e HYLE_RUN_INDEXER=false -e HYLE_REST=0.0.0.0:4321 -p 4321:4321 -p 1234:1234 ghcr.io/hyle-org/hyle:latest ``` If you want to run with an indexer with `HYLE_RUN_INDEXER=true`, you will need a running PostgreSQL server. You can set it up with Docker: diff --git a/docs/developers/getting-started/your-first-smart-contract.md b/docs/developers/getting-started/your-first-smart-contract.md index 3dff3c6..7272ca1 100644 --- a/docs/developers/getting-started/your-first-smart-contract.md +++ b/docs/developers/getting-started/your-first-smart-contract.md @@ -72,7 +72,7 @@ cargo run -- balance bob.simple_token See your contract's state digest at: `https://hyleou.hyle.eu/contract/$CONTRACT_NAME`. -See your transaction on Hylé's explorer: `https://hyleou.hyle.eu/transaction/$TX_HASH`. +See your transaction on Hylé's explorer: `https://hyleou.hyle.eu/tx/$TX_HASH`. ## Detailed information