From fc9f7e0fa60bfe21b5488f2c18ea689995057d48 Mon Sep 17 00:00:00 2001 From: Maksim Fomenkov Date: Fri, 18 Nov 2022 18:40:57 +0300 Subject: [PATCH 1/3] support network specific methods --- .../io/emeraldpay/dshackle/rpc/NativeCall.kt | 12 ++- .../upstream/calls/DefaultEthereumMethods.kt | 73 ++++++++++++++++++- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index 956b187d..d8d02f95 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -255,7 +255,14 @@ open class NativeCall( } private fun getRequestDecorator(method: String): RequestDecorator = - if (method == "eth_getFilterChanges" || method == "eth_uninstallFilter") + if (method in listOf( + "eth_getFilterChanges", + "eth_uninstallFilter", + "shh_getFilterChanges", + "shh_uninstallFilter", + "shh_getMessages" + ) + ) GetFilterUpdatesDecorator() else NoneRequestDecorator() @@ -384,7 +391,8 @@ open class NativeCall( val createFilterMethods = listOf( "eth_newFilter", "eth_newBlockFilter", - "eth_newPendingTransactionFilter" + "eth_newPendingTransactionFilter", + "shh_newFilter", ) } override fun processResult(result: QuorumRpcReader.Result): ByteArray { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt index 6f78cfe0..10a8e4b4 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt @@ -78,8 +78,6 @@ class DefaultEthereumMethods( "eth_uninstallFilter" ) - private val allowedMethods = anyResponseMethods + firstValueMethods + specialMethods + headVerifiedMethods + filterMethods - private val hardcodedMethods = listOf( "net_version", "net_peerCount", @@ -94,9 +92,29 @@ class DefaultEthereumMethods( "eth_chainId" ) + private val bscFilterMethods = listOf( + "shh_newFilter", + "shh_uninstallFilter", + "shh_getFilterChanges", + "shh_getMessages", + ) + + private val allowedMethods: List + + init { + allowedMethods = anyResponseMethods + + firstValueMethods + + specialMethods + + headVerifiedMethods + + filterMethods - + chainUnsupportedMethods(chain) + + getChainSpecificMethods(chain) + } + + override fun getQuorumFor(method: String): CallQuorum { return when { - filterMethods.contains(method) -> AlwaysQuorum() + filterMethods.contains(method) -> NotLaggingQuorum(1) hardcodedMethods.contains(method) -> AlwaysQuorum() firstValueMethods.contains(method) -> AlwaysQuorum() anyResponseMethods.contains(method) -> NotLaggingQuorum(4) @@ -110,10 +128,59 @@ class DefaultEthereumMethods( else -> AlwaysQuorum() } } + + getChainSpecificMethods(chain).contains(method) -> { + if (bscFilterMethods.contains(method)) { + NotLaggingQuorum(1) + } else { + when (method) { + "eth_getBlockRange" -> NotLaggingQuorum(1) + "bor_getAuthor" -> NotLaggingQuorum(0) + "bor_getCurrentValidators" -> NotLaggingQuorum(0) + "bor_getCurrentProposer" -> NotLaggingQuorum(0) + "bor_getRootHash" -> NotLaggingQuorum(1) + "eth_getRootHash" -> NotLaggingQuorum(1) + "shh_hasIdentity" -> NotLaggingQuorum(1) + else -> AlwaysQuorum() + } + } + } else -> AlwaysQuorum() } } + private fun getChainSpecificMethods(chain: Chain): List { + return when (chain) { + Chain.OPTIMISM -> listOf( + "eth_getBlockRange", + "rollup_gasPrices" + ) + Chain.POLYGON -> listOf( + "bor_getAuthor", + "bor_getCurrentValidators", + "bor_getCurrentProposer", + "bor_getRootHash", + "bor_getSignersAtHash", + "eth_getRootHash" + ) + Chain.BSC -> bscFilterMethods + listOf( + "shh_post", + "shh_version", + "shh_newIdentity", + "shh_hasIdentity", + "shh_addToGroup", + ) + else -> emptyList() + } + } + + private fun chainUnsupportedMethods(chain: Chain): Set { + if (chain == Chain.OPTIMISM) { + return setOf("eth_getAccounts", "eth_sendTransaction") + } + return emptySet() + } + override fun isCallable(method: String): Boolean { return allowedMethods.contains(method) } From b26dd989f55fc7924c6138846bd0355709e4e20d Mon Sep 17 00:00:00 2001 From: Maksim Fomenkov Date: Wed, 23 Nov 2022 06:02:21 +0400 Subject: [PATCH 2/3] fix specific methods --- .../io/emeraldpay/dshackle/rpc/NativeCall.kt | 4 -- .../upstream/calls/DefaultEthereumMethods.kt | 37 +++++-------------- .../calls/DefaultEthereumMethodsSpec.groovy | 25 +++++++++++++ 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index d8d02f95..3126254b 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -258,9 +258,6 @@ open class NativeCall( if (method in listOf( "eth_getFilterChanges", "eth_uninstallFilter", - "shh_getFilterChanges", - "shh_uninstallFilter", - "shh_getMessages" ) ) GetFilterUpdatesDecorator() @@ -392,7 +389,6 @@ open class NativeCall( "eth_newFilter", "eth_newBlockFilter", "eth_newPendingTransactionFilter", - "shh_newFilter", ) } override fun processResult(result: QuorumRpcReader.Result): ByteArray { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt index 10a8e4b4..b65053b4 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt @@ -92,13 +92,6 @@ class DefaultEthereumMethods( "eth_chainId" ) - private val bscFilterMethods = listOf( - "shh_newFilter", - "shh_uninstallFilter", - "shh_getFilterChanges", - "shh_getMessages", - ) - private val allowedMethods: List init { @@ -130,19 +123,14 @@ class DefaultEthereumMethods( } getChainSpecificMethods(chain).contains(method) -> { - if (bscFilterMethods.contains(method)) { - NotLaggingQuorum(1) - } else { - when (method) { - "eth_getBlockRange" -> NotLaggingQuorum(1) - "bor_getAuthor" -> NotLaggingQuorum(0) - "bor_getCurrentValidators" -> NotLaggingQuorum(0) - "bor_getCurrentProposer" -> NotLaggingQuorum(0) - "bor_getRootHash" -> NotLaggingQuorum(1) - "eth_getRootHash" -> NotLaggingQuorum(1) - "shh_hasIdentity" -> NotLaggingQuorum(1) - else -> AlwaysQuorum() - } + when (method) { + "eth_getBlockRange" -> NotLaggingQuorum(1) + "bor_getAuthor" -> NotLaggingQuorum(0) + "bor_getCurrentValidators" -> NotLaggingQuorum(0) + "bor_getCurrentProposer" -> NotLaggingQuorum(0) + "bor_getRootHash" -> NotLaggingQuorum(1) + "eth_getRootHash" -> NotLaggingQuorum(1) + else -> AlwaysQuorum() } } else -> AlwaysQuorum() @@ -163,20 +151,13 @@ class DefaultEthereumMethods( "bor_getSignersAtHash", "eth_getRootHash" ) - Chain.BSC -> bscFilterMethods + listOf( - "shh_post", - "shh_version", - "shh_newIdentity", - "shh_hasIdentity", - "shh_addToGroup", - ) else -> emptyList() } } private fun chainUnsupportedMethods(chain: Chain): Set { if (chain == Chain.OPTIMISM) { - return setOf("eth_getAccounts", "eth_sendTransaction") + return setOf("eth_getAccounts") } return emptySet() } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy index e58d3baf..2a321e88 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy @@ -44,4 +44,29 @@ class DefaultEthereumMethodsSpec extends Specification { Chain.TESTNET_RINKEBY | '"0x4"' Chain.TESTNET_ROPSTEN | '"0x3"' } + + def "Optimism chain unsupported methods"() { + setup: + def methods = new DefaultEthereumMethods(Chain.OPTIMISM) + when: + def acc = methods.isAvailable("eth_getAccounts") + def trans = methods.isAvailable("eth_sendTransaction") + then: + !acc + !trans + } + + def "Has supported specific methods"() { + expect: + new DefaultEthereumMethods(chain).getSupportedMethods().containsAll(methods) + where: + chain | methods + Chain.POLYGON | ["bor_getAuthor", + "bor_getCurrentValidators", + "bor_getCurrentProposer", + "bor_getRootHash", + "bor_getSignersAtHash", + "eth_getRootHash"] + Chain.OPTIMISM | ["eth_getBlockRange", "rollup_gasPrices"] + } } From 6ba1885d839b9b240999d819f8c1f20ce11dfcd1 Mon Sep 17 00:00:00 2001 From: Maksim Fomenkov Date: Wed, 23 Nov 2022 19:10:45 +0400 Subject: [PATCH 3/3] fix code style --- .../upstream/calls/DefaultEthereumMethods.kt | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt index b65053b4..a08d5b57 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt @@ -96,15 +96,14 @@ class DefaultEthereumMethods( init { allowedMethods = anyResponseMethods + - firstValueMethods + - specialMethods + - headVerifiedMethods + - filterMethods - - chainUnsupportedMethods(chain) + - getChainSpecificMethods(chain) + firstValueMethods + + specialMethods + + headVerifiedMethods + + filterMethods - + chainUnsupportedMethods(chain) + + getChainSpecificMethods(chain) } - override fun getQuorumFor(method: String): CallQuorum { return when { filterMethods.contains(method) -> NotLaggingQuorum(1) @@ -179,86 +178,113 @@ class DefaultEthereumMethods( Chain.ETHEREUM == chain -> { "\"1\"" } + Chain.ETHEREUM_CLASSIC == chain -> { "\"1\"" } + Chain.POLYGON == chain -> { "\"137\"" } + Chain.TESTNET_MORDEN == chain -> { "\"2\"" } + Chain.TESTNET_ROPSTEN == chain -> { "\"3\"" } + Chain.TESTNET_RINKEBY == chain -> { "\"4\"" } + Chain.TESTNET_KOVAN == chain -> { "\"42\"" } + Chain.TESTNET_GOERLI == chain -> { "\"5\"" } + else -> throw RpcException(-32602, "Invalid chain") } } + "eth_chainId" -> { when { Chain.ETHEREUM == chain -> { "\"0x1\"" } + Chain.POLYGON == chain -> { "\"0x89\"" } + Chain.TESTNET_ROPSTEN == chain -> { "\"0x3\"" } + Chain.TESTNET_RINKEBY == chain -> { "\"0x4\"" } + Chain.ETHEREUM_CLASSIC == chain -> { "\"0x3d\"" } + Chain.TESTNET_MORDEN == chain -> { "\"0x3c\"" } + Chain.TESTNET_KOVAN == chain -> { "\"0x2a\"" } + Chain.TESTNET_GOERLI == chain -> { "\"0x5\"" } + else -> throw RpcException(-32602, "Invalid chain") } } + "net_peerCount" -> { "\"0x2a\"" } + "net_listening" -> { "true" } + "web3_clientVersion" -> { version } + "eth_protocolVersion" -> { "\"0x3f\"" } + "eth_syncing" -> { "false" } + "eth_coinbase" -> { "\"0x0000000000000000000000000000000000000000\"" } + "eth_mining" -> { "false" } + "eth_hashrate" -> { "\"0x0\"" } + "eth_accounts" -> { "[]" } + else -> throw RpcException(-32601, "Method not found") } return json.toByteArray()