From 196bf10413bbc0a2b8bf55d91cb6600cd80ccf60 Mon Sep 17 00:00:00 2001 From: Daniel Lehrner Date: Wed, 9 Oct 2024 13:05:31 +0200 Subject: [PATCH] return no code if account has delegated code to precompile, treat precompile always as warm account when resolving code Signed-off-by: Daniel Lehrner --- .../mainnet/MainnetTransactionProcessor.java | 6 +----- .../evm/account/BaseDelegatedCodeAccount.java | 10 +++++++++- .../besu/evm/account/DelegatedCodeAccount.java | 7 +++++-- .../account/MutableDelegatedCodeAccount.java | 7 +++++-- .../besu/evm/gascalculator/GasCalculator.java | 10 ---------- .../evm/gascalculator/PragueGasCalculator.java | 5 ----- .../worldstate/DelegatedCodeGasCostHelper.java | 14 ++++++++++++-- .../evm/worldstate/DelegatedCodeService.java | 17 +++++++++++++---- .../besu/evm/worldstate/EVMWorldUpdater.java | 6 ++++-- 9 files changed, 49 insertions(+), 33 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index de6dee935f..ee3fc8aa9d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -286,7 +286,7 @@ public class MainnetTransactionProcessor { final TransactionValidationParams transactionValidationParams, final PrivateMetadataUpdater privateMetadataUpdater, final Wei blobGasPrice) { - final EVMWorldUpdater evmWorldUpdater = new EVMWorldUpdater(worldState); + final EVMWorldUpdater evmWorldUpdater = new EVMWorldUpdater(worldState, gasCalculator); try { final var transactionValidator = transactionValidatorFactory.get(); LOG.trace("Starting execution of {}", transaction); @@ -445,10 +445,6 @@ public class MainnetTransactionProcessor { final Address to = transaction.getTo().get(); final Optional maybeContract = Optional.ofNullable(evmWorldUpdater.get(to)); - if (maybeContract.isPresent() && maybeContract.get().hasDelegatedCode()) { - warmAddressList.add(to); - } - initialFrame = commonMessageFrameBuilder .type(MessageFrame.Type.MESSAGE_CALL) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java index 0e5219d835..4ee28145de 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.evm.account; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.Optional; @@ -25,13 +26,17 @@ import org.apache.tuweni.bytes.Bytes; class BaseDelegatedCodeAccount { private final WorldUpdater worldUpdater; + private final GasCalculator gasCalculator; /** The address of the account that has delegated code to be loaded into it. */ protected final Address delegatedCodeAddress; protected BaseDelegatedCodeAccount( - final WorldUpdater worldUpdater, final Address delegatedCodeAddress) { + final WorldUpdater worldUpdater, + final Address delegatedCodeAddress, + final GasCalculator gasCalculator) { this.worldUpdater = worldUpdater; + this.gasCalculator = gasCalculator; this.delegatedCodeAddress = delegatedCodeAddress; } @@ -86,6 +91,9 @@ class BaseDelegatedCodeAccount { } private Bytes resolveDelegatedCode() { + if (gasCalculator.isPrecompile(delegatedCodeAddress)) { + return Bytes.EMPTY; + } return getDelegatedAccount().map(Account::getUnprocessedCode).orElse(Bytes.EMPTY); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java index 1eba364c19..0ac969abad 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.evm.account; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.NavigableMap; @@ -37,12 +38,14 @@ public class DelegatedCodeAccount extends BaseDelegatedCodeAccount implements Ac * @param worldUpdater the world updater. * @param wrappedAccount the account that has delegated code to be loaded into it. * @param codeDelegationAddress the address of the delegated code. + * @param gasCalculator the gas calculator to check for precompiles. */ public DelegatedCodeAccount( final WorldUpdater worldUpdater, final Account wrappedAccount, - final Address codeDelegationAddress) { - super(worldUpdater, codeDelegationAddress); + final Address codeDelegationAddress, + final GasCalculator gasCalculator) { + super(worldUpdater, codeDelegationAddress, gasCalculator); this.wrappedAccount = wrappedAccount; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java index 0e1e1145dd..20894b4f28 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.evm.account; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.Map; @@ -39,12 +40,14 @@ public class MutableDelegatedCodeAccount extends BaseDelegatedCodeAccount * @param worldUpdater the world updater. * @param wrappedAccount the account that has delegated code to be loaded into it. * @param codeDelegationAddress the address of the delegated code. + * @param gasCalculator the gas calculator to check for precompiles. */ public MutableDelegatedCodeAccount( final WorldUpdater worldUpdater, final MutableAccount wrappedAccount, - final Address codeDelegationAddress) { - super(worldUpdater, codeDelegationAddress); + final Address codeDelegationAddress, + final GasCalculator gasCalculator) { + super(worldUpdater, codeDelegationAddress, gasCalculator); this.wrappedAccount = wrappedAccount; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java index fd453deac5..4c6770e70d 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java @@ -666,14 +666,4 @@ public interface GasCalculator { default long calculateDelegateCodeGasRefund(final long alreadyExistingAccountSize) { return 0L; } - - /** - * Returns the gas cost for resolving the code of a delegate account. - * - * @param isWarm whether the account is warm - * @return the gas cost - */ - default long delegatedCodeResolutionGasCost(final boolean isWarm) { - return 0L; - } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java index 33fe98b996..666292e9e1 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java @@ -52,9 +52,4 @@ public class PragueGasCalculator extends CancunGasCalculator { public long calculateDelegateCodeGasRefund(final long alreadyExistingAccounts) { return existingAccountGasRefund * alreadyExistingAccounts; } - - @Override - public long delegatedCodeResolutionGasCost(final boolean isWarm) { - return isWarm ? getWarmStorageReadCost() : getColdAccountAccessCost(); - } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java index fc67770314..3cdd2dc205 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.evm.worldstate; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; @@ -66,9 +67,9 @@ public class DelegatedCodeGasCostHelper { throw new RuntimeException("A delegated code account must have a delegated code address"); } - final boolean delegatedCodeIsWarm = frame.warmUpAddress(account.delegatedCodeAddress().get()); final long delegatedCodeResolutionGas = - gasCalculator.delegatedCodeResolutionGasCost(delegatedCodeIsWarm); + calculateDelegatedCodeResolutionGas( + frame, gasCalculator, account.delegatedCodeAddress().get()); if (frame.getRemainingGas() < delegatedCodeResolutionGas) { return new Result(delegatedCodeResolutionGas, Status.INSUFFICIENT_GAS); @@ -77,4 +78,13 @@ public class DelegatedCodeGasCostHelper { frame.decrementRemainingGas(delegatedCodeResolutionGas); return new Result(delegatedCodeResolutionGas, Status.SUCCESS); } + + private static long calculateDelegatedCodeResolutionGas( + final MessageFrame frame, final GasCalculator gasCalculator, final Address delegateeAddress) { + final boolean delegatedCodeIsWarm = + frame.warmUpAddress(delegateeAddress) || gasCalculator.isPrecompile(delegateeAddress); + return delegatedCodeIsWarm + ? gasCalculator.getWarmStorageReadCost() + : gasCalculator.getColdAccountAccessCost(); + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java index 885324b10b..1f23d48955 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.DelegatedCodeAccount; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.account.MutableDelegatedCodeAccount; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.apache.tuweni.bytes.Bytes; @@ -27,8 +28,16 @@ public class DelegatedCodeService { private static final Bytes DELEGATED_CODE_PREFIX = Bytes.fromHexString("ef0100"); private static final int DELEGATED_CODE_SIZE = DELEGATED_CODE_PREFIX.size() + Address.SIZE; - /** Creates a new DelegatedCodeService. */ - public DelegatedCodeService() {} + private final GasCalculator gasCalculator; + + /** + * Creates a new DelegatedCodeService. + * + * @param gasCalculator the gas calculator to check for pre compiles. + */ + public DelegatedCodeService(final GasCalculator gasCalculator) { + this.gasCalculator = gasCalculator; + } /** * Add the delegated code to the given account. @@ -64,7 +73,7 @@ public class DelegatedCodeService { } return new DelegatedCodeAccount( - worldUpdater, account, resolveDelegatedAddress(account.getCode())); + worldUpdater, account, resolveDelegatedAddress(account.getCode()), gasCalculator); } /** @@ -82,7 +91,7 @@ public class DelegatedCodeService { } return new MutableDelegatedCodeAccount( - worldUpdater, account, resolveDelegatedAddress(account.getCode())); + worldUpdater, account, resolveDelegatedAddress(account.getCode()), gasCalculator); } /** diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/EVMWorldUpdater.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/EVMWorldUpdater.java index 928118acfe..7911835eee 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/EVMWorldUpdater.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/EVMWorldUpdater.java @@ -19,6 +19,7 @@ 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 org.hyperledger.besu.evm.gascalculator.GasCalculator; import java.util.Collection; import java.util.Optional; @@ -35,9 +36,10 @@ public class EVMWorldUpdater implements WorldUpdater { * Instantiates a new EVM world updater. * * @param rootWorldUpdater the root world updater + * @param gasCalculator the gas calculator to check for precompiles. */ - public EVMWorldUpdater(final WorldUpdater rootWorldUpdater) { - this(rootWorldUpdater, new DelegatedCodeService()); + public EVMWorldUpdater(final WorldUpdater rootWorldUpdater, final GasCalculator gasCalculator) { + this(rootWorldUpdater, new DelegatedCodeService(gasCalculator)); } private EVMWorldUpdater(