Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
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;

Expand Down Expand Up @@ -427,6 +428,15 @@ public Optional<UInt256> getStorageValueBySlotHash(final Address address, final
.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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
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;
Expand Down Expand Up @@ -181,24 +182,37 @@ public Optional<Bytes> getWorldStateBlockHash() {
}

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)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
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;
Expand Down Expand Up @@ -96,7 +97,7 @@ void cloneFromUpdater(final BonsaiWorldStateUpdater source) {

@Override
public Account get(final Address address) {
return super.get(address);
return super.getAccount(address);
}

@Override
Expand Down Expand Up @@ -151,6 +152,12 @@ Map<Address, StorageConsumingMap<BonsaiValue<UInt256>>> getStorageToUpdate() {

@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);
Expand All @@ -162,7 +169,7 @@ protected BonsaiAccount getForMutation(final Address address) {
return null;
}
} else {
return bonsaiValue.getUpdated();
return bonsaiAccountFunction.apply(bonsaiValue);
}
}

Expand Down Expand Up @@ -359,7 +366,15 @@ public Optional<UInt256> getStorageValueBySlotHash(final Address address, final
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
Expand Down