https://github.com/datopia/abci-host
Clojure host/server for Tendermint's ABCI protocol.
https://github.com/datopia/abci-host
abci blockchain clojure consensus distributed-systems tendermint
Last synced: 2 months ago
JSON representation
Clojure host/server for Tendermint's ABCI protocol.
- Host: GitHub
- URL: https://github.com/datopia/abci-host
- Owner: datopia
- License: mit
- Created: 2018-12-07T14:03:43.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2025-05-31T06:58:43.000Z (4 months ago)
- Last Synced: 2025-07-03T06:42:27.850Z (3 months ago)
- Topics: abci, blockchain, clojure, consensus, distributed-systems, tendermint
- Language: Clojure
- Size: 114 KB
- Stars: 25
- Watchers: 5
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# org.datopia/abci
[](http://clojars.org/org.datopia/abci)A Clojure library which acts as an application host
for
[Tendermint](https://tendermint.com)'s
[ABCI](https://tendermint.com/docs/introduction/what-is-tendermint.html#abci-overview) ---
allowing the exposure of plain functions as replicable state machines.`org.datopia/abci`
uses [org.datopia/stickler](https://github.com/datopia/stickler) to provide
pure-data representations of
the [protobuf](https://developers.google.com/protocol-buffers/)-encoded messages
received from the Tendermint node process --- maps in, maps out.## Documentation
- [API docs](https://datopia.github.io/abci-host/).
- [K/V store example project](example).### [Change Log](CHANGELOG.md).
## Project -> Tendermint Version Mapping
| org.datopia/abci | Tendermint |
| ----------------- | ----------------- |
| 0.2.0 | 0.38.5 (CometBFT) |
| 0.1.0 | 0.34.12 |There's a previous, deprecated artifact:
| io.datopia/abci | |
| ----------------- | ------------- |
| 0.1.* | 0.26.0 |## Toy Example / Walkthrough
The simplest possible service looks something like:
```clojure
(ns my.abci
(:require [abci.host :as host]
[abci.host.middleware :as mw]))(def service
(-> (constantly ::mw/default)
;; Wrap handler invocations w/ (manifold.deferred/future).
mw/wrap-synchronous
;; Substitute ::mw/default for a default success response,
;; appropriate to the incoming request.
mw/wrap-default
;; Return a Closeable, per aleph.tcp/start-server.
host/start))
```While this isn't a particularly dynamic application, we can successfully point a
Tendermint node process at it and indefinitely operate a no-op blockchain.## Requests & Responses
Let's transform our handler from `(constantly ::mw/default)` to something
slightly different:```clojure
(fn [req]
(pprint req)
::mw/default)
```Once the Tendermint node connects, our first message:
```clojure
{:stickler/msg :abci/Request
:info {:stickler/msg :abci/RequestInfo
:version "0.26.0-c086d0a3"
:block-version 7
:p2p-version 4}
:stickler.one-of/value :info
;; The node initiates 3 distinct connections: :info, :query, :consensus
:abci.host/conn :info}
```The minimal success response to the above:
```clojure
{:stickler/msg :abci/Response
:info {:stickler/msg :abci/ResponseInfo
:data "NO_INFO"}}
```Let's update our service to construct this response explictly, while
using middleware to strip incoming `:abci/Request` envelopes - and
wrap responses in `:abci/Response` envelopes. While this won't alter
how our service functions, it may make it a little clearer.```clojure
(defn handler [{msg-type :stickler/msg :as req}]
(pprint req)
(case msg-type
:abci/RequestInfo {:stickler/msg :abci/ResponseInfo
:data "NO_INFO"}
::mw/default))(def service
(-> handler
mw/wrap-synchronous
mw/wrap-default
;; Combines mw/wrap-request-envelope and mw/wrap-response-envelope
mw/wrap-envelope
host/start))
```Without the envelopes, our incoming request sequence:
```clojure
{:stickler/msg :abci/RequestInfo
:version "0.26.0-c086d0a3"
:block-version 7
:p2p-version 4
:abci.host/conn :info}{:stickler/msg :abci/RequestFlush
:abci.host/conn :info}{:stickler/msg :abci/RequestInitChain
:time {:stickler/msg :google.protobuf/Timestamp
:seconds 1544530118
:nanos 776243100}
:chain-id "test-chain-anZqUW"
:validators
[{:stickler/msg :abci/ValidatorUpdate
:pub-key {:stickler/msg :abci/PubKey
:type "ed25519"
:data }
:power 10}]
...
:abci.host/conn :consensus}...
```The
project's
[abci.edn resource](https://github.com/datopia/abci-host/blob/master/resources/org.datopia.abci/abci.edn)
describes the full complement of messages. As Tendermint uses Go-specific
extensions in its protobuf files, `abci.edn` is generated by
[org.datopia/stickler](https://github.com/datopia/stickler) from
the [types.proto](https://github.com/jTendermint/jabci/blob/develop/src/main/proto/types.proto) maintained
by [jabci](https://github.com/jTendermint/jabci).## Contributors
- Moe Aboulkheir
## License
[MIT](https://github.com/datopia/abci-host/blob/master/LICENSE)