From e8410d76385b96aa1c389c19b0668624ad655dce Mon Sep 17 00:00:00 2001 From: Vyacheslav Date: Mon, 12 Aug 2024 14:46:16 +0300 Subject: [PATCH] detect gas limit for a node (#545) --- .../EthereumUpstreamSettingsDetector.kt | 46 +++++++++++++++++++ ...thereumUpstreamSettingsDetectorSpec.groovy | 27 ++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetector.kt index 430f70e6e..140472a81 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetector.kt @@ -11,6 +11,7 @@ import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Flux import reactor.core.publisher.Mono +import kotlin.text.toBigInteger const val ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" @@ -24,6 +25,7 @@ class EthereumUpstreamSettingsDetector( return Flux.merge( detectNodeType(), detectArchiveNode(), + detectGasLabels(), ) } @@ -43,6 +45,50 @@ class EthereumUpstreamSettingsDetector( return version } + /** + * We use this smart contract to get gas limit + * pragma solidity ^0.8.0; + * + * contract GasChecker { + * + * // Function to return the amount of gas left + * function getGasLeft() external view returns (uint256) { + * return gasleft(); + * } + * } + * + */ + private fun detectGasLabels(): Flux> { + return upstream.getIngressReader().read( + ChainRequest( + "eth_call", + ListParams( + mapOf( + "to" to "0x53Daa71B04d589429f6d3DF52db123913B818F22", + "data" to "0x51be4eaa", + ), + "latest", + mapOf( + "0x53Daa71B04d589429f6d3DF52db123913B818F22" to mapOf( + "code" to "0x6080604052348015600e575f80fd5b50600436106026575f3560e01c806351be4eaa14602a575b5f80fd5b60306044565b604051603b91906061565b60405180910390f35b5f5a905090565b5f819050919050565b605b81604b565b82525050565b5f60208201905060725f8301846054565b9291505056fea2646970667358221220a85b088da3911ea743505594ac7cfdd1a65865de64499ee1f3c6bd9cdad4552364736f6c634300081a0033", + ), + ), + ), + ), + ).flatMap { + it.requireResult() + }.flatMapMany { + val gaslimit = String(it).drop(3).dropLast(1).toBigInteger(16) + (21180).toBigInteger() + val labels = mutableListOf(Pair("gas-limit", gaslimit.toString(10))) + if (gaslimit >= (600_000_000).toBigInteger()) { + labels.add(Pair("extra_gas_limit", "600000000")) + } + Flux.fromIterable(labels) + }.onErrorResume { + Flux.empty() + } + } + private fun detectArchiveNode(): Mono> { if (upstream.getLabels().firstOrNull { it.getOrDefault("archive", "") == "false" } != null) { return Mono.empty() diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetectorSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetectorSpec.groovy index 7353aed1b..67c93bddf 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetectorSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamSettingsDetectorSpec.groovy @@ -25,6 +25,16 @@ class EthereumUpstreamSettingsDetectorSpec extends Specification { answer("eth_blockNumber", [], "0x10df3e5") answer("eth_getBalance", ["0x0000000000000000000000000000000000000000", "0x10dccd5"], "") answer("eth_getBalance", ["0x0000000000000000000000000000000000000000", "0x2710"], "") + answer("eth_call", [[ + "to": "0x53Daa71B04d589429f6d3DF52db123913B818F22", + "data": "0x51be4eaa", + ], + "latest", + [ + "0x53Daa71B04d589429f6d3DF52db123913B818F22": [ + "code": "0x6080604052348015600e575f80fd5b50600436106026575f3560e01c806351be4eaa14602a575b5f80fd5b60306044565b604051603b91906061565b60405180910390f35b5f5a905090565b5f819050919050565b605b81604b565b82525050565b5f60208201905060725f8301846054565b9291505056fea2646970667358221220a85b088da3911ea743505594ac7cfdd1a65865de64499ee1f3c6bd9cdad4552364736f6c634300081a0033", + ], + ]], "0x2fa9dc4") } ) def detector = new EthereumUpstreamSettingsDetector(up, Chain.ETHEREUM__MAINNET) @@ -36,7 +46,8 @@ class EthereumUpstreamSettingsDetectorSpec extends Specification { .expectNext( new Pair("client_type", clientType), new Pair("client_version", version), - new Pair("archive", "true") + new Pair("archive", "true"), + new Pair("gas-limit", "50000000") ) .expectComplete() .verify(Duration.ofSeconds(1)) @@ -76,7 +87,7 @@ class EthereumUpstreamSettingsDetectorSpec extends Specification { def "Only default label"() { setup: def up = Mock(DefaultUpstream) { - 4 * getIngressReader() >> Mock(Reader) { + 5 * getIngressReader() >> Mock(Reader) { 1 * read(new ChainRequest("web3_clientVersion", new ListParams())) >> Mono.just(new ChainResponse('no/v1.19.3+e8ac1da4/linux-x64/dotnet7.0.8'.getBytes(), null)) 1 * read(new ChainRequest("eth_blockNumber", new ListParams())) >> @@ -85,6 +96,18 @@ class EthereumUpstreamSettingsDetectorSpec extends Specification { Mono.error(new RuntimeException()) 1 * read(new ChainRequest("eth_getBalance", new ListParams(["0x0000000000000000000000000000000000000000", "0x2710"]))) >> Mono.just(new ChainResponse("".getBytes(), null)) + 1 * read(new ChainRequest("eth_call", new ListParams([ + "to": "0x53Daa71B04d589429f6d3DF52db123913B818F22", + "data": "0x51be4eaa", + ], + "latest", + [ + "0x53Daa71B04d589429f6d3DF52db123913B818F22": [ + "code": "0x6080604052348015600e575f80fd5b50600436106026575f3560e01c806351be4eaa14602a575b5f80fd5b60306044565b604051603b91906061565b60405180910390f35b5f5a905090565b5f819050919050565b605b81604b565b82525050565b5f60208201905060725f8301846054565b9291505056fea2646970667358221220a85b088da3911ea743505594ac7cfdd1a65865de64499ee1f3c6bd9cdad4552364736f6c634300081a0033", + ], + ], + ))) >> + Mono.just(new ChainResponse("".getBytes(), null)) } getLabels() >> [] }