diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java b/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java index 767b7cd6e52..76686bd19c0 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java @@ -16,6 +16,7 @@ import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; +import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.plugin.data.EnodeURL; @@ -74,6 +75,11 @@ public static EthNetworkConfig getNetworkConfig(final NetworkName networkName) { final GenesisConfigOptions genesisConfigOptions = genesisConfigFile.getConfigOptions(); final Optional> rawBootNodes = genesisConfigOptions.getDiscoveryOptions().getBootNodes(); + if (networkName == NetworkName.OP_MAINNET) { + rawBootNodes.get().addAll(DiscoveryConfiguration.V5_OP_BOOTNODES); + } else if (networkName == NetworkName.OP_SEPOLIA) { + rawBootNodes.get().addAll(DiscoveryConfiguration.V5_OP_TESTNET_BOOTNODES); + } final List bootNodes = rawBootNodes .map( @@ -113,7 +119,7 @@ public static class Builder { private String dnsDiscoveryUrl; private GenesisConfigFile genesisConfigFile; private BigInteger networkId; - private List bootNodes; + private final List bootNodes; private Map genesisConfigOverrides; /** @@ -168,7 +174,15 @@ public Builder setNetworkId(final BigInteger networkId) { * @return this builder */ public Builder setBootNodes(final List bootNodes) { - this.bootNodes = bootNodes; + if (bootNodes == null) { + return this; + } + bootNodes.forEach( + bootNode -> { + if (!this.bootNodes.contains(bootNode)) { + this.bootNodes.add(bootNode); + } + }); return this; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java index fc397c1da54..0a58969fe36 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java @@ -40,7 +40,7 @@ public enum NetworkName { /** Mordor network name. */ MORDOR("/mordor.json", BigInteger.valueOf(7)), /** Optimims Mainnet network name. */ - OP_MAINNET("/optimism_mainnet.json", BigInteger.valueOf(10L)), + OP_MAINNET("/optimism-mainnet.json", BigInteger.valueOf(10L)), /** Optimism sepolia network name. */ OP_SEPOLIA("/optimism-sepolia.json", BigInteger.valueOf(11155420L)); 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 bd1e117773b..b641d21cbd3 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java @@ -155,6 +155,15 @@ public String getParentHash() { return JsonUtil.getString(genesisRoot, "parenthash", ""); } + /** + * Gets parent hash. + * + * @return the parent hash + */ + public String getStateHash() { + return JsonUtil.getString(genesisRoot, "statehash", ""); + } + /** * Gets difficulty. * diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java index e975a01f8fe..18d555d62fb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java @@ -114,8 +114,13 @@ public static GenesisState fromConfig( final DataStorageConfiguration dataStorageConfiguration, final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule) { - final var genesisStateRoot = - calculateGenesisStateRoot(dataStorageConfiguration, genesisConfigFile); + var genesisStateRoot = calculateGenesisStateRoot(dataStorageConfiguration, genesisConfigFile); + if (genesisConfigFile.getConfigOptions().isOptimism()) { + if (genesisStateRoot.equals(Hash.EMPTY_TRIE_HASH) + && !genesisConfigFile.getStateHash().isEmpty()) { + genesisStateRoot = Hash.fromHexStringLenient(genesisConfigFile.getStateHash()); + } + } final Block block = new Block( buildHeader(genesisConfigFile, genesisStateRoot, protocolSchedule), diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java index 76a8fbd6377..13e81d94ad7 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java @@ -39,6 +39,7 @@ import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -162,32 +163,39 @@ public void persist(final BlockHeader blockHeader) { Runnable saveTrieLog = () -> {}; try { - final Hash calculatedRootHash; + final AtomicReference calculatedRootHash = new AtomicReference<>(); if (blockHeader == null || !worldStateConfig.isTrieDisabled()) { - calculatedRootHash = + calculatedRootHash.set( calculateRootHash( worldStateConfig.isFrozen() ? Optional.empty() : Optional.of(stateUpdater), - accumulator); + accumulator)); + ; } else { // if the trie is disabled, we cannot calculate the state root, so we directly use the root // of the block. It's important to understand that in all networks, // the state root must be validated independently and the block should not be trusted // implicitly. This mode // can be used in cases where Besu would just be a follower of another trusted client. - calculatedRootHash = unsafeRootHashUpdate(blockHeader, stateUpdater); + calculatedRootHash.set(unsafeRootHashUpdate(blockHeader, stateUpdater)); } // if we are persisted with a block header, and the prior state is the parent // then persist the TrieLog for that transition. // If specified but not a direct descendant simply store the new block hash. if (blockHeader != null) { - verifyWorldStateRoot(calculatedRootHash, blockHeader); + if (blockHeader.getNumber() == 0L + && calculatedRootHash.get().equals(getEmptyTrieHash()) + && !blockHeader.getStateRoot().equals(getEmptyTrieHash())) { + calculatedRootHash.set(blockHeader.getStateRoot()); + } + verifyWorldStateRoot(calculatedRootHash.get(), blockHeader); saveTrieLog = () -> { - trieLogManager.saveTrieLog(localCopy, calculatedRootHash, blockHeader, this); + trieLogManager.saveTrieLog(localCopy, calculatedRootHash.get(), blockHeader, this); // not save a frozen state in the cache if (!worldStateConfig.isFrozen()) { - cachedWorldStorageManager.addCachedLayer(blockHeader, calculatedRootHash, this); + cachedWorldStorageManager.addCachedLayer( + blockHeader, calculatedRootHash.get(), this); } }; @@ -202,8 +210,8 @@ public void persist(final BlockHeader blockHeader) { stateUpdater .getWorldStateTransaction() - .put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, calculatedRootHash.toArrayUnsafe()); - worldStateRootHash = calculatedRootHash; + .put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, calculatedRootHash.get().toArrayUnsafe()); + worldStateRootHash = calculatedRootHash.get(); success = true; } finally { if (success) { diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/config/DiscoveryConfiguration.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/config/DiscoveryConfiguration.java index 86bb079a298..e4821b488e9 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/config/DiscoveryConfiguration.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/config/DiscoveryConfiguration.java @@ -24,6 +24,29 @@ public class DiscoveryConfiguration { + public static final List V5_OP_BOOTNODES = + List.of( + // OP Labs + "enode://ca2774c3c401325850b2477fd7d0f27911efbf79b1e8b335066516e2bd8c4c9e0ba9696a94b1cb030a88eac582305ff55e905e64fb77fe0edcd70a4e5296d3ec@34.65.175.185:30305", + "enode://dd751a9ef8912be1bfa7a5e34e2c3785cc5253110bd929f385e07ba7ac19929fb0e0c5d93f77827291f4da02b2232240fbc47ea7ce04c46e333e452f8656b667@34.65.107.0:30305", + "enode://c5d289b56a77b6a2342ca29956dfd07aadf45364dde8ab20d1dc4efd4d1bc6b4655d902501daea308f4d8950737a4e93a4dfedd17b49cd5760ffd127837ca965@34.65.202.239:30305", + // Base + "enode://87a32fd13bd596b2ffca97020e31aef4ddcc1bbd4b95bb633d16c1329f654f34049ed240a36b449fda5e5225d70fe40bc667f53c304b71f8e68fc9d448690b51@3.231.138.188:30301", + "enode://ca21ea8f176adb2e229ce2d700830c844af0ea941a1d8152a9513b966fe525e809c3a6c73a2c18a12b74ed6ec4380edf91662778fe0b79f6a591236e49e176f9@184.72.129.189:30301", + "enode://acf4507a211ba7c1e52cdf4eef62cdc3c32e7c9c47998954f7ba024026f9a6b2150cd3f0b734d9c78e507ab70d59ba61dfe5c45e1078c7ad0775fb251d7735a2@3.220.145.177:30301", + "enode://8a5a5006159bf079d06a04e5eceab2a1ce6e0f721875b2a9c96905336219dbe14203d38f70f3754686a6324f786c2f9852d8c0dd3adac2d080f4db35efc678c5@3.231.11.52:30301", + "enode://cdadbe835308ad3557f9a1de8db411da1a260a98f8421d62da90e71da66e55e98aaa8e90aa7ce01b408a54e4bd2253d701218081ded3dbe5efbbc7b41d7cef79@54.198.153.150:30301"); + + public static final List V5_OP_TESTNET_BOOTNODES = + List.of( + // OP Labs + "enode://2bd2e657bb3c8efffb8ff6db9071d9eb7be70d7c6d7d980ff80fc93b2629675c5f750bc0a5ef27cd788c2e491b8795a7e9a4a6e72178c14acc6753c0e5d77ae4@34.65.205.244:30305", + "enode://db8e1cab24624cc62fc35dbb9e481b88a9ef0116114cd6e41034c55b5b4f18755983819252333509bd8e25f6b12aadd6465710cd2e956558faf17672cce7551f@34.65.173.88:30305", + "enode://bfda2e0110cfd0f4c9f7aa5bf5ec66e6bd18f71a2db028d36b8bf8b0d6fdb03125c1606a6017b31311d96a36f5ef7e1ad11604d7a166745e6075a715dfa67f8a@34.65.229.245:30305", + // Base + "enode://548f715f3fc388a7c917ba644a2f16270f1ede48a5d88a4d14ea287cc916068363f3092e39936f1a3e7885198bef0e5af951f1d7b1041ce8ba4010917777e71f@18.210.176.114:30301", + "enode://6f10052847a966a725c9f4adf6716f9141155b99a0fb487fea3f51498f4c2a2cb8d534e680ee678f9447db85b93ff7c74562762c3714783a7233ac448603b25f@107.21.251.55:30301"); + private boolean active = true; private String bindHost = NetworkUtility.INADDR_ANY; private int bindPort = 30303;