= Configuration Reference
:toc:
:toclevels: 2

toc::[]

== Example

.Example configuration with most options configured
[source,yaml]
----
host: 0.0.0.0
port: 2449

tls:
  enabled: true
  server:
    certificate: "/path/127.0.0.1.crt"
    key: "/path/127.0.0.1.p8.key"
  client:
    require: true
    ca: "/path/ca.dshackle.test.crt"

monitoring:
  enabled: true
  jvm: false
  extended: false
  prometheus:
    enabled: true
    bind: 127.0.0.1
    port: 8081
    path: /metrics

health:
  port: 8082
  host: 127.0.0.1
  path: /health
  blockchains:
   - chain: ethereum
     min-availability: 1

cache:
  redis:
    enabled: true
    host: redis-master
    port: 6379
    db: 0
    password: I1y0dGKy01by

signed-response:
  enabled: true
  algorithm: SECP256K1
  private-key: /path/key.pem

proxy:
  host: 0.0.0.0
  port: 8080
  websocket: true
  preserve-batch-order: false
  tls:
    enabled: true
    server:
      certificate: "/path/127.0.0.1.crt"
      key: "/path/127.0.0.1.p8.key"
    client:
      require: true
      ca: "/path/ca.dshackle.test.crt"
  routes:
    - id: eth
      blockchain: ethereum
    - id: kovan
      blockchain: kovan

tokens:
  - id: dai
    blockchain: ethereum
    name: DAI
    type: ERC-20
    address: 0x6B175474E89094C44Da98b954EedeAC495271d0F
  - id: tether
    blockchain: ethereum
    name: Tether
    type: ERC-20
    address: 0xdac17f958d2ee523a2206206994597c13d831ec7

accessLog:
  enabled: true
  filename: /var/log/dshackle/access_log.jsonl

cluster:
  defaults:
    - chains:
        - ethereum
      options:
        min-peers: 10
    - chains:
        - kovan
      options:
        min-peers: 3
  include:
    - "upstreams-extra.yaml"
  upstreams:
    - id: local
      chain: ethereum
      labels:
        fullnode: true
      methods:
        enabled:
          - name: "parity_trace"
        disabled:
          - name: "admin_shutdown"
      connection:
        ethereum-pos:
            execution:
              rpc:
                url: "http://localhost:8545"
              ws:
                url: "ws://localhost:8546"
                origin: "http://localhost"
                basic-auth:
                  username: 9c199ad8f281f20154fc258fe41a6814
                  password: 258fe4149c199ad8f2811a68f20154fc
    - id: infura
      chain: ethereum
      options:
        disable-validation: true
      connection:
        ethereum-pos:
            execution:
              rpc:
                url: "https://mainnet.infura.io/v3/fa28c968191849c1aff541ad1d8511f2"
                basic-auth:
                  username: 4fc258fe41a68149c199ad8f281f2015
                  password: 1a68f20154fc258fe4149c199ad8f281
    - id: bitcoin
      chain: bitcoin
      options:
        # use the node to fetch balances
        balance: true
      connection:
        bitcoin:
          rpc:
            url: "http://localhost:8332"
            basic-auth:
              username: bitcoin
              password: e984af45bb888428207c290
          # use Esplora index to fetch balances and utxo for an address
          esplora:
            url: "http://localhost:3001"
          # connect via ZeroMQ to get notifications about new blocks
          zeromq:
            address: "http://localhost:5555"
    - id: remote
      connection:
        grpc:
          host: "10.2.0.15"
          tls:
            ca: /path/ca.dshackle.test.crt
            certificate: /path/client1.dshackle.test.crt
            key: /path/client1.dshackle.test.key
----

== Top level config

[cols="2a,2,5"]
|===
| Option | Default Value | Description

| `host`
| `127.0.0.0`
| Host to bind gRPC server

| `port`
| `2449`
| Port to bind gRPC server

| `tls`
|
| Setup TLS configuration for the gRPC server.
See <<tls>> section

| `monitoring`
|
| Setup Prometheus monitoring.
See <<monitoring>> section

| `health`
|
| Setup Health Check endpoint See <<health>> section

| `proxy`
|
| Setup HTTP proxy that emulates all standard JSON RPC requests.
See <<proxy>> section

