Running the Application

In previous sections you learned about different ABCI 2.0 methods and how they are used.

In this section you will learn how to run the Forum Application.

Initializing and Running

The application is almost ready to run, but first we’ll need to populate the CometBFT configuration file.

The following command will create a cometbft home directory in your project and add a basic set of configuration files in ~/config/.

For more information on what these files contain see the configuration documentation.

Install comebft

Clone the cometbft repository:

git clone https://github.com/cometbft/cometbft

checkout the latest v1 release and install it

cd cometbft
git checkout v1.0.0-rc2
make install

initialize cometbft:

cometbft init --home /tmp/forum-app

You should see an output similar to the following:

I[2024-04-23|20:16:43.493] Found private validator                      module=main keyFile=/tmp/forum-app/config/priv_validator_key.json stateFile=/tmp/forum-app/data/priv_validator_state.json
I[2024-04-23|20:16:43.493] Found node key                               module=main path=/tmp/forum-app/config/node_key.json
I[2024-04-23|20:16:43.493] Found genesis file                           module=main path=/tmp/forum-app/config/genesis.json

Now build the app:

cd abci/tutorials/abci-v2-forum-app
go build

If there are no errors when running the build command above, then everything is now in place to run your application.

Note: If this is not the first time you’re running this application, you need to remove the previously created database, please run the command rm -Rf forum-db to remove the previous database folder and run from a fresh start

Lets run our Forum Application specifying a home directory (using --home) hosted in the tmp/forum-app folder (if you don’t specify the home folder, it is created under $HOME/.cometbft by default)

./abci-v2-forum-app --home /tmp/forum-app

This should start the full node and connect to our ABCI application, which will be reflected in the application output.

