Implement Eth/64 (#425)

Wire in the fork identifier into the status messages as Eth64.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
pull/429/head
Danno Ferrin 5 years ago committed by GitHub
parent 0a19f4750f
commit 7fe1d4796e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocol.java
  2. 42
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java
  3. 126
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java
  4. 11
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java
  5. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java
  6. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java
  7. 316
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManagerTest.java
  8. 4
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java

@ -64,6 +64,7 @@ public class EthProtocol implements SubProtocol {
case EthVersion.V62: case EthVersion.V62:
return 8; return 8;
case EthVersion.V63: case EthVersion.V63:
case EthVersion.V64:
return 17; return 17;
default: default:
return 0; return 0;
@ -76,6 +77,7 @@ public class EthProtocol implements SubProtocol {
case EthVersion.V62: case EthVersion.V62:
return eth62Messages.contains(code); return eth62Messages.contains(code);
case EthVersion.V63: case EthVersion.V63:
case EthVersion.V64:
return eth63Messages.contains(code); return eth63Messages.contains(code);
default: default:
return false; return false;

@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; 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.EthPV62;
import org.hyperledger.besu.ethereum.eth.messages.StatusMessage; import org.hyperledger.besu.ethereum.eth.messages.StatusMessage;
import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; 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.math.BigInteger;
import java.time.Clock; import java.time.Clock;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import com.google.common.annotations.VisibleForTesting;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
public class EthProtocolManager implements ProtocolManager, MinedBlockObserver { public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
private static final Logger LOG = LogManager.getLogger(); private static final Logger LOG = LogManager.getLogger();
private static final List<Capability> FAST_SYNC_CAPS = private static final List<Capability> FAST_SYNC_CAPS =
Collections.singletonList(EthProtocol.ETH63); List.of(EthProtocol.ETH63, EthProtocol.ETH64);
private static final List<Capability> FULL_SYNC_CAPS = private static final List<Capability> FULL_SYNC_CAPS =
Arrays.asList(EthProtocol.ETH62, EthProtocol.ETH63); List.of(EthProtocol.ETH62, EthProtocol.ETH63, EthProtocol.ETH64);
private final EthScheduler scheduler; private final EthScheduler scheduler;
private final CountDownLatch shutdown; private final CountDownLatch shutdown;
@ -93,7 +94,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
this.shutdown = new CountDownLatch(1); this.shutdown = new CountDownLatch(1);
genesisHash = blockchain.getBlockHashByNumber(0L).get(); genesisHash = blockchain.getBlockHashByNumber(0L).get();
this.forkIdManager = ForkIdManager.buildCollection(genesisHash); this.forkIdManager = forkIdManager;
ethPeers = new EthPeers(getSupportedProtocol(), clock, metricsSystem); ethPeers = new EthPeers(getSupportedProtocol(), clock, metricsSystem);
ethMessages = new EthMessages(); ethMessages = new EthMessages();
@ -110,30 +111,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
new EthServer(blockchain, worldStateArchive, ethMessages, ethereumWireProtocolConfiguration); new EthServer(blockchain, worldStateArchive, ethMessages, ethereumWireProtocolConfiguration);
} }
public EthProtocolManager( @VisibleForTesting
final Blockchain blockchain,
final WorldStateArchive worldStateArchive,
final BigInteger networkId,
final List<PeerValidator> 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()));
}
public EthProtocolManager( public EthProtocolManager(
final Blockchain blockchain, final Blockchain blockchain,
final WorldStateArchive worldStateArchive, final WorldStateArchive worldStateArchive,
@ -156,7 +134,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
ethereumWireProtocolConfiguration, ethereumWireProtocolConfiguration,
clock, clock,
metricsSystem, metricsSystem,
ForkIdManager.buildCollection(blockchain.getBlockHashByNumber(0L).get())); new ForkIdManager(blockchain, Collections.emptyList()));
} }
public EthProtocolManager( public EthProtocolManager(
@ -182,8 +160,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
ethereumWireProtocolConfiguration, ethereumWireProtocolConfiguration,
clock, clock,
metricsSystem, metricsSystem,
ForkIdManager.buildCollection( new ForkIdManager(blockchain, forks));
blockchain.getBlockHashByNumber(0L).get(), forks, blockchain));
} }
public EthContext ethContext() { public EthContext ethContext() {
@ -274,6 +251,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
} }
final Capability cap = connection.capability(getSupportedProtocol()); final Capability cap = connection.capability(getSupportedProtocol());
final ForkId latestForkId = cap.getVersion() >= 64 ? forkIdManager.getLatestForkId() : null;
// TODO: look to consolidate code below if possible // TODO: look to consolidate code below if possible
// making status non-final and implementing it above would be one way. // making status non-final and implementing it above would be one way.
final StatusMessage status = final StatusMessage status =
@ -283,7 +261,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHead().getTotalDifficulty(),
blockchain.getChainHeadHash(), blockchain.getChainHeadHash(),
genesisHash, genesisHash,
forkIdManager.getLatestForkId()); latestForkId);
try { try {
LOG.debug("Sending status message to {}.", peer); LOG.debug("Sending status message to {}.", peer);
peer.send(status); peer.send(status);

@ -14,8 +14,6 @@
*/ */
package org.hyperledger.besu.ethereum.eth.manager; 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.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
@ -27,52 +25,28 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.CRC32; import java.util.zip.CRC32;
import com.google.common.annotations.VisibleForTesting;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
public class ForkIdManager { public class ForkIdManager {
private final Blockchain blockchain;
private final Hash genesisHash; private final Hash genesisHash;
private final Long currentHead; private final List<Long> forks;
private Long forkNext; private long forkNext;
private final Long highestKnownFork = 0L; private final long highestKnownFork;
private final List<ForkId> forkAndHashList; private List<ForkId> forkAndHashList;
public ForkIdManager(final Hash genesisHash, final List<Long> forks, final Long currentHead) { public ForkIdManager(final Blockchain blockchain, final List<Long> forks) {
this.genesisHash = genesisHash; this.blockchain = blockchain;
this.currentHead = currentHead; this.genesisHash = blockchain.getGenesisBlock().getHash();
this.forkAndHashList = // de-dupe and sanitize forks
createForkIds( this.forks =
// If there are two forks at the same block height, we only want to add it once to the forks.stream().filter(fork -> fork > 0).distinct().collect(Collectors.toUnmodifiableList());
// crc checksum highestKnownFork = forks.size() > 0 ? forks.get(forks.size() - 1) : 0L;
forks.stream().distinct().collect(Collectors.toUnmodifiableList())); createForkIds();
};
static ForkIdManager buildCollection(
final Hash genesisHash, final List<Long> forks, final Blockchain blockchain) {
return new ForkIdManager(genesisHash, forks, blockchain.getChainHeadBlockNumber());
};
@VisibleForTesting
public static ForkIdManager buildCollection(final Hash genesisHash, final List<Long> forks) {
return new ForkIdManager(genesisHash, forks, Long.MAX_VALUE);
};
static ForkIdManager buildCollection(final Hash genesisHash) {
return new ForkIdManager(genesisHash, emptyList(), Long.MAX_VALUE);
}; };
// 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<ForkId> getForkAndHashList() { public List<ForkId> getForkAndHashList() {
return this.forkAndHashList; return this.forkAndHashList;
} }
@ -98,11 +72,11 @@ public class ForkIdManager {
* @param forkId to be validated. * @param forkId to be validated.
* @return boolean (peer valid (true) or invalid (false)) * @return boolean (peer valid (true) or invalid (false))
*/ */
public boolean peerCheck(final ForkId forkId) { boolean peerCheck(final ForkId forkId) {
if (forkId == null) { if (forkId == null) {
return true; // Another method must be used to validate (i.e. genesis hash) 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. // 1. If local and remote FORK_CSUM matches, connect.
// The two nodes are in the same fork state currently. They might know // 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 // of differing future forks, but that's not relevant until the fork
@ -119,7 +93,7 @@ public class ForkIdManager {
// information. // information.
// 4. Reject in all other cases. // 4. Reject in all other cases.
if (isHashKnown(forkId.getHash())) { if (isHashKnown(forkId.getHash())) {
if (currentHead < forkNext) { if (blockchain.getChainHeadBlockNumber() < forkNext) {
return true; return true;
} else { } else {
if (isForkKnown(forkId.getNext())) { if (isForkKnown(forkId.getNext())) {
@ -153,7 +127,7 @@ public class ForkIdManager {
} }
private boolean isRemoteAwareOfPresent(final Bytes forkHash, final Long nextFork) { private boolean isRemoteAwareOfPresent(final Bytes forkHash, final Long nextFork) {
for (ForkId j : forkAndHashList) { for (final ForkId j : forkAndHashList) {
if (forkHash.equals(j.getHash())) { if (forkHash.equals(j.getHash())) {
if (nextFork.equals(j.getNext())) { if (nextFork.equals(j.getNext())) {
return true; return true;
@ -167,9 +141,9 @@ public class ForkIdManager {
return false; return false;
} }
private List<ForkId> createForkIds(final List<Long> forks) { private void createForkIds() {
final CRC32 crc = new CRC32(); final CRC32 crc = new CRC32();
crc.update(this.genesisHash.toArray()); crc.update(genesisHash.toArray());
final List<Bytes> forkHashes = new ArrayList<>(List.of(getCurrentCrcHash(crc))); final List<Bytes> forkHashes = new ArrayList<>(List.of(getCurrentCrcHash(crc)));
for (final Long fork : forks) { for (final Long fork : forks) {
updateCrc(crc, fork); updateCrc(crc, fork);
@ -181,18 +155,14 @@ public class ForkIdManager {
forkIds.add(new ForkId(forkHashes.get(i), forks.get(i))); forkIds.add(new ForkId(forkHashes.get(i), forks.get(i)));
} }
if (!forks.isEmpty()) { if (!forks.isEmpty()) {
this.forkNext = forkIds.get(forkIds.size() - 1).getNext(); forkNext = forkIds.get(forkIds.size() - 1).getNext();
forkIds.add( forkIds.add(new ForkId(forkHashes.get(forkHashes.size() - 1), 0));
new ForkId(
forkHashes.get(forkHashes.size() - 1),
currentHead > forkNext ? 0 : forkNext // Use 0 if there are no known next forks
));
} }
return forkIds; this.forkAndHashList = forkIds;
} }
private void updateCrc(final CRC32 crc, final Long block) { private void updateCrc(final CRC32 crc, final Long block) {
byte[] byteRepresentationFork = longToBigEndian(block); final byte[] byteRepresentationFork = longToBigEndian(block);
crc.update(byteRepresentationFork, 0, byteRepresentationFork.length); crc.update(byteRepresentationFork, 0, byteRepresentationFork.length);
} }
@ -205,35 +175,14 @@ public class ForkIdManager {
final Bytes next; final Bytes next;
Bytes forkIdRLP; Bytes forkIdRLP;
ForkId(final Bytes hash, final Bytes next) { private ForkId(final Bytes hash, final Bytes next) {
this.hash = hash; this.hash = hash;
this.next = next; this.next = next;
createForkIdRLP(); createForkIdRLP();
} }
ForkId(final String hash, final String next) { public ForkId(final Bytes hash, final long next) {
this.hash = padToEightBytes(Bytes.fromHexString((hash.length() % 2 == 0 ? "" : "0") + hash)); this(hash, Bytes.wrap(longToBigEndian(next)).trimLeadingZeros());
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 long getNext() { public long getNext() {
@ -245,7 +194,7 @@ public class ForkIdManager {
} }
void createForkIdRLP() { void createForkIdRLP() {
BytesValueRLPOutput out = new BytesValueRLPOutput(); final BytesValueRLPOutput out = new BytesValueRLPOutput();
writeTo(out); writeTo(out);
forkIdRLP = out.encoded(); forkIdRLP = out.encoded();
} }
@ -260,26 +209,17 @@ public class ForkIdManager {
public static ForkId readFrom(final RLPInput in) { public static ForkId readFrom(final RLPInput in) {
in.enterList(); in.enterList();
final Bytes hash = in.readBytes(); final Bytes hash = in.readBytes();
final long next = in.readLong(); final long next = in.readLongScalar();
in.leaveList(); in.leaveList();
return new ForkId(hash, next); return new ForkId(hash, next);
} }
public List<ForkId> asList() { public List<ForkId> asList() {
ArrayList<ForkId> forRLP = new ArrayList<>(); final ArrayList<ForkId> forRLP = new ArrayList<>();
forRLP.add(this); forRLP.add(this);
return forRLP; 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 @Override
public String toString() { public String toString() {
return "ForkId(hash=" + this.hash + ", next=" + next.toLong() + ")"; return "ForkId(hash=" + this.hash + ", next=" + next.toLong() + ")";
@ -288,8 +228,8 @@ public class ForkIdManager {
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
if (obj instanceof ForkId) { if (obj instanceof ForkId) {
ForkId other = (ForkId) obj; final ForkId other = (ForkId) obj;
long thisNext = next.toLong(); final long thisNext = next.toLong();
return other.getHash().equals(this.hash) && thisNext == other.getNext(); return other.getHash().equals(this.hash) && thisNext == other.getNext();
} }
return false; return false;
@ -304,7 +244,7 @@ public class ForkIdManager {
// next two methods adopted from: // next two methods adopted from:
// https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/util/Pack.java // https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/util/Pack.java
private static byte[] longToBigEndian(final long n) { 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 >>> 32), bs, 0);
intToBigEndian((int) (n & 0xffffffffL), bs, 4); intToBigEndian((int) (n & 0xffffffffL), bs, 4);
return bs; return bs;

@ -182,15 +182,16 @@ public final class StatusMessage extends AbstractMessageData {
final Difficulty totalDifficulty = Difficulty.of(in.readUInt256Scalar()); final Difficulty totalDifficulty = Difficulty.of(in.readUInt256Scalar());
final Hash bestHash = Hash.wrap(in.readBytes32()); final Hash bestHash = Hash.wrap(in.readBytes32());
final Hash genesisHash = Hash.wrap(in.readBytes32()); final Hash genesisHash = Hash.wrap(in.readBytes32());
final ForkIdManager.ForkId forkId;
if (in.nextIsList()) { if (in.nextIsList()) {
final ForkIdManager.ForkId forkId = ForkIdManager.ForkId.readFrom(in); forkId = ForkIdManager.ForkId.readFrom(in);
in.leaveList(); } else {
return new EthStatus( forkId = null;
protocolVersion, networkId, totalDifficulty, bestHash, genesisHash, forkId);
} }
in.leaveList(); in.leaveList();
return new EthStatus(protocolVersion, networkId, totalDifficulty, bestHash, genesisHash); return new EthStatus(
protocolVersion, networkId, totalDifficulty, bestHash, genesisHash, forkId);
} }
} }
} }

@ -1094,7 +1094,7 @@ public final class EthProtocolManagerTest {
EthProtocolConfiguration.defaultConfig(), EthProtocolConfiguration.defaultConfig(),
TestClock.fixed(), TestClock.fixed(),
metricsSystem, 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 // Create a transaction pool. This has a side effect of registering a listener for the
// transactions message. // transactions message.

@ -63,7 +63,7 @@ public class EthProtocolManagerTestUtil {
EthProtocolConfiguration.defaultConfig(), EthProtocolConfiguration.defaultConfig(),
TestClock.fixed(), TestClock.fixed(),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
ForkIdManager.buildCollection(blockchain.getBlockHashByNumber(0L).get())); new ForkIdManager(blockchain, Collections.emptyList()));
} }
public static EthProtocolManager create( public static EthProtocolManager create(

@ -15,7 +15,12 @@
package org.hyperledger.besu.ethereum.eth.manager; package org.hyperledger.besu.ethereum.eth.manager;
import static org.assertj.core.api.Assertions.assertThat; 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.core.Hash;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
@ -32,86 +37,123 @@ public class ForkIdManagerTest {
private final String mainnetGenHash = private final String mainnetGenHash =
"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"; "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 @Test
public void checkItFunctionsWithPresentBehavior() { public void checkItFunctionsWithPresentBehavior() {
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), Collections.emptyList(), null); new ForkIdManager(mockBlockchain(mainnetGenHash, 0), Collections.emptyList());
assertThat(forkIdManager.peerCheck(Hash.fromHexString(mainnetGenHash))).isFalse(); assertThat(forkIdManager.peerCheck(Hash.fromHexString(mainnetGenHash))).isFalse();
assertThat(forkIdManager.getLatestForkId()).isNull(); assertThat(forkIdManager.getLatestForkId()).isNull();
} }
@Test @Test
public void checkCorrectMainnetForkIdHashesGenerated() { public void checkCorrectMainnetForkIdHashesGenerated() {
ForkIdManager.ForkId[] checkIds = { final ForkIdManager.ForkId[] checkIds = {
ForkIdManager.createIdEntry("0xfc64ec04", 1150000L), // Unsynced new ForkIdManager.ForkId(Bytes.fromHexString("0xfc64ec04"), 1150000L), // Unsynced
ForkIdManager.createIdEntry("0x97c2c34c", 1920000L), // First Homestead block new ForkIdManager.ForkId(
ForkIdManager.createIdEntry("0x91d1f948", 2463000L), // First DAO block Bytes.fromHexString("0x97c2c34c"), 1920000L), // First Homestead block
ForkIdManager.createIdEntry("0x7a64da13", 2675000L), // First Tangerine block new ForkIdManager.ForkId(Bytes.fromHexString("0x91d1f948"), 2463000L), // First DAO block
ForkIdManager.createIdEntry("0x3edd5b10", 4370000L), // First Spurious block new ForkIdManager.ForkId(
ForkIdManager.createIdEntry("0xa00bc324", 7280000L), // First Byzantium block Bytes.fromHexString("0x7a64da13"), 2675000L), // First Tangerine block
ForkIdManager.createIdEntry("0x668db0af", 0L) // Today Petersburg 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<Long> list = Arrays.asList(forksMainnet); final List<Long> list = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(mainnetGenHash, 0), list);
ForkIdManager.buildCollection(Hash.fromHexString(mainnetGenHash), list); final List<ForkIdManager.ForkId> entries = forkIdManager.getForkAndHashList();
List<ForkIdManager.ForkId> entries = forkIdManager.getForkAndHashList();
assertThat(entries).containsExactly(checkIds); assertThat(entries).containsExactly(checkIds);
assertThat(forkIdManager.getLatestForkId()).isNotNull(); assertThat(forkIdManager.getLatestForkId()).isNotNull();
assertThat(forkIdManager.getLatestForkId().equals(checkIds[6])).isTrue(); assertThat(forkIdManager.getLatestForkId()).isEqualTo(checkIds[6]);
} }
@Test @Test
public void checkCorrectRopstenForkIdHashesGenerated() { public void checkCorrectRopstenForkIdHashesGenerated() {
Long[] forks = {10L, 1700000L, 4230000L, 4939394L}; final Long[] forks = {10L, 1700000L, 4230000L, 4939394L};
String genHash = "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"; final String genHash = "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d";
ForkIdManager.ForkId[] checkIds = { final ForkIdManager.ForkId[] checkIds = {
ForkIdManager.createIdEntry( new ForkIdManager.ForkId(
"0x30c7ddbc", 10L), // Unsynced, last Frontier, Homestead and first Tangerine block Bytes.fromHexString("0x30c7ddbc"),
ForkIdManager.createIdEntry("0x63760190", 1700000L), // First Spurious block 10L), // Unsynced, last Frontier, Homestead and first Tangerine block
ForkIdManager.createIdEntry("0x3ea159c7", 4230000L), // First Byzantium block new ForkIdManager.ForkId(Bytes.fromHexString("0x63760190"), 1700000L), // First Spurious block
ForkIdManager.createIdEntry("0x97b544f3", 4939394L), // First Constantinople block new ForkIdManager.ForkId(
ForkIdManager.createIdEntry("0xd6e2149b", 0L) // Today Petersburg block 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<Long> list = Arrays.asList(forks); final List<Long> list = Arrays.asList(forks);
ForkIdManager forkIdManager = ForkIdManager.buildCollection(Hash.fromHexString(genHash), list); final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(genHash, 0), list);
List<ForkIdManager.ForkId> entries = forkIdManager.getForkAndHashList(); final List<ForkIdManager.ForkId> entries = forkIdManager.getForkAndHashList();
assertThat(entries).containsExactly(checkIds); assertThat(entries).containsExactly(checkIds);
assertThat(forkIdManager.getLatestForkId()).isNotNull(); assertThat(forkIdManager.getLatestForkId()).isNotNull();
assertThat(forkIdManager.getLatestForkId().equals(checkIds[4])).isTrue(); assertThat(forkIdManager.getLatestForkId()).isEqualTo(checkIds[4]);
} }
@Test @Test
public void checkCorrectRinkebyForkIdHashesGenerated() { public void checkCorrectRinkebyForkIdHashesGenerated() {
Long[] forks = {1L, 2L, 3L, 1035301L, 3660663L, 4321234L}; final Long[] forks = {1L, 2L, 3L, 1035301L, 3660663L, 4321234L};
String genHash = "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; final String genHash = "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177";
ForkIdManager.ForkId[] checkIds = { final ForkIdManager.ForkId[] checkIds = {
ForkIdManager.createIdEntry( new ForkIdManager.ForkId(
"0x3b8e0691", 1L), // Unsynced, last Frontier, Homestead and first Tangerine block Bytes.fromHexString("0x3b8e0691"),
ForkIdManager.createIdEntry("0x60949295", 2L), // Last Tangerine block 1L), // Unsynced, last Frontier, Homestead and first Tangerine block
ForkIdManager.createIdEntry("0x8bde40dd", 3L), // First Spurious block new ForkIdManager.ForkId(Bytes.fromHexString("0x60949295"), 2L), // Last Tangerine block
ForkIdManager.createIdEntry("0xcb3a64bb", 1035301L), // First Byzantium block new ForkIdManager.ForkId(Bytes.fromHexString("0x8bde40dd"), 3L), // First Spurious block
ForkIdManager.createIdEntry("0x8d748b57", 3660663L), // First Constantinople block new ForkIdManager.ForkId(
ForkIdManager.createIdEntry("0xe49cab14", 4321234L), // First Petersburg block Bytes.fromHexString("0xcb3a64bb"), 1035301L), // First Byzantium block
ForkIdManager.createIdEntry("0xafec6b27", 0L) // Today Petersburg 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<Long> list = Arrays.asList(forks);
final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(genHash, 0), list);
final List<ForkIdManager.ForkId> 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<Long> list = Arrays.asList(forks); final List<Long> list = Arrays.asList(forks);
ForkIdManager forkIdManager = ForkIdManager.buildCollection(Hash.fromHexString(genHash), list); final ForkIdManager forkIdManager = new ForkIdManager(mockBlockchain(genHash, 0), list);
List<ForkIdManager.ForkId> entries = forkIdManager.getForkAndHashList(); final List<ForkIdManager.ForkId> entries = forkIdManager.getForkAndHashList();
assertThat(entries).containsExactly(checkIds); assertThat(entries).containsExactly(checkIds);
assertThat(forkIdManager.getLatestForkId()).isNotNull(); assertThat(forkIdManager.getLatestForkId()).isNotNull();
assertThat(forkIdManager.getLatestForkId().equals(checkIds[6])).isTrue(); assertThat(forkIdManager.getLatestForkId()).isEqualTo(checkIds[1]);
} }
@Test @Test
public void check1PetersburgWithRemoteAnnouncingTheSame() { public void check1PetersburgWithRemoteAnnouncingTheSame() {
// 1 Local is mainnet Petersburg, remote announces the same. No future fork is announced. // 1 Local is mainnet Petersburg, remote announces the same. No future fork is announced.
// {7987396, ID{Hash: 0x668db0af, Next: 0}, nil}, // {7987396, ID{Hash: 0x668db0af, Next: 0}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), 0L));
assertThat(result).isTrue(); assertThat(result).isTrue();
assertThat(forkIdManager.getLatestForkId()).isNotNull(); 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 // 2 Local is mainnet Petersburg, remote announces the same. Remote also announces a next fork
// at block 0xffffffff, but that is uncertain. // at block 0xffffffff, but that is uncertain.
// {7987396, ID{Hash: 0x668db0af, Next: math.MaxUint64}, nil}, // {7987396, ID{Hash: 0x668db0af, Next: math.MaxUint64}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = final Boolean result =
forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", Long.MAX_VALUE)); forkIdManager.peerCheck(
new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), Long.MAX_VALUE));
assertThat(result).isTrue(); assertThat(result).isTrue();
} }
@ -136,10 +179,11 @@ public class ForkIdManagerTest {
// the fork). // the fork).
// In this case we don't know if Petersburg passed yet or not. // In this case we don't know if Petersburg passed yet or not.
// {7279999, ID{Hash: 0xa00bc324, Next: 0}, nil}, // {7279999, ID{Hash: 0xa00bc324, Next: 0}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7279999L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 0L));
assertThat(result).isTrue(); 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 // 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. // fork). We don't know if Petersburg passed yet (will pass) or not.
// {7279999, ID{Hash: 0xa00bc324, Next: 7280000}, nil}, // {7279999, ID{Hash: 0xa00bc324, Next: 7280000}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 7280000L)); final Boolean result =
forkIdManager.peerCheck(
new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 7280000L));
assertThat(result).isTrue(); assertThat(result).isTrue();
} }
@ -163,11 +209,12 @@ public class ForkIdManagerTest {
// Petersburg). // Petersburg).
// As neither forks passed at neither nodes, they may mismatch, but we still connect for now. // As neither forks passed at neither nodes, they may mismatch, but we still connect for now.
// {7279999, ID{Hash: 0xa00bc324, Next: math.MaxUint64}, nil}, // {7279999, ID{Hash: 0xa00bc324, Next: math.MaxUint64}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7279999), forkList);
Boolean result = final Boolean result =
forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", Long.MAX_VALUE)); forkIdManager.peerCheck(
new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), Long.MAX_VALUE));
assertThat(result).isTrue(); assertThat(result).isTrue();
} }
@ -176,10 +223,12 @@ public class ForkIdManagerTest {
// 6 Local is mainnet Petersburg, remote announces Byzantium + knowledge about Petersburg. // 6 Local is mainnet Petersburg, remote announces Byzantium + knowledge about Petersburg.
// Remote is simply out of sync, accept. // Remote is simply out of sync, accept.
// {7987396, ID{Hash: 0x668db0af, Next: 7280000}, nil}, // {7987396, ID{Hash: 0x668db0af, Next: 7280000}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 7280000L)); final Boolean result =
forkIdManager.peerCheck(
new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), 7280000L));
assertThat(result).isTrue(); 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 // Remote is definitely out of sync. It may or may not need the Petersburg update, we don't know
// yet. // yet.
// {7987396, ID{Hash: 0x3edd5b10, Next: 4370000}, nil}, // {7987396, ID{Hash: 0x3edd5b10, Next: 4370000}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x3edd5b10", 4370000L)); final Boolean result =
forkIdManager.peerCheck(
new ForkIdManager.ForkId(Bytes.fromHexString("0x3edd5b10"), 4370000L));
assertThat(result).isTrue(); assertThat(result).isTrue();
} }
@ -200,10 +251,11 @@ public class ForkIdManagerTest {
public void check8ByzantiumWithRemoteAnnouncingPetersburgLocalOutOfSync() { public void check8ByzantiumWithRemoteAnnouncingPetersburgLocalOutOfSync() {
// 8 Local is mainnet Byzantium, remote announces Petersburg. Local is out of sync, accept. // 8 Local is mainnet Byzantium, remote announces Petersburg. Local is out of sync, accept.
// {7279999, ID{Hash: 0x668db0af, Next: 0}, nil}, // {7279999, ID{Hash: 0x668db0af, Next: 0}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); new ForkIdManager(mockBlockchain(mainnetGenHash, 727999L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x668db0af"), 0L));
assertThat(result).isTrue(); assertThat(result).isTrue();
} }
@ -212,10 +264,11 @@ public class ForkIdManagerTest {
// 9 Local is mainnet Spurious, remote announces Byzantium, but is not aware of Petersburg. // 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. // Local out of sync. Local also knows about a future fork, but that is uncertain yet.
// {4369999, ID{Hash: 0xa00bc324, Next: 0}, nil}, // {4369999, ID{Hash: 0xa00bc324, Next: 0}, nil},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 4369999L); new ForkIdManager(mockBlockchain(mainnetGenHash, 4369999L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 0L));
assertThat(result).isTrue(); 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. // 10 Local is mainnet Petersburg. remote announces Byzantium but is not aware of further forks.
// Remote needs software update. // Remote needs software update.
// {7987396, ID{Hash: 0xa00bc324, Next: 0}, ErrRemoteStale}, // {7987396, ID{Hash: 0xa00bc324, Next: 0}, ErrRemoteStale},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 0L));
assertThat(result).isFalse(); 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 + // 11 Local is mainnet Petersburg, and isn't aware of more forks. Remote announces Petersburg +
// 0xffffffff. Local needs software update, reject. // 0xffffffff. Local needs software update, reject.
// {7987396, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale}, // {7987396, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x5cddc0e1", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x5cddc0e1"), 0L));
assertThat(result).isFalse(); assertThat(result).isFalse();
} }
@ -248,10 +303,11 @@ public class ForkIdManagerTest {
// 12 Local is mainnet Byzantium, and is aware of Petersburg. Remote announces Petersburg + // 12 Local is mainnet Byzantium, and is aware of Petersburg. Remote announces Petersburg +
// 0xffffffff. Local needs software update, reject. // 0xffffffff. Local needs software update, reject.
// {7279999, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale}, // {7279999, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7279999L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x5cddc0e1", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0x5cddc0e1"), 0L));
assertThat(result).isFalse(); assertThat(result).isFalse();
} }
@ -259,62 +315,66 @@ public class ForkIdManagerTest {
public void check13ByzantiumWithRemoteAnnouncingRinkebyPetersburg() { public void check13ByzantiumWithRemoteAnnouncingRinkebyPetersburg() {
// 13 Local is mainnet Petersburg, remote is Rinkeby Petersburg. // 13 Local is mainnet Petersburg, remote is Rinkeby Petersburg.
// {7987396, ID{Hash: 0xafec6b27, Next: 0}, ErrLocalIncompatibleOrStale}, // {7987396, ID{Hash: 0xafec6b27, Next: 0}, ErrLocalIncompatibleOrStale},
List<Long> forkList = Arrays.asList(forksMainnet); final List<Long> forkList = Arrays.asList(forksMainnet);
ForkIdManager forkIdManager = final ForkIdManager forkIdManager =
new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); new ForkIdManager(mockBlockchain(mainnetGenHash, 7987396L), forkList);
Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xafec6b27", 0L)); final Boolean result =
forkIdManager.peerCheck(new ForkIdManager.ForkId(Bytes.fromHexString("0xafec6b27"), 0L));
assertThat(result).isFalse(); assertThat(result).isFalse();
} }
@Test @Test
public void createAndDecodeRLP() { public void createAndDecodeRLP() {
ForkIdManager.ForkId forkIdEntry = ForkIdManager.createIdEntry("0xa00bc324", 7280000L); final ForkIdManager.ForkId forkIdEntry =
BytesValueRLPOutput out = new BytesValueRLPOutput(); new ForkIdManager.ForkId(Bytes.fromHexString("0xa00bc324"), 7280000L);
final BytesValueRLPOutput out = new BytesValueRLPOutput();
forkIdEntry.writeTo(out); forkIdEntry.writeTo(out);
Bytes bytesValue = out.encoded(); final Bytes bytesValue = out.encoded();
BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false);
ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in);
assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); assertThat(forkIdEntry).isEqualTo(decodedEntry);
} }
@Test @Test
public void check1ZeroZeroProperRLPEncoding() { public void check1ZeroZeroProperRLPEncoding() {
ForkIdManager.ForkId forkIdEntry = ForkIdManager.createIdEntry("0", "0x"); final ForkIdManager.ForkId forkIdEntry =
BytesValueRLPOutput out = new BytesValueRLPOutput(); new ForkIdManager.ForkId(Bytes.fromHexString("0x00000000"), 0);
final BytesValueRLPOutput out = new BytesValueRLPOutput();
forkIdEntry.writeTo(out); forkIdEntry.writeTo(out);
String str1 = "0xc6840000000080"; final String str1 = "0xc6840000000080";
Bytes bytesValue = out.encoded(); final Bytes bytesValue = out.encoded();
assertThat(str1.equals(bytesValue.toString())).isTrue(); assertThat(str1).isEqualTo(bytesValue.toString());
BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false);
ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in);
assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); assertThat(forkIdEntry).isEqualTo(decodedEntry);
} }
@Test @Test
public void check2ArbitraryProperRLPEncoding() { public void check2ArbitraryProperRLPEncoding() {
ForkIdManager.ForkId forkIdEntry = ForkIdManager.createIdEntry("0xdeadbeef", "0xBADDCAFE"); final ForkIdManager.ForkId forkIdEntry =
BytesValueRLPOutput out = new BytesValueRLPOutput(); new ForkIdManager.ForkId(Bytes.fromHexString("0xdeadbeef"), 0xbaddcafeL);
final BytesValueRLPOutput out = new BytesValueRLPOutput();
forkIdEntry.writeTo(out); forkIdEntry.writeTo(out);
String str1 = "0xca84deadbeef84baddcafe"; final String str1 = "0xca84deadbeef84baddcafe";
Bytes bytesValue = out.encoded(); final Bytes bytesValue = out.encoded();
assertThat(str1.equals(bytesValue.toString())).isTrue(); assertThat(str1).isEqualTo(bytesValue.toString());
BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false);
ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in);
assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); assertThat(forkIdEntry).isEqualTo(decodedEntry);
} }
@Test @Test
public void check3MaximumsProperRLPEncoding() { public void check3MaximumsProperRLPEncoding() {
ForkIdManager.ForkId forkIdEntry = final ForkIdManager.ForkId forkIdEntry =
ForkIdManager.createIdEntry("0xffffffff", Long.parseUnsignedLong("ffffffffffffffff", 16)); new ForkIdManager.ForkId(Bytes.fromHexString("0xffffffff"), 0xffffffffffffffffL);
BytesValueRLPOutput out = new BytesValueRLPOutput(); final BytesValueRLPOutput out = new BytesValueRLPOutput();
forkIdEntry.writeTo(out); forkIdEntry.writeTo(out);
String str1 = final String str1 =
"0xce84ffffffff88ffffffffffffffff"; // Check value supplied in EIP-2124 spec via GO lang "0xce84ffffffff88ffffffffffffffff"; // Check value supplied in EIP-2124 spec via GO lang
Bytes bytesValue = out.encoded(); final Bytes bytesValue = out.encoded();
assertThat(str1.equals(bytesValue.toString())).isTrue(); assertThat(str1).isEqualTo(bytesValue.toString());
BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false); final BytesValueRLPInput in = new BytesValueRLPInput(bytesValue, false);
ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in); final ForkIdManager.ForkId decodedEntry = ForkIdManager.readFrom(in);
assertThat(forkIdEntry.equals(decodedEntry)).isTrue(); assertThat(forkIdEntry).isEqualTo(decodedEntry);
} }
} }

@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Random; import java.util.Random;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.junit.Test; import org.junit.Test;
@ -74,7 +75,8 @@ public class StatusMessageTest {
final Difficulty td = Difficulty.of(1000L); final Difficulty td = Difficulty.of(1000L);
final Hash bestHash = randHash(1L); final Hash bestHash = randHash(1L);
final Hash genesisHash = randHash(2L); 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 = final MessageData msg =
StatusMessage.create(version, networkId, td, bestHash, genesisHash, forkId); StatusMessage.create(version, networkId, td, bestHash, genesisHash, forkId);

Loading…
Cancel
Save