To implement the architecture we intend to make use of the following open source components to integrate with Tendermint:
- CometBFT: One of the successors of the generic blockchain SMR system Tendermint Core (others might be listed here). Originally we used the upcoming v0.37, but it was eventually released as part of CometBFT. This version has the required extensions to ABCI++.
- tendermint-rs is a Rust library that contains Tendermint datatypes; the proto code generated from the Tendermint protobuf definitions; a synchronous ABCI server with a trait the application can implement, with a KV-store example familiar from the tutorial; and various other goodies for building docker images, integration testing the application with Tendermint, and so on. Since this PR the library supports both
v0.34
(the last stable release of Tendermint Core) and the newerv0.37
version (the two are not wire compatible). - tower-abci from Penumbra adapts the ABCI interfaces from
tendermint-rs
to be used with tower and has a server implementation that works with the thev0.37
wire format and uses tokio. So, unlike the ABCI server intendermint-rs
, this is asynchronous, which we can make use of if we want to inject our own networking.
That should be enough to get us started with Tendermint.
We will need Tendermint Core CometBFT running and building the blockchain, and since we don't want to fork it, we can install the pre-packaged cometbft
binary from the releases. At the time of this writing, our target is the v0.37.1 release, and things should work with the v0.37.0-rc2
version of Tendermint Core as well.
Alternatively, we can install the project from source. I expect to have to dig around in the source code to understand the finer nuances, so this is what I'll do. It needs go
1.18 or higher installed (check with go version
).
The following code downloads the source, checks out the branch with the necessary ABCI++ features, and installs it.
git clone https://github.com/cometbft/cometbft.git
cd cometbft
git checkout v0.37.1
make install
Check that the installation worked:
$ cometbft version
0.37.1+2af25aea6
After this we can follow the quick start guide to initialize a local node and try out the venerable kvstore
application.
Create the genesis files under $HOME/.cometbft
:
cometbft init
Start a node; we'll see blocks being created every second:
cometbft node --proxy_app=kvstore
Then, from another terminal, send a transaction:
curl -s 'localhost:26657/broadcast_tx_commit?tx="foo=bar"'
Finally, query the value of the key we just added:
curl -s 'localhost:26657/abci_query?data="foo"' | jq -r ".result.response.value | @base64d"
We should see bar
printed on the console.
Nice! The status of the node can be checked like so:
curl -s localhost:26657/status
To start from a clean slate, we can just clear out the data directory and run tendermint init
again:
rm -rf ~/.cometbft
Alternatively, once we have our own genesis set up, we can discard just the blockchain data with the following command:
cometbft unsafe-reset-all
This is an optional step to check that the branch that we'll need to be using from tendermint-rs
works with our chosen version of cometbft
. In practice we'll just add a library reference to the github project until it's released, we don't have to clone the project. But it's useful to do so, to get familiar with the code.
git clone [email protected]:informalsystems/tendermint-rs.git
cd tendermint-rs
git checkout v0.31.0
Then, go into the abci
crate to try the example with the kvstore
that, unlike previously, will run external to tendermint
:
cd abci
Build and run the store:
cargo run --bin kvstore-rs --features binary,kvstore-app
Go back to the terminal we used to run cometbft
and do what they suggest.
First ensure we have the genesis files:
cometbft init
Then try to run Tendermint; it's supposed to connect to 127.0.0.1:26658
where the store is running, and bind itself to 127.0.0.1:26657
:
cometbft unsafe-reset-all && cometbft start
This seems to work; in the CometBFT logs we see the process producing blocks:
❯ cometbft unsafe-reset-all && cometbft start
...
I[2023-05-19|09:22:50.094] ABCI Handshake App Info module=consensus height=0 hash=00000000000000000000000000000000 software-version=0.1.0 protocol-version=1
I[2023-05-19|09:22:50.094] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0
I[2023-05-19|09:22:50.097] Completed ABCI Handshake - CometBFT and App are synced module=consensus appHeight=0 appHash=00000000000000000000000000000000
...
I[2023-05-19|09:22:53.193] received complete proposal block module=consensus height=3 hash=CBAEA6A06C09F6E5D5D4C09315EBFA770FE75E165CDABABD95F91DBFF6E6AFF2
I[2023-05-19|09:22:53.208] finalizing commit of block module=consensus height=3 hash=CBAEA6A06C09F6E5D5D4C09315EBFA770FE75E165CDABABD95F91DBFF6E6AFF2 root=00 num_txs=0
I[2023-05-19|09:22:53.215] executed block module=state height=3 num_valid_txs=0 num_invalid_txs=0
I[2023-05-19|09:22:53.222] committed state module=state height=3 num_txs=0 app_hash=00
I[2023-05-19|09:22:53.229] indexed block exents module=txindex height=3
...
We can see the opposite side of the error in the console of the store:
❯ cargo run --bin kvstore-rs --features binary,kvstore-app
...
2023-05-19T08:22:14.247867Z INFO tendermint_abci::server: ABCI server running at 127.0.0.1:26658
2023-05-19T08:22:50.079635Z INFO tendermint_abci::server: Incoming connection from: 127.0.0.1:44564
2023-05-19T08:22:50.079749Z INFO tendermint_abci::server: Incoming connection from: 127.0.0.1:44572
2023-05-19T08:22:50.079843Z INFO tendermint_abci::server: Listening for incoming requests from 127.0.0.1:44564
2023-05-19T08:22:50.079879Z INFO tendermint_abci::server: Incoming connection from: 127.0.0.1:44576
2023-05-19T08:22:50.079887Z INFO tendermint_abci::server: Listening for incoming requests from 127.0.0.1:44572
2023-05-19T08:22:50.079996Z INFO tendermint_abci::server: Incoming connection from: 127.0.0.1:44590
2023-05-19T08:22:50.080002Z INFO tendermint_abci::server: Listening for incoming requests from 127.0.0.1:44576
2023-05-19T08:22:50.080110Z INFO tendermint_abci::server: Listening for incoming requests from 127.0.0.1:44590
2023-05-19T08:22:51.154772Z INFO tendermint_abci::application::kvstore: Committed height 1
2023-05-19T08:22:52.183919Z INFO tendermint_abci::application::kvstore: Committed height 2
2023-05-19T08:22:53.222453Z INFO tendermint_abci::application::kvstore: Committed height 3
...
Try to send a transaction:
❯ curl 'http://127.0.0.1:26657/broadcast_tx_async?tx="somekey=somevalue"'
{"jsonrpc":"2.0","id":-1,"result":{"code":0,"data":"","log":"","codespace":"","hash":"17ED61261A5357FEE7ACDE4FAB154882A346E479AC236CFB2F22A2E8870A9C3D"}}
and a query:
❯ curl 'http://127.0.0.1:26657/abci_query?data=0x736f6d656b6579'
{"jsonrpc":"2.0","id":-1,"result":{"response":{"code":0,"log":"exists","info":"","index":"0","key":"c29tZWtleQ==","value":"c29tZXZhbHVl","proofOps":null,"height":"300","codespace":""}}}
All balls!
Now just make sure we clean up the compilation artifacts:
cargo clean