diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java index ad96b788eb..a5713208e7 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java @@ -219,7 +219,7 @@ public class GraphQLDataFetchers { final Long bn = dataFetchingEnvironment.getArgument("blockNumber"); if (bn != null) { return blockchainQuery - .mapWorldState( + .getAndMapWorldState( bn, ws -> { final Account account = ws.get(addr); @@ -241,7 +241,7 @@ public class GraphQLDataFetchers { } else { // return account on latest block final long latestBn = blockchainQuery.latestBlock().get().getHeader().getNumber(); - return blockchainQuery.mapWorldState( + return blockchainQuery.getAndMapWorldState( latestBn, ws -> { final Account account = ws.get(addr); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java index 50a9147865..6135a409f3 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java @@ -96,7 +96,7 @@ public class BlockAdapterBase extends AdapterBase { } return query - .mapWorldState(blockNumber, ws -> ws.get(header.getCoinbase())) + .getAndMapWorldState(blockNumber, ws -> ws.get(header.getCoinbase())) .map(account -> (AdapterBase) new AccountAdapter(account)) .or(() -> Optional.of(new EmptyAccountAdapter(header.getCoinbase()))); } @@ -146,7 +146,7 @@ public class BlockAdapterBase extends AdapterBase { final BlockchainQueries query = getBlockchainQueries(environment); final long bn = header.getNumber(); - return query.mapWorldState( + return query.getAndMapWorldState( bn, ws -> { final Address address = environment.getArgument("address"); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java index dcc8c17599..52f55ea3ff 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java @@ -63,7 +63,7 @@ public class LogAdapter extends AdapterBase { blockNumber = bn; } - return query.mapWorldState( + return query.getAndMapWorldState( blockNumber, ws -> new AccountAdapter(ws.get(logWithMetadata.getLogger()))); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java index 04bedb0dbf..9a3d3d5fa8 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java @@ -65,7 +65,7 @@ public class PendingStateAdapter extends AdapterBase { final Long blockNumber = dataFetchingEnvironment.getArgument("blockNumber"); final long latestBlockNumber = blockchainQuery.latestBlock().get().getHeader().getNumber(); return blockchainQuery - .mapWorldState(latestBlockNumber, ws -> ws.get(addr)) + .getAndMapWorldState(latestBlockNumber, ws -> ws.get(addr)) .map(AccountAdapter::new); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java index d7badd8d74..454590539d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java @@ -82,7 +82,7 @@ public class TransactionAdapter extends AdapterBase { if (blockNumber == null) { blockNumber = transactionWithMetadata.getBlockNumber().orElseGet(query::headBlockNumber); } - return query.mapWorldState( + return query.getAndMapWorldState( blockNumber, mutableWorldState -> new AccountAdapter( @@ -96,7 +96,7 @@ public class TransactionAdapter extends AdapterBase { blockNumber = transactionWithMetadata.getBlockNumber().orElseGet(query::headBlockNumber); } - return query.mapWorldState( + return query.getAndMapWorldState( blockNumber, ws -> transactionWithMetadata @@ -174,7 +174,7 @@ public class TransactionAdapter extends AdapterBase { return Optional.empty(); } final long blockNumber = bn.orElseGet(txBlockNumber::get); - return query.mapWorldState(blockNumber, ws -> new AccountAdapter(ws.get(addr.get()))); + return query.getAndMapWorldState(blockNumber, ws -> new AccountAdapter(ws.get(addr.get()))); } } return Optional.empty(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugAccountRange.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugAccountRange.java index 00ef66dd8a..777cc3f98b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugAccountRange.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugAccountRange.java @@ -75,7 +75,7 @@ public class DebugAccountRange implements JsonRpcMethod { // TODO deal with mid-block locations return blockchainQueries .get() - .mapWorldState( + .getAndMapWorldState( blockHeaderOptional.get().getNumber(), state -> { final List accounts = diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStorageRangeAt.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStorageRangeAt.java index 8a954fb996..488ea999ea 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStorageRangeAt.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStorageRangeAt.java @@ -104,7 +104,7 @@ public class DebugStorageRangeAt implements JsonRpcMethod { () -> blockchainQueries .get() - .mapWorldState( + .getAndMapWorldState( blockHeaderOptional.get().getNumber(), worldState -> extractStorageAt( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProof.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProof.java index 2a479ac5bf..b2d5007579 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProof.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProof.java @@ -58,7 +58,7 @@ public class EthGetProof extends AbstractBlockParameterOrBlockHashMethod { final List storageKeys = getStorageKeys(requestContext); return getBlockchainQueries() - .mapWorldState( + .getAndMapWorldState( blockHash, worldState -> { Optional proofOptional = diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java index eecb648c5e..1292b7117c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java @@ -111,7 +111,7 @@ public class TraceCallMany extends TraceCall implements JsonRpcMethod { final List traceCallResults = new ArrayList<>(); return getBlockchainQueries() - .mapWorldState( + .getAndMapWorldState( blockHeader.getBlockHash(), ws -> { final WorldUpdater updater = 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 ae096150cd..0c79a7ccd2 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 @@ -294,7 +294,7 @@ public class BlockchainQueries { * @return The number of transactions sent from the given address. */ public long getTransactionCount(final Address address, final Hash blockHash) { - return mapWorldState(blockHash, worldState -> worldState.get(address)) + return getAndMapWorldState(blockHash, worldState -> worldState.get(address)) .map(Account::getNonce) .orElse(0L); } @@ -834,14 +834,16 @@ public class BlockchainQueries { } /** - * Wraps an operation on MutableWorldState with try-with-resources the corresponding block hash + * Wraps an operation on MutableWorldState with try-with-resources the corresponding block hash. + * This method provides access to the worldstate via a mapper function in order to ensure all of + * the uses of the MutableWorldState are subsequently closed, via the try-with-resources block. * * @param return type of the operation on the MutableWorldState * @param blockHash the block hash * @param mapper Function which performs an operation on a MutableWorldState * @return the world state at the block number */ - public Optional mapWorldState( + public Optional getAndMapWorldState( final Hash blockHash, final Function mapper) { return blockchain .getBlockHeader(blockHash) @@ -869,11 +871,11 @@ public class BlockchainQueries { * @param mapper Function which performs an operation on a MutableWorldState returning type U * @return the world state at the block number */ - public Optional mapWorldState( + public Optional getAndMapWorldState( final long blockNumber, final Function mapper) { final Hash blockHash = getBlockHeaderByNumber(blockNumber).map(BlockHeader::getHash).orElse(Hash.EMPTY); - return mapWorldState(blockHash, mapper); + return getAndMapWorldState(blockHash, mapper); } public Optional gasPrice() { @@ -938,7 +940,7 @@ public class BlockchainQueries { final Hash blockHash, final Function getter, final T noAccountValue) { - return mapWorldState( + return getAndMapWorldState( blockHash, worldState -> Optional.ofNullable(worldState.get(address)).map(getter).orElse(noAccountValue)); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProofTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProofTest.java index a9e0bddf2a..a207a24f96 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProofTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProofTest.java @@ -142,7 +142,7 @@ class EthGetProofTest { void errorWhenWorldStateUnavailable() { when(blockchainQueries.headBlockNumber()).thenReturn(14L); - when(blockchainQueries.mapWorldState(any(), any())).thenReturn(Optional.empty()); + when(blockchainQueries.getAndMapWorldState(any(), any())).thenReturn(Optional.empty()); final JsonRpcErrorResponse expectedResponse = new JsonRpcErrorResponse(null, JsonRpcError.WORLD_STATE_UNAVAILABLE); @@ -231,7 +231,7 @@ class EthGetProofTest { .>getArgument(1) .apply(mutableWorldState))) .when(blockchainQueries) - .mapWorldState(any(), any()); + .getAndMapWorldState(any(), any()); return GetProofResult.buildGetProofResult(address, worldStateProof); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/AbstractTrieLogManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/AbstractTrieLogManager.java index e5e220b873..472f713da7 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/AbstractTrieLogManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/AbstractTrieLogManager.java @@ -18,7 +18,7 @@ package org.hyperledger.besu.ethereum.bonsai; import static org.hyperledger.besu.util.Slf4jLambdaHelper.debugLambda; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.ethereum.bonsai.TrieLogManager.CachedLayer; +import org.hyperledger.besu.ethereum.bonsai.TrieLogManager.CachedWorldState; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MutableWorldState; @@ -32,7 +32,7 @@ import org.apache.tuweni.bytes.Bytes32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class AbstractTrieLogManager implements TrieLogManager { +public abstract class AbstractTrieLogManager implements TrieLogManager { private static final Logger LOG = LoggerFactory.getLogger(AbstractTrieLogManager.class); public static final long RETAINED_LAYERS = 512; // at least 256 + typical rollbacks diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/LayeredTrieLogManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/LayeredTrieLogManager.java index 2d69af64f1..83c72516d4 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/LayeredTrieLogManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/LayeredTrieLogManager.java @@ -91,7 +91,7 @@ public class LayeredTrieLogManager }); } - public static class LayeredWorldStateCache implements CachedLayer { + public static class LayeredWorldStateCache implements CachedWorldState { final BonsaiLayeredWorldState layeredWorldState; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/SnapshotTrieLogManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/SnapshotTrieLogManager.java index 6b70c4e3d6..6ca8efe945 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/SnapshotTrieLogManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/SnapshotTrieLogManager.java @@ -84,7 +84,7 @@ public class SnapshotTrieLogManager // no-op. Snapshots are independent and do not need to update 'next' worldstates } - public static class CachedSnapshotWorldState implements CachedLayer { + public static class CachedSnapshotWorldState implements CachedWorldState { final BonsaiSnapshotWorldState snapshot; final TrieLogLayer trieLog; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogManager.java index 4b9550ec80..b107513a9c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogManager.java @@ -43,7 +43,7 @@ public interface TrieLogManager { Optional getTrieLogLayer(final Hash blockHash); - interface CachedLayer { + interface CachedWorldState { long getHeight(); TrieLogLayer getTrieLog(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/GoQuorumKeyValueStorageProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/GoQuorumKeyValueStorageProvider.java index 0f8012f9c7..5339ecb300 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/GoQuorumKeyValueStorageProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/GoQuorumKeyValueStorageProvider.java @@ -41,7 +41,7 @@ public class GoQuorumKeyValueStorageProvider extends KeyValueStorageProvider { worldStatePreimageStorage, privateWorldStatePreimageStorage, segmentIsolationSupported, - false); + SNAPSHOT_ISOLATION_UNSUPPORTED); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java index 94a7e0b325..0d86533091 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java @@ -35,6 +35,9 @@ import java.util.function.Function; public class KeyValueStorageProvider implements StorageProvider { + public static final boolean SEGMENT_ISOLATION_SUPPORTED = true; + public static final boolean SNAPSHOT_ISOLATION_UNSUPPORTED = false; + protected final Function storageCreator; private final KeyValueStorage worldStatePreimageStorage; private final KeyValueStorage privateWorldStatePreimageStorage; @@ -50,7 +53,7 @@ public class KeyValueStorageProvider implements StorageProvider { this.worldStatePreimageStorage = worldStatePreimageStorage; this.privateWorldStatePreimageStorage = null; this.isWorldStateIterable = segmentIsolationSupported; - this.isWorldStateSnappable = false; + this.isWorldStateSnappable = SNAPSHOT_ISOLATION_UNSUPPORTED; } public KeyValueStorageProvider( 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 34fee5950d..3ac19c03d5 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 @@ -168,7 +168,7 @@ public class TransactionSimulator { .orElseThrow( () -> new IllegalArgumentException( - "Public world state not available for block " + header.getNumber())); + "Public world state not available for block " + header.toLogString())); } @Nonnull diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java index 7976249b7f..bccc21da8a 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java @@ -38,8 +38,8 @@ public class InMemoryKeyValueStorageProvider extends KeyValueStorageProvider { segmentIdentifier -> new InMemoryKeyValueStorage(), new InMemoryKeyValueStorage(), new InMemoryKeyValueStorage(), - true, - false); + SEGMENT_ISOLATION_SUPPORTED, + SNAPSHOT_ISOLATION_UNSUPPORTED); } public static MutableBlockchain createInMemoryBlockchain(final Block genesisBlock) { diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/BonsaiSnapshotWorldStateArchiveTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/BonsaiSnapshotWorldStateArchiveTest.java index ebf29718a0..2a2c16fe27 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/BonsaiSnapshotWorldStateArchiveTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/BonsaiSnapshotWorldStateArchiveTest.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * Copyright Hyperledger Besu Contributors. * * 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