Wrapped WorldUpdater into `EVMWorldupdater` (#7434)

* wrapped WorldUpdater into `EVMWorldupdater` to remove the authority code injection from the implementation of the actual world updaters

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>

* add CHANGELOG entry

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>

---------

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
Co-authored-by: Justin Florentine <justin+github@florentine.us>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/7452/head
daniellehrner 3 months ago committed by GitHub
parent 6623b2d693
commit b53db47dab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 20
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AuthorityProcessor.java
  3. 34
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
  4. 20
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateMutableWorldStateUpdater.java
  5. 6
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java
  6. 23
      evm/src/main/java/org/hyperledger/besu/evm/fluent/SimpleWorld.java
  7. 36
      evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java
  8. 1
      evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java
  9. 1
      evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java
  10. 1
      evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractExtCallOperation.java
  11. 22
      evm/src/main/java/org/hyperledger/besu/evm/worldstate/AbstractWorldUpdater.java
  12. 127
      evm/src/main/java/org/hyperledger/besu/evm/worldstate/EVMWorldUpdater.java
  13. 22
      evm/src/main/java/org/hyperledger/besu/evm/worldstate/JournaledUpdater.java
  14. 8
      evm/src/main/java/org/hyperledger/besu/evm/worldstate/WorldUpdater.java
  15. 22
      evm/src/test/java/org/hyperledger/besu/evm/toy/ToyWorld.java

@ -15,6 +15,7 @@
### Additions and Improvements
- Expose set finalized/safe block in plugin api BlockchainService. These method can be used by plugins to set finalized/safe block for a PoA network (such as QBFT, IBFT and Clique).[#7382](https://github.com/hyperledger/besu/pull/7382)
- In process RPC service [#7395](https://github.com/hyperledger/besu/pull/7395)
- Wrap WorldUpdater into EVMWorldupdater [#7434](https://github.com/hyperledger/besu/pull/7434)
### Bug fixes
- Correct entrypoint in Docker evmtool [#7430](https://github.com/hyperledger/besu/pull/7430)

@ -18,8 +18,7 @@ import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.AccountState;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.AuthorizedCodeService;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.evm.worldstate.EVMWorldUpdater;
import java.math.BigInteger;
import java.util.Optional;
@ -38,10 +37,7 @@ public class AuthorityProcessor {
}
public void addContractToAuthority(
final WorldUpdater worldState,
final AuthorizedCodeService authorizedCodeService,
final Transaction transaction) {
final EVMWorldUpdater evmWorldUpdater, final Transaction transaction) {
transaction
.getAuthorizationList()
.get()
@ -60,7 +56,7 @@ public class AuthorityProcessor {
}
final Optional<MutableAccount> maybeAccount =
Optional.ofNullable(worldState.getAccount(authorityAddress));
Optional.ofNullable(evmWorldUpdater.getAccount(authorityAddress));
final long accountNonce =
maybeAccount.map(AccountState::getNonce).orElse(0L);
@ -69,12 +65,14 @@ public class AuthorityProcessor {
return;
}
if (authorizedCodeService.hasAuthorizedCode(authorityAddress)) {
if (evmWorldUpdater
.authorizedCodeService()
.hasAuthorizedCode(authorityAddress)) {
return;
}
Optional<Account> codeAccount =
Optional.ofNullable(worldState.get(payload.address()));
Optional.ofNullable(evmWorldUpdater.get(payload.address()));
final Bytes code;
if (codeAccount.isPresent()) {
code = codeAccount.get().getCode();
@ -82,7 +80,9 @@ public class AuthorityProcessor {
code = Bytes.EMPTY;
}
authorizedCodeService.addAuthorizedCode(authorityAddress, code);
evmWorldUpdater
.authorizedCodeService()
.addAuthorizedCode(authorityAddress, code);
}));
}
}

@ -42,7 +42,7 @@ import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.AuthorizedCodeService;
import org.hyperledger.besu.evm.worldstate.EVMWorldUpdater;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import java.util.Deque;
@ -286,9 +286,8 @@ public class MainnetTransactionProcessor {
final TransactionValidationParams transactionValidationParams,
final PrivateMetadataUpdater privateMetadataUpdater,
final Wei blobGasPrice) {
final EVMWorldUpdater evmWorldUpdater = new EVMWorldUpdater(worldState);
try {
final AuthorizedCodeService authorizedCodeService = new AuthorizedCodeService();
worldState.setAuthorizedCodeService(authorizedCodeService);
final var transactionValidator = transactionValidatorFactory.get();
LOG.trace("Starting execution of {}", transaction);
ValidationResult<TransactionInvalidReason> validationResult =
@ -306,7 +305,7 @@ public class MainnetTransactionProcessor {
}
final Address senderAddress = transaction.getSender();
final MutableAccount sender = worldState.getOrCreateSenderAccount(senderAddress);
final MutableAccount sender = evmWorldUpdater.getOrCreateSenderAccount(senderAddress);
validationResult =
transactionValidator.validateForSender(transaction, sender, transactionValidationParams);
@ -315,7 +314,7 @@ public class MainnetTransactionProcessor {
return TransactionProcessingResult.invalid(validationResult);
}
operationTracer.tracePrepareTransaction(worldState, transaction);
operationTracer.tracePrepareTransaction(evmWorldUpdater, transaction);
final Set<Address> addressList = new BytesTrieSet<>(Address.SIZE);
@ -324,10 +323,8 @@ public class MainnetTransactionProcessor {
throw new RuntimeException("Authority processor is required for 7702 transactions");
}
maybeAuthorityProcessor
.get()
.addContractToAuthority(worldState, authorizedCodeService, transaction);
addressList.addAll(authorizedCodeService.getAuthorities());
maybeAuthorityProcessor.get().addContractToAuthority(evmWorldUpdater, transaction);
addressList.addAll(evmWorldUpdater.authorizedCodeService().getAuthorities());
}
final long previousNonce = sender.incrementNonce();
@ -384,8 +381,7 @@ public class MainnetTransactionProcessor {
accessListGas,
setCodeGas);
final WorldUpdater worldUpdater = worldState.updater();
worldUpdater.setAuthorizedCodeService(authorizedCodeService);
final WorldUpdater worldUpdater = evmWorldUpdater.updater();
final ImmutableMap.Builder<String, Object> contextVariablesBuilder =
ImmutableMap.<String, Object>builder()
.put(KEY_IS_PERSISTING_PRIVATE_STATE, isPersistingPrivateState)
@ -437,12 +433,11 @@ public class MainnetTransactionProcessor {
.contract(contractAddress)
.inputData(initCodeBytes.slice(code.getSize()))
.code(code)
.authorizedCodeService(authorizedCodeService)
.build();
} else {
@SuppressWarnings("OptionalGetWithoutIsPresent") // isContractCall tests isPresent
final Address to = transaction.getTo().get();
final Optional<Account> maybeContract = Optional.ofNullable(worldState.get(to));
final Optional<Account> maybeContract = Optional.ofNullable(evmWorldUpdater.get(to));
initialFrame =
commonMessageFrameBuilder
.type(MessageFrame.Type.MESSAGE_CALL)
@ -453,7 +448,6 @@ public class MainnetTransactionProcessor {
maybeContract
.map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode()))
.orElse(CodeV0.EMPTY_CODE))
.authorizedCodeService(authorizedCodeService)
.build();
}
Deque<MessageFrame> messageFrameStack = initialFrame.getMessageFrameStack();
@ -532,9 +526,9 @@ public class MainnetTransactionProcessor {
operationTracer.traceBeforeRewardTransaction(worldUpdater, transaction, coinbaseWeiDelta);
final var coinbase = worldState.getOrCreate(miningBeneficiary);
final var coinbase = evmWorldUpdater.getOrCreate(miningBeneficiary);
coinbase.incrementBalance(coinbaseWeiDelta);
authorizedCodeService.resetAuthorities();
evmWorldUpdater.authorizedCodeService().resetAuthorities();
operationTracer.traceEndTransaction(
worldUpdater,
@ -546,10 +540,10 @@ public class MainnetTransactionProcessor {
initialFrame.getSelfDestructs(),
0L);
initialFrame.getSelfDestructs().forEach(worldState::deleteAccount);
initialFrame.getSelfDestructs().forEach(evmWorldUpdater::deleteAccount);
if (clearEmptyAccounts) {
worldState.clearAccountsThatAreEmpty();
evmWorldUpdater.clearAccountsThatAreEmpty();
}
if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
@ -577,7 +571,7 @@ public class MainnetTransactionProcessor {
}
} catch (final MerkleTrieException re) {
operationTracer.traceEndTransaction(
worldState.updater(),
evmWorldUpdater.updater(),
transaction,
false,
Bytes.EMPTY,
@ -590,7 +584,7 @@ public class MainnetTransactionProcessor {
throw re;
} catch (final RuntimeException re) {
operationTracer.traceEndTransaction(
worldState.updater(),
evmWorldUpdater.updater(),
transaction,
false,
Bytes.EMPTY,

@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.AuthorizedCodeService;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import java.util.Collection;
@ -31,39 +30,35 @@ public class PrivateMutableWorldStateUpdater implements WorldUpdater {
protected final WorldUpdater publicWorldUpdater;
protected final WorldUpdater privateWorldUpdater;
private AuthorizedCodeService authorizedCodeService;
public PrivateMutableWorldStateUpdater(
final WorldUpdater publicWorldUpdater, final WorldUpdater privateWorldUpdater) {
this.publicWorldUpdater = publicWorldUpdater;
this.privateWorldUpdater = privateWorldUpdater;
this.authorizedCodeService = new AuthorizedCodeService();
}
@Override
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
return authorizedCodeService.processMutableAccount(
this, privateWorldUpdater.createAccount(address, nonce, balance), address);
return privateWorldUpdater.createAccount(address, nonce, balance);
}
@Override
public MutableAccount createAccount(final Address address) {
return authorizedCodeService.processMutableAccount(
this, privateWorldUpdater.createAccount(address), address);
return privateWorldUpdater.createAccount(address);
}
@Override
public MutableAccount getAccount(final Address address) {
final MutableAccount privateAccount = privateWorldUpdater.getAccount(address);
if (privateAccount != null && !privateAccount.isEmpty()) {
return authorizedCodeService.processMutableAccount(this, privateAccount, address);
return privateAccount;
}
final MutableAccount publicAccount = publicWorldUpdater.getAccount(address);
if (publicAccount != null && !publicAccount.isEmpty()) {
publicAccount.becomeImmutable();
return authorizedCodeService.processMutableAccount(this, publicAccount, address);
return publicAccount;
}
return authorizedCodeService.processMutableAccount(this, privateAccount, address);
return privateAccount;
}
@Override
@ -109,9 +104,4 @@ public class PrivateMutableWorldStateUpdater implements WorldUpdater {
public Optional<WorldUpdater> parentUpdater() {
return privateWorldUpdater.parentUpdater();
}
@Override
public void setAuthorizedCodeService(final AuthorizedCodeService authorizedCodeService) {
this.authorizedCodeService = authorizedCodeService;
}
}

@ -250,8 +250,7 @@ public abstract class DiffBasedWorldStateUpdateAccumulator<ACCOUNT extends DiffB
accountsToUpdate.put(address, diffBasedValue);
} else if (diffBasedValue.getUpdated() != null) {
if (diffBasedValue.getUpdated().isEmpty()) {
return authorizedCodeService.processMutableAccount(
this, track(new UpdateTrackingAccount<>(diffBasedValue.getUpdated())), address);
return track(new UpdateTrackingAccount<>(diffBasedValue.getUpdated()));
} else {
throw new IllegalStateException("Cannot create an account when one already exists");
}
@ -268,8 +267,7 @@ public abstract class DiffBasedWorldStateUpdateAccumulator<ACCOUNT extends DiffB
Hash.EMPTY,
true);
diffBasedValue.setUpdated(newAccount);
return authorizedCodeService.processMutableAccount(
this, track(new UpdateTrackingAccount<>(newAccount)), address);
return track(new UpdateTrackingAccount<>(newAccount));
}
@Override

@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.AuthorizedCodeService;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import java.util.Collection;
@ -35,8 +34,6 @@ public class SimpleWorld implements WorldUpdater {
/** The Accounts. */
Map<Address, SimpleAccount> accounts = new HashMap<>();
private AuthorizedCodeService authorizedCodeService;
/** Instantiates a new Simple world. */
public SimpleWorld() {
this(null);
@ -49,7 +46,6 @@ public class SimpleWorld implements WorldUpdater {
*/
public SimpleWorld(final SimpleWorld parent) {
this.parent = parent;
this.authorizedCodeService = new AuthorizedCodeService();
}
@Override
@ -60,11 +56,11 @@ public class SimpleWorld implements WorldUpdater {
@Override
public Account get(final Address address) {
if (accounts.containsKey(address)) {
return authorizedCodeService.processAccount(this, accounts.get(address), address);
return accounts.get(address);
} else if (parent != null) {
return authorizedCodeService.processAccount(this, parent.get(address), address);
return parent.get(address);
} else {
return authorizedCodeService.processAccount(this, null, address);
return null;
}
}
@ -75,14 +71,14 @@ public class SimpleWorld implements WorldUpdater {
}
SimpleAccount account = new SimpleAccount(address, nonce, balance);
accounts.put(address, account);
return authorizedCodeService.processMutableAccount(this, account, address);
return account;
}
@Override
public MutableAccount getAccount(final Address address) {
SimpleAccount account = accounts.get(address);
if (account != null) {
return authorizedCodeService.processMutableAccount(this, account, address);
return account;
}
Account parentAccount = parent == null ? null : parent.getAccount(address);
if (parentAccount != null) {
@ -94,9 +90,9 @@ public class SimpleWorld implements WorldUpdater {
parentAccount.getBalance(),
parentAccount.getCode());
accounts.put(address, account);
return authorizedCodeService.processMutableAccount(this, account, address);
return account;
}
return authorizedCodeService.processMutableAccount(this, null, address);
return null;
}
@Override
@ -136,9 +132,4 @@ public class SimpleWorld implements WorldUpdater {
public Optional<WorldUpdater> parentUpdater() {
return Optional.ofNullable(parent);
}
@Override
public void setAuthorizedCodeService(final AuthorizedCodeService authorizedCodeService) {
this.authorizedCodeService = authorizedCodeService;
}
}

@ -33,7 +33,6 @@ import org.hyperledger.besu.evm.internal.UnderflowException;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.evm.operation.Operation;
import org.hyperledger.besu.evm.worldstate.AuthorizedCodeService;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import java.util.ArrayDeque;
@ -202,7 +201,6 @@ public class MessageFrame {
// Global data fields.
private final WorldUpdater worldUpdater;
private final AuthorizedCodeService authorizedCodeService;
// Metadata fields.
private final Type type;
@ -272,8 +270,7 @@ public class MessageFrame {
final Consumer<MessageFrame> completer,
final Map<String, Object> contextVariables,
final Optional<Bytes> revertReason,
final TxValues txValues,
final AuthorizedCodeService authorizedCodeService) {
final TxValues txValues) {
this.txValues = txValues;
this.type = type;
@ -293,7 +290,6 @@ public class MessageFrame {
this.completer = completer;
this.contextVariables = contextVariables;
this.revertReason = revertReason;
this.authorizedCodeService = authorizedCodeService;
this.undoMark = txValues.transientStorage().mark();
}
@ -427,15 +423,6 @@ public class MessageFrame {
return returnData;
}
/**
* Return the authorized account service.
*
* @return the authorized account service
*/
public AuthorizedCodeService getAuthorizedCodeService() {
return authorizedCodeService;
}
/**
* Set the return data.
*
@ -1360,7 +1347,6 @@ public class MessageFrame {
private Optional<Bytes> reason = Optional.empty();
private Set<Address> accessListWarmAddresses = emptySet();
private Multimap<Address, Bytes32> accessListWarmStorage = HashMultimap.create();
private AuthorizedCodeService authorizedCodeService;
private Optional<List<VersionedHash>> versionedHashes = Optional.empty();
@ -1645,17 +1631,6 @@ public class MessageFrame {
return this;
}
/**
* Sets authorized account service.
*
* @param authorizedCodeService the authorized account service
* @return the builder
*/
public Builder authorizedCodeService(final AuthorizedCodeService authorizedCodeService) {
this.authorizedCodeService = authorizedCodeService;
return this;
}
private void validate() {
if (parentMessageFrame == null) {
checkState(worldUpdater != null, "Missing message frame world updater");
@ -1690,10 +1665,6 @@ public class MessageFrame {
boolean newStatic;
TxValues newTxValues;
if (authorizedCodeService == null) {
authorizedCodeService = new AuthorizedCodeService();
}
if (parentMessageFrame == null) {
newTxValues =
new TxValues(
@ -1721,8 +1692,6 @@ public class MessageFrame {
parentMessageFrame.warmUpAddress(contract);
}
updater.setAuthorizedCodeService(authorizedCodeService);
MessageFrame messageFrame =
new MessageFrame(
type,
@ -1739,8 +1708,7 @@ public class MessageFrame {
completer,
contextVariables == null ? Map.of() : contextVariables,
reason,
newTxValues,
authorizedCodeService);
newTxValues);
newTxValues.messageFrameStack().addFirst(messageFrame);
messageFrame.warmUpAddress(sender);
messageFrame.warmUpAddress(contract);

@ -230,7 +230,6 @@ public abstract class AbstractCallOperation extends AbstractOperation {
.code(code)
.isStatic(isStatic(frame))
.completer(child -> complete(frame, child))
.authorizedCodeService(frame.getAuthorizedCodeService())
.build();
// see note in stack depth check about incrementing cost
frame.incrementRemainingGas(cost);

@ -195,7 +195,6 @@ public abstract class AbstractCreateOperation extends AbstractOperation {
.apparentValue(value)
.code(code)
.completer(child -> complete(parent, child, evm))
.authorizedCodeService(parent.getAuthorizedCodeService())
.build();
parent.setState(MessageFrame.State.CODE_SUSPENDED);

@ -180,7 +180,6 @@ public abstract class AbstractExtCallOperation extends AbstractCallOperation {
.code(code)
.isStatic(isStatic(frame))
.completer(child -> complete(frame, child))
.authorizedCodeService(frame.getAuthorizedCodeService())
.build();
frame.setState(MessageFrame.State.CODE_SUSPENDED);

@ -43,9 +43,6 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
private final W world;
private final EvmConfiguration evmConfiguration;
/** The authorized code service. */
protected AuthorizedCodeService authorizedCodeService;
/** The Updated accounts. */
protected Map<Address, UpdateTrackingAccount<A>> updatedAccounts = new ConcurrentHashMap<>();
@ -62,7 +59,6 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
protected AbstractWorldUpdater(final W world, final EvmConfiguration evmConfiguration) {
this.world = world;
this.evmConfiguration = evmConfiguration;
this.authorizedCodeService = new AuthorizedCodeService();
}
/**
@ -91,7 +87,7 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
final UpdateTrackingAccount<A> account = new UpdateTrackingAccount<>(address);
account.setNonce(nonce);
account.setBalance(balance);
return authorizedCodeService.processMutableAccount(this, track(account), address);
return track(account);
}
@Override
@ -99,12 +95,12 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
// We may have updated it already, so check that first.
final MutableAccount existing = updatedAccounts.get(address);
if (existing != null) {
return authorizedCodeService.processAccount(this, existing, address);
return existing;
}
if (deletedAccounts.contains(address)) {
return null;
}
return authorizedCodeService.processAccount(this, getForMutation(address), address);
return getForMutation(address);
}
@Override
@ -112,7 +108,7 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
// We may have updated it already, so check that first.
final MutableAccount existing = updatedAccounts.get(address);
if (existing != null) {
return authorizedCodeService.processMutableAccount(this, existing, address);
return existing;
}
if (deletedAccounts.contains(address)) {
return null;
@ -121,10 +117,9 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
// Otherwise, get it from our wrapped view and create a new update tracker.
final A origin = getForMutation(address);
if (origin == null) {
return authorizedCodeService.processMutableAccount(this, null, address);
return null;
} else {
return authorizedCodeService.processMutableAccount(
this, track(new UpdateTrackingAccount<>(origin)), address);
return track(new UpdateTrackingAccount<>(origin));
}
}
@ -170,11 +165,6 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
}
}
@Override
public void setAuthorizedCodeService(final AuthorizedCodeService authorizedCodeService) {
this.authorizedCodeService = authorizedCodeService;
}
/**
* The accounts modified in this updater.
*

@ -0,0 +1,127 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm.worldstate;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.frame.MessageFrame;
import java.util.Collection;
import java.util.Optional;
/**
* The EVM world updater. This class is a wrapper around a WorldUpdater that provides an
* AuthorizedCodeService to manage the authorized code for accounts.
*/
public class EVMWorldUpdater implements WorldUpdater {
private final WorldUpdater rootWorldUpdater;
private final AuthorizedCodeService authorizedCodeService;
/**
* Instantiates a new EVM world updater.
*
* @param rootWorldUpdater the root world updater
*/
public EVMWorldUpdater(final WorldUpdater rootWorldUpdater) {
this(rootWorldUpdater, new AuthorizedCodeService());
}
private EVMWorldUpdater(
final WorldUpdater rootWorldUpdater, final AuthorizedCodeService authorizedCodeService) {
this.rootWorldUpdater = rootWorldUpdater;
this.authorizedCodeService = authorizedCodeService;
}
/**
* Authorized code service.
*
* @return the authorized code service
*/
public AuthorizedCodeService authorizedCodeService() {
return authorizedCodeService;
}
@Override
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
return authorizedCodeService.processMutableAccount(
this, rootWorldUpdater.createAccount(address, nonce, balance), address);
}
@Override
public MutableAccount getAccount(final Address address) {
return authorizedCodeService.processMutableAccount(
this, rootWorldUpdater.getAccount(address), address);
}
@Override
public MutableAccount getOrCreate(final Address address) {
return authorizedCodeService.processMutableAccount(
this, rootWorldUpdater.getOrCreate(address), address);
}
@Override
public MutableAccount getOrCreateSenderAccount(final Address address) {
return authorizedCodeService.processMutableAccount(
this, rootWorldUpdater.getOrCreateSenderAccount(address), address);
}
@Override
public MutableAccount getSenderAccount(final MessageFrame frame) {
return authorizedCodeService.processMutableAccount(
this, rootWorldUpdater.getSenderAccount(frame), frame.getSenderAddress());
}
@Override
public void deleteAccount(final Address address) {
rootWorldUpdater.deleteAccount(address);
}
@Override
public Collection<? extends Account> getTouchedAccounts() {
return rootWorldUpdater.getTouchedAccounts();
}
@Override
public Collection<Address> getDeletedAccountAddresses() {
return rootWorldUpdater.getDeletedAccountAddresses();
}
@Override
public void revert() {
rootWorldUpdater.revert();
}
@Override
public void commit() {
rootWorldUpdater.commit();
}
@Override
public Optional<WorldUpdater> parentUpdater() {
return rootWorldUpdater.parentUpdater();
}
@Override
public WorldUpdater updater() {
return new EVMWorldUpdater(rootWorldUpdater.updater(), authorizedCodeService);
}
@Override
public Account get(final Address address) {
return authorizedCodeService.processAccount(this, rootWorldUpdater.get(address), address);
}
}

@ -41,7 +41,6 @@ public class JournaledUpdater<W extends WorldView> implements WorldUpdater {
final UndoMap<Address, JournaledAccount> accounts;
final UndoSet<Address> deleted;
final long undoMark;
private AuthorizedCodeService authorizedCodeService;
/**
* Instantiates a new Stacked updater.
@ -67,7 +66,6 @@ public class JournaledUpdater<W extends WorldView> implements WorldUpdater {
"WorldUpdater must be a JournaledWorldUpdater or an AbstractWorldUpdater");
}
undoMark = accounts.mark();
this.authorizedCodeService = new AuthorizedCodeService();
}
/**
@ -128,18 +126,12 @@ public class JournaledUpdater<W extends WorldView> implements WorldUpdater {
accounts.values().forEach(JournaledAccount::markTransactionBoundary);
}
@Override
public void setAuthorizedCodeService(final AuthorizedCodeService authorizedCodeService) {
this.authorizedCodeService = authorizedCodeService;
}
@Override
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
JournaledAccount journaledAccount =
new JournaledAccount(rootWorld.createAccount(address, nonce, balance));
accounts.put(address, journaledAccount);
return authorizedCodeService.processMutableAccount(
this, new JournaledAccount(journaledAccount), address);
return new JournaledAccount(journaledAccount);
}
@Override
@ -147,7 +139,7 @@ public class JournaledUpdater<W extends WorldView> implements WorldUpdater {
// We may have updated it already, so check that first.
final JournaledAccount existing = accounts.get(address);
if (existing != null) {
return authorizedCodeService.processMutableAccount(this, existing, address);
return existing;
}
if (deleted.contains(address)) {
return null;
@ -156,11 +148,11 @@ public class JournaledUpdater<W extends WorldView> implements WorldUpdater {
// Otherwise, get it from our wrapped view and create a new update tracker.
final MutableAccount origin = rootWorld.getAccount(address);
if (origin == null) {
return authorizedCodeService.processMutableAccount(this, null, address);
return null;
} else {
var newAccount = new JournaledAccount(origin);
accounts.put(address, newAccount);
return authorizedCodeService.processMutableAccount(this, newAccount, address);
return newAccount;
}
}
@ -177,12 +169,12 @@ public class JournaledUpdater<W extends WorldView> implements WorldUpdater {
public Account get(final Address address) {
final MutableAccount existing = accounts.get(address);
if (existing != null) {
return authorizedCodeService.processAccount(this, existing, address);
return existing;
}
if (deleted.contains(address)) {
return authorizedCodeService.processAccount(this, null, address);
return null;
}
return authorizedCodeService.processAccount(this, rootWorld.get(address), address);
return rootWorld.get(address);
}
@Override

@ -179,12 +179,4 @@ public interface WorldUpdater extends MutableWorldView {
default void markTransactionBoundary() {
// default is to ignore
}
/**
* Sets the {@link AuthorizedCodeService} associated with this {@link WorldUpdater}.
*
* @param authorizedCodeService the {@link AuthorizedCodeService} to associate with this {@link
* WorldUpdater}
*/
void setAuthorizedCodeService(AuthorizedCodeService authorizedCodeService);
}

@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.AuthorizedCodeService;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import java.util.Collection;
@ -33,7 +32,6 @@ public class ToyWorld implements WorldUpdater {
ToyWorld parent;
Map<Address, ToyAccount> accounts = new HashMap<>();
private AuthorizedCodeService authorizedCodeService;
public ToyWorld() {
this(null);
@ -41,7 +39,6 @@ public class ToyWorld implements WorldUpdater {
public ToyWorld(final ToyWorld parent) {
this.parent = parent;
this.authorizedCodeService = new AuthorizedCodeService();
}
@Override
@ -52,11 +49,11 @@ public class ToyWorld implements WorldUpdater {
@Override
public Account get(final Address address) {
if (accounts.containsKey(address)) {
return authorizedCodeService.processAccount(this, accounts.get(address), address);
return accounts.get(address);
} else if (parent != null) {
return authorizedCodeService.processAccount(this, parent.get(address), address);
return parent.get(address);
} else {
return authorizedCodeService.processAccount(this, null, address);
return null;
}
}
@ -73,17 +70,17 @@ public class ToyWorld implements WorldUpdater {
final Bytes code) {
ToyAccount account = new ToyAccount(parentAccount, address, nonce, balance, code);
accounts.put(address, account);
return authorizedCodeService.processMutableAccount(this, account, address);
return account;
}
@Override
public MutableAccount getAccount(final Address address) {
if (accounts.containsKey(address)) {
return authorizedCodeService.processMutableAccount(this, accounts.get(address), address);
return accounts.get(address);
} else if (parent != null) {
Account parentAccount = parent.getAccount(address);
if (parentAccount == null) {
return authorizedCodeService.processMutableAccount(this, null, address);
return null;
} else {
return createAccount(
parentAccount,
@ -93,7 +90,7 @@ public class ToyWorld implements WorldUpdater {
parentAccount.getCode());
}
} else {
return authorizedCodeService.processMutableAccount(this, null, address);
return null;
}
}
@ -131,9 +128,4 @@ public class ToyWorld implements WorldUpdater {
public Optional<WorldUpdater> parentUpdater() {
return Optional.empty();
}
@Override
public void setAuthorizedCodeService(final AuthorizedCodeService authorizedCodeService) {
this.authorizedCodeService = authorizedCodeService;
}
}

Loading…
Cancel
Save