(abci-v2-forum-app) > ./abci-v2-forum-app --home /tmp/forum-app
badger 2024/07/11 11:00:19 INFO: All 0 tables opened in 0s
badger 2024/07/11 11:00:19 INFO: Discard stats nextEmptySlot: 0
badger 2024/07/11 11:00:19 INFO: Set nextTxnTs to 0
I[2024-07-11|15:00:19.091] State store key layout version               version=vv1
I[2024-07-11|15:00:19.100] Blockstore version                           version=v1
I[2024-07-11|15:00:19.100] WARNING: deleting genesis file from database if present, the database stores a hash of the original genesis file now
I[2024-07-11|15:00:19.100] service start                                module=proxy msg="Starting multiAppConn service" impl=multiAppConn
I[2024-07-11|15:00:19.100] service start                                module=abci-client connection=query msg="Starting localClient service" impl=localClient
I[2024-07-11|15:00:19.100] service start                                module=abci-client connection=snapshot msg="Starting localClient service" impl=localClient
I[2024-07-11|15:00:19.100] service start                                module=abci-client connection=mempool msg="Starting localClient service" impl=localClient
I[2024-07-11|15:00:19.100] service start                                module=abci-client connection=consensus msg="Starting localClient service" impl=localClient
I[2024-07-11|15:00:19.100] service start                                module=events msg="Starting EventBus service" impl=EventBus
I[2024-07-11|15:00:19.100] service start                                module=pubsub msg="Starting PubSub service" impl=PubSub
I[2024-07-11|15:00:19.120] service start                                module=txindex msg="Starting IndexerService service" impl=IndexerService
I[2024-07-11|15:00:19.120] ABCI Handshake App Info                      module=consensus height=0 hash=0000000000000000 software-version=2.1.0 protocol-version=1
I[2024-07-11|15:00:19.120] ABCI Replay Blocks                           module=consensus appHeight=0 storeHeight=0 stateHeight=0
I[2024-07-11|15:00:19.120] Executing Application InitChain
I[2024-07-11|15:00:19.124] Completed ABCI Handshake - CometBFT and App are synced module=consensus appHeight=0 appHash=0000000000000000
I[2024-07-11|15:00:19.124] Version info                                 tendermint_version=1.0.0-dev abci=2.1.0 block=11 p2p=9 commit_hash=
I[2024-07-11|15:00:19.124] This node is a validator                     module=consensus addr=488A741EC0B687FE06C045EFAB12DDBFF82A5993 pubKey=PubKeyEd25519{41AA07512ED9B4607C17AF49B7D30737FC19D77EAA2FE69F66F5F46AB619D221}
I[2024-07-11|15:00:19.157] P2P Node ID                                  module=p2p ID=f32302c56b40b7bc249613185913b422be494ee0 file=/tmp/forum-app/config/node_key.json
I[2024-07-11|15:00:19.157] Adding persistent peers                      module=p2p addrs=[]
I[2024-07-11|15:00:19.157] Adding unconditional peer ids                module=p2p ids=[]
I[2024-07-11|15:00:19.157] Add our address to book                      module=p2p book=/tmp/forum-app/config/addrbook.json addr=f32302c56b40b7bc249613185913b422be494ee0@0.0.0.0:26656
I[2024-07-11|15:00:19.157] service start                                msg="Starting Node service" impl=Node
I[2024-07-11|15:00:19.158] service start                                module=p2p msg="Starting P2P Switch service" impl="P2P Switch"
I[2024-07-11|15:00:19.158] service start                                module=mempool msg="Starting Mempool service" impl=Mempool
I[2024-07-11|15:00:19.158] service start                                module=blocksync msg="Starting Reactor service" impl=Reactor
I[2024-07-11|15:00:19.158] serve                                        module=rpc-server msg="Starting RPC HTTP server on 127.0.0.1:26657"
I[2024-07-11|15:00:19.158] service start                                module=consensus msg="Starting Consensus service" impl=ConsensusReactor
I[2024-07-11|15:00:19.158] service start                                module=consensus msg="Starting State service" impl=ConsensusState
I[2024-07-11|15:00:19.158] service start                                module=consensus wal=/tmp/forum-app/data/cs.wal/wal msg="Starting baseWAL service" impl=baseWAL
I[2024-07-11|15:00:19.162] service start                                module=consensus wal=/tmp/forum-app/data/cs.wal/wal msg="Starting Group service" impl=Group
I[2024-07-11|15:00:19.162] service start                                module=consensus msg="Starting TimeoutTicker service" impl=TimeoutTicker
I[2024-07-11|15:00:19.162] Searching for height                         module=consensus wal=/tmp/forum-app/data/cs.wal/wal height=1 min=0 max=0
I[2024-07-11|15:00:19.162] Searching for height                         module=consensus wal=/tmp/forum-app/data/cs.wal/wal height=0 min=0 max=0
I[2024-07-11|15:00:19.162] Found                                        module=consensus wal=/tmp/forum-app/data/cs.wal/wal height=0 index=0
I[2024-07-11|15:00:19.162] Catchup by replaying consensus messages      module=consensus height=1
I[2024-07-11|15:00:19.162] Replay: Done                                 module=consensus
I[2024-07-11|15:00:19.162] service start                                module=evidence msg="Starting Evidence service" impl=Evidence
I[2024-07-11|15:00:19.162] service start                                module=statesync msg="Starting StateSync service" impl=StateSync
I[2024-07-11|15:00:19.162] service start                                module=pex msg="Starting PEX service" impl=PEX
I[2024-07-11|15:00:19.162] service start                                module=p2p book=/tmp/forum-app/config/addrbook.json msg="Starting AddrBook service" impl=AddrBook
I[2024-07-11|15:00:19.163] Saving AddrBook to file                      module=p2p book=/tmp/forum-app/config/addrbook.json size=0
I[2024-07-11|15:00:19.163] Ensure peers                                 module=pex numOutPeers=0 numInPeers=0 numDialing=0 numToDial=10
I[2024-07-11|15:00:19.163] service start                                module=state msg="Starting Pruner service" impl=Pruner
I[2024-07-11|15:00:19.163] No addresses to dial. Falling back to seeds  module=pex
I[2024-07-11|15:00:19.163] Started pruning blocks                       module=state interval=10s
I[2024-07-11|15:00:20.154] Timed out                                    module=consensus dur=991.108ms height=1 round=0 step=RoundStepNewHeight
I[2024-07-11|15:00:20.154] Executing Application PrepareProposal
I[2024-07-11|15:00:20.154] Processed vote extensions                    curse_words=map[]
I[2024-07-11|15:00:20.166] Received proposal                            module=consensus proposal="Proposal{1/0 (3F859221DD1F92490BCB4D93E27BCF61716285DB1412091EDAEC41E31752A161:1:3E782D5C89A4, -1) C9C6EEDA8B33 @ 2024-07-11T15:00:11.194908Z}" proposer=488A741EC0B687FE06C045EFAB12DDBFF82A5993
I[2024-07-11|15:00:20.171] Received complete proposal block             module=consensus height=1 hash=3F859221DD1F92490BCB4D93E27BCF61716285DB1412091EDAEC41E31752A161
I[2024-07-11|15:00:20.171] Executing Application ProcessProposal
I[2024-07-11|15:00:20.176] Executing Application ExtendVote
I[2024-07-11|15:00:20.181] Finalizing commit of block                   module=consensus height=1 hash=3F859221DD1F92490BCB4D93E27BCF61716285DB1412091EDAEC41E31752A161 root=0000000000000000 num_txs=0
I[2024-07-11|15:00:20.190] Executing Application FinalizeBlock
I[2024-07-11|15:00:20.190] Finalized block                              module=state height=1 num_txs_res=0 num_val_updates=0 block_app_hash=0000000000000000 syncing_to_height=1
I[2024-07-11|15:00:20.194] Executing Application Commit
I[2024-07-11|15:00:20.194] Committed state                              module=state height=1 block_app_hash=0000000000000000
I[2024-07-11|15:00:20.203] indexed block events                         module=txindex height=1

