From ef29f33a87841e6dd3ed7305df42f9abf30d3450 Mon Sep 17 00:00:00 2001 From: lyfsn Date: Tue, 19 Mar 2024 19:26:50 +0800 Subject: [PATCH] feat: add --use-cached-genesis-state-hash paramater Signed-off-by: lyfsn --- .../org/hyperledger/besu/cli/BesuCommand.java | 8 ++++- .../controller/BesuControllerBuilder.java | 35 +++++++++++++++++-- .../besu/cli/CommandTestAbstract.java | 1 + .../src/test/resources/everything_config.toml | 1 + .../besu/ethereum/chain/GenesisState.java | 18 ++++++++++ .../besu/ethereum/chain/VariablesStorage.java | 7 +++- .../keyvalue/VariablesKeyValueStorage.java | 10 ++++++ 7 files changed, 76 insertions(+), 4 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index c993dda3d04..d81567e5362 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -360,6 +360,11 @@ public class BesuCommand implements DefaultCommandValues, Runnable { "Genesis file for your custom network. Setting this option requires --network-id to be set. (Cannot be used with --network)") private final File genesisFile = null; + @Option( + names = {"--use-cached-genesis-state-hash"}, + description = "Use genesis state hash from data on startup if specified") + private final Boolean useCachedGenesisStateHash = false; + @Option( names = "--identity", paramLabel = "", @@ -1855,7 +1860,8 @@ public BesuControllerBuilder getControllerBuilder() { .maxRemotelyInitiatedPeers(maxRemoteInitiatedPeers) .randomPeerPriority(p2PDiscoveryOptionGroup.randomPeerPriority) .chainPruningConfiguration(unstableChainPruningOptions.toDomainObject()) - .cacheLastBlocks(numberOfblocksToCache); + .cacheLastBlocks(numberOfblocksToCache) + .useCachedGenesisStateHash(useCachedGenesisStateHash); } private JsonRpcConfiguration createEngineJsonRpcConfiguration( diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 4229804903f..4dbb91fd55e 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -130,6 +130,9 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides .map(conf -> conf.getConfigOptions(genesisConfigOverrides)) .orElseThrow(); + /** The is genesis state hash from data. */ + protected boolean useCachedGenesisStateHash; + /** The Sync config. */ protected SynchronizerConfiguration syncConfig; /** The Ethereum wire protocol configuration. */ @@ -224,6 +227,17 @@ public BesuControllerBuilder genesisConfigFile(final GenesisConfigFile genesisCo return this; } + /** + * Genesis state hash from data besu controller builder. + * + * @param useCachedGenesisStateHash the is genesis state hash from data + * @return the besu controller builder + */ + public BesuControllerBuilder useCachedGenesisStateHash(final Boolean useCachedGenesisStateHash) { + this.useCachedGenesisStateHash = useCachedGenesisStateHash; + return this; + } + /** * Synchronizer configuration besu controller builder. * @@ -555,11 +569,28 @@ public BesuController build() { prepForBuild(); final ProtocolSchedule protocolSchedule = createProtocolSchedule(); - final GenesisState genesisState = - GenesisState.fromConfig(dataStorageConfiguration, genesisConfig, protocolSchedule); + final GenesisState genesisState; final VariablesStorage variablesStorage = storageProvider.createVariablesStorage(); + Optional genesisStateHash = Optional.empty(); + if (variablesStorage != null && this.useCachedGenesisStateHash) { + genesisStateHash = variablesStorage.getGenesisStateHash(); + } + + if (genesisStateHash.isPresent()) { + genesisState = + GenesisState.fromConfig(genesisStateHash.get(), genesisConfig, protocolSchedule); + } else { + genesisState = + GenesisState.fromConfig(dataStorageConfiguration, genesisConfig, protocolSchedule); + if (variablesStorage != null) { + VariablesStorage.Updater updater = variablesStorage.updater(); + updater.setGenesisStateHash(genesisState.getBlock().getHeader().getStateRoot()); + updater.commit(); + } + } + final WorldStateStorageCoordinator worldStateStorageCoordinator = storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index 63f664d7469..1d0bb07e132 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -301,6 +301,7 @@ public void initMocks() throws Exception { when(mockControllerBuilder.besuComponent(any(BesuComponent.class))) .thenReturn(mockControllerBuilder); when(mockControllerBuilder.cacheLastBlocks(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.useCachedGenesisStateHash(any())).thenReturn(mockControllerBuilder); // doReturn used because of generic BesuController doReturn(mockController).when(mockControllerBuilder).build(); diff --git a/besu/src/test/resources/everything_config.toml b/besu/src/test/resources/everything_config.toml index 2bcbd21b496..43d541c6584 100644 --- a/besu/src/test/resources/everything_config.toml +++ b/besu/src/test/resources/everything_config.toml @@ -55,6 +55,7 @@ discovery-dns-url="enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPR # chain network="MAINNET" genesis-file="~/genesis.json" +use-cached-genesis-state-hash=false sync-mode="fast" fast-sync-min-peers=5 network-id=303 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 ccf47b17f59..2a47d701593 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 @@ -127,6 +127,24 @@ public static GenesisState fromConfig( return new GenesisState(block, genesisAccounts); } + /** + * Construct a {@link GenesisState} from a JSON object. + * + * @param genesisStateHash The hash of the genesis state. + * @param config A {@link GenesisConfigFile} describing the genesis block. + * @param protocolSchedule A protocol Schedule associated with + * @return A new {@link GenesisState}. + */ + public static GenesisState fromConfig( + final Hash genesisStateHash, + final GenesisConfigFile config, + final ProtocolSchedule protocolSchedule) { + final List genesisAccounts = parseAllocations(config).toList(); + final Block block = + new Block(buildHeader(config, genesisStateHash, protocolSchedule), buildBody(config)); + return new GenesisState(block, genesisAccounts); + } + private static BlockBody buildBody(final GenesisConfigFile config) { final Optional> withdrawals = isShanghaiAtGenesis(config) ? Optional.of(emptyList()) : Optional.empty(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java index 43a4361a0e4..594f9c00acd 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java @@ -29,7 +29,8 @@ enum Keys { FORK_HEADS("forkHeads"), FINALIZED_BLOCK_HASH("finalizedBlockHash"), SAFE_BLOCK_HASH("safeBlockHash"), - SEQ_NO_STORE("local-enr-seqno"); + SEQ_NO_STORE("local-enr-seqno"), + GENESIS_STATE_HASH("genesisStateHash"); private final String key; private final byte[] byteArray; @@ -65,6 +66,8 @@ public String toString() { Optional getLocalEnrSeqno(); + Optional getGenesisStateHash(); + Updater updater(); interface Updater { @@ -79,6 +82,8 @@ interface Updater { void setLocalEnrSeqno(Bytes nodeRecord); + void setGenesisStateHash(Hash genesisStateHash); + void removeAll(); void commit(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java index 28e6648a82d..a880932ac39 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java @@ -67,6 +67,11 @@ public Optional getLocalEnrSeqno() { return getVariable(SEQ_NO_STORE).map(Bytes::wrap); } + @Override + public Optional getGenesisStateHash() { + return getVariable(Keys.GENESIS_STATE_HASH).map(this::bytesToHash); + } + @Override public Updater updater() { return new Updater(variables.startTransaction()); @@ -115,6 +120,11 @@ public void setLocalEnrSeqno(final Bytes nodeRecord) { setVariable(SEQ_NO_STORE, nodeRecord); } + @Override + public void setGenesisStateHash(final Hash genesisStateHash) { + setVariable(Keys.GENESIS_STATE_HASH, genesisStateHash); + } + @Override public void removeAll() { removeVariable(CHAIN_HEAD_HASH);