emeraldpay / dshackle

Fault Tolerant Load Balancer for Ethereum and Bitcoin APIs
Apache License 2.0
307 stars 65 forks source link

Can't use custom container after adding BSC Chain to Dshackle #222

Open tibz-starton opened 1 year ago

tibz-starton commented 1 year ago

Hey !

Hope you're fine !

Here is the situation

I forked 3 repositories of EmeraldPay to try to add BSC Chain to Dshackle and some other chains after.

Here are the 3 repositories with my last versions :

emerald-grpc

So, I firstly added the BSC Chain in the emerald-grpc (starton) repository.

emerald-java-client

Then, I updated the emerald-java-client (starton) repository to add the BSC Chain too.

I also edited the .gitmodules file to fetch the newly forked emerald-grpc (starton) repository :

[submodule "emerald-grpc"]
    path = emerald-grpc
    url = https://github.com/starton-io/emerald-grpc.git
    branch = master

Because I renamed the repository, I modified the build.gradle file with :

sourceSets {
    main {
        proto {
            srcDir 'emerald-grpc/proto'
        }
    }
}

And I built the Emerald Java Client with :

gradle build

For this part, all is working, the emerald-grpc (starton) repository is well fetched and the build is 100% done (with 100 warning oops).

dshackle

Here is the sad part. As all seems good for the two previous repositories, I now try to fetch the emerald-java-client (starton) repository from the dshackle (starton) one. As I didn't create a package on the Maven repository, I decided to use the JitPack plugin to easily get it. Here is the build.gradle snippet code that I added:

repositories {
    maven { url "https://jitpack.io" }
}

dependencies {
    implementation 'com.github.starton-io:emerald-java-client:master'
}

-- SOURCE: https://stackoverflow.com/questions/18748436/is-it-possible-to-declare-git-repository-as-dependency-in-android-gradle

Here is my dshackle.yaml file :

version: v1
port: 2449
tls:
  enabled: false

proxy:
  host: 0.0.0.0
  port: 8545
  routes:
    - id: eth
      blockchain: ethereum
    - id: bsc
      blockchain: bsc

cluster:
  upstreams:
    - id: infura-eth
      chain: ethereum
      connection:
        ethereum:
          rpc:
            url: "https://mainnet.infura.io/v3/${INFURA_USER}"
          ws:
            url: "wss://mainnet.infura.io/ws/v3/${INFURA_USER}"
    - id: infura-goerli
      chain: goerli
      connection:
        ethereum:
          rpc:
            url: "https://goerli.infura.io/v3/${INFURA_USER}"
    - id: bsc
      chain: bsc
      connection:
        ethereum:
          rpc:
            url: "https://bsc-dataseed.binance.org"

(NOTE: My INFURA_USER env var is well exported)

Then, I want to build Dshackle with :

gradle assemble

(I can't use gradle build because it will test the Gradle project and some tests doesn't pass and thus, the build fails...)

The build success at 100%, I now try to build a Docker Image :

gradle jibDockerBuild

All is good and I finally try to use my newly created image :

docker run -p 2449:2449 -p 8545:8545 -v $(pwd):/etc/dshackle -e "INFURA_USER=$INFURA_USER" 2bbbd761e3c9

