Skip to content

Commit

Permalink
feat(tsp): Basic implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
adetante committed Aug 29, 2017
0 parents commit 84f0852
Show file tree
Hide file tree
Showing 15 changed files with 680 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
.idea/
target/
56 changes: 56 additions & 0 deletions README.md
@@ -0,0 +1,56 @@
# tendermint-server

Scala implementation of Tendermint TSP ABCI Server (see [Tendermint documentation](https://tendermint.com/docs/guides/app-development#tsp)) using Akka Stream.


## Build & run the example

Run the main class `lu.intech.tendermint.Main` which starts a TSP server:

```
sbt run
```

In parallel, run **abci-cli**:

```
abci-cli info
```

or **tendermint**:

```
tendermint node
```

This basic implementation logs messages to stdout.


## Integration in your application

The purpose of this project is to integrate tendermint in your Scala application.
You have to create an instance of the `Server` class, and set your implementations to handle TSP messages:


```
implicit val system: ActorSystem = ActorSystem()
implicit val materializer: Materializer = ActorMaterializer()
import scala.concurrent.ExecutionContext.Implicits.global
val server = new Server(
consensusHandler = new lu.intech.tendermint.ConsensusHandler { /* ... */ } ,
mempoolHandler = new lu.intech.tendermint.MempoolHandler { /* ... */ } ,
queryHandler = new lu.intech.tendermint.QueryHandler { /* ... */ } ,
/* default values */
/* host = "127.0.0.1" ,*/
/* port = 46658 ,*/
)
server.start()
```

## Logging

`tendermint-server` uses **slf4j** as logging api and **logback** binding by default.
If you want to configure loggers, just provide a `logback.xml` file.
23 changes: 23 additions & 0 deletions build.sbt
@@ -0,0 +1,23 @@
import Dependencies._

lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "lu.intech",
scalaVersion := "2.12.3",
version := "0.1.0-SNAPSHOT"
)),
name := "tendermint-server",
libraryDependencies ++= Seq(
akkaStream,
grpcNetty,
grpcScalapb,
protobuf,
slf4jApi,
logbackClassic
)
)

PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
)
11 changes: 11 additions & 0 deletions project/Dependencies.scala
@@ -0,0 +1,11 @@
import sbt._

object Dependencies {
lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.3"
lazy val akkaStream = "com.typesafe.akka" %% "akka-stream" % "2.5.4"
lazy val grpcNetty = "io.grpc" % "grpc-netty" % com.trueaccord.scalapb.compiler.Version.grpcJavaVersion
lazy val grpcScalapb = "com.trueaccord.scalapb" %% "scalapb-runtime-grpc" % com.trueaccord.scalapb.compiler.Version.scalapbVersion
lazy val protobuf = "com.google.protobuf" % "protobuf-java" % "3.4.0"
lazy val slf4jApi = "org.slf4j" % "slf4j-api" % "1.7.25"
lazy val logbackClassic = "ch.qos.logback" % "logback-classic" % "1.2.3"
}
1 change: 1 addition & 0 deletions project/build.properties
@@ -0,0 +1 @@
sbt.version=0.13.16
1 change: 1 addition & 0 deletions project/sbtRevolver.sbt
@@ -0,0 +1 @@
addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.0")
2 changes: 2 additions & 0 deletions project/scalapb.sbt
@@ -0,0 +1,2 @@
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.11")
libraryDependencies += "com.trueaccord.scalapb" %% "compilerplugin" % "0.6.2"
241 changes: 241 additions & 0 deletions src/main/protobuf/types.proto
@@ -0,0 +1,241 @@
syntax = "proto3";
package types;

// This file is copied from http://github.com/tendermint/abci

//----------------------------------------
// Code types

enum CodeType {
OK = 0;

// General response codes, 0 ~ 99
InternalError = 1;
EncodingError = 2;
BadNonce = 3;
Unauthorized = 4;
InsufficientFunds = 5;
UnknownRequest = 6;

// Reserved for basecoin, 100 ~ 199
BaseDuplicateAddress = 101;
BaseEncodingError = 102;
BaseInsufficientFees = 103;
BaseInsufficientFunds = 104;
BaseInsufficientGasPrice = 105;
BaseInvalidInput = 106;
BaseInvalidOutput = 107;
BaseInvalidPubKey = 108;
BaseInvalidSequence = 109;
BaseInvalidSignature = 110;
BaseUnknownAddress = 111;
BaseUnknownPubKey = 112;
BaseUnknownPlugin = 113;

// Reserved for governance, 200 ~ 299
GovUnknownEntity = 201;
GovUnknownGroup = 202;
GovUnknownProposal = 203;
GovDuplicateGroup = 204;
GovDuplicateMember = 205;
GovDuplicateProposal = 206;
GovDuplicateVote = 207;
GovInvalidMember = 208;
GovInvalidVote = 209;
GovInvalidVotingPower = 210;

}

