add README & mock validators count

This commit is contained in:
folex 2019-06-16 14:59:52 +02:00
parent d4d2e0f985
commit a9c1a5ea53
4 changed files with 79 additions and 18 deletions

View File

@ -1 +1,56 @@
# cosmos-hackathon-backend # Shared Security for Cosmos Zones
![logo](img/salmon.png)
- Backend here
- Frontend [there](https://github.com/fluencelabs/cosmos-hackathon-frontend)
## If you want your Zone to be validated by Cosmic Salmon, reach out to @folexeyy on Telegram
# How to run
```bash
sbt assembly
java -jar ./target/scala-2.12/http-scala-api-assembly-0.1.jar
```
# API
### Retreieve running apps
```bash
curl http://salmon.fluence.one:8080/apps
```
```json
[
{
"name" : "nameservice",
"network" : "namechain",
"binaryHash" : "QmQ69JoPDaKFpPSbWvvUGRGG5E83u6nTP2hRegmCoa6aW5",
"consensusHeight" : 69386,
"validatorsCount" : 4
},
{
"name" : "commercionetwork",
"network" : "commercio-testnet1001",
"binaryHash" : "QmepV645qHM9XR97KiK7Bvd2jjK3MiKTGbq8cYm7izRyQK",
"consensusHeight" : 38783,
"validatorsCount" : 4
}
]
```
### Add your app on validation
- `nameservice` - any name for your app
- `207.154.210.117` - IP address of your validator node
- `26657` - RPC port
- `QmQ69JoPDaKFpPSbWvvUGRGG5E83u6nTP2hRegmCoa6aW5` - IPFS hash of the Zone app binary (built against glibc)
```bash
curl http://salmon.fluence.one:8080/create/nameservice/207.154.210.117/26657/QmQ69JoPDaKFpPSbWvvUGRGG5E83u6nTP2hRegmCoa6aW5"
```
### Stream validation results through websocket
JavaScript
```js
var ws = new WebSocket("ws://localhost:8080/websocket/commercionetwork")
ws.onmessage = console.log
```
For shell, use [websocat](https://github.com/vi/websocat).

BIN
img/salmon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View File

@ -9,6 +9,7 @@ import cats.effect._
import cats.effect.concurrent.{Deferred, Ref, TryableDeferred} import cats.effect.concurrent.{Deferred, Ref, TryableDeferred}
import cats.instances.list._ import cats.instances.list._
import cats.instances.option._ import cats.instances.option._
import cats.instances.either._
import cats.syntax.applicative._ import cats.syntax.applicative._
import cats.syntax.applicativeError._ import cats.syntax.applicativeError._
import cats.syntax.either._ import cats.syntax.either._
@ -17,7 +18,7 @@ import cats.syntax.functor._
import cats.syntax.option._ import cats.syntax.option._
import cats.{Monad, Traverse} import cats.{Monad, Traverse}
import com.softwaremill.sttp.{SttpBackend, Uri, sttp} import com.softwaremill.sttp.{SttpBackend, Uri, sttp}
import hackhack.ipfs.{IpfsError, IpfsStore} import hackhack.ipfs.{IpfsError, IpfsStore, Multihash}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.parser.parse import io.circe.parser.parse
import io.circe.{Decoder, Encoder, Json, ObjectEncoder} import io.circe.{Decoder, Encoder, Json, ObjectEncoder}
@ -54,8 +55,9 @@ object App {
case class AppInfo(name: String, case class AppInfo(name: String,
network: String, network: String,
binaryHash: ByteVector, binaryHash: String,
consensusHeight: Long) consensusHeight: Long,
validatorsCount: Int)
object AppInfo { object AppInfo {
private implicit val encbc: Encoder[ByteVector] = private implicit val encbc: Encoder[ByteVector] =
@ -180,8 +182,9 @@ class AppRegistry[F[_]: Monad: Concurrent: ContextShift: Timer: LiftIO](
case (app, status) => case (app, status) =>
AppInfo(app.name, AppInfo(app.name,
status.node_info.network, status.node_info.network,
app.binaryHash, Multihash.asBase58(app.binaryHash),
status.sync_info.latest_block_height) status.sync_info.latest_block_height,
4)
} }
} }

View File

@ -50,19 +50,21 @@ object ResponseOps {
} }
} }
object Multihash {
// https://github.com/multiformats/multicodec/blob/master/table.csv
val SHA256 = ByteVector(0x12, 32) // 0x12 => SHA256; 32 = 256 bits in bytes
def asBase58(hash: ByteVector): String = (SHA256 ++ hash).toBase58
}
class IpfsClient[F[_]: Monad](ipfsUri: Uri)( class IpfsClient[F[_]: Monad](ipfsUri: Uri)(
implicit sttpBackend: SttpBackend[EitherT[F, Throwable, ?], fs2.Stream[F, ByteBuffer]] implicit sttpBackend: SttpBackend[EitherT[F, Throwable, ?],
fs2.Stream[F, ByteBuffer]]
) { ) {
import IpfsClient._ import IpfsClient._
import IpfsLsResponse._ import IpfsLsResponse._
import ResponseOps._ import ResponseOps._
object Multihash {
// https://github.com/multiformats/multicodec/blob/master/table.csv
val SHA256 = ByteVector(0x12, 32) // 0x12 => SHA256; 32 = 256 bits in bytes
}
// URI for downloading data // URI for downloading data
private val CatUri = ipfsUri.path("/api/v0/cat") private val CatUri = ipfsUri.path("/api/v0/cat")
@ -80,12 +82,13 @@ class IpfsClient[F[_]: Monad](ipfsUri: Uri)(
ByteVector.fromBase58Descriptive(str).map(_.drop(2)) ByteVector.fromBase58Descriptive(str).map(_.drop(2))
/** /**
* Downloads data from IPFS. * Downloads data from IPFS.
* *
* @param hash data address in IPFS * @param hash data address in IPFS
* @return * @return
*/ */
def download(hash: ByteVector): EitherT[F, Throwable, fs2.Stream[F, ByteBuffer]] = { def download(
hash: ByteVector): EitherT[F, Throwable, fs2.Stream[F, ByteBuffer]] = {
// implicit val wtf = sttpBackend // implicit val wtf = sttpBackend
val address = toAddress(hash) val address = toAddress(hash)
val uri = CatUri.param("arg", address) val uri = CatUri.param("arg", address)