From a6552df9c80ea77b91b156bca093cf49b910b605 Mon Sep 17 00:00:00 2001 From: Matthew Whitehead Date: Tue, 8 Oct 2024 14:36:21 +0100 Subject: [PATCH] Multiple deletes of the same address in a single block causes Bonsai to fail the block Signed-off-by: Matthew Whitehead --- .../bonsai/worldview/BonsaiWorldState.java | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java index d00afda9ee3..18ad3b8d49d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java @@ -57,11 +57,15 @@ import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.rlp.RLP; import org.apache.tuweni.units.bigints.UInt256; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BonsaiWorldState extends DiffBasedWorldState { protected final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader; + private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldState.class); + public BonsaiWorldState( final BonsaiWorldStateProvider archive, final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, @@ -337,28 +341,34 @@ private void clearStorage( try { final StorageConsumingMap> storageToDelete = worldStateUpdater.getStorageToUpdate().get(address); - Map entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); - while (!entriesToDelete.isEmpty()) { - entriesToDelete.forEach( - (k, v) -> { - final StorageSlotKey storageSlotKey = - new StorageSlotKey(Hash.wrap(k), Optional.empty()); - final UInt256 slotValue = UInt256.fromBytes(Bytes32.leftPad(RLP.decodeValue(v))); - maybeStateUpdater.ifPresent( - bonsaiUpdater -> - bonsaiUpdater.removeStorageValueBySlotHash( - address.addressHash(), storageSlotKey.getSlotHash())); - storageToDelete - .computeIfAbsent( - storageSlotKey, key -> new DiffBasedValue<>(slotValue, null, true)) - .setPrior(slotValue); - }); - entriesToDelete.keySet().forEach(storageTrie::remove); - if (entriesToDelete.size() == 256) { - entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); - } else { - break; + if (storageToDelete != null) { + Map entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); + while (!entriesToDelete.isEmpty()) { + entriesToDelete.forEach( + (k, v) -> { + final StorageSlotKey storageSlotKey = + new StorageSlotKey(Hash.wrap(k), Optional.empty()); + final UInt256 slotValue = UInt256.fromBytes(Bytes32.leftPad(RLP.decodeValue(v))); + maybeStateUpdater.ifPresent( + bonsaiUpdater -> + bonsaiUpdater.removeStorageValueBySlotHash( + address.addressHash(), storageSlotKey.getSlotHash())); + storageToDelete + .computeIfAbsent( + storageSlotKey, key -> new DiffBasedValue<>(slotValue, null, true)) + .setPrior(slotValue); + }); + entriesToDelete.keySet().forEach(storageTrie::remove); + if (entriesToDelete.size() == 256) { + entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); + } else { + break; + } } + } else { + LOG.warn( + "No storage entries to delete for deleted address {}. Address storage may already have been deleted in this block.", + address); } } catch (MerkleTrieException e) { // need to throw to trigger the heal