From 48e6c83719396a9572c351810e51732552e4b611 Mon Sep 17 00:00:00 2001 From: Blazej Kolad Date: Fri, 1 Dec 2023 09:07:45 +0100 Subject: [PATCH] MockDa support for `demo-rollup` (#1193) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add mock config * Update mock-da readme * Test mock-da in the CI * Fix readme * Rneame config * Update readme * Rename job * Update readme * Update table of contents * cleanup * Fox ci * Code review feedback * Fix readme * Add celestia info * Update examples/demo-rollup/README.md Co-authored-by: Cem Özer * Update readme --------- Co-authored-by: Cem Özer --- .github/workflows/rust.yml | 36 +- examples/demo-rollup/Makefile | 28 +- examples/demo-rollup/README.md | 154 ++------ examples/demo-rollup/README_CELESTIA.md | 361 ++++++++++++++++++ ...onfig.toml => celestia_rollup_config.toml} | 0 examples/demo-rollup/mock_rollup_config.toml | 16 + examples/demo-rollup/src/main.rs | 8 +- .../demo-tests/{ => celestia}/accounts.json | 0 .../demo-tests/{ => celestia}/bank.json | 0 .../{ => celestia}/chain_state.json | 0 .../demo-tests/{ => celestia}/evm.json | 0 .../demo-tests/{ => celestia}/nft.json | 0 .../{ => celestia}/sequencer_registry.json | 0 .../{ => celestia}/value_setter.json | 0 .../genesis/demo-tests/mock/accounts.json | 3 + .../genesis/demo-tests/mock/bank.json | 17 + .../genesis/demo-tests/mock/chain_state.json | 7 + .../genesis/demo-tests/mock/evm.json | 25 ++ .../genesis/demo-tests/mock/nft.json | 1 + .../demo-tests/mock/sequencer_registry.json | 9 + .../genesis/demo-tests/mock/value_setter.json | 3 + 21 files changed, 522 insertions(+), 146 deletions(-) create mode 100644 examples/demo-rollup/README_CELESTIA.md rename examples/demo-rollup/{rollup_config.toml => celestia_rollup_config.toml} (100%) create mode 100644 examples/demo-rollup/mock_rollup_config.toml rename examples/test-data/genesis/demo-tests/{ => celestia}/accounts.json (100%) rename examples/test-data/genesis/demo-tests/{ => celestia}/bank.json (100%) rename examples/test-data/genesis/demo-tests/{ => celestia}/chain_state.json (100%) rename examples/test-data/genesis/demo-tests/{ => celestia}/evm.json (100%) rename examples/test-data/genesis/demo-tests/{ => celestia}/nft.json (100%) rename examples/test-data/genesis/demo-tests/{ => celestia}/sequencer_registry.json (100%) rename examples/test-data/genesis/demo-tests/{ => celestia}/value_setter.json (100%) create mode 100644 examples/test-data/genesis/demo-tests/mock/accounts.json create mode 100644 examples/test-data/genesis/demo-tests/mock/bank.json create mode 100644 examples/test-data/genesis/demo-tests/mock/chain_state.json create mode 100644 examples/test-data/genesis/demo-tests/mock/evm.json create mode 100644 examples/test-data/genesis/demo-tests/mock/nft.json create mode 100644 examples/test-data/genesis/demo-tests/mock/sequencer_registry.json create mode 100644 examples/test-data/genesis/demo-tests/mock/value_setter.json diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dfc2bc20d..d3fe5cd05 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -354,14 +354,47 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 - run: npm install -g doctoc - - name: Update table of contents + - name: Update table of contents for mock-da run: doctoc README.md --github --notitle working-directory: ./examples/demo-rollup + - name: Update table of contents for celestia-da + run: doctoc README_CELESTIA.md --github --notitle + working-directory: ./examples/demo-rollup - name: Check table of contents # Exit status 0 means no changes were made, so the table of contents is # up to date. run: git diff --exit-code check-demo-rollup-bash-commands: + runs-on: buildjet-4vcpu-ubuntu-2204 + needs: nextest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v3 + - uses: rui314/setup-mold@v1 + - name: Install Protoc + uses: arduino/setup-protoc@v2 + with: + version: "23.2" + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install cargo-risczero + uses: taiki-e/install-action@v2 + with: + tool: cargo-risczero@0.19 + - name: Install risc0-zkvm toolchain # Use the risc0 cargo extension to install the risc0 std library for the current toolchain + run: cargo risczero install + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Install Rust + run: rustup show + - uses: Swatinem/rust-cache@v2 + with: + cache-provider: "buildjet" + save-if: ${{ github.ref == 'refs/heads/nightly' }} + - name: Compile README.md to Bash + run: cargo run --bin bashtestmd -- --input examples/demo-rollup/README_CELESTIA.md --output demo-rollup-readme.sh --tag test-ci + - run: cat demo-rollup-readme.sh + - run: chmod +x demo-rollup-readme.sh && ./demo-rollup-readme.sh + check-demo-rollup-bash-commands-mock-da: runs-on: buildjet-4vcpu-ubuntu-2204 needs: nextest timeout-minutes: 60 @@ -391,6 +424,7 @@ jobs: run: cargo run --bin bashtestmd -- --input examples/demo-rollup/README.md --output demo-rollup-readme.sh --tag test-ci - run: cat demo-rollup-readme.sh - run: chmod +x demo-rollup-readme.sh && ./demo-rollup-readme.sh + validate-packages-to-publish-yml: runs-on: ubuntu-latest steps: diff --git a/examples/demo-rollup/Makefile b/examples/demo-rollup/Makefile index 87d1164d1..e03102d83 100644 --- a/examples/demo-rollup/Makefile +++ b/examples/demo-rollup/Makefile @@ -40,7 +40,7 @@ stop: check-docker @$(compose_down) # clean up rollup data and stop the celestia network -clean: stop clean-rollup-db +clean: stop clean-celestia-rollup-db # listen to celestia network logs compose-logs: check-docker @@ -64,13 +64,13 @@ wait-compose-ready: # update the rollup configuration with local network params update-config: wait-compose-ready ifeq ($(shell uname -s),Darwin) - @sed -i '' 's/^\(celestia_rpc_auth_token = \)"[^"]*"/\1"$(get_auth)"/' rollup_config.toml - @sed -i '' 's#^\(celestia_rpc_address = \)"[^"]*"#\1"http://127.0.0.1:$(RPC_PORT)"#' rollup_config.toml - @sed -i '' 's#^\(start_height = \)[0-9]*#\1$(START_HEIGHT)#' rollup_config.toml + @sed -i '' 's/^\(celestia_rpc_auth_token = \)"[^"]*"/\1"$(get_auth)"/' celestia_rollup_config.toml + @sed -i '' 's#^\(celestia_rpc_address = \)"[^"]*"#\1"http://127.0.0.1:$(RPC_PORT)"#' celestia_rollup_config.toml + @sed -i '' 's#^\(start_height = \)[0-9]*#\1$(START_HEIGHT)#' celestia_rollup_config.toml else - @sed -i 's/^\(celestia_rpc_auth_token = \)"[^"]*"/\1"$(get_auth)"/' rollup_config.toml - @sed -i 's#^\(celestia_rpc_address = \)"[^"]*"#\1"http://127.0.0.1:$(RPC_PORT)"#' rollup_config.toml - @sed -i 's#^\(start_height = \)[0-9]*#\1$(START_HEIGHT)#' rollup_config.toml + @sed -i 's/^\(celestia_rpc_auth_token = \)"[^"]*"/\1"$(get_auth)"/' celestia_rollup_config.toml + @sed -i 's#^\(celestia_rpc_address = \)"[^"]*"#\1"http://127.0.0.1:$(RPC_PORT)"#' celestia_rollup_config.toml + @sed -i 's#^\(start_height = \)[0-9]*#\1$(START_HEIGHT)#' celestia_rollup_config.toml endif build-sov-cli: @@ -91,11 +91,21 @@ test-create-token: set-rpc-url test-generate-create-token-tx import-keys remove-insecure-keys: build-sov-cli $(SOV_CLI_REL_PATH) keys remove by-address sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94 -clean-rollup-db: - $(eval path := ./$(shell awk -F'=' '/^path/ {print $$2}' rollup_config.toml | tr -d '[:space:]"\n')) +clean-celestia-rollup-db: + $(eval path := ./$(shell awk -F'=' '/^path/ {print $$2}' celestia_rollup_config.toml | tr -d '[:space:]"\n')) @if [ -z "${path}" ] || [ "${path}" = "./" ]; then \ echo "Path is empty or too short, not safe to remove"; \ exit 1; \ fi @echo removing rollup database "${path}" rm -rf "${path}" + + +clean-mock-rollup-db: + $(eval path := ./$(shell awk -F'=' '/^path/ {print $$2}' mock_rollup_config.toml | tr -d '[:space:]"\n')) + @if [ -z "${path}" ] || [ "${path}" = "./" ]; then \ + echo "Path is empty or too short, not safe to remove"; \ + exit 1; \ + fi + @echo removing rollup database "${path}" + rm -rf "${path}" \ No newline at end of file diff --git a/examples/demo-rollup/README.md b/examples/demo-rollup/README.md index 0d4f58b20..01bcf8a2c 100644 --- a/examples/demo-rollup/README.md +++ b/examples/demo-rollup/README.md @@ -1,7 +1,5 @@ # Demo Rollup ![Time - ~5 mins](https://img.shields.io/badge/Time-~5_mins-informational) -This is a demo full node running a simple Sovereign SDK rollup on [Celestia](https://celestia.org/). -


@@ -23,15 +21,11 @@ This is a demo full node running a simple Sovereign SDK rollup on [Celestia](htt - [Start the Rollup Full Node](#start-the-rollup-full-node) - [Sanity Check: Creating a Token](#sanity-check-creating-a-token) - [How to Submit Transactions](#how-to-submit-transactions) + - [How to Submit Transactions](#how-to-submit-transactions-1) - [1. Build `sov-cli`](#1-build-sov-cli) - [2. Generate the Transaction](#2-generate-the-transaction) - - [3. Submit the Transaction(s)](#3-submit-the-transactions) - - [4. Verify the Token Supply](#4-verify-the-token-supply) - - [Makefile](#makefile) - - [Remote setup](#remote-setup) -- [How to Customize This Example](#how-to-customize-this-example) - - [1. Initialize the DA Service](#1-initialize-the-da-service) - - [2. Run the Main Loop](#2-run-the-main-loop) + - [Submit the Transaction(s)](#submit-the-transactions) + - [Verify the Token Supply](#verify-the-token-supply) - [Disclaimer](#disclaimer) - [Interacting with your Node via RPC](#interacting-with-your-node-via-rpc) - [Key Concepts](#key-concepts) @@ -41,12 +35,12 @@ This is a demo full node running a simple Sovereign SDK rollup on [Celestia](htt - [`ledger_getBatches`](#ledger_getbatches) - [`ledger_getTransactions`](#ledger_gettransactions) - [`ledger_getEvents`](#ledger_getevents) +- [Testing with specific DA layers](#testing-with-specific-da-layers) - [License](#license) ## What is This? - This demo shows how to integrate a State Transition Function (STF) with a Data Availability (DA) layer and a zkVM to create a full zk-rollup. The code in this repository corresponds to running a full-node of the rollup, which executes every transaction. @@ -60,87 +54,45 @@ understand how to build your own state transition function, check out at the doc If you are looking for a simple rollup with minimal dependencies as a starting point, please have a look here: [sov-rollup-starter](https://github.com/Sovereign-Labs/sov-rollup-starter/) -### Run a local DA layer instance - -1. Install Docker: . - -2. Follow [this guide](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic) -to authorize yourself in github's container registry. (we use original celestia images which they publish in ghcr) -```shell -# this has to be ran only once, unless your token expires -$ echo $MY_PERSONAL_GITHUB_TOKEN | docker login ghcr.io -u $MY_GITHUB_USERNAME --password-stdin -``` +### Run a local DA layer instance +This setup works with an in-memory DA that is easy to set up for testing purposes. -3. Switch to the `examples/demo-rollup` directory (which is where this `README.md` is located!), and compile the application: +### Start the Rollup Full Node +1. Switch to the `examples/demo-rollup` and compile the application: ```shell,test-ci $ cd examples/demo-rollup/ $ cargo build --bins ``` -4. Spin up a local Celestia instance as your DA layer. We've built a small Makefile to simplify that process: - -```sh,test-ci,bashtestmd:long-running,bashtestmd:wait-until=genesis.json -$ make clean -# Make sure to run `make stop` or `make clean` when you're done with this demo! -$ make start -``` - -If interested, you can check out what the Makefile does [here](#Makefile). - The above command will also modify some configuration files: - +2. Clean up the existing database. +Makefile to simplify that process: ```sh,test-ci -$ git status -.. -.. - modified: rollup_config.toml +$ make clean-mock-rollup-db ``` -### Start the Rollup Full Node - -Now run the demo-rollup full node, as shown below. You will see it consuming blocks from the Celestia node running inside Docker: - +3. Now run the demo-rollup full node, as shown below. ```sh,test-ci,bashtestmd:long-running -# Make sure you're still in the examples/demo-rollup directory. $ cargo run -2023-06-07T10:03:25.473920Z INFO sov_celestia_adapter::da_service: Fetching header at height=1... -2023-06-07T10:03:25.496853Z INFO sov_demo_rollup: Received 0 blobs -2023-06-07T10:03:25.497700Z INFO sov_demo_rollup: Requesting data for height 2 and prev_state_root 0xa96745d3184e54d098982daf44923d84c358800bd22c1864734ccb978027a670 -2023-06-07T10:03:25.497719Z INFO sov_celestia_adapter::da_service: Fetching header at height=2... -2023-06-07T10:03:25.505412Z INFO sov_demo_rollup: Received 0 blobs -2023-06-07T10:03:25.505992Z INFO sov_demo_rollup: Requesting data for height 3 and prev_state_root 0xa96745d3184e54d098982daf44923d84c358800bd22c1864734ccb978027a670 -2023-06-07T10:03:25.506003Z INFO sov_celestia_adapter::da_service: Fetching header at height=3... -2023-06-07T10:03:25.511237Z INFO sov_demo_rollup: Received 0 blobs -2023-06-07T10:03:25.511815Z INFO sov_demo_rollup: Requesting data for height 4 and prev_state_root 0xa96745d3184e54d098982daf44923d84c358800bd22c1864734ccb978027a670 ``` - Leave it running while you proceed with the rest of the demo. -### Sanity Check: Creating a Token +### Sanity Check: Creating a Token After switching to a new terminal tab, let's submit our first transaction by creating a token: ```sh,test-ci $ make test-create-token ``` -...wait a few seconds and you will see the transaction receipt in the output of the demo-rollup full node: - -```sh -2023-07-12T15:04:52.291073Z INFO sov_celestia_adapter::da_service: Fetching header at height=31... -2023-07-12T15:05:02.304393Z INFO sov_demo_rollup: Received 1 blobs at height 31 -2023-07-12T15:05:02.305257Z INFO sov_demo_rollup: blob #0 at height 31 with blob_hash 0x4876c2258b57104356efa4630d3d9f901ccfda5dde426ba8aef81d4a3e357c79 has been applied with #1 transactions, sequencer outcome Rewarded(0) -2023-07-12T15:05:02.305280Z INFO sov_demo_rollup: tx #0 hash: 0x1e1892f77cf42c0abd2ca2acdd87eabb9aa65ec7497efea4ff9f5f33575f881a result Successful -2023-07-12T15:05:02.310714Z INFO sov_demo_rollup: Requesting data for height 32 and prev_state_root 0xae87adb5291d3e645c09ff74dfe3580a25ef0b893b67f09eb58ae70c1bf135c2 -``` - ### How to Submit Transactions +The `make test-create-token` command above was useful to test if everything is running correctly. Now let's get a better understanding of how to create and submit a transaction +### How to Submit Transactions The `make test-create-token` command above was useful to test if everything is running correctly. Now let's get a better understanding of how to create and submit a transaction. #### 1. Build `sov-cli` - You'll need the `sov-cli` binary in order to create transactions. Build it with these commands: ```bash,test-ci,bashtestmd:compare-output @@ -269,6 +221,7 @@ Options: Let's go ahead and import the transaction into the wallet + ```bash,test-ci,bashtestmd:compare-output $ cargo run --bin sov-cli -- transactions import from-file bank --path ../test-data/requests/transfer.json Adding the following transaction to batch: @@ -285,10 +238,7 @@ Adding the following transaction to batch: } ``` -This output indicates that the wallet has saved the transaction details for later signing. - -#### 3. Submit the Transaction(s) - +#### Submit the Transaction(s) You now have a batch with a single transaction in your wallet. If you want to submit any more transactions as part of this batch, you can import them now. Finally, let's submit your transaction to the rollup. @@ -296,76 +246,12 @@ batch, you can import them now. Finally, let's submit your transaction to the ro $ cargo run --bin sov-cli rpc submit-batch by-address sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94 ``` -This command will use your default private key. - -#### 4. Verify the Token Supply - +#### Verify the Token Supply ```bash,test-ci,bashtestmd:compare-output $ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"bank_supplyOf","params":["sov1zdwj8thgev2u3yyrrlekmvtsz4av4tp3m7dm5mx5peejnesga27svq9m72"],"id":1}' http://127.0.0.1:12345 {"jsonrpc":"2.0","result":{"amount":1000},"id":1} ``` -### Makefile - -`demo-rollup/Makefile` automates a number of things for convenience: - -- Starts docker compose with a Celestia network for a local setup -- `make start`: - - Performs a number of checks to ensure services are not already running - - Starts the docker compose setup - - Exposes the RPC port `26658` - - Waits until the container is started - - Sets up the config - - `examples/demo-rollup/rollup_config.toml` is modified - - - `start_height` is set to `3`, which is the block in which sequencers are funded with credits - - `celestia_rpc_auth_token` is set to the auth token exposed by sequencer (in /docker/credentials directory) - - `celestia_rpc_address` is set to point to `127.0.0.1` and the `RPC_PORT` -- `make stop`: - - Shuts down the Celestia docker compose setup, if running. - - Deletes all contents of the demo-rollup database. -- `make clean`: - - Stops any running containers with the name `sov-celestia-local` and also removes them - - Removes `demo-data` (or the configured path of the rollup database from rollup_config.toml) - -### Remote setup - -> 🚧 This feature is under development! 🚧 - -The above setup runs Celestia node locally to avoid any external network dependencies and to speed up development. Soon, the Sovereign SDK will also support connecting to the Celestia testnet using a Celestia light node running on your machine. - -## How to Customize This Example - -Any time you change out the state transition function, zkVM, or DA layer of your rollup, you'll -need to tweak this full-node code. At the very least, you'll need to modify the dependencies. In most cases, -your full node will also need to be aware of the STF's initialization logic, and how it exposes RPC. - -Given that constraint, we won't try to give you specific instructions for supporting every imaginable -combination of DA layers and State Transition Functions. Instead, we'll explain at a high level what -tasks a full-node needs to accomplish. - -### 1. Initialize the DA Service - -The first _mandatory_ step is to initialize a DA service, which allows the full node implementation to -communicate with the DA layer's RPC endpoints. - -If you're using Celestia as your DA layer, you can follow the instructions at the end -of this document to set up a local full node, or connect to -a remote node. Whichever option you pick, simply place the URL and authentication token -in the `rollup_config.toml` file and it will be -automatically picked up by the node implementation. For this tutorial, the Makefile below (which also helps start a local Celestia instance) handles this step for you. - -### 2. Run the Main Loop - -The full node implements a simple loop for processing blocks. The workflow is: - -1. Fetch slot data from the DA service -2. Run `stf.begin_slot()` -3. Iterate over the blobs, running `apply_batch` -4. Run `stf.end_slot()` - -In this demo, we also keep a `ledger_db`, which stores information -related to the chain's history - batches, transactions, receipts, etc. - ## Disclaimer > ⚠️ Warning! ⚠️ @@ -485,6 +371,10 @@ $ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method" This response indicates that event `1` has not been emitted yet. +## Testing with specific DA layers +Check [here](./README_CELESTIA.md) if you want to run with dockerized local Celestia instance. + + ## License Licensed under the [Apache License, Version 2.0](../../LICENSE). diff --git a/examples/demo-rollup/README_CELESTIA.md b/examples/demo-rollup/README_CELESTIA.md new file mode 100644 index 000000000..eb79b4287 --- /dev/null +++ b/examples/demo-rollup/README_CELESTIA.md @@ -0,0 +1,361 @@ +# Demo Rollup ![Time - ~5 mins](https://img.shields.io/badge/Time-~5_mins-informational) + +This is a demo full node running a simple Sovereign SDK rollup on [Celestia](https://celestia.org/). + +

+ +
+ Stuck, facing problems, or unsure about something? +
+ Join our Discord and ask your questions in #support! +

+ +You can follow the steps below to run the demo rollup on a local Celestia devnet instance. However, due to numerous users encountering failures because of basic local setup or Docker issues, we strongly suggest using the plain demo rollup with mock Data Availability (DA) for testing. +We are developing more robust tooling to enable seamless deployment of rollups on any DA layer. Until this tooling is available, we will only support our early partners in deploying on devnets. + +#### Table of Contents + + + + + + +- [What is This?](#what-is-this) +- [Getting Started](#getting-started) + - [Run a local DA layer instance](#run-a-local-da-layer-instance) + - [Start the Rollup Full Node](#start-the-rollup-full-node) + - [Sanity Check: Creating a Token](#sanity-check-creating-a-token) + - [How to Submit Transactions](#how-to-submit-transactions) + - [1. Build `sov-cli`](#1-build-sov-cli) + - [2. Generate the Transaction](#2-generate-the-transaction) + - [3. Submit the Transaction(s)](#3-submit-the-transactions) + - [4. Verify the Token Supply](#4-verify-the-token-supply) + - [Makefile](#makefile) + - [Remote setup](#remote-setup) +- [How to Customize This Example](#how-to-customize-this-example) + - [1. Initialize the DA Service](#1-initialize-the-da-service) + - [2. Run the Main Loop](#2-run-the-main-loop) + + + +## What is This? + +This demo shows how to integrate a State Transition Function (STF) with a Data Availability (DA) layer and a zkVM to create a full +zk-rollup. The code in this repository corresponds to running a full-node of the rollup, which executes +every transaction. + +By swapping out or modifying the imported state transition function, you can customize +this example full-node to run arbitrary logic. +This particular example relies on the state transition exported by [`demo-stf`](../demo-rollup/stf/). If you want to +understand how to build your own state transition function, check out at the docs in that package. + +## Getting Started +If you are looking for a simple rollup with minimal dependencies as a starting point, please have a look here: +[sov-rollup-starter](https://github.com/Sovereign-Labs/sov-rollup-starter/) + +### Run a local DA layer instance + +1. Install Docker: . + +2. Follow [this guide](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic) +to authorize yourself in github's container registry. (we use original celestia images which they publish in ghcr) + +```shell +# this has to be ran only once, unless your token expires +$ echo $MY_PERSONAL_GITHUB_TOKEN | docker login ghcr.io -u $MY_GITHUB_USERNAME --password-stdin +``` + +3. Switch to the `examples/demo-rollup` directory (which is where this `README.md` is located!), and compile the application: + +```shell,test-ci +$ cd examples/demo-rollup/ +$ cargo build --bins +``` + +4. Spin up a local Celestia instance as your DA layer. We've built a small Makefile to simplify that process: + +```sh,test-ci,bashtestmd:long-running,bashtestmd:wait-until=genesis.json +$ make clean +# Make sure to run `make stop` or `make clean` when you're done with this demo! +$ make start +``` + +If interested, you can check out what the Makefile does [here](#Makefile). + The above command will also modify some configuration files: + +```sh,test-ci +$ git status +.. +.. + modified: rollup_config.toml +``` + +### Start the Rollup Full Node + +Now run the demo-rollup full node, as shown below. You will see it consuming blocks from the Celestia node running inside Docker: + +```sh,test-ci,bashtestmd:long-running +# Make sure you're still in the examples/demo-rollup directory. +$ cargo run -- --da-layer celestia --rollup-config-path celestia_rollup_config.toml +2023-06-07T10:03:25.473920Z INFO sov_celestia_adapter::da_service: Fetching header at height=1... +2023-06-07T10:03:25.496853Z INFO sov_demo_rollup: Received 0 blobs +2023-06-07T10:03:25.497700Z INFO sov_demo_rollup: Requesting data for height 2 and prev_state_root 0xa96745d3184e54d098982daf44923d84c358800bd22c1864734ccb978027a670 +2023-06-07T10:03:25.497719Z INFO sov_celestia_adapter::da_service: Fetching header at height=2... +2023-06-07T10:03:25.505412Z INFO sov_demo_rollup: Received 0 blobs +2023-06-07T10:03:25.505992Z INFO sov_demo_rollup: Requesting data for height 3 and prev_state_root 0xa96745d3184e54d098982daf44923d84c358800bd22c1864734ccb978027a670 +2023-06-07T10:03:25.506003Z INFO sov_celestia_adapter::da_service: Fetching header at height=3... +2023-06-07T10:03:25.511237Z INFO sov_demo_rollup: Received 0 blobs +2023-06-07T10:03:25.511815Z INFO sov_demo_rollup: Requesting data for height 4 and prev_state_root 0xa96745d3184e54d098982daf44923d84c358800bd22c1864734ccb978027a670 +``` + +Leave it running while you proceed with the rest of the demo. + +### Sanity Check: Creating a Token + +After switching to a new terminal tab, let's submit our first transaction by creating a token: + +```sh,test-ci +$ make test-create-token +``` + +...wait a few seconds and you will see the transaction receipt in the output of the demo-rollup full node: + +```sh +2023-07-12T15:04:52.291073Z INFO sov_celestia_adapter::da_service: Fetching header at height=31... +2023-07-12T15:05:02.304393Z INFO sov_demo_rollup: Received 1 blobs at height 31 +2023-07-12T15:05:02.305257Z INFO sov_demo_rollup: blob #0 at height 31 with blob_hash 0x4876c2258b57104356efa4630d3d9f901ccfda5dde426ba8aef81d4a3e357c79 has been applied with #1 transactions, sequencer outcome Rewarded(0) +2023-07-12T15:05:02.305280Z INFO sov_demo_rollup: tx #0 hash: 0x1e1892f77cf42c0abd2ca2acdd87eabb9aa65ec7497efea4ff9f5f33575f881a result Successful +2023-07-12T15:05:02.310714Z INFO sov_demo_rollup: Requesting data for height 32 and prev_state_root 0xae87adb5291d3e645c09ff74dfe3580a25ef0b893b67f09eb58ae70c1bf135c2 +``` + +### How to Submit Transactions + +The `make test-create-token` command above was useful to test if everything is running correctly. Now let's get a better understanding of how to create and submit a transaction. + +#### 1. Build `sov-cli` + +You'll need the `sov-cli` binary in order to create transactions. Build it with these commands: + +```bash,test-ci,bashtestmd:compare-output +# Make sure you're still in `examples/demo-rollup` +$ cargo run --bin sov-cli -- --help +Usage: sov-cli + +Commands: + transactions Generate, sign, and send transactions + keys View and manage keys associated with this wallet + rpc Query the current state of the rollup and send transactions + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help + -V, --version Print version +``` + +Each transaction that we want to submit is a member of the `CallMessage` enum defined as part of creating a module. For example, let's consider the `Bank` module's `CallMessage`: + +```rust +use sov_bank::CallMessage::Transfer; +use sov_bank::Coins; +use sov_bank::Amount; + +pub enum CallMessage { + /// Creates a new token with the specified name and initial balance. + CreateToken { + /// Random value used to create a unique token address. + salt: u64, + /// The name of the new token. + token_name: String, + /// The initial balance of the new token. + initial_balance: Amount, + /// The address of the account that the new tokens are minted to. + minter_address: C::Address, + /// Authorized minter list. + authorized_minters: Vec, + }, + + /// Transfers a specified amount of tokens to the specified address. + Transfer { + /// The address to which the tokens will be transferred. + to: C::Address, + /// The amount of tokens to transfer. + coins: Coins::, + }, + + /// Burns a specified amount of tokens. + Burn { + /// The amount of tokens to burn. + coins: Coins::, + }, + + /// Mints a specified amount of tokens. + Mint { + /// The amount of tokens to mint. + coins: Coins::, + /// Address to mint tokens to + minter_address: C::Address, + }, + + /// Freeze a token so that the supply is frozen + Freeze { + /// Address of the token to be frozen + token_address: C::Address, + }, +} +``` + +In the above snippet, we can see that `CallMessage` in `Bank` supports five different types of calls. The `sov-cli` has the ability to parse a JSON file that aligns with any of these calls and subsequently serialize them. The structure of the JSON file, which represents the call, closely mirrors that of the Enum member. You can view the relevant JSON Schema for `Bank` [here](../../module-system/module-schemas/schemas/sov-bank.json) Consider the `Transfer` message as an example: + +```rust +use sov_bank::Coins; + +struct Transfer { + /// The address to which the tokens will be transferred. + to: C::Address, + /// The amount of tokens to transfer. + coins: Coins, +} +``` + +Here's an example of a JSON representing the above call: + +```json +{ + "Transfer": { + "to": "sov1zgfpyysjzgfpyysjzgfpyysjzgfpyysjzgfpyysjzgfpyysjzgfqve8h6h", + "coins": { + "amount": 200, + "token_address": "sov1zdwj8thgev2u3yyrrlekmvtsz4av4tp3m7dm5mx5peejnesga27svq9m72" + } + } +} +``` + +#### 2. Generate the Transaction + +The JSON above is the contents of the file [`examples/test-data/requests/transfer.json`](../../examples/test-data/requests/transfer.json). We'll use this transaction as our example for the rest of the tutorial. In order to send the transaction, we need to perform 2 operations: + +- Import the transaction data into the wallet +- Sign and submit the transaction + +Note: we're able to make a `Transfer` call here because we already created the token as part of the sanity check above, using `make test-create-token`. + +To generate transactions you can use the `transactions import from-file` subcommand, as shown below: + +```bash,test-ci,bashtestmd:compare-output +$ cargo run --bin sov-cli -- transactions import from-file -h +Import a transaction from a JSON file at the provided path + +Usage: sov-cli transactions import from-file + +Commands: + bank A subcommand for the `bank` module + sequencer-registry A subcommand for the `sequencer_registry` module + value-setter A subcommand for the `value_setter` module + accounts A subcommand for the `accounts` module + nft A subcommand for the `nft` module + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help +``` + +Let's go ahead and import the transaction into the wallet + +```bash,test-ci,bashtestmd:compare-output +$ cargo run --bin sov-cli -- transactions import from-file bank --path ../test-data/requests/transfer.json +Adding the following transaction to batch: +{ + "bank": { + "Transfer": { + "to": "sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94", + "coins": { + "amount": 200, + "token_address": "sov1zdwj8thgev2u3yyrrlekmvtsz4av4tp3m7dm5mx5peejnesga27svq9m72" + } + } + } +} +``` + +This output indicates that the wallet has saved the transaction details for later signing. + +#### 3. Submit the Transaction(s) + +You now have a batch with a single transaction in your wallet. If you want to submit any more transactions as part of this +batch, you can import them now. Finally, let's submit your transaction to the rollup. + +```bash,test-ci +$ cargo run --bin sov-cli rpc submit-batch by-address sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94 +``` + +This command will use your default private key. + +#### 4. Verify the Token Supply + +```bash,test-ci,bashtestmd:compare-output +$ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"bank_supplyOf","params":["sov1zdwj8thgev2u3yyrrlekmvtsz4av4tp3m7dm5mx5peejnesga27svq9m72"],"id":1}' http://127.0.0.1:12345 +{"jsonrpc":"2.0","result":{"amount":1000},"id":1} +``` + +### Makefile + +`demo-rollup/Makefile` automates a number of things for convenience: + +- Starts docker compose with a Celestia network for a local setup +- `make start`: + - Performs a number of checks to ensure services are not already running + - Starts the docker compose setup + - Exposes the RPC port `26658` + - Waits until the container is started + - Sets up the config + - `examples/demo-rollup/rollup_config.toml` is modified - + - `start_height` is set to `3`, which is the block in which sequencers are funded with credits + - `celestia_rpc_auth_token` is set to the auth token exposed by sequencer (in /docker/credentials directory) + - `celestia_rpc_address` is set to point to `127.0.0.1` and the `RPC_PORT` +- `make stop`: + - Shuts down the Celestia docker compose setup, if running. + - Deletes all contents of the demo-rollup database. +- `make clean`: + - Stops any running containers with the name `sov-celestia-local` and also removes them + - Removes `demo-data` (or the configured path of the rollup database from rollup_config.toml) + +### Remote setup + +> 🚧 This feature is under development! 🚧 + +The above setup runs Celestia node locally to avoid any external network dependencies and to speed up development. Soon, the Sovereign SDK will also support connecting to the Celestia testnet using a Celestia light node running on your machine. + +## How to Customize This Example + +Any time you change out the state transition function, zkVM, or DA layer of your rollup, you'll +need to tweak this full-node code. At the very least, you'll need to modify the dependencies. In most cases, +your full node will also need to be aware of the STF's initialization logic, and how it exposes RPC. + +Given that constraint, we won't try to give you specific instructions for supporting every imaginable +combination of DA layers and State Transition Functions. Instead, we'll explain at a high level what +tasks a full-node needs to accomplish. + +### 1. Initialize the DA Service + +The first _mandatory_ step is to initialize a DA service, which allows the full node implementation to +communicate with the DA layer's RPC endpoints. + +If you're using Celestia as your DA layer, you can follow the instructions at the end +of this document to set up a local full node, or connect to +a remote node. Whichever option you pick, simply place the URL and authentication token +in the `celestia_rollup_config.toml` file and it will be +automatically picked up by the node implementation. For this tutorial, the Makefile below (which also helps start a local Celestia instance) handles this step for you. + +### 2. Run the Main Loop + +The full node implements a simple loop for processing blocks. The workflow is: + +1. Fetch slot data from the DA service +2. Run `stf.begin_slot()` +3. Iterate over the blobs, running `apply_batch` +4. Run `stf.end_slot()` + +In this demo, we also keep a `ledger_db`, which stores information +related to the chain's history - batches, transactions, receipts, etc. + diff --git a/examples/demo-rollup/rollup_config.toml b/examples/demo-rollup/celestia_rollup_config.toml similarity index 100% rename from examples/demo-rollup/rollup_config.toml rename to examples/demo-rollup/celestia_rollup_config.toml diff --git a/examples/demo-rollup/mock_rollup_config.toml b/examples/demo-rollup/mock_rollup_config.toml new file mode 100644 index 000000000..2f25d2f48 --- /dev/null +++ b/examples/demo-rollup/mock_rollup_config.toml @@ -0,0 +1,16 @@ +[da] +sender_address = "0000000000000000000000000000000000000000000000000000000000000000" + +[storage] +# The path to the rollup's data directory. Paths that do not begin with `/` are interpreted as relative paths. +path = "demo_data" + +# We define the rollup's genesis to occur at block number `start_height`. The rollup will ignore +# any blocks before this height +[runner] +start_height = 0 + +[runner.rpc_config] +# the host and port to bind the rpc server for +bind_host = "127.0.0.1" +bind_port = 12345 \ No newline at end of file diff --git a/examples/demo-rollup/src/main.rs b/examples/demo-rollup/src/main.rs index 48df36878..99f58fd48 100644 --- a/examples/demo-rollup/src/main.rs +++ b/examples/demo-rollup/src/main.rs @@ -23,11 +23,11 @@ mod test_rpc; #[command(author, version, about, long_about = None)] struct Args { /// The data layer type. - #[arg(long, default_value = "celestia")] + #[arg(long, default_value = "mock")] da_layer: SupportedDaLayer, /// The path to the rollup config. - #[arg(long, default_value = "rollup_config.toml")] + #[arg(long, default_value = "mock_rollup_config.toml")] rollup_config_path: String, } @@ -57,7 +57,7 @@ async fn main() -> Result<(), anyhow::Error> { match args.da_layer { SupportedDaLayer::Mock => { let rollup = new_rollup_with_mock_da( - &GenesisPaths::from_dir("../test-data/genesis/integration-tests"), + &GenesisPaths::from_dir("../test-data/genesis/demo-tests/mock"), rollup_config_path, RollupProverConfig::Execute, ) @@ -66,7 +66,7 @@ async fn main() -> Result<(), anyhow::Error> { } SupportedDaLayer::Celestia => { let rollup = new_rollup_with_celestia_da( - &GenesisPaths::from_dir("../test-data/genesis/demo-tests"), + &GenesisPaths::from_dir("../test-data/genesis/demo-tests/celestia"), rollup_config_path, RollupProverConfig::Execute, ) diff --git a/examples/test-data/genesis/demo-tests/accounts.json b/examples/test-data/genesis/demo-tests/celestia/accounts.json similarity index 100% rename from examples/test-data/genesis/demo-tests/accounts.json rename to examples/test-data/genesis/demo-tests/celestia/accounts.json diff --git a/examples/test-data/genesis/demo-tests/bank.json b/examples/test-data/genesis/demo-tests/celestia/bank.json similarity index 100% rename from examples/test-data/genesis/demo-tests/bank.json rename to examples/test-data/genesis/demo-tests/celestia/bank.json diff --git a/examples/test-data/genesis/demo-tests/chain_state.json b/examples/test-data/genesis/demo-tests/celestia/chain_state.json similarity index 100% rename from examples/test-data/genesis/demo-tests/chain_state.json rename to examples/test-data/genesis/demo-tests/celestia/chain_state.json diff --git a/examples/test-data/genesis/demo-tests/evm.json b/examples/test-data/genesis/demo-tests/celestia/evm.json similarity index 100% rename from examples/test-data/genesis/demo-tests/evm.json rename to examples/test-data/genesis/demo-tests/celestia/evm.json diff --git a/examples/test-data/genesis/demo-tests/nft.json b/examples/test-data/genesis/demo-tests/celestia/nft.json similarity index 100% rename from examples/test-data/genesis/demo-tests/nft.json rename to examples/test-data/genesis/demo-tests/celestia/nft.json diff --git a/examples/test-data/genesis/demo-tests/sequencer_registry.json b/examples/test-data/genesis/demo-tests/celestia/sequencer_registry.json similarity index 100% rename from examples/test-data/genesis/demo-tests/sequencer_registry.json rename to examples/test-data/genesis/demo-tests/celestia/sequencer_registry.json diff --git a/examples/test-data/genesis/demo-tests/value_setter.json b/examples/test-data/genesis/demo-tests/celestia/value_setter.json similarity index 100% rename from examples/test-data/genesis/demo-tests/value_setter.json rename to examples/test-data/genesis/demo-tests/celestia/value_setter.json diff --git a/examples/test-data/genesis/demo-tests/mock/accounts.json b/examples/test-data/genesis/demo-tests/mock/accounts.json new file mode 100644 index 000000000..f65b078f6 --- /dev/null +++ b/examples/test-data/genesis/demo-tests/mock/accounts.json @@ -0,0 +1,3 @@ +{ + "pub_keys": [] +} diff --git a/examples/test-data/genesis/demo-tests/mock/bank.json b/examples/test-data/genesis/demo-tests/mock/bank.json new file mode 100644 index 000000000..d03fcc10f --- /dev/null +++ b/examples/test-data/genesis/demo-tests/mock/bank.json @@ -0,0 +1,17 @@ +{ + "tokens": [ + { + "token_name": "sov-demo-token", + "address_and_balances": [ + [ + "sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94", + 100000000 + ] + ], + "authorized_minters": [ + "sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94" + ], + "salt": 0 + } + ] +} diff --git a/examples/test-data/genesis/demo-tests/mock/chain_state.json b/examples/test-data/genesis/demo-tests/mock/chain_state.json new file mode 100644 index 000000000..d439a6854 --- /dev/null +++ b/examples/test-data/genesis/demo-tests/mock/chain_state.json @@ -0,0 +1,7 @@ +{ + "initial_slot_height": 0, + "current_time": { + "secs": 0, + "nanos": 0 + } +} diff --git a/examples/test-data/genesis/demo-tests/mock/evm.json b/examples/test-data/genesis/demo-tests/mock/evm.json new file mode 100644 index 000000000..7f5b2b108 --- /dev/null +++ b/examples/test-data/genesis/demo-tests/mock/evm.json @@ -0,0 +1,25 @@ +{ + "data": [ + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "balance": "0xffffffffffffffff", + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "code": "0x", + "nonce": 0 + } + ], + "chain_id": 1, + "limit_contract_code_size": null, + "spec": { + "0": "SHANGHAI" + }, + "coinbase": "0x0000000000000000000000000000000000000000", + "starting_base_fee": 7, + "block_gas_limit": 30000000, + "genesis_timestamp": 0, + "block_timestamp_delta": 1, + "base_fee_params": { + "max_change_denominator": 8, + "elasticity_multiplier": 2 + } +} diff --git a/examples/test-data/genesis/demo-tests/mock/nft.json b/examples/test-data/genesis/demo-tests/mock/nft.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/examples/test-data/genesis/demo-tests/mock/nft.json @@ -0,0 +1 @@ +{} diff --git a/examples/test-data/genesis/demo-tests/mock/sequencer_registry.json b/examples/test-data/genesis/demo-tests/mock/sequencer_registry.json new file mode 100644 index 000000000..fe2696ae5 --- /dev/null +++ b/examples/test-data/genesis/demo-tests/mock/sequencer_registry.json @@ -0,0 +1,9 @@ +{ + "seq_rollup_address": "sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94", + "seq_da_address": "0000000000000000000000000000000000000000000000000000000000000000", + "coins_to_lock": { + "amount": 50, + "token_address": "sov1zsnx7n2wjvtkr0ttscfgt06pjca3v2e6stxeu49qwynavmk7a8xqlxkkjp" + }, + "is_preferred_sequencer": true +} diff --git a/examples/test-data/genesis/demo-tests/mock/value_setter.json b/examples/test-data/genesis/demo-tests/mock/value_setter.json new file mode 100644 index 000000000..4e209004a --- /dev/null +++ b/examples/test-data/genesis/demo-tests/mock/value_setter.json @@ -0,0 +1,3 @@ +{ + "admin": "sov1l6n2cku82yfqld30lanm2nfw43n2auc8clw7r5u5m6s7p8jrm4zqrr8r94" +}