Merge branch 'master' into network_specific_methods_support

# Conflicts:
#	src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt
This commit is contained in:
Maksim Fomenkov
2022-11-28 18:38:48 +04:00
152 changed files with 775 additions and 1214 deletions

View File

@@ -40,35 +40,3 @@ jobs:
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v1
with: with:
file: ./build/reports/jacoco/test/jacocoTestReport.xml file: ./build/reports/jacoco/test/jacocoTestReport.xml
integration-test:
runs-on: ubuntu-latest
# Docker Hub image that `container-job` executes in.
# Use -buster which comes with Git 2.20, because action/checkout needs Git 2.18+ to make correct clone (needed by Gradle version plugin)
container: node:12-buster
services:
redis:
image: redis
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 13
- name: Check
uses: eskatos/gradle-command-action@v1
with:
arguments: check
env:
CI: true
DSHACKLE_TEST_ENABLED: redis
REDIS_HOST: redis
REDIS_PORT: 6379

9
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "emerald-java-client"] [submodule "emerald-grpc"]
path = emerald-java-client path = emerald-grpc
url = https://github.com/p2p-org/emerald-java-client.git url = git@github.com:p2p-org/emerald-grpc.git
[submodule "dshackle-cli/grpc"]
path = dshackle-cli/grpc
url = https://github.com/p2p-org/emerald-grpc.git

View File

