GM world rollup β
π Introduction β
This tutorial will guide you through building a sovereign gm-world
rollup (gm
stands for "good morning") using Rollkit. Unlike the quick start guide, this tutorial provides a more practical approach to understanding sovereign rollup development.
We will cover:
- Building and configuring a Cosmos-SDK application-specific rollup blockchain.
- Posting rollup data to a Data Availability (DA) network.
- Executing transactions (the end goal).
No prior understanding of the build process is required, just that it utilizes the Cosmos SDK for blockchain applications.
TIP
This tutorial explores Rollkit, currently in Alpha. If you encounter bugs, please report them via a GitHub issue ticket or reach out in our Telegram group.
π οΈ Dependencies β
As we move into more advanced use cases, we use ignite to help with managing all the services we need to run. You can install ignite here.
Once installed, you can verify the installation by running:
ignite version
Ignite CLI version: v28.7.0
Ignite CLI build date: 2025-01-15T08:23:41Z
Ignite CLI source hash: 2f83cfe6114cfc58bd6add791143fe43963c1b5c
Ignite CLI config version: v1
Cosmos SDK version: v0.50.11
Your OS: darwin
Your arch: arm64
Your go version: go version go1.24.2 darwin/arm64
Your uname -a: Darwin Markos-MacBook-Pro.local 24.3.0 Darwin Kernel Version 24.3.0: Thu Jan 2 20:24:16 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T6000 arm64
Your cwd: /Users/markobaricevic/code/CoTend/rollkit1/docs
Is on Gitpod: false
Generate your App β
ignite s chain gm --address-prefix gm
cd gm
Install a specific version of ignire to use rollkit
ignite app install -g github.com/ignite/apps/rollkit@9d51c52305be37356a1ecadab8733b77842e1c37
Install your app locally:
make install
π Starting your rollup β
Now that we have our gm app generated and installed, we can launch our GM rollup along with the local DA by running the following command:
First lets start the local DA network:
curl -sSL https://rollkit.dev/install-local-da.sh | bash -s {{constants.localDALatestTag}}
you should see logs like:
4:58PM INF NewLocalDA: initialized LocalDA module=local-da
4:58PM INF Listening on host=localhost maxBlobSize=1974272 module=da port=7980
4:58PM INF server started listening on=localhost:7980 module=da
After which we can start the app:
gmd start --rollkit.node.aggregator
You should see an output like this:
5:02PM INF Rollkit node run loop launched in background goroutine module=server
5:02PM INF Attempting to start Rollkit node run loop module=server
5:02PM INF serving HTTP listen address=[::]:26657 module=rollkit
5:02PM INF Started RPC server addr=127.0.0.1:7331 module=rollkit
5:02PM INF starting P2P client module=rollkit
5:02PM INF listening on address=/ip4/10.36.65.125/tcp/7676/p2p/12D3KooWCZ4oCNDkxisUWD9CbB5yEmSmjaTEtLLySk3Sccy4Vb8m module=p2p
5:02PM INF listening on address=/ip4/127.0.0.1/tcp/7676/p2p/12D3KooWCZ4oCNDkxisUWD9CbB5yEmSmjaTEtLLySk3Sccy4Vb8m module=p2p
5:02PM INF no peers - only listening for connections module=p2p
5:02PM INF working in aggregator mode block time=1s module=rollkit
5:02PM INF Reaper started interval=1000 module=Reaper
5:02PM INF Using pending block height=1 module=BlockManager
5:02PM INF Executing block height=1 module=rollkit num_txs=0 timestamp=2025-04-28T11:21:24-04:00
5:02PM INF Block executed successfully appHash=6AE75B65CDFE504876AC392554E16065C7C3699FFC99E6C4AA5FEB13B49CFB2D height=1 module=rollkit
5:02PM ERR failed to start syncer after initializing the store: error getting latest head during Start: header: not found module=rollkit
5:02PM ERR failed to start syncer after initializing the store: error getting latest head during Start: header: not found module=rollkit
5:02PM INF Attempting to start executor (Adapter.Start) module=server
5:02PM INF Executor started successfully module=server
5:02PM INF Waiting for services to complete... module=server
5:02PM INF starting API server... address=tcp://0.0.0.0:1317 module=api-server
5:02PM INF serve module=api-server msg="Starting RPC HTTP server on [::]:1317"
5:02PM INF starting gRPC server... address=localhost:9090 module=grpc-server
5:02PM INF Creating empty block height=2 module=BlockManager
5:02PM INF Executing block height=2 module=rollkit num_txs=0 timestamp=2025-05-13T17:02:14-04:00
5:02PM INF Block executed successfully appHash=CACB5B55477E8813D93A29CF25BA5DB8AD4A51992D96A72CF9A4E83D47F4FAAA height=2 module=rollkit
Ignite has successfully launched the GM rollup and the local DA network. The GM rollup is running on port 7331
and the local DA network is running on port 7980
.
Good work so far, we have a Rollup node, DA network node, now we can start submitting transactions.
πΈ Transactions β
First, list your keys:
gmd keys list --keyring-backend test
You should see an output like the following
- address: gm17rpwv7lnk96ka00v93rphhvcqqztpn896q0dxx
name: alice
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A5WPM5WzfNIPrGyha/TlHt0okdlzS1O4Gb1d1kU+xuG+"}'
type: local
- address: gm1r2udsh4za7r7sxvzy496qfazvjp04j4zgytve3
name: bob
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A+jOX/CWInFer2IkqgXGo0da9j7Ubq+e1LJWzTMDjwdt"}'
type: local
For convenience we export two of our keys like this:
export KEY1=gm17rpwv7lnk96ka00v93rphhvcqqztpn896q0dxx
export KEY2=gm1r2udsh4za7r7sxvzy496qfazvjp04j4zgytve3
Now let's submit a transaction that sends coins from one account to another (don't worry about all the flags, for now, we just want to submit transaction from a high-level perspective):
gmd tx bank send $KEY2 $KEY1 42069stake --keyring-backend test --chain-id gm --fees 5000stake
You'll be prompted to accept the transaction:
auth_info:
fee:
amount: []
gas_limit: "200000"
granter: ""
payer: ""
signer_infos: []
tip: null
body:
extension_options: []
memo: ""
messages:
- '@type': /cosmos.bank.v1beta1.MsgSend
amount:
- amount: "42069"
denom: stake
from_address: gm1r2udsh4za7r7sxvzy496qfazvjp04j4zgytve3
to_address: gm17rpwv7lnk96ka00v93rphhvcqqztpn896q0dxx
non_critical_extension_options: []
timeout_height: "0"
signatures: []
confirm transaction before signing and broadcasting [y/N]: // [!code focus]
Confirm and sign the transaction as prompted. now you see the transaction hash at the output:
//...
txhash: 677CAF6C80B85ACEF6F9EC7906FB3CB021322AAC78B015FA07D5112F2F824BFF
βοΈ Checking Balances β
Query balances after the transaction:
gmd query bank balances $KEY1
The receiverβs balance should show an increase.
balances: // [!code focus]
- amount: "42069" // [!code focus]
denom: stake
pagination:
next_key: null
total: "0"
For the senderβs balance:
gmd query bank balances $KEY2
Output:
balances: // [!code focus]
- amount: "99957931" // [!code focus]
denom: stake
pagination:
next_key: null
total: "0"
π Next steps β
Congratulations! You've experienced connecting to a rollup from the user side β simple and straightforward. Now, you might consider exploring how to add more application logic to your rollup using the Cosmos SDK, as demonstrated in our Wordle App tutorial.