Merge pull request #79 from p2p-org/configure_method_groups

configure method groups
This commit is contained in:
MaxFomenkov
2022-12-12 17:00:57 +03:00
committed by GitHub
18 changed files with 275 additions and 32 deletions

View File

@@ -410,9 +410,28 @@ class UpstreamsConfigReaderSpec extends Specification {
then:
act != null
act.upstreams.size() == 2
act.upstreams[0].nodeId == 1
act.upstreams[0].id == "has_node_id"
act.upstreams[1].nodeId == null
act.upstreams[1].id == "has_no_node_id"
with(act.upstreams.get(0)) {
nodeId == 1
id == "has_node_id"
}
with(act.upstreams.get(1)) {
nodeId == null
id == "has_no_node_id"
}
}
def "Parse method groups"() {
setup:
def config = this.class.getClassLoader().getResourceAsStream("upstreams-method-groups.yaml")
when:
def act = reader.read(config)
then:
act != null
act.upstreams.size() == 1
with(act.upstreams.get(0)) {
id == "enable_filter_methods"
methodGroups.enabled.first() == "filter"
methodGroups.disabled.first() == "trace"
}
}
}

View File

@@ -359,7 +359,7 @@ class NativeCallSpec extends Specification {
setup:
def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
["foo_bar"] as Set, [] as Set
["foo_bar"] as Set, [] as Set, [] as Set, [] as Set
)
methods.setQuorum("foo_bar", "not_lagging")
def head = Mock(Head) {
@@ -400,7 +400,7 @@ class NativeCallSpec extends Specification {
setup:
def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
["eth_newFilter"] as Set, [] as Set
["eth_newFilter"] as Set, [] as Set, [] as Set, [] as Set
)
methods.setQuorum("eth_newFilter", "always")
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM, TestingCommons.upstream())
@@ -431,9 +431,8 @@ class NativeCallSpec extends Specification {
setup:
def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
["eth_getFilterChanges"] as Set, [] as Set
["eth_getFilterChanges"] as Set, [] as Set, [] as Set, [] as Set
)
methods.setQuorum("eth_getFilterChanges", "always")
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM, TestingCommons.upstream())
multistream.customMethods = methods
multistream.customHead = Mock(Head)
@@ -462,9 +461,8 @@ class NativeCallSpec extends Specification {
setup:
def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
["eth_uninstallFilter"] as Set, [] as Set
["eth_uninstallFilter"] as Set, [] as Set, [] as Set, [] as Set
)
methods.setQuorum("eth_uninstallFilter", "always")
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM, TestingCommons.upstream())
multistream.customMethods = methods
multistream.customHead = Mock(Head)
@@ -558,14 +556,24 @@ class NativeCallSpec extends Specification {
def "Decorate eth_newFilter result"() {
setup:
def quorum = new AlwaysQuorum()
def nativeCall = nativeCall()
def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
[] as Set, [] as Set, ["filter"] as Set, [] as Set
)
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM, TestingCommons.upstream(
TestingCommons.api(), methods
))
multistream.customHead = Mock(Head)
def multistreamHolder = Mock(MultistreamHolder) {
_ * it.observeChains() >> Flux.empty()
}
def nativeCall = nativeCall(multistreamHolder)
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
1 * create(_, _, _) >> Mock(Reader) {
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList((byte)255)))
}
}
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum,
new NativeCall.ParsedCallDetails("eth_getFilterChanges", []),
new NativeCall.WithFilterIdDecorator(), new NativeCall.CreateFilterDecorator(), null)
@@ -580,14 +588,24 @@ class NativeCallSpec extends Specification {
def "Decorate eth_newFilter result with short nodeId"() {
setup:
def quorum = new AlwaysQuorum()
def nativeCall = nativeCall()
def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
[] as Set, [] as Set, ["filter"] as Set, [] as Set
)
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM, TestingCommons.upstream(
TestingCommons.api(), methods
))
multistream.customHead = Mock(Head)
def multistreamHolder = Mock(MultistreamHolder) {
_ * it.observeChains() >> Flux.empty()
}
def nativeCall = nativeCall(multistreamHolder)
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
1 * create(_, _, _) >> Mock(Reader) {
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList((byte)1)))
}
}
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum,
new NativeCall.ParsedCallDetails("eth_getFilterChanges", []),
new NativeCall.WithFilterIdDecorator(), new NativeCall.CreateFilterDecorator(), null)

View File

@@ -104,4 +104,26 @@ class ConfiguredUpstreamsSpec extends Specification {
h4 == (byte)8
h5 == (byte)-128
}
def "Supporting method groups"() {
setup:
def callTargetsHolder = new CallTargetsHolder()
def configurer = new ConfiguredUpstreams(
Stub(FileResolver),
Stub(UpstreamsConfig),
callTargetsHolder,
Mock(ApplicationEventPublisher)
)
def methodsGroup = new UpstreamsConfig.MethodGroups(
["filter"] as Set,
[] as Set
)
def upstream = new UpstreamsConfig.Upstream()
upstream.methodGroups = methodsGroup
when:
def act = configurer.buildMethods(upstream, Chain.ETHEREUM)
then:
act instanceof ManagedCallMethods
act.supportedMethods.findAll {it.containsIgnoreCase("filter")}.size() == 6
}
}

