338 lines
11 KiB
Plaintext
338 lines
11 KiB
Plaintext
= Emerald Dshackle
|
|
:imagesdir: docs/assets
|
|
ifdef::env-github[]
|
|
:imagesdir: https://raw.githubusercontent.com/emeraldpay/dshackle/master/docs/assets
|
|
endif::[]
|
|
|
|
image:https://github.com/emeraldpay/dshackle/workflows/Tests/badge.svg["Unit Tests"]
|
|
image:https://img.shields.io/docker/pulls/emeraldpay/dshackle?style=flat-square["Docker",link="https://hub.docker.com/r/emeraldpay/dshackle"]
|
|
image:https://img.shields.io/github/license/emeraldpay/dshackle.svg?style=flat-square&maxAge=2592000["License",link="https://github.com/emeraldpay/dshackle/blob/master/LICENSE"]
|
|
image:https://badges.gitter.im/emeraldpay/community.svg[link="https://gitter.im/emeraldpay/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge]
|
|
|
|
_Dshackle is an L7 Blockchain API Load Balancer._ It provides a high level aggregated API on top of several underlying upstreams.
|
|
I.e. on top of blockchain nodes such as Bitcoind, Geth, Parity, or providers like Infura, and so on.
|
|
It automatically verifies their availability and the current status of the network, executes commands making sure that the response is consistent and/or data successfully broadcasted to the network.
|
|
|
|
- Standard Bitcoin and Ethereum JSON RPC API, plus enhanced gRPC-based API
|
|
- **Secure** TLS with optional client authentication
|
|
- Blockchain-aware **caching** in memory and in Redis
|
|
- Routing based on **data availability** (peers, height, sync status)
|
|
- **Data consistency**, always gives the most actual state
|
|
- Automatic **failover** and retry
|
|
- Separate public blockchain nodes from your internal servers
|
|
|
|
Dshackle allows to build a mesh network of interconnected Dshackle servers for building blockchain based services that needs to have fast, secure, stable and fail-proof access to blockchain APIs.
|
|
|
|
Blockchain support:
|
|
|
|
- Ethereum, Ethereum Classic and Kovan testnet
|
|
- Bitcoin and Bitcoin Testnet
|
|
|
|
WARNING: The project is still under development, please use with caution.
|
|
|
|
Dshackle connects to several upstreams via JSON RPC, Websockets, or gRPC protocol.
|
|
The server verifies if a node ("upstream") is fully synchronized (not in initial sync mode), has enough peers, and its height is not behind other nodes.
|
|
If upstream lags behind others, lost peers below required, started to resync or went down, then Dshackle temporarily excludes it from requests and returns it when the upstream problem is fixed.
|
|
|
|
image::dshackle-intro.png[alt="",width=80%,align="center"]
|
|
|
|
== Roadmap
|
|
|
|
- [ ] External logging
|
|
- [ ] Access to ERC-20 tokens on asset level
|
|
- [ ] Subscription to bitcoind notification over gRPC (instead of ZeroMQ)
|
|
- [ ] Prometheus monitoring
|
|
- [ ] BIP-32 Pubkey
|
|
- [ ] Lightweight sidecar node connector
|
|
- [ ] Configurable upstream roles
|
|
|
|
== Quick Start
|
|
|
|
=== Configuration
|
|
|
|
Create file `dshackle.yaml` with the following content:
|
|
|
|
[source,yaml]
|
|
----
|
|
version: v1
|
|
port: 2449
|
|
tls:
|
|
enabled: false
|
|
|
|
proxy:
|
|
host: 0.0.0.0
|
|
port: 8545
|
|
routes:
|
|
- id: eth
|
|
blockchain: ethereum
|
|
- id: btc
|
|
blockchain: bitcoin
|
|
|
|
cluster:
|
|
upstreams:
|
|
- id: infura-eth
|
|
chain: ethereum
|
|
connection:
|
|
ethereum:
|
|
rpc:
|
|
url: "https://mainnet.infura.io/v3/${INFURA_USER}"
|
|
ws:
|
|
url: "wss://mainnet.infura.io/ws/v3/${INFURA_USER}"
|
|
- id: bitcoin-main
|
|
chain: bitcoin
|
|
connection:
|
|
bitcoin:
|
|
rpc:
|
|
url: "http://localhost:8332"
|
|
basic-auth:
|
|
username: bitcoin
|
|
password: mypassword
|
|
----
|
|
|
|
Which sets the following:
|
|
|
|
- gRPC access through 0.0.0.0:2449
|
|
** TLS security is disabled (_please don't use in production!_)
|
|
- JSON RPC access through 0.0.0.0:8545
|
|
** proxy requests to Ethereum and Kovan upstreams
|
|
** request path for Ethereum Mainnet is `/eth`, for bitcoin is `/btc`
|
|
** i.e. call Ethereum Mainnet by `POST http://127.0.0.0:8545/eth` with JSON RPC payload
|
|
- two upstreams, one for Ethereum Mainnet and another for Kovan Testnet (both upstreams are configured to use Infura endpoint)
|
|
- for Ethereum Mainnet it connects using JSON RPC and Websockets connections,
|
|
- for Bitcoin Mainet only JSON RPC is used
|
|
- `${INFURA_USER}` will be provided through environment variable
|
|
|
|
|
|
link:docs[See full documentations].
|
|
|
|
==== Run docker image
|
|
|
|
Official Docker image you can find at: emeraldpay/dshackle
|
|
|
|
.Setup Infura username
|
|
[source,bash]
|
|
----
|
|
export INFURA_USER=...
|
|
----
|
|
|
|
.Run Dshackle
|
|
[source,bash]
|
|
----
|
|
docker run -p 2449:2449 -p 8545:8545 -v $(pwd):/etc/dshackle -e "INFURA_USER=$INFURA_USER" emeraldpay/dshackle
|
|
----
|
|
|
|
Now it listen on port 2449 at the localhost and can be connected from any gRPC compatible client.
|
|
Tools such as https://github.com/fullstorydev/grpcurl[gRPCurl] can automatically parse protobuf definitions and connect to it (actual Protobuf sources are located in a separate repository which you can find at https://github.com/emeraldpay/proto)
|
|
|
|
Alternatively you can connect to port 8545 with traditional JSON RPC requests
|
|
|
|
==== Access using JSON RPC
|
|
|
|
Dshackle implements standard JSON RPC interface, providing additional caching layer, upstream readiness/liveness checks, retry and other features for building Fault Tolerant services.
|
|
|
|
.Request using Curl
|
|
[source,bash]
|
|
----
|
|
curl --request POST \
|
|
--url http://localhost:8545/eth \
|
|
--header 'content-type: application/json' \
|
|
--data '{"jsonrpc":"2.0", "method":"eth_getBalance", "id":1, "params":["0x690b2bdf41f33f9f251ae0459e5898b856ed96be", "latest"]}'
|
|
----
|
|
|
|
.Output
|
|
[source,bash]
|
|
----
|
|
{"jsonrpc":"2.0","id":1,"result":"0x72fa5e0181"}
|
|
----
|
|
|
|
==== Access using gRPC
|
|
|
|
NOTE: It's not necessary to use gRPC, as Dshackle can provide standard JSON RPC proxy, but Dshackle gRPC interface improves performance and provides additional features.
|
|
|
|
Dshackle provides a custom gRPC based API, which provides additional methods and other features such as streaming responses.
|
|
Please refer to the documentation: link:docs/06-methods.adoc[gRPC Methods]
|
|
|
|
.Connect and listen for new blocks on Ethereum Mainnet
|
|
[source,bash]
|
|
----
|
|
grpcurl -import-path ./proto/ -proto blockchain.proto -d "{\"type\": 100}" -plaintext 127.0.0.1:2449 emerald.Blockchain/SubscribeHead
|
|
----
|
|
|
|
`type: 100` specifies the blockchain id, and 100 means Ethereum Mainnet. `1` is for Bitcoin Mainnet.
|
|
There we use Ethereum because it creates new blocks every 14 seconds, which works better for demo purposes, but the same request applied to Bitcoin as well.
|
|
|
|
.Output would be like
|
|
----
|
|
{
|
|
"chain": "CHAIN_ETHEREUM",
|
|
"height": 8396159,
|
|
"blockId": "fc58a258adccc94466ae967b1178eea721349b0667f59d5fe1b0b436460bce75",
|
|
"timestamp": 1566423564000,
|
|
"weight": "AnMcf2VJB5kOSQ=="
|
|
}
|
|
{
|
|
"chain": "CHAIN_ETHEREUM",
|
|
"height": 8396160,
|
|
"blockId": "787899711b862b77df8d2faa69de664048598265a9f96abf178d341076e200e0",
|
|
"timestamp": 1566423574000,
|
|
"weight": "AnMch35tO6hSGg=="
|
|
}
|
|
...
|
|
...
|
|
----
|
|
|
|
The output above is for a _streaming subscription_ to all new blocks on the Ethereum Mainnet.
|
|
|
|
It's one of the services provided by Dshackle, in addition to standard methods provided by RPC JSON of underlying nodes.
|
|
|
|
.You can also subscribe to balances changes of the balance on an address:
|
|
[source,bash]
|
|
----
|
|
grpcurl -import-path ./proto/ -proto blockchain.proto -d '{"asset": {"chain": "100", "code": "ether"}, "address": {"address_single": {"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"}}}' -plaintext 127.0.0.1:2449 emerald.Blockchain/SubscribeBalance
|
|
----
|
|
|
|
.and see how balance of the contract responsible for Wrapped Ether is changing:
|
|
----
|
|
{
|
|
"asset": {
|
|
"chain": "CHAIN_ETHEREUM",
|
|
"code": "ETHER"
|
|
},
|
|
"address": {
|
|
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
|
},
|
|
"balance": "2410941696896999943701015"
|
|
}
|
|
{
|
|
"asset": {
|
|
"chain": "CHAIN_ETHEREUM",
|
|
"code": "ETHER"
|
|
},
|
|
"address": {
|
|
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
|
},
|
|
"balance": "2410930748488073834320430"
|
|
}
|
|
...
|
|
----
|
|
|
|
See other enhanced methods in the link:docs/06-methods.adoc[Documentation for Enhanced Methods]
|
|
|
|
== Documentation
|
|
|
|
For detailed documentation see link:docs/[] directory.
|
|
|
|
== Client Libraries
|
|
|
|
=== JSON RPC
|
|
|
|
Dshackle should be compatible with all standard libraries that use Ethereum JSON RPC over HTTP.
|
|
|
|
=== Java gRPC Client
|
|
|
|
image:https://api.bintray.com/packages/emerald/emerald-grpc/emerald-grpc/images/download.svg[link="https://bintray.com/emerald/emerald-grpc/emerald-grpc/"]
|
|
|
|
https://github.com/emeraldpay/emerald-java-client
|
|
|
|
[source,groovy]
|
|
----
|
|
repositories {
|
|
maven {
|
|
url "https://dl.bintray.com/emerald/emerald-grpc"
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
compile "io.emeraldpay:emerald-grpc:0.6.0-0.2"
|
|
}
|
|
----
|
|
|
|
=== Javascript gRPC Client
|
|
image:https://img.shields.io/npm/v/@emeraldpay/grpc-client.svg["npm (scoped)", link="https://www.npmjs.com/package/@emeraldpay/grpc-client"]
|
|
|
|
https://github.com/emeraldpay/emerald-js-grpc
|
|
|
|
[source,json]
|
|
----
|
|
"dependencies": {
|
|
"@emeraldpay/grpc-client": "0.11.0-0.2",
|
|
}
|
|
----
|
|
|
|
See more in the documentation for link:docs/10-client-libraries.adoc[Client Libraries].
|
|
|
|
== Development
|
|
|
|
WARNING: The code in `master` branch is considered a development version, which may lack proper testing and should not be used in production.
|
|
|
|
=== Setting up environment
|
|
|
|
Dshackle is JVM based project written in Kotlin.
|
|
To build and run it from sources you'll need to install https://openjdk.java.net/projects/jdk/11/[Java JDK] and https://gradle.org/[Gradle]
|
|
|
|
=== Build Dshackle
|
|
|
|
==== Build everything
|
|
|
|
[source,bash]
|
|
----
|
|
gradle build
|
|
----
|
|
|
|
==== Make a Zip distribution
|
|
|
|
[source, bash]
|
|
----
|
|
gradle distZip
|
|
----
|
|
|
|
You can find a redistributable zip in `build/distributions`
|
|
|
|
==== Make a Docker distribution
|
|
|
|
[source, bash]
|
|
----
|
|
gradle jib -Pdocker=gcr.io/myproject
|
|
----
|
|
|
|
Gradle will prepare a Docker image and upload it to your custom Docker Registry at `gcr.io/myproject` (please change to address of your actual registry)
|
|
|
|
==== Architecture
|
|
|
|
Dshackle is built using:
|
|
|
|
- Kotlin
|
|
- Spring Framework + Spring Boot
|
|
- Spring Reactor
|
|
- Netty
|
|
- Etherjar
|
|
- gRPC and HTTP2 protocol
|
|
- Groovy and Spock for testing
|
|
|
|
|
|
== Community
|
|
|
|
=== Development Chat
|
|
|
|
image:https://badges.gitter.im/emeraldpay/community.svg[link="https://gitter.im/emeraldpay/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge]
|
|
|
|
== Commercial Support
|
|
|
|
Want to support the project, prioritize a specific feature, or get commercial help with using Dshackle in your project?
|
|
Please contact splix@emeraldpay.io to discuss the possibility
|
|
|
|
== License
|
|
|
|
Copyright 2019 ETCDEV GmbH
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://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. |