diff --git a/README.adoc b/README.adoc index ef14b8f2e..f25ab5177 100644 --- a/README.adoc +++ b/README.adoc @@ -9,10 +9,11 @@ image:https://img.shields.io/docker/pulls/emeraldpay/dshackle?style=flat-square[ 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 provided a high level aggregated API on top of several underlying upstreams, i.e., blockchain nodes or providers, such as Geth, Parity, Infura, etc. -It automatically verifies their availability and the current status of the network, executes commands making sure that the response is consistent and/or sent data successfully broadcasted to the network. +_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 Ethereum JSON RPC API, plus advanced gRPC-based API +- 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) @@ -22,6 +23,13 @@ It automatically verifies their availability and the current status of the netwo 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. @@ -30,7 +38,6 @@ image::dshackle-intro.png[alt="",width=80%,align="center"] == Roadmap -- [ ] Support Bitcoin RPC - [ ] External logging - [ ] Access to ERC-20 tokens on asset level - [ ] Subscription to bitcoind notification over gRPC (instead of ZeroMQ) @@ -58,8 +65,8 @@ proxy: routes: - id: eth blockchain: ethereum - - id: kovan - blockchain: kovan + - id: btc + blockchain: bitcoin cluster: upstreams: @@ -71,12 +78,15 @@ cluster: url: "https://mainnet.infura.io/v3/${INFURA_USER}" ws: url: "wss://mainnet.infura.io/ws/v3/${INFURA_USER}" - - id: infura-kovan - chain: kovan + - id: bitcoin-main + chain: bitcoin connection: - ethereum: + bitcoin: rpc: - url: "https://kovan.infura.io/v3/${INFURA_USER}" + url: "http://localhost:8332" + basic-auth: + username: bitcoin + password: mypassword ---- Which sets the following: @@ -85,11 +95,11 @@ Which sets the following: ** 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 Kovan is `/kovan` -** i.e. call Mainnet by `POST http://127.0.0.0:8545/eth` with JSON RPC payload +** 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 Kovan only JSON RPC is used -- Infura authentication config is omitted for this demo +- 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 @@ -137,15 +147,20 @@ curl --request POST \ ==== 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 io.emeraldpay.api.Blockchain/SubscribeHead +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 ---- { @@ -166,8 +181,42 @@ grpcurl -import-path ./proto/ -proto blockchain.proto -d "{\"type\": 100}" -plai ... ---- -The output above is for a _streaming subscription_ to all new blocks on Ethereum Mainnet. -It's one of services provided by Dshackle, in additional to standard methods provided by RPC JSON of underlying nodes. +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 @@ -214,6 +263,8 @@ See more in the documentation for link:docs/10-client-libraries.adoc[Client Libr == 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. diff --git a/docs/00-intro.adoc b/docs/00-intro.adoc index 5530ad48f..501be5ac8 100644 --- a/docs/00-intro.adoc +++ b/docs/00-intro.adoc @@ -3,14 +3,13 @@ Dshackle is an L7 Blockchain API Load Balancer with automatic discovery and health checking, authentication, and TLS termination. It is designed to work as an edge proxy, middle proxy, or API gateway. -Dshackle provided a high level aggregated API on top of several underlying upstreams (blockchain nodes or providers, such -as Geth, Parity, Infura, etc), 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. +Dshackle provides a high level aggregated API on top of several underlying upstreams. +I.e. to 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. Example use cases: -- Read a _transaction_ - Dshackle tries to find it on different nodes and retries until it's found or there is a - consistent answer from upstreams that the transaction doesn't exist +- Read a _transaction_ - Dshackle tries to find it on different nodes and retries until it's found or there is a consistent answer from upstreams that the transaction doesn't exist - Get _nonce_ to send a transaction - Dshackle makes sure it finds the highest value across several nodes - Send _transaction_ - Dshackle distributes it to several nodes in parallel diff --git a/docs/02-quick-start.adoc b/docs/02-quick-start.adoc index 1d55a72d5..a022f1bf6 100644 --- a/docs/02-quick-start.adoc +++ b/docs/02-quick-start.adoc @@ -36,15 +36,18 @@ cluster: connection: ethereum: rpc: # <6> - url: "https://mainnet.infura.io/v3/${INFURA_USER}" - ws: # <7> + url: "https://mainnet.infura.io/v3/${INFURA_USER}" <7> + ws: # <8> url: "wss://mainnet.infura.io/ws/v3/${INFURA_USER}" - - id: infura-kovan - chain: kovan # <8> + - id: bitcoin-main + chain: bitcoin # <9> connection: - ethereum: + bitcoin: rpc: - url: "https://kovan.infura.io/v3/${INFURA_USER}" # <9> + url: "http://localhost:8332" + basic-auth: # <10> + username: bitcoin + password: test ---- <1> application listen for gRPC connections on 0.0.0.0:2449 <2> with TLS security for gRPC disabled (_never use in production!_) @@ -52,12 +55,12 @@ cluster: <4> sets up 2 upstreams <5> one for Ethereum Mainnet, using <6> HTTP and -<7> Websocket conection -<8> and another for Kovan Testnet -<9> `${INFURA_USER}` value is provided through environment variable +<7> `${INFURA_USER}` value is provided through environment variable +<8> Websocket conection +<9> and another for Bitcoin <10> with Basic Auth for bitcoin node connection + -Both upstreams are configured for Infura for demo purposes, but you can use other compatible endpoints. -Infura authentication is omitted for this demo +See detailed link:reference-configuration.adoc[Configuration Reference] ==== Run as docker @@ -99,9 +102,11 @@ curl --request POST \ .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 io.emeraldpay.api.Blockchain/SubscribeHead +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. + .Output would be like ---- { @@ -123,4 +128,37 @@ grpcurl -import-path ./proto/ -proto blockchain.proto -d "{\"type\": 100}" -plai ---- The output above is for a _streaming subscription_ to all new blocks on Ethereum Mainnet. -It's a method provided by Dshackle, available in additional to methods provided by RPC JSON of underlying nodes. +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:06-methods.adoc[Documentation for Enhanced Methods] \ No newline at end of file diff --git a/docs/04-upstream-config.adoc b/docs/04-upstream-config.adoc index b68a387e4..91ecb2e7c 100644 --- a/docs/04-upstream-config.adoc +++ b/docs/04-upstream-config.adoc @@ -10,7 +10,22 @@ Supported upstream protocols: Those protocols can be configures with additional security, TLS and authentication. -=== Example +=== Notes on upstream configuration + +==== Ethereum + +- Most of Ethereum nodes support WebSocket connection, in addition to the JSON RPC. +If it's available on your node, it's suggested to configure both JSON RPC and WebSocket connection + +==== Bitcoin + +- Bitcoind needs to be configured to index/track addresses that you're going to request. +Make sure you configure it to index your addresses with `importaddress`. +If you request balance for an address that is not indexed then it returns 0 balance. +- To track all transactions you need to setup index for transactions, which is disabled by default. +Run it with `-reindex` option, or set `txindex=1` in the config. + +=== Example Configuration .upstreams.yaml [source,yaml] @@ -104,9 +119,28 @@ Dshackle currently supports - `ws` websocket connection (supposed to be used in addition to `rpc` connection) - `grpc` connects to another Dshackle instance -=== Methods +=== Bitcoin Methods + +.By default an ethereum upstream allows call to the following JSON RPC methods: +- `getbestblockhash` +- `getblock` +- `getblocknumber` +- `getblockcount` +- `gettransaction` +- `getrawtransaction` +- `gettxout` +- `getreceivedbyaddress` +- `listunspent` +- `sendrawtransaction` + +.Plus following methods are answered directly by Dshackle +- `getmemorypool` +- `getconnectioncount` +- `getnetworkinfo` + +=== Ethereum Methods -.By default an ethereum upstream supports following JSON RPC methods: +.By default an ethereum upstream allows calls to the following JSON RPC methods: - `eth_gasPrice` - `eth_call` - `eth_estimateGas` diff --git a/docs/06-methods.adoc b/docs/06-methods.adoc index b3e491872..617360924 100644 --- a/docs/06-methods.adoc +++ b/docs/06-methods.adoc @@ -1,9 +1,12 @@ -== Methods +== Enhanced Methods -IMPORTANT: Dshackle provides an unified API based on gRPC and Protobuf. +IMPORTANT: Dshackle provides an enhanced API based on gRPC and Protobuf, in addition to JSON RPC proxy -Dshackle provides an unified API based on gRPC and Protobuf. I.e. it's not standard JSON RPC but client libraries could -be generated for all major libraries, and there're official libraries for Java and Javascript. +Dshackle provides an enhanced and unified API based on HTTP2, gRPC and Protobuf. +It works in addition to JSON RPC proxy and can be used separately. +Clients can be generated for all major programming languages, and there're official libraries for Java and Javascript. + +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. === gRPC definition @@ -25,8 +28,7 @@ service Blockchain { === Wrapped JSON RPC methods -Standard JSON RPC methods provided by Ethereum nodes are available wrapped into gRPC/Protobuf with additional features. -To call standard methods you use `NativeCall` method. +To call standard JSON RPC methods provided by Ethereum/Bitcoin you use `NativeCall` wrapping method, which provides additional flexibility and configuration for the calls. .NativeCallRequest [source,proto] @@ -72,13 +74,13 @@ Where: - `payload` is JSON response for a particular call, encoded into a string (when `succeed` is true) - or `error` if request failed (`succeed` is false) -NOTE: Reply Items comes right after their execution on an upstream, therefore streaming response. It allows to build - non-blocking queries +NOTE: Reply Items comes right after their execution on an upstream, therefore streaming response. +It allows to build non-blocking queries === SubscribeHead -Subscribes to new blocks on the specified chain. Returns stream of blocks right after it was accepted (and verified by -Dshackle) by any of the upstreams. +This methods provides subscription to the new blocks on the specified chain. +Returns stream of blocks right after it was accepted (and verified by Dshackle) by any of the upstreams. .ChainHead [source,proto] @@ -104,7 +106,7 @@ Where: === SubscribeBalance or GetBalance -Subscribes to changes of the balance for a single address or a set of addresses +Subscribes to changes (`SubscribeBalance`) or get current (`GetBalance`) balance for a single address or a set of addresses. .Request [source,proto] @@ -136,8 +138,9 @@ message AddressBalance { ==== SubscribeTxStatus -Subscribes to transaction confirmations. Allows to send a transactions and then listen to all changes until it -gets enough confirmations. Changes is `NOTFOUND -> BROADCASTED <- -> MINED <- -> CONFIRMED` +Subscribes to transaction confirmations. +Allows to send a transactions and then listen to all changes until it gets enough confirmations. +Changes are `NOTFOUND -> BROADCASTED <- -> MINED <- -> CONFIRMED` .Request [source,proto] @@ -161,3 +164,6 @@ message TxStatus { } ---- +=== gRPC Client Libraries + +See link:10-client-libraries.adoc[Client Libraries] documentation. diff --git a/docs/reference-configuration.adoc b/docs/reference-configuration.adoc index b76a5d984..1e9d485fd 100644 --- a/docs/reference-configuration.adoc +++ b/docs/reference-configuration.adoc @@ -89,6 +89,15 @@ cluster: basic-auth: username: 4fc258fe41a68149c199ad8f281f2015 password: 1a68f20154fc258fe4149c199ad8f281 + - id: bitcoin + chain: bitcoin + connection: + bitcoin: + rpc: + url: "http://localhost:8332" + basic-auth: + username: bitcoin + password: e984af45bb888428207c290 - id: remote connection: grpc: @@ -357,7 +366,7 @@ configuration, and may be omitted for most of the situations. | `chain` | yes -| Blockchain which is the provided by the upstream. `ethereum`, `ethereum_classic`, `kovan` +| Blockchain which is the provided by the upstream. `bitcoin`, `bitcoin-testnet`, `ethereum`, `ethereum-classic`, or `kovan` | `labels` | no @@ -369,7 +378,11 @@ configuration, and may be omitted for most of the situations. | `connection.ethereum` | yes -| Connection configuration for Ethereum JSON RPC API +| Connection configuration for Ethereum API + +| `connection.bitcoin` +| yes +| Connection configuration for Bitcoin API |===