diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java index 089b850385d..7149e8e357b 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java @@ -16,19 +16,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; import static org.hyperledger.besu.config.JsonUtil.normalizeKeys; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.Streams; import com.google.common.io.Resources; @@ -137,17 +133,17 @@ public long getTimestamp() { return parseLong("timestamp", JsonUtil.getValueAsString(configRoot, "timestamp", "0x0")); } - // TODO look into how to handle invalid or exceptional (i.e. null or "") fork values public List getForks() { return JsonUtil.getObjectNode(configRoot, "config").stream() - .flatMap(node -> - Streams.stream(node.fieldNames()) - .filter(name -> !name.toLowerCase().equals("chainid")) - .filter(name -> node.get(name).canConvertToLong()) - .filter(name -> name.contains("block")) - .map(name -> node.get(name).asLong()) - ) - .collect(toList()); + .flatMap( + node -> + Streams.stream(node.fieldNames()) + .filter(name -> !name.toLowerCase().equals("chainid")) + .filter(name -> node.get(name).canConvertToLong()) + .filter(name -> name.contains("block")) + .map(name -> node.get(name).asLong())) + .distinct() + .collect(toList()); } private String getRequiredString(final String key) { 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 7e93a9addf4..8ad8341aa0c 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 @@ -26,9 +26,7 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; import java.util.zip.CRC32; public class ForkIdManager { @@ -41,7 +39,7 @@ public class ForkIdManager { private ForkId lastKnownEntry = null; private ArrayDeque forkAndHashList; - public ForkIdManager(final Hash genesisHash, final Set forks, final Long currentHead) { + public ForkIdManager(final Hash genesisHash, final List forks, final Long currentHead) { this.genesisHash = genesisHash; this.currentHead = currentHead; if (forks != null) { @@ -56,8 +54,7 @@ static ForkIdManager buildCollection( if (forks == null) { return new ForkIdManager(genesisHash, null, blockchain.getChainHeadBlockNumber()); } else { - Set forkSet = new LinkedHashSet<>(forks); - return new ForkIdManager(genesisHash, forkSet, blockchain.getChainHeadBlockNumber()); + return new ForkIdManager(genesisHash, forks, blockchain.getChainHeadBlockNumber()); } }; @@ -65,8 +62,7 @@ public static ForkIdManager buildCollection(final Hash genesisHash, final List forkSet = new LinkedHashSet<>(forks); - return new ForkIdManager(genesisHash, forkSet, Long.MAX_VALUE); + return new ForkIdManager(genesisHash, forks, Long.MAX_VALUE); } }; @@ -100,8 +96,6 @@ public static ForkId readFrom(final RLPInput in) { return new ForkId(hash, next); } - - /** * EIP-2124 behaviour * @@ -146,11 +140,11 @@ public boolean peerCheck(final ForkId forkId) { /** * Non EIP-2124 behaviour * - * @param peerGenesisOrCheckSumHash Hash or checksum to be validated. + * @param peerGenesisHash Hash to be validated. * @return boolean */ - public boolean peerCheck(final Bytes32 peerGenesisOrCheckSumHash) { - return !peerGenesisOrCheckSumHash.equals(genesisHash); + public boolean peerCheck(final Bytes32 peerGenesisHash) { + return !peerGenesisHash.equals(genesisHash); } private boolean isHashKnown(final BytesValue forkHash) { @@ -189,8 +183,8 @@ private boolean isRemoteAwareOfPresent(final BytesValue forkHash, final Long nex return false; } - // TODO: sort these when the list of forks is first gathered - private ArrayDeque collectForksAndHashes(final Set forks, final Long currentHead) { + // TODO: should sort these when first gathering the list of forks to ensure order + private ArrayDeque collectForksAndHashes(final List forks, final Long currentHead) { boolean first = true; ArrayDeque forkList = new ArrayDeque<>(); Iterator iterator = forks.iterator(); @@ -235,7 +229,8 @@ private void updateCrc(final Long block) { } private BytesValue updateCrc(final String hash) { - byte[] byteRepresentation = hexStringToByteArray(hash); + BytesValue bv = BytesValue.fromHexString(hash); + byte[] byteRepresentation = bv.extractArray(); crc.update(byteRepresentation, 0, byteRepresentation.length); return getCurrentCrcHash(); } @@ -244,8 +239,6 @@ private BytesValue getCurrentCrcHash() { return BytesValues.ofUnsignedInt(crc.getValue()); } - // TODO use Hash class instead of string for checksum. convert to or from string only when needed - // ^ the crc is not hashed/checksum-ed any further so the hash class is not suited for this case public static class ForkId { BytesValue hash; BytesValue next; @@ -258,12 +251,12 @@ public static class ForkId { } ForkId(final String hash, final String next) { - this.hash = BytesValue.wrap(hexStringToByteArray(hash)); + this.hash = BytesValue.fromHexString((hash.length() % 2 == 0 ? "" : "0") + hash); if (this.hash.size() < 4) { this.hash = padToEightBytes(this.hash); } if (next.equals("") || next.equals("0x")) { - this.next = BytesValue.wrap(hexStringToByteArray("0x")); + this.next = BytesValue.EMPTY; } else if (next.startsWith("0x")) { long asLong = Long.parseLong(next.replaceFirst("0x", ""), 16); this.next = BytesValues.trimLeadingZeros(BytesValue.wrap(longToBigEndian(asLong))); @@ -274,7 +267,7 @@ public static class ForkId { } ForkId(final String hash, final long next) { - this.hash = BytesValue.wrap(hexStringToByteArray(hash)); + this.hash = BytesValue.fromHexString(hash); this.next = BytesValue.wrap(longToBigEndian(next)); createForkIdRLP(); } @@ -340,7 +333,7 @@ public List asList() { private static BytesValue padToEightBytes(final BytesValue hash) { if (hash.size() < 4) { BytesValue padded = - BytesValues.concatenate(hash, BytesValue.wrap(hexStringToByteArray("0x00"))); + BytesValues.concatenate(hash, BytesValue.fromHexString("0x00")); return padToEightBytes(padded); } else { return hash; @@ -368,17 +361,7 @@ public int hashCode() { } } - // TODO: Ask / look to see if there is a helper for these below <---------- - private static byte[] hexStringToByteArray(final String s) { - String string = ""; - if (s.startsWith("0x")) { - string = s.replaceFirst("0x", ""); - } - string = (string.length() % 2 == 0 ? "" : "0") + string; - return decodeHexString(string); - } - - // next three 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 private static byte[] longToBigEndian(final long n) { byte[] bs = new byte[8]; @@ -394,30 +377,4 @@ private static void intToBigEndian(final int n, final byte[] bs, int off) { bs[++off] = (byte) (n >>> 8); bs[++off] = (byte) (n); } - - private static byte[] decodeHexString(final String hexString) { - if (hexString.length() % 2 == 1) { - throw new IllegalArgumentException("Invalid hexadecimal String supplied."); - } - - byte[] bytes = new byte[hexString.length() / 2]; - for (int i = 0; i < hexString.length(); i += 2) { - bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); - } - return bytes; - } - - private static byte hexToByte(final String hexString) { - int firstDigit = toDigit(hexString.charAt(0)); - int secondDigit = toDigit(hexString.charAt(1)); - return (byte) ((firstDigit << 4) + secondDigit); - } - - private static int toDigit(final char hexChar) { - int digit = Character.digit(hexChar, 16); - if (digit == -1) { - throw new IllegalArgumentException("Invalid Hexadecimal Character: " + hexChar); - } - return digit; - } } 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 ebd695fa3d2..4d5ebeb5eb6 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 @@ -19,19 +19,12 @@ import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; -// import org.hyperledger.besu.ethereum.rlp.RLP; -//import org.hyperledger.besu.ethereum.rlp.RLPException; -// import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.util.bytes.BytesValue; import java.util.ArrayDeque; -// import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; -//import org.hyperledger.besu.util.bytes.BytesValues; import org.junit.Test; public class ForkIdManagerTest { @@ -126,10 +119,9 @@ public void checkCorrectRinkebyForkIdHashesGenerated() { 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7987396L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 0L)); assertThat(result).isTrue(); } @@ -139,10 +131,9 @@ public void check2PetersburgWithRemoteAnnouncingTheSameAndNextFork() { // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7987396L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", Long.MAX_VALUE)); assertThat(result).isTrue(); @@ -155,10 +146,9 @@ public void check3ByzantiumAwareOfPetersburgRemoteUnawareOfPetersburg() { // the fork). // In this case we don't know if Petersburg passed yet or not. // {7279999, ID{Hash: 0xa00bc324, Next: 0}, nil}, - List list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7279999L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); assertThat(result).isTrue(); } @@ -169,10 +159,9 @@ public void check4ByzantiumAwareOfPetersburgRemoteAwareOfPetersburg() { // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7279999L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 7280000L)); assertThat(result).isTrue(); } @@ -184,10 +173,9 @@ public void check5ByzantiumAwareOfPetersburgRemoteAnnouncingUnknownFork() { // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7279999L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", Long.MAX_VALUE)); assertThat(result).isTrue(); @@ -198,10 +186,9 @@ public void check6PetersburgWithRemoteAnnouncingByzantiumAwareOfPetersburg() { // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7987396L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 7280000L)); assertThat(result).isTrue(); } @@ -212,10 +199,9 @@ public void check7PetersburgWithRemoteAnnouncingSpuriousAwareOfByzantiumRemoteMa // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7987396L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x3edd5b10", 4370000L)); assertThat(result).isTrue(); } @@ -224,10 +210,9 @@ public void check7PetersburgWithRemoteAnnouncingSpuriousAwareOfByzantiumRemoteMa 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7279999L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x668db0af", 0L)); assertThat(result).isTrue(); } @@ -237,10 +222,9 @@ public void check9SpuriousWithRemoteAnnouncingByzantiumRemoteUnawareOfPetersburg // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 4369999L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 4369999L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); assertThat(result).isTrue(); } @@ -250,10 +234,9 @@ public void check10PetersburgWithRemoteAnnouncingByzantiumRemoteUnawareOfAdditio // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7987396L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xa00bc324", 0L)); assertThat(result).isFalse(); } @@ -263,10 +246,9 @@ public void check11PetersburgWithRemoteAnnouncingPetersburgAndFutureForkLocalNee // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7987396L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x5cddc0e1", 0L)); assertThat(result).isFalse(); } @@ -276,10 +258,9 @@ public void check12ByzantiumWithRemoteAnnouncingPetersburgAndFutureForkLocalNeed // 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 list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7279999L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7279999L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0x5cddc0e1", 0L)); assertThat(result).isFalse(); } @@ -288,10 +269,9 @@ public void check12ByzantiumWithRemoteAnnouncingPetersburgAndFutureForkLocalNeed public void check13ByzantiumWithRemoteAnnouncingRinkebyPetersburg() { // 13 Local is mainnet Petersburg, remote is Rinkeby Petersburg. // {7987396, ID{Hash: 0xafec6b27, Next: 0}, ErrLocalIncompatibleOrStale}, - List list = Arrays.asList(forksMainnet); - Set forkSet = new LinkedHashSet<>(list); + List forkList = Arrays.asList(forksMainnet); ForkIdManager forkIdManager = - new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkSet, 7987396L); + new ForkIdManager(Hash.fromHexString(mainnetGenHash), forkList, 7987396L); Boolean result = forkIdManager.peerCheck(ForkIdManager.createIdEntry("0xafec6b27", 0L)); assertThat(result).isFalse(); }