From 664c0918240414dd0c31e16a8af9911eb2cf0970 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Thu, 21 Nov 2024 11:35:16 +0000 Subject: [PATCH 01/23] Replace TTFB, RESP_TIMEOUT with MAX_CONCURRENT_REQUESTS --- .../pegasys/teku/networks/test-constants.yaml | 3 +- .../spec/config/DelegatingSpecConfig.java | 15 +-- .../spec/config/NetworkingSpecConfig.java | 8 +- .../teku/spec/config/SpecConfigPhase0.java | 32 ++--- .../config/builder/SpecConfigBuilder.java | 24 ++-- .../teku/spec/config/configs/chiado.yaml | 1 + .../teku/spec/config/configs/ephemery.yaml | 1 + .../teku/spec/config/configs/gnosis.yaml | 1 + .../teku/spec/config/configs/holesky.yaml | 1 + .../teku/spec/config/configs/less-swift.yaml | 1 + .../teku/spec/config/configs/lukso.yaml | 1 + .../teku/spec/config/configs/mainnet.yaml | 1 + .../teku/spec/config/configs/minimal.yaml | 1 + .../teku/spec/config/configs/sepolia.yaml | 1 + .../teku/spec/config/configs/swift.yaml | 1 + .../config/invalid/missingAltairField.yaml | 3 +- .../spec/config/invalid/unknownField.yaml | 3 +- .../spec/config/standard/with-overrides.yaml | 3 +- .../eth2/peers/Eth2PeerManager.java | 6 +- .../rpc/core/Eth2IncomingRequestHandler.java | 5 +- .../rpc/core/Eth2OutgoingRequestHandler.java | 90 +------------ .../methods/SingleProtocolEth2RpcMethod.java | 4 +- .../core/Eth2OutgoingRequestHandlerTest.java | 120 +----------------- .../p2p/libp2p/LibP2PNetworkBuilder.java | 4 +- .../networking/p2p/libp2p/rpc/RpcHandler.java | 25 +++- .../rpc/MaxConcurrentRequestsException.java | 8 ++ .../p2p/libp2p/rpc/RpcHandlerTest.java | 3 +- .../teku/cli/subcommand/test-spec.yaml | 3 +- .../cli/subcommand/RemoteSpecLoaderTest.java | 2 - .../pegasys/teku/cli/options/constants.yaml | 3 +- .../teku/cli/subcommand/deneb_config.yaml | 1 + 31 files changed, 91 insertions(+), 284 deletions(-) create mode 100644 networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java diff --git a/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml b/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml index 17f311def58..6aab2696a57 100644 --- a/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml +++ b/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml @@ -180,4 +180,5 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java index b513c9b16bf..bf61be828ae 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java @@ -327,16 +327,6 @@ public int getMaxChunkSize() { return specConfig.getMaxChunkSize(); } - @Override - public int getTtfbTimeout() { - return specConfig.getTtfbTimeout(); - } - - @Override - public int getRespTimeout() { - return specConfig.getRespTimeout(); - } - @Override public int getAttestationPropagationSlotRange() { return specConfig.getAttestationPropagationSlotRange(); @@ -392,6 +382,11 @@ public int getAttestationSubnetPrefixBits() { return specConfig.getAttestationSubnetPrefixBits(); } + @Override + public int getMaxConcurrentRequests() { + return specConfig.getMaxConcurrentRequests(); + } + @Override public int getProposerScoreBoost() { return specConfig.getProposerScoreBoost(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java index ef5b229dfcc..b4159f17166 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java @@ -27,12 +27,6 @@ public interface NetworkingSpecConfig { int getMinEpochsForBlockRequests(); - // in seconds - int getTtfbTimeout(); - - // in seconds - int getRespTimeout(); - int getAttestationPropagationSlotRange(); // in millis @@ -54,6 +48,8 @@ public interface NetworkingSpecConfig { // int(ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS) int getAttestationSubnetPrefixBits(); + int getMaxConcurrentRequests(); + default NetworkingSpecConfig getNetworkingConfig() { return this; } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java index 6d41969704c..6eccc85019a 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java @@ -107,8 +107,6 @@ public class SpecConfigPhase0 implements SpecConfig { private final int maxRequestBlocks; private final int epochsPerSubnetSubscription; private final int minEpochsForBlockRequests; - private final int ttfbTimeout; - private final int respTimeout; private final int attestationPropagationSlotRange; private final int maximumGossipClockDisparity; private final Bytes4 messageDomainInvalidSnappy; @@ -117,6 +115,7 @@ public class SpecConfigPhase0 implements SpecConfig { private final int attestationSubnetCount; private final int attestationSubnetExtraBits; private final int attestationSubnetPrefixBits; + private final int maxConcurrentRequests; private final int reorgMaxEpochsSinceFinalization; private final int reorgHeadWeightThreshold; private final int reorgParentWeightThreshold; @@ -179,8 +178,6 @@ public SpecConfigPhase0( final int maxRequestBlocks, final int epochsPerSubnetSubscription, final int minEpochsForBlockRequests, - final int ttfbTimeout, - final int respTimeout, final int attestationPropagationSlotRange, final int maximumGossipClockDisparity, final Bytes4 messageDomainInvalidSnappy, @@ -189,6 +186,7 @@ public SpecConfigPhase0( final int attestationSubnetCount, final int attestationSubnetExtraBits, final int attestationSubnetPrefixBits, + final int maxConcurrentRequests, final int reorgMaxEpochsSinceFinalization, final int reorgHeadWeightThreshold, final int reorgParentWeightThreshold, @@ -249,8 +247,6 @@ public SpecConfigPhase0( this.maxRequestBlocks = maxRequestBlocks; this.epochsPerSubnetSubscription = epochsPerSubnetSubscription; this.minEpochsForBlockRequests = minEpochsForBlockRequests; - this.ttfbTimeout = ttfbTimeout; - this.respTimeout = respTimeout; this.attestationPropagationSlotRange = attestationPropagationSlotRange; this.maximumGossipClockDisparity = maximumGossipClockDisparity; this.messageDomainInvalidSnappy = messageDomainInvalidSnappy; @@ -259,6 +255,7 @@ public SpecConfigPhase0( this.attestationSubnetCount = attestationSubnetCount; this.attestationSubnetExtraBits = attestationSubnetExtraBits; this.attestationSubnetPrefixBits = attestationSubnetPrefixBits; + this.maxConcurrentRequests = maxConcurrentRequests; this.reorgMaxEpochsSinceFinalization = reorgMaxEpochsSinceFinalization; this.reorgHeadWeightThreshold = reorgHeadWeightThreshold; this.reorgParentWeightThreshold = reorgParentWeightThreshold; @@ -585,16 +582,6 @@ public int getMinEpochsForBlockRequests() { return minEpochsForBlockRequests; } - @Override - public int getTtfbTimeout() { - return ttfbTimeout; - } - - @Override - public int getRespTimeout() { - return respTimeout; - } - @Override public int getAttestationPropagationSlotRange() { return attestationPropagationSlotRange; @@ -635,6 +622,11 @@ public int getAttestationSubnetPrefixBits() { return attestationSubnetPrefixBits; } + @Override + public int getMaxConcurrentRequests() { + return maxConcurrentRequests; + } + @Override public SpecMilestone getMilestone() { return SpecMilestone.PHASE0; @@ -691,8 +683,7 @@ public boolean equals(final Object o) { && attestationSubnetCount == that.attestationSubnetCount && attestationSubnetExtraBits == that.attestationSubnetExtraBits && attestationSubnetPrefixBits == that.attestationSubnetPrefixBits - && ttfbTimeout == that.ttfbTimeout - && respTimeout == that.respTimeout + && maxConcurrentRequests == that.maxConcurrentRequests && attestationPropagationSlotRange == that.attestationPropagationSlotRange && maximumGossipClockDisparity == that.maximumGossipClockDisparity && Objects.equals(eth1FollowDistance, that.eth1FollowDistance) @@ -772,8 +763,6 @@ public int hashCode() { maxChunkSize, maxRequestBlocks, epochsPerSubnetSubscription, - ttfbTimeout, - respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -781,6 +770,7 @@ public int hashCode() { subnetsPerNode, attestationSubnetCount, attestationSubnetExtraBits, - attestationSubnetPrefixBits); + attestationSubnetPrefixBits, + maxConcurrentRequests); } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java index 5e48e29614c..f3798c3c9b1 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java @@ -112,8 +112,6 @@ public class SpecConfigBuilder { private Integer maxChunkSize; private Integer maxRequestBlocks; private Integer epochsPerSubnetSubscription; - private Integer ttfbTimeout; - private Integer respTimeout; private Integer attestationPropagationSlotRange; private Integer maximumGossipClockDisparity; private Bytes4 messageDomainInvalidSnappy; @@ -123,6 +121,7 @@ public class SpecConfigBuilder { private Integer attestationSubnetCount; private Integer attestationSubnetExtraBits; private Integer attestationSubnetPrefixBits; + private Integer maxConcurrentRequests; // added after Phase0, so add default values, or will be compatibility issue private Integer reorgMaxEpochsSinceFinalization = 2; @@ -205,8 +204,6 @@ public SpecConfigAndParent build() { maxRequestBlocks, epochsPerSubnetSubscription, minEpochsForBlockRequests, - ttfbTimeout, - respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -215,6 +212,7 @@ public SpecConfigAndParent build() { attestationSubnetCount, attestationSubnetExtraBits, attestationSubnetPrefixBits, + maxConcurrentRequests, reorgMaxEpochsSinceFinalization, reorgHeadWeightThreshold, reorgParentWeightThreshold, @@ -279,8 +277,6 @@ private Map getValidationMap() { constants.put("maxRequestBlocks", maxRequestBlocks); constants.put("epochsPerSubnetSubscription", epochsPerSubnetSubscription); constants.put("minEpochsForBlockRequests", minEpochsForBlockRequests); - constants.put("ttfbTimeout", ttfbTimeout); - constants.put("respTimeout", respTimeout); constants.put("attestationPropagationSlotRange", attestationPropagationSlotRange); constants.put("maximumGossipClockDisparity", maximumGossipClockDisparity); constants.put("messageDomainInvalidSnappy", messageDomainInvalidSnappy); @@ -289,6 +285,7 @@ private Map getValidationMap() { constants.put("attestationSubnetCount", attestationSubnetCount); constants.put("attestationSubnetExtraBits", attestationSubnetExtraBits); constants.put("attestationSubnetPrefixBits", attestationSubnetPrefixBits); + constants.put("maxConcurrentRequests", maxConcurrentRequests); constants.put("reorgMaxEpochsSinceFinalization", reorgMaxEpochsSinceFinalization); constants.put("reorgHeadWeightThreshold", reorgHeadWeightThreshold); constants.put("reorgParentWeightThreshold", reorgParentWeightThreshold); @@ -651,16 +648,6 @@ public SpecConfigBuilder minEpochsForBlockRequests(final Integer minEpochsForBlo return this; } - public SpecConfigBuilder ttfbTimeout(final Integer ttfbTimeout) { - this.ttfbTimeout = ttfbTimeout; - return this; - } - - public SpecConfigBuilder respTimeout(final Integer respTimeout) { - this.respTimeout = respTimeout; - return this; - } - public SpecConfigBuilder attestationPropagationSlotRange( final Integer attestationPropagationSlotRange) { this.attestationPropagationSlotRange = attestationPropagationSlotRange; @@ -702,6 +689,11 @@ public SpecConfigBuilder attestationSubnetPrefixBits(final Integer attestationSu return this; } + public SpecConfigBuilder maxConcurrentRequests(final Integer maxConcurrentRequests) { + this.maxConcurrentRequests = maxConcurrentRequests; + return this; + } + public SpecConfigBuilder reorgMaxEpochsSinceFinalization( final Integer reorgMaxEpochsSinceFinalization) { this.reorgMaxEpochsSinceFinalization = reorgMaxEpochsSinceFinalization; diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml index 7ba59a19848..7848b3a8187 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml @@ -124,6 +124,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml index 0b3f87844d2..7de2db53508 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml @@ -113,6 +113,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml index c7600b8648a..b4f7814fcc0 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml @@ -123,6 +123,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml index 58f913a4f54..6d341cc89ea 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml @@ -115,6 +115,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml index 6adebb9c009..a8ab2dcaeac 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml @@ -126,6 +126,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml index 47ad8fa06a4..61cda0f6bc7 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml @@ -145,6 +145,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml index 3c831ba06eb..ec008d90f04 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml @@ -132,6 +132,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml index 1a6ea3507fa..9baa81d7170 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml @@ -132,6 +132,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml index f00e64693b0..729baecd8cb 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml @@ -108,6 +108,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml index 4dd4e891242..9e75a87ad53 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml @@ -127,6 +127,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml index 5db3829279c..181137fdd77 100644 --- a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml +++ b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml @@ -235,4 +235,5 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file diff --git a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml index 108fe0dca71..d987056e62b 100644 --- a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml +++ b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml @@ -280,4 +280,5 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file diff --git a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml index 58a6cc93411..976d9fcc4d6 100644 --- a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml +++ b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml @@ -106,4 +106,5 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java index afa52355653..1aa43c83f5f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java @@ -41,7 +41,6 @@ import tech.pegasys.teku.networking.p2p.peer.Peer; import tech.pegasys.teku.networking.p2p.peer.PeerConnectedSubscriber; import tech.pegasys.teku.spec.Spec; -import tech.pegasys.teku.spec.config.SpecConfig; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.metadata.MetadataMessage; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.metadata.MetadataMessageSchema; import tech.pegasys.teku.spec.datastructures.state.Checkpoint; @@ -66,7 +65,6 @@ public class Eth2PeerManager implements PeerLookup, PeerHandler { private final int eth2RpcOutstandingPingThreshold; private final Duration eth2StatusUpdateInterval; - private final SpecConfig specConfig; Eth2PeerManager( final Spec spec, @@ -99,7 +97,6 @@ public class Eth2PeerManager implements PeerLookup, PeerHandler { this.eth2RpcPingInterval = eth2RpcPingInterval; this.eth2RpcOutstandingPingThreshold = eth2RpcOutstandingPingThreshold; this.eth2StatusUpdateInterval = eth2StatusUpdateInterval; - this.specConfig = spec.getGenesisSpecConfig(); } public static Eth2PeerManager create( @@ -237,7 +234,8 @@ private void ensureStatusReceived(final Eth2Peer peer) { .ifExceptionGetsHereRaiseABug(); } }, - Duration.ofSeconds(specConfig.getRespTimeout())) + // TODO: change with a constant + Duration.ofSeconds(10)) .finish( () -> {}, error -> { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java index dc8dd90ed46..9732bcdae04 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java @@ -54,14 +54,15 @@ public Eth2IncomingRequestHandler( final AsyncRunner asyncRunner, final PeerLookup peerLookup, final LocalMessageHandler localMessageHandler, - final NetworkingSpecConfig networkingConfig) { + @SuppressWarnings("unused") final NetworkingSpecConfig networkingConfig) { this.protocolId = protocolId; this.asyncRunner = asyncRunner; this.peerLookup = peerLookup; this.localMessageHandler = localMessageHandler; this.responseEncoder = responseEncoder; this.requestDecoder = requestDecoder; - this.respTimeout = Duration.ofSeconds(networkingConfig.getRespTimeout()); + // TODO: figure out what we need to do here + this.respTimeout = Duration.ofSeconds(10); } @Override diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java index b39e2f70ad2..b0805a57a47 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java @@ -21,11 +21,8 @@ import com.google.common.annotations.VisibleForTesting; import io.netty.buffer.ByteBuf; -import java.time.Duration; -import java.time.temporal.ChronoUnit; import java.util.Collection; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; @@ -38,7 +35,6 @@ import tech.pegasys.teku.networking.p2p.peer.NodeId; import tech.pegasys.teku.networking.p2p.rpc.RpcRequestHandler; import tech.pegasys.teku.networking.p2p.rpc.RpcStream; -import tech.pegasys.teku.spec.config.NetworkingSpecConfig; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.RpcRequest; public class Eth2OutgoingRequestHandler< @@ -61,8 +57,6 @@ enum State { private final Eth2RpcResponseHandler responseHandler; private final ResponseStream responseStream; - private final AsyncRunner timeoutRunner; - private final AtomicBoolean hasReceivedInitialBytes = new AtomicBoolean(false); private final AtomicInteger currentChunkCount = new AtomicInteger(0); private final AtomicReference state; private final AtomicReference> responseProcessor = @@ -70,43 +64,26 @@ enum State { private final String protocolId; private final RpcResponseDecoder responseDecoder; - private final boolean shouldReceiveResponse; - private final Duration ttbfTimeout; - private final Duration respTimeout; public Eth2OutgoingRequestHandler( final AsyncRunner asyncRunner, - final AsyncRunner timeoutRunner, final String protocolId, final RpcResponseDecoder responseDecoder, final boolean shouldReceiveResponse, final TRequest request, - final Eth2RpcResponseHandler responseHandler, - final NetworkingSpecConfig networkingConfig) { + final Eth2RpcResponseHandler responseHandler) { this.asyncRunner = asyncRunner; - this.timeoutRunner = timeoutRunner; this.maximumResponseChunks = request.getMaximumResponseChunks(); - this.responseHandler = responseHandler; responseStream = new ResponseStream<>(responseHandler); this.responseDecoder = responseDecoder; - this.shouldReceiveResponse = shouldReceiveResponse; this.protocolId = protocolId; - this.ttbfTimeout = Duration.of(networkingConfig.getTtfbTimeout(), ChronoUnit.SECONDS); - this.respTimeout = Duration.of(networkingConfig.getRespTimeout(), ChronoUnit.SECONDS); this.state = new AtomicReference<>(shouldReceiveResponse ? EXPECT_DATA : DATA_COMPLETED); } public void handleInitialPayloadSent(final RpcStream stream) { // Close the write side of the stream stream.closeWriteStream().ifExceptionGetsHereRaiseABug(); - - if (shouldReceiveResponse) { - // Start timer for first bytes - ensureFirstBytesArriveWithinTimeLimit(stream); - } else { - ensureReadCompleteArrivesInTime(stream); - } } @Override @@ -123,8 +100,6 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By throw new RpcException.ExtraDataAppendedException(" extra data: " + bufToString(data)); } - onFirstByteReceived(rpcStream); - List maybeResponses = responseDecoder.decodeNextResponses(data); final int chunksReceived = currentChunkCount.addAndGet(maybeResponses.size()); @@ -135,16 +110,10 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By for (TResponse maybeResponse : maybeResponses) { getResponseProcessor(rpcStream).processResponse(maybeResponse); } - if (chunksReceived < maximumResponseChunks) { - if (!maybeResponses.isEmpty()) { - ensureNextResponseArrivesInTime(rpcStream, chunksReceived, currentChunkCount); - } - } else { + if (chunksReceived == maximumResponseChunks) { if (!transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); - return; } - ensureReadCompleteArrivesInTime(rpcStream); } } catch (final RpcException e) { abortRequest(rpcStream, e); @@ -216,13 +185,6 @@ private boolean transferToState(final State toState, final Collection fro return false; } - private void onFirstByteReceived(final RpcStream rpcStream) { - if (hasReceivedInitialBytes.compareAndSet(false, true)) { - // Setup initial chunk timeout - ensureNextResponseArrivesInTime(rpcStream, currentChunkCount.get(), currentChunkCount); - } - } - private void completeRequest(final RpcStream rpcStream) { getResponseProcessor(rpcStream) .finishProcessing() @@ -266,54 +228,6 @@ private void abortRequest(final RpcStream rpcStream, final Throwable error, fina } } - private void ensureFirstBytesArriveWithinTimeLimit(final RpcStream stream) { - timeoutRunner - .getDelayedFuture(ttbfTimeout) - .thenAccept( - (__) -> { - if (!hasReceivedInitialBytes.get()) { - abortRequest( - stream, - new RpcTimeoutException("Timed out waiting for initial response", ttbfTimeout)); - } - }) - .ifExceptionGetsHereRaiseABug(); - } - - private void ensureNextResponseArrivesInTime( - final RpcStream stream, - final int previousResponseCount, - final AtomicInteger currentResponseCount) { - final Duration timeout = respTimeout; - timeoutRunner - .getDelayedFuture(timeout) - .thenAccept( - (__) -> { - if (previousResponseCount == currentResponseCount.get()) { - abortRequest( - stream, - new RpcTimeoutException( - "Timed out waiting for response chunk " + previousResponseCount, timeout)); - } - }) - .ifExceptionGetsHereRaiseABug(); - } - - private void ensureReadCompleteArrivesInTime(final RpcStream stream) { - final Duration timeout = respTimeout; - timeoutRunner - .getDelayedFuture(timeout) - .thenAccept( - (__) -> { - if (!(state.get() == READ_COMPLETE || state.get() == CLOSED)) { - abortRequest( - stream, - new RpcTimeoutException("Timed out waiting for read channel close", timeout)); - } - }) - .ifExceptionGetsHereRaiseABug(); - } - @VisibleForTesting State getState() { return state.get(); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java index fd3224e848d..fe0eb15eba4 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java @@ -101,14 +101,12 @@ public Eth2OutgoingRequestHandler createOutgoingRequestHand final TRequest request, final Eth2RpcResponseHandler responseHandler) { return new Eth2OutgoingRequestHandler<>( - asyncRunner, asyncRunner, protocolId, createResponseDecoder(), expectResponseToRequest, request, - responseHandler, - networkingConfig); + responseHandler); } @Override diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java index ce83a72a55c..b7ec07fe6cc 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java @@ -20,7 +20,6 @@ import static org.mockito.Mockito.verify; import java.io.IOException; -import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -65,10 +64,6 @@ public class Eth2OutgoingRequestHandlerTest Eth2RpcResponseHandler.expectMultipleResponses(res -> responseListener.get().onResponse(res)); private final int maxChunks = 3; private final SafeFuture finishedProcessingFuture = responseHandler.getCompletedFuture(); - private final Duration ttbfTimeout = - Duration.ofSeconds(spec.getGenesisSpecConfig().getTtfbTimeout()); - private final Duration respTimeout = - Duration.ofSeconds(spec.getGenesisSpecConfig().getRespTimeout()); private RpcResponseEncoder responseEncoder; private List chunks; @@ -101,13 +96,11 @@ public void setup() { getRpcEncoding(), spec.getGenesisSchemaDefinitions().getSignedBeaconBlockSchema()); return new Eth2OutgoingRequestHandler<>( asyncRequestRunner, - timeoutRunner, method.getIds().get(0), responseDecoder, method.shouldReceiveResponse(), request, - responseHandler, - spec.getNetworkingConfig()); + responseHandler); } @Override @@ -269,94 +262,6 @@ public void shouldWorkWhenSendAllChunksPlusEmptyExtraChunk() throws Exception { verify(rpcStream, never()).closeAbruptly(); } - @Test - public void disconnectsIfInitialBytesAreNotReceivedInTime() { - sendInitialPayload(); - verify(rpcStream).closeWriteStream(); - verify(rpcStream, never()).closeAbruptly(); - - // Run async tasks - timeProvider.advanceTimeByMillis(ttbfTimeout.toMillis()); - timeoutRunner.executeDueActions(); - verify(rpcStream).closeAbruptly(); - } - - @Test - public void doesNotDisconnectIfInitialBytesAreReceivedInTime() throws Exception { - sendInitialPayload(); - verify(rpcStream).closeWriteStream(); - verify(rpcStream, never()).closeAbruptly(); - - // Deliver some bytes just in time - timeProvider.advanceTimeByMillis(ttbfTimeout.toMillis() - 1); - timeoutRunner.executeDueActions(); - deliverInitialBytes(); - - // Go past the time the first bytes should have been received and check it doesn't timeout - timeProvider.advanceTimeByMillis(10); - timeoutRunner.executeDueActions(); - verify(rpcStream, never()).closeAbruptly(); - } - - @Test - public void disconnectsIfFirstChunkIsNotReceivedInTime() throws Exception { - sendInitialPayload(); - - deliverInitialBytes(); - - // Run timeouts - timeProvider.advanceTimeByMillis(respTimeout.toMillis()); - timeoutRunner.executeDueActions(); - verify(rpcStream).closeAbruptly(); - } - - @Test - public void doNotDisconnectsIfFirstChunkReceivedInTime() throws Exception { - sendInitialPayload(); - - // First byte is received just in time - timeProvider.advanceTimeByMillis(ttbfTimeout.toMillis() - 1); - deliverChunk(0); - - // Go past the time the first chunk would have timed out but not enough to trigger timeout on - // the second chunk and ensure the timeout never fires. - timeProvider.advanceTimeByMillis(respTimeout.toMillis() - 1); - timeoutRunner.executeDueActions(); - verify(rpcStream, never()).closeAbruptly(); - } - - @Test - public void disconnectsIfSecondChunkNotReceivedInTime() throws Exception { - sendInitialPayload(); - - timeProvider.advanceTimeByMillis(100); - deliverChunk(0); - asyncRequestRunner.executeQueuedActions(); - assertThat(blocks.size()).isEqualTo(1); - - // Run timeouts - timeProvider.advanceTimeByMillis(respTimeout.toMillis()); - timeoutRunner.executeDueActions(); - verify(rpcStream).closeAbruptly(); - } - - @Test - public void abortsWhenNoReadComplete() throws Exception { - sendInitialPayload(); - - timeProvider.advanceTimeByMillis(100); - for (int i = 0; i < maxChunks; i++) { - deliverChunk(i); - } - - asyncRequestRunner.executeQueuedActions(); - - // Run timeouts - timeProvider.advanceTimeByMillis(respTimeout.toMillis()); - timeoutRunner.executeDueActions(); - verify(rpcStream).closeAbruptly(); - } - @Test public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { sendInitialPayload(); @@ -372,29 +277,6 @@ public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { assertThat(finishedProcessingFuture).isCompletedExceptionally(); } - @Test - public void doNotDisconnectsIfSecondChunkReceivedInTime() throws Exception { - sendInitialPayload(); - - timeProvider.advanceTimeByMillis(100); - deliverChunk(0); - asyncRequestRunner.executeQueuedActions(); - assertThat(blocks.size()).isEqualTo(1); - - // Second chunk is received just in time - timeProvider.advanceTimeByMillis(respTimeout.toMillis() - 1); - timeoutRunner.executeDueActions(); - deliverChunk(1); - asyncRequestRunner.executeQueuedActions(); - - // Go past the time the second chunk would have timed out but not enough to trigger timeout on - // the third chunk and ensure the timeout never fires. - timeProvider.advanceTimeByMillis(respTimeout.toMillis() - 1); - timeoutRunner.executeDueActions(); - verify(rpcStream, never()).closeAbruptly(); - assertThat(blocks.size()).isEqualTo(2); - } - @Test public void shouldWorkWhenInitialPayloadEventIsLate() throws Exception { deliverChunk(0); diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java index 5b809f77d14..3de2acd2675 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java @@ -152,7 +152,9 @@ public P2PNetwork build() { } protected List> createRpcHandlers() { - return rpcMethods.stream().map(m -> new RpcHandler<>(asyncRunner, m)).toList(); + return rpcMethods.stream() + .map(m -> new RpcHandler<>(asyncRunner, m, networkingSpecConfig.getMaxConcurrentRequests())) + .toList(); } protected LibP2PGossipNetwork createGossipNetwork() { diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java index 9de93c7765b..75a7a8b8db6 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java @@ -30,6 +30,7 @@ import io.netty.channel.SimpleChannelInboundHandler; import java.time.Duration; import java.util.Optional; +import java.util.concurrent.Semaphore; import java.util.function.Consumer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -43,6 +44,7 @@ import tech.pegasys.teku.networking.p2p.libp2p.rpc.RpcHandler.Controller; import tech.pegasys.teku.networking.p2p.peer.NodeId; import tech.pegasys.teku.networking.p2p.peer.PeerDisconnectedException; +import tech.pegasys.teku.networking.p2p.rpc.MaxConcurrentRequestsException; import tech.pegasys.teku.networking.p2p.rpc.RpcMethod; import tech.pegasys.teku.networking.p2p.rpc.RpcRequestHandler; import tech.pegasys.teku.networking.p2p.rpc.RpcResponseHandler; @@ -59,14 +61,17 @@ public class RpcHandler< private static final Duration TIMEOUT = Duration.ofSeconds(5); private static final Logger LOG = LogManager.getLogger(); - private final RpcMethod rpcMethod; private final AsyncRunner asyncRunner; + private final RpcMethod rpcMethod; + private final Semaphore concurrentRequestsSemaphore; public RpcHandler( final AsyncRunner asyncRunner, - final RpcMethod rpcMethod) { + final RpcMethod rpcMethod, + final int maxConcurrentRequests) { this.asyncRunner = asyncRunner; this.rpcMethod = rpcMethod; + concurrentRequestsSemaphore = new Semaphore(maxConcurrentRequests); } public RpcMethod getRpcMethod() { @@ -76,16 +81,25 @@ public RpcMethod getRpcMethod() { public SafeFuture> sendRequest( final Connection connection, final TRequest request, final TRespHandler responseHandler) { + if (!concurrentRequestsSemaphore.tryAcquire()) { + return SafeFuture.failedFuture( + new MaxConcurrentRequestsException( + String.format( + "Maximum number of concurrent requests for protocol(s) %s has been reached", + rpcMethod.getIds()))); + } + final Bytes initialPayload; try { initialPayload = rpcMethod.encodeRequest(request); } catch (Exception e) { + concurrentRequestsSemaphore.release(); return SafeFuture.failedFuture(e); } - Interruptor closeInterruptor = + final Interruptor closeInterruptor = SafeFuture.createInterruptor(connection.closeFuture(), PeerDisconnectedException::new); - Interruptor timeoutInterruptor = + final Interruptor timeoutInterruptor = SafeFuture.createInterruptor( asyncRunner.getDelayedFuture(TIMEOUT), () -> @@ -124,7 +138,8 @@ public SafeFuture> sendRequest( if (ExceptionUtil.hasCause(err, ConnectionClosedException.class)) { throw new PeerDisconnectedException(err); } - }); + }) + .alwaysRun(concurrentRequestsSemaphore::release); } private void closeStreamAbruptly(final Stream stream) { diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java new file mode 100644 index 00000000000..008c1191667 --- /dev/null +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java @@ -0,0 +1,8 @@ +package tech.pegasys.teku.networking.p2p.rpc; + +public class MaxConcurrentRequestsException extends RuntimeException { + + public MaxConcurrentRequestsException(final String message) { + super(message); + } +} diff --git a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java index 844e144ffc0..b59f8d6725d 100644 --- a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java +++ b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java @@ -52,8 +52,9 @@ public class RpcHandlerTest { StubAsyncRunner asyncRunner = new StubAsyncRunner(); RpcMethod> rpcMethod = mock(RpcMethod.class); + int maxConcurrentRequests = 2; RpcHandler> rpcHandler = - new RpcHandler<>(asyncRunner, rpcMethod); + new RpcHandler<>(asyncRunner, rpcMethod, maxConcurrentRequests); Connection connection = mock(Connection.class); Session session = mock(Session.class); diff --git a/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml b/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml index 0c17d3c4486..7db048bc9b4 100644 --- a/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml +++ b/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml @@ -107,4 +107,5 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file diff --git a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java index a6818600c2c..5747896cae1 100644 --- a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java +++ b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java @@ -78,8 +78,6 @@ void shouldDefaultNetworkConfigThatMovedFromConstants() throws IOException { assertThat(specConfig.getMaxRequestBlocks()).isEqualTo(1024); assertThat(specConfig.getEpochsPerSubnetSubscription()).isEqualTo(256); assertThat(specConfig.getMinEpochsForBlockRequests()).isEqualTo(33024); - assertThat(specConfig.getTtfbTimeout()).isEqualTo(5); - assertThat(specConfig.getRespTimeout()).isEqualTo(10); assertThat(specConfig.getAttestationPropagationSlotRange()).isEqualTo(32); assertThat(specConfig.getMaximumGossipClockDisparity()).isEqualTo(500); } diff --git a/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml b/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml index f2402b8c7c8..917ed1d29ee 100644 --- a/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml +++ b/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml @@ -180,4 +180,5 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file diff --git a/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml b/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml index 49c8d3b11bd..c4f2815f4d4 100644 --- a/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml +++ b/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml @@ -129,6 +129,7 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 +MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) From caa448eff38d2385147f0dff6065c2a937fa00e5 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Thu, 21 Nov 2024 11:55:52 +0000 Subject: [PATCH 02/23] fix spotless and assemble --- .../rpc/core/Eth2OutgoingRequestHandlerTest.java | 6 ------ .../p2p/rpc/MaxConcurrentRequestsException.java | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java index b7ec07fe6cc..9180942c32f 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -321,11 +320,6 @@ private void sendInitialPayload() { reqHandler.handleInitialPayloadSent(rpcStream); } - private void deliverInitialBytes() throws IOException { - final Bytes firstByte = chunks.get(0).slice(0, 1); - deliverBytes(firstByte); - } - private Bytes chunkBytes(final int chunk) { final SignedBeaconBlock block = dataStructureUtil.randomSignedBeaconBlock(chunk); return responseEncoder.encodeSuccessfulResponse(block); diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java index 008c1191667..77e17abd5c5 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java @@ -1,3 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package tech.pegasys.teku.networking.p2p.rpc; public class MaxConcurrentRequestsException extends RuntimeException { From cbb42632166c82073d4462068670d5a8074a638a Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Thu, 21 Nov 2024 14:51:45 +0000 Subject: [PATCH 03/23] fix stuff --- .../spec/config/DelegatingSpecConfig.java | 10 +++++ .../spec/config/NetworkingSpecConfig.java | 6 +++ .../teku/spec/config/SpecConfigPhase0.java | 20 ++++++++++ .../config/builder/SpecConfigBuilder.java | 16 ++++++++ .../networking/eth2/rpc/core/RpcTimeouts.java | 40 ------------------- 5 files changed, 52 insertions(+), 40 deletions(-) delete mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcTimeouts.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java index bf61be828ae..2829a5d0575 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java @@ -327,6 +327,16 @@ public int getMaxChunkSize() { return specConfig.getMaxChunkSize(); } + @Override + public int getTtfbTimeout() { + return specConfig.getTtfbTimeout(); + } + + @Override + public int getRespTimeout() { + return specConfig.getRespTimeout(); + } + @Override public int getAttestationPropagationSlotRange() { return specConfig.getAttestationPropagationSlotRange(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java index b4159f17166..f368253c989 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java @@ -27,6 +27,12 @@ public interface NetworkingSpecConfig { int getMinEpochsForBlockRequests(); + // in seconds + int getTtfbTimeout(); + + // in seconds + int getRespTimeout(); + int getAttestationPropagationSlotRange(); // in millis diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java index 6eccc85019a..57f19ccc2bb 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java @@ -107,6 +107,8 @@ public class SpecConfigPhase0 implements SpecConfig { private final int maxRequestBlocks; private final int epochsPerSubnetSubscription; private final int minEpochsForBlockRequests; + private final int ttfbTimeout; + private final int respTimeout; private final int attestationPropagationSlotRange; private final int maximumGossipClockDisparity; private final Bytes4 messageDomainInvalidSnappy; @@ -178,6 +180,8 @@ public SpecConfigPhase0( final int maxRequestBlocks, final int epochsPerSubnetSubscription, final int minEpochsForBlockRequests, + final int ttfbTimeout, + final int respTimeout, final int attestationPropagationSlotRange, final int maximumGossipClockDisparity, final Bytes4 messageDomainInvalidSnappy, @@ -247,6 +251,8 @@ public SpecConfigPhase0( this.maxRequestBlocks = maxRequestBlocks; this.epochsPerSubnetSubscription = epochsPerSubnetSubscription; this.minEpochsForBlockRequests = minEpochsForBlockRequests; + this.ttfbTimeout = ttfbTimeout; + this.respTimeout = respTimeout; this.attestationPropagationSlotRange = attestationPropagationSlotRange; this.maximumGossipClockDisparity = maximumGossipClockDisparity; this.messageDomainInvalidSnappy = messageDomainInvalidSnappy; @@ -582,6 +588,16 @@ public int getMinEpochsForBlockRequests() { return minEpochsForBlockRequests; } + @Override + public int getTtfbTimeout() { + return ttfbTimeout; + } + + @Override + public int getRespTimeout() { + return respTimeout; + } + @Override public int getAttestationPropagationSlotRange() { return attestationPropagationSlotRange; @@ -684,6 +700,8 @@ public boolean equals(final Object o) { && attestationSubnetExtraBits == that.attestationSubnetExtraBits && attestationSubnetPrefixBits == that.attestationSubnetPrefixBits && maxConcurrentRequests == that.maxConcurrentRequests + && ttfbTimeout == that.ttfbTimeout + && respTimeout == that.respTimeout && attestationPropagationSlotRange == that.attestationPropagationSlotRange && maximumGossipClockDisparity == that.maximumGossipClockDisparity && Objects.equals(eth1FollowDistance, that.eth1FollowDistance) @@ -763,6 +781,8 @@ public int hashCode() { maxChunkSize, maxRequestBlocks, epochsPerSubnetSubscription, + ttfbTimeout, + respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java index f3798c3c9b1..2a0ce2ded10 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java @@ -112,6 +112,8 @@ public class SpecConfigBuilder { private Integer maxChunkSize; private Integer maxRequestBlocks; private Integer epochsPerSubnetSubscription; + private Integer ttfbTimeout; + private Integer respTimeout; private Integer attestationPropagationSlotRange; private Integer maximumGossipClockDisparity; private Bytes4 messageDomainInvalidSnappy; @@ -204,6 +206,8 @@ public SpecConfigAndParent build() { maxRequestBlocks, epochsPerSubnetSubscription, minEpochsForBlockRequests, + ttfbTimeout, + respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -277,6 +281,8 @@ private Map getValidationMap() { constants.put("maxRequestBlocks", maxRequestBlocks); constants.put("epochsPerSubnetSubscription", epochsPerSubnetSubscription); constants.put("minEpochsForBlockRequests", minEpochsForBlockRequests); + constants.put("ttfbTimeout", ttfbTimeout); + constants.put("respTimeout", respTimeout); constants.put("attestationPropagationSlotRange", attestationPropagationSlotRange); constants.put("maximumGossipClockDisparity", maximumGossipClockDisparity); constants.put("messageDomainInvalidSnappy", messageDomainInvalidSnappy); @@ -648,6 +654,16 @@ public SpecConfigBuilder minEpochsForBlockRequests(final Integer minEpochsForBlo return this; } + public SpecConfigBuilder ttfbTimeout(final Integer ttfbTimeout) { + this.ttfbTimeout = ttfbTimeout; + return this; + } + + public SpecConfigBuilder respTimeout(final Integer respTimeout) { + this.respTimeout = respTimeout; + return this; + } + public SpecConfigBuilder attestationPropagationSlotRange( final Integer attestationPropagationSlotRange) { this.attestationPropagationSlotRange = attestationPropagationSlotRange; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcTimeouts.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcTimeouts.java deleted file mode 100644 index 0fce1e93fd1..00000000000 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcTimeouts.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package tech.pegasys.teku.networking.eth2.rpc.core; - -import java.time.Duration; -import tech.pegasys.teku.networking.p2p.rpc.StreamTimeoutException; - -/** - * This class holds constants related to handling rpc request timeouts. See: - * https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#configuration - */ -public abstract class RpcTimeouts { - - // The maximum time to wait for first byte of request response (time-to-first-byte). - static final Duration TTFB_TIMEOUT = Duration.ofSeconds(5); - // The maximum time for complete response transfer. - public static final Duration RESP_TIMEOUT = Duration.ofSeconds(10); - - public static class RpcTimeoutException extends StreamTimeoutException { - - public RpcTimeoutException(final String message, final Duration timeout) { - super(generateMessage(message, timeout)); - } - - private static String generateMessage(final String message, final Duration timeout) { - return String.format("Rpc request timed out after %d sec: %s", timeout.toSeconds(), message); - } - } -} From 7824474290b3cbd6007cd84382348f21ba1af0bc Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Thu, 21 Nov 2024 14:56:30 +0000 Subject: [PATCH 04/23] small nit --- .../pegasys/teku/networking/eth2/peers/Eth2PeerManager.java | 6 ++++-- .../eth2/rpc/core/Eth2IncomingRequestHandler.java | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java index 1aa43c83f5f..afa52355653 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java @@ -41,6 +41,7 @@ import tech.pegasys.teku.networking.p2p.peer.Peer; import tech.pegasys.teku.networking.p2p.peer.PeerConnectedSubscriber; import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.config.SpecConfig; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.metadata.MetadataMessage; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.metadata.MetadataMessageSchema; import tech.pegasys.teku.spec.datastructures.state.Checkpoint; @@ -65,6 +66,7 @@ public class Eth2PeerManager implements PeerLookup, PeerHandler { private final int eth2RpcOutstandingPingThreshold; private final Duration eth2StatusUpdateInterval; + private final SpecConfig specConfig; Eth2PeerManager( final Spec spec, @@ -97,6 +99,7 @@ public class Eth2PeerManager implements PeerLookup, PeerHandler { this.eth2RpcPingInterval = eth2RpcPingInterval; this.eth2RpcOutstandingPingThreshold = eth2RpcOutstandingPingThreshold; this.eth2StatusUpdateInterval = eth2StatusUpdateInterval; + this.specConfig = spec.getGenesisSpecConfig(); } public static Eth2PeerManager create( @@ -234,8 +237,7 @@ private void ensureStatusReceived(final Eth2Peer peer) { .ifExceptionGetsHereRaiseABug(); } }, - // TODO: change with a constant - Duration.ofSeconds(10)) + Duration.ofSeconds(specConfig.getRespTimeout())) .finish( () -> {}, error -> { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java index 9732bcdae04..dc8dd90ed46 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java @@ -54,15 +54,14 @@ public Eth2IncomingRequestHandler( final AsyncRunner asyncRunner, final PeerLookup peerLookup, final LocalMessageHandler localMessageHandler, - @SuppressWarnings("unused") final NetworkingSpecConfig networkingConfig) { + final NetworkingSpecConfig networkingConfig) { this.protocolId = protocolId; this.asyncRunner = asyncRunner; this.peerLookup = peerLookup; this.localMessageHandler = localMessageHandler; this.responseEncoder = responseEncoder; this.requestDecoder = requestDecoder; - // TODO: figure out what we need to do here - this.respTimeout = Duration.ofSeconds(10); + this.respTimeout = Duration.ofSeconds(networkingConfig.getRespTimeout()); } @Override From b48142885064d45e9ad09edd45a2027a58143aef Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Thu, 21 Nov 2024 16:28:25 +0000 Subject: [PATCH 05/23] Change semaphore usage --- .../pegasys/teku/spec/config/Constants.java | 1 + .../networking/p2p/libp2p/rpc/RpcHandler.java | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java index e9c7a6498e8..ed48b142f48 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java @@ -21,6 +21,7 @@ public class Constants { public static final int ATTESTATION_SUBNET_COUNT = 64; // Teku Networking Specific + public static final Duration RPC_REQUEST_TIMEOUT = Duration.ofSeconds(10); public static final int VALID_BLOCK_SET_SIZE = 1000; // Target holding two slots worth of aggregators (16 aggregators, 64 committees and 2 slots) public static final int VALID_AGGREGATE_SET_SIZE = 16 * 64 * 2; diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java index 75a7a8b8db6..285166c1653 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java @@ -14,6 +14,7 @@ package tech.pegasys.teku.networking.p2p.libp2p.rpc; import static tech.pegasys.teku.infrastructure.async.FutureUtil.ignoreFuture; +import static tech.pegasys.teku.spec.config.Constants.RPC_REQUEST_TIMEOUT; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Throwables; @@ -31,6 +32,7 @@ import java.time.Duration; import java.util.Optional; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -81,12 +83,17 @@ public RpcMethod getRpcMethod() { public SafeFuture> sendRequest( final Connection connection, final TRequest request, final TRespHandler responseHandler) { - if (!concurrentRequestsSemaphore.tryAcquire()) { - return SafeFuture.failedFuture( - new MaxConcurrentRequestsException( - String.format( - "Maximum number of concurrent requests for protocol(s) %s has been reached", - rpcMethod.getIds()))); + try { + if (!concurrentRequestsSemaphore.tryAcquire( + RPC_REQUEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)) { + return SafeFuture.failedFuture( + new MaxConcurrentRequestsException( + String.format( + "Maximum number of concurrent requests for protocol(s) %s has been reached", + rpcMethod.getIds()))); + } + } catch (InterruptedException e) { + return SafeFuture.failedFuture(new RuntimeException("Thread interrupted", e)); } final Bytes initialPayload; From bcf2f5a860b10598d05c2ead4824171531c600ac Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Fri, 22 Nov 2024 11:40:57 +0000 Subject: [PATCH 06/23] introduce timeouts --- .../pegasys/teku/spec/config/Constants.java | 1 + .../p2p/libp2p/LibP2PNetworkBuilder.java | 9 ++++++- .../networking/p2p/libp2p/rpc/RpcHandler.java | 25 ++++++++++--------- .../p2p/libp2p/rpc/RpcHandlerTest.java | 5 +++- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java index ed48b142f48..90b9d395991 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java @@ -21,6 +21,7 @@ public class Constants { public static final int ATTESTATION_SUBNET_COUNT = 64; // Teku Networking Specific + // General RPC timeout for receiving a full response after initiating a request public static final Duration RPC_REQUEST_TIMEOUT = Duration.ofSeconds(10); public static final int VALID_BLOCK_SET_SIZE = 1000; // Target holding two slots worth of aggregators (16 aggregators, 64 committees and 2 slots) diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java index 3de2acd2675..ad0da2cf0e4 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java @@ -15,6 +15,7 @@ import static tech.pegasys.teku.networking.p2p.libp2p.LibP2PNetwork.REMOTE_OPEN_STREAMS_RATE_LIMIT; import static tech.pegasys.teku.networking.p2p.libp2p.LibP2PNetwork.REMOTE_PARALLEL_OPEN_STREAMS_COUNT_LIMIT; +import static tech.pegasys.teku.spec.config.Constants.RPC_REQUEST_TIMEOUT; import com.google.common.base.Preconditions; import identify.pb.IdentifyOuterClass; @@ -153,7 +154,13 @@ public P2PNetwork build() { protected List> createRpcHandlers() { return rpcMethods.stream() - .map(m -> new RpcHandler<>(asyncRunner, m, networkingSpecConfig.getMaxConcurrentRequests())) + .map( + m -> + new RpcHandler<>( + asyncRunner, + m, + networkingSpecConfig.getMaxConcurrentRequests(), + RPC_REQUEST_TIMEOUT)) .toList(); } diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java index 285166c1653..b06544770ba 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java @@ -14,7 +14,6 @@ package tech.pegasys.teku.networking.p2p.libp2p.rpc; import static tech.pegasys.teku.infrastructure.async.FutureUtil.ignoreFuture; -import static tech.pegasys.teku.spec.config.Constants.RPC_REQUEST_TIMEOUT; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Throwables; @@ -66,14 +65,17 @@ public class RpcHandler< private final AsyncRunner asyncRunner; private final RpcMethod rpcMethod; private final Semaphore concurrentRequestsSemaphore; + private final Duration concurrentRequestsQueueTimeout; public RpcHandler( final AsyncRunner asyncRunner, final RpcMethod rpcMethod, - final int maxConcurrentRequests) { + final int maxConcurrentRequests, + final Duration concurrentRequestsQueueTimeout) { this.asyncRunner = asyncRunner; this.rpcMethod = rpcMethod; concurrentRequestsSemaphore = new Semaphore(maxConcurrentRequests); + this.concurrentRequestsQueueTimeout = concurrentRequestsQueueTimeout; } public RpcMethod getRpcMethod() { @@ -83,27 +85,26 @@ public RpcMethod getRpcMethod() { public SafeFuture> sendRequest( final Connection connection, final TRequest request, final TRespHandler responseHandler) { + final Bytes initialPayload; + try { + initialPayload = rpcMethod.encodeRequest(request); + } catch (Exception e) { + return SafeFuture.failedFuture(e); + } + try { if (!concurrentRequestsSemaphore.tryAcquire( - RPC_REQUEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)) { + concurrentRequestsQueueTimeout.toMillis(), TimeUnit.MILLISECONDS)) { return SafeFuture.failedFuture( new MaxConcurrentRequestsException( String.format( - "Maximum number of concurrent requests for protocol(s) %s has been reached", + "Timed out while waiting for concurrent requests availability for protocol(s) %s", rpcMethod.getIds()))); } } catch (InterruptedException e) { return SafeFuture.failedFuture(new RuntimeException("Thread interrupted", e)); } - final Bytes initialPayload; - try { - initialPayload = rpcMethod.encodeRequest(request); - } catch (Exception e) { - concurrentRequestsSemaphore.release(); - return SafeFuture.failedFuture(e); - } - final Interruptor closeInterruptor = SafeFuture.createInterruptor(connection.closeFuture(), PeerDisconnectedException::new); final Interruptor timeoutInterruptor = diff --git a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java index b59f8d6725d..517fef3aa6a 100644 --- a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java +++ b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java @@ -28,6 +28,7 @@ import io.libp2p.core.StreamPromise; import io.libp2p.core.multistream.ProtocolBinding; import io.libp2p.core.mux.StreamMuxer.Session; +import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import kotlin.Unit; @@ -53,8 +54,10 @@ public class RpcHandlerTest { StubAsyncRunner asyncRunner = new StubAsyncRunner(); RpcMethod> rpcMethod = mock(RpcMethod.class); int maxConcurrentRequests = 2; + Duration concurrentRequestsQueueTimeout = Duration.ofMillis(100); RpcHandler> rpcHandler = - new RpcHandler<>(asyncRunner, rpcMethod, maxConcurrentRequests); + new RpcHandler<>( + asyncRunner, rpcMethod, maxConcurrentRequests, concurrentRequestsQueueTimeout); Connection connection = mock(Connection.class); Session session = mock(Session.class); From 5e24b3609ba5d09969b8bdd23d6502b441d5930d Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Fri, 22 Nov 2024 13:54:17 +0000 Subject: [PATCH 07/23] Add one more test --- .../p2p/libp2p/rpc/RpcHandlerTest.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java index 517fef3aa6a..f6f67ff1e3d 100644 --- a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java +++ b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java @@ -31,6 +31,7 @@ import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.IntStream; import kotlin.Unit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -38,9 +39,11 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.async.SafeFutureAssert; import tech.pegasys.teku.infrastructure.async.StubAsyncRunner; import tech.pegasys.teku.networking.p2p.libp2p.rpc.RpcHandler.Controller; import tech.pegasys.teku.networking.p2p.peer.PeerDisconnectedException; +import tech.pegasys.teku.networking.p2p.rpc.MaxConcurrentRequestsException; import tech.pegasys.teku.networking.p2p.rpc.RpcMethod; import tech.pegasys.teku.networking.p2p.rpc.RpcRequestHandler; import tech.pegasys.teku.networking.p2p.rpc.RpcResponseHandler; @@ -54,7 +57,7 @@ public class RpcHandlerTest { StubAsyncRunner asyncRunner = new StubAsyncRunner(); RpcMethod> rpcMethod = mock(RpcMethod.class); int maxConcurrentRequests = 2; - Duration concurrentRequestsQueueTimeout = Duration.ofMillis(100); + Duration concurrentRequestsQueueTimeout = Duration.ofMillis(200); RpcHandler> rpcHandler = new RpcHandler<>( asyncRunner, rpcMethod, maxConcurrentRequests, concurrentRequestsQueueTimeout); @@ -251,6 +254,36 @@ void sendRequest_interruptBeforeInitialPayloadWritten( verify(stream).close(); } + @Test + void requestThrowsIfThereIsNoConcurrentRequestsAvailabilityInTime() { + // fill the queue + IntStream.range(0, maxConcurrentRequests) + .forEach(__ -> rpcHandler.sendRequest(connection, request, responseHandler)); + + // request should fail after the timeout + SafeFutureAssert.assertThatSafeFuture( + rpcHandler.sendRequest(connection, request, responseHandler)) + .isCompletedExceptionallyWith(MaxConcurrentRequestsException.class); + } + + @Test + void requestCompletesIfConcurrentRequestsQueueIsFreed() { + // fill the queue + IntStream.range(0, maxConcurrentRequests) + .forEach(__ -> rpcHandler.sendRequest(connection, request, responseHandler)); + + streamPromise.getStream().complete(stream); + streamPromise.getController().complete(controller); + stream.getProtocol().complete("test"); + writeFuture.complete(null); + + // request should complete since queue is freed + final SafeFuture> future = + rpcHandler.sendRequest(connection, request, responseHandler); + + assertThat(future).isCompleted(); + } + @SuppressWarnings("UnnecessaryAsync") private Class executeInterrupts( final boolean closeStream, final boolean exceedTimeout) { From 7d2ece02542fb670d2c9d5423f43c6b1592d60bf Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Fri, 22 Nov 2024 15:04:26 +0000 Subject: [PATCH 08/23] fix assemble --- .../pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java index f6f67ff1e3d..a7f993222d2 100644 --- a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java +++ b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java @@ -255,6 +255,7 @@ void sendRequest_interruptBeforeInitialPayloadWritten( } @Test + @SuppressWarnings("FutureReturnValueIgnored") void requestThrowsIfThereIsNoConcurrentRequestsAvailabilityInTime() { // fill the queue IntStream.range(0, maxConcurrentRequests) @@ -267,6 +268,7 @@ void requestThrowsIfThereIsNoConcurrentRequestsAvailabilityInTime() { } @Test + @SuppressWarnings("FutureReturnValueIgnored") void requestCompletesIfConcurrentRequestsQueueIsFreed() { // fill the queue IntStream.range(0, maxConcurrentRequests) From c6da5674d60f5400c20973c8b0a13f4eb25bc32f Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Fri, 22 Nov 2024 15:33:05 +0000 Subject: [PATCH 09/23] feedback --- .../eth2/rpc/core/Eth2OutgoingRequestHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java index b0805a57a47..003ab9cb9de 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java @@ -110,10 +110,9 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By for (TResponse maybeResponse : maybeResponses) { getResponseProcessor(rpcStream).processResponse(maybeResponse); } - if (chunksReceived == maximumResponseChunks) { - if (!transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { - abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); - } + if (chunksReceived >= maximumResponseChunks + && !transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { + abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); } } catch (final RpcException e) { abortRequest(rpcStream, e); From c7890a68a209c51518c545bf44fffc44a07a62cc Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Fri, 22 Nov 2024 18:02:20 +0000 Subject: [PATCH 10/23] Use ThrottlingTaskQueue --- .../async/ThrottlingTaskQueue.java | 4 ++ .../p2p/libp2p/LibP2PNetworkBuilder.java | 9 +--- .../networking/p2p/libp2p/rpc/RpcHandler.java | 35 +++++--------- .../p2p/libp2p/rpc/RpcHandlerTest.java | 46 +++++++++---------- 4 files changed, 37 insertions(+), 57 deletions(-) diff --git a/infrastructure/async/src/main/java/tech/pegasys/teku/infrastructure/async/ThrottlingTaskQueue.java b/infrastructure/async/src/main/java/tech/pegasys/teku/infrastructure/async/ThrottlingTaskQueue.java index 7927f27ec26..2d18705a41e 100644 --- a/infrastructure/async/src/main/java/tech/pegasys/teku/infrastructure/async/ThrottlingTaskQueue.java +++ b/infrastructure/async/src/main/java/tech/pegasys/teku/infrastructure/async/ThrottlingTaskQueue.java @@ -28,6 +28,10 @@ public class ThrottlingTaskQueue { private int inflightTaskCount = 0; + public static ThrottlingTaskQueue create(final int maximumConcurrentTasks) { + return new ThrottlingTaskQueue(maximumConcurrentTasks); + } + public static ThrottlingTaskQueue create( final int maximumConcurrentTasks, final MetricsSystem metricsSystem, diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java index ad0da2cf0e4..3de2acd2675 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java @@ -15,7 +15,6 @@ import static tech.pegasys.teku.networking.p2p.libp2p.LibP2PNetwork.REMOTE_OPEN_STREAMS_RATE_LIMIT; import static tech.pegasys.teku.networking.p2p.libp2p.LibP2PNetwork.REMOTE_PARALLEL_OPEN_STREAMS_COUNT_LIMIT; -import static tech.pegasys.teku.spec.config.Constants.RPC_REQUEST_TIMEOUT; import com.google.common.base.Preconditions; import identify.pb.IdentifyOuterClass; @@ -154,13 +153,7 @@ public P2PNetwork build() { protected List> createRpcHandlers() { return rpcMethods.stream() - .map( - m -> - new RpcHandler<>( - asyncRunner, - m, - networkingSpecConfig.getMaxConcurrentRequests(), - RPC_REQUEST_TIMEOUT)) + .map(m -> new RpcHandler<>(asyncRunner, m, networkingSpecConfig.getMaxConcurrentRequests())) .toList(); } diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java index b06544770ba..4acf69d73df 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java @@ -30,8 +30,6 @@ import io.netty.channel.SimpleChannelInboundHandler; import java.time.Duration; import java.util.Optional; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -40,12 +38,12 @@ import tech.pegasys.teku.infrastructure.async.AsyncRunner; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.async.SafeFuture.Interruptor; +import tech.pegasys.teku.infrastructure.async.ThrottlingTaskQueue; import tech.pegasys.teku.infrastructure.exceptions.ExceptionUtil; import tech.pegasys.teku.networking.p2p.libp2p.LibP2PNodeId; import tech.pegasys.teku.networking.p2p.libp2p.rpc.RpcHandler.Controller; import tech.pegasys.teku.networking.p2p.peer.NodeId; import tech.pegasys.teku.networking.p2p.peer.PeerDisconnectedException; -import tech.pegasys.teku.networking.p2p.rpc.MaxConcurrentRequestsException; import tech.pegasys.teku.networking.p2p.rpc.RpcMethod; import tech.pegasys.teku.networking.p2p.rpc.RpcRequestHandler; import tech.pegasys.teku.networking.p2p.rpc.RpcResponseHandler; @@ -64,18 +62,15 @@ public class RpcHandler< private final AsyncRunner asyncRunner; private final RpcMethod rpcMethod; - private final Semaphore concurrentRequestsSemaphore; - private final Duration concurrentRequestsQueueTimeout; + private final ThrottlingTaskQueue concurrentRequestsQueue; public RpcHandler( final AsyncRunner asyncRunner, final RpcMethod rpcMethod, - final int maxConcurrentRequests, - final Duration concurrentRequestsQueueTimeout) { + final int maxConcurrentRequests) { this.asyncRunner = asyncRunner; this.rpcMethod = rpcMethod; - concurrentRequestsSemaphore = new Semaphore(maxConcurrentRequests); - this.concurrentRequestsQueueTimeout = concurrentRequestsQueueTimeout; + concurrentRequestsQueue = ThrottlingTaskQueue.create(maxConcurrentRequests); } public RpcMethod getRpcMethod() { @@ -84,6 +79,12 @@ public RpcMethod getRpcMethod() { public SafeFuture> sendRequest( final Connection connection, final TRequest request, final TRespHandler responseHandler) { + return concurrentRequestsQueue.queueTask( + () -> sendRequestInternal(connection, request, responseHandler)); + } + + public SafeFuture> sendRequestInternal( + final Connection connection, final TRequest request, final TRespHandler responseHandler) { final Bytes initialPayload; try { @@ -92,19 +93,6 @@ public SafeFuture> sendRequest( return SafeFuture.failedFuture(e); } - try { - if (!concurrentRequestsSemaphore.tryAcquire( - concurrentRequestsQueueTimeout.toMillis(), TimeUnit.MILLISECONDS)) { - return SafeFuture.failedFuture( - new MaxConcurrentRequestsException( - String.format( - "Timed out while waiting for concurrent requests availability for protocol(s) %s", - rpcMethod.getIds()))); - } - } catch (InterruptedException e) { - return SafeFuture.failedFuture(new RuntimeException("Thread interrupted", e)); - } - final Interruptor closeInterruptor = SafeFuture.createInterruptor(connection.closeFuture(), PeerDisconnectedException::new); final Interruptor timeoutInterruptor = @@ -146,8 +134,7 @@ public SafeFuture> sendRequest( if (ExceptionUtil.hasCause(err, ConnectionClosedException.class)) { throw new PeerDisconnectedException(err); } - }) - .alwaysRun(concurrentRequestsSemaphore::release); + }); } private void closeStreamAbruptly(final Stream stream) { diff --git a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java index a7f993222d2..c267ce583eb 100644 --- a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java +++ b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java @@ -28,7 +28,6 @@ import io.libp2p.core.StreamPromise; import io.libp2p.core.multistream.ProtocolBinding; import io.libp2p.core.mux.StreamMuxer.Session; -import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.IntStream; @@ -39,11 +38,9 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import tech.pegasys.teku.infrastructure.async.SafeFuture; -import tech.pegasys.teku.infrastructure.async.SafeFutureAssert; import tech.pegasys.teku.infrastructure.async.StubAsyncRunner; import tech.pegasys.teku.networking.p2p.libp2p.rpc.RpcHandler.Controller; import tech.pegasys.teku.networking.p2p.peer.PeerDisconnectedException; -import tech.pegasys.teku.networking.p2p.rpc.MaxConcurrentRequestsException; import tech.pegasys.teku.networking.p2p.rpc.RpcMethod; import tech.pegasys.teku.networking.p2p.rpc.RpcRequestHandler; import tech.pegasys.teku.networking.p2p.rpc.RpcResponseHandler; @@ -57,10 +54,8 @@ public class RpcHandlerTest { StubAsyncRunner asyncRunner = new StubAsyncRunner(); RpcMethod> rpcMethod = mock(RpcMethod.class); int maxConcurrentRequests = 2; - Duration concurrentRequestsQueueTimeout = Duration.ofMillis(200); RpcHandler> rpcHandler = - new RpcHandler<>( - asyncRunner, rpcMethod, maxConcurrentRequests, concurrentRequestsQueueTimeout); + new RpcHandler<>(asyncRunner, rpcMethod, maxConcurrentRequests); Connection connection = mock(Connection.class); Session session = mock(Session.class); @@ -256,34 +251,35 @@ void sendRequest_interruptBeforeInitialPayloadWritten( @Test @SuppressWarnings("FutureReturnValueIgnored") - void requestThrowsIfThereIsNoConcurrentRequestsAvailabilityInTime() { - // fill the queue - IntStream.range(0, maxConcurrentRequests) - .forEach(__ -> rpcHandler.sendRequest(connection, request, responseHandler)); - - // request should fail after the timeout - SafeFutureAssert.assertThatSafeFuture( - rpcHandler.sendRequest(connection, request, responseHandler)) - .isCompletedExceptionallyWith(MaxConcurrentRequestsException.class); - } - - @Test - @SuppressWarnings("FutureReturnValueIgnored") - void requestCompletesIfConcurrentRequestsQueueIsFreed() { + void requestIsThrottledIfQueueIsFull() { // fill the queue IntStream.range(0, maxConcurrentRequests) .forEach(__ -> rpcHandler.sendRequest(connection, request, responseHandler)); + final StreamPromise> streamPromise = + new StreamPromise<>(new CompletableFuture<>(), new CompletableFuture<>()); + when(session.createStream((ProtocolBinding>) any())) + .thenReturn(streamPromise); + final Stream stream = mock(Stream.class); streamPromise.getStream().complete(stream); streamPromise.getController().complete(controller); - stream.getProtocol().complete("test"); - writeFuture.complete(null); + CompletableFuture protocolIdFuture = new CompletableFuture<>(); + when(stream.getProtocol()).thenReturn(protocolIdFuture); + protocolIdFuture.complete("test"); - // request should complete since queue is freed - final SafeFuture> future = + final SafeFuture> throttledResult = rpcHandler.sendRequest(connection, request, responseHandler); - assertThat(future).isCompleted(); + assertThat(throttledResult).isNotDone(); + + // empty the queue + this.streamPromise.getStream().complete(stream); + this.streamPromise.getController().complete(controller); + this.stream.getProtocol().complete("test"); + writeFuture.complete(null); + + // throttled request should have completed now + assertThat(throttledResult).isCompleted(); } @SuppressWarnings("UnnecessaryAsync") From a8f00b0bf66bbe3228ca9742ba6ea6fdd8996354 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Sat, 23 Nov 2024 18:15:09 +0000 Subject: [PATCH 11/23] Reintroduce timeouts --- .../pegasys/teku/spec/config/Constants.java | 5 +- .../rpc/core/Eth2IncomingRequestHandler.java | 14 ++-- .../rpc/core/Eth2OutgoingRequestHandler.java | 67 ++++++++++++++++++- .../methods/SingleProtocolEth2RpcMethod.java | 4 +- .../core/Eth2OutgoingRequestHandlerTest.java | 57 ++++++++++++++++ .../p2p/libp2p/rpc/RpcHandlerTest.java | 22 +++--- 6 files changed, 142 insertions(+), 27 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java index 90b9d395991..49d350f854e 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java @@ -21,8 +21,9 @@ public class Constants { public static final int ATTESTATION_SUBNET_COUNT = 64; // Teku Networking Specific - // General RPC timeout for receiving a full response after initiating a request - public static final Duration RPC_REQUEST_TIMEOUT = Duration.ofSeconds(10); + // Global RPC timeout for reading an incoming request or for receiving a response chunk after + // initiating a request + public static final Duration RPC_TIMEOUT = Duration.ofSeconds(10); public static final int VALID_BLOCK_SET_SIZE = 1000; // Target holding two slots worth of aggregators (16 aggregators, 64 committees and 2 slots) public static final int VALID_AGGREGATE_SET_SIZE = 16 * 64 * 2; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java index dc8dd90ed46..f1e38849d82 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java @@ -13,9 +13,10 @@ package tech.pegasys.teku.networking.eth2.rpc.core; +import static tech.pegasys.teku.spec.config.Constants.RPC_TIMEOUT; + import com.google.common.annotations.VisibleForTesting; import io.netty.buffer.ByteBuf; -import java.time.Duration; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.logging.log4j.LogManager; @@ -28,7 +29,6 @@ import tech.pegasys.teku.networking.p2p.rpc.RpcRequestHandler; import tech.pegasys.teku.networking.p2p.rpc.RpcStream; import tech.pegasys.teku.networking.p2p.rpc.StreamClosedException; -import tech.pegasys.teku.spec.config.NetworkingSpecConfig; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.RpcRequest; public class Eth2IncomingRequestHandler< @@ -45,7 +45,6 @@ public class Eth2IncomingRequestHandler< private final String protocolId; private final AsyncRunner asyncRunner; private final AtomicBoolean requestHandled = new AtomicBoolean(false); - private final Duration respTimeout; public Eth2IncomingRequestHandler( final String protocolId, @@ -53,15 +52,13 @@ public Eth2IncomingRequestHandler( final RpcRequestDecoder requestDecoder, final AsyncRunner asyncRunner, final PeerLookup peerLookup, - final LocalMessageHandler localMessageHandler, - final NetworkingSpecConfig networkingConfig) { + final LocalMessageHandler localMessageHandler) { this.protocolId = protocolId; this.asyncRunner = asyncRunner; this.peerLookup = peerLookup; this.localMessageHandler = localMessageHandler; this.responseEncoder = responseEncoder; this.requestDecoder = requestDecoder; - this.respTimeout = Duration.ofSeconds(networkingConfig.getRespTimeout()); } @Override @@ -121,15 +118,14 @@ private void handleRequest( } private void ensureRequestReceivedWithinTimeLimit(final RpcStream stream) { - final Duration timeout = respTimeout; asyncRunner - .getDelayedFuture(timeout) + .getDelayedFuture(RPC_TIMEOUT) .thenAccept( (__) -> { if (!requestHandled.get()) { LOG.debug( "Failed to receive incoming request data within {} sec for protocol {}. Close stream.", - timeout.toSeconds(), + RPC_TIMEOUT.toSeconds(), protocolId); stream.closeAbruptly().ifExceptionGetsHereRaiseABug(); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java index 003ab9cb9de..58811a403d6 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java @@ -18,11 +18,13 @@ import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.State.DATA_COMPLETED; import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.State.EXPECT_DATA; import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.State.READ_COMPLETE; +import static tech.pegasys.teku.spec.config.Constants.RPC_TIMEOUT; import com.google.common.annotations.VisibleForTesting; import io.netty.buffer.ByteBuf; import java.util.Collection; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; @@ -53,10 +55,12 @@ enum State { private static final Logger LOG = LogManager.getLogger(); private final AsyncRunner asyncRunner; + private final AsyncRunner timeoutRunner; private final int maximumResponseChunks; private final Eth2RpcResponseHandler responseHandler; private final ResponseStream responseStream; + private final AtomicBoolean hasReceivedInitialBytes = new AtomicBoolean(false); private final AtomicInteger currentChunkCount = new AtomicInteger(0); private final AtomicReference state; private final AtomicReference> responseProcessor = @@ -64,19 +68,23 @@ enum State { private final String protocolId; private final RpcResponseDecoder responseDecoder; + private final boolean shouldReceiveResponse; public Eth2OutgoingRequestHandler( final AsyncRunner asyncRunner, + final AsyncRunner timeoutRunner, final String protocolId, final RpcResponseDecoder responseDecoder, final boolean shouldReceiveResponse, final TRequest request, final Eth2RpcResponseHandler responseHandler) { this.asyncRunner = asyncRunner; + this.timeoutRunner = timeoutRunner; this.maximumResponseChunks = request.getMaximumResponseChunks(); this.responseHandler = responseHandler; responseStream = new ResponseStream<>(responseHandler); this.responseDecoder = responseDecoder; + this.shouldReceiveResponse = shouldReceiveResponse; this.protocolId = protocolId; this.state = new AtomicReference<>(shouldReceiveResponse ? EXPECT_DATA : DATA_COMPLETED); } @@ -84,6 +92,9 @@ public Eth2OutgoingRequestHandler( public void handleInitialPayloadSent(final RpcStream stream) { // Close the write side of the stream stream.closeWriteStream().ifExceptionGetsHereRaiseABug(); + if (!shouldReceiveResponse) { + ensureReadCompleteArrivesInTime(stream); + } } @Override @@ -100,6 +111,8 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By throw new RpcException.ExtraDataAppendedException(" extra data: " + bufToString(data)); } + onFirstByteReceived(rpcStream); + List maybeResponses = responseDecoder.decodeNextResponses(data); final int chunksReceived = currentChunkCount.addAndGet(maybeResponses.size()); @@ -110,9 +123,16 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By for (TResponse maybeResponse : maybeResponses) { getResponseProcessor(rpcStream).processResponse(maybeResponse); } - if (chunksReceived >= maximumResponseChunks - && !transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { - abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); + if (chunksReceived < maximumResponseChunks) { + if (!maybeResponses.isEmpty()) { + ensureNextResponseChunkArrivesInTime(rpcStream, chunksReceived, currentChunkCount); + } + } else { + if (!transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { + abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); + return; + } + ensureReadCompleteArrivesInTime(rpcStream); } } catch (final RpcException e) { abortRequest(rpcStream, e); @@ -184,6 +204,13 @@ private boolean transferToState(final State toState, final Collection fro return false; } + private void onFirstByteReceived(final RpcStream rpcStream) { + if (hasReceivedInitialBytes.compareAndSet(false, true)) { + // Setup initial chunk timeout + ensureNextResponseChunkArrivesInTime(rpcStream, currentChunkCount.get(), currentChunkCount); + } + } + private void completeRequest(final RpcStream rpcStream) { getResponseProcessor(rpcStream) .finishProcessing() @@ -227,6 +254,40 @@ private void abortRequest(final RpcStream rpcStream, final Throwable error, fina } } + private void ensureNextResponseChunkArrivesInTime( + final RpcStream stream, + final int previousResponseCount, + final AtomicInteger currentResponseCount) { + timeoutRunner + .getDelayedFuture(RPC_TIMEOUT) + .thenAccept( + (__) -> { + if (previousResponseCount == currentResponseCount.get()) { + abortRequest( + stream, + new RpcTimeoutException( + "Timed out waiting for response chunk " + previousResponseCount, + RPC_TIMEOUT)); + } + }) + .ifExceptionGetsHereRaiseABug(); + } + + private void ensureReadCompleteArrivesInTime(final RpcStream stream) { + timeoutRunner + .getDelayedFuture(RPC_TIMEOUT) + .thenAccept( + (__) -> { + if (!(state.get() == READ_COMPLETE || state.get() == CLOSED)) { + abortRequest( + stream, + new RpcTimeoutException( + "Timed out waiting for read channel close", RPC_TIMEOUT)); + } + }) + .ifExceptionGetsHereRaiseABug(); + } + @VisibleForTesting State getState() { return state.get(); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java index fe0eb15eba4..a961b2ec736 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java @@ -91,8 +91,7 @@ public Eth2IncomingRequestHandler createIncomingRequestHand createRequestDecoder(), asyncRunner, peerLookup, - localMessageHandler, - networkingConfig); + localMessageHandler); } @Override @@ -101,6 +100,7 @@ public Eth2OutgoingRequestHandler createOutgoingRequestHand final TRequest request, final Eth2RpcResponseHandler responseHandler) { return new Eth2OutgoingRequestHandler<>( + asyncRunner, asyncRunner, protocolId, createResponseDecoder(), diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java index 9180942c32f..a08132a9601 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java @@ -18,6 +18,7 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static tech.pegasys.teku.spec.config.Constants.RPC_TIMEOUT; import java.util.ArrayList; import java.util.List; @@ -95,6 +96,7 @@ public void setup() { getRpcEncoding(), spec.getGenesisSchemaDefinitions().getSignedBeaconBlockSchema()); return new Eth2OutgoingRequestHandler<>( asyncRequestRunner, + timeoutRunner, method.getIds().get(0), responseDecoder, method.shouldReceiveResponse(), @@ -261,6 +263,33 @@ public void shouldWorkWhenSendAllChunksPlusEmptyExtraChunk() throws Exception { verify(rpcStream, never()).closeAbruptly(); } + @Test + public void disconnectsIfFirstChunkIsNotReceivedInTime() { + sendInitialPayload(); + + deliverInitialBytes(); + + // Run timeouts + timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis()); + timeoutRunner.executeDueActions(); + verify(rpcStream).closeAbruptly(); + } + + @Test + public void disconnectsIfSecondChunkNotReceivedInTime() { + sendInitialPayload(); + + timeProvider.advanceTimeByMillis(100); + deliverChunk(0); + asyncRequestRunner.executeQueuedActions(); + assertThat(blocks.size()).isEqualTo(1); + + // Run timeouts + timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis()); + timeoutRunner.executeDueActions(); + verify(rpcStream).closeAbruptly(); + } + @Test public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { sendInitialPayload(); @@ -276,6 +305,29 @@ public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { assertThat(finishedProcessingFuture).isCompletedExceptionally(); } + @Test + public void doNotDisconnectsIfSecondChunkReceivedInTime() { + sendInitialPayload(); + + timeProvider.advanceTimeByMillis(100); + deliverChunk(0); + asyncRequestRunner.executeQueuedActions(); + assertThat(blocks.size()).isEqualTo(1); + + // Second chunk is received just in time + timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis() - 1); + timeoutRunner.executeDueActions(); + deliverChunk(1); + asyncRequestRunner.executeQueuedActions(); + + // Go past the time the second chunk would have timed out but not enough to trigger timeout on + // the third chunk and ensure the timeout never fires. + timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis() - 1); + timeoutRunner.executeDueActions(); + verify(rpcStream, never()).closeAbruptly(); + assertThat(blocks.size()).isEqualTo(2); + } + @Test public void shouldWorkWhenInitialPayloadEventIsLate() throws Exception { deliverChunk(0); @@ -320,6 +372,11 @@ private void sendInitialPayload() { reqHandler.handleInitialPayloadSent(rpcStream); } + private void deliverInitialBytes() { + final Bytes firstByte = chunks.get(0).slice(0, 1); + deliverBytes(firstByte); + } + private Bytes chunkBytes(final int chunk) { final SignedBeaconBlock block = dataStructureUtil.randomSignedBeaconBlock(chunk); return responseEncoder.encodeSuccessfulResponse(block); diff --git a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java index c267ce583eb..4537560323e 100644 --- a/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java +++ b/networking/p2p/src/test/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandlerTest.java @@ -256,16 +256,16 @@ void requestIsThrottledIfQueueIsFull() { IntStream.range(0, maxConcurrentRequests) .forEach(__ -> rpcHandler.sendRequest(connection, request, responseHandler)); - final StreamPromise> streamPromise = + final StreamPromise> streamPromise1 = new StreamPromise<>(new CompletableFuture<>(), new CompletableFuture<>()); when(session.createStream((ProtocolBinding>) any())) - .thenReturn(streamPromise); - final Stream stream = mock(Stream.class); - streamPromise.getStream().complete(stream); - streamPromise.getController().complete(controller); - CompletableFuture protocolIdFuture = new CompletableFuture<>(); - when(stream.getProtocol()).thenReturn(protocolIdFuture); - protocolIdFuture.complete("test"); + .thenReturn(streamPromise1); + final Stream stream1 = mock(Stream.class); + streamPromise1.getStream().complete(stream1); + streamPromise1.getController().complete(controller); + final CompletableFuture protocolIdFuture1 = new CompletableFuture<>(); + when(stream1.getProtocol()).thenReturn(protocolIdFuture1); + protocolIdFuture1.complete("test"); final SafeFuture> throttledResult = rpcHandler.sendRequest(connection, request, responseHandler); @@ -273,9 +273,9 @@ void requestIsThrottledIfQueueIsFull() { assertThat(throttledResult).isNotDone(); // empty the queue - this.streamPromise.getStream().complete(stream); - this.streamPromise.getController().complete(controller); - this.stream.getProtocol().complete("test"); + streamPromise.getStream().complete(stream); + streamPromise.getController().complete(controller); + stream.getProtocol().complete("test"); writeFuture.complete(null); // throttled request should have completed now From 8ac8d3c1e3612f52910b8e660aa4abc64956d191 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Sat, 23 Nov 2024 18:33:09 +0000 Subject: [PATCH 12/23] fix assemble --- .../rpc/beaconchain/BeaconChainMethods.java | 24 +++++++------------ .../methods/SingleProtocolEth2RpcMethod.java | 6 +---- .../eth2/rpc/core/RpcDecoderTestBase.java | 3 +-- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java index 63ba993db5f..e6c78ad3a63 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java @@ -165,8 +165,7 @@ private static Eth2RpcMethod createStatus( true, contextCodec, statusHandler, - peerLookup, - spec.getNetworkingConfig()); + peerLookup); } private static Eth2RpcMethod createGoodBye( @@ -187,8 +186,7 @@ private static Eth2RpcMethod createGoodBye( false, contextCodec, goodbyeHandler, - peerLookup, - spec.getNetworkingConfig()); + peerLookup); } private static Eth2RpcMethod @@ -221,8 +219,7 @@ private static Eth2RpcMethod createGoodBye( expectResponseToRequest, forkDigestContextCodec, beaconBlocksByRootHandler, - peerLookup, - spec.getNetworkingConfig()); + peerLookup); return VersionedEth2RpcMethod.create( rpcEncoding, requestType, expectResponseToRequest, List.of(v2Method)); @@ -259,8 +256,7 @@ private static Eth2RpcMethod createGoodBye( expectResponseToRequest, forkDigestContextCodec, beaconBlocksByRangeHandler, - peerLookup, - spec.getNetworkingConfig()); + peerLookup); return VersionedEth2RpcMethod.create( rpcEncoding, requestType, expectResponseToRequest, List.of(v2Method)); @@ -299,8 +295,7 @@ private static Eth2RpcMethod createGoodBye( true, forkDigestContextCodec, blobSidecarsByRootHandler, - peerLookup, - spec.getNetworkingConfig())); + peerLookup)); } private static Optional> @@ -336,8 +331,7 @@ private static Eth2RpcMethod createGoodBye( true, forkDigestContextCodec, blobSidecarsByRangeHandler, - peerLookup, - spec.getNetworkingConfig())); + peerLookup)); } private static Eth2RpcMethod createMetadata( @@ -369,8 +363,7 @@ private static Eth2RpcMethod createMetadata( expectResponse, phase0ContextCodec, messageHandler, - peerLookup, - spec.getNetworkingConfig()); + peerLookup); if (spec.isMilestoneSupported(SpecMilestone.ALTAIR)) { final SszSchema altairMetadataSchema = @@ -419,8 +412,7 @@ private static Eth2RpcMethod createPing( true, contextCodec, statusHandler, - peerLookup, - spec.getNetworkingConfig()); + peerLookup); } public Collection> all() { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java index a961b2ec736..1c25f683d43 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java @@ -29,7 +29,6 @@ import tech.pegasys.teku.networking.eth2.rpc.core.RpcResponseEncoder; import tech.pegasys.teku.networking.eth2.rpc.core.encodings.RpcEncoding; import tech.pegasys.teku.networking.eth2.rpc.core.encodings.context.RpcContextCodec; -import tech.pegasys.teku.spec.config.NetworkingSpecConfig; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.RpcRequest; public class SingleProtocolEth2RpcMethod< @@ -45,7 +44,6 @@ public class SingleProtocolEth2RpcMethod< private final LocalMessageHandler localMessageHandler; private final PeerLookup peerLookup; - private final NetworkingSpecConfig networkingConfig; public SingleProtocolEth2RpcMethod( final AsyncRunner asyncRunner, @@ -56,8 +54,7 @@ public SingleProtocolEth2RpcMethod( final boolean expectResponseToRequest, final RpcContextCodec contextCodec, final LocalMessageHandler localMessageHandler, - final PeerLookup peerLookup, - final NetworkingSpecConfig networkingConfig) { + final PeerLookup peerLookup) { super(encoding, requestType, expectResponseToRequest); this.asyncRunner = asyncRunner; this.contextCodec = contextCodec; @@ -66,7 +63,6 @@ public SingleProtocolEth2RpcMethod( this.protocolVersion = protocolVersion; this.localMessageHandler = localMessageHandler; this.peerLookup = peerLookup; - this.networkingConfig = networkingConfig; } @Override diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcDecoderTestBase.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcDecoderTestBase.java index 30e54675f05..9f526c9c21b 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcDecoderTestBase.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/RpcDecoderTestBase.java @@ -78,8 +78,7 @@ public class RpcDecoderTestBase { false, contextEncoder, mock(LocalMessageHandler.class), - peerLookup, - spec.getNetworkingConfig()); + peerLookup); protected List> testByteBufSlices(final Bytes... bytes) { List> ret = Utils.generateTestSlices(bytes); From b3f57707daad95d61e96bef4d72b76cdf5a4734f Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Sat, 23 Nov 2024 18:35:00 +0000 Subject: [PATCH 13/23] fix assemble --- .../eth2/rpc/beaconchain/BeaconChainMethods.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java index e6c78ad3a63..75a4feed619 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/beaconchain/BeaconChainMethods.java @@ -115,8 +115,8 @@ public static BeaconChainMethods create( final MetadataMessagesFactory metadataMessagesFactory, final RpcEncoding rpcEncoding) { return new BeaconChainMethods( - createStatus(spec, asyncRunner, statusMessageFactory, peerLookup, rpcEncoding), - createGoodBye(spec, asyncRunner, metricsSystem, peerLookup, rpcEncoding), + createStatus(asyncRunner, statusMessageFactory, peerLookup, rpcEncoding), + createGoodBye(asyncRunner, metricsSystem, peerLookup, rpcEncoding), createBeaconBlocksByRoot( spec, metricsSystem, asyncRunner, recentChainData, peerLookup, rpcEncoding), createBeaconBlocksByRange( @@ -144,11 +144,10 @@ public static BeaconChainMethods create( rpcEncoding, recentChainData), createMetadata(spec, asyncRunner, metadataMessagesFactory, peerLookup, rpcEncoding), - createPing(spec, asyncRunner, metadataMessagesFactory, peerLookup, rpcEncoding)); + createPing(asyncRunner, metadataMessagesFactory, peerLookup, rpcEncoding)); } private static Eth2RpcMethod createStatus( - final Spec spec, final AsyncRunner asyncRunner, final StatusMessageFactory statusMessageFactory, final PeerLookup peerLookup, @@ -169,7 +168,6 @@ private static Eth2RpcMethod createStatus( } private static Eth2RpcMethod createGoodBye( - final Spec spec, final AsyncRunner asyncRunner, final MetricsSystem metricsSystem, final PeerLookup peerLookup, @@ -385,8 +383,7 @@ private static Eth2RpcMethod createMetadata( expectResponse, altairContextCodec, messageHandler, - peerLookup, - spec.getNetworkingConfig()); + peerLookup); return VersionedEth2RpcMethod.create( rpcEncoding, requestType, expectResponse, List.of(v2Method, v1Method)); } else { @@ -395,7 +392,6 @@ private static Eth2RpcMethod createMetadata( } private static Eth2RpcMethod createPing( - final Spec spec, final AsyncRunner asyncRunner, final MetadataMessagesFactory metadataMessagesFactory, final PeerLookup peerLookup, From d78817a8964053af9ecaad3c85b347091233e6ac Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Sat, 23 Nov 2024 19:02:29 +0000 Subject: [PATCH 14/23] Fix assemble --- .../pegasys/teku/spec/config/Constants.java | 3 - .../rpc/core/Eth2IncomingRequestHandler.java | 8 +- .../rpc/core/Eth2OutgoingRequestHandler.java | 84 +++---------------- .../methods/SingleProtocolEth2RpcMethod.java | 1 - .../core/Eth2OutgoingRequestHandlerTest.java | 52 ------------ 5 files changed, 16 insertions(+), 132 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java index 49d350f854e..e9c7a6498e8 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java @@ -21,9 +21,6 @@ public class Constants { public static final int ATTESTATION_SUBNET_COUNT = 64; // Teku Networking Specific - // Global RPC timeout for reading an incoming request or for receiving a response chunk after - // initiating a request - public static final Duration RPC_TIMEOUT = Duration.ofSeconds(10); public static final int VALID_BLOCK_SET_SIZE = 1000; // Target holding two slots worth of aggregators (16 aggregators, 64 committees and 2 slots) public static final int VALID_AGGREGATE_SET_SIZE = 16 * 64 * 2; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java index f1e38849d82..2a1bce8e6f3 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2IncomingRequestHandler.java @@ -13,10 +13,9 @@ package tech.pegasys.teku.networking.eth2.rpc.core; -import static tech.pegasys.teku.spec.config.Constants.RPC_TIMEOUT; - import com.google.common.annotations.VisibleForTesting; import io.netty.buffer.ByteBuf; +import java.time.Duration; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.logging.log4j.LogManager; @@ -35,6 +34,7 @@ public class Eth2IncomingRequestHandler< TRequest extends RpcRequest & SszData, TResponse extends SszData> implements RpcRequestHandler { private static final Logger LOG = LogManager.getLogger(); + private static final Duration RECEIVE_INCOMING_REQUEST_TIMEOUT = Duration.ofSeconds(10); private final PeerLookup peerLookup; private final LocalMessageHandler localMessageHandler; @@ -119,13 +119,13 @@ private void handleRequest( private void ensureRequestReceivedWithinTimeLimit(final RpcStream stream) { asyncRunner - .getDelayedFuture(RPC_TIMEOUT) + .getDelayedFuture(RECEIVE_INCOMING_REQUEST_TIMEOUT) .thenAccept( (__) -> { if (!requestHandled.get()) { LOG.debug( "Failed to receive incoming request data within {} sec for protocol {}. Close stream.", - RPC_TIMEOUT.toSeconds(), + RECEIVE_INCOMING_REQUEST_TIMEOUT.toSeconds(), protocolId); stream.closeAbruptly().ifExceptionGetsHereRaiseABug(); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java index 58811a403d6..f2d36ae6467 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java @@ -18,13 +18,12 @@ import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.State.DATA_COMPLETED; import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.State.EXPECT_DATA; import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.State.READ_COMPLETE; -import static tech.pegasys.teku.spec.config.Constants.RPC_TIMEOUT; import com.google.common.annotations.VisibleForTesting; import io.netty.buffer.ByteBuf; import java.util.Collection; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; @@ -55,12 +54,10 @@ enum State { private static final Logger LOG = LogManager.getLogger(); private final AsyncRunner asyncRunner; - private final AsyncRunner timeoutRunner; private final int maximumResponseChunks; private final Eth2RpcResponseHandler responseHandler; private final ResponseStream responseStream; - private final AtomicBoolean hasReceivedInitialBytes = new AtomicBoolean(false); private final AtomicInteger currentChunkCount = new AtomicInteger(0); private final AtomicReference state; private final AtomicReference> responseProcessor = @@ -68,23 +65,19 @@ enum State { private final String protocolId; private final RpcResponseDecoder responseDecoder; - private final boolean shouldReceiveResponse; public Eth2OutgoingRequestHandler( final AsyncRunner asyncRunner, - final AsyncRunner timeoutRunner, final String protocolId, final RpcResponseDecoder responseDecoder, final boolean shouldReceiveResponse, final TRequest request, final Eth2RpcResponseHandler responseHandler) { this.asyncRunner = asyncRunner; - this.timeoutRunner = timeoutRunner; this.maximumResponseChunks = request.getMaximumResponseChunks(); this.responseHandler = responseHandler; responseStream = new ResponseStream<>(responseHandler); this.responseDecoder = responseDecoder; - this.shouldReceiveResponse = shouldReceiveResponse; this.protocolId = protocolId; this.state = new AtomicReference<>(shouldReceiveResponse ? EXPECT_DATA : DATA_COMPLETED); } @@ -92,9 +85,6 @@ public Eth2OutgoingRequestHandler( public void handleInitialPayloadSent(final RpcStream stream) { // Close the write side of the stream stream.closeWriteStream().ifExceptionGetsHereRaiseABug(); - if (!shouldReceiveResponse) { - ensureReadCompleteArrivesInTime(stream); - } } @Override @@ -111,8 +101,6 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By throw new RpcException.ExtraDataAppendedException(" extra data: " + bufToString(data)); } - onFirstByteReceived(rpcStream); - List maybeResponses = responseDecoder.decodeNextResponses(data); final int chunksReceived = currentChunkCount.addAndGet(maybeResponses.size()); @@ -123,16 +111,9 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By for (TResponse maybeResponse : maybeResponses) { getResponseProcessor(rpcStream).processResponse(maybeResponse); } - if (chunksReceived < maximumResponseChunks) { - if (!maybeResponses.isEmpty()) { - ensureNextResponseChunkArrivesInTime(rpcStream, chunksReceived, currentChunkCount); - } - } else { - if (!transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { - abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); - return; - } - ensureReadCompleteArrivesInTime(rpcStream); + if (chunksReceived >= maximumResponseChunks + && !transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { + abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); } } catch (final RpcException e) { abortRequest(rpcStream, e); @@ -144,14 +125,14 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By private AsyncResponseProcessor getResponseProcessor(final RpcStream rpcStream) { return responseProcessor.updateAndGet( - oldVal -> { - if (oldVal == null) { - return new AsyncResponseProcessor<>( - asyncRunner, responseStream, throwable -> abortRequest(rpcStream, throwable)); - } else { - return oldVal; - } - }); + oldVal -> + Objects.requireNonNullElseGet( + oldVal, + () -> + new AsyncResponseProcessor<>( + asyncRunner, + responseStream, + throwable -> abortRequest(rpcStream, throwable)))); } private String bufToString(final ByteBuf buf) { @@ -204,13 +185,6 @@ private boolean transferToState(final State toState, final Collection fro return false; } - private void onFirstByteReceived(final RpcStream rpcStream) { - if (hasReceivedInitialBytes.compareAndSet(false, true)) { - // Setup initial chunk timeout - ensureNextResponseChunkArrivesInTime(rpcStream, currentChunkCount.get(), currentChunkCount); - } - } - private void completeRequest(final RpcStream rpcStream) { getResponseProcessor(rpcStream) .finishProcessing() @@ -254,40 +228,6 @@ private void abortRequest(final RpcStream rpcStream, final Throwable error, fina } } - private void ensureNextResponseChunkArrivesInTime( - final RpcStream stream, - final int previousResponseCount, - final AtomicInteger currentResponseCount) { - timeoutRunner - .getDelayedFuture(RPC_TIMEOUT) - .thenAccept( - (__) -> { - if (previousResponseCount == currentResponseCount.get()) { - abortRequest( - stream, - new RpcTimeoutException( - "Timed out waiting for response chunk " + previousResponseCount, - RPC_TIMEOUT)); - } - }) - .ifExceptionGetsHereRaiseABug(); - } - - private void ensureReadCompleteArrivesInTime(final RpcStream stream) { - timeoutRunner - .getDelayedFuture(RPC_TIMEOUT) - .thenAccept( - (__) -> { - if (!(state.get() == READ_COMPLETE || state.get() == CLOSED)) { - abortRequest( - stream, - new RpcTimeoutException( - "Timed out waiting for read channel close", RPC_TIMEOUT)); - } - }) - .ifExceptionGetsHereRaiseABug(); - } - @VisibleForTesting State getState() { return state.get(); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java index 1c25f683d43..fabbd95de46 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java @@ -96,7 +96,6 @@ public Eth2OutgoingRequestHandler createOutgoingRequestHand final TRequest request, final Eth2RpcResponseHandler responseHandler) { return new Eth2OutgoingRequestHandler<>( - asyncRunner, asyncRunner, protocolId, createResponseDecoder(), diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java index a08132a9601..620f7c9ee65 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java @@ -18,7 +18,6 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static tech.pegasys.teku.spec.config.Constants.RPC_TIMEOUT; import java.util.ArrayList; import java.util.List; @@ -96,7 +95,6 @@ public void setup() { getRpcEncoding(), spec.getGenesisSchemaDefinitions().getSignedBeaconBlockSchema()); return new Eth2OutgoingRequestHandler<>( asyncRequestRunner, - timeoutRunner, method.getIds().get(0), responseDecoder, method.shouldReceiveResponse(), @@ -263,33 +261,6 @@ public void shouldWorkWhenSendAllChunksPlusEmptyExtraChunk() throws Exception { verify(rpcStream, never()).closeAbruptly(); } - @Test - public void disconnectsIfFirstChunkIsNotReceivedInTime() { - sendInitialPayload(); - - deliverInitialBytes(); - - // Run timeouts - timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis()); - timeoutRunner.executeDueActions(); - verify(rpcStream).closeAbruptly(); - } - - @Test - public void disconnectsIfSecondChunkNotReceivedInTime() { - sendInitialPayload(); - - timeProvider.advanceTimeByMillis(100); - deliverChunk(0); - asyncRequestRunner.executeQueuedActions(); - assertThat(blocks.size()).isEqualTo(1); - - // Run timeouts - timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis()); - timeoutRunner.executeDueActions(); - verify(rpcStream).closeAbruptly(); - } - @Test public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { sendInitialPayload(); @@ -305,29 +276,6 @@ public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { assertThat(finishedProcessingFuture).isCompletedExceptionally(); } - @Test - public void doNotDisconnectsIfSecondChunkReceivedInTime() { - sendInitialPayload(); - - timeProvider.advanceTimeByMillis(100); - deliverChunk(0); - asyncRequestRunner.executeQueuedActions(); - assertThat(blocks.size()).isEqualTo(1); - - // Second chunk is received just in time - timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis() - 1); - timeoutRunner.executeDueActions(); - deliverChunk(1); - asyncRequestRunner.executeQueuedActions(); - - // Go past the time the second chunk would have timed out but not enough to trigger timeout on - // the third chunk and ensure the timeout never fires. - timeProvider.advanceTimeByMillis(RPC_TIMEOUT.toMillis() - 1); - timeoutRunner.executeDueActions(); - verify(rpcStream, never()).closeAbruptly(); - assertThat(blocks.size()).isEqualTo(2); - } - @Test public void shouldWorkWhenInitialPayloadEventIsLate() throws Exception { deliverChunk(0); From 81058426744bb0f377acd1c1610d99de6eb7cdba Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Sun, 24 Nov 2024 10:37:59 +0000 Subject: [PATCH 15/23] fix assemble again --- .../eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java index 620f7c9ee65..9180942c32f 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java @@ -320,11 +320,6 @@ private void sendInitialPayload() { reqHandler.handleInitialPayloadSent(rpcStream); } - private void deliverInitialBytes() { - final Bytes firstByte = chunks.get(0).slice(0, 1); - deliverBytes(firstByte); - } - private Bytes chunkBytes(final int chunk) { final SignedBeaconBlock block = dataStructureUtil.randomSignedBeaconBlock(chunk); return responseEncoder.encodeSuccessfulResponse(block); From f40377a20fadda5c7ccd76d97b8adb2e8590cae7 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Mon, 25 Nov 2024 14:43:50 +0000 Subject: [PATCH 16/23] reintroduce timeouts --- .../rpc/core/Eth2OutgoingRequestHandler.java | 62 +++++++++++++- .../methods/SingleProtocolEth2RpcMethod.java | 1 + .../core/Eth2OutgoingRequestHandlerTest.java | 81 +++++++++++++++++++ .../networking/p2p/libp2p/rpc/RpcHandler.java | 5 +- 4 files changed, 144 insertions(+), 5 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java index f2d36ae6467..320a5a3f943 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandler.java @@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting; import io.netty.buffer.ByteBuf; +import java.time.Duration; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -53,11 +54,15 @@ enum State { private static final Logger LOG = LogManager.getLogger(); + @VisibleForTesting static final Duration READ_COMPLETE_TIMEOUT = Duration.ofSeconds(10); + @VisibleForTesting static final Duration RESPONSE_CHUNK_ARRIVAL_TIMEOUT = Duration.ofSeconds(30); + private final AsyncRunner asyncRunner; private final int maximumResponseChunks; private final Eth2RpcResponseHandler responseHandler; private final ResponseStream responseStream; + private final AsyncRunner timeoutRunner; private final AtomicInteger currentChunkCount = new AtomicInteger(0); private final AtomicReference state; private final AtomicReference> responseProcessor = @@ -65,19 +70,23 @@ enum State { private final String protocolId; private final RpcResponseDecoder responseDecoder; + private final boolean shouldReceiveResponse; public Eth2OutgoingRequestHandler( final AsyncRunner asyncRunner, + final AsyncRunner timeoutRunner, final String protocolId, final RpcResponseDecoder responseDecoder, final boolean shouldReceiveResponse, final TRequest request, final Eth2RpcResponseHandler responseHandler) { this.asyncRunner = asyncRunner; + this.timeoutRunner = timeoutRunner; this.maximumResponseChunks = request.getMaximumResponseChunks(); this.responseHandler = responseHandler; responseStream = new ResponseStream<>(responseHandler); this.responseDecoder = responseDecoder; + this.shouldReceiveResponse = shouldReceiveResponse; this.protocolId = protocolId; this.state = new AtomicReference<>(shouldReceiveResponse ? EXPECT_DATA : DATA_COMPLETED); } @@ -85,6 +94,12 @@ public Eth2OutgoingRequestHandler( public void handleInitialPayloadSent(final RpcStream stream) { // Close the write side of the stream stream.closeWriteStream().ifExceptionGetsHereRaiseABug(); + if (shouldReceiveResponse) { + // Setup initial chunk timeout + ensureNextResponseChunkArrivesInTime(stream, currentChunkCount.get(), currentChunkCount); + } else { + ensureReadCompleteArrivesInTime(stream); + } } @Override @@ -111,9 +126,16 @@ public void processData(final NodeId nodeId, final RpcStream rpcStream, final By for (TResponse maybeResponse : maybeResponses) { getResponseProcessor(rpcStream).processResponse(maybeResponse); } - if (chunksReceived >= maximumResponseChunks - && !transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { - abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); + if (chunksReceived < maximumResponseChunks) { + if (!maybeResponses.isEmpty()) { + ensureNextResponseChunkArrivesInTime(rpcStream, chunksReceived, currentChunkCount); + } + } else { + if (!transferToState(DATA_COMPLETED, List.of(EXPECT_DATA))) { + abortRequest(rpcStream, new IllegalStateException("Unexpected state: " + state)); + return; + } + ensureReadCompleteArrivesInTime(rpcStream); } } catch (final RpcException e) { abortRequest(rpcStream, e); @@ -228,6 +250,40 @@ private void abortRequest(final RpcStream rpcStream, final Throwable error, fina } } + private void ensureNextResponseChunkArrivesInTime( + final RpcStream stream, + final int previousResponseCount, + final AtomicInteger currentResponseCount) { + timeoutRunner + .getDelayedFuture(RESPONSE_CHUNK_ARRIVAL_TIMEOUT) + .thenAccept( + (__) -> { + if (previousResponseCount == currentResponseCount.get()) { + abortRequest( + stream, + new RpcTimeoutException( + "Timed out waiting for response chunk " + previousResponseCount, + RESPONSE_CHUNK_ARRIVAL_TIMEOUT)); + } + }) + .ifExceptionGetsHereRaiseABug(); + } + + private void ensureReadCompleteArrivesInTime(final RpcStream stream) { + timeoutRunner + .getDelayedFuture(READ_COMPLETE_TIMEOUT) + .thenAccept( + (__) -> { + if (!(state.get() == READ_COMPLETE || state.get() == CLOSED)) { + abortRequest( + stream, + new RpcTimeoutException( + "Timed out waiting for read channel close", READ_COMPLETE_TIMEOUT)); + } + }) + .ifExceptionGetsHereRaiseABug(); + } + @VisibleForTesting State getState() { return state.get(); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java index fabbd95de46..1c25f683d43 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/rpc/core/methods/SingleProtocolEth2RpcMethod.java @@ -96,6 +96,7 @@ public Eth2OutgoingRequestHandler createOutgoingRequestHand final TRequest request, final Eth2RpcResponseHandler responseHandler) { return new Eth2OutgoingRequestHandler<>( + asyncRunner, asyncRunner, protocolId, createResponseDecoder(), diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java index 9180942c32f..5dd08fe79f5 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/rpc/core/Eth2OutgoingRequestHandlerTest.java @@ -18,6 +18,8 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.READ_COMPLETE_TIMEOUT; +import static tech.pegasys.teku.networking.eth2.rpc.core.Eth2OutgoingRequestHandler.RESPONSE_CHUNK_ARRIVAL_TIMEOUT; import java.util.ArrayList; import java.util.List; @@ -95,6 +97,7 @@ public void setup() { getRpcEncoding(), spec.getGenesisSchemaDefinitions().getSignedBeaconBlockSchema()); return new Eth2OutgoingRequestHandler<>( asyncRequestRunner, + timeoutRunner, method.getIds().get(0), responseDecoder, method.shouldReceiveResponse(), @@ -261,6 +264,61 @@ public void shouldWorkWhenSendAllChunksPlusEmptyExtraChunk() throws Exception { verify(rpcStream, never()).closeAbruptly(); } + @Test + public void disconnectsIfFirstChunkIsNotReceivedInTime() { + sendInitialPayload(); + + // Run timeouts + timeProvider.advanceTimeByMillis(RESPONSE_CHUNK_ARRIVAL_TIMEOUT.toMillis()); + timeoutRunner.executeDueActions(); + verify(rpcStream).closeAbruptly(); + } + + @Test + public void doNotDisconnectsIfFirstChunkReceivedInTime() { + sendInitialPayload(); + + deliverChunk(0); + + // Go past the time the first chunk would have timed out but not enough to trigger timeout on + // the second chunk and ensure the timeout never fires. + timeProvider.advanceTimeByMillis(RESPONSE_CHUNK_ARRIVAL_TIMEOUT.toMillis() - 1); + timeoutRunner.executeDueActions(); + verify(rpcStream, never()).closeAbruptly(); + } + + @Test + public void disconnectsIfSecondChunkNotReceivedInTime() { + sendInitialPayload(); + + timeProvider.advanceTimeByMillis(100); + deliverChunk(0); + asyncRequestRunner.executeQueuedActions(); + assertThat(blocks.size()).isEqualTo(1); + + // Run timeouts + timeProvider.advanceTimeByMillis(RESPONSE_CHUNK_ARRIVAL_TIMEOUT.toMillis()); + timeoutRunner.executeDueActions(); + verify(rpcStream).closeAbruptly(); + } + + @Test + public void abortsWhenNoReadComplete() { + sendInitialPayload(); + + timeProvider.advanceTimeByMillis(100); + for (int i = 0; i < maxChunks; i++) { + deliverChunk(i); + } + + asyncRequestRunner.executeQueuedActions(); + + // Run timeouts + timeProvider.advanceTimeByMillis(READ_COMPLETE_TIMEOUT.toMillis()); + timeoutRunner.executeDueActions(); + verify(rpcStream).closeAbruptly(); + } + @Test public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { sendInitialPayload(); @@ -276,6 +334,29 @@ public void shouldCompleteExceptionallyWhenClosedWithTruncatedMessage() { assertThat(finishedProcessingFuture).isCompletedExceptionally(); } + @Test + public void doNotDisconnectsIfSecondChunkReceivedInTime() { + sendInitialPayload(); + + timeProvider.advanceTimeByMillis(100); + deliverChunk(0); + asyncRequestRunner.executeQueuedActions(); + assertThat(blocks.size()).isEqualTo(1); + + // Second chunk is received just in time + timeProvider.advanceTimeByMillis(RESPONSE_CHUNK_ARRIVAL_TIMEOUT.toMillis() - 1); + timeoutRunner.executeDueActions(); + deliverChunk(1); + asyncRequestRunner.executeQueuedActions(); + + // Go past the time the second chunk would have timed out but not enough to trigger timeout on + // the third chunk and ensure the timeout never fires. + timeProvider.advanceTimeByMillis(RESPONSE_CHUNK_ARRIVAL_TIMEOUT.toMillis() - 1); + timeoutRunner.executeDueActions(); + verify(rpcStream, never()).closeAbruptly(); + assertThat(blocks.size()).isEqualTo(2); + } + @Test public void shouldWorkWhenInitialPayloadEventIsLate() throws Exception { deliverChunk(0); diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java index 4acf69d73df..f5f85af3c22 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/rpc/RpcHandler.java @@ -57,9 +57,10 @@ public class RpcHandler< TRequest, TRespHandler extends RpcResponseHandler> implements ProtocolBinding> { - private static final Duration TIMEOUT = Duration.ofSeconds(5); private static final Logger LOG = LogManager.getLogger(); + private static final Duration STREAM_INITIALIZE_TIMEOUT = Duration.ofSeconds(5); + private final AsyncRunner asyncRunner; private final RpcMethod rpcMethod; private final ThrottlingTaskQueue concurrentRequestsQueue; @@ -97,7 +98,7 @@ public SafeFuture> sendRequestInternal( SafeFuture.createInterruptor(connection.closeFuture(), PeerDisconnectedException::new); final Interruptor timeoutInterruptor = SafeFuture.createInterruptor( - asyncRunner.getDelayedFuture(TIMEOUT), + asyncRunner.getDelayedFuture(STREAM_INITIALIZE_TIMEOUT), () -> new StreamTimeoutException( "Timed out waiting to initialize stream for protocol(s): " From e2b1d47414bbc3e60a56215240185ec1b0a7079d Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Mon, 25 Nov 2024 15:07:46 +0000 Subject: [PATCH 17/23] Change to constant --- .../pegasys/teku/networks/test-constants.yaml | 3 +- .../spec/config/DelegatingSpecConfig.java | 15 --------- .../spec/config/NetworkingSpecConfig.java | 8 ----- .../teku/spec/config/SpecConfigPhase0.java | 32 +------------------ .../teku/spec/config/SpecConfigReader.java | 4 ++- .../config/builder/SpecConfigBuilder.java | 24 -------------- .../teku/spec/constants/NetworkConstants.java | 3 ++ .../teku/spec/config/configs/chiado.yaml | 1 - .../teku/spec/config/configs/ephemery.yaml | 1 - .../teku/spec/config/configs/gnosis.yaml | 1 - .../teku/spec/config/configs/holesky.yaml | 1 - .../teku/spec/config/configs/less-swift.yaml | 1 - .../teku/spec/config/configs/lukso.yaml | 1 - .../teku/spec/config/configs/mainnet.yaml | 1 - .../teku/spec/config/configs/minimal.yaml | 1 - .../teku/spec/config/configs/sepolia.yaml | 1 - .../teku/spec/config/configs/swift.yaml | 1 - .../config/invalid/missingAltairField.yaml | 3 +- .../spec/config/invalid/unknownField.yaml | 3 +- .../spec/config/standard/with-overrides.yaml | 3 +- .../eth2/peers/Eth2PeerManager.java | 7 ++-- .../p2p/libp2p/LibP2PNetworkBuilder.java | 3 +- .../teku/cli/subcommand/test-spec.yaml | 3 +- .../pegasys/teku/cli/options/constants.yaml | 3 +- .../teku/cli/subcommand/deneb_config.yaml | 1 - 25 files changed, 18 insertions(+), 107 deletions(-) diff --git a/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml b/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml index 6aab2696a57..17f311def58 100644 --- a/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml +++ b/ethereum/networks/src/test/resources/tech/pegasys/teku/networks/test-constants.yaml @@ -180,5 +180,4 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java index 2829a5d0575..403dae93aba 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java @@ -327,16 +327,6 @@ public int getMaxChunkSize() { return specConfig.getMaxChunkSize(); } - @Override - public int getTtfbTimeout() { - return specConfig.getTtfbTimeout(); - } - - @Override - public int getRespTimeout() { - return specConfig.getRespTimeout(); - } - @Override public int getAttestationPropagationSlotRange() { return specConfig.getAttestationPropagationSlotRange(); @@ -392,11 +382,6 @@ public int getAttestationSubnetPrefixBits() { return specConfig.getAttestationSubnetPrefixBits(); } - @Override - public int getMaxConcurrentRequests() { - return specConfig.getMaxConcurrentRequests(); - } - @Override public int getProposerScoreBoost() { return specConfig.getProposerScoreBoost(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java index f368253c989..a41f0d5f920 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java @@ -27,12 +27,6 @@ public interface NetworkingSpecConfig { int getMinEpochsForBlockRequests(); - // in seconds - int getTtfbTimeout(); - - // in seconds - int getRespTimeout(); - int getAttestationPropagationSlotRange(); // in millis @@ -54,8 +48,6 @@ public interface NetworkingSpecConfig { // int(ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS) int getAttestationSubnetPrefixBits(); - int getMaxConcurrentRequests(); - default NetworkingSpecConfig getNetworkingConfig() { return this; } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java index 57f19ccc2bb..52654dfdd29 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java @@ -107,8 +107,6 @@ public class SpecConfigPhase0 implements SpecConfig { private final int maxRequestBlocks; private final int epochsPerSubnetSubscription; private final int minEpochsForBlockRequests; - private final int ttfbTimeout; - private final int respTimeout; private final int attestationPropagationSlotRange; private final int maximumGossipClockDisparity; private final Bytes4 messageDomainInvalidSnappy; @@ -117,7 +115,6 @@ public class SpecConfigPhase0 implements SpecConfig { private final int attestationSubnetCount; private final int attestationSubnetExtraBits; private final int attestationSubnetPrefixBits; - private final int maxConcurrentRequests; private final int reorgMaxEpochsSinceFinalization; private final int reorgHeadWeightThreshold; private final int reorgParentWeightThreshold; @@ -180,8 +177,6 @@ public SpecConfigPhase0( final int maxRequestBlocks, final int epochsPerSubnetSubscription, final int minEpochsForBlockRequests, - final int ttfbTimeout, - final int respTimeout, final int attestationPropagationSlotRange, final int maximumGossipClockDisparity, final Bytes4 messageDomainInvalidSnappy, @@ -190,7 +185,6 @@ public SpecConfigPhase0( final int attestationSubnetCount, final int attestationSubnetExtraBits, final int attestationSubnetPrefixBits, - final int maxConcurrentRequests, final int reorgMaxEpochsSinceFinalization, final int reorgHeadWeightThreshold, final int reorgParentWeightThreshold, @@ -251,8 +245,6 @@ public SpecConfigPhase0( this.maxRequestBlocks = maxRequestBlocks; this.epochsPerSubnetSubscription = epochsPerSubnetSubscription; this.minEpochsForBlockRequests = minEpochsForBlockRequests; - this.ttfbTimeout = ttfbTimeout; - this.respTimeout = respTimeout; this.attestationPropagationSlotRange = attestationPropagationSlotRange; this.maximumGossipClockDisparity = maximumGossipClockDisparity; this.messageDomainInvalidSnappy = messageDomainInvalidSnappy; @@ -261,7 +253,6 @@ public SpecConfigPhase0( this.attestationSubnetCount = attestationSubnetCount; this.attestationSubnetExtraBits = attestationSubnetExtraBits; this.attestationSubnetPrefixBits = attestationSubnetPrefixBits; - this.maxConcurrentRequests = maxConcurrentRequests; this.reorgMaxEpochsSinceFinalization = reorgMaxEpochsSinceFinalization; this.reorgHeadWeightThreshold = reorgHeadWeightThreshold; this.reorgParentWeightThreshold = reorgParentWeightThreshold; @@ -588,16 +579,6 @@ public int getMinEpochsForBlockRequests() { return minEpochsForBlockRequests; } - @Override - public int getTtfbTimeout() { - return ttfbTimeout; - } - - @Override - public int getRespTimeout() { - return respTimeout; - } - @Override public int getAttestationPropagationSlotRange() { return attestationPropagationSlotRange; @@ -638,11 +619,6 @@ public int getAttestationSubnetPrefixBits() { return attestationSubnetPrefixBits; } - @Override - public int getMaxConcurrentRequests() { - return maxConcurrentRequests; - } - @Override public SpecMilestone getMilestone() { return SpecMilestone.PHASE0; @@ -699,9 +675,6 @@ public boolean equals(final Object o) { && attestationSubnetCount == that.attestationSubnetCount && attestationSubnetExtraBits == that.attestationSubnetExtraBits && attestationSubnetPrefixBits == that.attestationSubnetPrefixBits - && maxConcurrentRequests == that.maxConcurrentRequests - && ttfbTimeout == that.ttfbTimeout - && respTimeout == that.respTimeout && attestationPropagationSlotRange == that.attestationPropagationSlotRange && maximumGossipClockDisparity == that.maximumGossipClockDisparity && Objects.equals(eth1FollowDistance, that.eth1FollowDistance) @@ -781,8 +754,6 @@ public int hashCode() { maxChunkSize, maxRequestBlocks, epochsPerSubnetSubscription, - ttfbTimeout, - respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -790,7 +761,6 @@ public int hashCode() { subnetsPerNode, attestationSubnetCount, attestationSubnetExtraBits, - attestationSubnetPrefixBits, - maxConcurrentRequests); + attestationSubnetPrefixBits); } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java index f48941998bd..eae0fbe2d56 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java @@ -70,7 +70,9 @@ public class SpecConfigReader { "TRANSITION_TOTAL_DIFFICULTY", // Deprecated fields "GOSSIP_MAX_SIZE_BELLATRIX", - "MAX_CHUNK_SIZE_BELLATRIX"); + "MAX_CHUNK_SIZE_BELLATRIX", + "TTFB_TIMEOUT", + "RESP_TIMEOUT"); private static final ImmutableSet CONSTANT_KEYS = ImmutableSet.of( // Phase0 constants which may exist in legacy config files, but should now be ignored diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java index 2a0ce2ded10..e731ec925fe 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java @@ -112,8 +112,6 @@ public class SpecConfigBuilder { private Integer maxChunkSize; private Integer maxRequestBlocks; private Integer epochsPerSubnetSubscription; - private Integer ttfbTimeout; - private Integer respTimeout; private Integer attestationPropagationSlotRange; private Integer maximumGossipClockDisparity; private Bytes4 messageDomainInvalidSnappy; @@ -123,7 +121,6 @@ public class SpecConfigBuilder { private Integer attestationSubnetCount; private Integer attestationSubnetExtraBits; private Integer attestationSubnetPrefixBits; - private Integer maxConcurrentRequests; // added after Phase0, so add default values, or will be compatibility issue private Integer reorgMaxEpochsSinceFinalization = 2; @@ -206,8 +203,6 @@ public SpecConfigAndParent build() { maxRequestBlocks, epochsPerSubnetSubscription, minEpochsForBlockRequests, - ttfbTimeout, - respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -216,7 +211,6 @@ public SpecConfigAndParent build() { attestationSubnetCount, attestationSubnetExtraBits, attestationSubnetPrefixBits, - maxConcurrentRequests, reorgMaxEpochsSinceFinalization, reorgHeadWeightThreshold, reorgParentWeightThreshold, @@ -281,8 +275,6 @@ private Map getValidationMap() { constants.put("maxRequestBlocks", maxRequestBlocks); constants.put("epochsPerSubnetSubscription", epochsPerSubnetSubscription); constants.put("minEpochsForBlockRequests", minEpochsForBlockRequests); - constants.put("ttfbTimeout", ttfbTimeout); - constants.put("respTimeout", respTimeout); constants.put("attestationPropagationSlotRange", attestationPropagationSlotRange); constants.put("maximumGossipClockDisparity", maximumGossipClockDisparity); constants.put("messageDomainInvalidSnappy", messageDomainInvalidSnappy); @@ -291,7 +283,6 @@ private Map getValidationMap() { constants.put("attestationSubnetCount", attestationSubnetCount); constants.put("attestationSubnetExtraBits", attestationSubnetExtraBits); constants.put("attestationSubnetPrefixBits", attestationSubnetPrefixBits); - constants.put("maxConcurrentRequests", maxConcurrentRequests); constants.put("reorgMaxEpochsSinceFinalization", reorgMaxEpochsSinceFinalization); constants.put("reorgHeadWeightThreshold", reorgHeadWeightThreshold); constants.put("reorgParentWeightThreshold", reorgParentWeightThreshold); @@ -654,16 +645,6 @@ public SpecConfigBuilder minEpochsForBlockRequests(final Integer minEpochsForBlo return this; } - public SpecConfigBuilder ttfbTimeout(final Integer ttfbTimeout) { - this.ttfbTimeout = ttfbTimeout; - return this; - } - - public SpecConfigBuilder respTimeout(final Integer respTimeout) { - this.respTimeout = respTimeout; - return this; - } - public SpecConfigBuilder attestationPropagationSlotRange( final Integer attestationPropagationSlotRange) { this.attestationPropagationSlotRange = attestationPropagationSlotRange; @@ -705,11 +686,6 @@ public SpecConfigBuilder attestationSubnetPrefixBits(final Integer attestationSu return this; } - public SpecConfigBuilder maxConcurrentRequests(final Integer maxConcurrentRequests) { - this.maxConcurrentRequests = maxConcurrentRequests; - return this; - } - public SpecConfigBuilder reorgMaxEpochsSinceFinalization( final Integer reorgMaxEpochsSinceFinalization) { this.reorgMaxEpochsSinceFinalization = reorgMaxEpochsSinceFinalization; diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/NetworkConstants.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/NetworkConstants.java index 2bbbf82f076..ff7e0c1d390 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/NetworkConstants.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/NetworkConstants.java @@ -20,4 +20,7 @@ public class NetworkConstants { public static final int DEFAULT_SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY = 128; public static final int NODE_ID_BITS = 256; + + // https://github.com/ethereum/consensus-specs/pull/3767 + public static final int MAX_CONCURRENT_REQUESTS = 2; } diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml index 7848b3a8187..7ba59a19848 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/chiado.yaml @@ -124,7 +124,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml index 7de2db53508..0b3f87844d2 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/ephemery.yaml @@ -113,7 +113,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml index b4f7814fcc0..c7600b8648a 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/gnosis.yaml @@ -123,7 +123,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml index 6d341cc89ea..58f913a4f54 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/holesky.yaml @@ -115,7 +115,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml index a8ab2dcaeac..6adebb9c009 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/less-swift.yaml @@ -126,7 +126,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml index 61cda0f6bc7..47ad8fa06a4 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/lukso.yaml @@ -145,7 +145,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml index ec008d90f04..3c831ba06eb 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/mainnet.yaml @@ -132,7 +132,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml index 9baa81d7170..1a6ea3507fa 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/minimal.yaml @@ -132,7 +132,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml index 729baecd8cb..f00e64693b0 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/sepolia.yaml @@ -108,7 +108,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml index 9e75a87ad53..4dd4e891242 100644 --- a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/configs/swift.yaml @@ -127,7 +127,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) diff --git a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml index 181137fdd77..5db3829279c 100644 --- a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml +++ b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/missingAltairField.yaml @@ -235,5 +235,4 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file diff --git a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml index d987056e62b..108fe0dca71 100644 --- a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml +++ b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/invalid/unknownField.yaml @@ -280,5 +280,4 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file diff --git a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml index 976d9fcc4d6..58a6cc93411 100644 --- a/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml +++ b/ethereum/spec/src/test/resources/tech/pegasys/teku/spec/config/standard/with-overrides.yaml @@ -106,5 +106,4 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java index afa52355653..88e57f491a7 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java @@ -41,7 +41,6 @@ import tech.pegasys.teku.networking.p2p.peer.Peer; import tech.pegasys.teku.networking.p2p.peer.PeerConnectedSubscriber; import tech.pegasys.teku.spec.Spec; -import tech.pegasys.teku.spec.config.SpecConfig; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.metadata.MetadataMessage; import tech.pegasys.teku.spec.datastructures.networking.libp2p.rpc.metadata.MetadataMessageSchema; import tech.pegasys.teku.spec.datastructures.state.Checkpoint; @@ -51,6 +50,8 @@ public class Eth2PeerManager implements PeerLookup, PeerHandler { private static final Logger LOG = LogManager.getLogger(); + private static final Duration STATUS_RECEIVED_TIMEOUT = Duration.ofSeconds(10); + private final AsyncRunner asyncRunner; private final RecentChainData recentChainData; private final Eth2PeerFactory eth2PeerFactory; @@ -66,7 +67,6 @@ public class Eth2PeerManager implements PeerLookup, PeerHandler { private final int eth2RpcOutstandingPingThreshold; private final Duration eth2StatusUpdateInterval; - private final SpecConfig specConfig; Eth2PeerManager( final Spec spec, @@ -99,7 +99,6 @@ public class Eth2PeerManager implements PeerLookup, PeerHandler { this.eth2RpcPingInterval = eth2RpcPingInterval; this.eth2RpcOutstandingPingThreshold = eth2RpcOutstandingPingThreshold; this.eth2StatusUpdateInterval = eth2StatusUpdateInterval; - this.specConfig = spec.getGenesisSpecConfig(); } public static Eth2PeerManager create( @@ -237,7 +236,7 @@ private void ensureStatusReceived(final Eth2Peer peer) { .ifExceptionGetsHereRaiseABug(); } }, - Duration.ofSeconds(specConfig.getRespTimeout())) + STATUS_RECEIVED_TIMEOUT) .finish( () -> {}, error -> { diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java index 3de2acd2675..733f92be5d2 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/libp2p/LibP2PNetworkBuilder.java @@ -15,6 +15,7 @@ import static tech.pegasys.teku.networking.p2p.libp2p.LibP2PNetwork.REMOTE_OPEN_STREAMS_RATE_LIMIT; import static tech.pegasys.teku.networking.p2p.libp2p.LibP2PNetwork.REMOTE_PARALLEL_OPEN_STREAMS_COUNT_LIMIT; +import static tech.pegasys.teku.spec.constants.NetworkConstants.MAX_CONCURRENT_REQUESTS; import com.google.common.base.Preconditions; import identify.pb.IdentifyOuterClass; @@ -153,7 +154,7 @@ public P2PNetwork build() { protected List> createRpcHandlers() { return rpcMethods.stream() - .map(m -> new RpcHandler<>(asyncRunner, m, networkingSpecConfig.getMaxConcurrentRequests())) + .map(m -> new RpcHandler<>(asyncRunner, m, MAX_CONCURRENT_REQUESTS)) .toList(); } diff --git a/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml b/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml index 7db048bc9b4..0c17d3c4486 100644 --- a/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml +++ b/teku/src/integration-test/resources/tech/pegasys/teku/cli/subcommand/test-spec.yaml @@ -107,5 +107,4 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file diff --git a/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml b/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml index 917ed1d29ee..f2402b8c7c8 100644 --- a/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml +++ b/teku/src/test/resources/tech/pegasys/teku/cli/options/constants.yaml @@ -180,5 +180,4 @@ SUBNETS_PER_NODE: 2 ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS -ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 \ No newline at end of file +ATTESTATION_SUBNET_PREFIX_BITS: 6 \ No newline at end of file diff --git a/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml b/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml index c4f2815f4d4..49c8d3b11bd 100644 --- a/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml +++ b/teku/src/test/resources/tech/pegasys/teku/cli/subcommand/deneb_config.yaml @@ -129,7 +129,6 @@ ATTESTATION_SUBNET_COUNT: 64 ATTESTATION_SUBNET_EXTRA_BITS: 0 # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS ATTESTATION_SUBNET_PREFIX_BITS: 6 -MAX_CONCURRENT_REQUESTS: 2 # Deneb # `2**7` (=128) From 895e5ab2d071fd8f140a43938a5243730090a571 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Mon, 25 Nov 2024 15:12:05 +0000 Subject: [PATCH 18/23] Delete file --- .../rpc/MaxConcurrentRequestsException.java | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java deleted file mode 100644 index 77e17abd5c5..00000000000 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/rpc/MaxConcurrentRequestsException.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package tech.pegasys.teku.networking.p2p.rpc; - -public class MaxConcurrentRequestsException extends RuntimeException { - - public MaxConcurrentRequestsException(final String message) { - super(message); - } -} From ca9438942e352a2ea5af805901bd2b97cda190ee Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 26 Nov 2024 11:22:27 +0000 Subject: [PATCH 19/23] fix acceptance test --- .../java/tech/pegasys/teku/spec/config/SpecConfigReader.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java index eae0fbe2d56..f48941998bd 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java @@ -70,9 +70,7 @@ public class SpecConfigReader { "TRANSITION_TOTAL_DIFFICULTY", // Deprecated fields "GOSSIP_MAX_SIZE_BELLATRIX", - "MAX_CHUNK_SIZE_BELLATRIX", - "TTFB_TIMEOUT", - "RESP_TIMEOUT"); + "MAX_CHUNK_SIZE_BELLATRIX"); private static final ImmutableSet CONSTANT_KEYS = ImmutableSet.of( // Phase0 constants which may exist in legacy config files, but should now be ignored From f772ec6338d00dee1139741e7e131fb7fae38d3e Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 26 Nov 2024 12:00:40 +0000 Subject: [PATCH 20/23] some reverts --- .../spec/config/DelegatingSpecConfig.java | 10 ++++++++++ .../spec/config/NetworkingSpecConfig.java | 6 ++++++ .../teku/spec/config/SpecConfigPhase0.java | 20 +++++++++++++++++++ .../config/builder/SpecConfigBuilder.java | 16 +++++++++++++++ .../cli/subcommand/RemoteSpecLoaderTest.java | 2 ++ 5 files changed, 54 insertions(+) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java index 403dae93aba..da606710f8a 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java @@ -362,6 +362,16 @@ public int getMinEpochsForBlockRequests() { return specConfig.getMinEpochsForBlockRequests(); } + @Override + public int getTtfbTimeout() { + return specConfig.getTtfbTimeout(); + } + + @Override + public int getRespTimeout() { + return specConfig.getRespTimeout(); + } + @Override public int getSubnetsPerNode() { return specConfig.getSubnetsPerNode(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java index a41f0d5f920..ef5b229dfcc 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java @@ -27,6 +27,12 @@ public interface NetworkingSpecConfig { int getMinEpochsForBlockRequests(); + // in seconds + int getTtfbTimeout(); + + // in seconds + int getRespTimeout(); + int getAttestationPropagationSlotRange(); // in millis diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java index 52654dfdd29..6d41969704c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java @@ -107,6 +107,8 @@ public class SpecConfigPhase0 implements SpecConfig { private final int maxRequestBlocks; private final int epochsPerSubnetSubscription; private final int minEpochsForBlockRequests; + private final int ttfbTimeout; + private final int respTimeout; private final int attestationPropagationSlotRange; private final int maximumGossipClockDisparity; private final Bytes4 messageDomainInvalidSnappy; @@ -177,6 +179,8 @@ public SpecConfigPhase0( final int maxRequestBlocks, final int epochsPerSubnetSubscription, final int minEpochsForBlockRequests, + final int ttfbTimeout, + final int respTimeout, final int attestationPropagationSlotRange, final int maximumGossipClockDisparity, final Bytes4 messageDomainInvalidSnappy, @@ -245,6 +249,8 @@ public SpecConfigPhase0( this.maxRequestBlocks = maxRequestBlocks; this.epochsPerSubnetSubscription = epochsPerSubnetSubscription; this.minEpochsForBlockRequests = minEpochsForBlockRequests; + this.ttfbTimeout = ttfbTimeout; + this.respTimeout = respTimeout; this.attestationPropagationSlotRange = attestationPropagationSlotRange; this.maximumGossipClockDisparity = maximumGossipClockDisparity; this.messageDomainInvalidSnappy = messageDomainInvalidSnappy; @@ -579,6 +585,16 @@ public int getMinEpochsForBlockRequests() { return minEpochsForBlockRequests; } + @Override + public int getTtfbTimeout() { + return ttfbTimeout; + } + + @Override + public int getRespTimeout() { + return respTimeout; + } + @Override public int getAttestationPropagationSlotRange() { return attestationPropagationSlotRange; @@ -675,6 +691,8 @@ public boolean equals(final Object o) { && attestationSubnetCount == that.attestationSubnetCount && attestationSubnetExtraBits == that.attestationSubnetExtraBits && attestationSubnetPrefixBits == that.attestationSubnetPrefixBits + && ttfbTimeout == that.ttfbTimeout + && respTimeout == that.respTimeout && attestationPropagationSlotRange == that.attestationPropagationSlotRange && maximumGossipClockDisparity == that.maximumGossipClockDisparity && Objects.equals(eth1FollowDistance, that.eth1FollowDistance) @@ -754,6 +772,8 @@ public int hashCode() { maxChunkSize, maxRequestBlocks, epochsPerSubnetSubscription, + ttfbTimeout, + respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java index e731ec925fe..5e48e29614c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java @@ -112,6 +112,8 @@ public class SpecConfigBuilder { private Integer maxChunkSize; private Integer maxRequestBlocks; private Integer epochsPerSubnetSubscription; + private Integer ttfbTimeout; + private Integer respTimeout; private Integer attestationPropagationSlotRange; private Integer maximumGossipClockDisparity; private Bytes4 messageDomainInvalidSnappy; @@ -203,6 +205,8 @@ public SpecConfigAndParent build() { maxRequestBlocks, epochsPerSubnetSubscription, minEpochsForBlockRequests, + ttfbTimeout, + respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -275,6 +279,8 @@ private Map getValidationMap() { constants.put("maxRequestBlocks", maxRequestBlocks); constants.put("epochsPerSubnetSubscription", epochsPerSubnetSubscription); constants.put("minEpochsForBlockRequests", minEpochsForBlockRequests); + constants.put("ttfbTimeout", ttfbTimeout); + constants.put("respTimeout", respTimeout); constants.put("attestationPropagationSlotRange", attestationPropagationSlotRange); constants.put("maximumGossipClockDisparity", maximumGossipClockDisparity); constants.put("messageDomainInvalidSnappy", messageDomainInvalidSnappy); @@ -645,6 +651,16 @@ public SpecConfigBuilder minEpochsForBlockRequests(final Integer minEpochsForBlo return this; } + public SpecConfigBuilder ttfbTimeout(final Integer ttfbTimeout) { + this.ttfbTimeout = ttfbTimeout; + return this; + } + + public SpecConfigBuilder respTimeout(final Integer respTimeout) { + this.respTimeout = respTimeout; + return this; + } + public SpecConfigBuilder attestationPropagationSlotRange( final Integer attestationPropagationSlotRange) { this.attestationPropagationSlotRange = attestationPropagationSlotRange; diff --git a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java index 5747896cae1..a6818600c2c 100644 --- a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java +++ b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java @@ -78,6 +78,8 @@ void shouldDefaultNetworkConfigThatMovedFromConstants() throws IOException { assertThat(specConfig.getMaxRequestBlocks()).isEqualTo(1024); assertThat(specConfig.getEpochsPerSubnetSubscription()).isEqualTo(256); assertThat(specConfig.getMinEpochsForBlockRequests()).isEqualTo(33024); + assertThat(specConfig.getTtfbTimeout()).isEqualTo(5); + assertThat(specConfig.getRespTimeout()).isEqualTo(10); assertThat(specConfig.getAttestationPropagationSlotRange()).isEqualTo(32); assertThat(specConfig.getMaximumGossipClockDisparity()).isEqualTo(500); } From 020e3fdf29c75ba5f1f54c679d869cbab2e85043 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Wed, 27 Nov 2024 09:00:35 +0000 Subject: [PATCH 21/23] change order --- .../spec/config/DelegatingSpecConfig.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java index da606710f8a..b513c9b16bf 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java @@ -327,6 +327,16 @@ public int getMaxChunkSize() { return specConfig.getMaxChunkSize(); } + @Override + public int getTtfbTimeout() { + return specConfig.getTtfbTimeout(); + } + + @Override + public int getRespTimeout() { + return specConfig.getRespTimeout(); + } + @Override public int getAttestationPropagationSlotRange() { return specConfig.getAttestationPropagationSlotRange(); @@ -362,16 +372,6 @@ public int getMinEpochsForBlockRequests() { return specConfig.getMinEpochsForBlockRequests(); } - @Override - public int getTtfbTimeout() { - return specConfig.getTtfbTimeout(); - } - - @Override - public int getRespTimeout() { - return specConfig.getRespTimeout(); - } - @Override public int getSubnetsPerNode() { return specConfig.getSubnetsPerNode(); From 3528efdd3c47d7b24f5f2653f33f4bc0ce97ec46 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Wed, 4 Dec 2024 16:08:56 +0000 Subject: [PATCH 22/23] remove constants --- .../spec/config/DelegatingSpecConfig.java | 10 ---------- .../spec/config/NetworkingSpecConfig.java | 6 ------ .../teku/spec/config/SpecConfigPhase0.java | 20 ------------------- .../config/builder/SpecConfigBuilder.java | 16 --------------- .../cli/subcommand/RemoteSpecLoaderTest.java | 2 -- 5 files changed, 54 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java index b513c9b16bf..403dae93aba 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java @@ -327,16 +327,6 @@ public int getMaxChunkSize() { return specConfig.getMaxChunkSize(); } - @Override - public int getTtfbTimeout() { - return specConfig.getTtfbTimeout(); - } - - @Override - public int getRespTimeout() { - return specConfig.getRespTimeout(); - } - @Override public int getAttestationPropagationSlotRange() { return specConfig.getAttestationPropagationSlotRange(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java index ef5b229dfcc..a41f0d5f920 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java @@ -27,12 +27,6 @@ public interface NetworkingSpecConfig { int getMinEpochsForBlockRequests(); - // in seconds - int getTtfbTimeout(); - - // in seconds - int getRespTimeout(); - int getAttestationPropagationSlotRange(); // in millis diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java index 6d41969704c..52654dfdd29 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java @@ -107,8 +107,6 @@ public class SpecConfigPhase0 implements SpecConfig { private final int maxRequestBlocks; private final int epochsPerSubnetSubscription; private final int minEpochsForBlockRequests; - private final int ttfbTimeout; - private final int respTimeout; private final int attestationPropagationSlotRange; private final int maximumGossipClockDisparity; private final Bytes4 messageDomainInvalidSnappy; @@ -179,8 +177,6 @@ public SpecConfigPhase0( final int maxRequestBlocks, final int epochsPerSubnetSubscription, final int minEpochsForBlockRequests, - final int ttfbTimeout, - final int respTimeout, final int attestationPropagationSlotRange, final int maximumGossipClockDisparity, final Bytes4 messageDomainInvalidSnappy, @@ -249,8 +245,6 @@ public SpecConfigPhase0( this.maxRequestBlocks = maxRequestBlocks; this.epochsPerSubnetSubscription = epochsPerSubnetSubscription; this.minEpochsForBlockRequests = minEpochsForBlockRequests; - this.ttfbTimeout = ttfbTimeout; - this.respTimeout = respTimeout; this.attestationPropagationSlotRange = attestationPropagationSlotRange; this.maximumGossipClockDisparity = maximumGossipClockDisparity; this.messageDomainInvalidSnappy = messageDomainInvalidSnappy; @@ -585,16 +579,6 @@ public int getMinEpochsForBlockRequests() { return minEpochsForBlockRequests; } - @Override - public int getTtfbTimeout() { - return ttfbTimeout; - } - - @Override - public int getRespTimeout() { - return respTimeout; - } - @Override public int getAttestationPropagationSlotRange() { return attestationPropagationSlotRange; @@ -691,8 +675,6 @@ public boolean equals(final Object o) { && attestationSubnetCount == that.attestationSubnetCount && attestationSubnetExtraBits == that.attestationSubnetExtraBits && attestationSubnetPrefixBits == that.attestationSubnetPrefixBits - && ttfbTimeout == that.ttfbTimeout - && respTimeout == that.respTimeout && attestationPropagationSlotRange == that.attestationPropagationSlotRange && maximumGossipClockDisparity == that.maximumGossipClockDisparity && Objects.equals(eth1FollowDistance, that.eth1FollowDistance) @@ -772,8 +754,6 @@ public int hashCode() { maxChunkSize, maxRequestBlocks, epochsPerSubnetSubscription, - ttfbTimeout, - respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java index 5e48e29614c..e731ec925fe 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java @@ -112,8 +112,6 @@ public class SpecConfigBuilder { private Integer maxChunkSize; private Integer maxRequestBlocks; private Integer epochsPerSubnetSubscription; - private Integer ttfbTimeout; - private Integer respTimeout; private Integer attestationPropagationSlotRange; private Integer maximumGossipClockDisparity; private Bytes4 messageDomainInvalidSnappy; @@ -205,8 +203,6 @@ public SpecConfigAndParent build() { maxRequestBlocks, epochsPerSubnetSubscription, minEpochsForBlockRequests, - ttfbTimeout, - respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -279,8 +275,6 @@ private Map getValidationMap() { constants.put("maxRequestBlocks", maxRequestBlocks); constants.put("epochsPerSubnetSubscription", epochsPerSubnetSubscription); constants.put("minEpochsForBlockRequests", minEpochsForBlockRequests); - constants.put("ttfbTimeout", ttfbTimeout); - constants.put("respTimeout", respTimeout); constants.put("attestationPropagationSlotRange", attestationPropagationSlotRange); constants.put("maximumGossipClockDisparity", maximumGossipClockDisparity); constants.put("messageDomainInvalidSnappy", messageDomainInvalidSnappy); @@ -651,16 +645,6 @@ public SpecConfigBuilder minEpochsForBlockRequests(final Integer minEpochsForBlo return this; } - public SpecConfigBuilder ttfbTimeout(final Integer ttfbTimeout) { - this.ttfbTimeout = ttfbTimeout; - return this; - } - - public SpecConfigBuilder respTimeout(final Integer respTimeout) { - this.respTimeout = respTimeout; - return this; - } - public SpecConfigBuilder attestationPropagationSlotRange( final Integer attestationPropagationSlotRange) { this.attestationPropagationSlotRange = attestationPropagationSlotRange; diff --git a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java index a6818600c2c..5747896cae1 100644 --- a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java +++ b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java @@ -78,8 +78,6 @@ void shouldDefaultNetworkConfigThatMovedFromConstants() throws IOException { assertThat(specConfig.getMaxRequestBlocks()).isEqualTo(1024); assertThat(specConfig.getEpochsPerSubnetSubscription()).isEqualTo(256); assertThat(specConfig.getMinEpochsForBlockRequests()).isEqualTo(33024); - assertThat(specConfig.getTtfbTimeout()).isEqualTo(5); - assertThat(specConfig.getRespTimeout()).isEqualTo(10); assertThat(specConfig.getAttestationPropagationSlotRange()).isEqualTo(32); assertThat(specConfig.getMaximumGossipClockDisparity()).isEqualTo(500); } From 493f2847cf2325c66bde26f3ba4e084313ee0005 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Wed, 4 Dec 2024 20:15:45 +0000 Subject: [PATCH 23/23] Revert "remove constants" This reverts commit b44ceabb46858d4d22e84fd5804620a26da4ae77. --- .../spec/config/DelegatingSpecConfig.java | 10 ++++++++++ .../spec/config/NetworkingSpecConfig.java | 6 ++++++ .../teku/spec/config/SpecConfigPhase0.java | 20 +++++++++++++++++++ .../config/builder/SpecConfigBuilder.java | 16 +++++++++++++++ .../cli/subcommand/RemoteSpecLoaderTest.java | 2 ++ 5 files changed, 54 insertions(+) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java index 403dae93aba..b513c9b16bf 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfig.java @@ -327,6 +327,16 @@ public int getMaxChunkSize() { return specConfig.getMaxChunkSize(); } + @Override + public int getTtfbTimeout() { + return specConfig.getTtfbTimeout(); + } + + @Override + public int getRespTimeout() { + return specConfig.getRespTimeout(); + } + @Override public int getAttestationPropagationSlotRange() { return specConfig.getAttestationPropagationSlotRange(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java index a41f0d5f920..ef5b229dfcc 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/NetworkingSpecConfig.java @@ -27,6 +27,12 @@ public interface NetworkingSpecConfig { int getMinEpochsForBlockRequests(); + // in seconds + int getTtfbTimeout(); + + // in seconds + int getRespTimeout(); + int getAttestationPropagationSlotRange(); // in millis diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java index 52654dfdd29..6d41969704c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigPhase0.java @@ -107,6 +107,8 @@ public class SpecConfigPhase0 implements SpecConfig { private final int maxRequestBlocks; private final int epochsPerSubnetSubscription; private final int minEpochsForBlockRequests; + private final int ttfbTimeout; + private final int respTimeout; private final int attestationPropagationSlotRange; private final int maximumGossipClockDisparity; private final Bytes4 messageDomainInvalidSnappy; @@ -177,6 +179,8 @@ public SpecConfigPhase0( final int maxRequestBlocks, final int epochsPerSubnetSubscription, final int minEpochsForBlockRequests, + final int ttfbTimeout, + final int respTimeout, final int attestationPropagationSlotRange, final int maximumGossipClockDisparity, final Bytes4 messageDomainInvalidSnappy, @@ -245,6 +249,8 @@ public SpecConfigPhase0( this.maxRequestBlocks = maxRequestBlocks; this.epochsPerSubnetSubscription = epochsPerSubnetSubscription; this.minEpochsForBlockRequests = minEpochsForBlockRequests; + this.ttfbTimeout = ttfbTimeout; + this.respTimeout = respTimeout; this.attestationPropagationSlotRange = attestationPropagationSlotRange; this.maximumGossipClockDisparity = maximumGossipClockDisparity; this.messageDomainInvalidSnappy = messageDomainInvalidSnappy; @@ -579,6 +585,16 @@ public int getMinEpochsForBlockRequests() { return minEpochsForBlockRequests; } + @Override + public int getTtfbTimeout() { + return ttfbTimeout; + } + + @Override + public int getRespTimeout() { + return respTimeout; + } + @Override public int getAttestationPropagationSlotRange() { return attestationPropagationSlotRange; @@ -675,6 +691,8 @@ public boolean equals(final Object o) { && attestationSubnetCount == that.attestationSubnetCount && attestationSubnetExtraBits == that.attestationSubnetExtraBits && attestationSubnetPrefixBits == that.attestationSubnetPrefixBits + && ttfbTimeout == that.ttfbTimeout + && respTimeout == that.respTimeout && attestationPropagationSlotRange == that.attestationPropagationSlotRange && maximumGossipClockDisparity == that.maximumGossipClockDisparity && Objects.equals(eth1FollowDistance, that.eth1FollowDistance) @@ -754,6 +772,8 @@ public int hashCode() { maxChunkSize, maxRequestBlocks, epochsPerSubnetSubscription, + ttfbTimeout, + respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java index e731ec925fe..5e48e29614c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java @@ -112,6 +112,8 @@ public class SpecConfigBuilder { private Integer maxChunkSize; private Integer maxRequestBlocks; private Integer epochsPerSubnetSubscription; + private Integer ttfbTimeout; + private Integer respTimeout; private Integer attestationPropagationSlotRange; private Integer maximumGossipClockDisparity; private Bytes4 messageDomainInvalidSnappy; @@ -203,6 +205,8 @@ public SpecConfigAndParent build() { maxRequestBlocks, epochsPerSubnetSubscription, minEpochsForBlockRequests, + ttfbTimeout, + respTimeout, attestationPropagationSlotRange, maximumGossipClockDisparity, messageDomainInvalidSnappy, @@ -275,6 +279,8 @@ private Map getValidationMap() { constants.put("maxRequestBlocks", maxRequestBlocks); constants.put("epochsPerSubnetSubscription", epochsPerSubnetSubscription); constants.put("minEpochsForBlockRequests", minEpochsForBlockRequests); + constants.put("ttfbTimeout", ttfbTimeout); + constants.put("respTimeout", respTimeout); constants.put("attestationPropagationSlotRange", attestationPropagationSlotRange); constants.put("maximumGossipClockDisparity", maximumGossipClockDisparity); constants.put("messageDomainInvalidSnappy", messageDomainInvalidSnappy); @@ -645,6 +651,16 @@ public SpecConfigBuilder minEpochsForBlockRequests(final Integer minEpochsForBlo return this; } + public SpecConfigBuilder ttfbTimeout(final Integer ttfbTimeout) { + this.ttfbTimeout = ttfbTimeout; + return this; + } + + public SpecConfigBuilder respTimeout(final Integer respTimeout) { + this.respTimeout = respTimeout; + return this; + } + public SpecConfigBuilder attestationPropagationSlotRange( final Integer attestationPropagationSlotRange) { this.attestationPropagationSlotRange = attestationPropagationSlotRange; diff --git a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java index 5747896cae1..a6818600c2c 100644 --- a/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java +++ b/teku/src/test/java/tech/pegasys/teku/cli/subcommand/RemoteSpecLoaderTest.java @@ -78,6 +78,8 @@ void shouldDefaultNetworkConfigThatMovedFromConstants() throws IOException { assertThat(specConfig.getMaxRequestBlocks()).isEqualTo(1024); assertThat(specConfig.getEpochsPerSubnetSubscription()).isEqualTo(256); assertThat(specConfig.getMinEpochsForBlockRequests()).isEqualTo(33024); + assertThat(specConfig.getTtfbTimeout()).isEqualTo(5); + assertThat(specConfig.getRespTimeout()).isEqualTo(10); assertThat(specConfig.getAttestationPropagationSlotRange()).isEqualTo(32); assertThat(specConfig.getMaximumGossipClockDisparity()).isEqualTo(500); }