Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Layered World State issue #5076

Merged
merged 14 commits into from
Feb 13, 2023
Merged
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ tests are updated to use EC private keys instead of RSA keys.

### Bug Fixes
- Mitigation fix for stale bonsai code storage leading to log rolling issues on contract recreates [#4906](https://github.com/hyperledger/besu/pull/4906)

- Ensure latest cached layered worldstate is subscribed to storage, fix problem with RPC calls using 'latest' [#5076](https://github.com/hyperledger/besu/pull/5076)

## 23.1.0-RC1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,12 +855,19 @@ public <U> Optional<U> getAndMapWorldState(
.getBlockHeader(blockHash)
.flatMap(
blockHeader -> {
try (var ws =
try (final var worldState =
worldStateArchive
.getMutable(blockHeader.getStateRoot(), blockHeader.getHash(), false)
.map(
ws -> {
if (!ws.isPersistable()) {
return ws.copy();
}
return ws;
})
.orElse(null)) {
if (ws != null) {
return Optional.ofNullable(mapper.apply(ws));
if (worldState != null) {
return Optional.ofNullable(mapper.apply(worldState));
}
} catch (Exception ex) {
LOG.error("failed worldstate query for " + blockHash.toShortHexString(), ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,17 @@ protected abstract void addCachedLayer(

@VisibleForTesting
TrieLogLayer prepareTrieLog(
final BlockHeader blockHeader,
final Hash worldStateRootHash,
final BlockHeader forBlockHeader,
final Hash forWorldStateRootHash,
final BonsaiWorldStateUpdater localUpdater,
final BonsaiWorldStateArchive worldStateArchive,
final BonsaiPersistedWorldState forWorldState) {
debugLambda(LOG, "Adding layered world state for {}", blockHeader::toLogString);
final TrieLogLayer trieLog = localUpdater.generateTrieLog(blockHeader.getBlockHash());
debugLambda(LOG, "Adding layered world state for {}", forBlockHeader::toLogString);
final TrieLogLayer trieLog = localUpdater.generateTrieLog(forBlockHeader.getBlockHash());
trieLog.freeze();
addCachedLayer(blockHeader, worldStateRootHash, trieLog, worldStateArchive, forWorldState);
scrubCachedLayers(blockHeader.getNumber());
addCachedLayer(
forBlockHeader, forWorldStateRootHash, trieLog, worldStateArchive, forWorldState);
scrubCachedLayers(forBlockHeader.getNumber());
return trieLog;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@
import org.apache.tuweni.units.bigints.UInt256;

/** A World State backed first by trie log layer and then by another world state. */
public class BonsaiLayeredWorldState implements MutableWorldState, BonsaiWorldView, WorldState {
private Optional<BonsaiWorldView> nextWorldView;
public class BonsaiLayeredWorldState
implements MutableWorldState,
BonsaiWorldView,
WorldState,
BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
private Optional<BonsaiWorldView> nextWorldView = Optional.empty();
private Optional<Long> newtWorldViewSubscribeId = Optional.empty();
protected final long height;
protected final TrieLogLayer trieLog;
private final Hash worldStateRootHash;
Expand All @@ -58,7 +63,7 @@ public class BonsaiLayeredWorldState implements MutableWorldState, BonsaiWorldVi
final TrieLogLayer trieLog) {
this.blockchain = blockchain;
this.archive = archive;
this.nextWorldView = nextWorldView;
this.setNextWorldView(nextWorldView);
this.height = height;
this.worldStateRootHash = worldStateRootHash;
this.trieLog = trieLog;
Expand All @@ -76,7 +81,34 @@ public Optional<BonsaiWorldView> getNextWorldView() {
}

public void setNextWorldView(final Optional<BonsaiWorldView> nextWorldView) {
maybeUnSubscribe(); // unsubscribe the old view
this.nextWorldView = nextWorldView;
maybeSubscribe(); // subscribe the next view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

private void maybeSubscribe() {
nextWorldView
.filter(BonsaiPersistedWorldState.class::isInstance)
.map(BonsaiPersistedWorldState.class::cast)
.ifPresent(
worldState -> {
newtWorldViewSubscribeId = Optional.of(worldState.worldStateStorage.subscribe(this));
});
}

private void maybeUnSubscribe() {
nextWorldView
.filter(BonsaiPersistedWorldState.class::isInstance)
.map(BonsaiPersistedWorldState.class::cast)
.ifPresent(
worldState -> {
newtWorldViewSubscribeId.ifPresent(worldState.worldStateStorage::unSubscribe);
});
}

@Override
public void close() throws Exception {
maybeUnSubscribe();
}

public TrieLogLayer getTrieLog() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,11 @@ private TransactionAddedStatus addTransaction(
LOG,
"Transaction {} not added because nonce too far in the future for sender {}",
transaction::toTraceLog,
maybeSenderAccount::toString);
() ->
maybeSenderAccount
.map(Account::getAddress)
.map(Address::toString)
.orElse("unknown"));
return NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER;
}

Expand Down