Also, the application using CometBFT Core is producing blocks 🎉🎉 and you can see this reflected in the log output of the service in lines like this:

I[2024-07-11|15:00:21.181] Executing Application PrepareProposal
I[2024-07-11|15:00:21.181] Processed vote extensions                    curse_words="map[bad:1 bloodmagic:1 cry:1 muggle:1 rain:1]"
I[2024-07-11|15:00:21.193] Received proposal                            module=consensus proposal="Proposal{2/0 (2F2187B9E889B4C9DD33B5D510039F12CE70DC2854D8EDF706B6C46178909BA6:1:F60DF39D940E, -1) 9E244663B13B @ 2024-07-11T15:00:20.176517Z}" proposer=488A741EC0B687FE06C045EFAB12DDBFF82A5993
I[2024-07-11|15:00:21.198] Received complete proposal block             module=consensus height=2 hash=2F2187B9E889B4C9DD33B5D510039F12CE70DC2854D8EDF706B6C46178909BA6
I[2024-07-11|15:00:21.198] Executing Application ProcessProposal
I[2024-07-11|15:00:21.202] Executing Application ExtendVote
I[2024-07-11|15:00:21.207] Finalizing commit of block                   module=consensus height=2 hash=2F2187B9E889B4C9DD33B5D510039F12CE70DC2854D8EDF706B6C46178909BA6 root=0000000000000000 num_txs=0
I[2024-07-11|15:00:21.216] Executing Application FinalizeBlock
I[2024-07-11|15:00:21.216] Finalized block                              module=state height=2 num_txs_res=0 num_val_updates=0 block_app_hash=0000000000000000 syncing_to_height=2
I[2024-07-11|15:00:21.220] Executing Application Commit
I[2024-07-11|15:00:21.220] Committed state                              module=state height=2 block_app_hash=0000000000000000
I[2024-07-11|15:00:21.228] indexed block events                         module=txindex height=2

Using the application

Let’s try submitting a transaction to our new application. Open another terminal window and run the following curl command:

