-
Notifications
You must be signed in to change notification settings - Fork 839
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
Make access event keys eip 6800 compatible #7594
Changes from 3 commits
dd4ea70
8558033
755f58c
764ce3a
b4983e6
2d12b65
2e3ba71
e8ed0e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,7 +51,6 @@ | |
import java.util.concurrent.ConcurrentHashMap; | ||
import javax.annotation.Nonnull; | ||
|
||
import kotlin.Pair; | ||
import org.apache.tuweni.bytes.Bytes; | ||
import org.apache.tuweni.bytes.Bytes32; | ||
import org.apache.tuweni.units.bigints.UInt256; | ||
|
@@ -125,8 +124,10 @@ protected Hash internalCalculateRootHash( | |
accountUpdate -> { | ||
final Address accountKey = accountUpdate.getKey(); | ||
// generate account triekeys | ||
final List<Bytes32> accountKeyIds = | ||
new ArrayList<>(trieKeyPreloader.generateAccountKeyIds()); | ||
final List<Bytes32> accountKeyIds = new ArrayList<>(); | ||
if (!accountUpdate.getValue().isUnchanged()) { | ||
accountKeyIds.addAll(trieKeyPreloader.generateAccountKeyIds()); | ||
} | ||
|
||
// generate storage triekeys | ||
final List<Bytes32> storageKeyIds = new ArrayList<>(); | ||
|
@@ -153,7 +154,7 @@ protected Hash internalCalculateRootHash( | |
!codeUpdate.isUnchanged() | ||
&& !(codeIsEmpty(previousCode) && codeIsEmpty(updatedCode)); | ||
if (isCodeUpdateNeeded) { | ||
accountKeyIds.add(Parameters.CODE_SIZE_LEAF_KEY); | ||
accountKeyIds.add(Parameters.CODE_HASH_LEAF_KEY); | ||
codeKeyIds.addAll( | ||
trieKeyPreloader.generateCodeChunkKeyIds( | ||
updatedCode == null ? previousCode : updatedCode)); | ||
|
@@ -166,24 +167,13 @@ protected Hash internalCalculateRootHash( | |
accountKey, accountKeyIds, storageKeyIds, codeKeyIds)); | ||
}); | ||
|
||
for (final Map.Entry<Address, DiffBasedValue<VerkleAccount>> accountUpdate : | ||
worldStateUpdater.getAccountsToUpdate().entrySet()) { | ||
final Address accountKey = accountUpdate.getKey(); | ||
final HasherContext hasherContext = preloadedHashers.get(accountKey); | ||
final VerkleEntryFactory verkleEntryFactory = new VerkleEntryFactory(hasherContext.hasher()); | ||
if (hasherContext.hasStorageTrieKeys()) { | ||
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> storageAccountUpdate = | ||
worldStateUpdater.getStorageToUpdate().get(accountKey); | ||
updateAccountStorageState( | ||
accountKey, stateTrie, maybeStateUpdater, verkleEntryFactory, storageAccountUpdate); | ||
} | ||
if (hasherContext.hasCodeTrieKeys()) { | ||
final DiffBasedValue<Bytes> codeUpdate = | ||
worldStateUpdater.getCodeToUpdate().get(accountKey); | ||
updateCode(accountKey, stateTrie, maybeStateUpdater, verkleEntryFactory, codeUpdate); | ||
} | ||
updateTheAccount( | ||
accountKey, stateTrie, maybeStateUpdater, verkleEntryFactory, accountUpdate.getValue()); | ||
for (final Address accountKey : worldStateUpdater.getAccountsToUpdate().keySet()) { | ||
updateState( | ||
accountKey, | ||
stateTrie, | ||
maybeStateUpdater, | ||
preloadedHashers.get(accountKey), | ||
worldStateUpdater); | ||
} | ||
|
||
LOG.info("start commit "); | ||
|
@@ -206,124 +196,75 @@ protected Hash internalCalculateRootHash( | |
return Hash.wrap(rootHash); | ||
} | ||
|
||
private void updateTheAccount( | ||
private static boolean codeIsEmpty(final Bytes value) { | ||
return value == null || value.isEmpty(); | ||
} | ||
|
||
private void generateAccountValues( | ||
final Address accountKey, | ||
final VerkleTrie stateTrie, | ||
final Optional<VerkleWorldStateKeyValueStorage.Updater> maybeStateUpdater, | ||
final VerkleEntryFactory verkleEntryFactory, | ||
final Optional<VerkleWorldStateKeyValueStorage.Updater> maybeStateUpdater, | ||
final DiffBasedValue<VerkleAccount> accountUpdate) { | ||
|
||
if (!accountUpdate.isUnchanged()) { | ||
final VerkleAccount priorAccount = accountUpdate.getPrior(); | ||
final VerkleAccount updatedAccount = accountUpdate.getUpdated(); | ||
if (updatedAccount == null) { | ||
final Hash addressHash = hashAndSavePreImage(accountKey); | ||
verkleEntryFactory | ||
.generateKeysForAccount(accountKey) | ||
.forEach( | ||
bytes -> { | ||
System.out.println( | ||
"remove " | ||
+ accountKey | ||
+ " " | ||
+ bytes | ||
+ " " | ||
+ accountUpdate.getPrior() | ||
+ " " | ||
+ accountUpdate.getUpdated()); | ||
stateTrie.remove(bytes); | ||
}); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> bonsaiUpdater.removeAccountInfoState(addressHash)); | ||
} else { | ||
final Bytes priorValue = priorAccount == null ? null : priorAccount.serializeAccount(); | ||
final Bytes accountValue = updatedAccount.serializeAccount(); | ||
if (!accountValue.equals(priorValue)) { | ||
verkleEntryFactory | ||
.generateKeyValuesForAccount( | ||
accountKey, | ||
updatedAccount.getNonce(), | ||
updatedAccount.getBalance(), | ||
updatedAccount.getCodeHash()) | ||
.forEach( | ||
(bytes, bytes2) -> { | ||
System.out.println( | ||
"add " | ||
+ accountKey | ||
+ " " | ||
+ bytes | ||
+ " " | ||
+ bytes2 | ||
+ " " | ||
+ updatedAccount.getBalance()); | ||
stateTrie.put(bytes, bytes2); | ||
}); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> | ||
bonsaiUpdater.putAccountInfoState(hashAndSavePreImage(accountKey), accountValue)); | ||
} | ||
} | ||
if (accountUpdate.isUnchanged()) { | ||
return; | ||
} else if (accountUpdate.getUpdated() == null) { | ||
verkleEntryFactory.generateAccountKeysForRemoval(accountKey); | ||
final Hash addressHash = hashAndSavePreImage(accountKey); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> bonsaiUpdater.removeAccountInfoState(addressHash)); | ||
return; | ||
} | ||
final Bytes priorValue = | ||
accountUpdate.getPrior() == null ? null : accountUpdate.getPrior().serializeAccount(); | ||
final Bytes accountValue = accountUpdate.getUpdated().serializeAccount(); | ||
if (!accountValue.equals(priorValue)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we still need this check if we have now https://github.com/hyperledger/besu/pull/7594/files#diff-a8c0068954d44abe33b85a9a6c2b70309adb959255e417350abe54c858574b62R208 ? |
||
verkleEntryFactory.generateAccountKeyValueForUpdate( | ||
accountKey, | ||
accountUpdate.getUpdated().getNonce(), | ||
accountUpdate.getUpdated().getBalance()); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> | ||
bonsaiUpdater.putAccountInfoState(hashAndSavePreImage(accountKey), accountValue)); | ||
} | ||
} | ||
|
||
private void updateCode( | ||
private void generateCodeValues( | ||
final Address accountKey, | ||
final VerkleTrie stateTrie, | ||
final Optional<VerkleWorldStateKeyValueStorage.Updater> maybeStateUpdater, | ||
final VerkleEntryFactory verkleEntryFactory, | ||
final Optional<VerkleWorldStateKeyValueStorage.Updater> maybeStateUpdater, | ||
final DiffBasedValue<Bytes> codeUpdate) { | ||
final Bytes priorCode = codeUpdate.getPrior(); | ||
final Bytes updatedCode = codeUpdate.getUpdated(); | ||
final Hash accountHash = accountKey.addressHash(); | ||
if (updatedCode == null) { | ||
final Hash priorCodeHash = Hash.hash(priorCode); | ||
verkleEntryFactory | ||
.generateKeysForCode(accountKey, priorCode) | ||
.forEach( | ||
bytes -> { | ||
System.out.println("remove code " + bytes); | ||
stateTrie.remove(bytes); | ||
}); | ||
if (codeUpdate == null | ||
|| codeUpdate.isUnchanged() | ||
|| (codeIsEmpty(codeUpdate.getPrior()) && codeIsEmpty(codeUpdate.getUpdated()))) { | ||
return; | ||
} else if (codeUpdate.getUpdated() == null) { | ||
final Hash priorCodeHash = Hash.hash(codeUpdate.getPrior()); | ||
verkleEntryFactory.generateCodeKeysForRemoval(accountKey, codeUpdate.getPrior()); | ||
final Hash accountHash = accountKey.addressHash(); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> bonsaiUpdater.removeCode(accountHash, priorCodeHash)); | ||
return; | ||
} | ||
final Hash accountHash = accountKey.addressHash(); | ||
final Hash codeHash = Hash.hash(codeUpdate.getUpdated()); | ||
verkleEntryFactory.generateCodeKeyValuesForUpdate( | ||
accountKey, codeUpdate.getUpdated(), codeHash); | ||
if (codeUpdate.getUpdated().isEmpty()) { | ||
maybeStateUpdater.ifPresent(bonsaiUpdater -> bonsaiUpdater.removeCode(accountHash, codeHash)); | ||
} else { | ||
if (updatedCode.isEmpty()) { | ||
final Hash codeHash = Hash.hash(updatedCode); | ||
verkleEntryFactory | ||
.generateKeyValuesForCode(accountKey, updatedCode) | ||
.forEach( | ||
(bytes, bytes2) -> { | ||
// System.out.println("add code " + bytes + " " + bytes2); | ||
stateTrie.put(bytes, bytes2); | ||
}); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> bonsaiUpdater.removeCode(accountHash, codeHash)); | ||
} else { | ||
final Hash codeHash = Hash.hash(updatedCode); | ||
verkleEntryFactory | ||
.generateKeyValuesForCode(accountKey, updatedCode) | ||
.forEach( | ||
(bytes, bytes2) -> { | ||
System.out.println("add code " + bytes + " " + bytes2); | ||
stateTrie.put(bytes, bytes2); | ||
}); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> bonsaiUpdater.putCode(accountHash, codeHash, updatedCode)); | ||
} | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> bonsaiUpdater.putCode(accountHash, codeHash, codeUpdate.getUpdated())); | ||
} | ||
} | ||
|
||
private boolean codeIsEmpty(final Bytes value) { | ||
return value == null || value.isEmpty(); | ||
} | ||
|
||
private void updateAccountStorageState( | ||
private void generateStorageValue( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. generateStorageValue-S ? |
||
final Address accountKey, | ||
final VerkleTrie stateTrie, | ||
final Optional<VerkleWorldStateKeyValueStorage.Updater> maybeStateUpdater, | ||
final VerkleEntryFactory verkleEntryFactory, | ||
final Optional<VerkleWorldStateKeyValueStorage.Updater> maybeStateUpdater, | ||
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> storageAccountUpdate) { | ||
|
||
if (storageAccountUpdate == null || storageAccountUpdate.keySet().isEmpty()) { | ||
return; | ||
} | ||
final Hash updatedAddressHash = accountKey.addressHash(); | ||
// for manicured tries and composting, collect branches here (not implemented) | ||
for (final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> storageUpdate : | ||
|
@@ -333,30 +274,13 @@ private void updateAccountStorageState( | |
if (!storageUpdate.getValue().isUnchanged()) { | ||
final UInt256 updatedStorage = storageUpdate.getValue().getUpdated(); | ||
if (updatedStorage == null) { | ||
verkleEntryFactory | ||
.generateKeysForStorage(accountKey, storageUpdate.getKey()) | ||
.forEach( | ||
bytes -> { | ||
System.out.println("remove storage" + bytes); | ||
stateTrie.remove(bytes); | ||
}); | ||
verkleEntryFactory.generateStorageKeysForRemoval(accountKey, storageUpdate.getKey()); | ||
maybeStateUpdater.ifPresent( | ||
diffBasedUpdater -> | ||
diffBasedUpdater.removeStorageValueBySlotHash(updatedAddressHash, slotHash)); | ||
} else { | ||
final Pair<Bytes, Bytes> storage = | ||
verkleEntryFactory.generateKeyValuesForStorage( | ||
accountKey, storageUpdate.getKey(), updatedStorage); | ||
System.out.println("add storage " + storage.getFirst() + " " + storage.getSecond()); | ||
stateTrie | ||
.put(storage.getFirst(), storage.getSecond()) | ||
.ifPresentOrElse( | ||
bytes -> { | ||
storageUpdate.getValue().setPrior(UInt256.fromBytes(bytes)); | ||
}, | ||
() -> { | ||
storageUpdate.getValue().setPrior(null); | ||
}); | ||
verkleEntryFactory.generateStorageKeyValueForUpdate( | ||
accountKey, storageUpdate.getKey(), updatedStorage); | ||
maybeStateUpdater.ifPresent( | ||
bonsaiUpdater -> | ||
bonsaiUpdater.putStorageValueBySlotHash( | ||
|
@@ -366,6 +290,69 @@ private void updateAccountStorageState( | |
} | ||
} | ||
|
||
private void updateState( | ||
final Address accountKey, | ||
final VerkleTrie stateTrie, | ||
final Optional<VerkleWorldStateKeyValueStorage.Updater> maybeStateUpdater, | ||
final HasherContext hasherContext, | ||
final VerkleWorldStateUpdateAccumulator worldStateUpdater) { | ||
|
||
final VerkleEntryFactory verkleEntryFactory = new VerkleEntryFactory(hasherContext.hasher()); | ||
|
||
generateAccountValues( | ||
accountKey, | ||
verkleEntryFactory, | ||
maybeStateUpdater, | ||
worldStateUpdater.getAccountsToUpdate().get(accountKey)); | ||
|
||
generateCodeValues( | ||
accountKey, | ||
verkleEntryFactory, | ||
maybeStateUpdater, | ||
worldStateUpdater.getCodeToUpdate().get(accountKey)); | ||
|
||
generateStorageValue( | ||
accountKey, | ||
verkleEntryFactory, | ||
maybeStateUpdater, | ||
worldStateUpdater.getStorageToUpdate().get(accountKey)); | ||
|
||
verkleEntryFactory | ||
.getKeysForRemoval() | ||
.forEach( | ||
key -> { | ||
System.out.println("remove key " + key); | ||
stateTrie.remove(key); | ||
}); | ||
verkleEntryFactory | ||
.getNonStorageKeyValuesForUpdate() | ||
.forEach( | ||
(key, value) -> { | ||
System.out.println("add key " + key + " leaf value " + value); | ||
stateTrie.put(key, value); | ||
}); | ||
verkleEntryFactory | ||
.getStorageKeyValuesForUpdate() | ||
.forEach( | ||
(storageSlotKey, pair) -> { | ||
var storageAccountUpdate = worldStateUpdater.getStorageToUpdate().get(accountKey); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this one is still needed as we already checked here https://github.com/hyperledger/besu/pull/7594/files#diff-a8c0068954d44abe33b85a9a6c2b70309adb959255e417350abe54c858574b62R267 but maybe I missing something ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I understand. So the link you posted is when the key values are generated. Here we commit them to the trie in one go. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was talking about this check (==null) when we are generating the key we already check if the collection is empty, so imo when we enter this loop we cannot have a null There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes you're right that we if there are elements we can't have null. I added it based on a defensive approach since we don't know how the programmer will generate keys and values. What if it's based on another object? |
||
if (storageAccountUpdate == null) { | ||
return; | ||
} | ||
System.out.println( | ||
"add storage key " + pair.getFirst() + " value " + pair.getSecond()); | ||
Optional<DiffBasedValue<UInt256>> storageUpdate = | ||
Optional.ofNullable(storageAccountUpdate.get(storageSlotKey)); | ||
stateTrie | ||
.put(pair.getFirst(), pair.getSecond()) | ||
.ifPresentOrElse( | ||
bytes -> | ||
storageUpdate.ifPresent( | ||
storage -> storage.setPrior(UInt256.fromBytes(bytes))), | ||
() -> storageUpdate.ifPresent(storage -> storage.setPrior(null))); | ||
}); | ||
} | ||
|
||
@Override | ||
public MutableWorldState freeze() { | ||
this.worldStateConfig.setFrozen(true); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we cannot use if, else if , else if ? I think it will be better