View File

@@ -26,6 +26,7 @@ import io.emeraldpay.dshackle.reader.EmptyReader
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.CallTargetsHolder
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
@@ -74,6 +75,10 @@ class TestingCommons {
return new EthereumPosRpcUpstreamMock(Chain.ETHEREUM, api, new DirectCallMethods(methods))
}
static EthereumPosRpcUpstreamMock upstream(Reader<JsonRpcRequest, JsonRpcResponse> api, CallMethods callMethods) {
return new EthereumPosRpcUpstreamMock(Chain.ETHEREUM, api, callMethods)
}
static Multistream multistream(Reader<JsonRpcRequest, JsonRpcResponse> api) {
return multistream(upstream(api))
}

View File

@@ -69,4 +69,22 @@ class DefaultEthereumMethodsSpec extends Specification {
"eth_getRootHash"]
Chain.OPTIMISM | ["rollup_gasPrices"]
}
def "Has no filter methods by default"() {
setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM)
when:
def act = methods.getSupportedMethods().findAll { it.containsIgnoreCase("filter") }
then:
act.isEmpty()
}
def "Has no trace methods by default"() {
setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM)
when:
def act = methods.getSupportedMethods().findAll { it.containsIgnoreCase("trace") }
then:
act.isEmpty()
}
}

View File

@@ -34,6 +34,8 @@ class ManagedCallMethodsSpec extends Specification {
def managed = new ManagedCallMethods(
new DirectCallMethods(["eth_test2", "foo_bar"] as Set),
["eth_test"] as Set,
[] as Set,
[] as Set,
[] as Set
)
when:
@@ -47,6 +49,8 @@ class ManagedCallMethodsSpec extends Specification {
def managed = new ManagedCallMethods(
new DirectCallMethods(["eth_test2"] as Set),
["eth_test"] as Set,
[] as Set,
[] as Set,
[] as Set
)
when:
@@ -60,7 +64,9 @@ class ManagedCallMethodsSpec extends Specification {
def managed = new ManagedCallMethods(
new DirectCallMethods(["eth_test2", "foo_bar"] as Set),
["eth_test"] as Set,
["foo_bar"] as Set
["foo_bar"] as Set,
[] as Set,
[] as Set
)
when:
def act = managed.getSupportedMethods()
@@ -78,7 +84,9 @@ class ManagedCallMethodsSpec extends Specification {
def managed = new ManagedCallMethods(
delegate,
["eth_test"] as Set,
["foo_bar"] as Set
["foo_bar"] as Set,
[] as Set,
[] as Set
)
when:
def act = managed.createQuorumFor("eth_test")
@@ -92,6 +100,8 @@ class ManagedCallMethodsSpec extends Specification {
def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
["eth_test", "eth_foo", "eth_bar"] as Set,
[] as Set,
[] as Set,
[] as Set
)
managed.setQuorum("eth_test", "not_empty")
@@ -116,6 +126,8 @@ class ManagedCallMethodsSpec extends Specification {
def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
["eth_test"] as Set,
[] as Set,
[] as Set,
[] as Set
)
def parallel = Executors.newFixedThreadPool(16)
@@ -133,4 +145,79 @@ class ManagedCallMethodsSpec extends Specification {
instances.size() == 50
ids.toSet().size() == 50
}
def "Test enable method group"() {
setup:
def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
[] as Set,
[] as Set,
["filter"] as Set,
[] as Set
)
when:
def act = managed.getSupportedMethods()
then:
act.containsAll([
"eth_getFilterChanges",
"eth_getFilterLogs",
"eth_uninstallFilter",
"eth_newFilter",
"eth_newBlockFilter",
"eth_newPendingTransactionFilter"
])
}
def "Test enable method group minus one"() {
setup:
def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
[] as Set,
["eth_newPendingTransactionFilter"] as Set,
["filter"] as Set,
[] as Set
)
when:
def act = managed.getSupportedMethods()
then:
act.containsAll([
"eth_getFilterChanges",
"eth_getFilterLogs",
"eth_uninstallFilter",
"eth_newFilter",
"eth_newBlockFilter",
])
!act.contains("eth_newPendingTransactionFilter")
}
def "Test disabled group not disable enabled method"() {
setup:
def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM),
["eth_newPendingTransactionFilter"] as Set,
[] as Set,
[] as Set,
["filter"] as Set
)
when:
def act = managed.getSupportedMethods()
then:
with(act.findAll {it in [
"eth_getFilterChanges",
"eth_getFilterLogs",
"eth_uninstallFilter",
"eth_newFilter",
"eth_newBlockFilter",
"eth_newPendingTransactionFilter"
]}) {
size() == 1
first() == "eth_newPendingTransactionFilter"
}
}
}

View File

@@ -0,0 +1,13 @@
version: v1
upstreams:
- id: enable_filter_methods
chain: ethereum
method-groups:
enabled:
- filter
disabled:
- trace
connection:
ethereum:
rpc:
url: "http://localhost:8545"