@@ -5,6 +5,15 @@ import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.1'
}
}
plugins { plugins {
id 'java' id 'java'
id 'groovy' id 'groovy'
@@ -49,6 +58,7 @@ configurations {
compile.exclude group: "org.slf4j", module: "log4j-over-slf4j" compile.exclude group: "org.slf4j", module: "log4j-over-slf4j"
// should be used only for generation of the stubs, the lib contains grpc classes // should be used only for generation of the stubs, the lib contains grpc classes
compile.exclude group: "com.salesforce.servicelibs", module: "reactor-grpc" compile.exclude group: "com.salesforce.servicelibs", module: "reactor-grpc"
} }
dependencies { dependencies {
@@ -70,10 +80,6 @@ dependencies {
implementation libs.bundles.etherjar implementation libs.bundles.etherjar
implementation(libs.emerald.api) {
exclude group: 'com.salesforce.servicelibs', module: 'reactor-grpc'
}
implementation libs.bitcoinj implementation libs.bitcoinj
implementation libs.snake.yaml implementation libs.snake.yaml
@@ -96,6 +102,13 @@ dependencies {
testImplementation libs.java.websocket testImplementation libs.java.websocket
testImplementation libs.equals.verifier testImplementation libs.equals.verifier
testImplementation libs.groovy testImplementation libs.groovy
testImplementation libs.bundles.testcontainers
testImplementation libs.bundles.junit
testImplementation(libs.spring.boot.starter.test) {
exclude module: 'spring-boot-starter-logging'
}
testImplementation libs.grpc.testing
detektPlugins libs.detekt.formatting detektPlugins libs.detekt.formatting
} }
@@ -188,14 +201,26 @@ protobuf {
artifact = System.getenv("PROTOC_PATH") == null ? "com.google.protobuf:protoc:${libs.versions.protoc.get()}" : null artifact = System.getenv("PROTOC_PATH") == null ? "com.google.protobuf:protoc:${libs.versions.protoc.get()}" : null
} }
plugins { plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
}
reactor { artifact = "com.salesforce.servicelibs:reactor-grpc:${reactiveGrpcVersion}" }
} }
generateProtoTasks { generateProtoTasks {
all()*.plugins {
grpc {}
reactor {}
}
} }
} }
sourceSets { sourceSets {
main { main {
resources.srcDirs += project.buildDir.absolutePath + "/generated/version" resources.srcDirs += project.buildDir.absolutePath + "/generated/version"
proto {
srcDir 'emerald-grpc/proto'
}
} }
} }
@@ -289,3 +314,6 @@ detekt {
tasks.withType(Detekt).configureEach { tasks.withType(Detekt).configureEach {
jvmTarget = "13" jvmTarget = "13"
} }
// formats code for each build
tasks.findByName("ktlintCheck").dependsOn("ktlintFormat")

View File

@@ -3,7 +3,7 @@ const path = require('path')
const protoLoader = require("@grpc/proto-loader"); const protoLoader = require("@grpc/proto-loader");
const fs = require('fs'); const fs = require('fs');
const PROTO_PATH = path.join(__dirname, "../grpc/proto/blockchain.proto"); const PROTO_PATH = path.join(__dirname, "../../emerald-grpc/proto/blockchain.proto");
const options = { const options = {
keepCase: true, keepCase: true,

1
emerald-grpc Submodule

Submodule emerald-grpc added at 441f828eb6

View File

@@ -1,3 +1,6 @@
kotlin.code.style=official kotlin.code.style=official
grpcVersion=1.49.2
reactiveGrpcVersion=1.2.0

View File

@@ -31,8 +31,6 @@ cglib-nodep = "cglib:cglib-nodep:3.3.0"
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" } detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
emerald-api = "io.emeraldpay:emerald-api:0.12-alpha.3"
equals-verifier = "nl.jqno.equalsverifier:equalsverifier:3.10.1" equals-verifier = "nl.jqno.equalsverifier:equalsverifier:3.10.1"
etherjar-domain = { module = "io.emeraldpay.etherjar:etherjar-domain", version.ref = "etherjar" } etherjar-domain = { module = "io.emeraldpay.etherjar:etherjar-domain", version.ref = "etherjar" }
@@ -113,6 +111,14 @@ spring-security-core = { module = "org.springframework.security:spring-security-
spring-security-web = { module = "org.springframework.security:spring-security-web", version.ref = "spring-security" } spring-security-web = { module = "org.springframework.security:spring-security-web", version.ref = "spring-security" }
spring-security-config = { module = "org.springframework.security:spring-security-config", version.ref = "spring-security" } spring-security-config = { module = "org.springframework.security:spring-security-config", version.ref = "spring-security" }
spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test", version.ref = "spring-boot" }
testcontainers = "org.testcontainers:testcontainers:1.17.5"
testcontainers-ganache = "io.github.ganchix:testcontainers-java-module-ganache:0.0.4"
junit-jupiter = "org.junit.jupiter:junit-jupiter:5.9.1"
assertj = "org.assertj:assertj-core:3.23.1"
[bundles] [bundles]
apache-commons = ["commons-io", "apache-commons-lang3", "apache-commons-collections4"] apache-commons = ["commons-io", "apache-commons-lang3", "apache-commons-collections4"]
etherjar = ["etherjar-domain", "etherjar-hex", "etherjar-rpc-api", "etherjar-rpc-http", "etherjar-rpc-ws", "etherjar-tx", "etherjar-contract", "etherjar-erc20"] etherjar = ["etherjar-domain", "etherjar-hex", "etherjar-rpc-api", "etherjar-rpc-http", "etherjar-rpc-ws", "etherjar-tx", "etherjar-contract", "etherjar-erc20"]
@@ -124,12 +130,15 @@ netty = ["netty-common", "netty-transport", "netty-handler-core", "netty-handler
reactor = ["reactor-core", "reactor-netty", "reactor-extra", "reactor-kotlin"] reactor = ["reactor-core", "reactor-netty", "reactor-extra", "reactor-kotlin"]
slf4j = ["slf4j-api", "slf4j-jul", "slf4j-jcl", "log4j-slf4j"] slf4j = ["slf4j-api", "slf4j-jul", "slf4j-jcl", "log4j-slf4j"]
spring-framework = ["spring-boot-starter", "spring-security-core", "spring-security-web", "spring-security-config"] spring-framework = ["spring-boot-starter", "spring-security-core", "spring-security-web", "spring-security-config"]
testcontainers = ["testcontainers", "testcontainers-ganache"]
junit = ["junit-jupiter", "assertj"]
[plugins] [plugins]
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
jib = { id = "com.google.cloud.tools.jib", version = "2.5.0" } jib = { id = "com.google.cloud.tools.jib", version = "2.5.0" }
spring = { id = "org.springframework.boot", version = "2.3.5.RELEASE" } spring = { id = "org.springframework.boot", version = "2.3.5.RELEASE" }
git = { id = "com.palantir.git-version", version = "0.12.3" } git = { id = "com.palantir.git-version", version = "0.12.3" }
protobuf = { id = "com.google.protobuf", version = "0.8.17" } protobuf = { id = "com.google.protobuf", version = "0.9.1" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "10.2.0" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "10.2.0" }
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }

View File

@@ -1,45 +0,0 @@
{ system ? builtins.currentSystem
, nixpkgs ? import ./nixpkgs.nix { inherit system; }
}:
let
mkEnv = nixpkgs.callPackage ./mkEnv.nix { };
in
rec {
inherit
nixpkgs
;
protoc-gen-grpc-java = nixpkgs.callPackage ./pkgs/protoc-gen-grpc-java { };
env = mkEnv {
env = {
# Configure nix to use nixpgks
NIX_PATH = "nixpkgs=${toString nixpkgs.path}";
# Set the env for gradle
JAVA_HOME = "@env-root@/lib/openjdk";
};
paths = [
# Development tools
nixpkgs.gitAndTools.git-absorb
nixpkgs.jq
nixpkgs.niv
nixpkgs.websocat
nixpkgs.yq
# Protobuf stuff
nixpkgs.protobuf3_9
protoc-gen-grpc-java
# Code formatting
nixpkgs.treefmt
nixpkgs.nixpkgs-fmt
nixpkgs.shfmt
nixpkgs.jdk
nixpkgs.coreutils
nixpkgs.gnugrep
nixpkgs.which
];
};
}

View File

@@ -1,38 +0,0 @@
# Source https://github.com/Mic92/nix-build-uncached/blob/master/scripts/force_cached.nix
coreutils: attrs:
with builtins;
let
# Copied from <nixpkgs/lib>
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
# Return true if `nix-build` would traverse that attribute set to look for
# more derivations to build.
hasRecurseIntoAttrs = x: isAttrs x && (x.recurseForDerivations or false);
# Wraps derivations that disallow substitutes so that they can be cached.
toCachedDrv = drv:
if !(drv.allowSubstitutes or true) then
derivation
{
name = "${drv.name}-to-cached";
system = drv.system;
builder = "/bin/sh";
args = [ "-c" "${coreutils}/bin/ln -s ${drv} $out; exit 0" ];
}
else
drv;
op = _: val:
if isDerivation val then
toCachedDrv val
else if hasRecurseIntoAttrs val then
forceCached val
else
val
;
# Traverses a tree of derivation and wrap all of those that disallow
# substitutes.
forceCached = attrs: mapAttrs op attrs;
in
forceCached attrs

View File

@@ -1,29 +0,0 @@
{ lib, writeText, buildEnv }:
{ name ? "dev-env"
, # Environment variables to set
env ? { }
, # Packages to add to the path
paths ? [ ]
}:
let
envToBash = name: value:
"export ${name}=${lib.escapeShellArg (toString value)}"
;
exports = lib.concatStringsSep "\n"
(map (name: envToBash name env.${name}) (lib.attrNames env));
env-root = writeText "env-root" ''
export PATH=@env-root@/bin:$PATH
${exports}
'';
in
buildEnv {
inherit name;
paths = paths;
postBuild = ''
sed "s|@env-root@|$out|g" ${env-root} > $out/.profile
'';
}

View File

@@ -1,9 +0,0 @@
{ system ? builtins.currentSystem }:
let
sources = import ./sources.nix;
in
import sources.nixpkgs {
inherit system;
config = { };
overlays = [ ];
}

View File

@@ -1,23 +0,0 @@
{ stdenv, runCommand, fetchurl, autoPatchelfHook, lib }:
stdenv.mkDerivation rec {
pname = "protoc-gen-grpc-java";
version = "1.38.0";
src = fetchurl {
url = "https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/${version}/protoc-gen-grpc-java-${version}-linux-x86_64.exe";
sha256 = "sha256:1gy5lkxj6d4vrgalwnjp15biybcnrmp695si9878y7high39ymr3";
};
nativeBuildInputs = [ autoPatchelfHook ];
unpackPhase = ''
cp $src ./bin
chmod +x ./bin
'';
installPhase = ''
mkdir -p $out/bin
mv ./bin $out/bin/$pname
'';
}

View File

@@ -1,16 +0,0 @@
# Use this file with nix-build-uncached on CI
{ system ? builtins.currentSystem }:
let
nixpkgs = import ./nixpkgs.nix { inherit system; };
# This is used to wrap all of our outputs, so they all end-up in the cache.
#
# There are two attributes ` allowSubstitutes = false;` and
# `preferLocalBuild = true;` that influence how derivations gets pulled and
# pushed.
forceCached = import ./lib/force_cached.nix nixpkgs.coreutils;
# All the packages that we care about
ourPackages = import ./. { inherit nixpkgs system; };
in
forceCached ourPackages

View File

@@ -1,14 +0,0 @@
{
"nixpkgs": {
"branch": "nixos-unstable",
"description": "Nix Packages collection",
"homepage": "",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e4ef597edfd8a0ba5f12362932fc9b1dd01a0aef",
"sha256": "1w6y7ma2crcsfph60z8j1k3af0v2m110cbjrb62z287mn4skhqjs",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/e4ef597edfd8a0ba5f12362932fc9b1dd01a0aef.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}

View File

@@ -1,160 +0,0 @@
# This file has been generated by Niv.
let
#
# The fetchers. fetch_<type> fetches specs of type <type>.
#
fetch_file = pkgs: name: spec:
let
name' = sanitizeName name + "-src";
in
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
else
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
fetch_tarball = pkgs: name: spec:
let
name' = sanitizeName name + "-src";
in
if spec.builtin or true then
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
else
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
fetch_git = name: spec:
let
ref =
if spec ? ref then spec.ref else
if spec ? branch then "refs/heads/${spec.branch}" else
if spec ? tag then "refs/tags/${spec.tag}" else
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
in
builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
fetch_local = spec: spec.path;
fetch_builtin-tarball = name: throw
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=tarball -a builtin=true'';
fetch_builtin-url = name: throw
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=file -a builtin=true'';
#
# Various helpers
#
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
sanitizeName = name:
(
concatMapStrings (s: if builtins.isList s then "-" else s)
(
builtins.split "[^[:alnum:]+._?=-]+"
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
)
);
# The actual fetching function.
fetch = pkgs: name: spec:
if ! builtins.hasAttr "type" spec then
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
else if spec.type == "file" then fetch_file pkgs name spec
else if spec.type == "tarball" then fetch_tarball pkgs name spec
else if spec.type == "git" then fetch_git name spec
else if spec.type == "local" then fetch_local spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
else if spec.type == "builtin-url" then fetch_builtin-url name
else
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# If the environment variable NIV_OVERRIDE_${name} is set, then use
# the path directly as opposed to the fetched source.
replace = name: drv:
let
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
in
if ersatz == "" then drv else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
mapAttrs = builtins.mapAttrs or (
f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
range = first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
concatMapStrings = f: list: concatStrings (map f list);
concatStrings = builtins.concatStringsSep "";
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
optionalAttrs = cond: as: if cond then as else { };
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchTarball;
in
if lessThan nixVersion "1.12" then
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchurl;
in
if lessThan nixVersion "1.12" then
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchurl attrs;
# Create the final "sources" from the config
mkSources = config:
mapAttrs
(
name: spec:
if builtins.hasAttr "outPath" spec
then
abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = replace name (fetch config.pkgs name spec); }
)
config.sources;
# The "config" used by the fetchers
mkConfig =
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
, sources ? if isNull sourcesFile then { } else builtins.fromJSON (builtins.readFile sourcesFile)
, system ? builtins.currentSystem
, pkgs ? abort ''
Some source is being used outside of nixpkgs. For example using import.
Edit the sources.json and add `"builtin": true` to that source.
''
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
inherit pkgs;
};
in
mkSources (mkConfig { }) // { __functor = _: settings: mkSources (mkConfig settings); }

View File

@@ -1,7 +0,0 @@
= Emerald Dshackle Protobuf definitions
Protobuf definition for the external interface (i.e. gRPC) of the Emerald Dshackle.
This gRPC definitions are part of the general Emerald API, please see the project with whole API at https://github.com/emeraldpay/emerald-grpc
Dshakle also has some internal Protobuf schemas, for example to serialize cached values.
You can find them in link:../src/main/proto/[].

View File

@@ -1,284 +0,0 @@
syntax = "proto3";
package emerald;
option java_package = "io.emeraldpay.api.proto";
import "common.proto";
service Blockchain {
rpc SubscribeHead (Chain) returns (stream ChainHead) {}
rpc SubscribeBalance (BalanceRequest) returns (stream AddressBalance) {}
rpc SubscribeTxStatus (TxStatusRequest) returns (stream TxStatus) {}
rpc GetBalance (BalanceRequest) returns (stream AddressBalance) {}
/**
* Fee Estimation service. The server tries to estimate a fair fee based on the last N blocks.
*/
rpc EstimateFee (EstimateFeeRequest) returns (EstimateFeeResponse) {}
rpc NativeCall (NativeCallRequest) returns (stream NativeCallReplyItem) {}
rpc NativeSubscribe (NativeSubscribeRequest) returns (stream NativeSubscribeReplyItem) {}
rpc Describe (DescribeRequest) returns (DescribeResponse) {}
rpc SubscribeStatus (StatusRequest) returns (stream ChainStatus) {}
}
message NativeCallRequest {
ChainRef chain = 1;
repeated NativeCallItem items = 2;
Selector selector = 3;
int32 quorum = 4;
AvailabilityEnum min_availability = 5;
}
message NativeCallItem {
uint32 id = 1;
string method = 3;
bytes payload = 4;
uint64 nonce = 5;
}
/**
* Signature for a response
*/
message NativeCallReplySignature {
/**
* Original nonce value used for the call
*/
uint64 nonce = 1;
/**
* Signature value
*/
bytes signature = 2;
/**
* Key Id used for the signing
*/
uint64 key_id = 3;
/**
* Id of the upstream produced the response
*/
string upstream_id = 4;
}
message NativeCallReplyItem {
uint32 id = 1;
bool succeed = 2;
bytes payload = 3;
string errorMessage = 4;
/**
* Optional signature for the response.
* Available only when it's configured at the edge dshackle and nonce is provided wit the request.
*/
NativeCallReplySignature signature = 5;
}
message NativeSubscribeRequest {
ChainRef chain = 1;
string method = 2;
bytes payload = 3;
}
message NativeSubscribeReplyItem {
bytes payload = 1;
}
message ChainHead {
ChainRef chain = 1;
uint64 height = 2;
string block_id = 3;
uint64 timestamp = 4;
bytes weight = 5;
uint64 reorg = 6;
}
message TxStatusRequest {
ChainRef chain = 1;
string tx_id = 2;
uint32 confirmation_limit = 3;
}
message TxStatus {
string tx_id = 1;
bool broadcasted = 2;
bool mined = 3;
BlockInfo block = 4;
uint32 confirmations = 5;
}
message BalanceRequest {
Asset asset = 1;
AnyAddress address = 2;
bool include_utxo = 3;
}
message AddressBalance {
Asset asset = 1;
SingleAddress address = 2;
string balance = 3;
bool confirmed = 4;
repeated Utxo utxo = 5;
}
message Utxo {
string tx_id = 1;
uint64 index = 2;
string balance = 3;
bool spent = 4;
}
message DescribeRequest {
}
message DescribeResponse {
repeated DescribeChain chains = 1;
}
message DescribeChain {
ChainRef chain = 1;
ChainStatus status = 2;
repeated NodeDetails nodes = 3;
repeated string supportedMethods = 4;
repeated string excludedMethods = 5;
repeated Capabilities capabilities = 6;
}
message StatusRequest {
repeated ChainRef chains = 1;
}
message ChainStatus {
ChainRef chain = 1;
AvailabilityEnum availability = 2;
uint32 quorum = 3;
}
enum AvailabilityEnum {
AVAIL_UNKNOWN = 0;
AVAIL_OK = 1;
AVAIL_LAGGING = 2;
AVAIL_IMMATURE = 3;
AVAIL_SYNCING = 4;
AVAIL_UNAVAILABLE = 5;
}
message NodeDetails {
uint32 quorum = 1;
repeated Label labels = 2;
}
enum Capabilities {
CAP_NONE = 0;
CAP_CALLS = 1;
CAP_BALANCE = 2;
}
message Label {
string name = 1;
string value = 2;
}
message Selector {
oneof selector_type {
LabelSelector labelSelector = 1;
OrSelector orSelector = 2;
AndSelector andSelector = 3;
NotSelector notSelector = 4;
ExistsSelector existsSelector = 5;
}
}
message LabelSelector {
string name = 1;
repeated string value = 2;
}
message OrSelector {
repeated Selector selectors = 1;
}
message AndSelector {
repeated Selector selectors = 1;
}
message NotSelector {
Selector selector = 1;
}
message ExistsSelector {
string name = 1;
}
/**
* Request for Fee Estimation Service
*/
message EstimateFeeRequest {
// Target chain
ChainRef chain = 1;
// The way how the fee should be estimated
FeeEstimationMode mode = 2;
// How many blocks the server is supposed to use to estimate current fee. Note that the server may use value, depending on configuration
uint32 blocks = 3;
}
/**
* Responset for Fee Estimation Service
*/
message EstimateFeeResponse {
// May return different struct, depending on the blockchain
oneof fee_type {
// Standard Ethereum Fee, supported by majority of forks and by Ethereum Mainnet before EIP-1559
EthereumStdFees ethereumStd = 1;
// Ethereum Fee for EIP-1559 compatible forks
EthereumExtFees ethereumExtended = 2;
// Standard Bitcoin Fee
BitcoinStdFees bitcoinStd = 3;
}
}
/**
* The mode of how the fee must be estimated
*/
enum FeeEstimationMode {
INVALID = 0;
// Average over last transaction in each block
AVG_LAST = 1;
// Average over transaction 5th from the end in each block
AVG_T5 = 2;
// Average over transaction 20th from the end in each block
AVG_T20 = 3;
// Average over transaction 50th from the end in each block
AVG_T50 = 4;
// Minimal fee that would be accepted by every last block
MIN_ALWAYS = 5;
// Average over transaction in the middle of each block
AVG_MIDDLE = 6;
// Average over transaction in head of each block. Note that for Bitcoin it doesn't count COINBASE tx as top tx.
AVG_TOP = 7;
}
/**
* Standard Ethereum Fee, supported by majority of forks and by Ethereum Mainnet before EIP-1559
*/
message EthereumStdFees {
// Big Number encoded as string. Fee value in Wei
string fee = 1;
}
/**
* Ethereum Fee for EIP-1559 compatible forks
*/
message EthereumExtFees {
// Big Number encoded as string. Estimated fee that expected to be actually paid. I.e. it's the Base Fee + Priority Fee
string expect = 1;
// Big Number encoded as string. Priority Fee in Wei
string priority = 2;
// Big Number encoded as string. Max Fee value in Wei. Note that it only indicates the current preference, and the actual Max may be significantly lower, depending on the usage scenario.
string max = 3;
}
/**
* Standard Bitcoin Fee
*/
message BitcoinStdFees {
// Fee in Satoshi per Kilobyte. Note that the actual fee calculation MUST divide it by 1024 at the last step to get a fair fee.
uint64 satPerKb = 1;
}

View File

@@ -1,74 +0,0 @@
syntax = "proto3";
package emerald;
option java_package = "io.emeraldpay.api.proto";
message Chain {
ChainRef type = 1;
}
enum ChainRef {
CHAIN_UNSPECIFIED = 0;
CHAIN_BITCOIN = 1;
// CHAIN_GRIN = 2;
CHAIN_ETHEREUM = 100;
CHAIN_ETHEREUM_CLASSIC = 101;
CHAIN_FANTOM = 102; // Fantom, https://fantom.foundation/
// Sidechains and state channels start with 1_000
// CHAIN_LIGHTNING = 1001;
CHAIN_MATIC = 1002; // Matic PoS Ethereum sidechain based on Polygon
CHAIN_RSK = 1003; // RSK sidechain, https://www.rsk.co/
// Testnets start with 10_000
CHAIN_MORDEN = 10001;
CHAIN_KOVAN = 10002;
CHAIN_TESTNET_BITCOIN = 10003;
// CHAIN_FLOONET = 10004;
CHAIN_GOERLI = 10005;
CHAIN_ROPSTEN = 10006;
CHAIN_RINKEBY = 10007;
// Non-standard starts from 20_000
}
message SingleAddress {
string address = 1;
}
message XpubAddress {
bytes xpub = 1;
string path = 2;
uint64 start = 3;
uint64 limit = 4;
}
message MultiAddress {
repeated SingleAddress addresses = 1;
}
message ReferenceAddress {
uint64 refid = 1;
}
message AnyAddress {
oneof addr_type {
SingleAddress address_single = 1;
MultiAddress address_multi = 2;
XpubAddress address_xpub = 3;
ReferenceAddress address_ref = 4;
}
}
message Asset {
ChainRef chain = 1;
string code = 2;
}
message BlockInfo {
uint64 height = 1;
string block_id = 2;
uint64 timestamp = 3;
bytes weight = 4;
}

View File

@@ -1,8 +1,2 @@
enableFeaturePreview("VERSION_CATALOGS") enableFeaturePreview("VERSION_CATALOGS")
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
includeBuild('./emerald-java-client') {
dependencySubstitution {
substitute module('io.emeraldpay:emerald-api:0.12-alpha.3') using project(':')
}
}

View File

@@ -0,0 +1,36 @@
package io.emeraldpay.dshackle
enum class BlockchainType {
BITCOIN, EVM_POW, EVM_POS;
companion object {
@JvmStatic
fun from(chain: Chain): BlockchainType {
if (chain == Chain.TESTNET_ROPSTEN ||
chain == Chain.POLYGON ||
chain == Chain.OPTIMISM ||
chain == Chain.BSC ||
chain == Chain.TESTNET_GOERLI ||
chain == Chain.ETHEREUM
) {
return EVM_POS
}
if (chain == Chain.ETHEREUM_CLASSIC ||
chain == Chain.ARBITRUM ||
chain == Chain.FANTOM ||
chain == Chain.RSK ||
chain == Chain.TESTNET_KOVAN ||
chain == Chain.TESTNET_MORDEN ||
chain == Chain.TESTNET_RINKEBY
) {
return EVM_POW
}
if (chain == Chain.BITCOIN ||
chain == Chain.TESTNET_BITCOIN
) {
return BITCOIN
}
throw IllegalArgumentException("Unknown type of blockchain: $chain")
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2016-2019 ETCDEV GmbH, All Rights Reserved.
*
* 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.
*/
package io.emeraldpay.dshackle
enum class Chain(val id: Int, val chainCode: String, val chainName: String) {
UNSPECIFIED(0, "UNSPECIFIED", "Unknown"),
BITCOIN(1, "BTC", "Bitcoin"), // GRIN(2, "GRIN", "Grin"),
// Networks with tokens
ETHEREUM(100, "ETH", "Ethereum"),
ETHEREUM_CLASSIC(101, "ETC", "Ethereum Classic"),
FANTOM(
102,
"FTM",
"Fantom"
), // LIGHTNING(1001, "BTC_LN", "Bitcoin Lightning"),
POLYGON(1002, "POLYGON", "Polygon Matic"),
RSK(1003, "RSK", "Bitcoin RSK"),
ARBITRUM(
1004,
"ARBITRUM",
"Arbitrum"
),
OPTIMISM(1005, "OPTIMISM", "Optimism"),
BSC(1006, "BSC", "Binance Smart Chain"), // Testnets
TESTNET_MORDEN(10001, "MORDEN", "Morden Testnet"),
TESTNET_KOVAN(10002, "KOVAN", "Kovan Testnet"),
TESTNET_BITCOIN(
10003,
"TESTNET_BITCOIN",
"Bitcoin Testnet"
), // TESTNET_FLOONET(10004, "FLOONET", "Floonet Testnet"),
TESTNET_GOERLI(10005, "GOERLI", "Goerli Testnet"),
TESTNET_ROPSTEN(
10006,
"ROPSTEN",
"Ropsten Testnet"
),
TESTNET_RINKEBY(10007, "RINKEBY", "Rinkeby Testnet");
companion object {
fun byId(id: Int): Chain {
for (chain in values()) {
if (chain.id == id) {
return chain
}
}
return UNSPECIFIED
}
}
}

View File

@@ -16,7 +16,6 @@
package io.emeraldpay.dshackle package io.emeraldpay.dshackle
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.grpc.Chain
import java.util.EnumMap import java.util.EnumMap
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock import kotlin.concurrent.withLock

View File

@@ -33,9 +33,11 @@ import org.springframework.boot.SpringApplication
import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.core.env.Environment import org.springframework.core.env.Environment
import org.springframework.scheduling.annotation.EnableAsync import org.springframework.scheduling.annotation.EnableAsync
import org.springframework.scheduling.annotation.EnableScheduling import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.util.ResourceUtils
import reactor.core.scheduler.Scheduler import reactor.core.scheduler.Scheduler
import reactor.core.scheduler.Schedulers import reactor.core.scheduler.Schedulers
import java.io.File import java.io.File
@@ -47,8 +49,8 @@ import kotlin.system.exitProcess
@EnableScheduling @EnableScheduling
@EnableAsync @EnableAsync
open class Config( open class Config(
@Autowired private val env: Environment, private val env: Environment,
@Autowired private val ctx: ApplicationContext private val ctx: ApplicationContext
) { ) {
companion object { companion object {
@@ -61,7 +63,12 @@ open class Config(
private var configFilePath: File? = null private var configFilePath: File? = null
init { init {
configFilePath = getConfigPath() configFilePath = if (env.activeProfiles.contains("integration-test")) {
ResourceUtils.getFile("classpath:integration/dshackle.yaml")
} else {
getConfigPath()
}
Global.version = env.getProperty("version.app", Global.version).let { Global.version = env.getProperty("version.app", Global.version).let {
if (it.contains("SNAPSHOT")) { if (it.contains("SNAPSHOT")) {
listOfNotNull(it, env.getProperty("version.commit")).joinToString("-") listOfNotNull(it, env.getProperty("version.commit")).joinToString("-")
@@ -95,6 +102,7 @@ open class Config(
} }
@Bean @Bean
@Profile("!integration-test")
open fun mainConfig(@Autowired fileResolver: FileResolver): MainConfig { open fun mainConfig(@Autowired fileResolver: FileResolver): MainConfig {
val f = configFilePath ?: throw IllegalStateException("Config path is not set") val f = configFilePath ?: throw IllegalStateException("Config path is not set")
log.info("Using config: ${f.absolutePath}") log.info("Using config: ${f.absolutePath}")

View File

@@ -27,7 +27,6 @@ import io.emeraldpay.dshackle.upstream.bitcoin.data.RpcUnspent
import io.emeraldpay.dshackle.upstream.bitcoin.data.RpcUnspentDeserializer import io.emeraldpay.dshackle.upstream.bitcoin.data.RpcUnspentDeserializer
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import java.util.TimeZone import java.util.TimeZone

View File

@@ -16,7 +16,6 @@
package io.emeraldpay.dshackle package io.emeraldpay.dshackle
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.grpc.Chain
/** /**
* Exception that should be handled/logged without a stacktrace in production * Exception that should be handled/logged without a stacktrace in production

View File

@@ -20,12 +20,10 @@ import org.slf4j.LoggerFactory
import org.springframework.boot.ResourceBanner import org.springframework.boot.ResourceBanner
import org.springframework.boot.SpringApplication import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.Import
import org.springframework.core.io.ClassPathResource import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.support.ResourcePropertySource import org.springframework.core.io.support.ResourcePropertySource
@SpringBootApplication(scanBasePackages = ["io.emeraldpay.dshackle"]) @SpringBootApplication(scanBasePackages = ["io.emeraldpay.dshackle"])
@Import(Config::class)
open class Starter open class Starter
private val log = LoggerFactory.getLogger(Starter::class.java) private val log = LoggerFactory.getLogger(Starter::class.java)

View File

@@ -16,12 +16,12 @@
package io.emeraldpay.dshackle.cache package io.emeraldpay.dshackle.cache
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.TxId import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.proto.CachesProto import io.emeraldpay.dshackle.proto.CachesProto
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.grpc.Chain
import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.reactive.RedisReactiveCommands
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Mono import reactor.core.publisher.Mono

View File

@@ -15,8 +15,8 @@
*/ */
package io.emeraldpay.dshackle.cache package io.emeraldpay.dshackle.cache
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.CacheConfig import io.emeraldpay.dshackle.config.CacheConfig
import io.emeraldpay.grpc.Chain
import io.lettuce.core.RedisClient import io.lettuce.core.RedisClient
import io.lettuce.core.RedisConnectionException import io.lettuce.core.RedisConnectionException
import io.lettuce.core.RedisURI import io.lettuce.core.RedisURI
@@ -42,7 +42,7 @@ open class CachesFactory(
} }
private var redis: StatefulRedisConnection<String, ByteArray>? = null private var redis: StatefulRedisConnection<String, ByteArray>? = null
private val all = EnumMap<Chain, Caches>(io.emeraldpay.grpc.Chain::class.java) private val all = EnumMap<Chain, Caches>(Chain::class.java)
@PostConstruct @PostConstruct
fun init() { fun init() {

View File

@@ -15,10 +15,10 @@
*/ */
package io.emeraldpay.dshackle.cache package io.emeraldpay.dshackle.cache
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.grpc.Chain
import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.reactive.RedisReactiveCommands
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Mono import reactor.core.publisher.Mono

View File

@@ -16,12 +16,12 @@
package io.emeraldpay.dshackle.cache package io.emeraldpay.dshackle.cache
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.proto.CachesProto import io.emeraldpay.dshackle.proto.CachesProto
import io.emeraldpay.dshackle.proto.CachesProto.ValueContainer import io.emeraldpay.dshackle.proto.CachesProto.ValueContainer
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.grpc.Chain
import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.reactive.RedisReactiveCommands
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Mono import reactor.core.publisher.Mono

View File

@@ -16,12 +16,12 @@
package io.emeraldpay.dshackle.cache package io.emeraldpay.dshackle.cache
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.TxId import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.proto.CachesProto import io.emeraldpay.dshackle.proto.CachesProto
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.grpc.Chain
import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.reactive.RedisReactiveCommands
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Mono import reactor.core.publisher.Mono

View File

@@ -15,10 +15,10 @@
*/ */
package io.emeraldpay.dshackle.cache package io.emeraldpay.dshackle.cache
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.data.DefaultContainer import io.emeraldpay.dshackle.data.DefaultContainer
import io.emeraldpay.dshackle.proto.CachesProto import io.emeraldpay.dshackle.proto.CachesProto
import io.emeraldpay.etherjar.rpc.json.TransactionReceiptJson import io.emeraldpay.etherjar.rpc.json.TransactionReceiptJson
import io.emeraldpay.grpc.Chain
import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.reactive.RedisReactiveCommands
import reactor.core.publisher.Mono import reactor.core.publisher.Mono

View File

@@ -16,13 +16,13 @@
package io.emeraldpay.dshackle.cache package io.emeraldpay.dshackle.cache
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.TxContainer import io.emeraldpay.dshackle.data.TxContainer
import io.emeraldpay.dshackle.data.TxId import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.proto.CachesProto import io.emeraldpay.dshackle.proto.CachesProto
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.grpc.Chain
import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.reactive.RedisReactiveCommands
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Mono import reactor.core.publisher.Mono

View File

@@ -15,7 +15,7 @@
*/ */
package io.emeraldpay.dshackle.config package io.emeraldpay.dshackle.config
import io.emeraldpay.grpc.Chain import io.emeraldpay.dshackle.Chain
class HealthConfig { class HealthConfig {

View File

@@ -15,8 +15,8 @@
*/ */
package io.emeraldpay.dshackle.config package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.yaml.snakeyaml.nodes.CollectionNode import org.yaml.snakeyaml.nodes.CollectionNode
import org.yaml.snakeyaml.nodes.MappingNode import org.yaml.snakeyaml.nodes.MappingNode

View File

@@ -16,7 +16,7 @@
*/ */
package io.emeraldpay.dshackle.config package io.emeraldpay.dshackle.config
import io.emeraldpay.grpc.Chain import io.emeraldpay.dshackle.Chain
/** /**
* Configure HTTP Proxy to Upstreams * Configure HTTP Proxy to Upstreams

View File

@@ -16,8 +16,8 @@
*/ */
package io.emeraldpay.dshackle.config package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.grpc.Chain
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.yaml.snakeyaml.nodes.MappingNode import org.yaml.snakeyaml.nodes.MappingNode

View File

@@ -15,9 +15,9 @@
*/ */
package io.emeraldpay.dshackle.config package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.Address import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
class TokensConfig( class TokensConfig(
val tokens: List<Token> val tokens: List<Token>

View File

@@ -0,0 +1,78 @@
package io.emeraldpay.dshackle.config.context
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.CachesFactory
import io.emeraldpay.dshackle.upstream.CallTargetsHolder
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
open class MultistreamsConfig(val beanFactory: ConfigurableListableBeanFactory) {
@Bean
open fun allMultistreams(
cachesFactory: CachesFactory,
callTargetsHolder: CallTargetsHolder
): List<Multistream> {
return Chain.values()
.filterNot { it == Chain.UNSPECIFIED }
.mapNotNull { chain ->
when (BlockchainType.from(chain)) {
BlockchainType.EVM_POS -> ethereumPosMultistream(chain, cachesFactory)
BlockchainType.EVM_POW -> ethereumMultistream(chain, cachesFactory)
BlockchainType.BITCOIN -> bitcoinMultistream(chain, cachesFactory)
else -> null
}
}
}
private fun ethereumMultistream(
chain: Chain,
cachesFactory: CachesFactory
): EthereumMultistream {
val name = "multi-ethereum-$chain"
return EthereumMultistream(
chain,
ArrayList(),
cachesFactory.getCaches(chain)
).also { register(it, name) }
}
open fun ethereumPosMultistream(
chain: Chain,
cachesFactory: CachesFactory
): EthereumPosMultiStream {
val name = "multi-ethereum-pos-$chain"
return EthereumPosMultiStream(
chain,
ArrayList(),
cachesFactory.getCaches(chain)
).also { register(it, name) }
}
open fun bitcoinMultistream(
chain: Chain,
cachesFactory: CachesFactory
): BitcoinMultistream {
val name = "multi-bitcoin-$chain"
return BitcoinMultistream(
chain,
ArrayList(),
cachesFactory.getCaches(chain)
).also { register(it, name) }
}
private fun register(bean: Any, name: String) {
beanFactory.initializeBean(bean, name)
beanFactory.autowireBean(bean)
this.beanFactory.registerSingleton(name, bean)
}
}

View File

@@ -1,9 +1,9 @@
package io.emeraldpay.dshackle.monitoring.accesslog package io.emeraldpay.dshackle.monitoring.accesslog
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.MainConfig import io.emeraldpay.dshackle.config.MainConfig
import io.emeraldpay.dshackle.rpc.NativeCall import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service

View File

@@ -16,7 +16,7 @@
package io.emeraldpay.dshackle.monitoring.accesslog package io.emeraldpay.dshackle.monitoring.accesslog
import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.annotation.JsonInclude
import io.emeraldpay.grpc.Chain import io.emeraldpay.dshackle.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.time.Instant import java.time.Instant
import java.util.UUID import java.util.UUID

View File

@@ -17,8 +17,8 @@ package io.emeraldpay.dshackle.monitoring.accesslog
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.AccessLogConfig import io.emeraldpay.dshackle.config.AccessLogConfig
import io.emeraldpay.grpc.Chain
import io.grpc.Attributes import io.grpc.Attributes
import io.grpc.Grpc import io.grpc.Grpc
import io.grpc.Metadata import io.grpc.Metadata

View File

@@ -17,9 +17,9 @@ package io.emeraldpay.dshackle.proxy
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp
import io.emeraldpay.dshackle.rpc.NativeCall import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.grpc.Chain
import org.reactivestreams.Publisher import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Flux import reactor.core.publisher.Flux

View File

@@ -15,13 +15,13 @@
*/ */
package io.emeraldpay.dshackle.proxy package io.emeraldpay.dshackle.proxy
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.config.ProxyConfig import io.emeraldpay.dshackle.config.ProxyConfig
import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp
import io.emeraldpay.dshackle.rpc.NativeCall import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.rpc.RpcException import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.grpc.Chain
import io.netty.buffer.ByteBuf import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled import io.netty.buffer.Unpooled
import org.reactivestreams.Publisher import org.reactivestreams.Publisher

View File

@@ -16,13 +16,13 @@
*/ */
package io.emeraldpay.dshackle.proxy package io.emeraldpay.dshackle.proxy
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.TlsSetup import io.emeraldpay.dshackle.TlsSetup
import io.emeraldpay.dshackle.config.ProxyConfig import io.emeraldpay.dshackle.config.ProxyConfig
import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp
import io.emeraldpay.dshackle.rpc.NativeCall import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.dshackle.rpc.NativeSubscribe import io.emeraldpay.dshackle.rpc.NativeSubscribe
import io.emeraldpay.grpc.Chain
import io.micrometer.core.instrument.Counter import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.Metrics import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Timer import io.micrometer.core.instrument.Timer

View File

@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.proxy
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.BlockchainOuterClass.Selector import io.emeraldpay.api.proto.BlockchainOuterClass.Selector
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.config.ProxyConfig import io.emeraldpay.dshackle.config.ProxyConfig
import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp
@@ -25,7 +26,6 @@ import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.dshackle.rpc.NativeSubscribe import io.emeraldpay.dshackle.rpc.NativeSubscribe
import io.emeraldpay.etherjar.rpc.json.RequestJson import io.emeraldpay.etherjar.rpc.json.RequestJson
import io.emeraldpay.etherjar.rpc.json.ResponseJson import io.emeraldpay.etherjar.rpc.json.ResponseJson
import io.emeraldpay.grpc.Chain
import io.netty.buffer.ByteBufInputStream import io.netty.buffer.ByteBufInputStream
import io.netty.buffer.Unpooled import io.netty.buffer.Unpooled
import org.reactivestreams.Publisher import org.reactivestreams.Publisher

View File

@@ -19,9 +19,9 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.api.proto.ReactorBlockchainGrpc import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.ChainValue import io.emeraldpay.dshackle.ChainValue
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.grpc.Chain
import io.micrometer.core.instrument.Counter import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.Metrics import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Timer import io.micrometer.core.instrument.Timer

View File

@@ -44,6 +44,7 @@ class Describe(
.setChain(Common.ChainRef.forNumber(chain.id)) .setChain(Common.ChainRef.forNumber(chain.id))
.addAllSupportedMethods(targets) .addAllSupportedMethods(targets)
.setStatus(status) .setStatus(status)
.setCurrentHeight(chainUpstreams.getHead().getCurrentHeight() ?: 0)
chainUpstreams.getAll().let { ups -> chainUpstreams.getAll().let { ups ->
ups.forEach { up -> ups.forEach { up ->
val nodes = QuorumForLabels() val nodes = QuorumForLabels()

View File

@@ -1,9 +1,9 @@
package io.emeraldpay.dshackle.rpc package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.upstream.ChainFees import io.emeraldpay.dshackle.upstream.ChainFees
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.grpc.Chain
import io.grpc.Status import io.grpc.Status
import io.grpc.StatusException import io.grpc.StatusException
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory

View File

@@ -19,6 +19,8 @@ package io.emeraldpay.dshackle.rpc
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.quorum.CallQuorum import io.emeraldpay.dshackle.quorum.CallQuorum
@@ -26,11 +28,11 @@ import io.emeraldpay.dshackle.quorum.NotLaggingQuorum
import io.emeraldpay.dshackle.quorum.QuorumReaderFactory import io.emeraldpay.dshackle.quorum.QuorumReaderFactory
import io.emeraldpay.dshackle.quorum.QuorumRpcReader import io.emeraldpay.dshackle.quorum.QuorumRpcReader
import io.emeraldpay.dshackle.startup.ConfiguredUpstreams import io.emeraldpay.dshackle.startup.ConfiguredUpstreams
import io.emeraldpay.dshackle.upstream.ApiSource import io.emeraldpay.dshackle.startup.UpstreamChangeEvent
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.calls.EthereumCallSelector import io.emeraldpay.dshackle.upstream.calls.EthereumCallSelector
import io.emeraldpay.dshackle.upstream.ethereum.EthereumLikeMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError
@@ -40,12 +42,10 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.dshackle.upstream.signature.ResponseSigner import io.emeraldpay.dshackle.upstream.signature.ResponseSigner
import io.emeraldpay.etherjar.rpc.RpcException import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.etherjar.rpc.RpcResponseError import io.emeraldpay.etherjar.rpc.RpcResponseError
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import io.micrometer.core.instrument.Metrics import io.micrometer.core.instrument.Metrics
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.event.EventListener
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
@@ -55,9 +55,9 @@ import java.util.concurrent.atomic.AtomicInteger
@Service @Service
open class NativeCall( open class NativeCall(
@Autowired private val multistreamHolder: MultistreamHolder, private val multistreamHolder: MultistreamHolder,
@Autowired private val configuredUpstreams: ConfiguredUpstreams, private val configuredUpstreams: ConfiguredUpstreams,
@Autowired private val signer: ResponseSigner private val signer: ResponseSigner
) { ) {
private val log = LoggerFactory.getLogger(NativeCall::class.java) private val log = LoggerFactory.getLogger(NativeCall::class.java)
@@ -66,18 +66,19 @@ open class NativeCall(
var quorumReaderFactory: QuorumReaderFactory = QuorumReaderFactory.default() var quorumReaderFactory: QuorumReaderFactory = QuorumReaderFactory.default()
private val ethereumCallSelectors = EnumMap<Chain, EthereumCallSelector>(Chain::class.java) private val ethereumCallSelectors = EnumMap<Chain, EthereumCallSelector>(Chain::class.java)
init { companion object {
val casting = mapOf( val casting: Map<BlockchainType, Class<out EthereumLikeMultistream>> = mapOf(
BlockchainType.EVM_POS to EthereumPosMultiStream::class.java, BlockchainType.EVM_POS to EthereumPosMultiStream::class.java,
BlockchainType.EVM_POW to EthereumMultistream::class.java, BlockchainType.EVM_POW to EthereumMultistream::class.java
) )
}
multistreamHolder.observeChains().subscribe { chain -> @EventListener
casting[BlockchainType.from(chain)]?.let { cast -> fun onUpstreamChangeEvent(event: UpstreamChangeEvent) {
multistreamHolder.getUpstream(chain)?.let { up -> casting[BlockchainType.from(event.chain)]?.let { cast ->
val reader = up.cast(cast).getReader() multistreamHolder.getUpstream(event.chain)?.let { up ->
ethereumCallSelectors.putIfAbsent(chain, EthereumCallSelector(reader.heightByHash())) val reader = up.cast(cast).getReader()
} ethereumCallSelectors.putIfAbsent(event.chain, EthereumCallSelector(reader.heightByHash()))
} }
} }
} }
@@ -166,7 +167,8 @@ open class NativeCall(
} }
val matcher = Selector.convertToMatcher(request.selector) val matcher = Selector.convertToMatcher(request.selector)
if (!configuredUpstreams.hasMatchingUpstream(chain, matcher)) {
if (!multistreamHolder.getUpstream(chain).hasMatchingUpstream(matcher)) {
if (Global.metricsExtended) { if (Global.metricsExtended) {
Metrics.globalRegistry Metrics.globalRegistry
.counter("no_matching_upstream", "chain", chain.chainCode, "matcher", matcher.describeInternal()) .counter("no_matching_upstream", "chain", chain.chainCode, "matcher", matcher.describeInternal())
@@ -176,7 +178,6 @@ open class NativeCall(
} }
val upstream = multistreamHolder.getUpstream(chain) val upstream = multistreamHolder.getUpstream(chain)
?: return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(chain)))
return prepareCall(request, upstream) return prepareCall(request, upstream)
} }
@@ -255,17 +256,13 @@ open class NativeCall(
} }
private fun getRequestDecorator(method: String): RequestDecorator = private fun getRequestDecorator(method: String): RequestDecorator =
if (method in listOf( if (method in DefaultEthereumMethods.withFilterIdMethods)
"eth_getFilterChanges", WithFilterIdDecorator()
"eth_uninstallFilter",
)
)
GetFilterUpdatesDecorator()
else else
NoneRequestDecorator() NoneRequestDecorator()
private fun getResultDecorator(method: String): ResultDecorator = private fun getResultDecorator(method: String): ResultDecorator =
if (CreateFilterDecorator.createFilterMethods.contains(method)) CreateFilterDecorator() else NoneResultDecorator() if (method in DefaultEthereumMethods.newFilterMethods) CreateFilterDecorator() else NoneResultDecorator()
fun fetch(ctx: ValidCallContext<ParsedCallDetails>): Mono<CallResult> { fun fetch(ctx: ValidCallContext<ParsedCallDetails>): Mono<CallResult> {
return ctx.upstream.getRoutedApi(ctx.matcher) return ctx.upstream.getRoutedApi(ctx.matcher)
@@ -385,11 +382,6 @@ open class NativeCall(
companion object { companion object {
const val quoteCode = '"'.code.toByte() const val quoteCode = '"'.code.toByte()
val createFilterMethods = listOf(
"eth_newFilter",
"eth_newBlockFilter",
"eth_newPendingTransactionFilter",
)
} }
override fun processResult(result: QuorumRpcReader.Result): ByteArray { override fun processResult(result: QuorumRpcReader.Result): ByteArray {
val bytes = result.value val bytes = result.value
@@ -410,7 +402,7 @@ open class NativeCall(
override fun processRequest(request: List<Any>): List<Any> = request override fun processRequest(request: List<Any>): List<Any> = request
} }
open class GetFilterUpdatesDecorator : RequestDecorator { open class WithFilterIdDecorator : RequestDecorator {
override fun processRequest(request: List<Any>): List<Any> { override fun processRequest(request: List<Any>): List<Any> {
val filterId = request.first().toString() val filterId = request.first().toString()
val sanitized = filterId.substring(0, filterId.lastIndex - 1) val sanitized = filterId.substring(0, filterId.lastIndex - 1)

View File

@@ -18,6 +18,8 @@ package io.emeraldpay.dshackle.rpc
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.BlockchainOuterClass.NativeSubscribeReplyItem import io.emeraldpay.api.proto.BlockchainOuterClass.NativeSubscribeReplyItem
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
@@ -25,8 +27,6 @@ import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.ethereum.EthereumLikeMultistream import io.emeraldpay.dshackle.upstream.ethereum.EthereumLikeMultistream
import io.emeraldpay.dshackle.upstream.ethereum.subscribe.json.HasUpstream import io.emeraldpay.dshackle.upstream.ethereum.subscribe.json.HasUpstream
import io.emeraldpay.dshackle.upstream.signature.ResponseSigner import io.emeraldpay.dshackle.upstream.signature.ResponseSigner
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import io.grpc.Status import io.grpc.Status
import io.grpc.StatusException import io.grpc.StatusException
import org.reactivestreams.Publisher import org.reactivestreams.Publisher

View File

@@ -19,9 +19,9 @@ package io.emeraldpay.dshackle.rpc
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service

View File

@@ -18,10 +18,10 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.grpc.Chain
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import reactor.core.publisher.Flux import reactor.core.publisher.Flux

View File

@@ -16,7 +16,7 @@
package io.emeraldpay.dshackle.rpc package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.grpc.Chain import io.emeraldpay.dshackle.Chain
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
/** /**

View File

@@ -18,27 +18,28 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.api.proto.ReactorBlockchainGrpc import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Defaults import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.startup.UpstreamChangeEvent
import io.emeraldpay.dshackle.upstream.Capability import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
import io.emeraldpay.dshackle.upstream.bitcoin.data.SimpleUnspent import io.emeraldpay.dshackle.upstream.bitcoin.data.SimpleUnspent
import io.emeraldpay.dshackle.upstream.grpc.BitcoinGrpcUpstream import io.emeraldpay.dshackle.upstream.grpc.BitcoinGrpcUpstream
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
import org.bitcoinj.params.MainNetParams import org.bitcoinj.params.MainNetParams
import org.bitcoinj.params.TestNet3Params import org.bitcoinj.params.TestNet3Params
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.event.EventListener
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.math.BigInteger import java.math.BigInteger
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import javax.annotation.PostConstruct
@Service @Service
class TrackBitcoinAddress( class TrackBitcoinAddress(
@@ -67,15 +68,13 @@ class TrackBitcoinAddress(
Selector.CapabilityMatcher(Capability.BALANCE) Selector.CapabilityMatcher(Capability.BALANCE)
) )
@PostConstruct @EventListener
fun listenChains() { fun onUpstreamChangeEvent(event: UpstreamChangeEvent) {
multistreamHolder.observeChains().subscribe { chain -> multistreamHolder.getUpstream(event.chain)?.let { mup ->
multistreamHolder.getUpstream(chain)?.let { mup -> val available = mup.getAll().any { up ->
val available = mup.getAll().any { up -> !up.isGrpc() && up.getCapabilities().contains(Capability.BALANCE)
!up.isGrpc() && up.getCapabilities().contains(Capability.BALANCE)
}
setBalanceAvailability(chain, available)
} }
setBalanceAvailability(event.chain, available)
} }
} }

View File

@@ -17,12 +17,12 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
import io.emeraldpay.dshackle.upstream.bitcoin.ExtractBlock import io.emeraldpay.dshackle.upstream.bitcoin.ExtractBlock
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service

View File

@@ -17,6 +17,8 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.config.TokensConfig import io.emeraldpay.dshackle.config.TokensConfig
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
@@ -26,8 +28,6 @@ import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.etherjar.domain.Address import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.domain.EventId import io.emeraldpay.etherjar.domain.EventId
import io.emeraldpay.etherjar.erc20.ERC20Token import io.emeraldpay.etherjar.erc20.ERC20Token
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service

View File

@@ -18,14 +18,14 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Defaults import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.etherjar.domain.Address import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.domain.Wei import io.emeraldpay.etherjar.domain.Wei
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service

View File

@@ -18,6 +18,8 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.TxId import io.emeraldpay.dshackle.data.TxId
@@ -29,8 +31,6 @@ import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.etherjar.rpc.json.BlockJson import io.emeraldpay.etherjar.rpc.json.BlockJson
import io.emeraldpay.etherjar.rpc.json.TransactionJson import io.emeraldpay.etherjar.rpc.json.TransactionJson
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service

View File

@@ -16,7 +16,7 @@
package io.emeraldpay.dshackle.rpc package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.grpc.Chain import io.emeraldpay.dshackle.Chain
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
interface TrackTx { interface TrackTx {

View File

@@ -17,17 +17,13 @@
package io.emeraldpay.dshackle.startup package io.emeraldpay.dshackle.startup
import com.google.common.annotations.VisibleForTesting import com.google.common.annotations.VisibleForTesting
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.FileResolver import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.BlockValidator import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.CurrentMultistreamHolder
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.HttpRpcFactory
import io.emeraldpay.dshackle.upstream.MergedHead
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinRpcHead import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinRpcHead
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinRpcUpstream import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinRpcUpstream
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinZMQHead import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinZMQHead
@@ -47,31 +43,30 @@ import io.emeraldpay.dshackle.upstream.forkchoice.NoChoiceWithPriorityForkChoice
import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstreams import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstreams
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.ApplicationArguments
import org.springframework.stereotype.Repository import org.springframework.boot.ApplicationRunner
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Component
import java.net.URI import java.net.URI
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import java.util.function.Function import java.util.function.Function
import javax.annotation.PostConstruct
import kotlin.math.abs import kotlin.math.abs
@Repository @Component
open class ConfiguredUpstreams( open class ConfiguredUpstreams(
@Autowired private val currentUpstreams: CurrentMultistreamHolder, private val fileResolver: FileResolver,
@Autowired private val fileResolver: FileResolver, private val config: UpstreamsConfig,
@Autowired private val config: UpstreamsConfig private val callTargets: CallTargetsHolder,
) { private val eventPublisher: ApplicationEventPublisher
) : ApplicationRunner {
private val log = LoggerFactory.getLogger(ConfiguredUpstreams::class.java) private val log = LoggerFactory.getLogger(ConfiguredUpstreams::class.java)
private var seq = AtomicInteger(0) private var seq = AtomicInteger(0)
private val hashes: MutableMap<Byte, Boolean> = HashMap() private val hashes: MutableMap<Byte, Boolean> = HashMap()
@PostConstruct override fun run(args: ApplicationArguments) {
fun start() {
log.debug("Starting upstreams") log.debug("Starting upstreams")
val defaultOptions = buildDefaultOptions(config) val defaultOptions = buildDefaultOptions(config)
config.upstreams.forEach { up -> config.upstreams.forEach { up ->
@@ -115,17 +110,13 @@ open class ConfiguredUpstreams(
} }
} }
upstream?.let { upstream?.let {
currentUpstreams.update(UpstreamChange(chain, upstream, UpstreamChange.ChangeType.ADDED)) val event = UpstreamChangeEvent(chain, upstream, UpstreamChangeEvent.ChangeType.ADDED)
eventPublisher.publishEvent(event)
} }
} }
} }
} }
fun hasMatchingUpstream(chain: Chain, matcher: Selector.LabelSelectorMatcher): Boolean =
config.upstreams.any { up ->
(up.chain?.let { Global.chainById(it) == chain } ?: true) && matcher.matches(up.labels)
}
private fun buildDefaultOptions(config: UpstreamsConfig): HashMap<Chain, UpstreamsConfig.Options> { private fun buildDefaultOptions(config: UpstreamsConfig): HashMap<Chain, UpstreamsConfig.Options> {
val defaultOptions = HashMap<Chain, UpstreamsConfig.Options>() val defaultOptions = HashMap<Chain, UpstreamsConfig.Options>()
config.defaultOptions.forEach { defaultsConfig -> config.defaultOptions.forEach { defaultsConfig ->
@@ -150,7 +141,7 @@ open class ConfiguredUpstreams(
fun buildMethods(config: UpstreamsConfig.Upstream<*>, chain: Chain): CallMethods { fun buildMethods(config: UpstreamsConfig.Upstream<*>, chain: Chain): CallMethods {
return if (config.methods != null) { return if (config.methods != null) {
ManagedCallMethods( ManagedCallMethods(
currentUpstreams.getDefaultMethods(chain), callTargets.getDefaultMethods(chain),
config.methods!!.enabled.map { it.name }.toSet(), config.methods!!.enabled.map { it.name }.toSet(),
config.methods!!.disabled.map { it.name }.toSet() config.methods!!.disabled.map { it.name }.toSet()
).also { ).also {
@@ -164,7 +155,7 @@ open class ConfiguredUpstreams(
} }
} }
} else { } else {
currentUpstreams.getDefaultMethods(chain) callTargets.getDefaultMethods(chain)
} }
} }
@@ -315,7 +306,7 @@ open class ConfiguredUpstreams(
.doOnNext { .doOnNext {
log.info("Chain ${it.chain} ${it.type} through gRPC at ${endpoint.host}:${endpoint.port}. With caps: ${it.upstream.getCapabilities()}") log.info("Chain ${it.chain} ${it.type} through gRPC at ${endpoint.host}:${endpoint.port}. With caps: ${it.upstream.getCapabilities()}")
} }
.subscribe(currentUpstreams::update) .subscribe(eventPublisher::publishEvent)
} }
private fun buildHttpFactory(conn: UpstreamsConfig.RpcConnection, urls: ArrayList<URI>? = null): HttpRpcFactory? { private fun buildHttpFactory(conn: UpstreamsConfig.RpcConnection, urls: ArrayList<URI>? = null): HttpRpcFactory? {

View File

@@ -16,15 +16,15 @@
*/ */
package io.emeraldpay.dshackle.startup package io.emeraldpay.dshackle.startup
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.grpc.Chain
/** /**
* An update event to the list of currently available upstreams. * An update event to the list of currently available upstreams.
*/ */
class UpstreamChange( class UpstreamChangeEvent(
/** /**
* Target blockchain * Target blockchain
*/ */

View File

@@ -0,0 +1,29 @@
package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import org.springframework.stereotype.Component
import java.util.HashMap
@Component
class CallTargetsHolder {
private val callTargets = HashMap<Chain, CallMethods>()
fun getDefaultMethods(chain: Chain): CallMethods {
return callTargets[chain] ?: return setupDefaultMethods(chain)
}
private fun setupDefaultMethods(chain: Chain): CallMethods {
val created = when (BlockchainType.from(chain)) {
BlockchainType.EVM_POW -> DefaultEthereumMethods(chain)
BlockchainType.BITCOIN -> DefaultBitcoinMethods()
BlockchainType.EVM_POS -> DefaultEthereumMethods(chain)
else -> throw IllegalStateException("Unsupported chain: $chain")
}
callTargets[chain] = created
return created
}
}

View File

@@ -16,156 +16,40 @@
*/ */
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.cache.CachesEnabled import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.CachesFactory
import io.emeraldpay.dshackle.startup.UpstreamChange
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosUpstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component
import org.springframework.stereotype.Repository
import reactor.core.publisher.Flux
import reactor.core.publisher.Sinks
import java.util.Collections
import java.util.concurrent.Callable
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.locks.ReentrantLock
import javax.annotation.PreDestroy import javax.annotation.PreDestroy
import kotlin.concurrent.withLock
@Repository @Component
open class CurrentMultistreamHolder( open class CurrentMultistreamHolder(
@Autowired private val cachesFactory: CachesFactory multistreams: List<Multistream>
) : MultistreamHolder { ) : MultistreamHolder {
private val log = LoggerFactory.getLogger(CurrentMultistreamHolder::class.java) private val log = LoggerFactory.getLogger(CurrentMultistreamHolder::class.java)
private val chainMapping = ConcurrentHashMap<Chain, Multistream>() private val chainMapping = multistreams.associateBy { it.chain }
private val chainsBus = Sinks.many()
.multicast()
.directBestEffort<Chain>()
private val callTargets = HashMap<Chain, CallMethods>()
private val updateLock = ReentrantLock()
fun update(change: UpstreamChange) { override fun getUpstream(chain: Chain): Multistream {
updateLock.withLock { return chainMapping.getValue(chain)
log.debug("Upstream update: ${change.type} ${change.chain} via ${change.upstream.getId()}")
val chain = change.chain
try {
when (BlockchainType.from(chain)) {
BlockchainType.EVM_POW -> {
val up = change.upstream.cast(EthereumUpstream::class.java)
val current = chainMapping[chain]
val factory = Callable<Multistream> {
EthereumMultistream(chain, ArrayList(), cachesFactory.getCaches(chain))
}
processUpdate(change, up, current, factory)
}
BlockchainType.EVM_POS -> {
val up = change.upstream.cast(EthereumPosUpstream::class.java)
val current = chainMapping[chain]
val factory = Callable<Multistream> {
EthereumPosMultiStream(chain, ArrayList(), cachesFactory.getCaches(chain))
}
processUpdate(change, up, current, factory)
}
BlockchainType.BITCOIN -> {
val up = change.upstream.cast(BitcoinUpstream::class.java)
val current = chainMapping[chain]
val factory = Callable<Multistream> {
BitcoinMultistream(chain, ArrayList(), cachesFactory.getCaches(chain))
}
processUpdate(change, up, current, factory)
}
else -> {
log.error("Update for unsupported chain: $chain")
}
}
} catch (e: Throwable) {
log.error("Failed to update upstream", e)
}
}
}
fun processUpdate(change: UpstreamChange, up: Upstream, current: Multistream?, factory: Callable<Multistream>) {
val chain = change.chain
if (change.type == UpstreamChange.ChangeType.REMOVED) {
current?.removeUpstream(up.getId())
log.info("Upstream ${change.upstream.getId()} with chain $chain has been removed")
} else {
if (current == null) {
val created = factory.call()
if (up is CachesEnabled) {
up.setCaches(created.caches)
}
created.addUpstream(up)
created.start()
chainMapping[chain] = created
chainsBus.tryEmitNext(chain)
} else {
if (up is CachesEnabled) {
up.setCaches(current.caches)
}
current.addUpstream(up)
}
if (!callTargets.containsKey(chain)) {
setupDefaultMethods(chain)
}
log.info("Upstream ${change.upstream.getId()} with chain $chain has been added")
}
}
override fun getUpstream(chain: Chain): Multistream? {
return chainMapping[chain]
} }
override fun getAvailable(): List<Chain> { override fun getAvailable(): List<Chain> {
return Collections.unmodifiableList(chainMapping.keys.toList()) return chainMapping.values.asSequence()
} .filter { it.haveUpstreams() }
.map { it.chain }
override fun observeChains(): Flux<Chain> { .toList()
return Flux.concat(
Flux.fromIterable(getAvailable()),
chainsBus.asFlux()
)
}
override fun getDefaultMethods(chain: Chain): CallMethods {
return callTargets[chain] ?: return setupDefaultMethods(chain)
}
fun setupDefaultMethods(chain: Chain): CallMethods {
val created = when (BlockchainType.from(chain)) {
BlockchainType.EVM_POW -> DefaultEthereumMethods(chain)
BlockchainType.BITCOIN -> DefaultBitcoinMethods()
BlockchainType.EVM_POS -> DefaultEthereumMethods(chain)
else -> throw IllegalStateException("Unsupported chain: $chain")
}
callTargets[chain] = created
return created
} }
override fun isAvailable(chain: Chain): Boolean { override fun isAvailable(chain: Chain): Boolean {
return chainMapping.containsKey(chain) && callTargets.containsKey(chain) return chainMapping.getValue(chain).isAvailable()
} }
@PreDestroy @PreDestroy
fun shutdown() { fun shutdown() {
log.info("Closing upstream connections...") log.info("Closing upstream connections...")
updateLock.withLock { chainMapping.values.forEach {
chainMapping.values.forEach { it.stop()
it.stop()
}
chainMapping.clear()
} }
} }
} }

View File

@@ -16,9 +16,9 @@
*/ */
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.grpc.Chain
import io.micrometer.core.instrument.DistributionSummary import io.micrometer.core.instrument.DistributionSummary
import io.micrometer.core.instrument.Metrics import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Tag

View File

@@ -1,9 +1,9 @@
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
interface HttpFactory { interface HttpFactory {
fun create(id: String?, chain: Chain): Reader<JsonRpcRequest, JsonRpcResponse> fun create(id: String?, chain: Chain): Reader<JsonRpcRequest, JsonRpcResponse>

View File

@@ -1,12 +1,12 @@
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.AuthConfig import io.emeraldpay.dshackle.config.AuthConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcHttpClient import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcHttpClient
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.dshackle.upstream.rpcclient.RpcMetrics import io.emeraldpay.dshackle.upstream.rpcclient.RpcMetrics
import io.emeraldpay.grpc.Chain
import io.micrometer.core.instrument.Counter import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.Metrics import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Tag

View File

@@ -0,0 +1,7 @@
package io.emeraldpay.dshackle.upstream
interface Lifecycle {
fun start()
fun stop()
fun isRunning(): Boolean
}

View File

@@ -21,7 +21,6 @@ import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
@@ -43,7 +42,7 @@ class MergedHead(
override fun start() { override fun start() {
super.start() super.start()
sources.forEach { head -> sources.forEach { head ->
if (head is Lifecycle && !head.isRunning) { if (head is Lifecycle && !head.isRunning()) {
head.start() head.start()
} }
} }
@@ -56,7 +55,7 @@ class MergedHead(
override fun stop() { override fun stop() {
super.stop() super.stop()
sources.forEach { head -> sources.forEach { head ->
if (head is Lifecycle && head.isRunning) { if (head is Lifecycle && head.isRunning()) {
head.stop() head.stop()
} }
} }

View File

@@ -16,26 +16,30 @@
*/ */
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.UpstreamChangeEvent
import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import io.micrometer.core.instrument.Metrics import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Tag
import org.apache.commons.collections4.Factory import org.apache.commons.collections4.Factory
import org.apache.commons.collections4.FunctorException import org.apache.commons.collections4.FunctorException
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle import org.springframework.context.event.EventListener
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
import java.util.Locale import java.util.*
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import java.util.function.Predicate import java.util.function.Predicate
@@ -56,6 +60,8 @@ abstract class Multistream(
private const val metrics = "upstreams" private const val metrics = "upstreams"
} }
private var started = false
private var cacheSubscription: Disposable? = null private var cacheSubscription: Disposable? = null
private val reconfigLock = ReentrantLock() private val reconfigLock = ReentrantLock()
private var callMethods: CallMethods? = null private var callMethods: CallMethods? = null
@@ -231,6 +237,7 @@ abstract class Multistream(
// print status _change_ every 15 seconds, at most; otherwise prints it on interval of 30 seconds // print status _change_ every 15 seconds, at most; otherwise prints it on interval of 30 seconds
.sample(Duration.ofSeconds(15)) .sample(Duration.ofSeconds(15))
.subscribe { printStatus() } .subscribe { printStatus() }
started = true
} }
override fun stop() { override fun stop() {
@@ -244,6 +251,7 @@ abstract class Multistream(
} }
} }
lagObserver?.stop() lagObserver?.stop()
started = false
} }
fun onHeadUpdated(head: Head) { fun onHeadUpdated(head: Head) {
@@ -316,6 +324,38 @@ abstract class Multistream(
log.info("State of ${chain.chainCode}: height=${height ?: '?'}, status=[$statuses], lag=[$lag], weak=[$weak]") log.info("State of ${chain.chainCode}: height=${height ?: '?'}, status=[$statuses], lag=[$lag], weak=[$weak]")
} }
fun test(event: UpstreamChangeEvent): Boolean {
return event.chain == this.chain
}
@EventListener
@Order(Ordered.HIGHEST_PRECEDENCE)
fun onUpstreamChange(event: UpstreamChangeEvent) {
val chain = event.chain
if (this.chain == chain) {
if (event.type == UpstreamChangeEvent.ChangeType.REMOVED) {
removeUpstream(event.upstream.getId())
log.error("Upstream ${event.upstream.getId()} with chain $chain has been removed")
} else {
if (event.upstream is CachesEnabled) {
event.upstream.setCaches(caches)
}
addUpstream(event.upstream)
if (!started) {
start()
}
log.error("Upstream ${event.upstream.getId()} with chain $chain has been added")
}
}
}
fun haveUpstreams(): Boolean =
upstreams.isNotEmpty()
fun hasMatchingUpstream(matcher: Selector.LabelSelectorMatcher): Boolean {
return upstreams.any { matcher.matches(it) }
}
// -------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------
class UpstreamStatus(val upstream: Upstream, val status: UpstreamAvailability, val ts: Instant = Instant.now()) class UpstreamStatus(val upstream: Upstream, val status: UpstreamAvailability, val ts: Instant = Instant.now())

View File

@@ -16,17 +16,13 @@
*/ */
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.Chain
import io.emeraldpay.grpc.Chain
import reactor.core.publisher.Flux
/** /**
* Holds Multistreams configured for a chain. * Holds Multistreams configured for a chain.
*/ */
interface MultistreamHolder { interface MultistreamHolder {
fun getUpstream(chain: Chain): Multistream? fun getUpstream(chain: Chain): Multistream
fun getAvailable(): List<Chain> fun getAvailable(): List<Chain>
fun observeChains(): Flux<Chain>
fun getDefaultMethods(chain: Chain): CallMethods
fun isAvailable(chain: Chain): Boolean fun isAvailable(chain: Chain): Boolean
} }

View File

@@ -15,24 +15,17 @@
*/ */
package io.emeraldpay.dshackle.upstream.bitcoin package io.emeraldpay.dshackle.upstream.bitcoin
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.ChainFees import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.EmptyHead import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.MergedHead
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.RequestPostprocessor
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -142,7 +135,7 @@ open class BitcoinMultistream(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return super.isRunning() || reader.isRunning return super.isRunning() || reader.isRunning()
} }
override fun start() { override fun start() {

View File

@@ -19,13 +19,13 @@ import com.fasterxml.jackson.databind.ObjectMapper
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.upstream.Capability import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.bitcoin.data.SimpleUnspent import io.emeraldpay.dshackle.upstream.bitcoin.data.SimpleUnspent
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import org.bitcoinj.core.Address import org.bitcoinj.core.Address
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.cast import reactor.kotlin.core.publisher.cast
@@ -72,7 +72,7 @@ open class BitcoinReader(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return mempool.isRunning return mempool.isRunning()
} }
override fun start() { override fun start() {

View File

@@ -19,11 +19,11 @@ import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.AbstractHead import io.emeraldpay.dshackle.upstream.AbstractHead
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import org.springframework.scheduling.concurrent.CustomizableThreadFactory import org.springframework.scheduling.concurrent.CustomizableThreadFactory
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Flux import reactor.core.publisher.Flux

View File

@@ -15,19 +15,19 @@
*/ */
package io.emeraldpay.dshackle.upstream.bitcoin package io.emeraldpay.dshackle.upstream.bitcoin
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.Capability import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
open class BitcoinRpcUpstream( open class BitcoinRpcUpstream(
@@ -92,7 +92,7 @@ open class BitcoinRpcUpstream(
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
var runningAny = validatorSubscription != null var runningAny = validatorSubscription != null
if (head is Lifecycle) { if (head is Lifecycle) {
runningAny = runningAny || head.isRunning runningAny = runningAny || head.isRunning()
} }
return runningAny return runningAny
} }
@@ -100,7 +100,7 @@ open class BitcoinRpcUpstream(
override fun start() { override fun start() {
log.info("Configured for ${chain.chainName}") log.info("Configured for ${chain.chainName}")
if (head is Lifecycle) { if (head is Lifecycle) {
if (!head.isRunning) { if (!head.isRunning()) {
head.start() head.start()
} }
} }

View File

@@ -15,12 +15,12 @@
*/ */
package io.emeraldpay.dshackle.upstream.bitcoin package io.emeraldpay.dshackle.upstream.bitcoin
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
abstract class BitcoinUpstream( abstract class BitcoinUpstream(

View File

@@ -5,12 +5,12 @@ import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.AbstractHead import io.emeraldpay.dshackle.upstream.AbstractHead
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import org.apache.commons.codec.binary.Hex import org.apache.commons.codec.binary.Hex
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
@@ -65,6 +65,6 @@ class BitcoinZMQHead(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return server.isRunning || refreshSubscription != null return server.isRunning() || refreshSubscription != null
} }
} }

View File

@@ -18,11 +18,11 @@ package io.emeraldpay.dshackle.upstream.bitcoin
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.time.Duration import java.time.Duration

View File

@@ -1,7 +1,7 @@
package io.emeraldpay.dshackle.upstream.bitcoin package io.emeraldpay.dshackle.upstream.bitcoin
import io.emeraldpay.dshackle.upstream.Lifecycle
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import org.zeromq.SocketType import org.zeromq.SocketType
import org.zeromq.ZContext import org.zeromq.ZContext
import org.zeromq.ZMQ import org.zeromq.ZMQ

View File

@@ -16,6 +16,7 @@
*/ */
package io.emeraldpay.dshackle.upstream.calls package io.emeraldpay.dshackle.upstream.calls
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.quorum.AlwaysQuorum import io.emeraldpay.dshackle.quorum.AlwaysQuorum
import io.emeraldpay.dshackle.quorum.BroadcastQuorum import io.emeraldpay.dshackle.quorum.BroadcastQuorum
@@ -23,7 +24,6 @@ import io.emeraldpay.dshackle.quorum.CallQuorum
import io.emeraldpay.dshackle.quorum.NonceQuorum import io.emeraldpay.dshackle.quorum.NonceQuorum
import io.emeraldpay.dshackle.quorum.NotLaggingQuorum import io.emeraldpay.dshackle.quorum.NotLaggingQuorum
import io.emeraldpay.etherjar.rpc.RpcException import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.grpc.Chain
/** /**
* Default configuration for Ethereum based RPC. Defines optimal Quorum strategies for different methods, and provides * Default configuration for Ethereum based RPC. Defines optimal Quorum strategies for different methods, and provides
@@ -35,6 +35,20 @@ class DefaultEthereumMethods(
private val version = "\"EmeraldDshackle/${Global.version}\"" private val version = "\"EmeraldDshackle/${Global.version}\""
companion object {
val withFilterIdMethods = listOf(
"eth_getFilterChanges",
"eth_getFilterLogs",
"eth_uninstallFilter"
)
val newFilterMethods = listOf(
"eth_newFilter",
"eth_newBlockFilter",
"eth_newPendingTransactionFilter",
)
}
private val anyResponseMethods = listOf( private val anyResponseMethods = listOf(
"eth_gasPrice", "eth_gasPrice",
"eth_call", "eth_call",
@@ -70,13 +84,7 @@ class DefaultEthereumMethods(
"eth_feeHistory" "eth_feeHistory"
) )
private val filterMethods = listOf( private val filterMethods = withFilterIdMethods + newFilterMethods
"eth_getFilterChanges",
"eth_newFilter",
"eth_newBlockFilter",
"eth_newPendingTransactionFilter",
"eth_uninstallFilter"
)
private val hardcodedMethods = listOf( private val hardcodedMethods = listOf(
"net_version", "net_version",

View File

@@ -57,7 +57,7 @@ class EthereumCallSelector(
return blockTagSelector(params, 1, head) return blockTagSelector(params, 1, head)
} else if (method == "eth_getStorageAt") { } else if (method == "eth_getStorageAt") {
return blockTagSelector(params, 2, head) return blockTagSelector(params, 2, head)
} else if (method == "eth_getFilterChanges" || method == "eth_uninstallFilter") { } else if (method in DefaultEthereumMethods.withFilterIdMethods) {
return sameUpstreamMatcher(params) return sameUpstreamMatcher(params)
} }
return Mono.empty() return Mono.empty()

View File

@@ -17,23 +17,17 @@
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.ChainFees import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.EmptyHead import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.MergedHead
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstream import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstream
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import org.springframework.util.ConcurrentReferenceHashMap import org.springframework.util.ConcurrentReferenceHashMap
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
@@ -85,7 +79,7 @@ open class EthereumMultistream(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return super.isRunning() || reader.isRunning return super.isRunning() || reader.isRunning()
} }
override fun getReader(): EthereumReader { override fun getReader(): EthereumReader {

View File

@@ -30,6 +30,7 @@ import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.reader.RekeyingReader import io.emeraldpay.dshackle.reader.RekeyingReader
import io.emeraldpay.dshackle.reader.RpcReader import io.emeraldpay.dshackle.reader.RpcReader
import io.emeraldpay.dshackle.reader.TransformingReader import io.emeraldpay.dshackle.reader.TransformingReader
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.etherjar.domain.Address import io.emeraldpay.etherjar.domain.Address
@@ -41,7 +42,6 @@ import io.emeraldpay.etherjar.rpc.json.TransactionJson
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
import org.apache.commons.collections4.Factory import org.apache.commons.collections4.Factory
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import java.util.function.Function import java.util.function.Function
/** /**
@@ -174,7 +174,7 @@ open class EthereumReader(
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
// TODO should be always running? // TODO should be always running?
return up.isRunning return true // up.isRunning
} }
override fun start() { override fun start() {

View File

@@ -18,11 +18,11 @@ package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.BlockValidator import io.emeraldpay.dshackle.upstream.BlockValidator
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import org.springframework.scheduling.concurrent.CustomizableThreadFactory import org.springframework.scheduling.concurrent.CustomizableThreadFactory
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Flux import reactor.core.publisher.Flux

View File

@@ -16,6 +16,7 @@
*/ */
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
@@ -29,7 +30,6 @@ import io.emeraldpay.dshackle.upstream.ethereum.connectors.ConnectorFactory
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
@@ -80,7 +80,7 @@ open class EthereumRpcUpstream(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return connector.isRunning return connector.isRunning()
} }
override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> { override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> {

View File

@@ -16,11 +16,11 @@
*/ */
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.AuthConfig import io.emeraldpay.dshackle.config.AuthConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.rpcclient.RpcMetrics import io.emeraldpay.dshackle.upstream.rpcclient.RpcMetrics
import io.emeraldpay.grpc.Chain
import io.micrometer.core.instrument.Counter import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.Metrics import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Tag

View File

@@ -17,10 +17,10 @@
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.upstream.BlockValidator import io.emeraldpay.dshackle.upstream.BlockValidator
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcWsClient import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcWsClient
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Flux import reactor.core.publisher.Flux

View File

@@ -1,8 +1,8 @@
package io.emeraldpay.dshackle.upstream.ethereum.connectors package io.emeraldpay.dshackle.upstream.ethereum.connectors
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstreamValidator import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstreamValidator
import io.emeraldpay.grpc.Chain
interface ConnectorFactory { interface ConnectorFactory {
fun create(upstream: DefaultUpstream, validator: EthereumUpstreamValidator, chain: Chain): EthereumConnector fun create(upstream: DefaultUpstream, validator: EthereumUpstreamValidator, chain: Chain): EthereumConnector

View File

@@ -2,9 +2,9 @@ package io.emeraldpay.dshackle.upstream.ethereum.connectors
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import org.springframework.context.Lifecycle
interface EthereumConnector : Lifecycle { interface EthereumConnector : Lifecycle {
fun getHead(): Head fun getHead(): Head

View File

@@ -1,12 +1,12 @@
package io.emeraldpay.dshackle.upstream.ethereum.connectors package io.emeraldpay.dshackle.upstream.ethereum.connectors
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.upstream.BlockValidator import io.emeraldpay.dshackle.upstream.BlockValidator
import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.HttpFactory import io.emeraldpay.dshackle.upstream.HttpFactory
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstreamValidator import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstreamValidator
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWsFactory import io.emeraldpay.dshackle.upstream.ethereum.EthereumWsFactory
import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
open class EthereumConnectorFactory( open class EthereumConnectorFactory(

View File

@@ -5,6 +5,7 @@ import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.BlockValidator import io.emeraldpay.dshackle.upstream.BlockValidator
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.MergedHead import io.emeraldpay.dshackle.upstream.MergedHead
import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcHead import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcHead
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWsFactory import io.emeraldpay.dshackle.upstream.ethereum.EthereumWsFactory
@@ -14,7 +15,6 @@ import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import java.time.Duration import java.time.Duration
class EthereumRpcConnector( class EthereumRpcConnector(
@@ -61,7 +61,7 @@ class EthereumRpcConnector(
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
if (head is Lifecycle) { if (head is Lifecycle) {
return head.isRunning return head.isRunning()
} }
return true return true
} }

View File

@@ -36,7 +36,7 @@ class EthereumWsConnector(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return head.isRunning return head.isRunning()
} }
override fun stop() { override fun stop() {

View File

@@ -17,23 +17,17 @@
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.ChainFees import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.EmptyHead import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.MergedHead
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.forkchoice.PriorityForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.PriorityForkChoice
import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstream import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstream
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import org.springframework.util.ConcurrentReferenceHashMap import org.springframework.util.ConcurrentReferenceHashMap
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
@@ -80,7 +74,7 @@ open class EthereumPosMultiStream(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return super.isRunning() || reader.isRunning return super.isRunning() || reader.isRunning()
} }
override fun getReader(): EthereumReader { override fun getReader(): EthereumReader {

View File

@@ -16,12 +16,14 @@
*/ */
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
@@ -29,9 +31,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.connectors.ConnectorFactory
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
open class EthereumPosRpcUpstream( open class EthereumPosRpcUpstream(
@@ -80,7 +80,7 @@ open class EthereumPosRpcUpstream(
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
return connector.isRunning return connector.isRunning()
} }
override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> { override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> {

View File

@@ -17,6 +17,7 @@ package io.emeraldpay.dshackle.upstream.grpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.ReactorBlockchainGrpc import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Defaults import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
@@ -24,6 +25,7 @@ import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.Capability import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
@@ -34,10 +36,8 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcGrpcClient
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.rpc.RpcException import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.grpc.Chain
import org.reactivestreams.Publisher import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.math.BigInteger import java.math.BigInteger

View File

@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.upstream.grpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.ReactorBlockchainGrpc import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Defaults import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
@@ -26,6 +27,7 @@ import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.Capability import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
@@ -37,10 +39,8 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.domain.BlockHash import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.RpcException import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.grpc.Chain
import org.reactivestreams.Publisher import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.math.BigInteger import java.math.BigInteger

View File

@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.upstream.grpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.ReactorBlockchainGrpc import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Defaults import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
@@ -26,6 +27,7 @@ import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.Capability import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
@@ -37,10 +39,8 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.domain.BlockHash import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.RpcException import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.grpc.Chain
import org.reactivestreams.Publisher import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.math.BigInteger import java.math.BigInteger

View File

@@ -18,16 +18,16 @@ package io.emeraldpay.dshackle.upstream.grpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.api.proto.ReactorBlockchainGrpc import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Defaults import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.upstream.AbstractHead import io.emeraldpay.dshackle.upstream.AbstractHead
import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice
import io.emeraldpay.grpc.Chain
import org.reactivestreams.Publisher import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable import reactor.core.Disposable
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
@@ -60,7 +60,7 @@ class GrpcHead(
* Initiate a new head subscription with connection to the remote * Initiate a new head subscription with connection to the remote
*/ */
private fun internalStart(remote: ReactorBlockchainGrpc.ReactorBlockchainStub) { private fun internalStart(remote: ReactorBlockchainGrpc.ReactorBlockchainStub) {
if (this.isRunning) { if (this.isRunning()) {
stop() stop()
} }
log.debug("Start Head subscription to ${parent.getId()}") log.debug("Start Head subscription to ${parent.getId()}")

Some files were not shown because too many files have changed in this diff Show More