-
Notifications
You must be signed in to change notification settings - Fork 231
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add minimal blocking ABCI crate (#794)
* Add minimal blocking ABCI library Signed-off-by: Thane Thomson <[email protected]> * Expand API to implement in-memory key/value store app Signed-off-by: Thane Thomson <[email protected]> * Add kvstore-rs ABCI app Signed-off-by: Thane Thomson <[email protected]> * Add rudimentary README Signed-off-by: Thane Thomson <[email protected]> * Bump proto version dependency to v0.18.0 Signed-off-by: Thane Thomson <[email protected]> * Replace manual default structs with Default::default() Signed-off-by: Thane Thomson <[email protected]> * Enable debug logging for all incoming ABCI requests Signed-off-by: Thane Thomson <[email protected]> * Improve CLI UX Signed-off-by: Thane Thomson <[email protected]> * Allow for read buffer size customization Signed-off-by: Thane Thomson <[email protected]> * Add crate description Signed-off-by: Thane Thomson <[email protected]> * Update README for ABCI crate Signed-off-by: Thane Thomson <[email protected]> * Add ABCI integration test for minimal ABCI crate (#797) * Add integration testing utility for ABCI key/value store Signed-off-by: Thane Thomson <[email protected]> * Add hacky bash script to demonstrate parallel execution Signed-off-by: Thane Thomson <[email protected]> * Created abci test harness (#800) * Created abci test harness * cargo make additions and docs Co-authored-by: Greg Szabo <[email protected]> * Update abci/src/codec.rs Co-authored-by: Romain Ruetschi <[email protected]> * Apply suggestion from https://github.com/informalsystems/tendermint-rs/pull/794\#discussion_r573100911 Signed-off-by: Thane Thomson <[email protected]> * Refactor error handing and expose eyre::Result as crate default Result type Signed-off-by: Thane Thomson <[email protected]> * Refactor to use tracing instead of log Signed-off-by: Thane Thomson <[email protected]> * Add newline Signed-off-by: Thane Thomson <[email protected]> * Remove comment relating to constraints on Codec struct params Signed-off-by: Thane Thomson <[email protected]> * Version tendermint-abci crate in line with other tendermint-rs crates Signed-off-by: Thane Thomson <[email protected]> * Update CHANGELOG Signed-off-by: Thane Thomson <[email protected]> * Expand crate documentation Signed-off-by: Thane Thomson <[email protected]> * Extract request dispatch functionality from Application trait Signed-off-by: Thane Thomson <[email protected]> * Move ABCI server example to crate root Signed-off-by: Thane Thomson <[email protected]> * Fix broken link in docs Signed-off-by: Thane Thomson <[email protected]> * Replace EchoApp example with KeyValueStoreApp example Signed-off-by: Thane Thomson <[email protected]> Co-authored-by: Greg Szabo <[email protected]> Co-authored-by: Romain Ruetschi <[email protected]>
- Loading branch information
1 parent
0269414
commit a2596d5
Showing
28 changed files
with
1,614 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Generated by Cargo | ||
# will have compiled files and executables | ||
/target/ | ||
|
||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries | ||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html | ||
Cargo.lock | ||
|
||
# These are backup files generated by rustfmt | ||
**/*.rs.bk | ||
|
||
# These are log files emitted by model-based tests | ||
**/*.log | ||
|
||
# RPC probe results | ||
/rpc-probe/probe-results/ | ||
|
||
# Proptest regressions dumps | ||
**/*.proptest-regressions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
[workspace] | ||
|
||
members = [ | ||
"abci", | ||
"light-client", | ||
"light-node", | ||
"p2p", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[package] | ||
name = "tendermint-abci" | ||
version = "0.18.1" | ||
authors = ["Thane Thomson <[email protected]>"] | ||
edition = "2018" | ||
description = """ | ||
tendermint-abci provides a simple framework with which to build low-level | ||
applications on top of Tendermint. | ||
""" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[[bin]] | ||
name = "kvstore-rs" | ||
path = "src/application/kvstore/main.rs" | ||
required-features = [ "binary", "kvstore-app" ] | ||
|
||
[features] | ||
client = [] | ||
echo-app = [] | ||
kvstore-app = [] | ||
binary = [ "structopt", "tracing-subscriber" ] | ||
|
||
[dependencies] | ||
bytes = "1.0" | ||
eyre = "0.6" | ||
prost = "0.7" | ||
tendermint-proto = { version = "0.18.0", path = "../proto" } | ||
thiserror = "1.0" | ||
tracing = "0.1" | ||
|
||
structopt = { version = "0.3", optional = true } | ||
tracing-subscriber = { version = "0.2", optional = true } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
## tendermint-abci | ||
|
||
[![Crate][crate-image]][crate-link] | ||
[![Docs][docs-image]][docs-link] | ||
[![Build Status][build-image]][build-link] | ||
[![Audit Status][audit-image]][audit-link] | ||
[![Apache 2.0 Licensed][license-image]][license-link] | ||
![Rust Stable][rustc-image] | ||
|
||
[ABCI] framework for building low-level applications for Tendermint in Rust. | ||
|
||
## Requirements | ||
|
||
- The latest stable version of Rust | ||
|
||
## API | ||
|
||
At present, this crate only exposes a synchronous, blocking API based on Rust's | ||
standard library's networking capabilities. `async` client/server support is | ||
planned in future updates. | ||
|
||
The primary trait to be implemented by an ABCI application is the | ||
[`Application`] trait. One of the core ideas here is that an ABCI application | ||
must be able to be cloned for use in different threads, since Tendermint opens | ||
4 connections to the ABCI server. See the [spec][tendermint-abci-spec] for | ||
details. | ||
|
||
## Examples | ||
|
||
See [`src/application`](./src/application/) for some example applications | ||
written using this crate. | ||
|
||
To run the key/value store example application, from the `tendermint-abci` | ||
crate's directory: | ||
|
||
```bash | ||
# Set your logging level through RUST_LOG (e.g. RUST_LOG=info) | ||
# Binds to 127.0.0.1:26658 | ||
RUST_LOG=debug cargo run --bin kvstore-rs --features binary,kvstore-app | ||
|
||
# Reset and run your Tendermint node (binds RPC to 127.0.0.1:26657 by default) | ||
tendermint unsafe_reset_all && tendermint start | ||
|
||
# Submit a key/value pair (set "somekey" to "somevalue") | ||
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" | ||
# } | ||
#} | ||
|
||
# Query for the value we just submitted ("736f6d656b6579" is the hex | ||
# representation of "somekey") | ||
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": "189", | ||
# "codespace": "" | ||
# } | ||
# } | ||
#} | ||
``` | ||
|
||
## License | ||
|
||
Copyright © 2021 Informal Systems | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use the files in this repository except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
https://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
|
||
[//]: # (badges) | ||
|
||
[crate-image]: https://img.shields.io/crates/v/tendermint-abci.svg | ||
[crate-link]: https://crates.io/crates/tendermint-abci | ||
[docs-image]: https://docs.rs/tendermint-abci/badge.svg | ||
[docs-link]: https://docs.rs/tendermint-abci/ | ||
[build-image]: https://github.com/informalsystems/tendermint-rs/workflows/Rust/badge.svg | ||
[build-link]: https://github.com/informalsystems/tendermint-rs/actions?query=workflow%3ARust | ||
[audit-image]: https://github.com/informalsystems/tendermint-rs/workflows/Audit-Check/badge.svg | ||
[audit-link]: https://github.com/informalsystems/tendermint-rs/actions?query=workflow%3AAudit-Check | ||
[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg | ||
[license-link]: https://github.com/informalsystems/tendermint-rs/blob/master/LICENSE | ||
[rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg | ||
|
||
[//]: # (general links) | ||
|
||
[ABCI]: https://docs.tendermint.com/master/spec/abci/ | ||
[`Application`]: ./src/application.rs | ||
[tendermint-abci-spec]: https://github.com/tendermint/spec/blob/master/spec/abci/abci.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
//! ABCI application interface. | ||
#[cfg(feature = "echo-app")] | ||
pub mod echo; | ||
#[cfg(feature = "kvstore-app")] | ||
pub mod kvstore; | ||
|
||
use tendermint_proto::abci::request::Value; | ||
use tendermint_proto::abci::{ | ||
response, Request, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, | ||
RequestDeliverTx, RequestEcho, RequestEndBlock, RequestInfo, RequestInitChain, | ||
RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, RequestSetOption, Response, | ||
ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, ResponseCommit, | ||
ResponseDeliverTx, ResponseEcho, ResponseEndBlock, ResponseFlush, ResponseInfo, | ||
ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot, | ||
ResponseQuery, ResponseSetOption, | ||
}; | ||
|
||
/// An ABCI application. | ||
/// | ||
/// Applications are `Send` + `Clone` + `'static` because they are cloned for | ||
/// each incoming connection to the ABCI [`Server`]. It is up to the | ||
/// application developer to manage shared state between these clones of their | ||
/// application. | ||
/// | ||
/// [`Server`]: crate::Server | ||
pub trait Application: Send + Clone + 'static { | ||
/// Echo back the same message as provided in the request. | ||
fn echo(&self, request: RequestEcho) -> ResponseEcho { | ||
ResponseEcho { | ||
message: request.message, | ||
} | ||
} | ||
|
||
/// Provide information about the ABCI application. | ||
fn info(&self, _request: RequestInfo) -> ResponseInfo { | ||
Default::default() | ||
} | ||
|
||
/// Called once upon genesis. | ||
fn init_chain(&self, _request: RequestInitChain) -> ResponseInitChain { | ||
Default::default() | ||
} | ||
|
||
/// Query the application for data at the current or past height. | ||
fn query(&self, _request: RequestQuery) -> ResponseQuery { | ||
Default::default() | ||
} | ||
|
||
/// Check the given transaction before putting it into the local mempool. | ||
fn check_tx(&self, _request: RequestCheckTx) -> ResponseCheckTx { | ||
Default::default() | ||
} | ||
|
||
/// Signals the beginning of a new block, prior to any `DeliverTx` calls. | ||
fn begin_block(&self, _request: RequestBeginBlock) -> ResponseBeginBlock { | ||
Default::default() | ||
} | ||
|
||
/// Apply a transaction to the application's state. | ||
fn deliver_tx(&self, _request: RequestDeliverTx) -> ResponseDeliverTx { | ||
Default::default() | ||
} | ||
|
||
/// Signals the end of a block. | ||
fn end_block(&self, _request: RequestEndBlock) -> ResponseEndBlock { | ||
Default::default() | ||
} | ||
|
||
/// Signals that messages queued on the client should be flushed to the server. | ||
fn flush(&self) -> ResponseFlush { | ||
ResponseFlush {} | ||
} | ||
|
||
/// Commit the current state at the current height. | ||
fn commit(&self) -> ResponseCommit { | ||
Default::default() | ||
} | ||
|
||
/// Allows the Tendermint node to request that the application set an | ||
/// option to a particular value. | ||
fn set_option(&self, _request: RequestSetOption) -> ResponseSetOption { | ||
Default::default() | ||
} | ||
|
||
/// Used during state sync to discover available snapshots on peers. | ||
fn list_snapshots(&self) -> ResponseListSnapshots { | ||
Default::default() | ||
} | ||
|
||
/// Called when bootstrapping the node using state sync. | ||
fn offer_snapshot(&self, _request: RequestOfferSnapshot) -> ResponseOfferSnapshot { | ||
Default::default() | ||
} | ||
|
||
/// Used during state sync to retrieve chunks of snapshots from peers. | ||
fn load_snapshot_chunk(&self, _request: RequestLoadSnapshotChunk) -> ResponseLoadSnapshotChunk { | ||
Default::default() | ||
} | ||
|
||
/// Apply the given snapshot chunk to the application's state. | ||
fn apply_snapshot_chunk( | ||
&self, | ||
_request: RequestApplySnapshotChunk, | ||
) -> ResponseApplySnapshotChunk { | ||
Default::default() | ||
} | ||
} | ||
|
||
/// Provides a mechanism for the [`Server`] to execute incoming requests while | ||
/// expecting the correct response types. | ||
pub trait RequestDispatcher { | ||
/// Executes the relevant application method based on the type of the | ||
/// request, and produces the corresponding response. | ||
fn handle(&self, request: Request) -> Response; | ||
} | ||
|
||
// Implement `RequestDispatcher` for all `Application`s. | ||
impl<A: Application> RequestDispatcher for A { | ||
fn handle(&self, request: Request) -> Response { | ||
tracing::debug!("Incoming request: {:?}", request); | ||
Response { | ||
value: Some(match request.value.unwrap() { | ||
Value::Echo(req) => response::Value::Echo(self.echo(req)), | ||
Value::Flush(_) => response::Value::Flush(self.flush()), | ||
Value::Info(req) => response::Value::Info(self.info(req)), | ||
Value::SetOption(req) => response::Value::SetOption(self.set_option(req)), | ||
Value::InitChain(req) => response::Value::InitChain(self.init_chain(req)), | ||
Value::Query(req) => response::Value::Query(self.query(req)), | ||
Value::BeginBlock(req) => response::Value::BeginBlock(self.begin_block(req)), | ||
Value::CheckTx(req) => response::Value::CheckTx(self.check_tx(req)), | ||
Value::DeliverTx(req) => response::Value::DeliverTx(self.deliver_tx(req)), | ||
Value::EndBlock(req) => response::Value::EndBlock(self.end_block(req)), | ||
Value::Commit(_) => response::Value::Commit(self.commit()), | ||
Value::ListSnapshots(_) => response::Value::ListSnapshots(self.list_snapshots()), | ||
Value::OfferSnapshot(req) => { | ||
response::Value::OfferSnapshot(self.offer_snapshot(req)) | ||
} | ||
Value::LoadSnapshotChunk(req) => { | ||
response::Value::LoadSnapshotChunk(self.load_snapshot_chunk(req)) | ||
} | ||
Value::ApplySnapshotChunk(req) => { | ||
response::Value::ApplySnapshotChunk(self.apply_snapshot_chunk(req)) | ||
} | ||
}), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
//! Trivial ABCI echo application | ||
use crate::Application; | ||
|
||
/// Trivial echo application, mainly for testing purposes. | ||
#[derive(Clone)] | ||
pub struct EchoApp; | ||
|
||
impl Default for EchoApp { | ||
fn default() -> Self { | ||
Self {} | ||
} | ||
} | ||
|
||
impl Application for EchoApp {} |
Oops, something went wrong.