diff --git a/consensus/ibftlegacy/src/test/java/org/hyperledger/besu/consensus/ibftlegacy/protocol/Istanbul99ProtocolManagerTest.java b/consensus/ibftlegacy/src/test/java/org/hyperledger/besu/consensus/ibftlegacy/protocol/Istanbul99ProtocolManagerTest.java index 1c8c578393..9565afacbb 100644 --- a/consensus/ibftlegacy/src/test/java/org/hyperledger/besu/consensus/ibftlegacy/protocol/Istanbul99ProtocolManagerTest.java +++ b/consensus/ibftlegacy/src/test/java/org/hyperledger/besu/consensus/ibftlegacy/protocol/Istanbul99ProtocolManagerTest.java @@ -20,8 +20,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; -import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; +import org.hyperledger.besu.ethereum.eth.EthProtocolVersion; import org.hyperledger.besu.ethereum.eth.manager.DeterministicEthScheduler; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthMessages; @@ -82,7 +82,7 @@ public class Istanbul99ProtocolManagerTest { final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, onSend); final StatusMessage statusMessage = StatusMessage.create( - EthProtocol.EthVersion.V63, + EthProtocolVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocol.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocol.java index 991f64e608..394ac0cebd 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocol.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * Copyright contributors to Hyperledger Besu * * 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 @@ -14,58 +14,28 @@ */ package org.hyperledger.besu.ethereum.eth; -import static java.util.stream.Collectors.toUnmodifiableList; - import org.hyperledger.besu.ethereum.eth.messages.EthPV62; import org.hyperledger.besu.ethereum.eth.messages.EthPV63; import org.hyperledger.besu.ethereum.eth.messages.EthPV65; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol; -import java.util.List; import java.util.Set; -import java.util.stream.Stream; /** - * Eth protocol messages as defined in - * https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol#new-model-syncing-pv62} + * Eth protocol messages as defined in Ethereum Wire Protocol + * (ETH)} */ public class EthProtocol implements SubProtocol { public static final String NAME = "eth"; - public static final Capability ETH62 = Capability.create(NAME, EthVersion.V62); - public static final Capability ETH63 = Capability.create(NAME, EthVersion.V63); - public static final Capability ETH64 = Capability.create(NAME, EthVersion.V64); - public static final Capability ETH65 = Capability.create(NAME, EthVersion.V65); - public static final Capability ETH66 = Capability.create(NAME, EthVersion.V66); - private static final EthProtocol INSTANCE = new EthProtocol(); - private static final List eth62Messages = - List.of( - EthPV62.STATUS, - EthPV62.NEW_BLOCK_HASHES, - EthPV62.TRANSACTIONS, - EthPV62.GET_BLOCK_HEADERS, - EthPV62.BLOCK_HEADERS, - EthPV62.GET_BLOCK_BODIES, - EthPV62.BLOCK_BODIES, - EthPV62.NEW_BLOCK); - - private static final List eth63Messages = - Stream.concat( - eth62Messages.stream(), - Stream.of( - EthPV63.GET_NODE_DATA, EthPV63.NODE_DATA, EthPV63.GET_RECEIPTS, EthPV63.RECEIPTS)) - .collect(toUnmodifiableList()); - - private static final List eth65Messages = - Stream.concat( - eth63Messages.stream(), - Stream.of( - EthPV65.NEW_POOLED_TRANSACTION_HASHES, - EthPV65.GET_POOLED_TRANSACTIONS, - EthPV65.POOLED_TRANSACTIONS)) - .collect(toUnmodifiableList()); + public static final Capability ETH62 = Capability.create(NAME, EthProtocolVersion.V62); + public static final Capability ETH63 = Capability.create(NAME, EthProtocolVersion.V63); + public static final Capability ETH64 = Capability.create(NAME, EthProtocolVersion.V64); + public static final Capability ETH65 = Capability.create(NAME, EthProtocolVersion.V65); + public static final Capability ETH66 = Capability.create(NAME, EthProtocolVersion.V66); public static boolean requestIdCompatible(final int code) { return Set.of( @@ -90,12 +60,12 @@ public class EthProtocol implements SubProtocol { @Override public int messageSpace(final int protocolVersion) { switch (protocolVersion) { - case EthVersion.V62: + case EthProtocolVersion.V62: return 8; - case EthVersion.V63: - case EthVersion.V64: - case EthVersion.V65: - case EthVersion.V66: + case EthProtocolVersion.V63: + case EthProtocolVersion.V64: + case EthProtocolVersion.V65: + case EthProtocolVersion.V66: // same number of messages in each range, eth65 defines messages in the middle of the // range defined by eth63 and eth64 defines no new ranges. return 17; @@ -106,18 +76,7 @@ public class EthProtocol implements SubProtocol { @Override public boolean isValidMessageCode(final int protocolVersion, final int code) { - switch (protocolVersion) { - case EthVersion.V62: - return eth62Messages.contains(code); - case EthVersion.V63: - case EthVersion.V64: - return eth63Messages.contains(code); - case EthVersion.V65: - case EthVersion.V66: - return eth65Messages.contains(code); - default: - return false; - } + return EthProtocolVersion.getSupportedMessages(protocolVersion).contains(code); } @Override @@ -162,14 +121,6 @@ public class EthProtocol implements SubProtocol { return INSTANCE; } - public static class EthVersion { - public static final int V62 = 62; - public static final int V63 = 63; - public static final int V64 = 64; - public static final int V65 = 65; - public static final int V66 = 66; - } - public static boolean isEth66Compatible(final Capability capability) { return NAME.equals(capability.getName()) && capability.getVersion() >= ETH66.getVersion(); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolVersion.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolVersion.java new file mode 100644 index 0000000000..2e8d84e001 --- /dev/null +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolVersion.java @@ -0,0 +1,112 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth; + +import org.hyperledger.besu.ethereum.eth.messages.EthPV62; +import org.hyperledger.besu.ethereum.eth.messages.EthPV63; +import org.hyperledger.besu.ethereum.eth.messages.EthPV65; + +import java.util.Collections; +import java.util.List; + +/** + * Eth protocol messages as defined in Ethereum Wire Protocol + * (ETH)} + */ +public class EthProtocolVersion { + public static final int V62 = 62; + public static final int V63 = 63; + public static final int V64 = 64; + public static final int V65 = 65; + public static final int V66 = 66; + + /** eth/62 (2015) */ + private static final List eth62Messages = + List.of( + EthPV62.STATUS, + EthPV62.NEW_BLOCK_HASHES, + EthPV62.TRANSACTIONS, + EthPV62.GET_BLOCK_HEADERS, + EthPV62.BLOCK_HEADERS, + EthPV62.GET_BLOCK_BODIES, + EthPV62.BLOCK_BODIES, + EthPV62.NEW_BLOCK); + + /** + * eth/63 (2016) + * + *

Version 63 added the GetNodeData, NodeData, GetReceipts and Receipts messages which allow + * synchronizing transaction execution results. + */ + private static final List eth63Messages = + List.of( + EthPV62.STATUS, + EthPV62.NEW_BLOCK_HASHES, + EthPV62.TRANSACTIONS, + EthPV62.GET_BLOCK_HEADERS, + EthPV62.BLOCK_HEADERS, + EthPV62.GET_BLOCK_BODIES, + EthPV62.BLOCK_BODIES, + EthPV62.NEW_BLOCK, + EthPV63.GET_NODE_DATA, + EthPV63.NODE_DATA, + EthPV63.GET_RECEIPTS, + EthPV63.RECEIPTS); + /** + * eth/65 (EIP-2464, January 2020) + * + *

Version 65 improved transaction exchange, introducing three additional messages: + * NewPooledTransactionHashes, GetPooledTransactions, and PooledTransactions. + */ + private static final List eth65Messages = + List.of( + EthPV62.STATUS, + EthPV62.NEW_BLOCK_HASHES, + EthPV62.TRANSACTIONS, + EthPV62.GET_BLOCK_HEADERS, + EthPV62.BLOCK_HEADERS, + EthPV62.GET_BLOCK_BODIES, + EthPV62.BLOCK_BODIES, + EthPV62.NEW_BLOCK, + EthPV63.GET_NODE_DATA, + EthPV63.NODE_DATA, + EthPV63.GET_RECEIPTS, + EthPV63.RECEIPTS, + EthPV65.NEW_POOLED_TRANSACTION_HASHES, + EthPV65.GET_POOLED_TRANSACTIONS, + EthPV65.POOLED_TRANSACTIONS); + + /** + * Returns a list of integers containing the supported messages given the protocol version + * + * @param protocolVersion the protocol version + * @return a list containing the codes of supported messages + */ + public static List getSupportedMessages(final int protocolVersion) { + switch (protocolVersion) { + case EthProtocolVersion.V62: + return eth62Messages; + case EthProtocolVersion.V63: + case EthProtocolVersion.V64: + return eth63Messages; + case EthProtocolVersion.V65: + case EthProtocolVersion.V66: + return eth65Messages; + default: + return Collections.emptyList(); + } + } +} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java index cdacc183b5..d5e751b618 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * Copyright contributors to Hyperledger Besu * * 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 diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java index 7930285eaf..15dcbbfc0c 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * Copyright contributors to Hyperledger Besu * * 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 @@ -43,6 +43,7 @@ import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; +import org.hyperledger.besu.ethereum.eth.EthProtocolVersion; import org.hyperledger.besu.ethereum.eth.manager.MockPeerConnection.PeerSendHandler; import org.hyperledger.besu.ethereum.eth.messages.BlockBodiesMessage; import org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage; @@ -193,7 +194,7 @@ public final class EthProtocolManagerTest { // Send status message with wrong chain final StatusMessage statusMessage = StatusMessage.create( - EthProtocol.EthVersion.V63, + EthProtocolVersion.V63, BigInteger.valueOf(2222), blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), @@ -221,7 +222,7 @@ public final class EthProtocolManagerTest { final StatusMessage workPeerStatus = StatusMessage.create( - EthProtocol.EthVersion.V63, + EthProtocolVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty().add(20), blockchain.getChainHeadHash(), @@ -229,7 +230,7 @@ public final class EthProtocolManagerTest { final StatusMessage stakePeerStatus = StatusMessage.create( - EthProtocol.EthVersion.V63, + EthProtocolVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), @@ -290,7 +291,7 @@ public final class EthProtocolManagerTest { // Send status message with wrong chain final StatusMessage statusMessage = StatusMessage.create( - EthProtocol.EthVersion.V63, + EthProtocolVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), gen.hash(), @@ -515,7 +516,7 @@ public final class EthProtocolManagerTest { final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, onSend); final StatusMessage statusMessage = StatusMessage.create( - EthProtocol.EthVersion.V63, + EthProtocolVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), @@ -1041,7 +1042,7 @@ public final class EthProtocolManagerTest { ethManager.handleNewConnection(peer); final StatusMessage statusMessage = StatusMessage.create( - EthProtocol.EthVersion.V63, + EthProtocolVersion.V63, BigInteger.ONE, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java index e84c795f4b..27e5ddf29d 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Difficulty; -import org.hyperledger.besu.ethereum.eth.EthProtocol; +import org.hyperledger.besu.ethereum.eth.EthProtocolVersion; import org.hyperledger.besu.ethereum.eth.manager.ForkId; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; @@ -33,7 +33,7 @@ public class StatusMessageTest { @Test public void getters() { - final int version = EthProtocol.EthVersion.V62; + final int version = EthProtocolVersion.V62; final BigInteger networkId = BigInteger.ONE; final Difficulty td = Difficulty.of(1000L); final Hash bestHash = randHash(1L); @@ -50,7 +50,7 @@ public class StatusMessageTest { @Test public void serializeDeserialize() { - final int version = EthProtocol.EthVersion.V62; + final int version = EthProtocolVersion.V62; final BigInteger networkId = BigInteger.ONE; final Difficulty td = Difficulty.of(1000L); final Hash bestHash = randHash(1L); @@ -70,7 +70,7 @@ public class StatusMessageTest { @Test public void serializeDeserializeWithForkId() { - final int version = EthProtocol.EthVersion.V64; + final int version = EthProtocolVersion.V64; final BigInteger networkId = BigInteger.ONE; final Difficulty td = Difficulty.of(1000L); final Hash bestHash = randHash(1L); @@ -92,7 +92,7 @@ public class StatusMessageTest { @Test public void toStringHasExpectedInfo() { - final int version = EthProtocol.EthVersion.V64; + final int version = EthProtocolVersion.V64; final BigInteger networkId = BigInteger.ONE; final Difficulty td = Difficulty.of(1000L); final Hash bestHash = randHash(1L);