From 955576b1a9c9e68085a5e03561973f4d4cac6cd6 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Mon, 29 Apr 2024 17:19:40 +0200 Subject: [PATCH] [SKIP_CI] fix getBalance and extCodesize operations refactor access witness code part Signed-off-by: Karim Taam --- .../besu/datatypes/AccessWitness.java | 4 - .../mainnet/MainnetTransactionProcessor.java | 4 +- .../eth/messages/GetBlockHeadersMessage.java | 2 +- .../java/org/hyperledger/besu/evm/EVM.java | 4 +- .../gascalculator/BerlinGasCalculator.java | 6 +- .../gascalculator/Eip4762GasCalculator.java | 52 ++++++++++--- .../gascalculator/FrontierGasCalculator.java | 11 +-- .../besu/evm/gascalculator/GasCalculator.java | 19 +++-- .../gascalculator/IstanbulGasCalculator.java | 3 +- .../TangerineWhistleGasCalculator.java | 5 +- .../stateless}/AccessEvents.java | 2 +- .../stateless/Eip4762AccessWitness.java | 29 ++------ .../stateless/NoopAccessWitness.java | 73 +++++++++++++++++++ .../besu/evm/operation/BalanceOperation.java | 23 ++++-- .../besu/evm/operation/CodeSizeOperation.java | 2 +- .../evm/operation/ExtCodeHashOperation.java | 17 +++-- .../evm/operation/ExtCodeSizeOperation.java | 22 ++++-- .../besu/evm/operation/PushOperation.java | 1 - 18 files changed, 193 insertions(+), 86 deletions(-) rename {ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core => evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless}/AccessEvents.java (96%) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java => evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java (93%) create mode 100644 evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/NoopAccessWitness.java diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java index f6a02698f74..ec99693681e 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java @@ -6,12 +6,8 @@ public interface AccessWitness { - void merge(AccessWitness other); - List
keys(); - AccessWitness copy(); - long touchAndChargeProofOfAbsence(Address address); long touchAndChargeValueTransfer(Address caller, Address target); 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 996c39982e5..d819a95b866 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 @@ -21,10 +21,10 @@ import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.AccessListEntry; +import org.hyperledger.besu.datatypes.AccessWitness; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.Blockchain; -import org.hyperledger.besu.ethereum.core.AccessWitness; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator; @@ -337,7 +337,7 @@ public TransactionProcessingResult processTransaction( if (warmCoinbase) { addressList.add(miningBeneficiary); } - final AccessWitness accessWitness = new AccessWitness(); + final AccessWitness accessWitness = gasCalculator.newAccessWitness(); final long intrinsicGas = gasCalculator.transactionIntrinsicGasCost( transaction.getPayload(), transaction.isContractCreation()); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/GetBlockHeadersMessage.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/GetBlockHeadersMessage.java index 0e5cd112a10..0f41b64560d 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/GetBlockHeadersMessage.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/GetBlockHeadersMessage.java @@ -171,7 +171,7 @@ public static GetBlockHeadersData create( public static GetBlockHeadersData create( final Hash hash, final int maxHeaders, final int skip, final boolean reverse) { - //System.out.println("create " + hash + " " + maxHeaders); + // System.out.println("create " + hash + " " + maxHeaders); return new GetBlockHeadersData( Optional.of(hash), OptionalLong.empty(), maxHeaders, skip, reverse); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java index 707aefcb7bb..7a6b9bc1a78 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.evm; import static com.google.common.base.Preconditions.checkNotNull; -import static org.hyperledger.besu.evm.operation.PushOperation.PUSH_BASE; import static org.hyperledger.besu.evm.operation.SwapOperation.SWAP_BASE; import org.hyperledger.besu.datatypes.Hash; @@ -53,7 +52,6 @@ import org.hyperledger.besu.evm.operation.OrOperation; import org.hyperledger.besu.evm.operation.PopOperation; import org.hyperledger.besu.evm.operation.Push0Operation; -import org.hyperledger.besu.evm.operation.PushOperation; import org.hyperledger.besu.evm.operation.SDivOperation; import org.hyperledger.besu.evm.operation.SGtOperation; import org.hyperledger.besu.evm.operation.SLtOperation; @@ -184,7 +182,6 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { var operationTracer = tracing == OperationTracer.NO_TRACING ? null : tracing; byte[] code = frame.getCode().getBytes().toArrayUnsafe(); - Operation[] operationArray = operations.getOperations(); while (frame.getState() == MessageFrame.State.CODE_EXECUTING) { Operation currentOperation; @@ -292,6 +289,7 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { } catch (final UnderflowException ue) { result = UNDERFLOW_RESPONSE; } + final ExceptionalHaltReason haltReason = result.getHaltReason(); if (haltReason != null) { LOG.trace("MessageFrame evaluation halted because of {}", haltReason); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java index 3aea7f690e2..89329fab880 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java @@ -120,7 +120,8 @@ public long getWarmStorageReadCost() { // Zeroed out old costs @Override - public long getBalanceOperationGasCost(final MessageFrame frame) { + public long getBalanceOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { return 0L; } @@ -136,7 +137,8 @@ public long extCodeHashOperationGasCost( } @Override - public long getExtCodeSizeOperationGasCost() { + public long getExtCodeSizeOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { return 0L; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip4762GasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip4762GasCalculator.java index 9a74fe0d905..28f81170e0e 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip4762GasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip4762GasCalculator.java @@ -29,6 +29,7 @@ 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.stateless.Eip4762AccessWitness; import java.util.List; import java.util.Optional; @@ -258,11 +259,15 @@ public long pushOperationGasCost( } @Override - public long getBalanceOperationGasCost(final MessageFrame frame) { - return frame - .getAccessWitness() - .touchAddressOnWriteAndComputeGas( - frame.getContractAddress(), UInt256.ZERO, BALANCE_LEAF_KEY); + public long getBalanceOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { + return maybeAddress + .map( + address -> + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, BALANCE_LEAF_KEY)) + .orElse(0L); } @Override @@ -277,6 +282,28 @@ public long extCodeHashOperationGasCost( .orElse(0L); } + @Override + public long getExtCodeSizeOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { + return maybeAddress + .map( + address -> { + long gasCost = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY); + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + return gasCost; + }) + .orElse(0L); + } + @Override public long selfDestructOperationGasCost( final MessageFrame frame, @@ -307,12 +334,10 @@ public long selfDestructOperationGasCost( public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key) { AccessWitness accessWitness = frame.getAccessWitness(); List treeIndexes = accessWitness.getStorageSlotTreeIndexes(key); - long gasCost = - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas( - frame.getContractAddress(), treeIndexes.get(0), treeIndexes.get(1)); - return gasCost; + return frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + frame.getContractAddress(), treeIndexes.get(0), treeIndexes.get(1)); } @Override @@ -342,4 +367,9 @@ public long completedCreateContractGasCost(final MessageFrame frame) { .getAccessWitness() .touchAndChargeContractCreateCompleted(frame.getContractAddress()); } + + @Override + public AccessWitness newAccessWitness() { + return new Eip4762AccessWitness(); + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java index e51e0344fb2..f1d2d8a0470 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java @@ -235,11 +235,6 @@ public long pushOperationGasCost( return getVeryLowTierGasCost(); } - @Override - public long extCodeSizeOperationGasCost(final MessageFrame frame) { - return getBaseTierGasCost(); - } - @SuppressWarnings("removal") @Override public long callOperationGasCost( @@ -410,7 +405,8 @@ public long memoryExpansionGasCost( } @Override - public long getBalanceOperationGasCost(final MessageFrame frame) { + public long getBalanceOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { return BALANCE_OPERATION_GAS_COST; } @@ -462,7 +458,8 @@ public long extCodeHashOperationGasCost( } @Override - public long getExtCodeSizeOperationGasCost() { + public long getExtCodeSizeOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { return extCodeBaseGasCost(); } 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 75975fca0da..d3dcb81f32e 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 @@ -22,6 +22,7 @@ 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.stateless.NoopAccessWitness; import org.hyperledger.besu.evm.operation.BalanceOperation; import org.hyperledger.besu.evm.operation.BlockHashOperation; import org.hyperledger.besu.evm.operation.ExpOperation; @@ -320,9 +321,6 @@ long codeCopyOperationGasCost( long pushOperationGasCost(MessageFrame frame, long codeOffset, long readSize, long codeSize); - - long extCodeSizeOperationGasCost(MessageFrame frame); - /** * Returns the cost of expanding memory for the specified access. * @@ -338,9 +336,11 @@ long codeCopyOperationGasCost( /** * Returns the cost for executing a {@link BalanceOperation}. * + * @param frame The current frame + * @param maybeAddress targeted address * @return the cost for executing the balance operation */ - long getBalanceOperationGasCost(MessageFrame frame); + long getBalanceOperationGasCost(MessageFrame frame, final Optional
maybeAddress); /** * Returns the cost for executing a {@link BlockHashOperation}. @@ -379,16 +379,20 @@ long extCodeCopyOperationGasCost( /** * Returns the cost for executing a {@link ExtCodeHashOperation}. * + * @param frame The current frame + * @param maybeAddress targeted address * @return the cost for executing the external code hash operation */ - long extCodeHashOperationGasCost(final MessageFrame frame, Optional
address); + long extCodeHashOperationGasCost(final MessageFrame frame, Optional
maybeAddress); /** * Returns the cost for executing a {@link ExtCodeSizeOperation}. * + * @param frame The current frame + * @param maybeAddress targeted address * @return the cost for executing the external code size operation */ - long getExtCodeSizeOperationGasCost(); + long getExtCodeSizeOperationGasCost(MessageFrame frame, Optional
maybeAddress); /** * Returns the cost for executing a {@link JumpDestOperation}. @@ -684,4 +688,7 @@ default long computeBaseAccessEventsCost( return 0L; } + default AccessWitness newAccessWitness() { + return new NoopAccessWitness(); + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java index fe42096a43f..cb71271d62c 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java @@ -130,7 +130,8 @@ public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key @Override // As per https://eips.ethereum.org/EIPS/eip-1884 - public long getBalanceOperationGasCost(final MessageFrame frame) { + public long getBalanceOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { return BALANCE_OPERATION_GAS_COST; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/TangerineWhistleGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/TangerineWhistleGasCalculator.java index 74623e41257..9559c351160 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/TangerineWhistleGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/TangerineWhistleGasCalculator.java @@ -22,6 +22,8 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.internal.Words; +import java.util.Optional; + import org.apache.tuweni.units.bigints.UInt256; /** The Tangerine whistle gas calculator. */ @@ -40,7 +42,8 @@ public class TangerineWhistleGasCalculator extends HomesteadGasCalculator { private static final long SLOAD_OPERATION_GAS_COST = 200L; @Override - public long getBalanceOperationGasCost(final MessageFrame frame) { + public long getBalanceOperationGasCost( + final MessageFrame frame, final Optional
maybeAddress) { return BALANCE_OPERATION_GAS_COST; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessEvents.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/AccessEvents.java similarity index 96% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessEvents.java rename to evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/AccessEvents.java index 76d27e1c492..7073c33a6ea 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessEvents.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/AccessEvents.java @@ -1,4 +1,4 @@ -package org.hyperledger.besu.ethereum.core; +package org.hyperledger.besu.evm.gascalculator.stateless; public class AccessEvents { private boolean branchRead; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java similarity index 93% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java rename to evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java index 4e01152a037..14b3b48b80f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java @@ -1,4 +1,4 @@ -package org.hyperledger.besu.ethereum.core; +package org.hyperledger.besu.evm.gascalculator.stateless; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.BALANCE_LEAF_KEY; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_KECCAK_LEAF_KEY; @@ -20,7 +20,7 @@ import org.apache.tuweni.units.bigints.UInt256; -public class AccessWitness implements org.hyperledger.besu.datatypes.AccessWitness { +public class Eip4762AccessWitness implements org.hyperledger.besu.datatypes.AccessWitness { private static final long WITNESS_BRANCH_READ_COST = 1900; private static final long WITNESS_CHUNK_READ_COST = 200; @@ -34,28 +34,16 @@ public class AccessWitness implements org.hyperledger.besu.datatypes.AccessWitne private final Map branches; private final Map chunks; - public AccessWitness() { + public Eip4762AccessWitness() { this(new HashMap<>(), new HashMap<>()); } - public AccessWitness( + public Eip4762AccessWitness( final Map branches, final Map chunks) { this.branches = branches; this.chunks = chunks; } - @Override - public void merge(final org.hyperledger.besu.datatypes.AccessWitness other) { - // TODO VERKLE - // for (BranchAccessKey k : other.getBranches.keySet()) { - // this.branches.put(k, (byte) (this.branches.get(k) | other.getBranches.get(k))); - // } - // for (Map.Entry entry : other.getChunks.entrySet()) { - // this.chunks.put(entry.getKey(), (byte) (this.chunks.get(entry.getKey()) | - // entry.getValue())); - // } - } - @Override public List
keys() { return this.chunks.keySet().stream() @@ -63,13 +51,6 @@ public List
keys() { .toList(); } - @Override - public AccessWitness copy() { - AccessWitness naw = new AccessWitness(); - naw.merge(this); - return naw; - } - @Override public long touchAndChargeProofOfAbsence(final Address address) { long gas = 0; @@ -359,7 +340,7 @@ public AccessEvents touchAddress( public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - AccessWitness that = (AccessWitness) o; + Eip4762AccessWitness that = (Eip4762AccessWitness) o; return Objects.equals(branches, that.branches) && Objects.equals(chunks, that.chunks); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/NoopAccessWitness.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/NoopAccessWitness.java new file mode 100644 index 00000000000..6f0f0453e77 --- /dev/null +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/NoopAccessWitness.java @@ -0,0 +1,73 @@ +package org.hyperledger.besu.evm.gascalculator.stateless; + +import org.hyperledger.besu.datatypes.Address; + +import org.apache.tuweni.units.bigints.UInt256; + +public class NoopAccessWitness extends Eip4762AccessWitness { + + @Override + public long touchAndChargeProofOfAbsence(final Address address) { + return 0; + } + + @Override + public long touchAndChargeValueTransfer(final Address caller, final Address target) { + return 0; + } + + @Override + public long touchAndChargeMessageCall(final Address address) { + return 0; + } + + @Override + public long touchTxOriginAndComputeGas(final Address origin) { + return 0; + } + + @Override + public long touchTxExistingAndComputeGas(final Address target, final boolean sendsValue) { + return 0; + } + + @Override + public long touchAndChargeContractCreateInit( + final Address address, final boolean createSendsValue) { + return 0; + } + + @Override + public long touchAndChargeContractCreateCompleted(final Address address) { + return 0; + } + + @Override + public long touchAddressOnWriteAndComputeGas( + final Address address, final UInt256 treeIndex, final UInt256 subIndex) { + return 0; + } + + @Override + public long touchAddressOnReadAndComputeGas( + final Address address, final UInt256 treeIndex, final UInt256 subIndex) { + return 0; + } + + @Override + public long touchCodeChunksUponContractCreation(final Address address, final long codeLength) { + return 0; + } + + @Override + public long touchCodeChunks( + final Address address, final long offset, final long readSize, final long codeLength) { + return 0; + } + + @Override + public long touchCodeChunksWithoutAccessCost( + final Address address, final long offset, final long readSize, final long codeLength) { + return 0; + } +} diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/BalanceOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/BalanceOperation.java index eaf3d07da11..08a04c8edb2 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/BalanceOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/BalanceOperation.java @@ -24,6 +24,8 @@ import org.hyperledger.besu.evm.internal.UnderflowException; import org.hyperledger.besu.evm.internal.Words; +import java.util.Optional; + import org.apache.tuweni.bytes.Bytes; /** The Balance operation. */ @@ -42,11 +44,13 @@ public BalanceOperation(final GasCalculator gasCalculator) { * Gets Balance operation Gas Cost plus warm storage read cost or cold account access cost. * * @param frame current frame + * @param maybeAddress to use for get balance * @param accountIsWarm true to add warm storage read cost, false to add cold account access cost * @return the long */ - protected long cost(final MessageFrame frame, final boolean accountIsWarm) { - return gasCalculator().getBalanceOperationGasCost(frame) + protected long cost( + final MessageFrame frame, final Optional
maybeAddress, final boolean accountIsWarm) { + return gasCalculator().getBalanceOperationGasCost(frame, maybeAddress) + (accountIsWarm ? gasCalculator().getWarmStorageReadCost() : gasCalculator().getColdAccountAccessCost()); @@ -54,11 +58,17 @@ protected long cost(final MessageFrame frame, final boolean accountIsWarm) { @Override public OperationResult execute(final MessageFrame frame, final EVM evm) { + final Address address; + try { + address = Words.toAddress(frame.popStackItem()); + } catch (final UnderflowException ufe) { + return new OperationResult( + cost(frame, Optional.empty(), true), ExceptionalHaltReason.INSUFFICIENT_STACK_ITEMS); + } try { - final Address address = Words.toAddress(frame.popStackItem()); final boolean accountIsWarm = frame.warmUpAddress(address) || gasCalculator().isPrecompile(address); - final long cost = cost(frame, accountIsWarm); + final long cost = cost(frame, Optional.of(address), accountIsWarm); if (frame.getRemainingGas() < cost) { return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS); } else { @@ -66,10 +76,9 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { frame.pushStackItem(account == null ? Bytes.EMPTY : account.getBalance()); return new OperationResult(cost, null); } - } catch (final UnderflowException ufe) { - return new OperationResult(cost(frame, true), ExceptionalHaltReason.INSUFFICIENT_STACK_ITEMS); } catch (final OverflowException ofe) { - return new OperationResult(cost(frame, true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS); + return new OperationResult( + cost(frame, Optional.of(address), true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS); } } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeSizeOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeSizeOperation.java index 8284b72ec52..690b5692f88 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeSizeOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeSizeOperation.java @@ -34,7 +34,7 @@ public CodeSizeOperation(final GasCalculator gasCalculator) { @Override public Operation.OperationResult executeFixedCostOperation( - final MessageFrame frame, final EVM evm) { + final MessageFrame frame, final EVM evm) { final Code code = frame.getCode(); frame.pushStackItem(Words.intBytes(code.getSize())); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java index 4beffc77802..e561fae6a3d 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java @@ -58,8 +58,16 @@ protected long cost( @Override public OperationResult execute(final MessageFrame frame, final EVM evm) { + final Address address; + try { + address = Words.toAddress(frame.popStackItem()); + } catch (final UnderflowException ufe) { + // TODO not sure about this case, we need to check what is the gas cost in case of underflow + // exception + return new OperationResult( + cost(frame, Optional.empty(), true), ExceptionalHaltReason.INSUFFICIENT_STACK_ITEMS); + } try { - final Address address = Words.toAddress(frame.popStackItem()); final boolean accountIsWarm = frame.warmUpAddress(address) || gasCalculator().isPrecompile(address); final long cost = cost(frame, Optional.of(address), accountIsWarm); @@ -74,16 +82,11 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { } return new OperationResult(cost, null); } - } catch (final UnderflowException ufe) { - // TODO not sure about this case, we need to check what is the gas cost in case of underflow - // exception - return new OperationResult( - cost(frame, Optional.empty(), true), ExceptionalHaltReason.INSUFFICIENT_STACK_ITEMS); } catch (final OverflowException ofe) { // TODO not sure about this case, we need to check what is the gas cost in case of overflow // exception return new OperationResult( - cost(frame, Optional.empty(), true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS); + cost(frame, Optional.of(address), true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS); } } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java index 9d891f7d37e..757f52cb00b 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java @@ -24,6 +24,8 @@ import org.hyperledger.besu.evm.internal.UnderflowException; import org.hyperledger.besu.evm.internal.Words; +import java.util.Optional; + import org.apache.tuweni.bytes.Bytes; /** The Ext code size operation. */ @@ -44,8 +46,9 @@ public ExtCodeSizeOperation(final GasCalculator gasCalculator) { * @param accountIsWarm the account is warm * @return the long */ - protected long cost(final boolean accountIsWarm) { - return gasCalculator().getExtCodeSizeOperationGasCost() + protected long cost( + final boolean accountIsWarm, final MessageFrame frame, final Optional
maybeAddress) { + return gasCalculator().getExtCodeSizeOperationGasCost(frame, maybeAddress) + (accountIsWarm ? gasCalculator().getWarmStorageReadCost() : gasCalculator().getColdAccountAccessCost()); @@ -53,11 +56,17 @@ protected long cost(final boolean accountIsWarm) { @Override public OperationResult execute(final MessageFrame frame, final EVM evm) { + final Address address; + try { + address = Words.toAddress(frame.popStackItem()); + } catch (final UnderflowException ufe) { + return new OperationResult( + cost(true, frame, Optional.empty()), ExceptionalHaltReason.INSUFFICIENT_STACK_ITEMS); + } try { - final Address address = Words.toAddress(frame.popStackItem()); final boolean accountIsWarm = frame.warmUpAddress(address) || gasCalculator().isPrecompile(address); - final long cost = cost(accountIsWarm); + final long cost = cost(accountIsWarm, frame, Optional.of(address)); if (frame.getRemainingGas() < cost) { return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS); } else { @@ -66,10 +75,9 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { account == null ? Bytes.EMPTY : Words.intBytes(account.getCode().size())); return new OperationResult(cost, null); } - } catch (final UnderflowException ufe) { - return new OperationResult(cost(true), ExceptionalHaltReason.INSUFFICIENT_STACK_ITEMS); } catch (final OverflowException ofe) { - return new OperationResult(cost(true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS); + return new OperationResult( + cost(true, frame, Optional.of(address)), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS); } } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/PushOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/PushOperation.java index 34d22e0ea73..e4f4e65ceee 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/PushOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/PushOperation.java @@ -47,7 +47,6 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { final byte[] code = frame.getCode().getBytes().toArrayUnsafe(); int pc = frame.getPC(); - int copyStart = pc + 1; long gasCost = gasCalculator().pushOperationGasCost(frame, copyStart, length, code.length);