Submit a tx with non curse word

curl -s 'localhost:26657/broadcast_tx_commit?tx="sender:Ron,message:Music"'

If everything went well, you should see a response indicating which height the transaction was included in the blockchain.

{"jsonrpc":"2.0","id":-1,"result":{"check_tx":{"code":0,"data":null,"log":"","info":"","gas_wanted":"0","gas_used":"0","events":[],"codespace":""},"tx_result":{"code":0,"data":null,"log":"","info":"","gas_wanted":"0","gas_used":"0","events":[],"codespace":""},"hash":"DD0DD9613C83E5CCDE31342DC49CEF1DD6423271B090BC6A73E800FD163E7ADD","height":"25"}}%

Let’s make sure that transaction really was persisted by the application. Run the following command:

curl -s 'localhost:26657/abci_query?data="Ron"'

Let’s examine the response object that this request returns. The request returns a json object with a key and value field set.

{
  "jsonrpc": "2.0",
  "id": -1,
  "result": {
    "response": {
      "code": 0,
      "log": "\"Music\"",
      "info": "",
      "index": "0",
      "key": "Um9u",
      "value": "Ik11c2ljIg==",
      "proofOps": null,
      "height": "0",
      "codespace": ""
    }
  }
}

Those values don’t look like the key and value we sent to CometBFT. What’s going on here?

The response contains a base64 encoded representation of the data we submitted. To get the original value out of this data, we can use the base64 command line utility to view the key (sender) and value (message):

To view the value of key (which is the sender) run:

echo Um9u | base64 -d

It will output Ron

Then run the command below to view the value (which is the message):

echo Ik11c2ljIg== | base64 -d

It will output Music

As you can observe, the Music message was added by Ron.

Submit a tx with curse word

curl -s 'localhost:26657/broadcast_tx_commit?tx="sender:Malfoy,message:muggle"'

After a certain amount of time you will see a message that tx could not be included in the block. This happens as tx is being rejected in PrepareProposal

{"jsonrpc":"2.0","id":-1,"error":{"code":-32603,"message":"Internal error","data":"timed out waiting for tx to be included in a block"}}

Let’s make sure that transaction really was not persisted by the application. Run the following command:

curl -s 'localhost:26657/abci_query?data="Malfoy"'

This should return an error with Key not found since the sender and message were not included in the application

{"jsonrpc":"2.0","id":-1,"error":{"code":-32603,"message":"Internal error","data":"Key not found"}}

Submit a tx with non curse word for banned user

curl -s 'localhost:26657/broadcast_tx_commit?tx="sender:Malfoy,message:heroic"'

After a certain amount of time you will observe that tx was rejected in checkTx since the user has been already banned.

{"jsonrpc":"2.0","id":-1,"result":{"check_tx":{"code":3,"data":null,"log":"User is banned","info":"","gas_wanted":"0","gas_used":"0","events":[],"codespace":""},"tx_result":{"code":0,"data":null,"log":"","info":"","gas_wanted":"0","gas_used":"0","events":[],"codespace":""},"hash":"9B110D7648000037B8385562B15810C70E1957AF2F65790B3617CB84C9398536","height":"0"}}%

Checking the chat history

The application can also return the history of messages that were submitted and added to the application. To view the chat history run the following query:

curl -s 'localhost:26657/abci_query?data="history"'

You can see the chat history in the log field of the response:

{"jsonrpc":"2.0","id":-1,"result":{"response":{"code":0,"log":"{sender:Ron,message:Music}","info":"","index":"0","key":"aGlzdG9yeQ==","value":"e3NlbmRlcjpSb24sbWVzc2FnZTpNdXNpY30=","proofOps":null,"height":"0","codespace":""}}}%

Congratulations

Our tutorial on building an ABCI 2 application using CometBFT has come to a close. We hope that the comprehensive tutorial we’ve provided has equipped you with the knowledge and skills necessary to develop your own ABCI 2.0 applications with ease and confidence.

Decorative Orb