use the updater cache to get an account during block processing (#4897)

Use WorldStateBonsaiUpdater accounts cache each time we try to get an account from storage. Currently, we use this cache only in some code paths.

Signed-off-by: Karim TAAM <karim.t2am@gmail.com>
Co-authored-by: Ameziane H <ameziane.hamlat@consensys.net>
pull/4969/head
matkt 2 years ago committed by GitHub
parent 679ea46e6f
commit 5627ee03fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java
  3. 26
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateKeyValueStorage.java
  4. 21
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java

@ -6,6 +6,7 @@
### Additions and Improvements
- Added option to evm CLI tool to allow code execution at specific forks [#4913](https://github.com/hyperledger/besu/pull/4913)
- Improve get account performance by using the world state updater cache [#4897](https://github.com/hyperledger/besu/pull/4897)
### Bug Fixes

@ -35,6 +35,7 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
@ -427,6 +428,15 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld
.map(UInt256::fromBytes);
}
public Optional<UInt256> getStorageValueBySlotHash(
final Supplier<Optional<Hash>> storageRootSupplier,
final Address address,
final Hash slotHash) {
return worldStateStorage
.getStorageValueBySlotHash(storageRootSupplier, Hash.hash(address), slotHash)
.map(UInt256::fromBytes);
}
@Override
public UInt256 getPriorStorageValue(final Address address, final UInt256 storageKey) {
return getStorageValue(address, storageKey);

@ -33,6 +33,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
@ -181,24 +182,37 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoC
}
public Optional<Bytes> getStorageValueBySlotHash(final Hash accountHash, final Hash slotHash) {
return getStorageValueBySlotHash(
() ->
getAccount(accountHash)
.map(
b ->
StateTrieAccountValue.readFrom(
org.hyperledger.besu.ethereum.rlp.RLP.input(b))
.getStorageRoot()),
accountHash,
slotHash);
}
public Optional<Bytes> getStorageValueBySlotHash(
final Supplier<Optional<Hash>> storageRootSupplier,
final Hash accountHash,
final Hash slotHash) {
Optional<Bytes> response =
storageStorage
.get(Bytes.concatenate(accountHash, slotHash).toArrayUnsafe())
.map(Bytes::wrap);
if (response.isEmpty()) {
final Optional<Bytes> account = getAccount(accountHash);
final Optional<Hash> storageRoot = storageRootSupplier.get();
final Optional<Bytes> worldStateRootHash = getWorldStateRootHash();
if (account.isPresent() && worldStateRootHash.isPresent()) {
final StateTrieAccountValue accountValue =
StateTrieAccountValue.readFrom(
org.hyperledger.besu.ethereum.rlp.RLP.input(account.get()));
if (storageRoot.isPresent() && worldStateRootHash.isPresent()) {
response =
new StoredMerklePatriciaTrie<>(
new StoredNodeFactory<>(
(location, hash) -> getAccountStorageTrieNode(accountHash, location, hash),
Function.identity(),
Function.identity()),
accountValue.getStorageRoot())
storageRoot.get())
.get(slotHash)
.map(bytes -> Bytes32.leftPad(RLP.decodeValue(bytes)));
}

@ -37,6 +37,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import com.google.common.collect.ForwardingMap;
import org.apache.tuweni.bytes.Bytes;
@ -96,7 +97,7 @@ public class BonsaiWorldStateUpdater extends AbstractWorldUpdater<BonsaiWorldVie
@Override
public Account get(final Address address) {
return super.get(address);
return super.getAccount(address);
}
@Override
@ -151,6 +152,12 @@ public class BonsaiWorldStateUpdater extends AbstractWorldUpdater<BonsaiWorldVie
@Override
protected BonsaiAccount getForMutation(final Address address) {
return loadAccount(address, BonsaiValue::getUpdated);
}
protected BonsaiAccount loadAccount(
final Address address,
final Function<BonsaiValue<BonsaiAccount>, BonsaiAccount> bonsaiAccountFunction) {
final BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address);
if (bonsaiValue == null) {
final Account account = wrappedWorldView().get(address);
@ -162,7 +169,7 @@ public class BonsaiWorldStateUpdater extends AbstractWorldUpdater<BonsaiWorldVie
return null;
}
} else {
return bonsaiValue.getUpdated();
return bonsaiAccountFunction.apply(bonsaiValue);
}
}
@ -359,7 +366,15 @@ public class BonsaiWorldStateUpdater extends AbstractWorldUpdater<BonsaiWorldVie
return Optional.empty();
} else {
final Optional<UInt256> valueUInt =
wrappedWorldView().getStorageValueBySlotHash(address, slotHash);
(wrappedWorldView() instanceof BonsaiPersistedWorldState)
? ((BonsaiPersistedWorldState) wrappedWorldView())
.getStorageValueBySlotHash(
() ->
Optional.ofNullable(loadAccount(address, BonsaiValue::getPrior))
.map(BonsaiAccount::getStorageRoot),
address,
slotHash)
: wrappedWorldView().getStorageValueBySlotHash(address, slotHash);
valueUInt.ifPresentOrElse(
v ->
storageToUpdate

Loading…
Cancel
Save