diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleAccount.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleAccount.java index 692dd19f731..bd7170dd71e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleAccount.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleAccount.java @@ -37,6 +37,7 @@ public class VerkleAccount extends DiffBasedAccount { private Hash storageRoot; // TODO REMOVE AS USELESS + private int hashCode; public VerkleAccount( final DiffBasedWorldView context, @@ -180,4 +181,33 @@ public static void assertCloseEnoughForDiffing( public boolean isStorageEmpty() { return true; // TODO need to find a way to manage that with verkle } + + @Override + public boolean equals(final Object other) { + if (this == other) { + return true; + } else if (!(other instanceof VerkleAccount)) { + return false; + } + VerkleAccount otherVerkleAccount = (VerkleAccount) other; + return Objects.equals(this.address, otherVerkleAccount.address) + && this.nonce == otherVerkleAccount.nonce + && Objects.equals(this.balance, otherVerkleAccount.balance) + && Objects.equals(this.codeHash, otherVerkleAccount.codeHash); + } + + @Override + public int hashCode() { + if (!immutable) { + return computeHashCode(); + } + if (hashCode == 0) { + hashCode = computeHashCode(); + } + return hashCode; + } + + private int computeHashCode() { + return Objects.hash(address, nonce, balance, codeHash); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java index 286a1f621d1..a5e8dd3b244 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java @@ -44,6 +44,7 @@ import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -119,17 +120,19 @@ protected Hash internalCalculateRootHash( final Map preloadedHashers = new ConcurrentHashMap<>(); - worldStateUpdater.getAccountsToUpdate().entrySet().parallelStream() + final Set
addressesToPersist = getAddressesToPersist(worldStateUpdater); + addressesToPersist.parallelStream() .forEach( - accountUpdate -> { - final Address accountKey = accountUpdate.getKey(); - // generate account triekeys + accountKey -> { + final DiffBasedValue accountUpdate = + worldStateUpdater.getAccountsToUpdate().get(accountKey); + // generate triekeys for account final List accountKeyIds = new ArrayList<>(); - if (!accountUpdate.getValue().isUnchanged()) { + if (accountUpdate != null && !accountUpdate.isUnchanged()) { accountKeyIds.add(trieKeyPreloader.generateAccountKeyId()); } - // generate storage triekeys + // generate triekeys for storage final List storageKeyIds = new ArrayList<>(); final StorageConsumingMap> storageAccountUpdate = worldStateUpdater.getStorageToUpdate().get(accountKey); @@ -142,7 +145,7 @@ protected Hash internalCalculateRootHash( } } - // generate code triekeys + // generate triekeys for code final List codeKeyIds = new ArrayList<>(); final DiffBasedValue codeUpdate = worldStateUpdater.getCodeToUpdate().get(accountKey); @@ -167,7 +170,7 @@ protected Hash internalCalculateRootHash( accountKey, accountKeyIds, storageKeyIds, codeKeyIds)); }); - for (final Address accountKey : worldStateUpdater.getAccountsToUpdate().keySet()) { + for (final Address accountKey : addressesToPersist) { updateState( accountKey, stateTrie, @@ -205,7 +208,7 @@ private void generateAccountValues( final VerkleEntryFactory verkleEntryFactory, final Optional maybeStateUpdater, final DiffBasedValue accountUpdate) { - if (accountUpdate.isUnchanged()) { + if (accountUpdate == null || accountUpdate.isUnchanged()) { return; } if (accountUpdate.getUpdated() == null) { @@ -355,6 +358,16 @@ private void updateState( }); } + public Set
getAddressesToPersist( + final DiffBasedWorldStateUpdateAccumulator accumulator) { + Set
mergedAddresses = + new HashSet<>(accumulator.getAccountsToUpdate().keySet()); // accountsToUpdate + mergedAddresses.addAll(accumulator.getCodeToUpdate().keySet()); // codeToUpdate + mergedAddresses.addAll(accumulator.getStorageToClear()); // storageToClear + mergedAddresses.addAll(accumulator.getStorageToUpdate().keySet()); // storageToUpdate + return mergedAddresses; + } + @Override public MutableWorldState freeze() { this.worldStateConfig.setFrozen(true);