And from this point, I have the following error:

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
                                _     _     __ _     _                _    _
                               | |   | |   / /| |   | |              | |  | |
   ___ _ __ ___   ___ _ __ __ _| | __| |  / /_| |___| |__   __ _  ___| | _| | ___
  / _ \ '_ ` _ \ / _ \ '__/ _` | |/ _` | / / _` / __| '_ \ / _` |/ __| |/ / |/ _ \
 |  __/ | | | | |  __/ | | (_| | | (_| |/ / (_| \__ \ | | | (_| | (__|   <| |  __/
  \___|_| |_| |_|\___|_|  \__,_|_|\__,_/_/ \__,_|___/_| |_|\__,_|\___|_|\_\_|\___|
   Emerald Dshackle - Fault Tolerant Load Balancer for Blockchain API
   https://github.com/emeraldpay/dshackle
   v0.14.0-SNAPSHOT built from 22b7b8f142 on 2023-01-06T18:39:38 UTC

2023-06-01 18:40:31.814 | INFO  |            StarterKt | Starting StarterKt using Java 13.0.2 on 5d787eb70555 with PID 1 (/app/classes started by root in /)
2023-06-01 18:40:31.833 | INFO  |            StarterKt | No active profile set, falling back to default profiles: default
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.bouncycastle.jcajce.provider.drbg.DRBG (file:/app/libs/bcprov-jdk15on-1.61.jar) to constructor sun.security.provider.Sun()
WARNING: Please consider reporting this to the maintainers of org.bouncycastle.jcajce.provider.drbg.DRBG
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2023-06-01 18:40:38.717 | INFO  |               Config | Using config: /etc/dshackle/dshackle.yaml
2023-06-01 18:40:39.989 | INFO  |      MonitoringSetup | Run Prometheus metrics on 127.0.0.1:8081/metrics
2023-06-01 18:40:41.088 | INFO  | rrentEgressLogWriter | Egress Log is disabled
2023-06-01 18:40:41.096 | INFO  |           GrpcServer | Starting gRPC Server...
2023-06-01 18:40:41.111 | INFO  |           GrpcServer | Listening Native gRPC on 127.0.0.1:2449
2023-06-01 18:40:41.489 | WARN  | igApplicationContext | Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grpcServer': Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: 'io.grpc.Deadline$Ticker io.grpc.Deadline.getSystemTicker()'
2023-06-01 18:40:41.492 | INFO  | entMultistreamHolder | Closing upstream connections...
2023-06-01 18:40:42.258 | ERROR | lureAnalysisReporter |

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    io.grpc.internal.ServerImplBuilder.<init>(ServerImplBuilder.java:88)

The following method did not exist:

    'io.grpc.Deadline$Ticker io.grpc.Deadline.getSystemTicker()'

The method's class, io.grpc.Deadline, is available from the following locations:

    jar:file:/app/libs/reactor-grpc-1.0.1.jar!/io/grpc/Deadline.class
    jar:file:/app/libs/grpc-context-1.42.1.jar!/io/grpc/Deadline.class

The class hierarchy was loaded from the following locations:

    io.grpc.Deadline: file:/app/libs/reactor-grpc-1.0.1.jar

Action:

Correct the classpath of your application so that it contains a single, compatible version of io.grpc.Deadline

Here is my configuration :

Java:        java 11.0.17 2022-10-18 LTS (openjdk@11)
Gradle:      7.6
Kotlin:      1.7.10
Groovy:      3.0.13
Ant:         Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:         17.0.5 (Homebrew 17.0.5+0)
OS:          Mac OS X 13.1 aarch64 (M1)

/!\ WARNING /!\ : I had to fix the protobuf and reactor plugins because of my Mac M1, here is the code snippets available in the build.gradle file for both emerald-java-client (starton) and dshackle (starton) repositories :

// FOR EMERALD-JAVA-CLIENT

protobuf {
    protoc {
        // if $PROTOC_PATH is set then locally installed protoc is used otherwise it is downloaded remotely
        path = System.getenv("PROTOC_PATH") ?: null
        if (osdetector.os == "osx") {
            artifact = "com.google.protobuf:protoc:${protocVersion}:osx-x86_64"
        } else {
            artifact = "com.google.protobuf:protoc:${protocVersion}"
        }
    }
    plugins {
        grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
        reactor {
            path = System.getenv("PROTOC_PATH") ?: null
            if (osdetector.os == "osx") {
                artifact = "com.salesforce.servicelibs:reactor-grpc:${reactiveGrpcVersion}:osx-x86_64"
            } else {
                artifact = "com.salesforce.servicelibs:reactor-grpc:${reactiveGrpcVersion}"
            }
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc {}
            reactor {}
        }
    }
}

and

// FOR DSHACKLE

protobuf {
    protoc {
        // if $PROTOC_PATH is set then locally installed protoc is used otherwise it is downloaded remotely
        path = System.getenv("PROTOC_PATH") ?: null
        if (osdetector.os == "osx") {
            artifact = "com.google.protobuf:protoc:3.9.0:osx-x86_64"
        } else {
            artifact = "com.google.protobuf:protoc:3.9.0"
        }
    }
    plugins {
    }
    generateProtoTasks {
    }
}

-- SOURCE: this GitHub issue comment

Do you know where could be the problem ?

Thanks :)

tibz-starton commented 1 year ago

NOTE : When I'm using the default emeraldpay/dshackle:0.13 Docker image, all is good, and when I build a custom Docker image without adding the BSC Chain and with a generic dshackle.yaml file, it works too.

I test the Ethereum providers with the following command line (and it works for a basic configuration):

curl --request POST \
  --url http://localhost:8545/eth \
  --header 'content-type: application/json' \
  --data '{"jsonrpc":"2.0", "method":"eth_getTransactionReceipt", "id":1, "params":["0x0842267f92e70526f32a0f770d4d8135b1f1fa5b79922256617d1942646a2cdd", "latest"]}'

Have a good day ! ;)

tibz-starton commented 1 year ago

UPDATE: When I'm trying to build my custom image :

gradle jibDockerBuild --warning-mode all

I have the following output :

> Configure project :
IncrementalTaskInputs has been deprecated. This is scheduled to be removed in Gradle 8.0. On method 'AbstractKotlinCompile.execute' use 'org.gradle.work.InputChanges' instead. Consult the upgrading guide for further information: https://docs.gradle.org/7.6/userguide/upgrading_version_7.html#incremental_task_inputs_deprecation

> Task :generateProto
Relying on FileTrees for ignoring empty directories when using @SkipWhenEmpty has been deprecated. This is scheduled to be removed in Gradle 8.0. Annotate the property sourceFiles with @IgnoreEmptyDirectories or remove @SkipWhenEmpty. Consult the upgrading guide for further information: https://docs.gradle.org/7.6/userguide/upgrading_version_7.html#empty_directories_file_tree

> Task :compileKotlin
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/cache/BlocksRedisCache.kt: (77, 13): Condition 'block.timestamp == null' is always 'false'
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/cache/BlocksRedisCache.kt: (77, 40): Condition 'block.hash == null' is always 'false'
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/cache/Caches.kt: (101, 15): Parameter 'tag' is never used
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfigReader.kt: (238, 69): Parameter 'defaultPort' is never used
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfigReader.kt: (282, 9): Parameter 'upstream' is never used
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/proxy/ReadRpcJson.kt: (165, 13): Variable 'seq' is never used
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/proxy/WriteRpcJson.kt: (70, 39): Unnecessary safe call on a non-null receiver of type Any
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/proxy/WriteRpcJson.kt: (72, 11): Elvis operator (?:) always returns the left operand of non-nullable type JsonRpcResponse.Id
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/proxy/WriteRpcJson.kt: (85, 37): Elvis operator (?:) always returns the left operand of non-nullable type Any
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/quorum/NonEmptyQuorum.kt: (57, 75): The corresponding parameter in the supertype 'ValueAwareQuorum' is named 'signature'. This may cause problems when calling this function with named arguments.
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt: (292, 25): Unchecked cast: NativeCall.ValidCallContext<T> to NativeCall.ValidCallContext<X>
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/DefaultUpstream.kt: (103, 13): Variable 'quorum' is never used
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinFees.kt: (38, 28): Unchecked cast: Any to List<String>
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinFees.kt: (47, 48): Unchecked cast: Any to List<Map<String, Any>>
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinFees.kt: (93, 50): Unchecked cast: Any to List<Map<String, Any>>
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidator.kt: (110, 49): Elvis operator (?:) always returns the left operand of non-nullable type Int
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumWsHead.kt: (68, 74): Unchecked cast: BlockJson<*>! to BlockJson<TransactionRefJson>
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/AggregatedPendingTxes.kt: (35, 29): Unchecked cast: HexDataComparator to kotlin.Comparator<TransactionId> /* = java.util.Comparator<TransactionId> */
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumDshackleIngressSubscription.kt: (44, 32): Unchecked cast: DshacklePendingTxesSource to SubscriptionConnect<T>
w: /Users/tibo/Documents/Starton/dshackle/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/ProduceNewHeads.kt: (45, 31): Unchecked cast: Any? to BlockJson<TransactionRefJson>

> Task :jibDockerBuild

Containerizing application to Docker daemon as emeraldpay/dshackle:snapshot, emeraldpay/dshackle:0.14.0-SNAPSHOT, emeraldpay/dshackle:t202301111040, emeraldpay/dshackle:0.14...
Base image 'openjdk:13' does not use a specific image digest - build may not be reproducible
The base image requires auth. Trying again for openjdk:13...
The credential helper (docker-credential-desktop) has nothing for server URL: registry-1.docker.io

Got output:

credentials not found in native keychain

The credential helper (docker-credential-desktop) has nothing for server URL: registry.hub.docker.com

Got output:

credentials not found in native keychain

Using credentials from Docker config (/Users/tibo/.docker/config.json) for openjdk:13
The base image reference is a manifest list, searching for architecture=amd64, os=linux
Using base image with digest: sha256:53cacd45e87d2e24e07143f73540e8aa40b31d9f52c6ee69ebffe7bd34bc8ca2

Container entrypoint set to [java, -Xms1024m, -cp, /app/resources:/app/classes:/app/libs/*, io.emeraldpay.dshackle.StarterKt]
Container program arguments set to []

Built image to Docker daemon as emeraldpay/dshackle:snapshot, emeraldpay/dshackle:0.14.0-SNAPSHOT, emeraldpay/dshackle:t202301111040, emeraldpay/dshackle:0.14
Executing tasks:
[==============================] 100.0% complete

BUILD SUCCESSFUL in 22s
8 actionable tasks: 8 executed