From f1c292142178e58178b9253c2ea944521ebbefcd Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Wed, 24 Jan 2024 09:55:32 +0100 Subject: [PATCH] use reference tests to verify trielog generation (#6415) use reference tests to validate trielog generation. Like that we will validate besu trielog generation for all of the tests we have in the references tests suite for past and future EIPs --------- Signed-off-by: Karim Taam --- .circleci/config.yml | 2 +- .../ethereum/trie/bonsai/BonsaiValue.java | 15 ++ .../bonsai/worldview/BonsaiWorldState.java | 6 +- .../BonsaiWorldStateUpdateAccumulator.java | 8 +- .../backwardsync/BackwardSyncContextTest.java | 4 +- .../backwardsync/ForwardSyncStepTest.java | 4 +- .../BonsaiReferenceTestUpdateAccumulator.java | 28 ++++ .../BonsaiReferenceTestWorldState.java | 137 +++++++++++++++++- ...ava => ForestReferenceTestWorldState.java} | 24 ++- .../ReferenceTestWorldState.java | 3 + .../vm/GeneralStateReferenceTestTools.java | 4 +- 11 files changed, 214 insertions(+), 21 deletions(-) rename ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/{DefaultReferenceTestWorldState.java => ForestReferenceTestWorldState.java} (67%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 065a0280d0..0e84ab22aa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -204,7 +204,7 @@ jobs: at: ~/project - run: name: ReferenceTests - no_output_timeout: 30m + no_output_timeout: 40m command: | git submodule update --init --recursive ./gradlew --no-daemon referenceTest diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/BonsaiValue.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/BonsaiValue.java index c4f8ab0efd..c99da3fe24 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/BonsaiValue.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/BonsaiValue.java @@ -42,6 +42,17 @@ public class BonsaiValue implements TrieLog.LogTuple { this.clearedAtLeastOnce = lastStepCleared; } + public BonsaiValue( + final T prior, + final T updated, + final boolean lastStepCleared, + final boolean clearedAtLeastOnce) { + this.prior = prior; + this.updated = updated; + this.lastStepCleared = lastStepCleared; + this.clearedAtLeastOnce = clearedAtLeastOnce; + } + @Override public T getPrior() { return prior; @@ -117,4 +128,8 @@ public class BonsaiValue implements TrieLog.LogTuple { .append(lastStepCleared) .toHashCode(); } + + public BonsaiValue copy() { + return new BonsaiValue(prior, updated, lastStepCleared, clearedAtLeastOnce); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java index 4544a1c1de..8abcd442cf 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java @@ -119,12 +119,12 @@ public class BonsaiWorldState } /** - * Having a protected method to override the accumulator solves the chicken-egg problem of needing - * a worldstate reference (this) when construction the Accumulator. + * Override the accumulator solves the chicken-egg problem of needing a worldstate reference + * (this) when construction the Accumulator. * * @param accumulator accumulator to use. */ - protected void setAccumulator(final BonsaiWorldStateUpdateAccumulator accumulator) { + public void setAccumulator(final BonsaiWorldStateUpdateAccumulator accumulator) { this.accumulator = accumulator; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java index 9f0dd07d3b..d73c272829 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java @@ -60,13 +60,13 @@ public class BonsaiWorldStateUpdateAccumulator implements BonsaiWorldView, TrieLogAccumulator { private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateUpdateAccumulator.class); - private final Consumer> accountPreloader; - private final Consumer storagePreloader; + protected final Consumer> accountPreloader; + protected final Consumer storagePreloader; private final AccountConsumingMap> accountsToUpdate; private final Map> codeToUpdate = new ConcurrentHashMap<>(); private final Set
storageToClear = Collections.synchronizedSet(new HashSet<>()); - private final EvmConfiguration evmConfiguration; + protected final EvmConfiguration evmConfiguration; // storage sub mapped by _hashed_ key. This is because in self_destruct calls we need to // enumerate the old storage and delete it. Those are trie stored by hashed key by spec and the @@ -74,7 +74,7 @@ public class BonsaiWorldStateUpdateAccumulator private final Map>> storageToUpdate = new ConcurrentHashMap<>(); - private boolean isAccumulatorStateChanged; + protected boolean isAccumulatorStateChanged; public BonsaiWorldStateUpdateAccumulator( final BonsaiWorldView world, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java index 3187f55ef9..27c931bb78 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java @@ -48,7 +48,7 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; -import org.hyperledger.besu.ethereum.referencetests.DefaultReferenceTestWorldState; +import org.hyperledger.besu.ethereum.referencetests.ForestReferenceTestWorldState; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; @@ -154,7 +154,7 @@ public class BackwardSyncContextTest { new BlockProcessingOutputs( // use forest-based worldstate since it does not require // blockheader stateroot to match actual worldstate root - DefaultReferenceTestWorldState.create(Collections.emptyMap()), + ForestReferenceTestWorldState.create(Collections.emptyMap()), blockDataGenerator.receipts(block)))); }); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java index e38a9647b7..e1848493dd 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java @@ -38,7 +38,7 @@ import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.ethereum.referencetests.DefaultReferenceTestWorldState; +import org.hyperledger.besu.ethereum.referencetests.ForestReferenceTestWorldState; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; import java.nio.charset.StandardCharsets; @@ -138,7 +138,7 @@ public class ForwardSyncStepTest { return new BlockProcessingResult( Optional.of( new BlockProcessingOutputs( - DefaultReferenceTestWorldState.create(Collections.emptyMap()), + ForestReferenceTestWorldState.create(Collections.emptyMap()), blockDataGenerator.receipts(block)))); }); } diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestUpdateAccumulator.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestUpdateAccumulator.java index b56053f54a..8c1bd51552 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestUpdateAccumulator.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestUpdateAccumulator.java @@ -23,7 +23,10 @@ import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdat import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.units.bigints.UInt256; public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdateAccumulator { private final BonsaiPreImageProxy preImageProxy; @@ -43,4 +46,29 @@ public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdate // by default do not save hash preImages return preImageProxy.hashAndSavePreImage(bytes); } + + public BonsaiReferenceTestUpdateAccumulator createDetachedAccumulator() { + final BonsaiReferenceTestUpdateAccumulator copy = + new BonsaiReferenceTestUpdateAccumulator( + wrappedWorldView(), + accountPreloader, + storagePreloader, + preImageProxy, + evmConfiguration); + getAccountsToUpdate().forEach((k, v) -> copy.getAccountsToUpdate().put(k, v.copy())); + getCodeToUpdate().forEach((k, v) -> copy.getCodeToUpdate().put(k, v.copy())); + copy.getStorageToClear().addAll(getStorageToClear()); + getStorageToUpdate() + .forEach( + (k, v) -> { + StorageConsumingMap> newMap = + new StorageConsumingMap<>(k, new ConcurrentHashMap<>(), v.getConsumer()); + v.forEach((key, value) -> newMap.put(key, value.copy())); + copy.getStorageToUpdate().put(k, newMap); + }); + copy.updatedAccounts.putAll(updatedAccounts); + copy.deletedAccounts.addAll(deletedAccounts); + copy.isAccumulatorStateChanged = true; + return copy; + } } diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java index 91c768a55c..e0a49fbf64 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java @@ -23,19 +23,25 @@ import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager import org.hyperledger.besu.ethereum.trie.bonsai.cache.NoOpCachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy; import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage; -import org.hyperledger.besu.ethereum.trie.bonsai.trielog.NoOpTrieLogManager; +import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage; +import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogAddedEvent; import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; +import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.trielogs.TrieLog; import java.util.Map; +import java.util.Optional; import java.util.stream.Stream; import com.fasterxml.jackson.annotation.JsonCreator; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -98,6 +104,99 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState // The test harness validates the root hash, no need to validate in-line for reference test } + @Override + public void processExtraStateStorageFormatValidation(final BlockHeader blockHeader) { + if (blockHeader != null) { + final Hash parentStateRoot = getWorldStateRootHash(); + final BonsaiReferenceTestUpdateAccumulator originalUpdater = + ((BonsaiReferenceTestUpdateAccumulator) updater()).createDetachedAccumulator(); + + // validate trielog generation with persisted state + validateStateRolling(parentStateRoot, originalUpdater, blockHeader, false); + // validate trielog generation with frozen state + validateStateRolling(parentStateRoot, originalUpdater, blockHeader, true); + } + } + + /** + * TrieLog is an important part of Bonsai, so it's important to verify the generation of the + * TrieLog by performing rollbacks and rollforwards. + * + * @param blockHeader header of the block to import + */ + private void validateStateRolling( + final Hash parentStateRoot, + final BonsaiReferenceTestUpdateAccumulator originalUpdater, + final BlockHeader blockHeader, + final boolean isFrozenState) { + // With Bonsai, a TrieLog is generated when the state is persisted. Therefore, we generate the + // TrieLog by triggering a state persist in order to closely match the real case scenario. + generateTrieLogFromState(blockHeader, originalUpdater, isFrozenState); + final TrieLog trieLogFromFrozenState = + trieLogManager + .getTrieLogLayer(blockHeader.getBlockHash()) + .orElseThrow(() -> new RuntimeException("trielog not found during test")); + // trying rollback rollfoward with frozen state + validateTrieLog(parentStateRoot, blockHeader, trieLogFromFrozenState); + } + + private void validateTrieLog( + final Hash parentStateRoot, final BlockHeader blockHeader, final TrieLog trieLog) { + + try (var bonsaiWorldState = createBonsaiWorldState(false)) { + BonsaiWorldStateUpdateAccumulator updaterForState = + (BonsaiWorldStateUpdateAccumulator) bonsaiWorldState.updater(); + updaterForState.rollForward(trieLog); + updaterForState.commit(); + bonsaiWorldState.persist(blockHeader); + Hash generatedRootHash = bonsaiWorldState.rootHash(); + if (!bonsaiWorldState.rootHash().equals(blockHeader.getStateRoot())) { + throw new RuntimeException( + "state root becomes invalid following a rollForward %s != %s" + .formatted(blockHeader.getStateRoot(), generatedRootHash)); + } + + updaterForState = (BonsaiWorldStateUpdateAccumulator) bonsaiWorldState.updater(); + updaterForState.rollBack(trieLog); + updaterForState.commit(); + bonsaiWorldState.persist(null); + generatedRootHash = bonsaiWorldState.rootHash(); + if (!bonsaiWorldState.rootHash().equals(parentStateRoot)) { + throw new RuntimeException( + "state root becomes invalid following a rollBackward %s != %s" + .formatted(parentStateRoot, generatedRootHash)); + } + } + } + + private void generateTrieLogFromState( + final BlockHeader blockHeader, + final BonsaiReferenceTestUpdateAccumulator originalUpdater, + final boolean isFrozen) { + // generate trielog + BonsaiReferenceTestUpdateAccumulator updaterForState = + originalUpdater.createDetachedAccumulator(); + try (var bonsaiWorldState = createBonsaiWorldState(isFrozen)) { + bonsaiWorldState.setAccumulator(updaterForState); + updaterForState.commit(); + bonsaiWorldState.persist(blockHeader); + } + } + + private BonsaiWorldState createBonsaiWorldState(final boolean isFrozen) { + BonsaiWorldState bonsaiWorldState = + new BonsaiWorldState( + new BonsaiWorldStateLayerStorage(worldStateStorage), + cachedMerkleTrieLoader, + cachedWorldStorageManager, + trieLogManager, + evmConfiguration); + if (isFrozen) { + bonsaiWorldState.freeze(); // freeze state + } + return bonsaiWorldState; + } + @JsonCreator public static BonsaiReferenceTestWorldState create( final Map accounts) { @@ -110,7 +209,7 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState final EvmConfiguration evmConfiguration) { final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem(); final CachedMerkleTrieLoader cachedMerkleTrieLoader = new CachedMerkleTrieLoader(metricsSystem); - final TrieLogManager trieLogManager = new NoOpTrieLogManager(); + final TrieLogManager trieLogManager = new ReferenceTestsInMemoryTrieLogManager(); final BonsaiPreImageProxy preImageProxy = new BonsaiPreImageProxy.BonsaiReferenceTestPreImageProxy(); @@ -149,6 +248,40 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState return this.refTestStorage.streamAccounts(this, startKeyHash, limit); } + static class ReferenceTestsInMemoryTrieLogManager extends TrieLogManager { + + private final Cache trieLogCache = + CacheBuilder.newBuilder().maximumSize(5).build(); + + public ReferenceTestsInMemoryTrieLogManager() { + super(null, null, 0, null); + } + + @Override + public synchronized void saveTrieLog( + final BonsaiWorldStateUpdateAccumulator localUpdater, + final Hash forWorldStateRootHash, + final BlockHeader forBlockHeader, + final BonsaiWorldState forWorldState) { + // notify trie log added observers, synchronously + TrieLog trieLog = trieLogFactory.create(localUpdater, forBlockHeader); + trieLogCache.put(forBlockHeader.getHash(), trieLogFactory.serialize(trieLog)); + trieLogObservers.forEach(o -> o.onTrieLogAdded(new TrieLogAddedEvent(trieLog))); + } + + @Override + public long getMaxLayersToLoad() { + return 0; + } + + @Override + public Optional getTrieLogLayer(final Hash blockHash) { + final byte[] trielog = trieLogCache.getIfPresent(blockHash); + trieLogCache.invalidate(blockHash); // remove trielog from the cache + return Optional.ofNullable(trieLogFactory.deserialize(trielog)); + } + } + @Override protected Hash hashAndSavePreImage(final Bytes value) { // by default do not save has preImages diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/DefaultReferenceTestWorldState.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ForestReferenceTestWorldState.java similarity index 67% rename from ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/DefaultReferenceTestWorldState.java rename to ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ForestReferenceTestWorldState.java index d9ed862676..9ab158a554 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/DefaultReferenceTestWorldState.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ForestReferenceTestWorldState.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.referencetests; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState; @@ -27,28 +28,41 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; -public class DefaultReferenceTestWorldState extends ForestMutableWorldState +public class ForestReferenceTestWorldState extends ForestMutableWorldState implements ReferenceTestWorldState { - DefaultReferenceTestWorldState() { + ForestReferenceTestWorldState() { super( new ForestWorldStateKeyValueStorage(new InMemoryKeyValueStorage()), new WorldStatePreimageKeyValueStorage(new InMemoryKeyValueStorage()), EvmConfiguration.DEFAULT); } - public DefaultReferenceTestWorldState(final WorldState worldState) { + public ForestReferenceTestWorldState(final WorldState worldState) { super(worldState, EvmConfiguration.DEFAULT); } @Override public ReferenceTestWorldState copy() { - return new DefaultReferenceTestWorldState(this); + return new ForestReferenceTestWorldState(this); + } + + /** + * Executes additional validation checks that are specific to the storage format. + * + *

Depending on the storage format (e.g., Bonsai, etc.), this method performs additional checks + * to validate the state. This could include validating the TrieLog and rolling for Bonsai, or + * potentially other checks for other modes. This method is intended to be used before the state + * root has been validated, to ensure the integrity of other aspects of the state. + */ + @Override + public void processExtraStateStorageFormatValidation(final BlockHeader blockHeader) { + // nothing more to verify with forest } @JsonCreator public static ReferenceTestWorldState create(final Map accounts) { - final ReferenceTestWorldState worldState = new DefaultReferenceTestWorldState(); + final ReferenceTestWorldState worldState = new ForestReferenceTestWorldState(); final WorldUpdater updater = worldState.updater(); for (final Map.Entry entry : accounts.entrySet()) { diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java index 3d4db1edaa..ae446a7607 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.referencetests; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -90,6 +91,8 @@ public interface ReferenceTestWorldState extends MutableWorldState { ReferenceTestWorldState copy(); + void processExtraStateStorageFormatValidation(final BlockHeader blockHeader); + @JsonCreator static ReferenceTestWorldState create(final Map accounts) { // delegate to a Bonsai reference test world state: diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java index e0b0c7332e..5314ff5cc8 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java @@ -28,7 +28,6 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; -import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -151,7 +150,7 @@ public class GeneralStateReferenceTestTools { return; } - final MutableWorldState worldState = initialWorldState.copy(); + final ReferenceTestWorldState worldState = initialWorldState.copy(); // Several of the GeneralStateTests check if the transaction could potentially // consume more gas than is left for the block it's attempted to be included in. // This check is performed within the `BlockImporter` rather than inside the @@ -193,6 +192,7 @@ public class GeneralStateReferenceTestTools { worldStateUpdater.deleteAccount(coinbase.getAddress()); } worldStateUpdater.commit(); + worldState.processExtraStateStorageFormatValidation(blockHeader); worldState.persist(blockHeader); // Check the world state root hash.