@ -341,59 +341,55 @@ public class BonsaiWorldState
final Optional < BonsaiWorldStateKeyValueStorage . BonsaiUpdater > maybeStateUpdater ,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater ) {
maybeStateUpdater . ifPresent (
bonsaiUpdater - > {
for ( final Address address : worldStateUpdater . getStorageToClear ( ) ) {
// because we are clearing persisted values we need the account root as persisted
final BonsaiAccount oldAccount =
worldStateStorage
. getAccount ( address . addressHash ( ) )
. map (
bytes - > BonsaiAccount . fromRLP ( BonsaiWorldState . this , address , bytes , true ) )
. orElse ( null ) ;
if ( oldAccount = = null ) {
// This is when an account is both created and deleted within the scope of the same
// block. A not-uncommon DeFi bot pattern.
continue ;
}
final Hash addressHash = address . addressHash ( ) ;
final MerkleTrie < Bytes , Bytes > storageTrie =
createTrie (
( location , key ) - > getStorageTrieNode ( addressHash , location , key ) ,
oldAccount . getStorageRoot ( ) ) ;
try {
final StorageConsumingMap < StorageSlotKey , BonsaiValue < UInt256 > > storageToDelete =
worldStateUpdater . getStorageToUpdate ( ) . get ( address ) ;
Map < Bytes32 , Bytes > 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 ) ) ) ;
bonsaiUpdater . removeStorageValueBySlotHash (
address . addressHash ( ) , storageSlotKey . getSlotHash ( ) ) ;
storageToDelete
. computeIfAbsent (
storageSlotKey , key - > new BonsaiValue < > ( slotValue , null , true ) )
. setPrior ( slotValue ) ;
} ) ;
entriesToDelete . keySet ( ) . forEach ( storageTrie : : remove ) ;
if ( entriesToDelete . size ( ) = = 256 ) {
entriesToDelete = storageTrie . entriesFrom ( Bytes32 . ZERO , 256 ) ;
} else {
break ;
}
}
} catch ( MerkleTrieException e ) {
// need to throw to trigger the heal
throw new MerkleTrieException (
e . getMessage ( ) , Optional . of ( Address . wrap ( address ) ) , e . getHash ( ) , e . getLocation ( ) ) ;
}
for ( final Address address : worldStateUpdater . getStorageToClear ( ) ) {
// because we are clearing persisted values we need the account root as persisted
final BonsaiAccount oldAccount =
worldStateStorage
. getAccount ( address . addressHash ( ) )
. map ( bytes - > BonsaiAccount . fromRLP ( BonsaiWorldState . this , address , bytes , true ) )
. orElse ( null ) ;
if ( oldAccount = = null ) {
// This is when an account is both created and deleted within the scope of the same
// block. A not-uncommon DeFi bot pattern.
continue ;
}
final Hash addressHash = address . addressHash ( ) ;
final MerkleTrie < Bytes , Bytes > storageTrie =
createTrie (
( location , key ) - > getStorageTrieNode ( addressHash , location , key ) ,
oldAccount . getStorageRoot ( ) ) ;
try {
final StorageConsumingMap < StorageSlotKey , BonsaiValue < UInt256 > > storageToDelete =
worldStateUpdater . getStorageToUpdate ( ) . get ( address ) ;
Map < Bytes32 , Bytes > 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 BonsaiValue < > ( slotValue , null , true ) )
. setPrior ( slotValue ) ;
} ) ;
entriesToDelete . keySet ( ) . forEach ( storageTrie : : remove ) ;
if ( entriesToDelete . size ( ) = = 256 ) {
entriesToDelete = storageTrie . entriesFrom ( Bytes32 . ZERO , 256 ) ;
} else {
break ;
}
} ) ;
}
} catch ( MerkleTrieException e ) {
// need to throw to trigger the heal
throw new MerkleTrieException (
e . getMessage ( ) , Optional . of ( Address . wrap ( address ) ) , e . getHash ( ) , e . getLocation ( ) ) ;
}
}
}
@Override