|
30 | 30 | import org.hyperledger.besu.ethereum.trie.pathbased.bonsai.worldview.BonsaiWorldState; |
31 | 31 | import org.hyperledger.besu.ethereum.trie.pathbased.common.worldview.PathBasedWorldState; |
32 | 32 | import org.hyperledger.besu.ethereum.trie.pathbased.common.worldview.accumulator.PathBasedWorldStateUpdateAccumulator; |
| 33 | +import org.hyperledger.besu.evm.account.MutableAccount; |
33 | 34 | import org.hyperledger.besu.evm.blockhash.BlockHashLookup; |
34 | 35 | import org.hyperledger.besu.evm.tracing.OperationTracer; |
35 | 36 | import org.hyperledger.besu.evm.worldstate.WorldUpdater; |
36 | 37 | import org.hyperledger.besu.plugin.services.metrics.Counter; |
37 | 38 |
|
38 | 39 | import java.time.Duration; |
39 | | -import java.util.Comparator; |
| 40 | +import java.util.Collection; |
40 | 41 | import java.util.Optional; |
41 | 42 | import java.util.concurrent.CompletableFuture; |
42 | 43 | import java.util.concurrent.TimeUnit; |
@@ -179,49 +180,103 @@ private void applyWritesFromPriorTransactions( |
179 | 180 | final BlockAccessList blockAccessList, |
180 | 181 | final int balIndex, |
181 | 182 | final PathBasedWorldStateUpdateAccumulator<?> worldStateUpdater) { |
| 183 | + for (var accountChanges : blockAccessList.accountChanges()) { |
| 184 | + final Address address = accountChanges.address(); |
| 185 | + MutableAccount account = null; |
| 186 | + |
| 187 | + final var latestBalance = findLatestBalanceChange(accountChanges.balanceChanges(), balIndex); |
| 188 | + if (latestBalance != null) { |
| 189 | + if (account == null) { |
| 190 | + account = worldStateUpdater.getOrCreate(address); |
| 191 | + } |
| 192 | + account.setBalance(latestBalance.postBalance()); |
| 193 | + } |
| 194 | + |
| 195 | + final var latestNonce = findLatestNonceChange(accountChanges.nonceChanges(), balIndex); |
| 196 | + if (latestNonce != null) { |
| 197 | + if (account == null) { |
| 198 | + account = worldStateUpdater.getOrCreate(address); |
| 199 | + } |
| 200 | + account.setNonce(latestNonce.newNonce()); |
| 201 | + } |
| 202 | + |
| 203 | + final var latestCode = findLatestCodeChange(accountChanges.codeChanges(), balIndex); |
| 204 | + if (latestCode != null) { |
| 205 | + if (account == null) { |
| 206 | + account = worldStateUpdater.getOrCreate(address); |
| 207 | + } |
| 208 | + account.setCode(latestCode.newCode()); |
| 209 | + } |
| 210 | + |
| 211 | + for (var slotChanges : accountChanges.storageChanges()) { |
| 212 | + final UInt256 slotKey = slotChanges.slot().getSlotKey().orElseThrow(); |
| 213 | + |
| 214 | + final var latestStorage = findLatestStorageChange(slotChanges.changes(), balIndex); |
| 215 | + |
| 216 | + if (latestStorage != null) { |
| 217 | + if (account == null) { |
| 218 | + account = worldStateUpdater.getOrCreate(address); |
| 219 | + } |
| 220 | + account.setStorageValue( |
| 221 | + slotKey, latestStorage.newValue() != null ? latestStorage.newValue() : UInt256.ZERO); |
| 222 | + } |
| 223 | + } |
| 224 | + } |
| 225 | + } |
182 | 226 |
|
183 | | - blockAccessList |
184 | | - .accountChanges() |
185 | | - .forEach( |
186 | | - accountChanges -> { |
187 | | - final Address address = accountChanges.address(); |
188 | | - |
189 | | - accountChanges.balanceChanges().stream() |
190 | | - .filter(change -> change.txIndex() < balIndex) |
191 | | - .max(Comparator.comparingInt(BlockAccessList.BalanceChange::txIndex)) |
192 | | - .ifPresent( |
193 | | - change -> |
194 | | - worldStateUpdater.getOrCreate(address).setBalance(change.postBalance())); |
195 | | - |
196 | | - accountChanges.nonceChanges().stream() |
197 | | - .filter(change -> change.txIndex() < balIndex) |
198 | | - .max(Comparator.comparingInt(BlockAccessList.NonceChange::txIndex)) |
199 | | - .ifPresent( |
200 | | - change -> worldStateUpdater.getOrCreate(address).setNonce(change.newNonce())); |
201 | | - |
202 | | - accountChanges.codeChanges().stream() |
203 | | - .filter(change -> change.txIndex() < balIndex) |
204 | | - .max(Comparator.comparingInt(BlockAccessList.CodeChange::txIndex)) |
205 | | - .ifPresent( |
206 | | - change -> worldStateUpdater.getOrCreate(address).setCode(change.newCode())); |
207 | | - |
208 | | - accountChanges |
209 | | - .storageChanges() |
210 | | - .forEach( |
211 | | - slotChanges -> { |
212 | | - final UInt256 slotKey = slotChanges.slot().getSlotKey().orElseThrow(); |
213 | | - slotChanges.changes().stream() |
214 | | - .filter(change -> change.txIndex() < balIndex) |
215 | | - .max(Comparator.comparingInt(BlockAccessList.StorageChange::txIndex)) |
216 | | - .ifPresent( |
217 | | - change -> |
218 | | - worldStateUpdater |
219 | | - .getOrCreate(address) |
220 | | - .setStorageValue( |
221 | | - slotKey, |
222 | | - Optional.ofNullable(change.newValue()) |
223 | | - .orElse(UInt256.ZERO))); |
224 | | - }); |
225 | | - }); |
| 227 | + private BlockAccessList.BalanceChange findLatestBalanceChange( |
| 228 | + final Collection<BlockAccessList.BalanceChange> changes, final int maxIndex) { |
| 229 | + BlockAccessList.BalanceChange latest = null; |
| 230 | + int latestIndex = -1; |
| 231 | + for (var change : changes) { |
| 232 | + final int txIndex = change.txIndex(); |
| 233 | + if (txIndex < maxIndex && txIndex > latestIndex) { |
| 234 | + latest = change; |
| 235 | + latestIndex = txIndex; |
| 236 | + } |
| 237 | + } |
| 238 | + return latest; |
| 239 | + } |
| 240 | + |
| 241 | + private BlockAccessList.NonceChange findLatestNonceChange( |
| 242 | + final Collection<BlockAccessList.NonceChange> changes, final int maxIndex) { |
| 243 | + BlockAccessList.NonceChange latest = null; |
| 244 | + int latestIndex = -1; |
| 245 | + for (var change : changes) { |
| 246 | + final int txIndex = change.txIndex(); |
| 247 | + if (txIndex < maxIndex && txIndex > latestIndex) { |
| 248 | + latest = change; |
| 249 | + latestIndex = txIndex; |
| 250 | + } |
| 251 | + } |
| 252 | + return latest; |
| 253 | + } |
| 254 | + |
| 255 | + private BlockAccessList.CodeChange findLatestCodeChange( |
| 256 | + final Collection<BlockAccessList.CodeChange> changes, final int maxIndex) { |
| 257 | + BlockAccessList.CodeChange latest = null; |
| 258 | + int latestIndex = -1; |
| 259 | + for (var change : changes) { |
| 260 | + final int txIndex = change.txIndex(); |
| 261 | + if (txIndex < maxIndex && txIndex > latestIndex) { |
| 262 | + latest = change; |
| 263 | + latestIndex = txIndex; |
| 264 | + } |
| 265 | + } |
| 266 | + return latest; |
| 267 | + } |
| 268 | + |
| 269 | + private BlockAccessList.StorageChange findLatestStorageChange( |
| 270 | + final Collection<BlockAccessList.StorageChange> changes, final int maxIndex) { |
| 271 | + BlockAccessList.StorageChange latest = null; |
| 272 | + int latestIndex = -1; |
| 273 | + for (var change : changes) { |
| 274 | + final int txIndex = change.txIndex(); |
| 275 | + if (txIndex < maxIndex && txIndex > latestIndex) { |
| 276 | + latest = change; |
| 277 | + latestIndex = txIndex; |
| 278 | + } |
| 279 | + } |
| 280 | + return latest; |
226 | 281 | } |
227 | 282 | } |
0 commit comments