| `accessLog`
|
| Configure access logging.
See <<accessLog>> section


| `tokens`
|
| Configure tokens for tracking balance.
See <<tokens>> section

| `cache`
|
| Caching configuration.
See <<cache>> section.

| `signed-response`
|
| Signed responses
See <<signed-response>> section.

| `cluster`
|
| Setup connection to remote nodes.See <<cluster>> section

|===

[#tls]
== TLS server config

[source,yaml]
----
tls:
  enabled: true
  server:
    certificate: "/path/127.0.0.1.crt"
    key: "/path/127.0.0.1.p8.key"
  client:
    require: true
    ca: "/path/ca.dshackle.test.crt"
----

[cols="2a,2,5"]
|===
| Option | Default Value | Description

| `enabled`
a| `true` if any value is set
| Enable/Disable TLS

| `server.certificate`
|
| Path to x509 certificate

| `server.key`
|
| Path to a private key to the certificate.The key _MUST BE_ in PKCS 8 format

| `client.require`
|
| If true then the server will required certificate from a client, otherwise client authentication is optional

| `client.ca`
|
| Certificate to validate client authentication

|===

[#monitoring]
== Monitoring

Configure Prometheus monitoring

[source,yaml]
----
monitoring:
  enabled: true
  jvm: false
  extended: false
  prometheus:
    enabled: true
    bind: 127.0.0.1
    port: 8081
    path: /metrics
----

[cols="2a,2a,5"]
|===
| Option | Default Value | Description

| `enabled`
| `true`
| Enable/Disable monitoring endpoint

| `jvm`
| `false`
| Enable/Disable JVM metrics (threads, GC, memory, etc)

| `extended`
| `false`
| Enable/Disable additional metrics (query selectors, etc)

| `prometheus.enabled`
| `true`
| Enable/Disable monitoring endpoint.
_Reserved for future use_, in case of multiple different types of endpoints.

| `prometheus.bind`
| `127.0.0.1`
| Host to bind the server

| `prometheus.port`
| `8081`
| Port to bind the server

| `prometheus.path`
| `/metrics`
| HTTP path to bind the server

|===

[#health]
== Health Check endpoint

[source,yaml]
----
health:
  port: 8082
  host: 127.0.0.1
  path: /health
  blockchains:
    - chain: ethereum
      min-available: 2
    - chain: bitcoin
      min-available: 1
----

[cols="2a,2a,5"]
|===
| Option | Default Value | Description

| `port`
| `8082`
| HTTP port to bind the server

| `host`
| `127.0.0.1`
| HTTP host to bind the server

| `path`
| `/health`
| HTTP path to respond on requests

| `blockchains`
|
| List of blockchains that must be available to consider the server _healthy_

| `[blockchain].chain`
|
| Blockchain id

| `[blockchain].min-available`
| 1
| How many _available_ upstreams for the blockchain is required to pass

|===

[#proxy]
== Proxy config

[source,yaml]
----
proxy:
  host: 0.0.0.0
  port: 8080
  preserve-batch-order: false
  tls:
    enabled: true
    server:
      certificate: "/path/127.0.0.1.crt"
      key: "/path/127.0.0.1.p8.key"
    client:
      require: true
      ca: "/path/ca.dshackle.test.crt"
  routes:
    - id: eth
      blockchain: ethereum
    - id: kovan
      blockchain: kovan
----

.Top config
[cols="2a,2,5"]
|===
| Option | Default Value | Description

| `host`
| `127.0.0.0`
| Host to bind HTTP server

| `port`
| `8080`
| Port to bind HTT server

| `port`
| `false`
| Should proxy preserve request-response correspondence when sending batch request via http

| `websocket`
| `true`
| Enable WebSocket Proxy

| `tls`
|
| Setup TLS configuration for the Proxy server.
See <<tls>> section

| `preserve-batch-order`
| false
| If `false` Dshackle may produce _batch_ response in different order, which is correct as per JSON RPC Spec.
If set to `true` then Dshackle preserves _batch_ order based on request order.
Note that latter is ineffective and use this option only when a client cannot reference responses by their IDs.

| `cors-origin`
|
| Access-Control-Allow-Origin contents. If empty the header will be omitted in response

| `cors-allowed-headers`
| `Content-Type`
| Access-Control-Allow-Headers contents. Takes effect only if сors-origi is present in config

| `routes`
|
a| Routing paths for Proxy.
The proxy will handle requests as `https://${HOST}:${PORT}/${ROUTE_ID}` (or `http://` if TLS is not enabled).
For WebSocket it's `wss` / `ws`, accordingly.
|===

.Route config
[cols="2a,2,5"]
|===
| Option | Default Value | Description

| `id`
|
| Internal _alphanumeric_ id, and a path of binding url - `https://${HOST}:${PORT}/${ROUTE_ID}`.

| `blockchain`
|
| A blockchain that must be used to handle that route.

|===

[#accessLog]
== Access Log config

[source,yaml]
----
accessLog:
  enabled: true
  filename: /var/log/dshackle/access_log.jsonl
----

.Access Log config
[cols="2a,3a,7"]
|===
| Option | Default | Description

| `enabled`
| `false`
| Enable/Disable Access logging

| `include-messages`
| `false`
| Include request params and response result/error (i.e., a JSON) in access log.
It's an expensive operation, use it for debugging only.
Note that for errors it provides only error message, not the error response itself.

| `filename`
| `access_log.jsonl`
| Path to the access log file

|===

[#tokens]
== Tokens config

[source,yaml]
----
tokens:
  - id: dai
    blockchain: ethereum
    name: DAI
    type: ERC-20
    address: 0x6B175474E89094C44Da98b954EedeAC495271d0F
  - id: tether
    blockchain: ethereum
    name: Tether
    type: ERC-20
    address: 0xdac17f958d2ee523a2206206994597c13d831ec7
----

Tokens config enables tracking of a balance amount in the configured tokens.
After making the configuration above you can request balance (`GetBalance`), or subscribe to balance changes (`SubscribeBalance`), using link:07-methods.adoc[enhanced protocol]

.Token config
[cols="2a,7"]
|===
| Option | Description

| `id`
| Internal id for reference (used in logging, etc)

| `blockchain`
| An ethereum-based blockchain where the contract is deployed

| `name`
| Name of the token, used for balance response as asset code (as converted to UPPERCASE)

| `type`
| Type of token.Only `ERC-20` is supported at this moment

| `address`
| Address of the deployed contract

|===

[#cache]
== Cache config

[source,yaml]
----
cache:
  redis:
    enabled: true
    host: redis-master
    port: 6379
    db: 0
    password: I1y0dGKy01by
----

.Redis Config
[cols="2a,2,5"]
|===
| Option | Default Value | Description

| `enabled`
| `false`
| Enable/disable Redis cache

| `host`
| `127.0.0.1`
| Redis host address

| `port`
| `6379`
| Redis port

| `db`
| `0`
| Redis DB to select

| `password`
|
| Password for connection, if required

|===

[#signed-response]
== Signed Response

[source,yaml]
----
signed-response:
  enabled: true
  algorithm: SECP256K1
  private-key: /path/key.pem
----

.Redis Config
[cols="2a,2,5"]
|===
| Option | Default Value | Description

| `enabled`
| `false`
| Enable/disable Signed Responses

| `algorithm`
| `SECP256K1`
| `SECP256K1` or `NIST-P256`

| `private-key`
|
| Path to a private key in PEM format

|===

See more details at link:07-methods.adoc#signatures[Signed Response]  in gRPC Methods.

[#cluster]
== Cluster

The cluster config is the main part, that defines all connection to nodes and other servers

[source,yaml]
----
cluster:
  defaults:
    - chains:
        - ethereum
      options:
        min-peers: 10
  upstreams:
    - id: local
      chain: ethereum
      connection:
        ethereum-pos:
            execution:
              rpc:
                url: "http://localhost:8545"
              ws:
                url: "ws://localhost:8546"
                origin: "http://localhost"
  include:
    - "upstreams-extra.yaml"
----

=== Main Cluster Configuration

.Top Level Config
[cols="2a,5"]
|===
| Option | Description

| `defaults`
| Default options applied to all upstreams within the specified blockchain. It's an optional
configuration, and may be omitted for most of the situations.

| `upstreams`
| List of upstream servers. The main part of the config. There are two types of upstream: <<upstream-json>> and <<upstream-dshackle>>.

| `include`
| Path(s) to include configurations for upstream servers. Same as `upstreams`, but load it from an external file.

|===

[#upstream-json]
=== JSON RPC Upstream

[source,yaml]
----
- id: local
  chain: ethereum
  role: standard
  labels:
    fullnode: true
  methods:
    enabled:
      - name: "parity_trace"
        quorum: "not_empty"
    disabled:
      - name: "admin_shutdown"
  connection:
    ethereum-pos:
      execution:
          rpc:
            url: "http://localhost:8545"
          ws:
            url: "ws://localhost:8546"
            origin: "http://localhost"
            basic-auth:
              username: 9c199ad8f281f20154fc258fe41a6814
              password: 258fe4149c199ad8f2811a68f20154fc
            frameSize: 5mb
            msgSize: 15mb
----

.Main Config
[cols="2a,1a,5"]
|===
| Option | Required | Description

| `id`
| yes
| Per-cluster identifier of an upstream

| `role`
| no
| `primary` (default), `secondary` or `fallback`.
First it makes the requests to the upstreams with role `primary`, then if none are available to upstreams with role `secondary`.
Fallback role mean that the upstream is used only after other upstreams failed or didn't return quorum

| `chain`
| yes
| Blockchain which is the provided by the upstream.
Cluster may have multiple upstreams for a single blockchain.
Accepted types: `bitcoin`, `bitcoin-testnet`, `ethereum`, `ethereum-classic`, `kovan-testnet`, `rinkeby-testnet`, `ropsten-testnet`, or `goerli-testnet`

| `enabled`
| no
| `true` (default) or `false`.
Enable/disable the upstream.

| `labels`
| no
| Key-Value pairs that are assigned to the upstream.
Used to select an upstream per-request.
See link:09-quorum-and-selectors.adoc[Quorum and Selectors]

| `options`
|
| Other configuration options. See <<general-options>>

| `methods`
| no
| Enable (`enabled`) or disable (`disabled`) additional JSON RPC methods that are provided by that particular upstream

| `methods.enabled.name`, `methods.disabled.name`
| yes
| Name of the RPC method to enable/disable.

| `methods.enabled.quorum`
| no
| Set quorum criteria to accept a response.
`always` (default) - accept any response;
`not_empty` - accept not _null_ value, otherwise retry another upstream;
`not_lagging` - accept response only from a fully synced upstream.

| `connection.ethereum-pos`
| yes
| Connection configuration for Ethereum API of PoS network

| `connection.bitcoin`
| yes
| Connection configuration for Bitcoin API

|===

[#general-options]
=== General Upstream Options

[cols="2a,1,1a,5"]
|===
| Option | Type | Default | Description

| `disable-validation`
| boolean
| `false`
| Disables all the validations of the upstream. I.e., it turns off `validate-peers` and `validate-syncing` checks if set to `true`.

| `validation-interval`
| number
| `30`
| Period in seconds to re-validate the upstream.

| `validate-peers`
| boolean
| `true`
| Disables validation of the peers connected to the upstream (as `net_peerCount` method).
Dshackle assumes that if there are too few peers then the Upstream is just started and may produce invalid/outdated responses

| `min-peers`
| number
| `1`
| The minimum number of connected peer to consider the upstream valid if `validate-peers` is enabled.
If it's set to `0` it essentially disables the peer validation.

| `validate-syncing`
| boolean
| `true`
| Disables checking for the state of syncing on the upstream (as `eth_syncing` method).
If the Upstream is in _syncing_ state then the Dshackle doesn't use it for call until it reaches the blockchain head.

| `timeout`
| number
| `60`
| Timeout in seconds to wait for an answer from the upstream before considering it as failed.

| `balance`
| boolean
|
| Suitable for Bitcoin upstream.
Tells if the Upstream can be used to call balance methods, which requires that the node has the indexing as turned on.

|===

==== Ethereum Connection Options

.Connection Config for Ethereum Upstream
[cols="2a,5"]
|===
| Option | Description

| `rpc.url`
a| HTTP URL to connect to.This is required for a connection. +
URL can be configured with Environment Variable placeholders `${ENV_VAR_NAME}`. +
Example: `https://kovan.infura.io/v3/${INFURA_USER}`

| `rpc.basic-auth` + `rpc.basic-auth.username`, `rpc.basic-auth.password`
a| HTTP Basic Auth configuration, if required by the remote server. +
Values can also reference env variables, for example:
[source,yaml]
----
rpc:
  url: "https://ethereum.com:8545"
  basic-auth:
    username: "${ETH_USERNAME}"
    password: "${ETH_PASSWORD}"
----

| `ws.url`
| WebSocket URL to connect to.
Optional, but optimizes performance if it's available.

| `ws.origin`
| HTTP `Origin` if required by WebSocket remote server.

| `ws.basic-auth` + ...
| WebSocket Basic Auth configuration, if required by the remote server

| `ws.frameSize`
| WebSocket frame size limit.
Ex `1kb`, `1024` (same as `1kb), `2mb`, etc.
Default is 5Mb

| `ws.msgSize`
| Total limit for a message size consisting from multiple frames.
Ex `1kb`, `1024` (same as `1kb), `2mb`, etc.
Default is 15Mb

| `ws.connections`
| How many concurrent connection to make. If more than one, each used in a robin-round fashion.
Defaults is `1`
|===

==== PoS Ethereum Connection Options
.Connection Config for PoS Ethereum Upstream
[cols="2a,5"]
|===
| Option | Description

| `execution`
a| Here you can specify any option from plain ethereum connection options listed above +
This is your connection to an execution layer of PoS Ethereum

| `upstream-rating`
a| Rating for this upstream. We will always consider the head of the chain to be +
the latest block we saw from the upstream with the highest rating.

|===

==== Bitcoin Connection Options

.Connection Config for Bitcoin Upstream
[cols="2a,5"]
|===
| Option | Description

| `rpc.url`
a| HTTP URL to connect to. This is required for a connection. +
URL can be configured with Environment Variable placeholders `${ENV_VAR_NAME}`. +
Example: `http://${NODE_HOST}:${NODE_PORT}`

| `rpc.basic-auth` + `rpc.basic-auth.username`, `rpc.basic-auth.password`
a| HTTP Basic Auth configuration, which is required by the Bitcoind server. +
Values can also reference env variables, for example:
[source,yaml]
----
rpc:
  url: "http://127.0.0.1:8332"
  basic-auth:
    username: "${NODE_USERNAME}"
    password: "${NODE_PASSWORD}"
----

| `zeromq.address`
a| Set up an additional connection via ZeroMQ protocol to subscribe to the new blocks.
The node must be launched with the same address specified as `-zmqpubhashblock="tcp://${HOST}:${POST}"` or in `bitcoin.conf`
[source,yaml]
----
zeromq:
  address: "127.0.0.1:5555"
----

|===

[#upstream-dshackle]
=== Dshackle Upstream

Another option is using another Dshackle server as an upstream.
It's more effective, easier to secure connection, and allows to build a distributed network of servers.

[source,yaml]
----
- id: test1
  labels:
    provider: some
  connection:
    grpc:
      host: eu-api.mycompany.com
      port: 2449
      tls:
        ca: ca.api.mycompany.crt
        certificate: client-1.api.mycompany.crt
        key: client-1.api.mycompany.p8.key
----

.Main Config
[cols="2a,1a,5"]
|===
| Option | Required | Description

| `id`
| yes
| Per-cluster identifier of an upstream

| `labels`
| no
| Defines the labels can be used for the proper upstream instance selection. Overrides the labels retrieved by the `describe` method

| `connection.grpc`
| yes
| Connection configuration for Dshackle gRPC
|===

.Connection Config
[cols="2a,5"]
|===
| Option | Description

| `host` and `port`
| Address to connect to

| `tls`
a| TLC configuration for the connection.
In general it's an optional configuration, but it's strongly recommended.
Also HTTP2 + gRPC is designed to be used with TLS, and some of the related software is unable to use it without TLS. +
See link:08-authentication.adoc[Authentication] docs and <<tls>>.

| `tls.ca`
| Path to x509 certificate to verify remote server

| `tls.certificate` + `tls.key`
| Client certificate (x509) and its private key (PKCS 8) used for authentication on the remote server.

|===
