Fix verkle state root calculation for BASIC_DATA_LEAF and CODE_HASH_LEAF (#7681)

* Fix storing BASIC_DATA_LEAF values in Big endian order

Signed-off-by: Luis Pinto <luis.pinto@consensys.net>

* Write code hash on account creation in all cases

Signed-off-by: Luis Pinto <luis.pinto@consensys.net>

---------

Signed-off-by: Luis Pinto <luis.pinto@consensys.net>
pull/7714/head
Luis Pinto 2 months ago committed by GitHub
parent f61b2a4ec5
commit efb55c1f54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java
  2. 34
      ethereum/verkletrie/src/main/java/org/hyperledger/besu/ethereum/verkletrie/VerkleEntryFactory.java
  3. 2
      gradle/versions.gradle

@ -130,6 +130,9 @@ public class VerkleWorldState extends DiffBasedWorldState {
final List<Bytes32> accountKeyIds = new ArrayList<>(); final List<Bytes32> accountKeyIds = new ArrayList<>();
if (accountUpdate != null && !accountUpdate.isUnchanged()) { if (accountUpdate != null && !accountUpdate.isUnchanged()) {
accountKeyIds.add(trieKeyPreloader.generateAccountKeyId()); accountKeyIds.add(trieKeyPreloader.generateAccountKeyId());
if (accountUpdate.getPrior() == null) {
accountKeyIds.add(Parameters.CODE_HASH_LEAF_KEY);
}
} }
// generate storage triekeys // generate storage triekeys
@ -212,13 +215,16 @@ public class VerkleWorldState extends DiffBasedWorldState {
return; return;
} }
if (accountUpdate.getUpdated() == null) { if (accountUpdate.getUpdated() == null) {
verkleEntryFactory.generateAccountKeysForRemoval(accountKey); verkleEntryFactory.generateAccountKeyForRemoval(accountKey);
final Hash addressHash = hashAndSavePreImage(accountKey); final Hash addressHash = hashAndSavePreImage(accountKey);
maybeStateUpdater.ifPresent( maybeStateUpdater.ifPresent(
bonsaiUpdater -> bonsaiUpdater.removeAccountInfoState(addressHash)); bonsaiUpdater -> bonsaiUpdater.removeAccountInfoState(addressHash));
return; return;
} }
final VerkleAccount updatedAcount = accountUpdate.getUpdated(); final VerkleAccount updatedAcount = accountUpdate.getUpdated();
if (accountUpdate.getPrior() == null) {
verkleEntryFactory.generateCodeHashKeyValueForUpdate(accountKey, updatedAcount.getCodeHash());
}
verkleEntryFactory.generateAccountKeyValueForUpdate( verkleEntryFactory.generateAccountKeyValueForUpdate(
accountKey, updatedAcount.getNonce(), updatedAcount.getBalance()); accountKey, updatedAcount.getNonce(), updatedAcount.getBalance());
maybeStateUpdater.ifPresent( maybeStateUpdater.ifPresent(
@ -274,7 +280,7 @@ public class VerkleWorldState extends DiffBasedWorldState {
if (!storageUpdate.getValue().isUnchanged()) { if (!storageUpdate.getValue().isUnchanged()) {
final UInt256 updatedStorage = storageUpdate.getValue().getUpdated(); final UInt256 updatedStorage = storageUpdate.getValue().getUpdated();
if (updatedStorage == null) { if (updatedStorage == null) {
verkleEntryFactory.generateStorageKeysForRemoval(accountKey, storageUpdate.getKey()); verkleEntryFactory.generateStorageKeyForRemoval(accountKey, storageUpdate.getKey());
maybeStateUpdater.ifPresent( maybeStateUpdater.ifPresent(
diffBasedUpdater -> diffBasedUpdater ->
diffBasedUpdater.removeStorageValueBySlotHash(updatedAddressHash, slotHash)); diffBasedUpdater.removeStorageValueBySlotHash(updatedAddressHash, slotHash));

@ -45,7 +45,7 @@ public class VerkleEntryFactory {
trieKeyAdapter = new TrieKeyBatchAdapter(hasher); trieKeyAdapter = new TrieKeyBatchAdapter(hasher);
} }
public void generateAccountKeysForRemoval(final Address address) { public void generateAccountKeyForRemoval(final Address address) {
keysForRemoval.add(trieKeyAdapter.basicDataKey(address)); keysForRemoval.add(trieKeyAdapter.basicDataKey(address));
} }
@ -58,8 +58,7 @@ public class VerkleEntryFactory {
} }
} }
public void generateStorageKeysForRemoval( public void generateStorageKeyForRemoval(final Address address, final StorageSlotKey storageKey) {
final Address address, final StorageSlotKey storageKey) {
keysForRemoval.add(trieKeyAdapter.storageKey(address, storageKey.getSlotKey().orElseThrow())); keysForRemoval.add(trieKeyAdapter.storageKey(address, storageKey.getSlotKey().orElseThrow()));
} }
@ -69,32 +68,39 @@ public class VerkleEntryFactory {
Bytes32 basicDataValue; Bytes32 basicDataValue;
if ((basicDataValue = nonStorageKeyValuesForUpdate.get(basicDataKey)) == null) { if ((basicDataValue = nonStorageKeyValuesForUpdate.get(basicDataKey)) == null) {
basicDataValue = Bytes32.ZERO; basicDataValue = Bytes32.ZERO;
} else {
basicDataValue = SuffixTreeEncoder.eraseVersion(basicDataValue);
basicDataValue = SuffixTreeEncoder.eraseNonce(basicDataValue);
basicDataValue = SuffixTreeEncoder.eraseBalance(basicDataValue);
} }
basicDataValue = SuffixTreeEncoder.addVersionIntoValue(basicDataValue, Bytes32.ZERO); basicDataValue = SuffixTreeEncoder.setVersionInValue(basicDataValue, Bytes.of(0));
basicDataValue = SuffixTreeEncoder.addNonceIntoValue(basicDataValue, UInt256.valueOf(nonce)); basicDataValue = SuffixTreeEncoder.setNonceInValue(basicDataValue, Bytes.ofUnsignedLong(nonce));
basicDataValue = SuffixTreeEncoder.addBalanceIntoValue(basicDataValue, balance); basicDataValue =
SuffixTreeEncoder.setBalanceInValue(
basicDataValue,
// balance size is exactly 16 bytes
balance.slice(16));
nonStorageKeyValuesForUpdate.put(basicDataKey, basicDataValue); nonStorageKeyValuesForUpdate.put(basicDataKey, basicDataValue);
} }
public void generateCodeHashKeyValueForUpdate(final Address address, final Hash codeHash) {
nonStorageKeyValuesForUpdate.put(trieKeyAdapter.codeHashKey(address), codeHash);
}
public void generateCodeKeyValuesForUpdate( public void generateCodeKeyValuesForUpdate(
final Address address, final Bytes code, final Hash codeHash) { final Address address, final Bytes code, final Hash codeHash) {
Bytes32 basicDataKey = trieKeyAdapter.basicDataKey(address); Bytes32 basicDataKey = trieKeyAdapter.basicDataKey(address);
Bytes32 basicDataValue; Bytes32 basicDataValue;
if ((basicDataValue = nonStorageKeyValuesForUpdate.get(basicDataKey)) == null) { if ((basicDataValue = nonStorageKeyValuesForUpdate.get(basicDataKey)) == null) {
basicDataValue = Bytes32.ZERO; basicDataValue = Bytes32.ZERO;
} else {
basicDataValue = SuffixTreeEncoder.eraseCodeSize(basicDataValue);
} }
basicDataValue = basicDataValue =
SuffixTreeEncoder.addCodeSizeIntoValue(basicDataValue, UInt256.valueOf(code.size())); SuffixTreeEncoder.setCodeSizeInValue(
basicDataValue,
// code size is exactly 3 bytes
Bytes.ofUnsignedInt(code.size()).slice(1));
nonStorageKeyValuesForUpdate.put(basicDataKey, basicDataValue); nonStorageKeyValuesForUpdate.put(basicDataKey, basicDataValue);
nonStorageKeyValuesForUpdate.put(trieKeyAdapter.codeHashKey(address), codeHash);
generateCodeHashKeyValueForUpdate(address, codeHash);
List<UInt256> codeChunks = trieKeyAdapter.chunkifyCode(code); List<UInt256> codeChunks = trieKeyAdapter.chunkifyCode(code);
for (int i = 0; i < codeChunks.size(); i++) { for (int i = 0; i < codeChunks.size(); i++) {
nonStorageKeyValuesForUpdate.put( nonStorageKeyValuesForUpdate.put(

@ -169,7 +169,7 @@ dependencyManagement {
entry 'ipa-multipoint' entry 'ipa-multipoint'
} }
dependency 'org.hyperledger.besu:besu-verkle-trie:0.0.3-20240917.164246-1' dependency 'org.hyperledger.besu:besu-verkle-trie:0.0.3-20240926.131636-2'
dependencySet(group: 'org.immutables', version: '2.10.0') { dependencySet(group: 'org.immutables', version: '2.10.0') {
entry 'value-annotations' entry 'value-annotations'

Loading…
Cancel
Save