//----------------------------------------
// Request types

message Request {
oneof value{
RequestEcho echo = 1;
RequestFlush flush = 2;
RequestInfo info = 3;
RequestSetOption set_option = 4;
RequestDeliverTx deliver_tx = 5;
RequestCheckTx check_tx = 6;
RequestCommit commit = 7;
RequestQuery query = 8;
RequestInitChain init_chain = 9;
RequestBeginBlock begin_block = 10;
RequestEndBlock end_block = 11;
}
}

message RequestEcho {
string message = 1;
}

message RequestFlush {
}

message RequestInfo {
}

message RequestSetOption{
string key = 1;
string value = 2;
}

message RequestDeliverTx{
bytes tx = 1;
}

message RequestCheckTx{
bytes tx = 1;
}

message RequestQuery{
bytes data = 1;
string path = 2;
uint64 height = 3;
bool prove = 4;
}

message RequestCommit{
}

message RequestInitChain{
repeated Validator validators = 1;
}

message RequestBeginBlock{
bytes hash = 1;
Header header = 2;
}

message RequestEndBlock{
uint64 height = 1;
}

//----------------------------------------
// Response types


message Response {
oneof value{
ResponseException exception = 1;
ResponseEcho echo = 2;
ResponseFlush flush = 3;
ResponseInfo info = 4;
ResponseSetOption set_option = 5;
ResponseDeliverTx deliver_tx = 6;
ResponseCheckTx check_tx = 7;
ResponseCommit commit = 8;
ResponseQuery query = 9;
ResponseInitChain init_chain = 10;
ResponseBeginBlock begin_block = 11;
ResponseEndBlock end_block = 12;
}
}

message ResponseException{
string error = 1;
}

message ResponseEcho {
string message = 1;
}

message ResponseFlush{
}

message ResponseInfo {
string data = 1;
string version = 2;
uint64 last_block_height = 3;
bytes last_block_app_hash = 4;
}

message ResponseSetOption{
string log = 1;
}

message ResponseDeliverTx{
CodeType code = 1;
bytes data = 2;
string log = 3;
}

message ResponseCheckTx{
CodeType code = 1;
bytes data = 2;
string log = 3;
}

message ResponseQuery{
CodeType code = 1;
int64 index = 2;
bytes key = 3;
bytes value = 4;
bytes proof = 5;
uint64 height = 6;
string log = 7;
}

message ResponseCommit{
CodeType code = 1;
bytes data = 2;
string log = 3;
}


message ResponseInitChain{
}

message ResponseBeginBlock{
}

message ResponseEndBlock{
repeated Validator diffs = 1;
}

//----------------------------------------
// Blockchain Types

message Header {
string chain_id = 1;
uint64 height = 2;
uint64 time = 3;
uint64 num_txs = 4;
BlockID last_block_id = 5;
bytes last_commit_hash = 6;
bytes data_hash = 7;
bytes validators_hash = 8;
bytes app_hash = 9;
}

message BlockID {
bytes hash = 1;
PartSetHeader parts = 2;
}

message PartSetHeader {
uint64 total = 1;
bytes hash = 2;
}

message Validator {
bytes pubKey = 1;
uint64 power = 2;
}

//----------------------------------------
// Service Definition

service ABCIApplication {
rpc Echo(RequestEcho) returns (ResponseEcho) ;
rpc Flush(RequestFlush) returns (ResponseFlush);
rpc Info(RequestInfo) returns (ResponseInfo);
rpc SetOption(RequestSetOption) returns (ResponseSetOption);
rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx);
rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx);
rpc Query(RequestQuery) returns (ResponseQuery);
rpc Commit(RequestCommit) returns (ResponseCommit);
rpc InitChain(RequestInitChain) returns (ResponseInitChain);
rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock);
rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock);
}
22 changes: 22 additions & 0 deletions src/main/resources/logback.xml
@@ -0,0 +1,22 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
</encoder>
</appender>

<logger name="tsp.messages" level="ERROR" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="tsp.server" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="handler" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
</logger>

<root level="error">
<appender-ref ref="STDOUT" />
</root>
</configuration>

0 comments on commit 84f0852

Please sign in to comment.