diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/connectors/GenericRpcConnector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/connectors/GenericRpcConnector.kt index e73f0b432..30001a93d 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/connectors/GenericRpcConnector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/connectors/GenericRpcConnector.kt @@ -62,7 +62,15 @@ class GenericRpcConnector( head = when (connectorType) { RPC_ONLY -> { log.warn("Setting up connector for $id upstream with RPC-only access, less effective than WS+RPC") - GenericRpcHead(getIngressReader(), forkChoice, id, blockValidator, headScheduler, chainSpecific) + GenericRpcHead( + getIngressReader(), + forkChoice, + id, + blockValidator, + headScheduler, + chainSpecific, + expectedBlockTime.coerceAtLeast(Duration.ofSeconds(1)), + ) } WS_ONLY -> { diff --git a/src/test/kotlin/io/emeraldpay/dshackle/upstream/generic/connectors/GenericConnectorFactoryCreatorTest.kt b/src/test/kotlin/io/emeraldpay/dshackle/upstream/generic/connectors/GenericConnectorFactoryCreatorTest.kt new file mode 100644 index 000000000..25225d420 --- /dev/null +++ b/src/test/kotlin/io/emeraldpay/dshackle/upstream/generic/connectors/GenericConnectorFactoryCreatorTest.kt @@ -0,0 +1,71 @@ +package io.emeraldpay.dshackle.upstream.generic.connectors + +import io.emeraldpay.dshackle.Chain +import io.emeraldpay.dshackle.FileResolver +import io.emeraldpay.dshackle.config.ChainsConfig +import io.emeraldpay.dshackle.config.ChainsConfigReader +import io.emeraldpay.dshackle.config.UpstreamsConfig +import io.emeraldpay.dshackle.foundation.ChainOptionsReader +import io.emeraldpay.dshackle.startup.configure.GenericConnectorFactoryCreator +import io.emeraldpay.dshackle.upstream.BlockValidator +import io.emeraldpay.dshackle.upstream.DefaultUpstream +import io.emeraldpay.dshackle.upstream.forkchoice.AlwaysForkChoice +import io.emeraldpay.dshackle.upstream.generic.GenericRpcHead +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource +import org.mockito.Mockito.mockConstruction +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import reactor.core.scheduler.Schedulers.immediate +import java.io.File +import java.net.URI +import java.time.Duration + +class GenericConnectorFactoryCreatorTest { + + @ParameterizedTest + @MethodSource("data") + fun `rpc head poll interval must equal to expected-block-time`( + expectedBlockTime: Duration, + config: ChainsConfig.ChainConfig, + ) { + val factory = GenericConnectorFactoryCreator( + FileResolver(File("")), + immediate(), + immediate(), + immediate(), + immediate(), + ) + var args: List<*>? = null + + mockConstruction(GenericRpcHead::class.java) { _, ctx -> args = ctx.arguments() } + .use { + factory.createConnectorFactoryCreator( + "id", + UpstreamsConfig.RpcConnection( + UpstreamsConfig.HttpEndpoint(URI("http://localhost")), + ), + Chain.ETHEREUM__MAINNET, + AlwaysForkChoice(), + BlockValidator.ALWAYS_VALID, + config, + )?.create(mock { on { getId() } doReturn "id" }, Chain.ETHEREUM__MAINNET) + + assertEquals(expectedBlockTime, args?.get(6)) + } + } + + companion object { + private val chainsConfigReader = ChainsConfigReader(ChainOptionsReader()) + + @JvmStatic + fun data(): List = chainsConfigReader.read(null) + .flatMap { cfg -> + cfg.shortNames.map { + Arguments.of(cfg.expectedBlockTime.coerceAtLeast(Duration.ofSeconds(1)), cfg) + } + } + } +}