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 775aafca35..05239e3038 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 @@ -64,6 +64,7 @@ public class EthProtocol implements SubProtocol { case EthVersion.V62: return 8; case EthVersion.V63: + case EthVersion.V64: return 17; default: return 0; @@ -76,6 +77,7 @@ public class EthProtocol implements SubProtocol { case EthVersion.V62: return eth62Messages.contains(code); case EthVersion.V63: + case EthVersion.V64: return eth63Messages.contains(code); default: return false; 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 3f7b9ce1e2..94c35fbbd6 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 @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; +import org.hyperledger.besu.ethereum.eth.manager.ForkIdManager.ForkId; import org.hyperledger.besu.ethereum.eth.messages.EthPV62; import org.hyperledger.besu.ethereum.eth.messages.StatusMessage; import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; @@ -41,21 +42,21 @@ import org.hyperledger.besu.plugin.services.MetricsSystem; import java.math.BigInteger; import java.time.Clock; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; +import com.google.common.annotations.VisibleForTesting; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { private static final Logger LOG = LogManager.getLogger(); private static final List FAST_SYNC_CAPS = - Collections.singletonList(EthProtocol.ETH63); + List.of(EthProtocol.ETH63, EthProtocol.ETH64); private static final List FULL_SYNC_CAPS = - Arrays.asList(EthProtocol.ETH62, EthProtocol.ETH63); + List.of(EthProtocol.ETH62, EthProtocol.ETH63, EthProtocol.ETH64); private final EthScheduler scheduler; private final CountDownLatch shutdown; @@ -93,7 +94,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { this.shutdown = new CountDownLatch(1); genesisHash = blockchain.getBlockHashByNumber(0L).get(); - this.forkIdManager = ForkIdManager.buildCollection(genesisHash); + this.forkIdManager = forkIdManager; ethPeers = new EthPeers(getSupportedProtocol(), clock, metricsSystem); ethMessages = new EthMessages(); @@ -110,30 +111,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { new EthServer(blockchain, worldStateArchive, ethMessages, ethereumWireProtocolConfiguration); } - public EthProtocolManager( - final Blockchain blockchain, - final WorldStateArchive worldStateArchive, - final BigInteger networkId, - final List peerValidators, - final boolean fastSyncEnabled, - final int syncWorkers, - final int txWorkers, - final int computationWorkers, - final Clock clock, - final MetricsSystem metricsSystem) { - this( - blockchain, - worldStateArchive, - networkId, - peerValidators, - fastSyncEnabled, - new EthScheduler(syncWorkers, txWorkers, computationWorkers, metricsSystem), - EthProtocolConfiguration.defaultConfig(), - clock, - metricsSystem, - ForkIdManager.buildCollection(blockchain.getBlockHashByNumber(0L).get())); - } - + @VisibleForTesting public EthProtocolManager( final Blockchain blockchain, final WorldStateArchive worldStateArchive, @@ -156,7 +134,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { ethereumWireProtocolConfiguration, clock, metricsSystem, - ForkIdManager.buildCollection(blockchain.getBlockHashByNumber(0L).get())); + new ForkIdManager(blockchain, Collections.emptyList())); } public EthProtocolManager( @@ -182,8 +160,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { ethereumWireProtocolConfiguration, clock, metricsSystem, - ForkIdManager.buildCollection( - blockchain.getBlockHashByNumber(0L).get(), forks, blockchain)); + new ForkIdManager(blockchain, forks)); } public EthContext ethContext() { @@ -274,6 +251,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { } final Capability cap = connection.capability(getSupportedProtocol()); + final ForkId latestForkId = cap.getVersion() >= 64 ? forkIdManager.getLatestForkId() : null; // TODO: look to consolidate code below if possible // making status non-final and implementing it above would be one way. final StatusMessage status = @@ -283,7 +261,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), genesisHash, - forkIdManager.getLatestForkId()); + latestForkId); try { LOG.debug("Sending status message to {}.", peer); peer.send(status); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java index b1b7b73ff3..464ec173d0 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java @@ -14,8 +14,6 @@ */ package org.hyperledger.besu.ethereum.eth.manager; -import static java.util.Collections.emptyList; - import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; @@ -27,52 +25,28 @@ import java.util.List; import java.util.stream.Collectors; import java.util.zip.CRC32; -import com.google.common.annotations.VisibleForTesting; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; public class ForkIdManager { + private final Blockchain blockchain; private final Hash genesisHash; - private final Long currentHead; - private Long forkNext; - private final Long highestKnownFork = 0L; - private final List forkAndHashList; - - public ForkIdManager(final Hash genesisHash, final List forks, final Long currentHead) { - this.genesisHash = genesisHash; - this.currentHead = currentHead; - this.forkAndHashList = - createForkIds( - // If there are two forks at the same block height, we only want to add it once to the - // crc checksum - forks.stream().distinct().collect(Collectors.toUnmodifiableList())); - }; - - static ForkIdManager buildCollection( - final Hash genesisHash, final List forks, final Blockchain blockchain) { - return new ForkIdManager(genesisHash, forks, blockchain.getChainHeadBlockNumber()); - }; - - @VisibleForTesting - public static ForkIdManager buildCollection(final Hash genesisHash, final List forks) { - return new ForkIdManager(genesisHash, forks, Long.MAX_VALUE); - }; - - static ForkIdManager buildCollection(final Hash genesisHash) { - return new ForkIdManager(genesisHash, emptyList(), Long.MAX_VALUE); + private final List forks; + private long forkNext; + private final long highestKnownFork; + private List forkAndHashList; + + public ForkIdManager(final Blockchain blockchain, final List forks) { + this.blockchain = blockchain; + this.genesisHash = blockchain.getGenesisBlock().getHash(); + // de-dupe and sanitize forks + this.forks = + forks.stream().filter(fork -> fork > 0).distinct().collect(Collectors.toUnmodifiableList()); + highestKnownFork = forks.size() > 0 ? forks.get(forks.size() - 1) : 0L; + createForkIds(); }; - // Non-generated entry (for tests) - public static ForkId createIdEntry(final String hash, final long next) { - return new ForkId(hash, next); - } - - // Non-generated entry (for tests) - public static ForkId createIdEntry(final String hash, final String next) { - return new ForkId(hash, next); - } - public List getForkAndHashList() { return this.forkAndHashList; } @@ -98,11 +72,11 @@ public class ForkIdManager { * @param forkId to be validated. * @return boolean (peer valid (true) or invalid (false)) */ - public boolean peerCheck(final ForkId forkId) { + boolean peerCheck(final ForkId forkId) { if (forkId == null) { return true; // Another method must be used to validate (i.e. genesis hash) } - // Run the fork checksum validation ruleset: + // Run the fork checksum validation rule set: // 1. If local and remote FORK_CSUM matches, connect. // The two nodes are in the same fork state currently. They might know // of differing future forks, but that's not relevant until the fork @@ -119,7 +93,7 @@ public class ForkIdManager { // information. // 4. Reject in all other cases. if (isHashKnown(forkId.getHash())) { - if (currentHead < forkNext) { + if (blockchain.getChainHeadBlockNumber() < forkNext) { return true; } else { if (isForkKnown(forkId.getNext())) { @@ -153,7 +127,7 @@ public class ForkIdManager { } private boolean isRemoteAwareOfPresent(final Bytes forkHash, final Long nextFork) { - for (ForkId j : forkAndHashList) { + for (final ForkId j : forkAndHashList) { if (forkHash.equals(j.getHash())) { if (nextFork.equals(j.getNext())) { return true; @@ -167,9 +141,9 @@ public class ForkIdManager { return false; } - private List createForkIds(final List forks) { + private void createForkIds() { final CRC32 crc = new CRC32(); - crc.update(this.genesisHash.toArray()); + crc.update(genesisHash.toArray()); final List forkHashes = new ArrayList<>(List.of(getCurrentCrcHash(crc))); for (final Long fork : forks) { updateCrc(crc, fork); @@ -181,18 +155,14 @@ public class ForkIdManager { forkIds.add(new ForkId(forkHashes.get(i), forks.get(i))); } if (!forks.isEmpty()) { - this.forkNext = forkIds.get(forkIds.size() - 1).getNext(); - forkIds.add( - new ForkId( - forkHashes.get(forkHashes.size() - 1), - currentHead > forkNext ? 0 : forkNext // Use 0 if there are no known next forks - )); + forkNext = forkIds.get(forkIds.size() - 1).getNext(); + forkIds.add(new ForkId(forkHashes.get(forkHashes.size() - 1), 0)); } - return forkIds; + this.forkAndHashList = forkIds; } private void updateCrc(final CRC32 crc, final Long block) { - byte[] byteRepresentationFork = longToBigEndian(block); + final byte[] byteRepresentationFork = longToBigEndian(block); crc.update(byteRepresentationFork, 0, byteRepresentationFork.length); } @@ -205,35 +175,14 @@ public class ForkIdManager { final Bytes next; Bytes forkIdRLP; - ForkId(final Bytes hash, final Bytes next) { + private ForkId(final Bytes hash, final Bytes next) { this.hash = hash; this.next = next; createForkIdRLP(); } - ForkId(final String hash, final String next) { - this.hash = padToEightBytes(Bytes.fromHexString((hash.length() % 2 == 0 ? "" : "0") + hash)); - if (next.equals("") || next.equals("0x")) { - this.next = Bytes.EMPTY; - } else if (next.startsWith("0x")) { - long asLong = Long.parseLong(next.replaceFirst("0x", ""), 16); - this.next = Bytes.wrap(longToBigEndian(asLong)).trimLeadingZeros(); - } else { - this.next = Bytes.wrap(longToBigEndian(Long.parseLong(next))); - } - createForkIdRLP(); - } - - ForkId(final String hash, final long next) { - this.hash = Bytes.fromHexString(hash); - this.next = Bytes.wrap(longToBigEndian(next)); - createForkIdRLP(); - } - - ForkId(final Bytes hash, final long next) { - this.hash = hash; - this.next = Bytes.wrap(longToBigEndian(next)); - createForkIdRLP(); + public ForkId(final Bytes hash, final long next) { + this(hash, Bytes.wrap(longToBigEndian(next)).trimLeadingZeros()); } public long getNext() { @@ -245,7 +194,7 @@ public class ForkIdManager { } void createForkIdRLP() { - BytesValueRLPOutput out = new BytesValueRLPOutput(); + final BytesValueRLPOutput out = new BytesValueRLPOutput(); writeTo(out); forkIdRLP = out.encoded(); } @@ -260,26 +209,17 @@ public class ForkIdManager { public static ForkId readFrom(final RLPInput in) { in.enterList(); final Bytes hash = in.readBytes(); - final long next = in.readLong(); + final long next = in.readLongScalar(); in.leaveList(); return new ForkId(hash, next); } public List asList() { - ArrayList forRLP = new ArrayList<>(); + final ArrayList forRLP = new ArrayList<>(); forRLP.add(this); return forRLP; } - private static Bytes padToEightBytes(final Bytes hash) { - if (hash.size() < 4) { - Bytes padded = Bytes.concatenate(hash, Bytes.fromHexString("0x00")); - return padToEightBytes(padded); - } else { - return hash; - } - } - @Override public String toString() { return "ForkId(hash=" + this.hash + ", next=" + next.toLong() + ")"; @@ -288,8 +228,8 @@ public class ForkIdManager { @Override public boolean equals(final Object obj) { if (obj instanceof ForkId) { - ForkId other = (ForkId) obj; - long thisNext = next.toLong(); + final ForkId other = (ForkId) obj; + final long thisNext = next.toLong(); return other.getHash().equals(this.hash) && thisNext == other.getNext(); } return false; @@ -304,7 +244,7 @@ public class ForkIdManager { // next two methods adopted from: // https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/util/Pack.java private static byte[] longToBigEndian(final long n) { - byte[] bs = new byte[8]; + final byte[] bs = new byte[8]; intToBigEndian((int) (n >>> 32), bs, 0); intToBigEndian((int) (n & 0xffffffffL), bs, 4); return bs; diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java index 80050ecd92..c3847878cf 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java @@ -182,15 +182,16 @@ public final class StatusMessage extends AbstractMessageData { final Difficulty totalDifficulty = Difficulty.of(in.readUInt256Scalar()); final Hash bestHash = Hash.wrap(in.readBytes32()); final Hash genesisHash = Hash.wrap(in.readBytes32()); + final ForkIdManager.ForkId forkId; if (in.nextIsList()) { - final ForkIdManager.ForkId forkId = ForkIdManager.ForkId.readFrom(in); - in.leaveList(); - return new EthStatus( - protocolVersion, networkId, totalDifficulty, bestHash, genesisHash, forkId); + forkId = ForkIdManager.ForkId.readFrom(in); + } else { + forkId = null; } in.leaveList(); - return new EthStatus(protocolVersion, networkId, totalDifficulty, bestHash, genesisHash); + return new EthStatus( + protocolVersion, networkId, totalDifficulty, bestHash, genesisHash, forkId); } } } 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 b2d70f21ca..e9666a486b 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 @@ -1094,7 +1094,7 @@ public final class EthProtocolManagerTest { EthProtocolConfiguration.defaultConfig(), TestClock.fixed(), metricsSystem, - ForkIdManager.buildCollection(blockchain.getBlockHashByNumber(0L).get()))) { + new ForkIdManager(blockchain, Collections.emptyList()))) { // Create a transaction pool. This has a side effect of registering a listener for the // transactions message. diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java index 15265a68a0..2ecba9f725 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java @@ -63,7 +63,7 @@ public class EthProtocolManagerTestUtil { EthProtocolConfiguration.defaultConfig(), TestClock.fixed(), new NoOpMetricsSystem(), - ForkIdManager.buildCollection(blockchain.getBlockHashByNumber(0L).get())); + new ForkIdManager(blockchain, Collections.emptyList())); } public static EthProtocolManager create( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManagerTest.java index 13ad8e1c7c..51c047891b 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManagerTest.java @@ -15,7 +15,12 @@ package org.hyperledger.besu.ethereum.eth.manager; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.Block; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; @@ -32,86 +37,123 @@ public class ForkIdManagerTest { private final String mainnetGenHash = "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"; + private Blockchain mockBlockchain(final String genesisHash, final long chainHeight) { + final Blockchain mockchain = mock(Blockchain.class); + final BlockHeader mockHeader = mock(BlockHeader.class); + final Block block = new Block(mockHeader, null); + when(mockchain.getGenesisBlock()).thenReturn(block); + when(mockchain.getChainHeadBlockNumber()).thenReturn(chainHeight); + when(mockHeader.getHash()).thenReturn(Hash.fromHexString(genesisHash)); + return mockchain; + } + @Test public void checkItFunctionsWithPresentBehavior() { - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), Collections.emptyList(), null); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 0), Collections.emptyList()); assertThat(forkIdManager.peerCheck(Hash.fromHexString(mainnetGenHash))).isFalse(); assertThat(forkIdManager.getLatestForkId()).isNull(); } @Test public void checkCorrectMainnetForkIdHashesGenerated() { - ForkIdManager.ForkId[] checkIds = { - ForkIdManager.createIdEntry("0xfc64ec04", 1150000L), // Unsynced - ForkIdManager.createIdEntry("0x97c2c34c", 1920000L), // First Homestead block - ForkIdManager.createIdEntry("0x91d1f948", 2463000L), // First DAO block - ForkIdManager.createIdEntry("0x7a64da13", 2675000L), // First Tangerine block - ForkIdManager.createIdEntry("0x3edd5b10", 4370000L), // First Spurious block - ForkIdManager.createIdEntry("0xa00bc324", 7280000L), // First Byzantium block - ForkIdManager.createIdEntry("0x668db0af", 0L) // Today Petersburg block + final ForkIdManager.ForkId[] checkIds = { + new ForkIdManager.ForkId(Bytes.fromHexString("0xfc64ec04"), 1150000L), // Unsynced + new ForkIdManager.ForkId( + Bytes.fromHexString("0x97c2c34c"), 1920000L), // First Homestead block + new ForkIdManager.ForkId(Bytes.fromHexString("0x91d1f948"), 2463000L), // First DAO block + new ForkIdManager.ForkId( + Bytes.fromHexString("0x7a64da13"), 2675000L), // First Tangerine block + new ForkIdManager.ForkId(Bytes.fromHexString("0x3edd5b10"), 4370000L), // First Spurious block + new ForkIdManager.ForkId( + Bytes.fromHexString("0xa00bc324"), 7280000L), // First Byzantium block + new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), 0L) // Today Petersburg block }; - List list = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - ForkIdManager.buildCollection(Hash.fromHexString(mainnetGenHash), list); - List entries = forkIdManager.getForkAndHashList(); + final List list = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(mainnetGenHash, 0), list); + final List entries = forkIdManager.getForkAndHashList(); assertThat(entries).containsExactly(checkIds); assertThat(forkIdManager.getLatestForkId()).isNotNull(); - assertThat(forkIdManager.getLatestForkId().equals(checkIds[6])).isTrue(); + assertThat(forkIdManager.getLatestForkId()).isEqualTo(checkIds[6]); } @Test public void checkCorrectRopstenForkIdHashesGenerated() { - Long[] forks = {10L, 1700000L, 4230000L, 4939394L}; - String genHash = "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"; - ForkIdManager.ForkId[] checkIds = { - ForkIdManager.createIdEntry( - "0x30c7ddbc", 10L), // Unsynced, last Frontier, Homestead and first Tangerine block - ForkIdManager.createIdEntry("0x63760190", 1700000L), // First Spurious block - ForkIdManager.createIdEntry("0x3ea159c7", 4230000L), // First Byzantium block - ForkIdManager.createIdEntry("0x97b544f3", 4939394L), // First Constantinople block - ForkIdManager.createIdEntry("0xd6e2149b", 0L) // Today Petersburg block + final Long[] forks = {10L, 1700000L, 4230000L, 4939394L}; + final String genHash = "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"; + final ForkIdManager.ForkId[] checkIds = { + new ForkIdManager.ForkId( + Bytes.fromHexString("0x30c7ddbc"), + 10L), // Unsynced, last Frontier, Homestead and first Tangerine block + new ForkIdManager.ForkId(Bytes.fromHexString("0x63760190"), 1700000L), // First Spurious block + new ForkIdManager.ForkId( + Bytes.fromHexString("0x3ea159c7"), 4230000L), // First Byzantium block + new ForkIdManager.ForkId( + Bytes.fromHexString("0x97b544f3"), 4939394L), // First Constantinople block + new ForkIdManager.ForkId(Bytes.fromHexString("0xd6e2149b"), 0L) // Today Petersburg block }; - List list = Arrays.asList(forks); - ForkIdManager forkIdManager = ForkIdManager.buildCollection(Hash.fromHexString(genHash), list); - List entries = forkIdManager.getForkAndHashList(); + final List list = Arrays.asList(forks); + final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(genHash, 0), list); + final List entries = forkIdManager.getForkAndHashList(); assertThat(entries).containsExactly(checkIds); assertThat(forkIdManager.getLatestForkId()).isNotNull(); - assertThat(forkIdManager.getLatestForkId().equals(checkIds[4])).isTrue(); + assertThat(forkIdManager.getLatestForkId()).isEqualTo(checkIds[4]); } @Test public void checkCorrectRinkebyForkIdHashesGenerated() { - Long[] forks = {1L, 2L, 3L, 1035301L, 3660663L, 4321234L}; - String genHash = "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; - ForkIdManager.ForkId[] checkIds = { - ForkIdManager.createIdEntry( - "0x3b8e0691", 1L), // Unsynced, last Frontier, Homestead and first Tangerine block - ForkIdManager.createIdEntry("0x60949295", 2L), // Last Tangerine block - ForkIdManager.createIdEntry("0x8bde40dd", 3L), // First Spurious block - ForkIdManager.createIdEntry("0xcb3a64bb", 1035301L), // First Byzantium block - ForkIdManager.createIdEntry("0x8d748b57", 3660663L), // First Constantinople block - ForkIdManager.createIdEntry("0xe49cab14", 4321234L), // First Petersburg block - ForkIdManager.createIdEntry("0xafec6b27", 0L) // Today Petersburg block + final Long[] forks = {1L, 2L, 3L, 1035301L, 3660663L, 4321234L}; + final String genHash = "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; + final ForkIdManager.ForkId[] checkIds = { + new ForkIdManager.ForkId( + Bytes.fromHexString("0x3b8e0691"), + 1L), // Unsynced, last Frontier, Homestead and first Tangerine block + new ForkIdManager.ForkId(Bytes.fromHexString("0x60949295"), 2L), // Last Tangerine block + new ForkIdManager.ForkId(Bytes.fromHexString("0x8bde40dd"), 3L), // First Spurious block + new ForkIdManager.ForkId( + Bytes.fromHexString("0xcb3a64bb"), 1035301L), // First Byzantium block + new ForkIdManager.ForkId( + Bytes.fromHexString("0x8d748b57"), 3660663L), // First Constantinople block + new ForkIdManager.ForkId( + Bytes.fromHexString("0xe49cab14"), 4321234L), // First Petersburg block + new ForkIdManager.ForkId(Bytes.fromHexString("0xafec6b27"), 0L) // Today Petersburg block + }; + final List list = Arrays.asList(forks); + final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(genHash, 0), list); + final List entries = forkIdManager.getForkAndHashList(); + + assertThat(entries).containsExactly(checkIds); + assertThat(forkIdManager.getLatestForkId()).isNotNull(); + assertThat(forkIdManager.getLatestForkId()).isEqualTo(checkIds[6]); + } + + @Test + public void checkCorrectGoerliForkIdHashesGenerated() { + final Long[] forks = {1561651L}; + final String genHash = "0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a"; + final ForkIdManager.ForkId[] checkIds = { + new ForkIdManager.ForkId(Bytes.fromHexString("0xa3f5ab08"), 1561651L), // Frontier->Petersburg + new ForkIdManager.ForkId(Bytes.fromHexString("0xc25efa5c"), 0L) // Istanbul }; - List list = Arrays.asList(forks); - ForkIdManager forkIdManager = ForkIdManager.buildCollection(Hash.fromHexString(genHash), list); - List entries = forkIdManager.getForkAndHashList(); + final List list = Arrays.asList(forks); + final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(genHash, 0), list); + final List entries = forkIdManager.getForkAndHashList(); assertThat(entries).containsExactly(checkIds); assertThat(forkIdManager.getLatestForkId()).isNotNull(); - assertThat(forkIdManager.getLatestForkId().equals(checkIds[6])).isTrue(); + assertThat(forkIdManager.getLatestForkId()).isEqualTo(checkIds[1]); } @Test public void check1PetersburgWithRemoteAnnouncingTheSame() { // 1 Local is mainnet Petersburg, remote announces the same. No future fork is announced. // {7987396, ID{Hash: 0x668db0af, Next: 0}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), 0L)); assertThat(result).isTrue(); assertThat(forkIdManager.getLatestForkId()).isNotNull(); } @@ -121,11 +163,12 @@ public class ForkIdManagerTest { // 2 Local is mainnet Petersburg, remote announces the same. Remote also announces a next fork // at block 0xffffffff, but that is uncertain. // {7987396, ID{Hash: 0x668db0af, Next: math.MaxUint64}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); - Boolean result = - forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", Long.MAX_VALUE)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck( + new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), Long.MAX_VALUE)); assertThat(result).isTrue(); } @@ -136,10 +179,11 @@ public class ForkIdManagerTest { // the fork). // In this case we don't know if Petersburg passed yet or not. // {7279999, ID{Hash: 0xa00bc324, Next: 0}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7279999L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 0L)); assertThat(result).isTrue(); } @@ -149,10 +193,12 @@ public class ForkIdManagerTest { // announces also Byzantium, and it's also aware of Petersburg (e.g. updated node before the // fork). We don't know if Petersburg passed yet (will pass) or not. // {7279999, ID{Hash: 0xa00bc324, Next: 7280000}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 7280000L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck( + new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 7280000L)); assertThat(result).isTrue(); } @@ -163,11 +209,12 @@ public class ForkIdManagerTest { // Petersburg). // As neither forks passed at neither nodes, they may mismatch, but we still connect for now. // {7279999, ID{Hash: 0xa00bc324, Next: math.MaxUint64}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); - Boolean result = - forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", Long.MAX_VALUE)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7279999), forkList); + final Boolean result = + forkIdManager.peerCheck( + new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), Long.MAX_VALUE)); assertThat(result).isTrue(); } @@ -176,10 +223,12 @@ public class ForkIdManagerTest { // 6 Local is mainnet Petersburg, remote announces Byzantium + knowledge about Petersburg. // Remote is simply out of sync, accept. // {7987396, ID{Hash: 0x668db0af, Next: 7280000}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 7280000L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck( + new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), 7280000L)); assertThat(result).isTrue(); } @@ -189,10 +238,12 @@ public class ForkIdManagerTest { // Remote is definitely out of sync. It may or may not need the Petersburg update, we don't know // yet. // {7987396, ID{Hash: 0x3edd5b10, Next: 4370000}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x3edd5b10", 4370000L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck( + new ForkIdManager.ForkId(Bytes.fromHexString("0x3edd5b10"), 4370000L)); assertThat(result).isTrue(); } @@ -200,10 +251,11 @@ public class ForkIdManagerTest { public void check8ByzantiumWithRemoteAnnouncingPetersburgLocalOutOfSync() { // 8 Local is mainnet Byzantium, remote announces Petersburg. Local is out of sync, accept. // {7279999, ID{Hash: 0x668db0af, Next: 0}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 727999L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), 0L)); assertThat(result).isTrue(); } @@ -212,10 +264,11 @@ public class ForkIdManagerTest { // 9 Local is mainnet Spurious, remote announces Byzantium, but is not aware of Petersburg. // Local out of sync. Local also knows about a future fork, but that is uncertain yet. // {4369999, ID{Hash: 0xa00bc324, Next: 0}, nil}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 4369999L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 4369999L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 0L)); assertThat(result).isTrue(); } @@ -224,10 +277,11 @@ public class ForkIdManagerTest { // 10 Local is mainnet Petersburg. remote announces Byzantium but is not aware of further forks. // Remote needs software update. // {7987396, ID{Hash: 0xa00bc324, Next: 0}, ErrRemoteStale}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 0L)); assertThat(result).isFalse(); } @@ -236,10 +290,11 @@ public class ForkIdManagerTest { // 11 Local is mainnet Petersburg, and isn't aware of more forks. Remote announces Petersburg + // 0xffffffff. Local needs software update, reject. // {7987396, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x5cddc0e1", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x5cddc0e1"), 0L)); assertThat(result).isFalse(); } @@ -248,10 +303,11 @@ public class ForkIdManagerTest { // 12 Local is mainnet Byzantium, and is aware of Petersburg. Remote announces Petersburg + // 0xffffffff. Local needs software update, reject. // {7279999, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x5cddc0e1", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7279999L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x5cddc0e1"), 0L)); assertThat(result).isFalse(); } @@ -259,62 +315,66 @@ public class ForkIdManagerTest { public void check13ByzantiumWithRemoteAnnouncingRinkebyPetersburg() { // 13 Local is mainnet Petersburg, remote is Rinkeby Petersburg. // {7987396, ID{Hash: 0xafec6b27, Next: 0}, ErrLocalIncompatibleOrStale}, - List forkList = Arrays.asList(forksMainnet); - ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); - Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xafec6b27", 0L)); + final List forkList = Arrays.asList(forksMainnet); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList); + final Boolean result = + forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xafec6b27"), 0L)); assertThat(result).isFalse(); } @Test public void createAndDecodeRLP() { - ForkIdManager.ForkId forkIdEntry = ForkIdManager.createIdEntry("0xa00bc324", 7280000L); - BytesValueRLPOutput out = new BytesValueRLPOutput(); + final ForkIdManager.ForkId forkIdEntry = + new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 7280000L); + final BytesValueRLPOutput out = new BytesValueRLPOutput(); forkIdEntry.writeTo(out); - Bytes bytesValue = out.encoded(); - BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); - ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); - assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); + final Bytes bytesValue = out.encoded(); + final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); + final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); + assertThat(forkIdEntry).isEqualTo(decodedEntry); } @Test public void check1ZeroZeroProperRLPEncoding() { - ForkIdManager.ForkId forkIdEntry = ForkIdManager.createIdEntry("0", "0x"); - BytesValueRLPOutput out = new BytesValueRLPOutput(); + final ForkIdManager.ForkId forkIdEntry = + new ForkIdManager.ForkId(Bytes.fromHexString("0x00000000"), 0); + final BytesValueRLPOutput out = new BytesValueRLPOutput(); forkIdEntry.writeTo(out); - String str1 = "0xc6840000000080"; - Bytes bytesValue = out.encoded(); - assertThat(str1.equals(bytesValue.toString())).isTrue(); - BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); - ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); - assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); + final String str1 = "0xc6840000000080"; + final Bytes bytesValue = out.encoded(); + assertThat(str1).isEqualTo(bytesValue.toString()); + final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); + final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); + assertThat(forkIdEntry).isEqualTo(decodedEntry); } @Test public void check2ArbitraryProperRLPEncoding() { - ForkIdManager.ForkId forkIdEntry = ForkIdManager.createIdEntry("0xdeadbeef", "0xBADDCAFE"); - BytesValueRLPOutput out = new BytesValueRLPOutput(); + final ForkIdManager.ForkId forkIdEntry = + new ForkIdManager.ForkId(Bytes.fromHexString("0xdeadbeef"), 0xbaddcafeL); + final BytesValueRLPOutput out = new BytesValueRLPOutput(); forkIdEntry.writeTo(out); - String str1 = "0xca84deadbeef84baddcafe"; - Bytes bytesValue = out.encoded(); - assertThat(str1.equals(bytesValue.toString())).isTrue(); - BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); - ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); - assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); + final String str1 = "0xca84deadbeef84baddcafe"; + final Bytes bytesValue = out.encoded(); + assertThat(str1).isEqualTo(bytesValue.toString()); + final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); + final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); + assertThat(forkIdEntry).isEqualTo(decodedEntry); } @Test public void check3MaximumsProperRLPEncoding() { - ForkIdManager.ForkId forkIdEntry = - ForkIdManager.createIdEntry("0xffffffff", Long.parseUnsignedLong("ffffffffffffffff", 16)); - BytesValueRLPOutput out = new BytesValueRLPOutput(); + final ForkIdManager.ForkId forkIdEntry = + new ForkIdManager.ForkId(Bytes.fromHexString("0xffffffff"), 0xffffffffffffffffL); + final BytesValueRLPOutput out = new BytesValueRLPOutput(); forkIdEntry.writeTo(out); - String str1 = + final String str1 = "0xce84ffffffff88ffffffffffffffff"; // Check value supplied in EIP-2124 spec via GO lang - Bytes bytesValue = out.encoded(); - assertThat(str1.equals(bytesValue.toString())).isTrue(); - BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); - ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); - assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); + final Bytes bytesValue = out.encoded(); + assertThat(str1).isEqualTo(bytesValue.toString()); + final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); + final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); + assertThat(forkIdEntry).isEqualTo(decodedEntry); } } 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 ce6ad7d4da..1bdf3dc543 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 @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; import java.math.BigInteger; import java.util.Random; +import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.junit.Test; @@ -74,7 +75,8 @@ public class StatusMessageTest { final Difficulty td = Difficulty.of(1000L); final Hash bestHash = randHash(1L); final Hash genesisHash = randHash(2L); - final ForkIdManager.ForkId forkId = ForkIdManager.createIdEntry("0xa00bc334", 0L); + final ForkIdManager.ForkId forkId = + new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc334"), 0L); final MessageData msg = StatusMessage.create(version, networkId, td, bestHash, genesisHash, forkId);