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 d10ab04362c..d385cae036f 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -621,7 +621,7 @@ public BesuController build() { worldStateHealerSupplier::get); if (maybeStoredGenesisBlockHash.isEmpty()) { - genesisState.writeStateTo(worldStateArchive.getMutable()); + genesisState.writeStateTo(worldStateArchive.getWorldState()); } transactionSimulator = diff --git a/besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java index 5e275961e0f..ed290cc9d2e 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.transaction.BlockStateCall; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.Unstable; import org.hyperledger.besu.plugin.data.BlockOverrides; @@ -135,8 +136,13 @@ private BlockHeader getBlockHeader(final long blockNumber) { } private MutableWorldState getWorldState(final BlockHeader header, final boolean isPersisting) { + final WorldStateQueryParams worldStateQueryParams = + WorldStateQueryParams.newBuilder() + .withBlockHeader(header) + .withShouldWorldStateUpdateHead(isPersisting) + .build(); return worldStateArchive - .getMutable(header, isPersisting) + .getWorldState(worldStateQueryParams) .orElseThrow( () -> new IllegalArgumentException( diff --git a/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java index cd4f494dc65..b2dffbca529 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.services; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; + import org.hyperledger.besu.consensus.merge.MergeContext; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.ProtocolContext; @@ -25,7 +27,7 @@ import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; -import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.data.BlockBody; @@ -109,7 +111,9 @@ public boolean setHeadUnsafe(final BlockHeader blockHeader, final BlockBody bloc final MutableBlockchain blockchain = protocolContext.getBlockchain(); - if (worldStateArchive.flatMap(archive -> archive.getMutable(coreHeader, true)).isPresent()) { + if (worldStateArchive + .flatMap(archive -> archive.getWorldState(withBlockHeaderAndUpdateNodeHead(coreHeader))) + .isPresent()) { if (coreHeader.getParentHash().equals(blockchain.getChainHeadHash())) { LOG.atDebug() .setMessage( @@ -142,7 +146,7 @@ public void disableWorldStateTrie() { // TODO maybe find a best way in the future to delete and disable trie worldStateArchive.ifPresent( archive -> { - archive.getDefaultWorldStateConfig().setTrieDisabled(true); + archive.getWorldStateSharedSpec().setTrieDisabled(true); final DiffBasedWorldStateKeyValueStorage worldStateStorage = archive.getWorldStateKeyValueStorage(); final Optional worldStateBlockHash = worldStateStorage.getWorldStateBlockHash(); diff --git a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java index 453e31378d2..7b52cc4dbb8 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java @@ -16,7 +16,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -59,6 +58,7 @@ import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.data.AddedBlockContext; @@ -152,7 +152,7 @@ public void setUp() { .when(mockTransactionValidatorFactory.get().validateForSender(any(), any(), any())) .thenReturn(ValidationResult.valid()); lenient() - .when(mockWorldStateArchive.getMutable(any(), anyBoolean())) + .when(mockWorldStateArchive.getWorldState(any(WorldStateQueryParams.class))) .thenReturn(Optional.of(mockWorldState)); blockBroadcaster = new BlockBroadcaster(mockEthContext, 10 * ByteUnits.MEGABYTE); diff --git a/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java index 21b36de45c8..23d1cdaabae 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java @@ -92,7 +92,7 @@ void shouldRetrieveStateUpdatePostTracingForOneBlock() { Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); final long persistedNonceForAccount = - worldStateArchive.getMutable().get(addressToVerify).getNonce(); + worldStateArchive.getWorldState().get(addressToVerify).getNonce(); final long blockNumber = 2; @@ -109,7 +109,7 @@ void shouldRetrieveStateUpdatePostTracingForOneBlock() { }, opTracer); - assertThat(worldStateArchive.getMutable().get(addressToVerify).getNonce()) + assertThat(worldStateArchive.getWorldState().get(addressToVerify).getNonce()) .isEqualTo(persistedNonceForAccount); final Block tracedBlock = blockchain.getBlockByNumber(blockNumber).get(); @@ -139,7 +139,7 @@ void shouldRetrieveStateUpdatePostTracingForAllBlocks() { Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); final long persistedNonceForAccount = - worldStateArchive.getMutable().get(addressToVerify).getNonce(); + worldStateArchive.getWorldState().get(addressToVerify).getNonce(); final long startBlock = 1; final long endBlock = 32; @@ -157,7 +157,7 @@ void shouldRetrieveStateUpdatePostTracingForAllBlocks() { }, opTracer); - assertThat(worldStateArchive.getMutable().get(addressToVerify).getNonce()) + assertThat(worldStateArchive.getWorldState().get(addressToVerify).getNonce()) .isEqualTo(persistedNonceForAccount); LongStream.rangeClosed(startBlock, endBlock) diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java index 7570e97d4d6..e1192de1705 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java @@ -16,6 +16,7 @@ import static java.util.stream.Collectors.joining; import static org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator.ForkchoiceResult.Status.INVALID; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; import org.hyperledger.besu.consensus.merge.MergeContext; import org.hyperledger.besu.consensus.merge.PayloadWrapper; @@ -679,7 +680,7 @@ private boolean moveWorldStateTo(final BlockHeader newHead) { Optional newWorldState = protocolContext .getWorldStateArchive() - .getMutable(newHead.getStateRoot(), newHead.getHash()); + .getWorldState(withBlockHeaderAndUpdateNodeHead(newHead)); newWorldState.ifPresentOrElse( mutableWorldState -> diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index 3cfdd70f52d..91d05e0cf7a 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -189,7 +189,7 @@ public void setUp() { protocolContext = new ProtocolContext(blockchain, worldStateArchive, mergeContext, badBlockManager); - var mutable = worldStateArchive.getMutable(); + var mutable = worldStateArchive.getWorldState(); genesisState.writeStateTo(mutable); mutable.persist(null); diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java index cb8b3977a1a..250ba94348c 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java @@ -85,7 +85,7 @@ public class MergeReorgTest implements MergeGenesisConfigHelper { @BeforeEach public void setUp() { - var mutable = worldStateArchive.getMutable(); + var mutable = worldStateArchive.getWorldState(); genesisState.writeStateTo(mutable); mutable.persist(null); mergeContext.setTerminalTotalDifficulty(Difficulty.of(1001)); diff --git a/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContextBuilder.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContextBuilder.java index 29d65eda0b6..4ee1c92dc64 100644 --- a/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContextBuilder.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContextBuilder.java @@ -264,7 +264,7 @@ public TestContext build() { createInMemoryBlockchain( genesisState.getBlock(), BftBlockHeaderFunctions.forOnchainBlock(BFT_EXTRA_DATA_ENCODER)); - genesisState.writeStateTo(worldStateArchive.getMutable()); + genesisState.writeStateTo(worldStateArchive.getWorldState()); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java index 57100943e36..a764d124631 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java @@ -85,7 +85,7 @@ public JsonRpcTestMethodsFactory(final BlockchainImporter importer) { this.importer = importer; this.blockchain = createInMemoryBlockchain(importer.getGenesisBlock()); this.stateArchive = createInMemoryWorldStateArchive(); - this.importer.getGenesisState().writeStateTo(stateArchive.getMutable()); + this.importer.getGenesisState().writeStateTo(stateArchive.getWorldState()); this.context = new ProtocolContext( blockchain, stateArchive, mock(ConsensusContext.class), new BadBlockManager()); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java index 7e26a4d8126..d3e2423a671 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java @@ -67,7 +67,7 @@ public static void setUpOnce() throws Exception { MutableBlockchain chain = InMemoryKeyValueStorageProvider.createInMemoryBlockchain(importer.getGenesisBlock()); WorldStateArchive state = InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive(); - importer.getGenesisState().writeStateTo(state.getMutable()); + importer.getGenesisState().writeStateTo(state.getWorldState()); ProtocolContext context = new ProtocolContext(chain, state, mock(ConsensusContext.class), new BadBlockManager()); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHead.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHead.java index 444fc8cf93f..e6f42f25ff4 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHead.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHead.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.UNKNOWN_BLOCK; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.ProtocolContext; @@ -29,7 +30,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.DiffBasedWorldStateProvider; import java.util.Optional; @@ -137,14 +138,14 @@ private boolean rollIncrementally( interimHead.ifPresent( it -> { blockchain.rewindToBlock(it.getBlockHash()); - archive.getMutable(it.getStateRoot(), it.getBlockHash()); + archive.getWorldState(withBlockHeaderAndUpdateNodeHead(it)); LOG.info("incrementally rolled worldstate to {}", it.toLogString()); }); currentHead = interimHead; } else { blockchain.rewindToBlock(target.getBlockHash()); - archive.getMutable(target.getStateRoot(), target.getBlockHash()); + archive.getWorldState(withBlockHeaderAndUpdateNodeHead(target)); currentHead = Optional.of(target); LOG.info("finished rolling worldstate to {}", target.toLogString()); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateTracer.java index c79feead167..95a899b1bf2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateTracer.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.privateProcessor; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead; + import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; @@ -49,11 +51,12 @@ public static Optional processTracing( final MutableWorldState disposablePrivateState = privacyParameters .getPrivateWorldStateArchive() - .getMutable( - privacyController - .getStateRootByBlockNumber(privacyGroupId, enclaveKey, blockNumber) - .get(), - parentHash) + .getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead( + privacyController + .getStateRootByBlockNumber(privacyGroupId, enclaveKey, blockNumber) + .get(), + parentHash)) .get(); return blockchainQueries.getAndMapWorldState( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java index a673e1df7b1..64bf7fb61e5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java @@ -17,6 +17,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher.BLOCKS_PER_BLOOM_CACHE; import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -1002,7 +1003,10 @@ public Optional getAndMapWorldState( .getBlockHeader(blockHash) .flatMap( blockHeader -> { - try (var ws = worldStateArchive.getMutable(blockHeader, false).orElse(null)) { + try (var ws = + worldStateArchive + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader)) + .orElse(null)) { if (ws != null) { return mapper.apply(ws); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/StateBackupService.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/StateBackupService.java index 27d96a1be93..e46ecf35904 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/StateBackupService.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/StateBackupService.java @@ -228,7 +228,6 @@ private void backupLeaves() throws IOException { header.get().getStateRoot(), Function.identity(), Function.identity()); - accountTrie.visitLeafs(this::visitAccount); backupStatus.currentAccount = null; } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHeadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHeadTest.java index 8d552ee3765..62e33218d25 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHeadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugSetHeadTest.java @@ -90,7 +90,7 @@ public void assertOnlyChainHeadMovesWorldParameterAbsent(final String blockParam // assert the chain moved, and the worldstate did not assertThat(newChainTip).isEqualTo(blockOne); - assertThat(archive.getMutable().rootHash()).isEqualTo(chainTip.getStateRoot()); + assertThat(archive.getWorldState().rootHash()).isEqualTo(chainTip.getStateRoot()); } @ParameterizedTest @@ -116,7 +116,7 @@ public void assertOnlyChainHeadMoves(final String blockParam) { // assert the chain moved, and the worldstate did not assertThat(newChainTip).isEqualTo(blockOne); - assertThat(archive.getMutable().rootHash()).isEqualTo(chainTip.getStateRoot()); + assertThat(archive.getWorldState().rootHash()).isEqualTo(chainTip.getStateRoot()); } @ParameterizedTest @@ -142,7 +142,7 @@ public void assertBothChainHeadAndWorldStatByNumber(final String blockParam) { // assert both the chain and worldstate moved to block one assertThat(newChainTip).isEqualTo(blockOne); - assertThat(archive.getMutable().rootHash()).isEqualTo(blockOne.getStateRoot()); + assertThat(archive.getWorldState().rootHash()).isEqualTo(blockOne.getStateRoot()); } @Test @@ -167,7 +167,7 @@ public void assertNotFound() { // assert neither the chain nor the worldstate moved assertThat(newChainTip).isEqualTo(chainTip); - assertThat(archive.getMutable().rootHash()).isEqualTo(chainTip.getStateRoot()); + assertThat(archive.getWorldState().rootHash()).isEqualTo(chainTip.getStateRoot()); } private JsonRpcRequestContext debugSetHead( diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index e060b06954c..5a37d079c4d 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -16,6 +16,7 @@ import static org.hyperledger.besu.ethereum.core.BlockHeaderBuilder.createPending; import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; @@ -404,7 +405,7 @@ private MutableWorldState duplicateWorldStateAtParent(final BlockHeader parentHe final Hash parentStateRoot = parentHeader.getStateRoot(); return protocolContext .getWorldStateArchive() - .getMutable(parentHeader, false) + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(parentHeader)) .orElseThrow( () -> { LOG.info("Unable to create block because world state is not available"); diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java index 202b0fdee66..70fd8f0d67a 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java @@ -76,6 +76,7 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -182,7 +183,7 @@ public void setup() { worldStateUpdater.createAccount(sender, 0, Wei.of(1_000_000_000L)); worldStateUpdater.commit(); - when(protocolContext.getWorldStateArchive().getMutable(any(), anyBoolean())) + when(protocolContext.getWorldStateArchive().getWorldState(any(WorldStateQueryParams.class))) .thenReturn(Optional.of(worldState)); when(ethContext.getEthPeers().subscribeConnect(any())).thenReturn(1L); when(ethScheduler.scheduleBlockCreationTask(any(Runnable.class))) diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java index 8813fcf38c7..551c9782dab 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java @@ -250,7 +250,7 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { ethScheduler); final MutableWorldState mutableWorldState = - executionContextTestFixture.getStateArchive().getMutable(); + executionContextTestFixture.getStateArchive().getWorldState(); assertThat(mutableWorldState.get(BLOCK_1_COINBASE)).isNull(); final ProcessableBlockHeader header = @@ -327,7 +327,7 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() { ethScheduler); final MutableWorldState mutableWorldState = - executionContextTestFixture.getStateArchive().getMutable(); + executionContextTestFixture.getStateArchive().getWorldState(); assertThat(mutableWorldState.get(BLOCK_1_COINBASE)).isNull(); final ProcessableBlockHeader header = diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/EntriesFromIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/EntriesFromIntegrationTest.java index fcfd71f206e..f5157e4e212 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/EntriesFromIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/EntriesFromIntegrationTest.java @@ -37,7 +37,7 @@ public class EntriesFromIntegrationTest { @Test @SuppressWarnings("MathAbsoluteRandom") public void shouldCollectStateEntries() { - final MutableWorldState worldState = createInMemoryWorldStateArchive().getMutable(); + final MutableWorldState worldState = createInMemoryWorldStateArchive().getWorldState(); final WorldUpdater updater = worldState.updater(); MutableAccount account = updater.getOrCreate(Address.fromHexString("0x56")); final Map expectedValues = new TreeMap<>(); diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java index 655ccda796b..644c280e22f 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java @@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead; import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; @@ -102,7 +103,9 @@ public void shouldTraceSStoreOperation() { final BlockHeader genesisBlockHeader = genesisBlock.getHeader(); final MutableWorldState worldState = worldStateArchive - .getMutable(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash()) + .getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead( + genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash())) .get(); final WorldUpdater createTransactionUpdater = worldState.updater(); TransactionProcessingResult result = @@ -177,7 +180,9 @@ public void shouldTraceContractCreation() { final BlockHeader genesisBlockHeader = genesisBlock.getHeader(); transactionProcessor.processTransaction( worldStateArchive - .getMutable(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash()) + .getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead( + genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash())) .get() .updater(), genesisBlockHeader, diff --git a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/TransientStorageOperationBenchmark.java b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/TransientStorageOperationBenchmark.java index aa7ce37313b..dda593ac3a5 100644 --- a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/TransientStorageOperationBenchmark.java +++ b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/TransientStorageOperationBenchmark.java @@ -50,7 +50,7 @@ private MessageFrame createMessageFrame(final Address address) { final Blockchain blockchain = mock(Blockchain.class); final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); - final WorldUpdater worldStateUpdater = worldStateArchive.getMutable().updater(); + final WorldUpdater worldStateUpdater = worldStateArchive.getWorldState().updater(); final BlockHeader blockHeader = new BlockHeaderTestFixture().buildHeader(); final MessageFrame benchmarkFrame = new MessageFrameTestFixture() diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java index c2925d651bd..bdfbe5065b4 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.plugin.services.exception.StorageException; import java.util.ArrayList; @@ -115,7 +116,7 @@ public BlockProcessingResult validateAndProcessBlock( final Block block, final HeaderValidationMode headerValidationMode, final HeaderValidationMode ommerValidationMode, - final boolean shouldPersist, + final boolean shouldUpdateHead, final boolean shouldRecordBadBlock) { final BlockHeader header = block.getHeader(); @@ -148,8 +149,14 @@ public BlockProcessingResult validateAndProcessBlock( handleFailedBlockProcessing(block, retval, false); return retval; } + + final WorldStateQueryParams worldStateQueryParams = + WorldStateQueryParams.newBuilder() + .withBlockHeader(parentHeader) + .withShouldWorldStateUpdateHead(shouldUpdateHead) + .build(); try (final var worldState = - context.getWorldStateArchive().getMutable(parentHeader, shouldPersist).orElse(null)) { + context.getWorldStateArchive().getWorldState(worldStateQueryParams).orElse(null)) { if (worldState == null) { var retval = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContract.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContract.java index 98709a4eaad..119f487f38f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContract.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContract.java @@ -18,6 +18,7 @@ import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_IS_PERSISTING_PRIVATE_STATE; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndUpdateNodeHead; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.enclave.Enclave; @@ -156,7 +157,7 @@ public PrecompileContractResult computePrecompile( privateStateRootResolver.resolveLastStateRoot(privacyGroupId, privateMetadataUpdater); final MutableWorldState disposablePrivateState = - privateWorldStateArchive.getMutable(lastRootHash, null).get(); + privateWorldStateArchive.getWorldState(withStateRootAndUpdateNodeHead(lastRootHash)).get(); final WorldUpdater privateWorldStateUpdater = disposablePrivateState.updater(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java index cf1a3dc198f..1285f05b64b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.mainnet.precompiles.privacy; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndUpdateNodeHead; + import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.PrivacyParameters; @@ -81,7 +83,7 @@ public PrecompileContractResult computePrecompile( privateStateRootResolver.resolveLastStateRoot(privacyGroupId, privateMetadataUpdater); final MutableWorldState disposablePrivateState = - privateWorldStateArchive.getMutable(lastRootHash, null).get(); + privateWorldStateArchive.getWorldState(withStateRootAndUpdateNodeHead(lastRootHash)).get(); final WorldUpdater privateWorldStateUpdater = disposablePrivateState.updater(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContract.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContract.java index 7e9bfa1ac4b..f0aa32ab86a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContract.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContract.java @@ -18,6 +18,7 @@ import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH; import static org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver.EMPTY_ROOT_HASH; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -172,7 +173,7 @@ public PrecompileContractResult computePrecompile( privateStateRootResolver.resolveLastStateRoot(privacyGroupId, privateMetadataUpdater); final MutableWorldState disposablePrivateState = - privateWorldStateArchive.getMutable(lastRootHash, null).get(); + privateWorldStateArchive.getWorldState(withStateRootAndUpdateNodeHead(lastRootHash)).get(); final WorldUpdater privateWorldStateUpdater = disposablePrivateState.updater(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/FlexiblePrivacyGroupContract.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/FlexiblePrivacyGroupContract.java index 6a1ce56f70a..3b4456dc133 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/FlexiblePrivacyGroupContract.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/FlexiblePrivacyGroupContract.java @@ -18,6 +18,7 @@ import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.CAN_EXECUTE_METHOD_SIGNATURE; import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.GET_PARTICIPANTS_METHOD_SIGNATURE; import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.GET_VERSION_METHOD_SIGNATURE; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithm; @@ -107,7 +108,11 @@ public FlexiblePrivacyGroupContract( final Bytes privacyGroupId = Bytes.fromBase64String(base64privacyGroupId); final MutableWorldState localMutableState = - privateWorldStateArchive.getMutable(disposablePrivateState.rootHash(), null).get(); + privateWorldStateArchive + .getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead( + disposablePrivateState.rootHash(), null)) + .get(); final WorldUpdater updater = localMutableState.updater(); final PrivateTransaction privateTransaction = buildTransaction(privacyGroupId, privateWorldStateUpdater, callData); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java index cab4d148fa7..51ada13f091 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.privacy; import static org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver.EMPTY_ROOT_HASH; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -125,7 +126,9 @@ public BlockProcessingResult processBlock( privateStateRootResolver.resolveLastStateRoot(privacyGroupId, metadataUpdater); final MutableWorldState disposablePrivateState = - privateWorldStateArchive.getMutable(lastRootHash, null).get(); + privateWorldStateArchive + .getWorldState(withStateRootAndUpdateNodeHead(lastRootHash)) + .get(); final WorldUpdater privateWorldStateUpdater = disposablePrivateState.updater(); if (lastRootHash.equals(EMPTY_ROOT_HASH)) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java index dc2d991258a..91933dc8703 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.privacy; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; + import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.TransactionLocation; @@ -156,7 +158,8 @@ public void rehydrate( .getBlockHeader(blockHeader.getParentHash()) .flatMap( header -> - publicWorldStateArchive.getMutable(header.getStateRoot(), header.getHash())) + publicWorldStateArchive.getWorldState( + withBlockHeaderAndUpdateNodeHead(header))) .orElseThrow(RuntimeException::new); privateGroupRehydrationBlockProcessor.processBlock( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java index 218c88f4cb2..52f2eb75bf0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java @@ -14,6 +14,9 @@ */ package org.hyperledger.besu.ethereum.privacy; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead; + import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; @@ -105,7 +108,7 @@ private Optional process( } final MutableWorldState publicWorldState = - worldStateArchive.getMutable(header.getStateRoot(), header.getHash()).orElse(null); + worldStateArchive.getWorldState(withBlockHeaderAndUpdateNodeHead(header)).orElse(null); if (publicWorldState == null) { return Optional.empty(); } @@ -118,7 +121,8 @@ private Optional process( final MutableWorldState disposablePrivateState = privacyParameters .getPrivateWorldStateArchive() - .getMutable(lastRootHash, header.getHash()) + .getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead(lastRootHash, header.getHash())) .get(); final PrivateTransaction transaction = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java index 3a005db5bc3..6e0c8f5198f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.privacy.storage.migration; import static org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage.SCHEMA_VERSION_1_4_0; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -102,7 +103,8 @@ public void migratePrivateStorage() { .getBlockHeader(blockHeader.getParentHash()) .flatMap( header -> - publicWorldStateArchive.getMutable(header.getStateRoot(), header.getHash())) + publicWorldStateArchive.getWorldState( + withBlockHeaderAndUpdateNodeHead(header))) .orElseThrow(PrivateStorageMigrationException::new); final List transactionsToProcess = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java index 43bf25915ad..b82ee1dfa06 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.transaction; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; + import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.StateOverride; @@ -91,7 +93,7 @@ public List process( final BlockHeader header, final List blockStateCalls) { try (final MutableWorldState ws = worldStateArchive - .getMutable(header, false) + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(header)) .orElseThrow( () -> new IllegalArgumentException( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index cc0f77bb2dc..fd4c5a4a318 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -16,6 +16,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithm; @@ -210,7 +211,7 @@ private MutableWorldState duplicateWorldStateAtParent(final Hash parentHash) { final Hash parentStateRoot = parentHeader.getStateRoot(); return worldStateArchive - .getMutable(parentHeader, false) + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(parentHeader)) .orElseThrow( () -> new IllegalArgumentException( @@ -337,7 +338,7 @@ public Optional process( private MutableWorldState getWorldState(final BlockHeader header) { return worldStateArchive - .getMutable(header, false) + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(header)) .orElseThrow( () -> new IllegalArgumentException( @@ -580,7 +581,7 @@ public WorldUpdater getEffectiveWorldStateUpdater(final MutableWorldState public public Optional doesAddressExistAtHead(final Address address) { final BlockHeader header = blockchain.getChainHeadHeader(); try (final MutableWorldState worldState = - worldStateArchive.getMutable(header, false).orElseThrow()) { + worldStateArchive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(header)).orElseThrow()) { return doesAddressExist(worldState, address, header); } catch (final Exception ex) { return Optional.empty(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java index 78bcb417e37..ff738fb0b45 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.trie.common; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig.createStatefulConfigWithTrie; + import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage; @@ -22,7 +24,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; @@ -74,7 +75,7 @@ private static MutableWorldState createGenesisBonsaiWorldState() { new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage), new NoOpTrieLogManager(), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); } /** diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java index afbb1e05816..879a9bb5c75 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java @@ -23,9 +23,8 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.plugin.ServiceManager; @@ -60,10 +59,10 @@ public BonsaiWorldStateProvider( this.worldStateHealerSupplier = worldStateHealerSupplier; provideCachedWorldStorageManager( new BonsaiCachedWorldStorageManager( - this, worldStateKeyValueStorage, this::cloneBonsaiWorldStateConfig)); - loadPersistedState( + this, worldStateKeyValueStorage, worldStateSharedConfig)); + loadHeadWorldState( new BonsaiWorldState( - this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig)); + this, worldStateKeyValueStorage, evmConfiguration, worldStateSharedConfig)); } @VisibleForTesting @@ -79,9 +78,9 @@ public BonsaiWorldStateProvider( this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; this.worldStateHealerSupplier = worldStateHealerSupplier; provideCachedWorldStorageManager(bonsaiCachedWorldStorageManager); - loadPersistedState( + loadHeadWorldState( new BonsaiWorldState( - this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig)); + this, worldStateKeyValueStorage, evmConfiguration, worldStateSharedConfig)); } public BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader() { @@ -113,7 +112,7 @@ public void prepareStateHealing(final Address address, final Bytes location) { } return node; }, - persistedState.getWorldStateRootHash(), + headWorldState.getWorldStateRootHash(), Function.identity(), Function.identity()); try { @@ -154,10 +153,6 @@ public void prepareStateHealing(final Address address, final Bytes location) { getBonsaiWorldStateKeyValueStorage().downgradeToPartialFlatDbMode(); } - private DiffBasedWorldStateConfig cloneBonsaiWorldStateConfig() { - return new DiffBasedWorldStateConfig(defaultWorldStateConfig); - } - @Override public void heal(final Optional
maybeAccountToRepair, final Bytes location) { worldStateHealerSupplier.get().heal(maybeAccountToRepair, location); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java index 60cf25e880c..fdccbe8ef73 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java @@ -19,22 +19,20 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import java.util.function.Supplier; - public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager { public BonsaiCachedWorldStorageManager( final BonsaiWorldStateProvider archive, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, - final Supplier defaultBonsaiWorldStateConfigSupplier) { - super(archive, worldStateKeyValueStorage, defaultBonsaiWorldStateConfigSupplier); + final WorldStateSharedConfig worldStateSharedConfig) { + super(archive, worldStateKeyValueStorage, worldStateSharedConfig); } @Override @@ -46,7 +44,7 @@ public DiffBasedWorldState createWorldState( (BonsaiWorldStateProvider) archive, (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage, evmConfiguration, - defaultBonsaiWorldStateConfigSupplier.get()); + WorldStateSharedConfig.newBuilder(worldStateSharedConfig).build()); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java index a054b437037..8290cb39c45 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java @@ -18,7 +18,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig; import java.util.Optional; import java.util.function.Function; @@ -27,7 +27,10 @@ public class NoOpBonsaiCachedWorldStorageManager extends BonsaiCachedWorldStorag public NoOpBonsaiCachedWorldStorageManager( final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage) { - super(null, bonsaiWorldStateKeyValueStorage, DiffBasedWorldStateConfig::new); + super( + null, + bonsaiWorldStateKeyValueStorage, + WorldStateSharedConfig.createStatefulConfigWithTrie()); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java index b62805c1fda..7a078a9cf33 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java @@ -35,7 +35,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; @@ -66,14 +66,14 @@ public BonsaiWorldState( final BonsaiWorldStateProvider archive, final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, final EvmConfiguration evmConfiguration, - final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { + final WorldStateSharedConfig worldStateConfig) { this( worldStateKeyValueStorage, archive.getCachedMerkleTrieLoader(), archive.getCachedWorldStorageManager(), archive.getTrieLogManager(), evmConfiguration, - diffBasedWorldStateConfig); + worldStateConfig); } public BonsaiWorldState( @@ -85,7 +85,7 @@ public BonsaiWorldState( worldState.cachedWorldStorageManager, worldState.trieLogManager, worldState.accumulator.getEvmConfiguration(), - new DiffBasedWorldStateConfig(worldState.worldStateConfig)); + WorldStateSharedConfig.newBuilder(worldState.worldStateConfig).build()); } public BonsaiWorldState( @@ -94,12 +94,8 @@ public BonsaiWorldState( final DiffBasedCachedWorldStorageManager cachedWorldStorageManager, final TrieLogManager trieLogManager, final EvmConfiguration evmConfiguration, - final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { - super( - worldStateKeyValueStorage, - cachedWorldStorageManager, - trieLogManager, - diffBasedWorldStateConfig); + final WorldStateSharedConfig worldStateConfig) { + super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager, worldStateConfig); this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; this.worldStateKeyValueStorage = worldStateKeyValueStorage; this.setAccumulator( @@ -449,7 +445,7 @@ public Map getAllAccountStorage(final Address address, final Has @Override public MutableWorldState freeze() { - this.worldStateConfig.setFrozen(true); + this.isStorageFrozen = true; this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage()); return this; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java index 160c7ac1e3e..b61e7f104e8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java @@ -14,16 +14,18 @@ */ package org.hyperledger.besu.ethereum.trie.diffbased.common.cache; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; + import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig; import org.hyperledger.besu.evm.internal.EvmConfiguration; import java.util.ArrayList; @@ -34,7 +36,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.function.Function; -import java.util.function.Supplier; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; @@ -48,7 +49,7 @@ public abstract class DiffBasedCachedWorldStorageManager implements StorageSubsc LoggerFactory.getLogger(DiffBasedCachedWorldStorageManager.class); private final DiffBasedWorldStateProvider archive; private final EvmConfiguration evmConfiguration; - protected final Supplier defaultBonsaiWorldStateConfigSupplier; + protected final WorldStateSharedConfig worldStateSharedConfig; private final Cache stateRootToBlockHeaderCache = Caffeine.newBuilder() .maximumSize(RETAINED_LAYERS) @@ -63,25 +64,25 @@ private DiffBasedCachedWorldStorageManager( final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final Map cachedWorldStatesByHash, final EvmConfiguration evmConfiguration, - final Supplier defaultBonsaiWorldStateConfigSupplier) { + final WorldStateSharedConfig worldStateSharedConfig) { worldStateKeyValueStorage.subscribe(this); this.rootWorldStateStorage = worldStateKeyValueStorage; this.cachedWorldStatesByHash = cachedWorldStatesByHash; this.archive = archive; this.evmConfiguration = evmConfiguration; - this.defaultBonsaiWorldStateConfigSupplier = defaultBonsaiWorldStateConfigSupplier; + this.worldStateSharedConfig = worldStateSharedConfig; } public DiffBasedCachedWorldStorageManager( final DiffBasedWorldStateProvider archive, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, - final Supplier defaultBonsaiWorldStateConfigSupplier) { + final WorldStateSharedConfig worldStateSharedConfig) { this( archive, worldStateKeyValueStorage, new ConcurrentHashMap<>(), EvmConfiguration.DEFAULT, - defaultBonsaiWorldStateConfigSupplier); + worldStateSharedConfig); } public synchronized void addCachedLayer( @@ -92,7 +93,7 @@ public synchronized void addCachedLayer( Optional.ofNullable(this.cachedWorldStatesByHash.get(blockHeader.getBlockHash())); if (cachedDiffBasedWorldView.isPresent()) { // only replace if it is a layered storage - if (forWorldState.isPersisted() + if (forWorldState.isModifyingHeadWorldState() && cachedDiffBasedWorldView.get().getWorldStateStorage() instanceof DiffBasedLayeredWorldStateKeyValueStorage) { LOG.atDebug() @@ -111,7 +112,7 @@ public synchronized void addCachedLayer( .addArgument(blockHeader::toLogString) .addArgument(worldStateRootHash::toShortHexString) .log(); - if (forWorldState.isPersisted()) { + if (forWorldState.isModifyingHeadWorldState()) { cachedWorldStatesByHash.put( blockHeader.getHash(), new DiffBasedCachedWorldView( @@ -252,7 +253,9 @@ public synchronized Optional getStorageByRoo () -> { // if not cached already, maybe fetch and cache this worldstate var maybeWorldState = - archive.getMutable(header, false).map(BonsaiWorldState.class::cast); + archive + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(header)) + .map(BonsaiWorldState.class::cast); maybeWorldState.ifPresent( ws -> addCachedLayer(header, header.getStateRoot(), ws)); return maybeWorldState.map(BonsaiWorldState::getWorldStateStorage); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/provider/DiffBasedWorldStateProvider.java similarity index 60% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/provider/DiffBasedWorldStateProvider.java index 70e077a41b8..8ef3ec3c0b8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/provider/DiffBasedWorldStateProvider.java @@ -12,7 +12,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.trie.diffbased.common; +package org.hyperledger.besu.ethereum.trie.diffbased.common.provider; + +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -26,7 +28,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; @@ -52,27 +54,24 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive { protected final TrieLogManager trieLogManager; protected DiffBasedCachedWorldStorageManager cachedWorldStorageManager; - protected DiffBasedWorldState persistedState; - + protected DiffBasedWorldState headWorldState; protected final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage; - protected final DiffBasedWorldStateConfig defaultWorldStateConfig; + // Configuration that will be shared by all instances of world state at their creation + protected final WorldStateSharedConfig worldStateSharedConfig; public DiffBasedWorldStateProvider( final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final Blockchain blockchain, final Optional maxLayersToLoad, final ServiceManager pluginContext) { - - this.worldStateKeyValueStorage = worldStateKeyValueStorage; - // TODO: de-dup constructors - this.trieLogManager = + this( + worldStateKeyValueStorage, + blockchain, new TrieLogManager( blockchain, worldStateKeyValueStorage, maxLayersToLoad.orElse(DiffBasedCachedWorldStorageManager.RETAINED_LAYERS), - pluginContext); - this.blockchain = blockchain; - this.defaultWorldStateConfig = new DiffBasedWorldStateConfig(); + pluginContext)); } public DiffBasedWorldStateProvider( @@ -81,10 +80,10 @@ public DiffBasedWorldStateProvider( final TrieLogManager trieLogManager) { this.worldStateKeyValueStorage = worldStateKeyValueStorage; - // TODO: de-dup constructors this.trieLogManager = trieLogManager; this.blockchain = blockchain; - this.defaultWorldStateConfig = new DiffBasedWorldStateConfig(); + this.worldStateSharedConfig = WorldStateSharedConfig.newBuilder().build(); + ; } protected void provideCachedWorldStorageManager( @@ -92,14 +91,14 @@ protected void provideCachedWorldStorageManager( this.cachedWorldStorageManager = cachedWorldStorageManager; } - protected void loadPersistedState(final DiffBasedWorldState persistedState) { - this.persistedState = persistedState; + protected void loadHeadWorldState(final DiffBasedWorldState headWorldState) { + this.headWorldState = headWorldState; blockchain - .getBlockHeader(persistedState.getWorldStateBlockHash()) + .getBlockHeader(headWorldState.getWorldStateBlockHash()) .ifPresent( blockHeader -> this.cachedWorldStorageManager.addCachedLayer( - blockHeader, persistedState.getWorldStateRootHash(), persistedState)); + blockHeader, headWorldState.getWorldStateRootHash(), headWorldState)); } @Override @@ -108,8 +107,8 @@ public Optional get(final Hash rootHash, final Hash blockHash) { .getWorldState(blockHash) .or( () -> { - if (blockHash.equals(persistedState.blockHash())) { - return Optional.of(persistedState); + if (blockHash.equals(headWorldState.blockHash())) { + return Optional.of(headWorldState); } else { return Optional.empty(); } @@ -120,40 +119,120 @@ public Optional get(final Hash rootHash, final Hash blockHash) { @Override public boolean isWorldStateAvailable(final Hash rootHash, final Hash blockHash) { return cachedWorldStorageManager.contains(blockHash) - || persistedState.blockHash().equals(blockHash) + || headWorldState.blockHash().equals(blockHash) || worldStateKeyValueStorage.isWorldStateAvailable(rootHash, blockHash); } + /** + * Gets a mutable world state based on the provided query parameters. + * + *

This method checks if the world state is configured to be stateful. If it is, it retrieves + * the full world state using the provided query parameters. If the world state is not configured + * to be full, the stateless one will be returned. + * + *

The method follows these steps: 1. Check if the world state is configured to be stateful. 2. + * If true, call {@link #getFullWorldState(WorldStateQueryParams)} with the query parameters. 3. + * If false, throw a RuntimeException indicating that stateless mode is not yet available. + * + * @param queryParams the query parameters + * @return the mutable world state, if available + * @throws RuntimeException if the world state is not configured to be stateful + */ @Override - public Optional getMutable( - final BlockHeader blockHeader, final boolean shouldPersistState) { - if (shouldPersistState) { - return getMutable(blockHeader.getStateRoot(), blockHeader.getHash()); + public Optional getWorldState(final WorldStateQueryParams queryParams) { + if (worldStateSharedConfig.isStateful()) { + return getFullWorldState(queryParams); } else { - final BlockHeader chainHeadBlockHeader = blockchain.getChainHeadHeader(); - if (chainHeadBlockHeader.getNumber() - blockHeader.getNumber() - >= trieLogManager.getMaxLayersToLoad()) { - LOG.warn( - "Exceeded the limit of historical blocks that can be loaded ({}). If you need to make older historical queries, configure your `--bonsai-historical-block-limit`.", - trieLogManager.getMaxLayersToLoad()); - return Optional.empty(); - } - return cachedWorldStorageManager - .getWorldState(blockHeader.getHash()) - .or(() -> cachedWorldStorageManager.getNearestWorldState(blockHeader)) - .or(() -> cachedWorldStorageManager.getHeadWorldState(blockchain::getBlockHeader)) - .flatMap(worldState -> rollMutableStateToBlockHash(worldState, blockHeader.getHash())) - .map(MutableWorldState::freeze); + throw new RuntimeException("stateless mode is not yet available"); } } + /** + * Gets the head world state. + * + *

This method returns the head world state, which is the most recent state of the world. + * + * @return the head world state + */ @Override - public synchronized Optional getMutable( - final Hash rootHash, final Hash blockHash) { - return rollMutableStateToBlockHash(persistedState, blockHash); + public MutableWorldState getWorldState() { + return headWorldState; + } + + /** + * Gets the full world state based on the provided query parameters. + * + *

This method determines whether to retrieve the full world state from the head or from the + * cache based on the query parameters. If the query parameters indicate that the world state + * should update the head, the method retrieves the full world state from the head. Otherwise, it + * retrieves the full world state from the cache. + * + *

The method follows these steps: 1. Check if the query parameters indicate that the world + * state should update the head. 2. If true, call {@link #getFullWorldStateFromHead(Hash)} with + * the block hash from the query parameters. 3. If false, call {@link + * #getFullWorldStateFromCache(BlockHeader)} with the block header from the query parameters. + * + * @param queryParams the query parameters + * @return the stateful world state, if available + */ + private Optional getFullWorldState(final WorldStateQueryParams queryParams) { + return queryParams.shouldWorldStateUpdateHead() + ? getFullWorldStateFromHead(queryParams.getBlockHash()) + : getFullWorldStateFromCache(queryParams.getBlockHeader()); + } + + /** + * Gets the full world state from the head based on the provided block hash. + * + *

This method attempts to roll the head world state to the specified block hash. If the block + * hash matches the block hash of the head world state, the head world state is returned. + * Otherwise, the method attempts to roll the full world state to the specified block hash. + * + *

The method follows these steps: 1. Check if the block hash matches the block hash of the + * head world state. 2. If it matches, return the head world state. 3. If it does not match, + * attempt to roll the full world state to the specified block hash. + * + * @param blockHash the block hash + * @return the full world state, if available + */ + private Optional getFullWorldStateFromHead(final Hash blockHash) { + return rollFullWorldStateToBlockHash(headWorldState, blockHash); } - Optional rollMutableStateToBlockHash( + /** + * Gets the full world state from the cache based on the provided block header. + * + *

This method attempts to retrieve the world state from the cache using the block header. If + * the block header is too old (i.e., the number of blocks between the chain head and the provided + * block header exceeds the maximum layers to load), a warning is logged and an empty Optional is + * returned. + * + *

The method follows these steps: 1. Check if the world state for the given block header is + * available in the cache. 2. If not, attempt to get the nearest world state from the cache. 3. If + * still not found, attempt to get the head world state. 4. If a world state is found, roll it to + * the block hash of the provided block header. 5. Freeze the world state and return it. + * + * @param blockHeader the block header + * @return the full world state, if available + */ + private Optional getFullWorldStateFromCache(final BlockHeader blockHeader) { + final BlockHeader chainHeadBlockHeader = blockchain.getChainHeadHeader(); + if (chainHeadBlockHeader.getNumber() - blockHeader.getNumber() + >= trieLogManager.getMaxLayersToLoad()) { + LOG.warn( + "Exceeded the limit of historical blocks that can be loaded ({}). If you need to make older historical queries, configure your `--bonsai-historical-block-limit`.", + trieLogManager.getMaxLayersToLoad()); + return Optional.empty(); + } + return cachedWorldStorageManager + .getWorldState(blockHeader.getHash()) + .or(() -> cachedWorldStorageManager.getNearestWorldState(blockHeader)) + .or(() -> cachedWorldStorageManager.getHeadWorldState(blockchain::getBlockHeader)) + .flatMap(worldState -> rollFullWorldStateToBlockHash(worldState, blockHeader.getHash())) + .map(MutableWorldState::freeze); + } + + private Optional rollFullWorldStateToBlockHash( final DiffBasedWorldState mutableState, final Hash blockHash) { if (blockHash.equals(mutableState.blockHash())) { return Optional.of(mutableState); @@ -251,18 +330,8 @@ Optional rollMutableStateToBlockHash( } } - @Override - public MutableWorldState getMutable() { - return persistedState; - } - - public DiffBasedWorldStateConfig getDefaultWorldStateConfig() { - return defaultWorldStateConfig; - } - - public void disableTrie() { - defaultWorldStateConfig.setTrieDisabled(true); - worldStateKeyValueStorage.clearTrie(); + public WorldStateSharedConfig getWorldStateSharedSpec() { + return worldStateSharedConfig; } public DiffBasedWorldStateKeyValueStorage getWorldStateKeyValueStorage() { @@ -279,10 +348,10 @@ public DiffBasedCachedWorldStorageManager getCachedWorldStorageManager() { @Override public void resetArchiveStateTo(final BlockHeader blockHeader) { - persistedState.resetWorldStateTo(blockHeader); + headWorldState.resetWorldStateTo(blockHeader); this.cachedWorldStorageManager.reset(); this.cachedWorldStorageManager.addCachedLayer( - blockHeader, persistedState.getWorldStateRootHash(), persistedState); + blockHeader, headWorldState.getWorldStateRootHash(), headWorldState); } @Override @@ -292,7 +361,8 @@ public Optional getAccountProof( final List accountStorageKeys, final Function, ? extends Optional> mapper) { try (DiffBasedWorldState ws = - (DiffBasedWorldState) getMutable(blockHeader, false).orElse(null)) { + (DiffBasedWorldState) + getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader)).orElse(null)) { if (ws != null) { final WorldStateProofProvider worldStateProofProvider = new WorldStateProofProvider( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/provider/WorldStateQueryParams.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/provider/WorldStateQueryParams.java new file mode 100644 index 00000000000..f4ccaa5313b --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/provider/WorldStateQueryParams.java @@ -0,0 +1,231 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.trie.diffbased.common.provider; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.core.BlockHeader; + +import java.util.Objects; +import java.util.Optional; + +/** Parameters for querying the world state. */ +public class WorldStateQueryParams { + private final BlockHeader blockHeader; + private final boolean shouldWorldStateUpdateHead; + private final Hash blockHash; + private final Optional stateRoot; + + /** + * Private constructor to enforce the use of the Builder. + * + * @param builder the builder to create an instance of WorldStateQueryParams + */ + private WorldStateQueryParams(final Builder builder) { + this.blockHeader = builder.blockHeader; + this.shouldWorldStateUpdateHead = builder.shouldWorldStateUpdateHead; + this.blockHash = builder.blockHash; + this.stateRoot = builder.stateRoot; + } + + /** + * Gets the block header. + * + * @return the block header + */ + public BlockHeader getBlockHeader() { + return blockHeader; + } + + /** + * Checks if the world state should update the node head. + * + * @return true if the world state should update the node head, false otherwise + */ + public boolean shouldWorldStateUpdateHead() { + return shouldWorldStateUpdateHead; + } + + /** + * Gets the block hash. + * + * @return the block hash + */ + public Hash getBlockHash() { + return blockHash; + } + + /** + * Gets the state root. + * + * @return the state root + */ + public Optional getStateRoot() { + return stateRoot; + } + + /** + * Creates a new builder for WorldStateQueryParams. + * + * @return a new builder + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Creates an instance with a block header and updates the node head. + * + * @param blockHeader the block header + * @return an instance of WorldStateQueryParams + */ + public static WorldStateQueryParams withBlockHeaderAndUpdateNodeHead( + final BlockHeader blockHeader) { + return newBuilder().withBlockHeader(blockHeader).withShouldWorldStateUpdateHead(true).build(); + } + + /** + * Creates an instance with a block header and does not update the node head. + * + * @param blockHeader the block header + * @return an instance of WorldStateQueryParams + */ + public static WorldStateQueryParams withBlockHeaderAndNoUpdateNodeHead( + final BlockHeader blockHeader) { + return newBuilder().withBlockHeader(blockHeader).withShouldWorldStateUpdateHead(false).build(); + } + + /** + * Should return a worldstate instance with a state root, block hash, and should update the node + * head. + * + * @param stateRoot the state root + * @param blockHash the block hash + * @return an instance of WorldStateQueryParams + */ + public static WorldStateQueryParams withStateRootAndBlockHashAndUpdateNodeHead( + final Hash stateRoot, final Hash blockHash) { + return newBuilder() + .withStateRoot(stateRoot) + .withBlockHash(blockHash) + .withShouldWorldStateUpdateHead(true) + .build(); + } + + /** + * Should return a worldstate instance with a state root and should update the node head. + * + * @param stateRoot the state root + * @return an instance of WorldStateQueryParams + */ + public static WorldStateQueryParams withStateRootAndUpdateNodeHead(final Hash stateRoot) { + return newBuilder().withStateRoot(stateRoot).withShouldWorldStateUpdateHead(true).build(); + } + + /** + * Creates an instance with a state root, block hash, and does not update the node head. + * + * @param stateRoot the state root + * @param blockHash the block hash + * @return an instance of WorldStateQueryParams + */ + public static WorldStateQueryParams withStateRootAndBlockHashAndNoUpdateNodeHead( + final Hash stateRoot, final Hash blockHash) { + return newBuilder() + .withStateRoot(stateRoot) + .withBlockHash(blockHash) + .withShouldWorldStateUpdateHead(false) + .build(); + } + + @Override + public boolean equals(final Object o) { + if (o == null || getClass() != o.getClass()) return false; + WorldStateQueryParams that = (WorldStateQueryParams) o; + return shouldWorldStateUpdateHead == that.shouldWorldStateUpdateHead + && Objects.equals(blockHeader, that.blockHeader) + && Objects.equals(blockHash, that.blockHash) + && Objects.equals(stateRoot, that.stateRoot); + } + + @Override + public int hashCode() { + return Objects.hash(blockHeader, shouldWorldStateUpdateHead, blockHash, stateRoot); + } + + public static class Builder { + private BlockHeader blockHeader; + private boolean shouldWorldStateUpdateHead = false; + private Hash blockHash; + private Optional stateRoot = Optional.empty(); + + private Builder() {} + + /** + * Sets the block header. + * + * @param blockHeader the block header + * @return the builder + */ + public Builder withBlockHeader(final BlockHeader blockHeader) { + this.blockHeader = blockHeader; + this.blockHash = blockHeader.getBlockHash(); + this.stateRoot = Optional.of(blockHeader.getStateRoot()); + return this; + } + + /** + * Sets whether the world state should update the node head. + * + * @param shouldWorldStateUpdateHead true if the world state should update the node head, false + * otherwise + * @return the builder + */ + public Builder withShouldWorldStateUpdateHead(final boolean shouldWorldStateUpdateHead) { + this.shouldWorldStateUpdateHead = shouldWorldStateUpdateHead; + return this; + } + + /** + * Sets the block hash. + * + * @param blockHash the block hash + * @return the builder + */ + public Builder withBlockHash(final Hash blockHash) { + this.blockHash = blockHash; + return this; + } + + /** + * Sets the state root. + * + * @param stateRoot the state root + * @return the builder + */ + public Builder withStateRoot(final Hash stateRoot) { + this.stateRoot = Optional.ofNullable(stateRoot); + return this; + } + + /** + * Builds an instance of WorldStateQueryParams. + * + * @return an instance of WorldStateQueryParams + */ + public WorldStateQueryParams build() { + return new WorldStateQueryParams(this); + } + } +} 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..6e672961c56 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 @@ -60,13 +60,25 @@ public abstract class DiffBasedWorldState protected Hash worldStateRootHash; protected Hash worldStateBlockHash; - protected DiffBasedWorldStateConfig worldStateConfig; + + // configuration parameters for the world state. + protected WorldStateSharedConfig worldStateConfig; + + /* + * Indicates whether the world state is in "frozen" mode. + * + * When `isStorageFrozen` is true: + * - Changes to accounts, code, or slots will not affect the underlying storage. + * - The state root can still be recalculated, and a trie log can be generated. + * - All modifications are temporary and will be lost once the world state is discarded. + */ + protected boolean isStorageFrozen; protected DiffBasedWorldState( final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedCachedWorldStorageManager cachedWorldStorageManager, final TrieLogManager trieLogManager, - final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { + final WorldStateSharedConfig worldStateConfig) { this.worldStateKeyValueStorage = worldStateKeyValueStorage; this.worldStateRootHash = Hash.wrap( @@ -77,7 +89,8 @@ protected DiffBasedWorldState( Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO))); this.cachedWorldStorageManager = cachedWorldStorageManager; this.trieLogManager = trieLogManager; - this.worldStateConfig = diffBasedWorldStateConfig; + this.worldStateConfig = worldStateConfig; + this.isStorageFrozen = false; } /** @@ -108,12 +121,21 @@ public Hash getWorldStateRootHash() { return worldStateRootHash; } + /** + * Determines whether the current world state is directly modifying the "head" state of the + * blockchain. A world state modifying the head directly updates the latest state of the node, + * while a world state derived from a snapshot or historical view (e.g., layered or snapshot world + * state) does not directly modify the head + * + * @return {@code true} if the current world state is modifying the head, {@code false} otherwise. + */ @Override - public boolean isPersisted() { - return isPersisted(worldStateKeyValueStorage); + public boolean isModifyingHeadWorldState() { + return isModifyingHeadWorldState(worldStateKeyValueStorage); } - private boolean isPersisted(final WorldStateKeyValueStorage worldStateKeyValueStorage) { + private boolean isModifyingHeadWorldState( + final WorldStateKeyValueStorage worldStateKeyValueStorage) { return !(worldStateKeyValueStorage instanceof DiffBasedSnapshotWorldStateKeyValueStorage); } @@ -140,8 +162,7 @@ protected Hash unsafeRootHashUpdate( final BlockHeader blockHeader, final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater) { // calling calculateRootHash in order to update the state - calculateRootHash( - worldStateConfig.isFrozen() ? Optional.empty() : Optional.of(stateUpdater), accumulator); + calculateRootHash(isStorageFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator); return blockHeader.getStateRoot(); } @@ -167,8 +188,7 @@ public void persist(final BlockHeader blockHeader) { if (blockHeader == null || !worldStateConfig.isTrieDisabled()) { calculatedRootHash = calculateRootHash( - worldStateConfig.isFrozen() ? Optional.empty() : Optional.of(stateUpdater), - accumulator); + isStorageFrozen ? Optional.empty() : Optional.of(stateUpdater), 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, @@ -186,7 +206,7 @@ public void persist(final BlockHeader blockHeader) { () -> { trieLogManager.saveTrieLog(localCopy, calculatedRootHash, blockHeader, this); // not save a frozen state in the cache - if (!worldStateConfig.isFrozen()) { + if (!isStorageFrozen) { cachedWorldStorageManager.addCachedLayer(blockHeader, calculatedRootHash, this); } }; @@ -234,7 +254,7 @@ public WorldUpdater updater() { @Override public Hash rootHash() { - if (worldStateConfig.isFrozen() && accumulator.isAccumulatorStateChanged()) { + if (isStorageFrozen && accumulator.isAccumulatorStateChanged()) { worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy()); accumulator.resetAccumulatorStateChanged(); } @@ -307,9 +327,9 @@ public UInt256 getPriorStorageValue(final Address address, final UInt256 storage @Override public void close() { try { - if (!isPersisted()) { + if (!isModifyingHeadWorldState()) { this.worldStateKeyValueStorage.close(); - if (worldStateConfig.isFrozen()) { + if (isStorageFrozen) { closeFrozenStorage(); } } @@ -322,7 +342,7 @@ private void closeFrozenStorage() { try { final DiffBasedLayeredWorldStateKeyValueStorage worldStateLayerStorage = (DiffBasedLayeredWorldStateKeyValueStorage) worldStateKeyValueStorage; - if (!isPersisted(worldStateLayerStorage.getParentWorldStateStorage())) { + if (!isModifyingHeadWorldState(worldStateLayerStorage.getParentWorldStateStorage())) { worldStateLayerStorage.getParentWorldStateStorage().close(); } } catch (Exception e) { @@ -333,6 +353,19 @@ private void closeFrozenStorage() { @Override public abstract Hash frontierRootHash(); + /** + * Configures the current world state to operate in "frozen" mode. + * + *

In this mode: - Changes (to accounts, code, or slots) are isolated and not applied to the + * underlying storage. - The state root can be recalculated, and a trie log can be generated, but + * updates will not affect the world state storage. - All modifications are temporary and will be + * lost once the world state is discarded. + * + *

Use Cases: - Calculating the state root after updates without altering the storage. - + * Generating a trie log. + * + * @return The current world state in "frozen" mode. + */ @Override public abstract MutableWorldState freeze(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java deleted file mode 100644 index cab7f3f8736..00000000000 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright contributors to Hyperledger Besu. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview; - -public class DiffBasedWorldStateConfig { - - private boolean isFrozen; - - private boolean isTrieDisabled; - - public DiffBasedWorldStateConfig() { - this(false, false); - } - - public DiffBasedWorldStateConfig(final boolean isTrieDisabled) { - this(false, isTrieDisabled); - } - - public DiffBasedWorldStateConfig(final DiffBasedWorldStateConfig config) { - this(config.isFrozen(), config.isTrieDisabled()); - } - - public DiffBasedWorldStateConfig(final boolean isFrozen, final boolean isTrieDisabled) { - this.isFrozen = isFrozen; - this.isTrieDisabled = isTrieDisabled; - } - - /** - * Checks if the world state is frozen. When the world state is frozen, it cannot mutate. - * - * @return true if the world state is frozen, false otherwise. - */ - public boolean isFrozen() { - return isFrozen; - } - - /** - * Sets the frozen status of the world state. When the world state is frozen, it cannot mutate. - * - * @param frozen the new frozen status to set. - */ - public void setFrozen(final boolean frozen) { - isFrozen = frozen; - } - - /** - * Checks if the trie is disabled for the world state. When the trie is disabled, the world state - * will only work with the flat database and not the trie. In this mode, it's impossible to verify - * the state root. - * - * @return true if the trie is disabled, false otherwise. - */ - public boolean isTrieDisabled() { - return isTrieDisabled; - } - - /** - * Sets the disabled status of the trie for the world state. When the trie is disabled, the world - * state will only work with the flat database and not the trie. In this mode, it's impossible to - * verify the state root. - * - * @param trieDisabled the new disabled status to set for the trie. - */ - public void setTrieDisabled(final boolean trieDisabled) { - isTrieDisabled = trieDisabled; - } -} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldView.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldView.java index 7ecc49e2863..8f3e2807266 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldView.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldView.java @@ -55,7 +55,7 @@ static Bytes encodeTrieValue(final Bytes bytes) { return out.encoded(); } - boolean isPersisted(); + boolean isModifyingHeadWorldState(); DiffBasedWorldStateKeyValueStorage getWorldStateStorage(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/WorldStateSharedConfig.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/WorldStateSharedConfig.java new file mode 100644 index 00000000000..ea6f4542e83 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/WorldStateSharedConfig.java @@ -0,0 +1,99 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview; + +/** WorldStateSharedConfig encapsulates the shared configuration parameters for the world state. */ +public class WorldStateSharedConfig { + + /** + * Indicates whether the trie is disabled for the world state. When the trie is disabled, the + * world state will only work with the flat database and not the trie. In this mode, it's + * impossible to verify the state root. + */ + private boolean isTrieDisabled; + + /** Indicates whether the mode is stateful. Default is true. */ + private boolean isStateful; + + private WorldStateSharedConfig(final Builder builder) { + this.isTrieDisabled = builder.isTrieDisabled; + this.isStateful = builder.isStateful; + } + + public boolean isTrieDisabled() { + return isTrieDisabled; + } + + public boolean isStateful() { + return isStateful; + } + + public void setTrieDisabled(final boolean trieDisabled) { + isTrieDisabled = trieDisabled; + } + + public void setStateful(final boolean stateful) { + isStateful = stateful; + } + + /** + * Merges this WorldStateSharedConfig with another WorldStateSharedConfig and returns a new + * instance. + * + * @param other the other WorldStateSharedConfig to merge with + * @return a new WorldStateSharedConfig instance with merged values + */ + public WorldStateSharedConfig apply(final WorldStateSharedConfig other) { + return new Builder(this).trieDisabled(other.isTrieDisabled).stateful(other.isStateful).build(); + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Builder newBuilder(final WorldStateSharedConfig worldStateSharedConfig) { + return new Builder(worldStateSharedConfig); + } + + public static WorldStateSharedConfig createStatefulConfigWithTrie() { + return newBuilder().stateful(true).trieDisabled(false).build(); + } + + public static class Builder { + private boolean isStateful = true; + private boolean isTrieDisabled = false; + + public Builder() {} + + public Builder(final WorldStateSharedConfig spec) { + this.isTrieDisabled = spec.isTrieDisabled(); + this.isStateful = spec.isStateful(); + } + + public Builder trieDisabled(final boolean trieDisabled) { + this.isTrieDisabled = trieDisabled; + return this; + } + + public Builder stateful(final boolean stateful) { + this.isStateful = stateful; + return this; + } + + public WorldStateSharedConfig build() { + return new WorldStateSharedConfig(this); + } + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/WorldStateStorageConfig.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/WorldStateStorageConfig.java new file mode 100644 index 00000000000..e2379330370 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/WorldStateStorageConfig.java @@ -0,0 +1,56 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview; + +public class WorldStateStorageConfig { + + private final boolean isFrozen; + + private WorldStateStorageConfig(final Builder builder) { + this.isFrozen = builder.isFrozen; + } + + public boolean isFrozen() { + return isFrozen; + } + + public static WorldStateStorageConfig.Builder newBuilder() { + return new WorldStateStorageConfig.Builder(); + } + + public static WorldStateStorageConfig.Builder newBuilder( + final WorldStateStorageConfig worldStateStorageConfig) { + return new WorldStateStorageConfig.Builder(worldStateStorageConfig); + } + + public static class Builder { + private boolean isFrozen = false; + + public Builder() {} + + public Builder(final WorldStateStorageConfig spec) { + this.isFrozen = spec.isFrozen(); + } + + public Builder setFrozen(final boolean isFrozen) { + this.isFrozen = isFrozen; + return this; + } + + public WorldStateStorageConfig build() { + return new WorldStateStorageConfig(this); + } + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java index 37e9c9c5830..b97ffe747b3 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java @@ -338,11 +338,6 @@ public Collection

getDeletedAccountAddresses() { return getDeletedAccounts(); } - @Override - public void revert() { - super.reset(); - } - @Override public void commit() { this.isAccumulatorStateChanged = true; @@ -604,7 +599,7 @@ public Map getAllAccountStorage(final Address address, final Has } @Override - public boolean isPersisted() { + public boolean isModifyingHeadWorldState() { return true; } @@ -867,6 +862,25 @@ public void resetAccumulatorStateChanged() { isAccumulatorStateChanged = false; } + /** + * Reverts all changes that have not yet been committed. + * + *

This method calls the `reset` method of the superclass, which cancels all changes that have + * not yet been committed. This effectively reverts the state to the last committed state. + */ + @Override + public void revert() { + super.reset(); + } + + /** + * Resets the accumulator by clearing all changes, including those that have been committed. + * + *

This method clears all internal maps and data structures that track changes. This includes + * clearing the storage to clear, storage to update, code to update, accounts to update, and other + * related data structures. This effectively removes all changes, even those that have been + * committed in the accumulator. + */ @Override public void reset() { storageToClear.clear(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/ForestWorldStateArchive.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/ForestWorldStateArchive.java index 800d2c98343..1d170a40133 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/ForestWorldStateArchive.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/ForestWorldStateArchive.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProof; import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider; import org.hyperledger.besu.ethereum.trie.MerkleTrie; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; @@ -57,7 +58,7 @@ public ForestWorldStateArchive( @Override public Optional get(final Hash rootHash, final Hash blockHash) { - return getMutable(rootHash, blockHash).map(state -> state); + return getWorldState(rootHash).map(state -> state); } @Override @@ -66,13 +67,20 @@ public boolean isWorldStateAvailable(final Hash rootHash, final Hash blockHash) } @Override - public Optional getMutable( - final BlockHeader blockHeader, final boolean isPersistingState) { - return getMutable(blockHeader.getStateRoot(), blockHeader.getHash()); + public Optional getWorldState(final WorldStateQueryParams queryParams) { + if (queryParams.getStateRoot().isEmpty()) { + throw new IllegalArgumentException( + "State root cannot be empty. A valid state root is required to retrieve the world state."); + } + return getWorldState(queryParams.getStateRoot().get()); } @Override - public Optional getMutable(final Hash rootHash, final Hash blockHash) { + public MutableWorldState getWorldState() { + return getWorldState(EMPTY_ROOT_HASH).get(); + } + + private Optional getWorldState(final Hash rootHash) { if (!worldStateKeyValueStorage.isWorldStateAvailable(rootHash)) { return Optional.empty(); } @@ -81,11 +89,6 @@ public Optional getMutable(final Hash rootHash, final Hash bl rootHash, worldStateKeyValueStorage, preimageStorage, evmConfiguration)); } - @Override - public MutableWorldState getMutable() { - return getMutable(EMPTY_ROOT_HASH, null).get(); - } - @Override public void resetArchiveStateTo(final BlockHeader blockHeader) { // ignore for forest diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/worldview/ForestMutableWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/worldview/ForestMutableWorldState.java index 360dabb0c6d..659608c20e9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/worldview/ForestMutableWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/forest/worldview/ForestMutableWorldState.java @@ -405,7 +405,6 @@ public void commit() { for (final UpdateTrackingAccount updated : getUpdatedAccounts()) { final WorldStateAccount origin = updated.getWrappedAccount(); - // Save the code in key-value storage ... Hash codeHash = origin == null ? Hash.EMPTY : origin.getCodeHash(); if (updated.codeWasUpdated()) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java index 9856a200b21..ac0f11b0102 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.proof.WorldStateProof; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.evm.worldstate.WorldState; import java.io.Closeable; @@ -34,11 +35,26 @@ public interface WorldStateArchive extends Closeable { boolean isWorldStateAvailable(Hash rootHash, Hash blockHash); - Optional getMutable(BlockHeader blockHeader, boolean isPersistingState); - - Optional getMutable(Hash rootHash, Hash blockHash); + /** + * Gets a mutable world state based on the provided query parameters. + * + *

This method retrieves the mutable world state using the provided query parameters. The query + * parameters can specify various conditions and filters to determine the specific world state to + * be retrieved. + * + * @param worldStateQueryParams the query parameters + * @return the mutable world state, if available + */ + Optional getWorldState(WorldStateQueryParams worldStateQueryParams); - MutableWorldState getMutable(); + /** + * Gets the head world state. + * + *

This method returns the head world state, which is the most recent state of the world. + * + * @return the head world state + */ + MutableWorldState getWorldState(); /** * Resetting the archive cache and adding the new pivot as the only entry diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java index acbd8679f41..de7ca749315 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java @@ -124,7 +124,7 @@ private List blockSequence( final List storageKeys) { final List seq = new ArrayList<>(count); - final MutableWorldState worldState = worldStateArchive.getMutable(); + final MutableWorldState worldState = worldStateArchive.getWorldState(); long nextBlockNumber = nextBlock; Hash parentHash = parent; diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java index b705ba01117..0d6cbccc31b 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java @@ -181,7 +181,7 @@ private static BlockchainSetupUtil create( : createInMemoryWorldStateArchive(); final TransactionPool transactionPool = mock(TransactionPool.class); - genesisState.writeStateTo(worldArchive.getMutable()); + genesisState.writeStateTo(worldArchive.getWorldState()); final ProtocolContext protocolContext = protocolContextProvider.get(blockchain, worldArchive); final Path blocksPath = Path.of(chainResources.getBlocksURL().toURI()); diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java index 873490fd451..4c423966d90 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java @@ -78,7 +78,7 @@ private ExecutionContextTestFixture( this.protocolContext = new ProtocolContext( blockchain, stateArchive, new ConsensusContextFixture(), new BadBlockManager()); - genesisState.writeStateTo(stateArchive.getMutable()); + genesisState.writeStateTo(stateArchive.getWorldState()); } public static ExecutionContextTestFixture create() { diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java index c4f492e3c80..f8c5749d500 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java @@ -191,7 +191,7 @@ public MessageFrame build() { } private WorldUpdater createDefaultWorldUpdater() { - return getOrCreateExecutionContextTestFixture().getStateArchive().getMutable().updater(); + return getOrCreateExecutionContextTestFixture().getStateArchive().getWorldState().updater(); } private Blockchain createDefaultBlockchain() { diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java index 06580ad4dea..08c62605ffb 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig.createStatefulConfigWithTrie; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -46,7 +47,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; @@ -105,7 +105,7 @@ class BlockImportExceptionHandlingTest { (BonsaiWorldStateKeyValueStorage) worldStateStorageCoordinator.worldStateKeyValueStorage(), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig())); + createStatefulConfigWithTrie())); private final BadBlockManager badBlockManager = new BadBlockManager(); @@ -128,8 +128,8 @@ public void setup() { void shouldNotBadBlockWhenInternalErrorDuringPersisting() { Mockito.doThrow(new StorageException("database problem")).when(persisted).persist(any()); - Mockito.doReturn(persisted).when(worldStateArchive).getMutable(); - Mockito.doReturn(Optional.of(persisted)).when(worldStateArchive).getMutable(any(), any()); + Mockito.doReturn(persisted).when(worldStateArchive).getWorldState(); + Mockito.doReturn(Optional.of(persisted)).when(worldStateArchive).getWorldState(any()); Block goodBlock = new BlockDataGenerator() @@ -234,8 +234,8 @@ void shouldNotBadBlockWhenInternalErrorDuringValidateHeader() { @Test void shouldNotBadBlockWhenInternalErrorDuringValidateBody() { Mockito.doNothing().when(persisted).persist(any()); - Mockito.doReturn(persisted).when(worldStateArchive).getMutable(); - Mockito.doReturn(Optional.of(persisted)).when(worldStateArchive).getMutable(any(), any()); + Mockito.doReturn(persisted).when(worldStateArchive).getWorldState(); + Mockito.doReturn(Optional.of(persisted)).when(worldStateArchive).getWorldState(any()); Block goodBlock = new BlockDataGenerator() diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java index 96e8cafe191..25f8a40131c 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/MainnetBlockValidatorTest.java @@ -15,9 +15,9 @@ package org.hyperledger.besu.ethereum; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; @@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.services.exception.StorageException; @@ -50,6 +51,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; public class MainnetBlockValidatorTest { @@ -91,11 +93,9 @@ public void setup() { when(protocolContext.getBlockchain()).thenReturn(blockchain); when(protocolContext.getWorldStateArchive()).thenReturn(worldStateArchive); - when(worldStateArchive.getMutable(any(BlockHeader.class), anyBoolean())) - .thenReturn(Optional.of(worldState)); - when(worldStateArchive.getMutable(any(Hash.class), any(Hash.class))) - .thenReturn(Optional.of(worldState)); - when(worldStateArchive.getMutable()).thenReturn(worldState); + when(worldStateArchive.getWorldState(any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getWorldState(any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getWorldState()).thenReturn(worldState); when(blockHeaderValidator.validateHeader(any(), any(), any())).thenReturn(true); when(blockHeaderValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(blockBodyValidator.validateBody(any(), any(), any(), any(), any(), any())) @@ -182,8 +182,17 @@ public void validateAndProcessBlock_whenBlockBodyInvalid() { @Test public void validateAndProcessBlock_whenParentWorldStateNotAvailable() { - when(worldStateArchive.getMutable(eq(blockParent.getHeader()), anyBoolean())) - .thenReturn(Optional.empty()); + final ArgumentCaptor captor = + ArgumentCaptor.forClass(WorldStateQueryParams.class); + when(worldStateArchive.getWorldState(captor.capture())) + .thenAnswer( + invocation -> { + WorldStateQueryParams capturedParams = captor.getValue(); + if (capturedParams.getBlockHeader().equals(blockParent.getHeader())) { + return Optional.empty(); + } + return null; + }); BlockProcessingResult result = mainnetBlockValidator.validateAndProcessBlock( @@ -258,7 +267,9 @@ public void validateAndProcessBlock_whenStorageExceptionThrownProcessingBlock( public void validateAndProcessBlock_whenStorageExceptionThrownGettingWorldState( final String caseName, final Exception storageException) { final BlockHeader parentHeader = blockParent.getHeader(); - doThrow(storageException).when(worldStateArchive).getMutable(eq(parentHeader), anyBoolean()); + doThrow(storageException) + .when(worldStateArchive) + .getWorldState(eq(withBlockHeaderAndUpdateNodeHead(parentHeader))); BlockProcessingResult result = mainnetBlockValidator.validateAndProcessBlock( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java index 0d05376183d..3f714150563 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java @@ -216,7 +216,7 @@ private void processSimpleTransfers(final BlockProcessor blockProcessor) { createTransferTransaction( 0, 2_000_000_000_000_000_000L, 300000L, 5L, 7L, ACCOUNT_3, ACCOUNT_GENESIS_2_KEYPAIR); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BonsaiAccount senderAccount1 = (BonsaiAccount) worldState.get(transactionTransfer1.getSender()); BonsaiAccount senderAccount2 = (BonsaiAccount) worldState.get(transactionTransfer2.getSender()); @@ -258,7 +258,7 @@ private void processConflictedSimpleTransfersSameSender(final BlockProcessor blo createTransferTransaction( 2, 3_000_000_000_000_000_000L, 300000L, 5L, 7L, ACCOUNT_6, ACCOUNT_GENESIS_1_KEYPAIR); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BonsaiAccount senderAccount = (BonsaiAccount) worldState.get(transferTransaction1.getSender()); Block blockWithTransactions = @@ -311,7 +311,7 @@ private void processConflictedSimpleTransfersSameAddressReceiverAndSender( ACCOUNT_2, ACCOUNT_GENESIS_2_KEYPAIR); // ACCOUNT_GENESIS_2 -> ACCOUNT_2 - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BonsaiAccount transferTransaction1Sender = (BonsaiAccount) worldState.get(transferTransaction1.getSender()); @@ -370,7 +370,7 @@ private void processConflictedSimpleTransfersWithCoinbase(final BlockProcessor b coinbase.toHexString(), ACCOUNT_GENESIS_2_KEYPAIR); // ACCOUNT_GENESIS_2 -> COINBASE - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BonsaiAccount transferTransaction1Sender = (BonsaiAccount) worldState.get(transferTransaction1.getSender()); Block blockWithTransactions = @@ -427,7 +427,7 @@ void processContractSlotUpdateThenReadTx(final BlockProcessor blockProcessor) { setSlot3Transaction, setSlot4Transaction); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BlockProcessingResult blockProcessingResult = blockProcessor.processBlock(blockchain, worldState, blockWithTransactions); @@ -462,7 +462,7 @@ void processSlotReadThenUpdateTx(final BlockProcessor blockProcessor) { setSlot1Transaction, setSlo2Transaction, setSlot3Transaction); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BlockProcessingResult blockProcessingResult = blockProcessor.processBlock(blockchain, worldState, blockWithTransactions); @@ -505,7 +505,7 @@ void processAccountReadThenUpdateTx(final BlockProcessor blockProcessor) { transactionTransfer, getcontractBalanceTransaction, sendEthFromContractTransaction); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BlockProcessingResult blockProcessingResult = blockProcessor.processBlock(blockchain, worldState, blockWithTransactions); @@ -551,7 +551,7 @@ void processAccountUpdateThenReadTx(final BlockProcessor blockProcessor) { transactionTransfer, sendEthFromContractTransaction, getcontractBalanceTransaction); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BlockProcessingResult blockProcessingResult = blockProcessor.processBlock(blockchain, worldState, blockWithTransactions); @@ -596,7 +596,7 @@ void processAccountReadThenUpdateTxWithTwoAccounts(final BlockProcessor blockPro transactionTransfer, getcontractBalanceTransaction, sendEthFromContractTransaction); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BlockProcessingResult blockProcessingResult = blockProcessor.processBlock(blockchain, worldState, blockWithTransactions); @@ -642,7 +642,7 @@ void processAccountUpdateThenReadTxWithTwoAccounts(final BlockProcessor blockPro transactionTransfer, sendEthFromContractTransaction, getcontractBalanceTransaction); - MutableWorldState worldState = worldStateArchive.getMutable(); + MutableWorldState worldState = worldStateArchive.getWorldState(); BlockProcessingResult blockProcessingResult = blockProcessor.processBlock(blockchain, worldState, blockWithTransactions); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java index d80e183da28..ce6e7c91fcc 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java @@ -157,10 +157,9 @@ void mustPerformRehydration() { when(blockchain.getBlockHeader(any())).thenReturn(Optional.of(firstBlock.getHeader())); final ProtocolSpec protocolSpec = mockProtocolSpec(); when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); - when(publicWorldStateArchive.getMutable(any(), any())) - .thenReturn(Optional.of(mutableWorldState)); + when(publicWorldStateArchive.getWorldState(any())).thenReturn(Optional.of(mutableWorldState)); final MutableWorldState mockPrivateStateArchive = mockPrivateStateArchive(); - when(privateWorldStateArchive.getMutable(any(), any())) + when(privateWorldStateArchive.getWorldState(any())) .thenReturn(Optional.of(mockPrivateStateArchive)); final PrivacyGroupHeadBlockMap expected = diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java index c446b18f28b..325df40c0aa 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet.parallelization; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig.createStatefulConfigWithTrie; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -39,7 +40,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.blockhash.BlockHashLookup; @@ -88,7 +88,7 @@ void setUp() { new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage), new NoOpTrieLogManager(), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); when(transactionCollisionDetector.hasCollision(any(), any(), any(), any())).thenReturn(false); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java index c4653856ef1..1db44f94984 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java @@ -106,8 +106,8 @@ private PrivateTransactionProcessor mockPrivateTxProcessor( public void setUp() { final MutableWorldState mutableWorldState = mock(MutableWorldState.class); when(mutableWorldState.updater()).thenReturn(mock(WorldUpdater.class)); - when(worldStateArchive.getMutable()).thenReturn(mutableWorldState); - when(worldStateArchive.getMutable(any(), any())).thenReturn(Optional.of(mutableWorldState)); + when(worldStateArchive.getWorldState()).thenReturn(mutableWorldState); + when(worldStateArchive.getWorldState(any())).thenReturn(Optional.of(mutableWorldState)); final PrivateStateStorage.Updater storageUpdater = mock(PrivateStateStorage.Updater.class); when(privateStateStorage.getPrivacyGroupHeadBlockMap(any())) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java index 6b333ef3497..b869a3d32dc 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java @@ -113,8 +113,8 @@ private PrivateTransactionProcessor mockPrivateTxProcessor( public void setUp() { final MutableWorldState mutableWorldState = mock(MutableWorldState.class); when(mutableWorldState.updater()).thenReturn(mock(WorldUpdater.class)); - when(worldStateArchive.getMutable()).thenReturn(mutableWorldState); - when(worldStateArchive.getMutable(any(), any())).thenReturn(Optional.of(mutableWorldState)); + when(worldStateArchive.getWorldState()).thenReturn(mutableWorldState); + when(worldStateArchive.getWorldState(any())).thenReturn(Optional.of(mutableWorldState)); when(privateMetadataUpdater.getPrivacyGroupHeadBlockMap()) .thenReturn(PrivacyGroupHeadBlockMap.empty()); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java index a4f7b3e400c..9a17c076ee6 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java @@ -21,6 +21,7 @@ import static org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver.EMPTY_ROOT_HASH; import static org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage.SCHEMA_VERSION_1_0_0; import static org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage.SCHEMA_VERSION_1_4_0; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.lenient; @@ -313,7 +314,7 @@ private void mockBlockInBlockchain(final Block block) { when(blockchain.getBlockHeader(blockHash)).thenReturn(Optional.of(blockHeader)); when(blockchain.getBlockBody(blockHash)).thenReturn(Optional.of(block.getBody())); - when(publicWorldStateArchive.getMutable(blockHeader.getStateRoot(), blockHash)) + when(publicWorldStateArchive.getWorldState(withBlockHeaderAndUpdateNodeHead(blockHeader))) .thenReturn(Optional.of(publicMutableWorldState)); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java index 4a615aad006..b60a4afb6e5 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java @@ -15,12 +15,12 @@ package org.hyperledger.besu.ethereum.transaction; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -98,20 +99,20 @@ public void setUp() { @Test public void shouldProcessWithValidWorldState() { - when(worldStateArchive.getMutable(any(BlockHeader.class), eq(false))) + + when(worldStateArchive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader))) .thenReturn(Optional.of(mutableWorldState)); List results = blockSimulator.process(blockHeader, Collections.emptyList()); - assertNotNull(results); - verify(worldStateArchive).getMutable(any(BlockHeader.class), eq(false)); + verify(worldStateArchive).getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader)); } @Test public void shouldNotProcessWithInvalidWorldState() { - when(worldStateArchive.getMutable(any(BlockHeader.class), eq(false))) - .thenReturn(Optional.empty()); + when(worldStateArchive.getWorldState(any(WorldStateQueryParams.class))) + .thenAnswer(invocation -> Optional.empty()); IllegalArgumentException exception = assertThrows( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java index f0e32ead379..0c96b65a301 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.transaction; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import static org.hyperledger.besu.evm.tracing.OperationTracer.NO_TRACING; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -805,7 +806,7 @@ private void mockWorldStateForAccount( final BlockHeader blockHeader, final Address address, final long nonce) { final Account account = mock(Account.class); when(account.getNonce()).thenReturn(nonce); - when(worldStateArchive.getMutable(eq(blockHeader), anyBoolean())) + when(worldStateArchive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader))) .thenReturn(Optional.of(worldState)); final WorldUpdater updater = mock(WorldUpdater.class); when(updater.get(address)).thenReturn(account); @@ -813,7 +814,7 @@ private void mockWorldStateForAccount( } private void mockWorldStateForAbsentAccount(final BlockHeader blockHeader) { - when(worldStateArchive.getMutable(eq(blockHeader), anyBoolean())) + when(worldStateArchive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader))) .thenReturn(Optional.of(worldState)); final WorldUpdater updater = mock(WorldUpdater.class); when(updater.get(any())).thenReturn(null); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java index de0aa4a8cb8..4b8ce3b0fb8 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java @@ -171,7 +171,7 @@ public void createStorage() { null, EvmConfiguration.DEFAULT, throwingWorldStateHealerSupplier()); - var ws = archive.getMutable(); + var ws = archive.getWorldState(); genesisState.writeStateTo(ws); protocolContext = new ProtocolContext( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java index 322aacb7eb7..78141235458 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java @@ -15,6 +15,8 @@ package org.hyperledger.besu.ethereum.trie.diffbased.bonsai; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; @@ -32,11 +34,15 @@ public class BonsaiSnapshotIsolationTests extends AbstractIsolationTests { @Test public void ensureTruncateDoesNotCauseSegfault() { - var preTruncatedWorldState = archive.getMutable(genesisState.getBlock().getHeader(), false); + var preTruncatedWorldState = + archive.getWorldState( + withBlockHeaderAndNoUpdateNodeHead(genesisState.getBlock().getHeader())); assertThat(preTruncatedWorldState) .isPresent(); // really just assert that we have not segfaulted after truncating worldStateKeyValueStorage.clear(); - var postTruncatedWorldState = archive.getMutable(genesisState.getBlock().getHeader(), false); + var postTruncatedWorldState = + archive.getWorldState( + withBlockHeaderAndNoUpdateNodeHead(genesisState.getBlock().getHeader())); assertThat(postTruncatedWorldState).isEmpty(); // assert that trying to access pre-worldstate does not segfault after truncating preTruncatedWorldState.get().get(accounts.get(0).address()); @@ -47,14 +53,17 @@ public void ensureTruncateDoesNotCauseSegfault() { public void testIsolatedFromHead_behindHead() { Address testAddress = Address.fromHexString("0xdeadbeef"); // assert we can mutate head without mutating the isolated snapshot - var isolated = archive.getMutable(genesisState.getBlock().getHeader(), false); + var isolated = + archive.getWorldState( + withBlockHeaderAndNoUpdateNodeHead(genesisState.getBlock().getHeader())); var firstBlock = forTransactions(List.of(burnTransaction(sender1, 0L, testAddress))); - var res = executeBlock(archive.getMutable(), firstBlock); + var res = executeBlock(archive.getWorldState(), firstBlock); - var isolated2 = archive.getMutable(firstBlock.getHeader(), false); + var isolated2 = + archive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(firstBlock.getHeader())); var secondBlock = forTransactions(List.of(burnTransaction(sender1, 1L, testAddress))); - var res2 = executeBlock(archive.getMutable(), secondBlock); + var res2 = executeBlock(archive.getWorldState(), secondBlock); assertThat(res.isSuccessful()).isTrue(); assertThat(res2.isSuccessful()).isTrue(); @@ -62,8 +71,8 @@ public void testIsolatedFromHead_behindHead() { assertThat(archive.getCachedWorldStorageManager().contains(firstBlock.getHash())).isTrue(); assertThat(archive.getCachedWorldStorageManager().contains(secondBlock.getHash())).isTrue(); - assertThat(archive.getMutable().get(testAddress)).isNotNull(); - assertThat(archive.getMutable().get(testAddress).getBalance()) + assertThat(archive.getWorldState().get(testAddress)).isNotNull(); + assertThat(archive.getWorldState().get(testAddress).getBalance()) .isEqualTo(Wei.of(2_000_000_000_000_000_000L)); assertThat(isolated.get().get(testAddress)).isNull(); @@ -89,13 +98,13 @@ public void testSnapshotRollToTrieLogBlockHash() { Address testAddress = Address.fromHexString("0xdeadbeef"); var block1 = forTransactions(List.of(burnTransaction(sender1, 0L, testAddress))); - var res = executeBlock(archive.getMutable(), block1); + var res = executeBlock(archive.getWorldState(), block1); var block2 = forTransactions(List.of(burnTransaction(sender1, 1L, testAddress))); - var res2 = executeBlock(archive.getMutable(), block2); + var res2 = executeBlock(archive.getWorldState(), block2); var block3 = forTransactions(List.of(burnTransaction(sender1, 2L, testAddress))); - var res3 = executeBlock(archive.getMutable(), block3); + var res3 = executeBlock(archive.getWorldState(), block3); assertThat(res.isSuccessful()).isTrue(); assertThat(res2.isSuccessful()).isTrue(); @@ -103,7 +112,8 @@ public void testSnapshotRollToTrieLogBlockHash() { // roll chain and worldstate to block 2 blockchain.rewindToBlock(2L); - var block1State = archive.getMutable(null, block2.getHash()); + var block1State = + archive.getWorldState(withStateRootAndBlockHashAndUpdateNodeHead(null, block2.getHash())); // BonsaiWorldState should be at block 2 assertThat(block1State.get().get(testAddress)).isNotNull(); @@ -111,7 +121,8 @@ public void testSnapshotRollToTrieLogBlockHash() { .isEqualTo(Wei.of(2_000_000_000_000_000_000L)); assertThat(block1State.get().rootHash()).isEqualTo(block2.getHeader().getStateRoot()); - var isolatedRollForward = archive.getMutable(block3.getHeader(), false); + var isolatedRollForward = + archive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(block3.getHeader())); // we should be at block 3, one block ahead of BonsaiPersistatedWorldState assertThat(isolatedRollForward.get().get(testAddress)).isNotNull(); @@ -120,7 +131,8 @@ public void testSnapshotRollToTrieLogBlockHash() { assertThat(isolatedRollForward.get().rootHash()).isEqualTo(block3.getHeader().getStateRoot()); // we should be at block 1, one block behind BonsaiPersistatedWorldState - var isolatedRollBack = archive.getMutable(block1.getHeader(), false); + var isolatedRollBack = + archive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(block1.getHeader())); assertThat(isolatedRollBack.get().get(testAddress)).isNotNull(); assertThat(isolatedRollBack.get().get(testAddress).getBalance()) .isEqualTo(Wei.of(1_000_000_000_000_000_000L)); @@ -138,10 +150,12 @@ public void testSnapshotRollToTrieLogBlockHash() { public void assertCloseDisposesOfStateWithoutCommitting() { Address testAddress = Address.fromHexString("0xdeadbeef"); - var head = archive.getMutable(); + var head = archive.getWorldState(); try (var shouldCloseSnapshot = - archive.getMutable(genesisState.getBlock().getHeader(), false).get()) { + archive + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(genesisState.getBlock().getHeader())) + .get()) { var tx1 = burnTransaction(sender1, 0L, testAddress); Block oneTx = forTransactions(List.of(tx1)); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProviderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProviderTest.java index 87cc16c23c3..f2a7a65fe29 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProviderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProviderTest.java @@ -18,6 +18,9 @@ import static org.hyperledger.besu.ethereum.core.WorldStateHealerHelper.throwingWorldStateHealerSupplier; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.BLOCKCHAIN; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndUpdateNodeHead; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead; import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY; import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY; import static org.mockito.ArgumentMatchers.any; @@ -115,7 +118,7 @@ void testGetMutableReturnPersistedStateWhenNeeded() { EvmConfiguration.DEFAULT, throwingWorldStateHealerSupplier()); - assertThat(bonsaiWorldStateArchive.getMutable(chainHead, true)) + assertThat(bonsaiWorldStateArchive.getWorldState(withBlockHeaderAndUpdateNodeHead(chainHead))) .containsInstanceOf(BonsaiWorldState.class); } @@ -136,7 +139,9 @@ void testGetMutableReturnEmptyWhenLoadMoreThanLimitLayersBack() { final BlockHeader blockHeader = blockBuilder.number(0).buildHeader(); final BlockHeader chainHead = blockBuilder.number(512).buildHeader(); when(blockchain.getChainHeadHeader()).thenReturn(chainHead); - assertThat(bonsaiWorldStateArchive.getMutable(blockHeader, false)).isEmpty(); + assertThat( + bonsaiWorldStateArchive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader))) + .isEmpty(); verify(cachedWorldStorageManager, Mockito.never()).getWorldState(any(Hash.class)); } @@ -165,7 +170,8 @@ void testGetMutableWhenLoadLessThanLimitLayersBack() { when(cachedWorldStorageManager.getWorldState(blockHeader.getHash())) .thenReturn(Optional.of(mockWorldState)); when(blockchain.getChainHeadHeader()).thenReturn(chainHead); - assertThat(bonsaiWorldStateArchive.getMutable(blockHeader, false)) + assertThat( + bonsaiWorldStateArchive.getWorldState(withBlockHeaderAndNoUpdateNodeHead(blockHeader))) .containsInstanceOf(BonsaiWorldState.class); } @@ -195,7 +201,9 @@ void testGetMutableWithStorageInconsistencyRollbackTheState() { when(blockchain.getBlockHeader(blockHeader.getHash())).thenReturn(Optional.of(blockHeader)); - assertThat(bonsaiWorldStateArchive.getMutable(null, blockHeader.getHash())) + assertThat( + bonsaiWorldStateArchive.getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead(null, blockHeader.getHash()))) .containsInstanceOf(BonsaiWorldState.class); // verify is trying to get the trie log layer to rollback @@ -227,7 +235,9 @@ void testGetMutableWithStorageConsistencyNotRollbackTheState() { when(blockchain.getBlockHeader(blockHeader.getHash())).thenReturn(Optional.of(blockHeader)); when(blockchain.getBlockHeader(Hash.ZERO)).thenReturn(Optional.of(blockHeader)); - assertThat(bonsaiWorldStateArchive.getMutable(null, blockHeader.getHash())) + assertThat( + bonsaiWorldStateArchive.getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead(null, blockHeader.getHash()))) .containsInstanceOf(BonsaiWorldState.class); // verify is not trying to get the trie log layer to rollback when block is present @@ -269,7 +279,9 @@ void testGetMutableWithStorageConsistencyToRollbackAndRollForwardTheState() { .thenReturn(Optional.of(blockHeaderChainB)); when(blockchain.getBlockHeader(genesis.getHash())).thenReturn(Optional.of(genesis)); - assertThat(bonsaiWorldStateArchive.getMutable(null, blockHeaderChainB.getHash())) + assertThat( + bonsaiWorldStateArchive.getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead(null, blockHeaderChainB.getHash()))) .containsInstanceOf(BonsaiWorldState.class); // verify is trying to get the trie log layers to rollback and roll forward @@ -279,7 +291,7 @@ void testGetMutableWithStorageConsistencyToRollbackAndRollForwardTheState() { @Test // TODO: refactor to test original intent - @Disabled("needs refactor, getMutable(hash, hash) cannot trigger saveTrieLog") + @Disabled("needs refactor, getWorldState(hash, hash) cannot trigger saveTrieLog") void testGetMutableWithRollbackNotOverrideTrieLogLayer() { when(segmentedKeyValueStorage.startTransaction()) .thenReturn(segmentedKeyValueStorageTransaction); @@ -321,7 +333,9 @@ void testGetMutableWithRollbackNotOverrideTrieLogLayer() { .thenReturn(Optional.of(blockHeaderChainB)); when(blockchain.getBlockHeader(genesis.getHash())).thenReturn(Optional.of(genesis)); - assertThat(bonsaiWorldStateArchive.getMutable(null, blockHeaderChainB.getHash())) + assertThat( + bonsaiWorldStateArchive.getWorldState( + withStateRootAndBlockHashAndUpdateNodeHead(null, blockHeaderChainB.getHash()))) .containsInstanceOf(BonsaiWorldState.class); // verify is not persisting if already present diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java index e43d464474c..410b4322c87 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.trie.diffbased.bonsai; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig.createStatefulConfigWithTrie; import static org.mockito.Mockito.mock; import org.hyperledger.besu.datatypes.Address; @@ -32,7 +33,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -164,7 +164,7 @@ void simpleRollForwardTest() { new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -181,7 +181,7 @@ provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFI new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); final BonsaiWorldStateUpdateAccumulator secondUpdater = (BonsaiWorldStateUpdateAccumulator) secondWorldState.updater(); @@ -214,7 +214,7 @@ void rollForwardTwice() { new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -239,7 +239,7 @@ provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFI new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); final BonsaiWorldStateUpdateAccumulator secondUpdater = (BonsaiWorldStateUpdateAccumulator) secondWorldState.updater(); @@ -273,7 +273,7 @@ void rollBackOnce() { new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -305,7 +305,7 @@ provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFI new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); final WorldUpdater secondUpdater = secondWorldState.updater(); final MutableAccount secondMutableAccount = diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java index 09e21138fd3..d927655d9a0 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java @@ -19,6 +19,7 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig.createStatefulConfigWithTrie; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; @@ -28,7 +29,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -59,7 +59,7 @@ public static void main(final String[] arg) throws IOException { new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); final SegmentedInMemoryKeyValueStorage worldStateKeyValueStorage = (SegmentedInMemoryKeyValueStorage) provider.getStorageBySegmentIdentifiers( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java index b342172b1ba..0c700f5117b 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig.createStatefulConfigWithTrie; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -24,7 +25,6 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.evm.internal.EvmConfiguration; import java.util.HashMap; @@ -63,7 +63,7 @@ void setup() { InMemoryKeyValueStorageProvider.createBonsaiInMemoryWorldStateArchive(blockchain), bonsaiWorldStateKeyValueStorage, EvmConfiguration.DEFAULT, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); } @ParameterizedTest diff --git a/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java b/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java index f4764f129dd..b575af0f37c 100644 --- a/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java +++ b/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java @@ -131,7 +131,7 @@ public void setUpUnchangedState() { private Hash createExistingWorldState() { // Setup existing state final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); - final MutableWorldState worldState = worldStateArchive.getMutable(); + final MutableWorldState worldState = worldStateArchive.getWorldState(); dataGen.createRandomAccounts(worldState, 10000); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java index 1adc5977bb6..a2310049e39 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java @@ -18,6 +18,7 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INTERNAL_ERROR; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.TRANSACTION_ALREADY_KNOWN; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobsWithCommitments; @@ -476,7 +477,7 @@ && strictReplayProtectionShouldBeEnforcedLocally(chainHeadBlockHeader) try (final var worldState = protocolContext .getWorldStateArchive() - .getMutable(chainHeadBlockHeader, false) + .getWorldState(withBlockHeaderAndNoUpdateNodeHead(chainHeadBlockHeader)) .orElseThrow()) { final Account senderAccount = worldState.get(transaction.getSender()); return new ValidationResultAndAccount( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServerGetAccountRangeTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServerGetAccountRangeTest.java index eb97419967b..8dfdb034e60 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServerGetAccountRangeTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServerGetAccountRangeTest.java @@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.ImmutableSnapSyncConfiguration; import org.hyperledger.besu.ethereum.eth.sync.snapsync.SnapSyncConfiguration; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; -import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; @@ -379,7 +379,7 @@ private NavigableMap getAccountRange(final AccountRangeRequestPa @SuppressWarnings("UnusedVariable") private void initAccounts() { - rootHash = protocolContext.getWorldStateArchive().getMutable().rootHash(); + rootHash = protocolContext.getWorldStateArchive().getWorldState().rootHash(); GetAccountRangeMessage requestMessage = GetAccountRangeMessage.create(rootHash, Hash.ZERO, Hash.LAST, BigInteger.valueOf(4000)); AccountRangeMessage resultMessage = diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java index 431c044cbbf..82d21e39b89 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java @@ -201,7 +201,7 @@ void downloadEmptyWorldState() { void downloadAlreadyAvailableWorldState() { // Setup existing state final ForestWorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); - final MutableWorldState worldState = worldStateArchive.getMutable(); + final MutableWorldState worldState = worldStateArchive.getWorldState(); // Generate accounts and save corresponding state root dataGen.createRandomAccounts(worldState, 20); @@ -252,7 +252,7 @@ void canRecoverFromTimeouts() { // Setup "remote" state final WorldStateArchive remoteWorldStateArchive = createInMemoryWorldStateArchive(); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root final List accounts = dataGen.createRandomAccounts(remoteWorldState, 20); @@ -309,7 +309,7 @@ void handlesPartialResponsesFromNetwork() { void doesNotRequestKnownCodeFromNetwork() { // Setup "remote" state final WorldStateArchive remoteWorldStateArchive = createInMemoryWorldStateArchive(); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root final List accounts = @@ -397,7 +397,7 @@ private void testCancellation(final boolean shouldCancelFuture) { // Setup "remote" state final WorldStateArchive remoteWorldStateArchive = createInMemoryWorldStateArchive(); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root dataGen.createRandomContractAccountsWithNonEmptyStorage(remoteWorldState, 20); @@ -474,7 +474,7 @@ void doesNotRequestKnownAccountTrieNodesFromNetwork() { new WorldStateStorageCoordinator(remoteStorage), createPreimageStorage(), EvmConfiguration.DEFAULT); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root final List accounts = @@ -565,7 +565,7 @@ void doesNotRequestKnownStorageTrieNodesFromNetwork() { new WorldStateStorageCoordinator(remoteStorage), createPreimageStorage(), EvmConfiguration.DEFAULT); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root final List accounts = @@ -679,7 +679,7 @@ void stalledDownloader() { new WorldStateStorageCoordinator(remoteStorage), createPreimageStorage(), EvmConfiguration.DEFAULT); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root dataGen.createRandomAccounts(remoteWorldState, 10); @@ -743,7 +743,7 @@ void resumesFromNonEmptyQueue() { new WorldStateStorageCoordinator(remoteStorage), createPreimageStorage(), EvmConfiguration.DEFAULT); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root List accounts = dataGen.createRandomAccounts(remoteWorldState, 10); @@ -886,7 +886,7 @@ private void downloadAvailableWorldStateFromPeers( new WorldStateStorageCoordinator(remoteStorage), createPreimageStorage(), EvmConfiguration.DEFAULT); - final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable(); + final MutableWorldState remoteWorldState = remoteWorldStateArchive.getWorldState(); // Generate accounts and save corresponding state root final List accounts = dataGen.createRandomAccounts(remoteWorldState, accountCount); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java index e29b8285c9c..2da4f7f68d6 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java @@ -134,7 +134,7 @@ public TestNode( final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock(), blockHeaderFunctions); final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); - genesisState.writeStateTo(worldStateArchive.getMutable()); + genesisState.writeStateTo(worldStateArchive.getWorldState()); final ProtocolContext protocolContext = new ProtocolContext( blockchain, worldStateArchive, mock(ConsensusContext.class), new BadBlockManager()); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/BlockchainTestSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/BlockchainTestSubCommand.java index bec68a3cc39..8f7b58ea9eb 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/BlockchainTestSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/BlockchainTestSubCommand.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.referencetests.BlockchainReferenceTestCaseSpec; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules; import org.hyperledger.besu.ethereum.rlp.RLPException; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.EvmSpecVersion; import org.hyperledger.besu.evm.account.AccountState; @@ -168,7 +169,9 @@ private void traceTestSpecs(final String test, final BlockchainReferenceTestCase final BlockHeader genesisBlockHeader = spec.getGenesisBlockHeader(); final MutableWorldState worldState = spec.getWorldStateArchive() - .getMutable(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash()) + .getWorldState( + WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead( + genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash())) .orElseThrow(); final ProtocolSchedule schedule = diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java index 487874d8e3d..4782f4d1c50 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java @@ -68,7 +68,7 @@ private NodeSmartContractPermissioningController setupController( final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final WorldStateArchive worldArchive = createInMemoryWorldStateArchive(); - genesisState.writeStateTo(worldArchive.getMutable()); + genesisState.writeStateTo(worldArchive.getWorldState()); final TransactionSimulator ts = new TransactionSimulator( diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java index daea4a6d210..4857c0ecaee 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java @@ -66,7 +66,7 @@ private TransactionSmartContractPermissioningController setupController( final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final WorldStateArchive worldArchive = createInMemoryWorldStateArchive(); - genesisState.writeStateTo(worldArchive.getMutable()); + genesisState.writeStateTo(worldArchive.getWorldState()); final TransactionSimulator ts = new TransactionSimulator( diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java index d39c436ee5b..6bd038eda43 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java @@ -73,7 +73,7 @@ private static WorldStateArchive buildWorldStateArchive( final Map accounts) { final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); - final MutableWorldState worldState = worldStateArchive.getMutable(); + final MutableWorldState worldState = worldStateArchive.getWorldState(); final WorldUpdater updater = worldState.updater(); for (final Map.Entry entry : accounts.entrySet()) { diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java index 5d67318ab40..e2f62b5ce5a 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.referencetests; +import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.WorldStateSharedConfig.createStatefulConfigWithTrie; + import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -28,7 +30,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -74,7 +75,7 @@ protected BonsaiReferenceTestWorldState( cachedWorldStorageManager, trieLogManager, evmConfiguration, - new DiffBasedWorldStateConfig()); + createStatefulConfigWithTrie()); this.refTestStorage = worldStateKeyValueStorage; this.preImageProxy = preImageProxy; this.evmConfiguration = evmConfiguration; diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java index f4cb3dc67db..b273a8dd818 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java @@ -30,6 +30,7 @@ import org.hyperledger.besu.ethereum.referencetests.BlockchainReferenceTestCaseSpec; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules; import org.hyperledger.besu.ethereum.rlp.RLPException; +import org.hyperledger.besu.ethereum.trie.diffbased.common.provider.WorldStateQueryParams; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.EvmSpecVersion; import org.hyperledger.besu.evm.account.AccountState; @@ -109,7 +110,7 @@ public static void executeTest(final BlockchainReferenceTestCaseSpec spec) { final BlockHeader genesisBlockHeader = spec.getGenesisBlockHeader(); final MutableWorldState worldState = spec.getWorldStateArchive() - .getMutable(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash()) + .getWorldState(WorldStateQueryParams.withStateRootAndBlockHashAndUpdateNodeHead(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash())) .orElseThrow(); final ProtocolSchedule schedule = diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 77d918b2445..a554dcf5756 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -71,7 +71,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = '2b6i9SVzINvYv2E4yHk10d6ad+pzA12xsMltKghnW+U=' + knownHash = 'vL/8rpk/1ZsOjnDKgXm8K6v6pwZthTYH8mCs9dZV1Qk=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java deleted file mode 100644 index 3f66ffb86e1..00000000000 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright contributors to Hyperledger Besu. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.plugin.services.sync; - -/** interface for worldstate configuration * */ -public interface WorldStateConfiguration { - - /** - * Returns whether the trie is disabled. - * - * @return true if the trie is disabled, false otherwise. - */ - boolean isTrieDisabled(); -}