Bugfix potential chain head and worldstate inconsistency (#4862)

* bugfix, ensure setNewHead does not move the chain head forward if the worldstate forward fails

Signed-off-by: garyschulte <garyschulte@gmail.com>
This commit is contained in:
garyschulte
2022-12-23 10:22:18 -08:00
committed by GitHub
parent 3ecb09d721
commit 642d477867
2 changed files with 33 additions and 19 deletions

View File

@@ -33,6 +33,7 @@ import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BackwardSyncContext;
import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BadChainListener;
@@ -521,30 +522,42 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
LOG,
"Forwarding chain head to the block {} saved from a previous newPayload invocation",
newHead::toLogString);
forwardWorldStateTo(newHead);
return blockchain.forwardToBlock(newHead);
if (forwardWorldStateTo(newHead)) {
// move chain head forward:
return blockchain.forwardToBlock(newHead);
} else {
debugLambda(
LOG,
"Failed to move the worldstate forward to hash {}, not moving chain head",
newHead::toLogString);
return false;
}
}
debugLambda(LOG, "New head {} is a chain reorg, rewind chain head to it", newHead::toLogString);
return blockchain.rewindToBlock(newHead.getHash());
}
private void forwardWorldStateTo(final BlockHeader newHead) {
protocolContext
.getWorldStateArchive()
.getMutable(newHead.getStateRoot(), newHead.getHash())
.ifPresentOrElse(
mutableWorldState ->
debugLambda(
LOG,
"World state for state root hash {} and block hash {} persisted successfully",
mutableWorldState::rootHash,
newHead::getHash),
() ->
LOG.error(
"Could not persist world for root hash {} and block hash {}",
newHead.getStateRoot(),
newHead.getHash()));
private boolean forwardWorldStateTo(final BlockHeader newHead) {
Optional<MutableWorldState> newWorldState =
protocolContext
.getWorldStateArchive()
.getMutable(newHead.getStateRoot(), newHead.getHash());
newWorldState.ifPresentOrElse(
mutableWorldState ->
debugLambda(
LOG,
"World state for state root hash {} and block hash {} persisted successfully",
mutableWorldState::rootHash,
newHead::getHash),
() ->
LOG.error(
"Could not persist world for root hash {} and block hash {}",
newHead.getStateRoot(),
newHead.getHash()));
return newWorldState.isPresent();
}
@Override

View File

@@ -39,8 +39,9 @@ import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.rlp.RLP;
public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoCloseable {
// 0x776f726c64526f6f74
public static final byte[] WORLD_ROOT_HASH_KEY = "worldRoot".getBytes(StandardCharsets.UTF_8);
// 0x776f726c64426c6f636b48617368
public static final byte[] WORLD_BLOCK_HASH_KEY =
"worldBlockHash".getBytes(StandardCharsets.UTF_8);