From 8079f0fe9649712aa5d5cd3a7a1b0df9a6f8c625 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Fri, 19 Apr 2024 17:27:26 +0200 Subject: [PATCH 01/18] fix codecopy, call operation and code deployment issues Signed-off-by: Karim Taam --- .../merge/blockcreation/MergeCoordinator.java | 2 +- .../besu/datatypes/AccessWitness.java | 2 + .../besu/ethereum/core/AccessWitness.java | 21 ++++- .../gascalculator/BerlinGasCalculator.java | 9 ++- .../gascalculator/FrontierGasCalculator.java | 23 +++++- .../besu/evm/gascalculator/GasCalculator.java | 32 ++++++-- .../gascalculator/ShanghaiGasCalculator.java | 78 +++++++++++++++---- .../evm/operation/AbstractCallOperation.java | 1 + .../operation/AbstractCreateOperation.java | 1 + .../besu/evm/operation/CodeCopyOperation.java | 12 +-- .../evm/operation/ExtCodeCopyOperation.java | 30 ++++--- .../processor/ContractCreationProcessor.java | 3 +- 12 files changed, 167 insertions(+), 47 deletions(-) diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java index dde165e90a6..83b7d128ed4 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java @@ -637,7 +637,7 @@ && isDescendantOf(newHead, blockchain.getChainHeadHeader())) { return ForkchoiceResult.withResult(newFinalized, Optional.of(newHead)); } - private boolean setNewHead(final MutableBlockchain blockchain, final BlockHeader newHead) { + public boolean setNewHead(final MutableBlockchain blockchain, final BlockHeader newHead) { if (newHead.getHash().equals(blockchain.getChainHeadHash())) { LOG.atDebug() 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 8af88590113..8ea3db513b5 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java @@ -33,4 +33,6 @@ public interface AccessWitness { List getStorageSlotTreeIndexes(UInt256 storageKey); long touchCodeChunksUponContractCreation(Address address, long codeLength); + + long touchCodeChunks(Address address, long offset, long readSize, long codeLength); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java index ef78fcf0c18..ef223a317f1 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java @@ -177,8 +177,25 @@ public long touchCodeChunksUponContractCreation(final Address address, final lon gas += touchAddressOnWriteAndComputeGas( address, - CODE_OFFSET.subtract(i).divide(VERKLE_NODE_WIDTH), - CODE_OFFSET.subtract(i).mod(VERKLE_NODE_WIDTH)); + CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), + CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH)); + } + return gas; + } + + @Override + public long touchCodeChunks( + final Address address, final long offset, final long readSize, final long codeLength) { + long gas = 0; + if (readSize == 0 || codeLength == 0 || offset > codeLength) { + return 0; + } + for (long i = offset / 31; i <= (Math.min(offset + readSize, codeLength) - 1) / 31; i++) { + gas += + touchAddressOnReadAndComputeGas( + address, + CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), + CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH)); } return gas; } 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 7b17bde9a57..3aea7f690e2 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 @@ -203,8 +203,13 @@ public long callOperationGasCost( // defined in Frontier, but re-implemented with no base cost. @Override public long extCodeCopyOperationGasCost( - final MessageFrame frame, final long offset, final long length) { - return copyWordsToMemoryGasCost(frame, 0L, COPY_WORD_GAS_COST, offset, length); + final MessageFrame frame, + final Address address, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + return copyWordsToMemoryGasCost(frame, 0L, COPY_WORD_GAS_COST, memOffset, readSize); } // defined in Istanbul, but re-implemented with new constants 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 21817f62293..859d3856d31 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 @@ -376,9 +376,19 @@ public long gasAvailableForChildCreate(final long stipend) { @Override public long dataCopyOperationGasCost( - final MessageFrame frame, final long offset, final long length) { + final MessageFrame frame, final long offset, final long readSize) { return copyWordsToMemoryGasCost( - frame, VERY_LOW_TIER_GAS_COST, COPY_WORD_GAS_COST, offset, length); + frame, VERY_LOW_TIER_GAS_COST, COPY_WORD_GAS_COST, offset, readSize); + } + + @Override + public long codeCopyOperationGasCost( + final MessageFrame frame, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + return dataCopyOperationGasCost(frame, memOffset, readSize); } @Override @@ -428,9 +438,14 @@ protected long extCodeBaseGasCost() { @Override public long extCodeCopyOperationGasCost( - final MessageFrame frame, final long offset, final long length) { + final MessageFrame frame, + final Address address, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { return copyWordsToMemoryGasCost( - frame, extCodeBaseGasCost(), COPY_WORD_GAS_COST, offset, length); + frame, extCodeBaseGasCost(), COPY_WORD_GAS_COST, memOffset, readSize); } @Override 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 832c9d847c9..3ed7d79898b 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 @@ -297,10 +297,23 @@ long callOperationGasCost( * * @param frame The current frame * @param offset The offset in memory to copy the data to - * @param length The length of the data being copied into memory + * @param readSize The length of the data being copied into memory * @return the amount of gas consumed by the data copy operation */ - long dataCopyOperationGasCost(MessageFrame frame, long offset, long length); + long dataCopyOperationGasCost(MessageFrame frame, long offset, long readSize); + + /** + * Returns the amount of gas consumed by the code copy operation. + * + * @param frame The current frame + * @param memOffset The offset in memory to copy the code to + * @param codeOffset The starting offset within the code from which to begin copying + * @param readSize The length of the code being copied into memory + * @param codeSize The size of the code to copy + * @return the amount of gas consumed by the code copy operation + */ + long codeCopyOperationGasCost( + MessageFrame frame, long memOffset, long codeOffset, long readSize, final long codeSize); /** * Returns the cost of expanding memory for the specified access. @@ -340,11 +353,20 @@ long callOperationGasCost( * Returns the cost for executing a {@link ExtCodeCopyOperation}. * * @param frame The current frame - * @param offset The offset in memory to external code copy the data to - * @param length The length of the code being copied into memory + * @param address The address to use for the gas cost computation + * @param memOffset The offset in memory to external code copy the data to + * @param codeOffset The starting offset within the code from which to begin copying + * @param readSize The length of the code being copied into memory + * @param codeSize The size of the code to copy * @return the cost for executing the external code size operation */ - long extCodeCopyOperationGasCost(MessageFrame frame, long offset, long length); + long extCodeCopyOperationGasCost( + MessageFrame frame, + final Address address, + long memOffset, + long codeOffset, + long readSize, + final long codeSize); /** * Returns the cost for executing a {@link ExtCodeHashOperation}. diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java index 5616ca457e7..86c2ee033bc 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java @@ -16,6 +16,8 @@ */ 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; +import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; +import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import static org.hyperledger.besu.evm.internal.Words.numWords; @@ -103,12 +105,9 @@ public long completedCreateContractGasCost(final MessageFrame frame) { @Override public long codeDepositGasCost(final MessageFrame frame, final int codeSize) { - long cost = super.codeDepositGasCost(frame, codeSize); - return clampedAdd( - cost, - frame - .getAccessWitness() - .touchCodeChunksUponContractCreation(frame.getContractAddress(), codeSize)); + return frame + .getAccessWitness() + .touchCodeChunksUponContractCreation(frame.getContractAddress(), codeSize); } @SuppressWarnings("removal") @@ -135,6 +134,11 @@ public long initcodeCost(final int initCodeLength) { return numWords(initCodeLength) * INIT_CODE_COST; } + @Override + public long txCreateCost() { + return CREATE_OPERATION_GAS_COST; + } + @Override public long callOperationGasCost( final MessageFrame frame, @@ -200,10 +204,6 @@ public long calculateStorageCost( .getAccessWitness() .touchAddressOnWriteAndComputeGas( frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); - - if (gasCost == 0) { - gasCost = WARM_STORAGE_READ_COST; - } return gasCost; } @@ -216,9 +216,6 @@ public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key .getAccessWitness() .touchAddressOnReadAndComputeGas( frame.getContractAddress(), treeIndexes.get(0), treeIndexes.get(1)); - if (gasCost == 0) { - gasCost = WARM_STORAGE_READ_COST; - } return gasCost; } @@ -235,13 +232,64 @@ public long extCodeHashOperationGasCost( final MessageFrame frame, final Optional
maybeAddress) { return maybeAddress .map( - add -> + address -> frame .getAccessWitness() - .touchAddressOnReadAndComputeGas(add, UInt256.ZERO, CODE_KECCAK_LEAF_KEY)) + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_KECCAK_LEAF_KEY)) .orElse(0L); } + @Override + public long extCodeCopyOperationGasCost( + final MessageFrame frame, + final Address address, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + long gasCost = + super.extCodeCopyOperationGasCost( + frame, address, memOffset, codeOffset, readSize, codeSize); + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY)); + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + gasCost = + clampedAdd( + gasCost, + frame.getAccessWitness().touchCodeChunks(address, codeOffset, readSize, codeSize)); + } + return gasCost; + } + + @Override + public long codeCopyOperationGasCost( + final MessageFrame frame, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + long gasCost = super.dataCopyOperationGasCost(frame, memOffset, readSize); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); + } + return gasCost; + } + @Override public long calculateStorageRefundAmount( final UInt256 newValue, diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java index 3e038de65ef..f023786b2b9 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java @@ -210,6 +210,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { .value(value(frame)) .apparentValue(apparentValue(frame)) .code(code) + .accessWitness(frame.getAccessWitness()) .isStatic(isStatic(frame)) .completer(child -> complete(frame, child)) .build(); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java index 1cac2ceee86..f127862fb8b 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java @@ -173,6 +173,7 @@ private void spawnChildMessage(final MessageFrame parent, final Code code, final .value(value) .apparentValue(value) .code(code) + .accessWitness(parent.getAccessWitness()) .completer(child -> complete(parent, child, evm)) .build(); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeCopyOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeCopyOperation.java index f135880c2f4..25a937c7a54 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeCopyOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/CodeCopyOperation.java @@ -38,16 +38,18 @@ public CodeCopyOperation(final GasCalculator gasCalculator) { public OperationResult execute(final MessageFrame frame, final EVM evm) { final long memOffset = clampedToLong(frame.popStackItem()); final long sourceOffset = clampedToLong(frame.popStackItem()); - final long numBytes = clampedToLong(frame.popStackItem()); + final long readSize = clampedToLong(frame.popStackItem()); - final long cost = gasCalculator().dataCopyOperationGasCost(frame, memOffset, numBytes); + final Code code = frame.getCode(); + + final long cost = + gasCalculator() + .codeCopyOperationGasCost(frame, memOffset, sourceOffset, readSize, code.getSize()); if (frame.getRemainingGas() < cost) { return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS); } - final Code code = frame.getCode(); - - frame.writeMemory(memOffset, sourceOffset, numBytes, code.getBytes(), true); + frame.writeMemory(memOffset, sourceOffset, readSize, code.getBytes(), true); return new OperationResult(cost, null); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java index 7801b6d7d37..906b0cd6b52 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java @@ -43,18 +43,25 @@ public ExtCodeCopyOperation(final GasCalculator gasCalculator) { * Cost of Ext Code Copy operation. * * @param frame the frame + * @param address to use * @param memOffset the mem offset - * @param length the length + * @param sourceOffset the code offset + * @param codeSize the size of the code * @param accountIsWarm the account is warm * @return the long */ protected long cost( final MessageFrame frame, + final Address address, final long memOffset, - final long length, + final long sourceOffset, + final long readSize, + final long codeSize, final boolean accountIsWarm) { return clampedAdd( - gasCalculator().extCodeCopyOperationGasCost(frame, memOffset, length), + gasCalculator() + .extCodeCopyOperationGasCost( + frame, address, memOffset, sourceOffset, readSize, codeSize), accountIsWarm ? gasCalculator().getWarmStorageReadCost() : gasCalculator().getColdAccountAccessCost()); @@ -65,20 +72,21 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { final Address address = Words.toAddress(frame.popStackItem()); final long memOffset = clampedToLong(frame.popStackItem()); final long sourceOffset = clampedToLong(frame.popStackItem()); - final long numBytes = clampedToLong(frame.popStackItem()); + final long readSize = clampedToLong(frame.popStackItem()); - final boolean accountIsWarm = - frame.warmUpAddress(address) || gasCalculator().isPrecompile(address); - final long cost = cost(frame, memOffset, numBytes, accountIsWarm); + final boolean isPrecompiled = gasCalculator().isPrecompile(address); + final boolean accountIsWarm = frame.warmUpAddress(address) || isPrecompiled; + final Account account = frame.getWorldUpdater().get(address); + final Bytes code = account != null ? account.getCode() : Bytes.EMPTY; + + final long cost = + cost(frame, address, memOffset, sourceOffset, readSize, code.size(), accountIsWarm); if (frame.getRemainingGas() < cost) { return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS); } - final Account account = frame.getWorldUpdater().get(address); - final Bytes code = account != null ? account.getCode() : Bytes.EMPTY; - - frame.writeMemory(memOffset, sourceOffset, numBytes, code); + frame.writeMemory(memOffset, sourceOffset, readSize, code); return new OperationResult(cost, null); } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java index 67b20573571..480c7f103de 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java @@ -140,7 +140,6 @@ public void start(final MessageFrame frame, final OperationTracer operationTrace @Override public void codeSuccess(final MessageFrame frame, final OperationTracer operationTracer) { final Bytes contractCode = frame.getOutputData(); - final long depositFee = gasCalculator.codeDepositGasCost(frame, contractCode.size()); if (frame.getRemainingGas() < depositFee) { @@ -186,7 +185,7 @@ public void codeSuccess(final MessageFrame frame, final OperationTracer operatio final MutableAccount contract = frame.getWorldUpdater().getOrCreate(frame.getContractAddress()); contract.setCode(contractCode); - LOG.info( + LOG.trace( "Successful creation of contract {} with code of size {} (Gas remaining: {})", frame.getContractAddress(), contractCode.size(), From 80b8cd766980910184a21d8444dd0d44052d5670 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Mon, 22 Apr 2024 17:31:34 +0200 Subject: [PATCH 02/18] add push modification Signed-off-by: Karim Taam --- .../java/org/hyperledger/besu/evm/EVM.java | 35 +---------------- .../gascalculator/FrontierGasCalculator.java | 11 ++++++ .../besu/evm/gascalculator/GasCalculator.java | 6 +++ .../gascalculator/ShanghaiGasCalculator.java | 33 ++++++++++++++++ .../besu/evm/operation/CodeSizeOperation.java | 14 ++++--- .../evm/operation/ExtCodeSizeOperation.java | 1 + .../besu/evm/operation/PushOperation.java | 38 +++++-------------- .../processor/ContractCreationProcessor.java | 1 + 8 files changed, 72 insertions(+), 67 deletions(-) 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 ea490d9ff50..e440c6c9f96 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -228,46 +228,12 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { case 0x19 -> NotOperation.staticOperation(frame); case 0x1a -> ByteOperation.staticOperation(frame); case 0x50 -> PopOperation.staticOperation(frame); - case 0x56 -> JumpOperation.staticOperation(frame); case 0x57 -> JumpiOperation.staticOperation(frame); case 0x5b -> JumpDestOperation.JUMPDEST_SUCCESS; case 0x5f -> enableShanghai ? Push0Operation.staticOperation(frame) : InvalidOperation.INVALID_RESULT; - case 0x60, // PUSH1-32 - 0x61, - 0x62, - 0x63, - 0x64, - 0x65, - 0x66, - 0x67, - 0x68, - 0x69, - 0x6a, - 0x6b, - 0x6c, - 0x6d, - 0x6e, - 0x6f, - 0x70, - 0x71, - 0x72, - 0x73, - 0x74, - 0x75, - 0x76, - 0x77, - 0x78, - 0x79, - 0x7a, - 0x7b, - 0x7c, - 0x7d, - 0x7e, - 0x7f -> - PushOperation.staticOperation(frame, code, pc, opcode - PUSH_BASE); case 0x80, // DUP1-16 0x81, 0x82, @@ -312,6 +278,7 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { } catch (final UnderflowException ue) { result = UNDERFLOW_RESPONSE; } + System.out.println("operation "+currentOperation.getName()+" "+result.getGasCost()+" "+frame.getRemainingGas()); 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/FrontierGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java index 859d3856d31..c174d5d48db 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 @@ -229,6 +229,17 @@ long newAccountGasCost() { return NEW_ACCOUNT_GAS_COST; } + @Override + public long pushOperationGasCost( + final MessageFrame frame, final long codeOffset, final long readSize, final long codeSize) { + return getVeryLowTierGasCost(); + } + + @Override + public long extCodeSizeOperationGasCost(final MessageFrame frame) { + return getBaseTierGasCost(); + } + @SuppressWarnings("removal") @Override public long callOperationGasCost( 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 3ed7d79898b..56d98760c36 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 @@ -315,6 +315,11 @@ long callOperationGasCost( long codeCopyOperationGasCost( MessageFrame frame, long memOffset, long codeOffset, long readSize, final long codeSize); + long pushOperationGasCost(MessageFrame frame, long codeOffset, long readSize, long codeSize); + + + long extCodeSizeOperationGasCost(MessageFrame frame); + /** * Returns the cost of expanding memory for the specified access. * @@ -675,4 +680,5 @@ default long computeBaseAccessEventsCost( final MutableAccount sender) { return 0L; } + } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java index 86c2ee033bc..cdaa29a33a3 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java @@ -290,6 +290,39 @@ public long codeCopyOperationGasCost( return gasCost; } + @Override + public long pushOperationGasCost( + final MessageFrame frame, final long codeOffset, final long readSize, final long codeSize) { + long gasCost = super.pushOperationGasCost(frame, codeOffset, readSize, codeSize); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); + System.out.println("push "+isPrecompile(frame.getContractAddress())+" "+frame.getContractAddress()+" "+codeOffset+" "+readSize+" "+codeSize+" "+gasCost); + } + return gasCost; + } + + @Override + public long extCodeSizeOperationGasCost(final MessageFrame frame) { + if(!isPrecompile(frame.getContractAddress())) { + long gasCost = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(frame.getContractAddress(), UInt256.ZERO, VERSION_LEAF_KEY); + return + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(frame.getContractAddress(), UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + } + return 0; + } + @Override public long calculateStorageRefundAmount( final UInt256 newValue, 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 690b5692f88..3c1d0de7dfc 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 @@ -21,7 +21,7 @@ import org.hyperledger.besu.evm.internal.Words; /** The Code size operation. */ -public class CodeSizeOperation extends AbstractFixedCostOperation { +public class CodeSizeOperation extends AbstractOperation { /** * Instantiates a new Code size operation. @@ -29,15 +29,19 @@ public class CodeSizeOperation extends AbstractFixedCostOperation { * @param gasCalculator the gas calculator */ public CodeSizeOperation(final GasCalculator gasCalculator) { - super(0x38, "CODESIZE", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost()); + super(0x38, "CODESIZE", 0, 1, gasCalculator); } + protected long cost(final MessageFrame frame) { + return gasCalculator().extCodeSizeOperationGasCost(frame); + } + + @Override - public Operation.OperationResult executeFixedCostOperation( + public Operation.OperationResult execute( final MessageFrame frame, final EVM evm) { final Code code = frame.getCode(); frame.pushStackItem(Words.intBytes(code.getSize())); - - return successResponse; + return new OperationResult(cost(frame),null); } } 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..81cde5ca799 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 @@ -64,6 +64,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { final Account account = frame.getWorldUpdater().get(address); frame.pushStackItem( account == null ? Bytes.EMPTY : Words.intBytes(account.getCode().size())); + System.out.println("code size "+gasCalculator().isPrecompile(address)); return new OperationResult(cost, null); } } catch (final UnderflowException ufe) { 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 006956207b3..34d22e0ea73 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 @@ -21,7 +21,7 @@ import org.apache.tuweni.bytes.Bytes; /** The Push operation. */ -public class PushOperation extends AbstractFixedCostOperation { +public class PushOperation extends AbstractOperation { /** The constant PUSH_BASE. */ public static final int PUSH_BASE = 0x5F; @@ -31,9 +31,6 @@ public class PushOperation extends AbstractFixedCostOperation { private final int length; - /** The Push operation success result. */ - static final OperationResult pushSuccess = new OperationResult(3, null); - /** * Instantiates a new Push operation. * @@ -41,43 +38,28 @@ public class PushOperation extends AbstractFixedCostOperation { * @param gasCalculator the gas calculator */ public PushOperation(final int length, final GasCalculator gasCalculator) { - super( - PUSH_BASE + length, - "PUSH" + length, - 0, - 1, - gasCalculator, - gasCalculator.getVeryLowTierGasCost()); + super(PUSH_BASE + length, "PUSH" + length, 0, 1, gasCalculator); this.length = length; } @Override - public OperationResult executeFixedCostOperation(final MessageFrame frame, final EVM evm) { + public OperationResult execute(final MessageFrame frame, final EVM evm) { final byte[] code = frame.getCode().getBytes().toArrayUnsafe(); - return staticOperation(frame, code, frame.getPC(), length); - } + int pc = frame.getPC(); + - /** - * Performs Push operation. - * - * @param frame the frame - * @param code the code - * @param pc the pc - * @param pushSize the push size - * @return the operation result - */ - public static OperationResult staticOperation( - final MessageFrame frame, final byte[] code, final int pc, final int pushSize) { int copyStart = pc + 1; + + long gasCost = gasCalculator().pushOperationGasCost(frame, copyStart, length, code.length); Bytes push; if (code.length <= copyStart) { push = Bytes.EMPTY; } else { - final int copyLength = Math.min(pushSize, code.length - pc - 1); + final int copyLength = Math.min(length, code.length - pc - 1); push = Bytes.wrap(code, copyStart, copyLength); } frame.pushStackItem(push); - frame.setPC(pc + pushSize); - return pushSuccess; + frame.setPC(pc + length); + return new OperationResult(gasCost, null); } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java index 480c7f103de..53a44041e26 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java @@ -107,6 +107,7 @@ public void start(final MessageFrame frame, final OperationTracer operationTrace LOG.trace("Executing contract-creation"); } try { + System.out.println("start contract creation "); final MutableAccount sender = frame.getWorldUpdater().getSenderAccount(frame); sender.decrementBalance(frame.getValue()); From 229b867c95abdccb1b61b486733b1db99289bd71 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Tue, 23 Apr 2024 17:59:19 +0200 Subject: [PATCH 03/18] gas cost modification Signed-off-by: Karim Taam --- .../besu/ethereum/core/AccessWitness.java | 19 +++++--- .../mainnet/MainnetTransactionProcessor.java | 8 ++-- .../java/org/hyperledger/besu/evm/EVM.java | 7 ++- .../gascalculator/PragueGasCalculator.java | 2 +- .../gascalculator/ShanghaiGasCalculator.java | 43 ++++++++----------- 5 files changed, 43 insertions(+), 36 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java index ef223a317f1..e0affe66e8a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java @@ -9,6 +9,7 @@ import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.NONCE_LEAF_KEY; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERKLE_NODE_WIDTH; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; +import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import org.hyperledger.besu.datatypes.Address; @@ -114,7 +115,6 @@ public long touchAndChargeContractCreateInit( if (createSendsValue) { gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY); } - return gas; } @@ -185,17 +185,24 @@ public long touchCodeChunksUponContractCreation(final Address address, final lon @Override public long touchCodeChunks( - final Address address, final long offset, final long readSize, final long codeLength) { + final Address address, final long startPc, final long readSize, final long codeLength) { long gas = 0; - if (readSize == 0 || codeLength == 0 || offset > codeLength) { + if ((readSize == 0 && codeLength == 0) || startPc > codeLength) { return 0; } - for (long i = offset / 31; i <= (Math.min(offset + readSize, codeLength) - 1) / 31; i++) { - gas += + long endPc = startPc+readSize; + if(endPc>codeLength){ + endPc = codeLength; + } + if(endPc>0){ + endPc-=1; + } + for (long i = startPc / 31; i <= endPc/31; i++) { + gas = clampedAdd(gas, touchAddressOnReadAndComputeGas( address, CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), - CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH)); + CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH))); } return gas; } 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 8c503221e36..996c39982e5 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 @@ -462,11 +462,11 @@ public TransactionProcessingResult processTransaction( final Wei balancePriorToRefund = sender.getBalance(); sender.incrementBalance(refundedWei); LOG.atTrace() - .setMessage("refunded sender {} {} wei ({} -> {})") + .setMessage("refunded sender {} {} wei (balance before:{} -> after:{})") .addArgument(senderAddress) - .addArgument(refundedWei) - .addArgument(balancePriorToRefund) - .addArgument(sender.getBalance()) + .addArgument(refundedWei.toShortHexString()) + .addArgument(balancePriorToRefund.toShortHexString()) + .addArgument(sender.getBalance().toShortHexString()) .log(); final long gasUsedByTransaction = transaction.getGasLimit() - initialFrame.getRemainingGas(); LOG.info( 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 e440c6c9f96..1b061e89c8a 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -183,11 +183,17 @@ 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; int opcode; int pc = frame.getPC(); + + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + frame.getAccessWitness().touchCodeChunks(frame.getContractAddress(), pc, 1, code.length); + } try { opcode = code[pc] & 0xff; currentOperation = operationArray[opcode]; @@ -278,7 +284,6 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { } catch (final UnderflowException ue) { result = UNDERFLOW_RESPONSE; } - System.out.println("operation "+currentOperation.getName()+" "+result.getGasCost()+" "+frame.getRemainingGas()); 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/PragueGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java index a48085f4263..6f2839f265a 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 @@ -26,7 +26,7 @@ *
  • TBD * */ -public class PragueGasCalculator extends CancunGasCalculator { +public class PragueGasCalculator extends ShanghaiGasCalculator { /** Instantiates a new Prague Gas Calculator. */ public PragueGasCalculator() { diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java index cdaa29a33a3..4eeb3fb8fb5 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java @@ -295,32 +295,27 @@ public long pushOperationGasCost( final MessageFrame frame, final long codeOffset, final long readSize, final long codeSize) { long gasCost = super.pushOperationGasCost(frame, codeOffset, readSize, codeSize); if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); - System.out.println("push "+isPrecompile(frame.getContractAddress())+" "+frame.getContractAddress()+" "+codeOffset+" "+readSize+" "+codeSize+" "+gasCost); - } - return gasCost; - } + if(readSize==1){ + if( (codeOffset%31==0)){ + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset+1, readSize, codeSize)); + + } + } else { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); - @Override - public long extCodeSizeOperationGasCost(final MessageFrame frame) { - if(!isPrecompile(frame.getContractAddress())) { - long gasCost = - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(frame.getContractAddress(), UInt256.ZERO, VERSION_LEAF_KEY); - return - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(frame.getContractAddress(), UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + } } - return 0; + return gasCost; } @Override From dd893219ef5c602ad02d0077e56d703cbdd893fa Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Tue, 23 Apr 2024 18:30:27 +0200 Subject: [PATCH 04/18] clean gas cost modification Signed-off-by: Karim Taam --- .../main/java/org/hyperledger/besu/evm/EVM.java | 1 + .../besu/evm/operation/CodeSizeOperation.java | 16 ++++++---------- 2 files changed, 7 insertions(+), 10 deletions(-) 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 1b061e89c8a..e42eb7f632a 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -234,6 +234,7 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { case 0x19 -> NotOperation.staticOperation(frame); case 0x1a -> ByteOperation.staticOperation(frame); case 0x50 -> PopOperation.staticOperation(frame); + case 0x56 -> JumpOperation.staticOperation(frame); case 0x57 -> JumpiOperation.staticOperation(frame); case 0x5b -> JumpDestOperation.JUMPDEST_SUCCESS; case 0x5f -> 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 3c1d0de7dfc..8284b72ec52 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 @@ -21,7 +21,7 @@ import org.hyperledger.besu.evm.internal.Words; /** The Code size operation. */ -public class CodeSizeOperation extends AbstractOperation { +public class CodeSizeOperation extends AbstractFixedCostOperation { /** * Instantiates a new Code size operation. @@ -29,19 +29,15 @@ public class CodeSizeOperation extends AbstractOperation { * @param gasCalculator the gas calculator */ public CodeSizeOperation(final GasCalculator gasCalculator) { - super(0x38, "CODESIZE", 0, 1, gasCalculator); + super(0x38, "CODESIZE", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost()); } - protected long cost(final MessageFrame frame) { - return gasCalculator().extCodeSizeOperationGasCost(frame); - } - - @Override - public Operation.OperationResult execute( - final MessageFrame frame, final EVM evm) { + public Operation.OperationResult executeFixedCostOperation( + final MessageFrame frame, final EVM evm) { final Code code = frame.getCode(); frame.pushStackItem(Words.intBytes(code.getSize())); - return new OperationResult(cost(frame),null); + + return successResponse; } } From 852ace4c3fb38f450f1b0059beb6fb0f6e69099c Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 23 Apr 2024 17:35:59 -0700 Subject: [PATCH 05/18] call value transfer cost fix, added non-accumulating method for touchCodeChunks Signed-off-by: garyschulte --- .../besu/datatypes/AccessWitness.java | 5 +++++ .../besu/ethereum/core/AccessWitness.java | 22 ++++++++++--------- .../gascalculator/ShanghaiGasCalculator.java | 2 +- 3 files changed, 18 insertions(+), 11 deletions(-) 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 8ea3db513b5..f6a02698f74 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccessWitness.java @@ -35,4 +35,9 @@ public interface AccessWitness { long touchCodeChunksUponContractCreation(Address address, long codeLength); long touchCodeChunks(Address address, long offset, long readSize, long codeLength); + + default long touchCodeChunksWithoutAccessCost( + final Address address, final long offset, final long readSize, final long codeLength) { + return touchCodeChunks(address, offset, readSize, codeLength); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java index e0affe66e8a..4e01152a037 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AccessWitness.java @@ -190,19 +190,21 @@ public long touchCodeChunks( if ((readSize == 0 && codeLength == 0) || startPc > codeLength) { return 0; } - long endPc = startPc+readSize; - if(endPc>codeLength){ + long endPc = startPc + readSize; + if (endPc > codeLength) { endPc = codeLength; } - if(endPc>0){ - endPc-=1; + if (endPc > 0) { + endPc -= 1; } - for (long i = startPc / 31; i <= endPc/31; i++) { - gas = clampedAdd(gas, - touchAddressOnReadAndComputeGas( - address, - CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), - CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH))); + for (long i = startPc / 31; i <= endPc / 31; i++) { + gas = + clampedAdd( + gas, + touchAddressOnReadAndComputeGas( + address, + CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), + CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH))); } return gas; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java index 4eeb3fb8fb5..86e461675f6 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java @@ -174,7 +174,7 @@ public long callOperationGasCost( if (!transferValue.isZero()) { cost = clampedAdd( - baseCost, + cost, frame.getAccessWitness().touchAndChargeValueTransfer(recipient.getAddress(), to)); } return cost; From 478a62b7e2cc6fe5cb2826ded444cd0359ab11d5 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Wed, 24 Apr 2024 14:29:40 -0700 Subject: [PATCH 06/18] karim's recent logging and gas changes Signed-off-by: garyschulte --- evm/src/main/java/org/hyperledger/besu/evm/EVM.java | 7 ++++++- .../besu/evm/processor/ContractCreationProcessor.java | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) 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 e42eb7f632a..e98beaa3f9c 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -191,8 +191,13 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { int opcode; int pc = frame.getPC(); + long statelessGas = 0; if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - frame.getAccessWitness().touchCodeChunks(frame.getContractAddress(), pc, 1, code.length); + statelessGas = + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), pc, 1, code.length); + frame.decrementRemainingGas(statelessGas); } try { opcode = code[pc] & 0xff; diff --git a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java index 53a44041e26..2888f881aa9 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java @@ -142,7 +142,10 @@ public void start(final MessageFrame frame, final OperationTracer operationTrace public void codeSuccess(final MessageFrame frame, final OperationTracer operationTracer) { final Bytes contractCode = frame.getOutputData(); final long depositFee = gasCalculator.codeDepositGasCost(frame, contractCode.size()); - + System.out.println( + String.format( + "opcode CREATE deposit fee %d codeSize %d frame codeSize %d pc %d", + depositFee, contractCode.size(), frame.getCode().getSize(), frame.getPC())); if (frame.getRemainingGas() < depositFee) { LOG.trace( "Not enough gas to pay the code deposit fee for {}: " @@ -170,7 +173,7 @@ public void codeSuccess(final MessageFrame frame, final OperationTracer operatio final long statelessContractCompletionFee = gasCalculator.completedCreateContractGasCost(frame); - + System.out.println("opcode CREATE completion " + statelessContractCompletionFee); if (frame.getRemainingGas() < statelessContractCompletionFee) { LOG.trace( "Not enough gas to pay the contract creation completion fee for {}: " From f6141535e74d3094a1538e9729a05cc533e7c921 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Thu, 25 Apr 2024 17:05:12 -0700 Subject: [PATCH 07/18] karim's create gas cost fixes Signed-off-by: garyschulte --- .../gascalculator/FrontierGasCalculator.java | 5 -- .../besu/evm/gascalculator/GasCalculator.java | 7 +- .../gascalculator/PragueGasCalculator.java | 58 +++++++++++++ .../gascalculator/ShanghaiGasCalculator.java | 83 ------------------- .../operation/AbstractCreateOperation.java | 23 +++-- .../besu/evm/operation/Create2Operation.java | 7 ++ .../besu/evm/operation/CreateOperation.java | 7 ++ .../besu/evm/operation/SStoreOperation.java | 2 +- .../processor/ContractCreationProcessor.java | 2 - .../AbstractCreateOperationTest.java | 6 ++ 10 files changed, 100 insertions(+), 100 deletions(-) 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 c174d5d48db..e51e0344fb2 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 @@ -317,11 +317,6 @@ public long gasAvailableForChildCall( } } - @Override - public long initCreateContractGasCost(final MessageFrame frame) { - return 0; - } - @Override public long completedCreateContractGasCost(final MessageFrame frame) { return 0; 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 56d98760c36..75975fca0da 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 @@ -231,8 +231,6 @@ long callOperationGasCost( */ long gasAvailableForChildCall(MessageFrame frame, long stipend, boolean transfersValue); - long initCreateContractGasCost(MessageFrame frame); - long completedCreateContractGasCost(final MessageFrame frame); /** @@ -282,6 +280,11 @@ long callOperationGasCost( */ long initcodeCost(final int initCodeLength); + default long initcodeStatelessCost( + final MessageFrame frame, final Address address, final Wei value) { + return 0; + } + /** * Returns the amount of gas parent will provide its child CREATE. * 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 6f2839f265a..0da8184b9f4 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 @@ -15,6 +15,12 @@ package org.hyperledger.besu.evm.gascalculator; import static org.hyperledger.besu.datatypes.Address.KZG_POINT_EVAL; +import static org.hyperledger.besu.evm.internal.Words.clampedAdd; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.frame.MessageFrame; /** * Gas Calculator for Prague @@ -27,6 +33,7 @@ * */ public class PragueGasCalculator extends ShanghaiGasCalculator { + private static final long CREATE_OPERATION_GAS_COST = 1_000L; /** Instantiates a new Prague Gas Calculator. */ public PragueGasCalculator() { @@ -51,4 +58,55 @@ public long getColdSloadCost() { public long getColdAccountAccessCost() { return 0; // no cold gas cost after verkle } + + @Override + public long initcodeCost(final int initCodeLength) { + return super.initcodeCost(initCodeLength); + } + + @Override + public long callOperationGasCost( + final MessageFrame frame, + final long stipend, + final long inputDataOffset, + final long inputDataLength, + final long outputDataOffset, + final long outputDataLength, + final Wei transferValue, + final Account recipient, + final Address to, + final boolean accountIsWarm) { + + long cost = + super.callOperationGasCost( + frame, + stipend, + inputDataOffset, + inputDataLength, + outputDataOffset, + outputDataLength, + transferValue, + recipient, + to, + true); + if (!super.isPrecompile(to)) { + if (frame.getWorldUpdater().get(to) == null) { + cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeProofOfAbsence(to)); + } else { + cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeMessageCall(to)); + } + if (!transferValue.isZero()) { + cost = + clampedAdd( + cost, + frame.getAccessWitness().touchAndChargeValueTransfer(recipient.getAddress(), to)); + } + } + return cost; + } + + @Override + public long txCreateCost() { + return CREATE_OPERATION_GAS_COST; + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java index 86e461675f6..d81b9a1090a 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java @@ -19,7 +19,6 @@ import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; -import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import static org.hyperledger.besu.evm.internal.Words.numWords; import org.hyperledger.besu.datatypes.AccessWitness; @@ -42,8 +41,6 @@ public class ShanghaiGasCalculator extends LondonGasCalculator { private static final long INIT_CODE_COST = 2L; - private static final long CREATE_OPERATION_GAS_COST = 1_000L; - /** * Instantiates a new ShanghaiGasCalculator * @@ -89,13 +86,6 @@ public long computeBaseAccessEventsCost( return cost; } - @Override - public long initCreateContractGasCost(final MessageFrame frame) { - return frame - .getAccessWitness() - .touchAndChargeContractCreateInit(frame.getContractAddress(), !frame.getValue().isZero()); - } - @Override public long completedCreateContractGasCost(final MessageFrame frame) { return frame @@ -110,76 +100,11 @@ public long codeDepositGasCost(final MessageFrame frame, final int codeSize) { .touchCodeChunksUponContractCreation(frame.getContractAddress(), codeSize); } - @SuppressWarnings("removal") - @Override - @Deprecated(since = "24.4.1", forRemoval = true) - public long createOperationGasCost(final MessageFrame frame) { - - final long initCodeOffset = clampedToLong(frame.getStackItem(1)); - final long initCodeLength = clampedToLong(frame.getStackItem(2)); - - final long memoryGasCost = memoryExpansionGasCost(frame, initCodeOffset, initCodeLength); - long gasCost = clampedAdd(CREATE_OPERATION_GAS_COST, memoryGasCost); - - return clampedAdd(gasCost, calculateInitGasCost(initCodeLength)); - } - - private static long calculateInitGasCost(final long initCodeLength) { - final int dataLength = (int) Math.ceil(initCodeLength / 32.0); - return dataLength * INIT_CODE_COST; - } - @Override public long initcodeCost(final int initCodeLength) { return numWords(initCodeLength) * INIT_CODE_COST; } - @Override - public long txCreateCost() { - return CREATE_OPERATION_GAS_COST; - } - - @Override - public long callOperationGasCost( - final MessageFrame frame, - final long stipend, - final long inputDataOffset, - final long inputDataLength, - final long outputDataOffset, - final long outputDataLength, - final Wei transferValue, - final Account recipient, - final Address to) { - - final long baseCost = - super.callOperationGasCost( - frame, - stipend, - inputDataOffset, - inputDataLength, - outputDataOffset, - outputDataLength, - transferValue, - recipient, - to); - long cost = baseCost; - if (frame.getWorldUpdater().get(to) == null) { - cost = clampedAdd(baseCost, frame.getAccessWitness().touchAndChargeProofOfAbsence(to)); - } else { - if (!super.isPrecompile(to)) { - cost = clampedAdd(baseCost, frame.getAccessWitness().touchAndChargeMessageCall(to)); - } - } - - if (!transferValue.isZero()) { - cost = - clampedAdd( - cost, - frame.getAccessWitness().touchAndChargeValueTransfer(recipient.getAddress(), to)); - } - return cost; - } - @Override public long calculateStorageCost( final MessageFrame frame, @@ -318,14 +243,6 @@ public long pushOperationGasCost( return gasCost; } - @Override - public long calculateStorageRefundAmount( - final UInt256 newValue, - final Supplier currentValue, - final Supplier originalValue) { - return 0L; - } - @Override public long selfDestructOperationGasCost( final MessageFrame frame, diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java index f127862fb8b..e0c96c2a1e6 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java @@ -105,9 +105,13 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { // addresses disk loading delay, and we already have the code. Code code = evm.getCodeUncached(inputData); + final Address contractAddress = targetContractAddress(frame, code); + final Wei contractValue = Wei.wrap(frame.getStackItem(0)); + if (code.isValid() && frame.getCode().getEofVersion() <= code.getEofVersion()) { + frame.decrementRemainingGas(statelessCost(frame, contractAddress, contractValue)); frame.decrementRemainingGas(cost); - spawnChildMessage(frame, code, evm); + spawnChildMessage(frame, contractAddress, contractValue, code, evm); frame.incrementRemainingGas(cost); } else { fail(frame); @@ -126,6 +130,9 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { */ protected abstract long cost(final MessageFrame frame, Supplier codeSupplier); + protected abstract long statelessCost( + final MessageFrame frame, final Address contractAddress, final Wei value); + /** * Target contract address. * @@ -152,10 +159,12 @@ private void fail(final MessageFrame frame) { frame.pushStackItem(FAILURE_STACK_ITEM); } - private void spawnChildMessage(final MessageFrame parent, final Code code, final EVM evm) { - final Wei value = Wei.wrap(parent.getStackItem(0)); - - final Address contractAddress = targetContractAddress(parent, code); + private void spawnChildMessage( + final MessageFrame parent, + final Address contractAddress, + final Wei contractValue, + final Code code, + final EVM evm) { final long childGasStipend = gasCalculator().gasAvailableForChildCreate(parent.getRemainingGas()); @@ -170,8 +179,8 @@ private void spawnChildMessage(final MessageFrame parent, final Code code, final .contract(contractAddress) .inputData(Bytes.EMPTY) .sender(parent.getRecipientAddress()) - .value(value) - .apparentValue(value) + .value(contractValue) + .apparentValue(contractValue) .code(code) .accessWitness(parent.getAccessWitness()) .completer(child -> complete(parent, child, evm)) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/Create2Operation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/Create2Operation.java index bdf7172f363..374ce72e0d0 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/Create2Operation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/Create2Operation.java @@ -20,6 +20,7 @@ import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -57,6 +58,12 @@ public long cost(final MessageFrame frame, final Supplier unused) { gasCalculator().createKeccakCost(inputSize), gasCalculator().initcodeCost(inputSize))); } + @Override + protected long statelessCost( + final MessageFrame frame, final Address contractAddress, final Wei value) { + return gasCalculator().initcodeStatelessCost(frame, contractAddress, value); + } + @Override public Address targetContractAddress(final MessageFrame frame, final Code initcode) { final Address sender = frame.getRecipientAddress(); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/CreateOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/CreateOperation.java index c0332f378c6..2a47e9a3940 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/CreateOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/CreateOperation.java @@ -19,6 +19,7 @@ import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.account.Account; @@ -53,6 +54,12 @@ public long cost(final MessageFrame frame, final Supplier unused) { gasCalculator().initcodeCost(inputSize)); } + @Override + protected long statelessCost( + final MessageFrame frame, final Address contractAddress, final Wei value) { + return gasCalculator().initcodeStatelessCost(frame, contractAddress, value); + } + @Override protected Address targetContractAddress(final MessageFrame frame, final Code initcode) { final Account sender = frame.getWorldUpdater().get(frame.getRecipientAddress()); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java index fefdc7b9f17..9c877c5bf97 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java @@ -84,7 +84,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { .calculateStorageCost( frame, key, newValue, currentValueSupplier, originalValueSupplier) + (slotIsWarm ? 0L : gasCalculator().getColdSloadCost()); - + System.out.println("=> sstore gas cost: " + cost); final long remainingGas = frame.getRemainingGas(); if (frame.isStatic()) { return new OperationResult(remainingGas, ExceptionalHaltReason.ILLEGAL_STATE_CHANGE); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java index 2888f881aa9..f256ee43290 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java @@ -113,8 +113,6 @@ public void start(final MessageFrame frame, final OperationTracer operationTrace Address contractAddress = frame.getContractAddress(); - frame.decrementRemainingGas(gasCalculator.initCreateContractGasCost(frame)); - final MutableAccount contract = frame.getWorldUpdater().getOrCreate(contractAddress); if (accountExists(contract)) { LOG.trace( diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java index a471c45b010..4fd3cd130c2 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java @@ -119,6 +119,12 @@ public long cost(final MessageFrame frame, final Supplier unused) { gasCalculator().initcodeCost(inputSize)); } + @Override + protected long statelessCost( + final MessageFrame frame, final Address contractAddress, final Wei value) { + return gasCalculator().initcodeStatelessCost(frame, contractAddress, value); + } + @Override protected Address targetContractAddress(final MessageFrame frame, final Code initcode) { final Account sender = frame.getWorldUpdater().get(frame.getRecipientAddress()); From 57797fd4843773d8a47406ac7958bc895ef0926b Mon Sep 17 00:00:00 2001 From: garyschulte Date: Fri, 26 Apr 2024 10:42:48 -0700 Subject: [PATCH 08/18] consolidate changes into PragueGasCalculator Signed-off-by: garyschulte --- .../java/org/hyperledger/besu/evm/EVM.java | 16 +- .../gascalculator/PragueGasCalculator.java | 272 ++++++++++++++++++ .../gascalculator/ShanghaiGasCalculator.java | 216 -------------- 3 files changed, 281 insertions(+), 223 deletions(-) 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 e98beaa3f9c..707aefcb7bb 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -192,16 +192,18 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) { int pc = frame.getPC(); long statelessGas = 0; - if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - statelessGas = - frame - .getAccessWitness() - .touchCodeChunks(frame.getContractAddress(), pc, 1, code.length); - frame.decrementRemainingGas(statelessGas); - } try { opcode = code[pc] & 0xff; currentOperation = operationArray[opcode]; + + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + statelessGas = + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), pc, 1, code.length); + frame.decrementRemainingGas(statelessGas); + } + } catch (ArrayIndexOutOfBoundsException aiiobe) { opcode = 0; currentOperation = endOfScriptStop; 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 0da8184b9f4..49d546a8fc5 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 @@ -15,13 +15,27 @@ package org.hyperledger.besu.evm.gascalculator; import static org.hyperledger.besu.datatypes.Address.KZG_POINT_EVAL; +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; +import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; +import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; +import static org.hyperledger.besu.evm.internal.Words.clampedToLong; +import org.hyperledger.besu.datatypes.AccessWitness; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Transaction; 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.List; +import java.util.Optional; +import java.util.function.Supplier; + +import org.apache.tuweni.units.bigints.UInt256; + /** * Gas Calculator for Prague * @@ -34,6 +48,7 @@ */ public class PragueGasCalculator extends ShanghaiGasCalculator { private static final long CREATE_OPERATION_GAS_COST = 1_000L; + private static final long INIT_CODE_COST = 2L; /** Instantiates a new Prague Gas Calculator. */ public PragueGasCalculator() { @@ -64,6 +79,12 @@ public long initcodeCost(final int initCodeLength) { return super.initcodeCost(initCodeLength); } + @Override + public long initcodeStatelessCost( + final MessageFrame frame, final Address address, final Wei value) { + return frame.getAccessWitness().touchAndChargeContractCreateInit(address, !value.isZero()); + } + @Override public long callOperationGasCost( final MessageFrame frame, @@ -105,8 +126,259 @@ public long callOperationGasCost( return cost; } + @SuppressWarnings("removal") + @Override + @Deprecated(since = "24.4.1", forRemoval = true) + public long createOperationGasCost(final MessageFrame frame) { + + final long initCodeOffset = clampedToLong(frame.getStackItem(1)); + final long initCodeLength = clampedToLong(frame.getStackItem(2)); + + final long memoryGasCost = memoryExpansionGasCost(frame, initCodeOffset, initCodeLength); + long gasCost = clampedAdd(CREATE_OPERATION_GAS_COST, memoryGasCost); + + return clampedAdd(gasCost, calculateInitGasCost(initCodeLength)); + } + + private static long calculateInitGasCost(final long initCodeLength) { + final int dataLength = (int) Math.ceil(initCodeLength / 32.0); + return dataLength * INIT_CODE_COST; + } + @Override public long txCreateCost() { return CREATE_OPERATION_GAS_COST; } + + @Override + public long codeDepositGasCost(final MessageFrame frame, final int codeSize) { + return frame + .getAccessWitness() + .touchCodeChunksUponContractCreation(frame.getContractAddress(), codeSize); + } + + @Override + public long calculateStorageCost( + final MessageFrame frame, + final UInt256 key, + final UInt256 newValue, + final Supplier currentValue, + final Supplier originalValue) { + + long gasCost = 0; + + // TODO VEKLE: right now we're not computing what is the tree index and subindex we're just + // charging the cost of writing to the storage + AccessWitness accessWitness = frame.getAccessWitness(); + List treeIndexes = accessWitness.getStorageSlotTreeIndexes(key); + gasCost += + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); + gasCost += + frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); + + if (gasCost == 0) { + gasCost = WARM_STORAGE_READ_COST; + } + + return gasCost; + } + + @Override + public long calculateStorageRefundAmount( + final UInt256 newValue, + final Supplier currentValue, + final Supplier originalValue) { + return 0L; + } + + @Override + public long extCodeCopyOperationGasCost( + final MessageFrame frame, + final Address address, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + long gasCost = + super.extCodeCopyOperationGasCost( + frame, address, memOffset, codeOffset, readSize, codeSize); + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY)); + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + gasCost = + clampedAdd( + gasCost, + frame.getAccessWitness().touchCodeChunks(address, codeOffset, readSize, codeSize)); + } + System.out.println("ext copy gas cost " + gasCost); + return gasCost; + } + + // TODO: @Override + @SuppressWarnings("unused") + public long codeCopyOperationGasCost_NOT_IMPLEMENTED( + final MessageFrame frame, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + long gasCost = super.dataCopyOperationGasCost(frame, memOffset, readSize); + System.out.println( + frame.getContractAddress() + + " " + + codeOffset + + " " + + readSize + + " " + + codeSize + + " " + + gasCost); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); + } + return gasCost; + } + + @Override + public long pushOperationGasCost( + final MessageFrame frame, final long codeOffset, final long readSize, final long codeSize) { + long gasCost = super.pushOperationGasCost(frame, codeOffset, readSize, codeSize); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + if (readSize == 1) { + if ((codeOffset % 31 == 0)) { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks( + frame.getContractAddress(), codeOffset + 1, readSize, codeSize)); + } + } else { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); + } + System.out.println( + String.format( + "push%d %s isPre? %b offset %d codeSize %d gas: %d", + readSize, + frame.getContractAddress(), + isPrecompile(frame.getContractAddress()), + codeOffset, + codeSize, + gasCost)); + } + return gasCost; + } + + @Override + public long getBalanceOperationGasCost(final MessageFrame frame) { + return frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + frame.getContractAddress(), UInt256.ZERO, BALANCE_LEAF_KEY); + } + + @Override + public long extCodeHashOperationGasCost( + final MessageFrame frame, final Optional
    maybeAddress) { + return maybeAddress + .map( + address -> + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_KECCAK_LEAF_KEY)) + .orElse(0L); + } + + @Override + public long selfDestructOperationGasCost( + final MessageFrame frame, + final Account recipient, + final Address recipientAddress, + final Wei inheritance, + final Address originatorAddress) { + long cost = + super.selfDestructOperationGasCost( + frame, recipient, recipientAddress, inheritance, originatorAddress); + cost = + clampedAdd( + cost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + originatorAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); + cost = + clampedAdd( + cost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(recipientAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); + return cost; + } + + @Override + 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; + } + + @Override + public long computeBaseAccessEventsCost( + final AccessWitness accessWitness, + final Transaction transaction, + final MutableAccount sender) { + final boolean sendsValue = !transaction.getValue().equals(Wei.ZERO); + long cost = 0; + cost += accessWitness.touchTxOriginAndComputeGas(transaction.getSender()); + + if (transaction.getTo().isPresent()) { + final Address to = transaction.getTo().get(); + cost += accessWitness.touchTxExistingAndComputeGas(to, sendsValue); + } else { + cost += + accessWitness.touchAndChargeContractCreateInit( + Address.contractAddress(transaction.getSender(), sender.getNonce() - 1L), sendsValue); + } + + return cost; + } + + @Override + public long completedCreateContractGasCost(final MessageFrame frame) { + return frame + .getAccessWitness() + .touchAndChargeContractCreateCompleted(frame.getContractAddress()); + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java index d81b9a1090a..c0f37a6e86d 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java @@ -14,27 +14,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ -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; -import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; -import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import static org.hyperledger.besu.evm.internal.Words.numWords; -import org.hyperledger.besu.datatypes.AccessWitness; -import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Transaction; -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.List; -import java.util.Optional; -import java.util.function.Supplier; - import org.apache.tuweni.bytes.Bytes; -import org.apache.tuweni.units.bigints.UInt256; /** The Shanghai gas calculator. */ public class ShanghaiGasCalculator extends LondonGasCalculator { @@ -65,207 +48,8 @@ public long transactionIntrinsicGasCost(final Bytes payload, final boolean isCon } } - @Override - public long computeBaseAccessEventsCost( - final AccessWitness accessWitness, - final Transaction transaction, - final MutableAccount sender) { - final boolean sendsValue = !transaction.getValue().equals(Wei.ZERO); - long cost = 0; - cost += accessWitness.touchTxOriginAndComputeGas(transaction.getSender()); - - if (transaction.getTo().isPresent()) { - final Address to = transaction.getTo().get(); - cost += accessWitness.touchTxExistingAndComputeGas(to, sendsValue); - } else { - cost += - accessWitness.touchAndChargeContractCreateInit( - Address.contractAddress(transaction.getSender(), sender.getNonce() - 1L), sendsValue); - } - - return cost; - } - - @Override - public long completedCreateContractGasCost(final MessageFrame frame) { - return frame - .getAccessWitness() - .touchAndChargeContractCreateCompleted(frame.getContractAddress()); - } - - @Override - public long codeDepositGasCost(final MessageFrame frame, final int codeSize) { - return frame - .getAccessWitness() - .touchCodeChunksUponContractCreation(frame.getContractAddress(), codeSize); - } - @Override public long initcodeCost(final int initCodeLength) { return numWords(initCodeLength) * INIT_CODE_COST; } - - @Override - public long calculateStorageCost( - final MessageFrame frame, - final UInt256 key, - final UInt256 newValue, - final Supplier currentValue, - final Supplier originalValue) { - - long gasCost = 0; - - // TODO VEKLE: right now we're not computing what is the tree index and subindex we're just - // charging the cost of writing to the storage - AccessWitness accessWitness = frame.getAccessWitness(); - List treeIndexes = accessWitness.getStorageSlotTreeIndexes(key); - gasCost += - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas( - frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); - gasCost += - frame - .getAccessWitness() - .touchAddressOnWriteAndComputeGas( - frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); - return gasCost; - } - - @Override - 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; - } - - @Override - public long getBalanceOperationGasCost(final MessageFrame frame) { - return frame - .getAccessWitness() - .touchAddressOnWriteAndComputeGas( - frame.getContractAddress(), UInt256.ZERO, BALANCE_LEAF_KEY); - } - - @Override - public long extCodeHashOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { - return maybeAddress - .map( - address -> - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_KECCAK_LEAF_KEY)) - .orElse(0L); - } - - @Override - public long extCodeCopyOperationGasCost( - final MessageFrame frame, - final Address address, - final long memOffset, - final long codeOffset, - final long readSize, - final long codeSize) { - long gasCost = - super.extCodeCopyOperationGasCost( - frame, address, memOffset, codeOffset, readSize, codeSize); - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY)); - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); - if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - gasCost = - clampedAdd( - gasCost, - frame.getAccessWitness().touchCodeChunks(address, codeOffset, readSize, codeSize)); - } - return gasCost; - } - - @Override - public long codeCopyOperationGasCost( - final MessageFrame frame, - final long memOffset, - final long codeOffset, - final long readSize, - final long codeSize) { - long gasCost = super.dataCopyOperationGasCost(frame, memOffset, readSize); - if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); - } - return gasCost; - } - - @Override - public long pushOperationGasCost( - final MessageFrame frame, final long codeOffset, final long readSize, final long codeSize) { - long gasCost = super.pushOperationGasCost(frame, codeOffset, readSize, codeSize); - if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - if(readSize==1){ - if( (codeOffset%31==0)){ - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchCodeChunks(frame.getContractAddress(), codeOffset+1, readSize, codeSize)); - - } - } else { - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); - - } - } - return gasCost; - } - - @Override - public long selfDestructOperationGasCost( - final MessageFrame frame, - final Account recipient, - final Address recipientAddress, - final Wei inheritance, - final Address originatorAddress) { - long cost = - super.selfDestructOperationGasCost( - frame, recipient, recipientAddress, inheritance, originatorAddress); - cost = - clampedAdd( - cost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas( - originatorAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); - cost = - clampedAdd( - cost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(recipientAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); - return cost; - } } From 5a01f849e9a5233e0f0e12ce8562ed5d084e42db Mon Sep 17 00:00:00 2001 From: garyschulte Date: Fri, 26 Apr 2024 10:59:22 -0700 Subject: [PATCH 09/18] re-add codeCopy for logging only Signed-off-by: garyschulte --- .../besu/evm/gascalculator/PragueGasCalculator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 49d546a8fc5..b0ea652951b 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 @@ -230,9 +230,8 @@ public long extCodeCopyOperationGasCost( return gasCost; } - // TODO: @Override - @SuppressWarnings("unused") - public long codeCopyOperationGasCost_NOT_IMPLEMENTED( + @Override + public long codeCopyOperationGasCost( final MessageFrame frame, final long memOffset, final long codeOffset, @@ -257,7 +256,8 @@ public long codeCopyOperationGasCost_NOT_IMPLEMENTED( .getAccessWitness() .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); } - return gasCost; + System.out.println(" 4762 codeCopyOperationGasCost: " + gasCost); + return super.codeCopyOperationGasCost(frame, memOffset, codeOffset, readSize, codeSize); } @Override From 1b7a0449cc968967a7076592287f56463ebad774 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Fri, 26 Apr 2024 11:03:37 -0700 Subject: [PATCH 10/18] return 4762 codeCopy gas cost in prague Signed-off-by: garyschulte --- .../hyperledger/besu/evm/gascalculator/PragueGasCalculator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b0ea652951b..5eba5b7b12d 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 @@ -257,7 +257,7 @@ public long codeCopyOperationGasCost( .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); } System.out.println(" 4762 codeCopyOperationGasCost: " + gasCost); - return super.codeCopyOperationGasCost(frame, memOffset, codeOffset, readSize, codeSize); + return gasCost; } @Override From 4be2f9d6b00998982ac6d5097e7beb5188790125 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Sat, 27 Apr 2024 07:15:06 -0700 Subject: [PATCH 11/18] add eip4762 definiton and gas calculator, revert prague Signed-off-by: garyschulte --- .../mainnet/MainnetProtocolSpecFactory.java | 4 +- .../mainnet/MainnetProtocolSpecs.java | 98 ++--- .../org/hyperledger/besu/evm/MainnetEVMs.java | 51 +++ .../gascalculator/Eip4762GasCalculator.java | 365 ++++++++++++++++++ .../gascalculator/PragueGasCalculator.java | 342 +--------------- 5 files changed, 470 insertions(+), 390 deletions(-) create mode 100644 evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip4762GasCalculator.java diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java index 06bc45084a7..10201a03944 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java @@ -179,7 +179,9 @@ public ProtocolSpecBuilder cancunDefinition(final GenesisConfigOptions genesisCo } public ProtocolSpecBuilder pragueDefinition(final GenesisConfigOptions genesisConfigOptions) { - return MainnetProtocolSpecs.pragueDefinition( + // TODO: this is for VERKLE devnet + // return MainnetProtocolSpecs.pragueDefinition( + return MainnetProtocolSpecs.eip4762Definition( chainId, contractSizeLimit, evmStackSize, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index 72c48422f20..aab26424276 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator; import org.hyperledger.besu.ethereum.mainnet.ClearEmptyAccountStrategy.ClearEmptyAccount; -import org.hyperledger.besu.ethereum.mainnet.ClearEmptyAccountStrategy.ClearEmptyAccountWithException; import org.hyperledger.besu.ethereum.mainnet.ClearEmptyAccountStrategy.NotClearEmptyAccount; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder.BlockValidatorBuilder; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; @@ -50,6 +49,7 @@ import org.hyperledger.besu.evm.gascalculator.ByzantiumGasCalculator; import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; +import org.hyperledger.besu.evm.gascalculator.Eip4762GasCalculator; import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator; import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator; import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator; @@ -728,52 +728,6 @@ static ProtocolSpecBuilder cancunDefinition( .name("Cancun"); } - // TODO FIX THAT TO HAVE CORRECT CONFIGURATION - static ProtocolSpecBuilder pragueDefinition( - final Optional chainId, - final OptionalInt configContractSizeLimit, - final OptionalInt configStackSizeLimit, - final boolean enableRevertReason, - final GenesisConfigOptions genesisConfigOptions, - final EvmConfiguration evmConfiguration, - final MiningParameters miningParameters) { - final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE); - - final ClearEmptyAccountStrategy clearEmptyAccountStrategy = - new ClearEmptyAccountWithException( - List.of(HistoricalBlockHashProcessor.HISTORICAL_BLOCKHASH_ADDRESS)); - return shanghaiDefinition( - chainId, - configContractSizeLimit, - configStackSizeLimit, - enableRevertReason, - genesisConfigOptions, - evmConfiguration, - miningParameters) - .gasCalculator(PragueGasCalculator::new) - .transactionProcessorBuilder( - (gasCalculator, - feeMarket, - transactionValidator, - contractCreationProcessor, - messageCallProcessor) -> - new MainnetTransactionProcessor( - gasCalculator, - transactionValidator, - contractCreationProcessor, - messageCallProcessor, - clearEmptyAccountStrategy, - true, - stackSizeLimit, - feeMarket, - CoinbaseFeePriceCalculator.eip1559())) - .withdrawalsProcessor(new WithdrawalsProcessor(clearEmptyAccountStrategy)) - .historicalBlockHashProcessor( - new HistoricalBlockHashProcessor(genesisConfigOptions.getPragueTime().orElse(0))) - .name("Prague"); - } - - /* //TODO REACTIVATE static ProtocolSpecBuilder pragueDefinition( final Optional chainId, final OptionalInt configContractSizeLimit, @@ -819,7 +773,55 @@ static ProtocolSpecBuilder pragueDefinition( .exitsValidator(new ValidatorExitsValidator.AllowedExits()) .name("Prague"); } - */ + + static ProtocolSpecBuilder eip4762Definition( + final Optional chainId, + final OptionalInt configContractSizeLimit, + final OptionalInt configStackSizeLimit, + final boolean enableRevertReason, + final GenesisConfigOptions genesisConfigOptions, + final EvmConfiguration evmConfiguration, + final MiningParameters miningParameters) { + + // extra variables need to support flipping the warm coinbase flag. + final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE); + final ClearEmptyAccountStrategy clearEmptyAccountStrategy = + new ClearEmptyAccountStrategy.ClearEmptyAccountWithException( + List.of(HistoricalBlockHashProcessor.HISTORICAL_BLOCKHASH_ADDRESS)); + return shanghaiDefinition( + chainId, + configContractSizeLimit, + configStackSizeLimit, + enableRevertReason, + genesisConfigOptions, + evmConfiguration, + miningParameters) + .gasCalculator(Eip4762GasCalculator::new) + .evmBuilder( + (gasCalculator, jdCacheConfig) -> + MainnetEVMs.eip4762( + gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) + .transactionProcessorBuilder( + (gasCalculator, + feeMarket, + transactionValidatorFactory, + contractCreationProcessor, + messageCallProcessor) -> + new MainnetTransactionProcessor( + gasCalculator, + transactionValidatorFactory, + contractCreationProcessor, + messageCallProcessor, + clearEmptyAccountStrategy, + true, + stackSizeLimit, + feeMarket, + CoinbaseFeePriceCalculator.eip1559())) + .withdrawalsProcessor(new WithdrawalsProcessor(clearEmptyAccountStrategy)) + .historicalBlockHashProcessor( + new HistoricalBlockHashProcessor(genesisConfigOptions.getPragueTime().orElse(0))) + .name("eip4762"); + } static ProtocolSpecBuilder futureEipsDefinition( final Optional chainId, diff --git a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java index b0492d77a4e..d50fa3e15fd 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java @@ -1087,6 +1087,57 @@ public static void registerBogotaOperations( registerOsakaOperations(registry, gasCalculator, chainID); } + /** + * eip4762 evm. + * + * @param gasCalculator the gas calculator + * @param chainId the chain id + * @param evmConfiguration the evm configuration + * @return the evm + */ + public static EVM eip4762( + final GasCalculator gasCalculator, + final BigInteger chainId, + final EvmConfiguration evmConfiguration) { + return new EVM( + eip4762Operations(gasCalculator, chainId), + gasCalculator, + evmConfiguration, + EvmSpecVersion.FUTURE_EIPS); + } + + /** + * Operation registry for eip472's operations. + * + * @param gasCalculator the gas calculator + * @param chainId the chain id + * @return the operation registry + */ + public static OperationRegistry eip4762Operations( + final GasCalculator gasCalculator, final BigInteger chainId) { + OperationRegistry operationRegistry = new OperationRegistry(); + registerEip4762Operations(operationRegistry, gasCalculator, chainId); + return operationRegistry; + } + + /** + * Register eip4762 operations. + * + * @param registry the registry + * @param gasCalculator the gas calculator + * @param chainID the chain id + */ + public static void registerEip4762Operations( + final OperationRegistry registry, + final GasCalculator gasCalculator, + final BigInteger chainID) { + // basing off of shanghai for devnet-6 + registerShanghaiOperations(registry, gasCalculator, chainID); + registry.put(new BlockHashOperation(gasCalculator, true)); + // mimic a weird behavior by geth that ignores eip-1706 + registry.put(new SStoreOperation(gasCalculator, 272L)); + } + /** * Future eips evm. * 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 new file mode 100644 index 00000000000..a77c433e9a9 --- /dev/null +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip4762GasCalculator.java @@ -0,0 +1,365 @@ +/* + * Copyright Hyperledger Besu contributors. + * + * 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.gascalculator; + +import static org.hyperledger.besu.datatypes.Address.KZG_POINT_EVAL; +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; +import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; +import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; +import static org.hyperledger.besu.evm.internal.Words.clampedAdd; +import static org.hyperledger.besu.evm.internal.Words.clampedToLong; + +import org.hyperledger.besu.datatypes.AccessWitness; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Transaction; +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.List; +import java.util.Optional; +import java.util.function.Supplier; + +import org.apache.tuweni.units.bigints.UInt256; + +public class Eip4762GasCalculator extends PragueGasCalculator { + private static final long CREATE_OPERATION_GAS_COST = 1_000L; + private static final long INIT_CODE_COST = 2L; + + /** Instantiates a new Prague Gas Calculator. */ + public Eip4762GasCalculator() { + super(KZG_POINT_EVAL.toArrayUnsafe()[19]); + } + + @Override + public long getColdSloadCost() { + return 0; // no cold gas cost after verkle + } + + @Override + public long getColdAccountAccessCost() { + return 0; // no cold gas cost after verkle + } + + @Override + public long initcodeCost(final int initCodeLength) { + return super.initcodeCost(initCodeLength); + } + + @Override + public long initcodeStatelessCost( + final MessageFrame frame, final Address address, final Wei value) { + return frame.getAccessWitness().touchAndChargeContractCreateInit(address, !value.isZero()); + } + + @Override + public long callOperationGasCost( + final MessageFrame frame, + final long stipend, + final long inputDataOffset, + final long inputDataLength, + final long outputDataOffset, + final long outputDataLength, + final Wei transferValue, + final Account recipient, + final Address to, + final boolean accountIsWarm) { + + long cost = + super.callOperationGasCost( + frame, + stipend, + inputDataOffset, + inputDataLength, + outputDataOffset, + outputDataLength, + transferValue, + recipient, + to, + true); + if (!super.isPrecompile(to)) { + if (frame.getWorldUpdater().get(to) == null) { + cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeProofOfAbsence(to)); + } else { + cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeMessageCall(to)); + } + if (!transferValue.isZero()) { + cost = + clampedAdd( + cost, + frame.getAccessWitness().touchAndChargeValueTransfer(recipient.getAddress(), to)); + } + } + return cost; + } + + @SuppressWarnings("removal") + @Override + @Deprecated(since = "24.4.1", forRemoval = true) + public long createOperationGasCost(final MessageFrame frame) { + + final long initCodeOffset = clampedToLong(frame.getStackItem(1)); + final long initCodeLength = clampedToLong(frame.getStackItem(2)); + + final long memoryGasCost = memoryExpansionGasCost(frame, initCodeOffset, initCodeLength); + long gasCost = clampedAdd(CREATE_OPERATION_GAS_COST, memoryGasCost); + + return clampedAdd(gasCost, calculateInitGasCost(initCodeLength)); + } + + private static long calculateInitGasCost(final long initCodeLength) { + final int dataLength = (int) Math.ceil(initCodeLength / 32.0); + return dataLength * INIT_CODE_COST; + } + + @Override + public long txCreateCost() { + return CREATE_OPERATION_GAS_COST; + } + + @Override + public long codeDepositGasCost(final MessageFrame frame, final int codeSize) { + return frame + .getAccessWitness() + .touchCodeChunksUponContractCreation(frame.getContractAddress(), codeSize); + } + + @Override + public long calculateStorageCost( + final MessageFrame frame, + final UInt256 key, + final UInt256 newValue, + final Supplier currentValue, + final Supplier originalValue) { + + long gasCost = 0; + + // TODO VEKLE: right now we're not computing what is the tree index and subindex we're just + // charging the cost of writing to the storage + AccessWitness accessWitness = frame.getAccessWitness(); + List treeIndexes = accessWitness.getStorageSlotTreeIndexes(key); + gasCost += + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); + gasCost += + frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); + + if (gasCost == 0) { + gasCost = WARM_STORAGE_READ_COST; + } + + return gasCost; + } + + @Override + public long calculateStorageRefundAmount( + final UInt256 newValue, + final Supplier currentValue, + final Supplier originalValue) { + return 0L; + } + + @Override + public long extCodeCopyOperationGasCost( + final MessageFrame frame, + final Address address, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + long gasCost = + super.extCodeCopyOperationGasCost( + frame, address, memOffset, codeOffset, readSize, codeSize); + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY)); + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + gasCost = + clampedAdd( + gasCost, + frame.getAccessWitness().touchCodeChunks(address, codeOffset, readSize, codeSize)); + } + System.out.println("ext copy gas cost " + gasCost); + return gasCost; + } + + @Override + public long codeCopyOperationGasCost( + final MessageFrame frame, + final long memOffset, + final long codeOffset, + final long readSize, + final long codeSize) { + long gasCost = super.dataCopyOperationGasCost(frame, memOffset, readSize); + System.out.println( + frame.getContractAddress() + + " " + + codeOffset + + " " + + readSize + + " " + + codeSize + + " " + + gasCost); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); + } + System.out.println(" 4762 codeCopyOperationGasCost: " + gasCost); + return gasCost; + } + + @Override + public long pushOperationGasCost( + final MessageFrame frame, final long codeOffset, final long readSize, final long codeSize) { + long gasCost = super.pushOperationGasCost(frame, codeOffset, readSize, codeSize); + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { + if (readSize == 1) { + if ((codeOffset % 31 == 0)) { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks( + frame.getContractAddress(), codeOffset + 1, readSize, codeSize)); + } + } else { + gasCost = + clampedAdd( + gasCost, + frame + .getAccessWitness() + .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); + } + System.out.println( + String.format( + "push%d %s isPre? %b offset %d codeSize %d gas: %d", + readSize, + frame.getContractAddress(), + isPrecompile(frame.getContractAddress()), + codeOffset, + codeSize, + gasCost)); + } + return gasCost; + } + + @Override + public long getBalanceOperationGasCost(final MessageFrame frame) { + return frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + frame.getContractAddress(), UInt256.ZERO, BALANCE_LEAF_KEY); + } + + @Override + public long extCodeHashOperationGasCost( + final MessageFrame frame, final Optional
    maybeAddress) { + return maybeAddress + .map( + address -> + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_KECCAK_LEAF_KEY)) + .orElse(0L); + } + + @Override + public long selfDestructOperationGasCost( + final MessageFrame frame, + final Account recipient, + final Address recipientAddress, + final Wei inheritance, + final Address originatorAddress) { + long cost = + super.selfDestructOperationGasCost( + frame, recipient, recipientAddress, inheritance, originatorAddress); + cost = + clampedAdd( + cost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + originatorAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); + cost = + clampedAdd( + cost, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(recipientAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); + return cost; + } + + @Override + 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; + } + + @Override + public long computeBaseAccessEventsCost( + final AccessWitness accessWitness, + final Transaction transaction, + final MutableAccount sender) { + final boolean sendsValue = !transaction.getValue().equals(Wei.ZERO); + long cost = 0; + cost += accessWitness.touchTxOriginAndComputeGas(transaction.getSender()); + + if (transaction.getTo().isPresent()) { + final Address to = transaction.getTo().get(); + cost += accessWitness.touchTxExistingAndComputeGas(to, sendsValue); + } else { + cost += + accessWitness.touchAndChargeContractCreateInit( + Address.contractAddress(transaction.getSender(), sender.getNonce() - 1L), sendsValue); + } + + return cost; + } + + @Override + public long completedCreateContractGasCost(final MessageFrame frame) { + return frame + .getAccessWitness() + .touchAndChargeContractCreateCompleted(frame.getContractAddress()); + } +} 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 5eba5b7b12d..5d7eab4d0a9 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 @@ -15,26 +15,6 @@ package org.hyperledger.besu.evm.gascalculator; import static org.hyperledger.besu.datatypes.Address.KZG_POINT_EVAL; -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; -import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; -import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; -import static org.hyperledger.besu.evm.internal.Words.clampedAdd; -import static org.hyperledger.besu.evm.internal.Words.clampedToLong; - -import org.hyperledger.besu.datatypes.AccessWitness; -import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Transaction; -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.List; -import java.util.Optional; -import java.util.function.Supplier; - -import org.apache.tuweni.units.bigints.UInt256; /** * Gas Calculator for Prague @@ -46,9 +26,7 @@ *
  • TBD * */ -public class PragueGasCalculator extends ShanghaiGasCalculator { - private static final long CREATE_OPERATION_GAS_COST = 1_000L; - private static final long INIT_CODE_COST = 2L; +public class PragueGasCalculator extends CancunGasCalculator { /** Instantiates a new Prague Gas Calculator. */ public PragueGasCalculator() { @@ -63,322 +41,4 @@ public PragueGasCalculator() { protected PragueGasCalculator(final int maxPrecompile) { super(maxPrecompile); } - - @Override - public long getColdSloadCost() { - return 0; // no cold gas cost after verkle - } - - @Override - public long getColdAccountAccessCost() { - return 0; // no cold gas cost after verkle - } - - @Override - public long initcodeCost(final int initCodeLength) { - return super.initcodeCost(initCodeLength); - } - - @Override - public long initcodeStatelessCost( - final MessageFrame frame, final Address address, final Wei value) { - return frame.getAccessWitness().touchAndChargeContractCreateInit(address, !value.isZero()); - } - - @Override - public long callOperationGasCost( - final MessageFrame frame, - final long stipend, - final long inputDataOffset, - final long inputDataLength, - final long outputDataOffset, - final long outputDataLength, - final Wei transferValue, - final Account recipient, - final Address to, - final boolean accountIsWarm) { - - long cost = - super.callOperationGasCost( - frame, - stipend, - inputDataOffset, - inputDataLength, - outputDataOffset, - outputDataLength, - transferValue, - recipient, - to, - true); - if (!super.isPrecompile(to)) { - if (frame.getWorldUpdater().get(to) == null) { - cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeProofOfAbsence(to)); - } else { - cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeMessageCall(to)); - } - if (!transferValue.isZero()) { - cost = - clampedAdd( - cost, - frame.getAccessWitness().touchAndChargeValueTransfer(recipient.getAddress(), to)); - } - } - return cost; - } - - @SuppressWarnings("removal") - @Override - @Deprecated(since = "24.4.1", forRemoval = true) - public long createOperationGasCost(final MessageFrame frame) { - - final long initCodeOffset = clampedToLong(frame.getStackItem(1)); - final long initCodeLength = clampedToLong(frame.getStackItem(2)); - - final long memoryGasCost = memoryExpansionGasCost(frame, initCodeOffset, initCodeLength); - long gasCost = clampedAdd(CREATE_OPERATION_GAS_COST, memoryGasCost); - - return clampedAdd(gasCost, calculateInitGasCost(initCodeLength)); - } - - private static long calculateInitGasCost(final long initCodeLength) { - final int dataLength = (int) Math.ceil(initCodeLength / 32.0); - return dataLength * INIT_CODE_COST; - } - - @Override - public long txCreateCost() { - return CREATE_OPERATION_GAS_COST; - } - - @Override - public long codeDepositGasCost(final MessageFrame frame, final int codeSize) { - return frame - .getAccessWitness() - .touchCodeChunksUponContractCreation(frame.getContractAddress(), codeSize); - } - - @Override - public long calculateStorageCost( - final MessageFrame frame, - final UInt256 key, - final UInt256 newValue, - final Supplier currentValue, - final Supplier originalValue) { - - long gasCost = 0; - - // TODO VEKLE: right now we're not computing what is the tree index and subindex we're just - // charging the cost of writing to the storage - AccessWitness accessWitness = frame.getAccessWitness(); - List treeIndexes = accessWitness.getStorageSlotTreeIndexes(key); - gasCost += - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas( - frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); - gasCost += - frame - .getAccessWitness() - .touchAddressOnWriteAndComputeGas( - frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); - - if (gasCost == 0) { - gasCost = WARM_STORAGE_READ_COST; - } - - return gasCost; - } - - @Override - public long calculateStorageRefundAmount( - final UInt256 newValue, - final Supplier currentValue, - final Supplier originalValue) { - return 0L; - } - - @Override - public long extCodeCopyOperationGasCost( - final MessageFrame frame, - final Address address, - final long memOffset, - final long codeOffset, - final long readSize, - final long codeSize) { - long gasCost = - super.extCodeCopyOperationGasCost( - frame, address, memOffset, codeOffset, readSize, codeSize); - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY)); - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); - if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - gasCost = - clampedAdd( - gasCost, - frame.getAccessWitness().touchCodeChunks(address, codeOffset, readSize, codeSize)); - } - System.out.println("ext copy gas cost " + gasCost); - return gasCost; - } - - @Override - public long codeCopyOperationGasCost( - final MessageFrame frame, - final long memOffset, - final long codeOffset, - final long readSize, - final long codeSize) { - long gasCost = super.dataCopyOperationGasCost(frame, memOffset, readSize); - System.out.println( - frame.getContractAddress() - + " " - + codeOffset - + " " - + readSize - + " " - + codeSize - + " " - + gasCost); - if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); - } - System.out.println(" 4762 codeCopyOperationGasCost: " + gasCost); - return gasCost; - } - - @Override - public long pushOperationGasCost( - final MessageFrame frame, final long codeOffset, final long readSize, final long codeSize) { - long gasCost = super.pushOperationGasCost(frame, codeOffset, readSize, codeSize); - if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - if (readSize == 1) { - if ((codeOffset % 31 == 0)) { - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchCodeChunks( - frame.getContractAddress(), codeOffset + 1, readSize, codeSize)); - } - } else { - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); - } - System.out.println( - String.format( - "push%d %s isPre? %b offset %d codeSize %d gas: %d", - readSize, - frame.getContractAddress(), - isPrecompile(frame.getContractAddress()), - codeOffset, - codeSize, - gasCost)); - } - return gasCost; - } - - @Override - public long getBalanceOperationGasCost(final MessageFrame frame) { - return frame - .getAccessWitness() - .touchAddressOnWriteAndComputeGas( - frame.getContractAddress(), UInt256.ZERO, BALANCE_LEAF_KEY); - } - - @Override - public long extCodeHashOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { - return maybeAddress - .map( - address -> - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_KECCAK_LEAF_KEY)) - .orElse(0L); - } - - @Override - public long selfDestructOperationGasCost( - final MessageFrame frame, - final Account recipient, - final Address recipientAddress, - final Wei inheritance, - final Address originatorAddress) { - long cost = - super.selfDestructOperationGasCost( - frame, recipient, recipientAddress, inheritance, originatorAddress); - cost = - clampedAdd( - cost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas( - originatorAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); - cost = - clampedAdd( - cost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(recipientAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); - return cost; - } - - @Override - 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; - } - - @Override - public long computeBaseAccessEventsCost( - final AccessWitness accessWitness, - final Transaction transaction, - final MutableAccount sender) { - final boolean sendsValue = !transaction.getValue().equals(Wei.ZERO); - long cost = 0; - cost += accessWitness.touchTxOriginAndComputeGas(transaction.getSender()); - - if (transaction.getTo().isPresent()) { - final Address to = transaction.getTo().get(); - cost += accessWitness.touchTxExistingAndComputeGas(to, sendsValue); - } else { - cost += - accessWitness.touchAndChargeContractCreateInit( - Address.contractAddress(transaction.getSender(), sender.getNonce() - 1L), sendsValue); - } - - return cost; - } - - @Override - public long completedCreateContractGasCost(final MessageFrame frame) { - return frame - .getAccessWitness() - .touchAndChargeContractCreateCompleted(frame.getContractAddress()); - } } From 30d4422c13b45b375eb098055a03ced35e64e36e Mon Sep 17 00:00:00 2001 From: garyschulte Date: Sat, 27 Apr 2024 07:20:39 -0700 Subject: [PATCH 12/18] [SKIP_CI] some cleanup Signed-off-by: garyschulte --- .../gascalculator/Eip4762GasCalculator.java | 22 +------------------ .../evm/operation/ExtCodeSizeOperation.java | 1 - .../besu/evm/operation/SStoreOperation.java | 1 - .../processor/ContractCreationProcessor.java | 6 ----- 4 files changed, 1 insertion(+), 29 deletions(-) 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 a77c433e9a9..9a74fe0d905 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 @@ -207,7 +207,7 @@ public long extCodeCopyOperationGasCost( gasCost, frame.getAccessWitness().touchCodeChunks(address, codeOffset, readSize, codeSize)); } - System.out.println("ext copy gas cost " + gasCost); + return gasCost; } @@ -219,16 +219,6 @@ public long codeCopyOperationGasCost( final long readSize, final long codeSize) { long gasCost = super.dataCopyOperationGasCost(frame, memOffset, readSize); - System.out.println( - frame.getContractAddress() - + " " - + codeOffset - + " " - + readSize - + " " - + codeSize - + " " - + gasCost); if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { gasCost = clampedAdd( @@ -237,7 +227,6 @@ public long codeCopyOperationGasCost( .getAccessWitness() .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); } - System.out.println(" 4762 codeCopyOperationGasCost: " + gasCost); return gasCost; } @@ -264,15 +253,6 @@ public long pushOperationGasCost( .getAccessWitness() .touchCodeChunks(frame.getContractAddress(), codeOffset, readSize, codeSize)); } - System.out.println( - String.format( - "push%d %s isPre? %b offset %d codeSize %d gas: %d", - readSize, - frame.getContractAddress(), - isPrecompile(frame.getContractAddress()), - codeOffset, - codeSize, - gasCost)); } return gasCost; } 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 81cde5ca799..9d891f7d37e 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 @@ -64,7 +64,6 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { final Account account = frame.getWorldUpdater().get(address); frame.pushStackItem( account == null ? Bytes.EMPTY : Words.intBytes(account.getCode().size())); - System.out.println("code size "+gasCalculator().isPrecompile(address)); return new OperationResult(cost, null); } } catch (final UnderflowException ufe) { diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java index 9c877c5bf97..38fd3139303 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java @@ -84,7 +84,6 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { .calculateStorageCost( frame, key, newValue, currentValueSupplier, originalValueSupplier) + (slotIsWarm ? 0L : gasCalculator().getColdSloadCost()); - System.out.println("=> sstore gas cost: " + cost); final long remainingGas = frame.getRemainingGas(); if (frame.isStatic()) { return new OperationResult(remainingGas, ExceptionalHaltReason.ILLEGAL_STATE_CHANGE); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java index f256ee43290..1a4a1931a86 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java @@ -107,7 +107,6 @@ public void start(final MessageFrame frame, final OperationTracer operationTrace LOG.trace("Executing contract-creation"); } try { - System.out.println("start contract creation "); final MutableAccount sender = frame.getWorldUpdater().getSenderAccount(frame); sender.decrementBalance(frame.getValue()); @@ -140,10 +139,6 @@ public void start(final MessageFrame frame, final OperationTracer operationTrace public void codeSuccess(final MessageFrame frame, final OperationTracer operationTracer) { final Bytes contractCode = frame.getOutputData(); final long depositFee = gasCalculator.codeDepositGasCost(frame, contractCode.size()); - System.out.println( - String.format( - "opcode CREATE deposit fee %d codeSize %d frame codeSize %d pc %d", - depositFee, contractCode.size(), frame.getCode().getSize(), frame.getPC())); if (frame.getRemainingGas() < depositFee) { LOG.trace( "Not enough gas to pay the code deposit fee for {}: " @@ -171,7 +166,6 @@ public void codeSuccess(final MessageFrame frame, final OperationTracer operatio final long statelessContractCompletionFee = gasCalculator.completedCreateContractGasCost(frame); - System.out.println("opcode CREATE completion " + statelessContractCompletionFee); if (frame.getRemainingGas() < statelessContractCompletionFee) { LOG.trace( "Not enough gas to pay the contract creation completion fee for {}: " From 3e846eb0fdccbe0ab6a03a8ce9f3d2e85bdad267 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Mon, 29 Apr 2024 17:19:40 +0200 Subject: [PATCH 13/18] 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); From 68f34e128927195e518249da4c5fd6ff8e22f387 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Tue, 30 Apr 2024 16:45:27 +0200 Subject: [PATCH 14/18] fix gas cost implementation and prevent charging invalid warm storage cost Signed-off-by: Karim Taam --- .../gascalculator/BerlinGasCalculator.java | 24 ++- .../ConstantinopleGasCalculator.java | 2 +- .../gascalculator/Eip4762GasCalculator.java | 180 ++++++++++-------- .../gascalculator/FrontierGasCalculator.java | 10 +- .../besu/evm/gascalculator/GasCalculator.java | 16 +- .../gascalculator/IstanbulGasCalculator.java | 7 +- .../TangerineWhistleGasCalculator.java | 5 +- .../besu/evm/operation/BalanceOperation.java | 5 +- .../evm/operation/ExtCodeCopyOperation.java | 13 +- .../evm/operation/ExtCodeHashOperation.java | 5 +- .../evm/operation/ExtCodeSizeOperation.java | 5 +- .../besu/evm/operation/SLoadOperation.java | 5 +- 12 files changed, 146 insertions(+), 131 deletions(-) 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 89329fab880..8c71c63b060 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 @@ -67,7 +67,7 @@ public class BerlinGasCalculator extends IstanbulGasCalculator { private static final long NEGATIVE_SSTORE_CLEARS_SCHEDULE = -SSTORE_CLEARS_SCHEDULE; // unchanged from Frontier - private static final long COPY_WORD_GAS_COST = 3L; + protected static final long COPY_WORD_GAS_COST = 3L; private final int maxPrecompile; @@ -121,8 +121,8 @@ public long getWarmStorageReadCost() { // Zeroed out old costs @Override public long getBalanceOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { - return 0L; + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { + return accountIsWarm ? getWarmStorageReadCost() : getColdAccountAccessCost(); } @Override @@ -132,19 +132,20 @@ public long callOperationBaseGasCost() { @Override public long extCodeHashOperationGasCost( - final MessageFrame frame, final Optional
    address) { - return 0L; + final MessageFrame frame, final boolean accountIsWarm, final Optional
    address) { + return (accountIsWarm ? getWarmStorageReadCost() : getColdAccountAccessCost()); } @Override public long getExtCodeSizeOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { - return 0L; + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { + return (accountIsWarm ? getWarmStorageReadCost() : getColdAccountAccessCost()); } @Override - public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key) { - return 0L; + public long getSloadOperationGasCost( + final MessageFrame frame, final UInt256 key, final boolean slotIsWarm) { + return (slotIsWarm ? getWarmStorageReadCost() : getColdSloadCost()); } // Redefined costs from EIP-2929 @@ -207,11 +208,14 @@ public long callOperationGasCost( public long extCodeCopyOperationGasCost( final MessageFrame frame, final Address address, + final boolean accountIsWarm, final long memOffset, final long codeOffset, final long readSize, final long codeSize) { - return copyWordsToMemoryGasCost(frame, 0L, COPY_WORD_GAS_COST, memOffset, readSize); + return clampedAdd( + copyWordsToMemoryGasCost(frame, 0L, COPY_WORD_GAS_COST, memOffset, readSize), + accountIsWarm ? getWarmStorageReadCost() : getColdAccountAccessCost()); } // defined in Istanbul, but re-implemented with new constants diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ConstantinopleGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ConstantinopleGasCalculator.java index 14059a498ff..7bc61e22cc8 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ConstantinopleGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ConstantinopleGasCalculator.java @@ -128,7 +128,7 @@ public long calculateStorageRefundAmount( @Override public long extCodeHashOperationGasCost( - final MessageFrame frame, final Optional
    address) { + final MessageFrame frame, final boolean accountIsWarm, final Optional
    address) { return EXTCODE_HASH_COST; } } 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 28f81170e0e..2b6c752f5ee 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 @@ -20,7 +20,6 @@ import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; -import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import org.hyperledger.besu.datatypes.AccessWitness; import org.hyperledger.besu.datatypes.Address; @@ -39,7 +38,6 @@ public class Eip4762GasCalculator extends PragueGasCalculator { private static final long CREATE_OPERATION_GAS_COST = 1_000L; - private static final long INIT_CODE_COST = 2L; /** Instantiates a new Prague Gas Calculator. */ public Eip4762GasCalculator() { @@ -80,7 +78,7 @@ public long callOperationGasCost( final Address to, final boolean accountIsWarm) { - long cost = + long gasCost = super.callOperationGasCost( frame, stipend, @@ -92,39 +90,26 @@ public long callOperationGasCost( recipient, to, true); - if (!super.isPrecompile(to)) { + if (super.isPrecompile(to)) { + return gasCost; + } else { + long statelessGas; if (frame.getWorldUpdater().get(to) == null) { - cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeProofOfAbsence(to)); + statelessGas = frame.getAccessWitness().touchAndChargeProofOfAbsence(to); } else { - cost = clampedAdd(cost, frame.getAccessWitness().touchAndChargeMessageCall(to)); + statelessGas = frame.getAccessWitness().touchAndChargeMessageCall(to); } if (!transferValue.isZero()) { - cost = + statelessGas = clampedAdd( - cost, + statelessGas, frame.getAccessWitness().touchAndChargeValueTransfer(recipient.getAddress(), to)); } + if (statelessGas == 0) { + return getWarmStorageReadCost(); + } + return clampedAdd(gasCost, statelessGas); } - return cost; - } - - @SuppressWarnings("removal") - @Override - @Deprecated(since = "24.4.1", forRemoval = true) - public long createOperationGasCost(final MessageFrame frame) { - - final long initCodeOffset = clampedToLong(frame.getStackItem(1)); - final long initCodeLength = clampedToLong(frame.getStackItem(2)); - - final long memoryGasCost = memoryExpansionGasCost(frame, initCodeOffset, initCodeLength); - long gasCost = clampedAdd(CREATE_OPERATION_GAS_COST, memoryGasCost); - - return clampedAdd(gasCost, calculateInitGasCost(initCodeLength)); - } - - private static long calculateInitGasCost(final long initCodeLength) { - final int dataLength = (int) Math.ceil(initCodeLength / 32.0); - return dataLength * INIT_CODE_COST; } @Override @@ -165,7 +150,7 @@ public long calculateStorageCost( frame.getRecipientAddress(), treeIndexes.get(0), treeIndexes.get(1)); if (gasCost == 0) { - gasCost = WARM_STORAGE_READ_COST; + return getWarmStorageReadCost(); } return gasCost; @@ -183,33 +168,35 @@ public long calculateStorageRefundAmount( public long extCodeCopyOperationGasCost( final MessageFrame frame, final Address address, + final boolean accountIsWarm, final long memOffset, final long codeOffset, final long readSize, final long codeSize) { - long gasCost = - super.extCodeCopyOperationGasCost( - frame, address, memOffset, codeOffset, readSize, codeSize); - gasCost = - clampedAdd( - gasCost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY)); - gasCost = + long gasCost = copyWordsToMemoryGasCost(frame, 0L, COPY_WORD_GAS_COST, memOffset, readSize); + + long statelessGas = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY); + statelessGas = clampedAdd( - gasCost, + statelessGas, frame .getAccessWitness() .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + if (statelessGas == 0) { + statelessGas = getWarmStorageReadCost(); + } + if (!frame.wasCreatedInTransaction(frame.getContractAddress())) { - gasCost = + statelessGas = clampedAdd( - gasCost, + statelessGas, frame.getAccessWitness().touchCodeChunks(address, codeOffset, readSize, codeSize)); } - return gasCost; + return clampedAdd(gasCost, statelessGas); } @Override @@ -260,48 +247,71 @@ public long pushOperationGasCost( @Override public long getBalanceOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { - return maybeAddress - .map( - address -> - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, BALANCE_LEAF_KEY)) - .orElse(0L); + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { + if (maybeAddress.isPresent()) { + final Address address = maybeAddress.get(); + final long statelessGas = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, BALANCE_LEAF_KEY); + if (statelessGas == 0) { + return getWarmStorageReadCost(); + } else { + return statelessGas; + } + } + return 0L; } @Override public long extCodeHashOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { - return maybeAddress - .map( - address -> - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_KECCAK_LEAF_KEY)) - .orElse(0L); + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { + if (maybeAddress.isPresent()) { + final Address address = maybeAddress.get(); + if (isPrecompile(address)) { + return 0L; + } else { + final long statelessGas = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_KECCAK_LEAF_KEY); + if (statelessGas == 0) { + return getWarmStorageReadCost(); + } else { + return statelessGas; + } + } + } + return 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); + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { + + if (maybeAddress.isPresent()) { + final Address address = maybeAddress.get(); + if (isPrecompile(address)) { + return 0L; + } else { + long statelessGas = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, VERSION_LEAF_KEY); + statelessGas = + clampedAdd( + statelessGas, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(address, UInt256.ZERO, CODE_SIZE_LEAF_KEY)); + if (statelessGas == 0) { + return getWarmStorageReadCost(); + } else { + return statelessGas; + } + } + } + return 0L; } @Override @@ -331,13 +341,19 @@ public long selfDestructOperationGasCost( } @Override - public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key) { + public long getSloadOperationGasCost( + final MessageFrame frame, final UInt256 key, final boolean slotIsWarm) { AccessWitness accessWitness = frame.getAccessWitness(); List treeIndexes = accessWitness.getStorageSlotTreeIndexes(key); - return frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas( - frame.getContractAddress(), treeIndexes.get(0), treeIndexes.get(1)); + long gasCost = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + frame.getContractAddress(), treeIndexes.get(0), treeIndexes.get(1)); + if (gasCost == 0) { + return getWarmStorageReadCost(); + } + return gasCost; } @Override 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 f1d2d8a0470..704aebcdcc5 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 @@ -406,7 +406,7 @@ public long memoryExpansionGasCost( @Override public long getBalanceOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { return BALANCE_OPERATION_GAS_COST; } @@ -442,6 +442,7 @@ protected long extCodeBaseGasCost() { public long extCodeCopyOperationGasCost( final MessageFrame frame, final Address address, + final boolean accountIsWarm, final long memOffset, final long codeOffset, final long readSize, @@ -452,14 +453,14 @@ public long extCodeCopyOperationGasCost( @Override public long extCodeHashOperationGasCost( - final MessageFrame frame, final Optional
    address) { + final MessageFrame frame, final boolean accountIsWarm, final Optional
    address) { throw new UnsupportedOperationException( "EXTCODEHASH not supported by " + getClass().getSimpleName()); } @Override public long getExtCodeSizeOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { return extCodeBaseGasCost(); } @@ -517,7 +518,8 @@ public long keccak256OperationGasCost( } @Override - public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key) { + public long getSloadOperationGasCost( + final MessageFrame frame, final UInt256 key, final boolean slotIsWarm) { return SLOAD_OPERATION_GAS_COST; } 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 d3dcb81f32e..359df7ae597 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 @@ -337,10 +337,12 @@ long codeCopyOperationGasCost( * Returns the cost for executing a {@link BalanceOperation}. * * @param frame The current frame + * @param accountIsWarm true to add warm storage read cost, false to add cold account access cost * @param maybeAddress targeted address * @return the cost for executing the balance operation */ - long getBalanceOperationGasCost(MessageFrame frame, final Optional
    maybeAddress); + long getBalanceOperationGasCost( + MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress); /** * Returns the cost for executing a {@link BlockHashOperation}. @@ -362,6 +364,7 @@ long codeCopyOperationGasCost( * * @param frame The current frame * @param address The address to use for the gas cost computation + * @param accountIsWarm true to add warm storage read cost, false to add cold account access cost * @param memOffset The offset in memory to external code copy the data to * @param codeOffset The starting offset within the code from which to begin copying * @param readSize The length of the code being copied into memory @@ -371,6 +374,7 @@ long codeCopyOperationGasCost( long extCodeCopyOperationGasCost( MessageFrame frame, final Address address, + final boolean accountIsWarm, long memOffset, long codeOffset, long readSize, @@ -380,19 +384,23 @@ long extCodeCopyOperationGasCost( * Returns the cost for executing a {@link ExtCodeHashOperation}. * * @param frame The current frame + * @param accountIsWarm true to add warm storage read cost, false to add cold account access cost * @param maybeAddress targeted address * @return the cost for executing the external code hash operation */ - long extCodeHashOperationGasCost(final MessageFrame frame, Optional
    maybeAddress); + long extCodeHashOperationGasCost( + final MessageFrame frame, final boolean accountIsWarm, Optional
    maybeAddress); /** * Returns the cost for executing a {@link ExtCodeSizeOperation}. * * @param frame The current frame + * @param accountIsWarm true to add warm storage read cost, false to add cold account access cost * @param maybeAddress targeted address * @return the cost for executing the external code size operation */ - long getExtCodeSizeOperationGasCost(MessageFrame frame, Optional
    maybeAddress); + long getExtCodeSizeOperationGasCost( + MessageFrame frame, final boolean accountIsWarm, Optional
    maybeAddress); /** * Returns the cost for executing a {@link JumpDestOperation}. @@ -471,7 +479,7 @@ long selfDestructOperationGasCost( * * @return the cost for executing the storage load operation */ - long getSloadOperationGasCost(MessageFrame frame, UInt256 key); + long getSloadOperationGasCost(MessageFrame frame, UInt256 key, final boolean slotIsWarm); /** * Returns the cost for an SSTORE operation. 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 cb71271d62c..6e50b48fcf5 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 @@ -124,21 +124,22 @@ public long calculateStorageRefundAmount( @Override // As per https://eips.ethereum.org/EIPS/eip-1884 - public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key) { + public long getSloadOperationGasCost( + final MessageFrame frame, final UInt256 key, final boolean slotIsWarm) { return SLOAD_GAS; } @Override // As per https://eips.ethereum.org/EIPS/eip-1884 public long getBalanceOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { return BALANCE_OPERATION_GAS_COST; } @Override // As per https://eips.ethereum.org/EIPS/eip-1884 public long extCodeHashOperationGasCost( - final MessageFrame frame, final Optional
    address) { + final MessageFrame frame, final boolean accountIsWarm, final Optional
    address) { return EXTCODE_HASH_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 9559c351160..2742a71be09 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 @@ -43,7 +43,7 @@ public class TangerineWhistleGasCalculator extends HomesteadGasCalculator { @Override public long getBalanceOperationGasCost( - final MessageFrame frame, final Optional
    maybeAddress) { + final MessageFrame frame, final boolean accountIsWarm, final Optional
    maybeAddress) { return BALANCE_OPERATION_GAS_COST; } @@ -134,7 +134,8 @@ public long selfDestructOperationGasCost( } @Override - public long getSloadOperationGasCost(final MessageFrame frame, final UInt256 key) { + public long getSloadOperationGasCost( + final MessageFrame frame, final UInt256 key, final boolean slotIsWarm) { return SLOAD_OPERATION_GAS_COST; } } 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 08a04c8edb2..32f366aa77c 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 @@ -50,10 +50,7 @@ public BalanceOperation(final GasCalculator gasCalculator) { */ protected long cost( final MessageFrame frame, final Optional
    maybeAddress, final boolean accountIsWarm) { - return gasCalculator().getBalanceOperationGasCost(frame, maybeAddress) - + (accountIsWarm - ? gasCalculator().getWarmStorageReadCost() - : gasCalculator().getColdAccountAccessCost()); + return gasCalculator().getBalanceOperationGasCost(frame, accountIsWarm, maybeAddress); } @Override diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java index 906b0cd6b52..823727a48d9 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.evm.operation; -import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import org.hyperledger.besu.datatypes.Address; @@ -47,7 +46,7 @@ public ExtCodeCopyOperation(final GasCalculator gasCalculator) { * @param memOffset the mem offset * @param sourceOffset the code offset * @param codeSize the size of the code - * @param accountIsWarm the account is warm + * @param accountIsWarm true to add warm storage read cost, false to add cold account access cost * @return the long */ protected long cost( @@ -58,13 +57,9 @@ protected long cost( final long readSize, final long codeSize, final boolean accountIsWarm) { - return clampedAdd( - gasCalculator() - .extCodeCopyOperationGasCost( - frame, address, memOffset, sourceOffset, readSize, codeSize), - accountIsWarm - ? gasCalculator().getWarmStorageReadCost() - : gasCalculator().getColdAccountAccessCost()); + return gasCalculator() + .extCodeCopyOperationGasCost( + frame, address, accountIsWarm, memOffset, sourceOffset, readSize, codeSize); } @Override 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 e561fae6a3d..c47a7a3063b 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 @@ -50,10 +50,7 @@ public ExtCodeHashOperation(final GasCalculator gasCalculator) { */ protected long cost( final MessageFrame frame, final Optional
    maybeAddress, final boolean accountIsWarm) { - return gasCalculator().extCodeHashOperationGasCost(frame, maybeAddress) - + (accountIsWarm - ? gasCalculator().getWarmStorageReadCost() - : gasCalculator().getColdAccountAccessCost()); + return gasCalculator().extCodeHashOperationGasCost(frame, accountIsWarm, maybeAddress); } @Override 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 757f52cb00b..53857db00c4 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 @@ -48,10 +48,7 @@ public ExtCodeSizeOperation(final GasCalculator gasCalculator) { */ protected long cost( final boolean accountIsWarm, final MessageFrame frame, final Optional
    maybeAddress) { - return gasCalculator().getExtCodeSizeOperationGasCost(frame, maybeAddress) - + (accountIsWarm - ? gasCalculator().getWarmStorageReadCost() - : gasCalculator().getColdAccountAccessCost()); + return gasCalculator().getExtCodeSizeOperationGasCost(frame, accountIsWarm, maybeAddress); } @Override diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/SLoadOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/SLoadOperation.java index 4df38b4b244..9a4d6e84286 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/SLoadOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/SLoadOperation.java @@ -39,10 +39,7 @@ public SLoadOperation(final GasCalculator gasCalculator) { } protected long cost(final MessageFrame frame, final Bytes32 key, final boolean slotIsWarm) { - return gasCalculator().getSloadOperationGasCost(frame, UInt256.fromBytes(key)) - + (slotIsWarm - ? gasCalculator().getWarmStorageReadCost() - : gasCalculator().getColdSloadCost()); + return gasCalculator().getSloadOperationGasCost(frame, UInt256.fromBytes(key), slotIsWarm); } @Override From 5c10263b783baf5bc9127f6fe4819b5de85b92bf Mon Sep 17 00:00:00 2001 From: garyschulte Date: Wed, 1 May 2024 15:44:53 -0700 Subject: [PATCH 15/18] use non-EOF evm spec version for eip4762 fork Signed-off-by: garyschulte --- evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java index d50fa3e15fd..9dc1646854b 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java @@ -1103,7 +1103,7 @@ public static EVM eip4762( eip4762Operations(gasCalculator, chainId), gasCalculator, evmConfiguration, - EvmSpecVersion.FUTURE_EIPS); + EvmSpecVersion.PRAGUE); } /** From e4b910c36af11fdf29dd5a7b7f90ecee31ae98ab Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Mon, 6 May 2024 11:49:12 +0200 Subject: [PATCH 16/18] fix selfdestruct gas cost Signed-off-by: Karim Taam --- .../gascalculator/Eip4762GasCalculator.java | 69 +++++++++++++++---- 1 file changed, 54 insertions(+), 15 deletions(-) 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 2b6c752f5ee..61943ab394b 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 @@ -18,6 +18,7 @@ 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; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; +import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.NONCE_LEAF_KEY; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; @@ -321,23 +322,61 @@ public long selfDestructOperationGasCost( final Address recipientAddress, final Wei inheritance, final Address originatorAddress) { - long cost = + final long gasCost = super.selfDestructOperationGasCost( frame, recipient, recipientAddress, inheritance, originatorAddress); - cost = - clampedAdd( - cost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas( - originatorAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); - cost = - clampedAdd( - cost, - frame - .getAccessWitness() - .touchAddressOnReadAndComputeGas(recipientAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); - return cost; + if (isPrecompile(recipientAddress)) { + return gasCost; + } else { + long statelessGas = + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas(originatorAddress, UInt256.ZERO, BALANCE_LEAF_KEY); + if (!originatorAddress.equals(recipientAddress)) { + statelessGas = + clampedAdd( + statelessGas, + frame + .getAccessWitness() + .touchAddressOnReadAndComputeGas( + recipientAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); + } + if (!inheritance.isZero()) { + statelessGas = + clampedAdd( + statelessGas, + frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + originatorAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); + if (!originatorAddress.equals(recipientAddress)) { + statelessGas = + clampedAdd( + statelessGas, + frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + recipientAddress, UInt256.ZERO, BALANCE_LEAF_KEY)); + } + if (recipient == null) { + statelessGas = + clampedAdd( + statelessGas, + frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + recipientAddress, UInt256.ZERO, VERSION_LEAF_KEY)); + statelessGas = + clampedAdd( + statelessGas, + frame + .getAccessWitness() + .touchAddressOnWriteAndComputeGas( + recipientAddress, UInt256.ZERO, NONCE_LEAF_KEY)); + } + } + return clampedAdd(gasCost, statelessGas); + } } @Override From c9739066983f7621106555dcea0abbe7efe5fb8b Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Fri, 17 May 2024 11:23:09 +0200 Subject: [PATCH 17/18] fix slot key overflow issue Signed-off-by: Karim Taam --- .../stateless/Eip4762AccessWitness.java | 85 +++++++++---------- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java index 14b3b48b80f..67ce54e7e0a 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java @@ -4,8 +4,6 @@ import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_KECCAK_LEAF_KEY; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_OFFSET; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.CODE_SIZE_LEAF_KEY; -import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.HEADER_STORAGE_OFFSET; -import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.MAIN_STORAGE_OFFSET; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.NONCE_LEAF_KEY; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERKLE_NODE_WIDTH; import static org.hyperledger.besu.ethereum.trie.verkle.util.Parameters.VERSION_LEAF_KEY; @@ -19,9 +17,12 @@ import java.util.Objects; import org.apache.tuweni.units.bigints.UInt256; +import org.hyperledger.besu.ethereum.trie.verkle.adapter.TrieKeyAdapter; +import org.hyperledger.besu.ethereum.trie.verkle.hasher.PedersenHasher; public class Eip4762AccessWitness implements org.hyperledger.besu.datatypes.AccessWitness { + private static final TrieKeyAdapter TRIE_KEY_ADAPTER = new TrieKeyAdapter(new PedersenHasher()); private static final long WITNESS_BRANCH_READ_COST = 1900; private static final long WITNESS_CHUNK_READ_COST = 200; private static final long WITNESS_BRANCH_WRITE_COST = 3000; @@ -54,11 +55,11 @@ public List
    keys() { @Override public long touchAndChargeProofOfAbsence(final Address address) { long gas = 0; - gas += touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); return gas; } @@ -67,8 +68,8 @@ public long touchAndChargeMessageCall(final Address address) { long gas = 0; - gas += touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); return gas; } @@ -78,8 +79,8 @@ public long touchAndChargeValueTransfer(final Address caller, final Address targ long gas = 0; - gas += touchAddressOnWriteAndComputeGas(caller, zeroTreeIndex, BALANCE_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(caller, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); return gas; } @@ -90,11 +91,11 @@ public long touchAndChargeContractCreateInit( long gas = 0; - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); if (createSendsValue) { - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); } return gas; } @@ -104,11 +105,11 @@ public long touchAndChargeContractCreateCompleted(final Address address) { long gas = 0; - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); return gas; } @@ -119,11 +120,11 @@ public long touchTxOriginAndComputeGas(final Address origin) { long gas = 0; - gas += touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, VERSION_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, BALANCE_LEAF_KEY); - gas += touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, NONCE_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_KECCAK_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_SIZE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); // modifying this after update on EIP-4762 to not charge simple transfers @@ -136,15 +137,15 @@ public long touchTxExistingAndComputeGas(final Address target, final boolean sen long gas = 0; - gas += touchAddressOnReadAndComputeGas(target, zeroTreeIndex, VERSION_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(target, zeroTreeIndex, NONCE_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_SIZE_LEAF_KEY); - gas += touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_KECCAK_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); if (sendsValue) { - gas += touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); } else { - gas += touchAddressOnReadAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY); + gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); } // modifying this after update on EIP-4762 to not charge simple transfers @@ -155,11 +156,10 @@ public long touchTxExistingAndComputeGas(final Address target, final boolean sen public long touchCodeChunksUponContractCreation(final Address address, final long codeLength) { long gas = 0; for (long i = 0; i < (codeLength + 30) / 31; i++) { - gas += - touchAddressOnWriteAndComputeGas( + gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas( address, CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), - CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH)); + CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH))); } return gas; } @@ -213,7 +213,7 @@ public long touchAddressAndChargeGas( boolean logEnabled = false; long gas = 0; if (accessEvent.isBranchRead()) { - gas += WITNESS_BRANCH_READ_COST; + gas = clampedAdd(gas,WITNESS_BRANCH_READ_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessBranchReadCost " @@ -229,7 +229,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isChunkRead()) { - gas += WITNESS_CHUNK_READ_COST; + gas = clampedAdd(gas,WITNESS_CHUNK_READ_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessChunkReadCost " @@ -245,7 +245,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isBranchWrite()) { - gas += WITNESS_BRANCH_WRITE_COST; + gas = clampedAdd(gas,WITNESS_BRANCH_WRITE_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessBranchWriteCost " @@ -261,7 +261,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isChunkWrite()) { - gas += WITNESS_CHUNK_WRITE_COST; + gas = clampedAdd(gas,WITNESS_CHUNK_WRITE_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessChunkWriteCost " @@ -277,7 +277,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isChunkFill()) { - gas += WITNESS_CHUNK_FILL_COST; + gas = clampedAdd(gas,WITNESS_CHUNK_FILL_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessChunkFillCost " @@ -374,13 +374,6 @@ public ChunkAccessKey( @Override public List getStorageSlotTreeIndexes(final UInt256 storageKey) { - - UInt256 pos; - if (storageKey.lessThan(CODE_OFFSET.subtract(HEADER_STORAGE_OFFSET))) { - pos = HEADER_STORAGE_OFFSET.add(storageKey); - } else { - pos = MAIN_STORAGE_OFFSET.add(storageKey); - } - return List.of(pos.divide(VERKLE_NODE_WIDTH), pos.mod(VERKLE_NODE_WIDTH)); + return List.of(TRIE_KEY_ADAPTER.locateStorageKeyOffset(storageKey),TRIE_KEY_ADAPTER.locateStorageKeySuffix(storageKey)); } } From 87dfbcd744f10ab07b127d6352f39767ae825703 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Fri, 17 May 2024 11:34:05 +0200 Subject: [PATCH 18/18] fix storage slot key generation and clean code Signed-off-by: Karim Taam --- .../mainnet/MainnetTransactionProcessor.java | 52 +++++++- .../verkle/trielog/TrieLogFactoryImpl.java | 2 - .../stateless/Eip4762AccessWitness.java | 115 ++++++++++++------ 3 files changed, 123 insertions(+), 46 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 d819a95b866..a770946133e 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 @@ -23,6 +23,7 @@ import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.AccessWitness; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; @@ -44,14 +45,22 @@ import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldUpdater; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.util.Deque; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimap; +import io.vertx.core.json.JsonObject; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.slf4j.Logger; @@ -469,10 +478,6 @@ public TransactionProcessingResult processTransaction( .addArgument(sender.getBalance().toShortHexString()) .log(); final long gasUsedByTransaction = transaction.getGasLimit() - initialFrame.getRemainingGas(); - LOG.info( - "Gas used by transaction({}): {}", - transaction.getHash().toShortHexString(), - gasUsedByTransaction); operationTracer.traceEndTransaction( worldUpdater, transaction, @@ -482,6 +487,8 @@ public TransactionProcessingResult processTransaction( gasUsedByTransaction, 0L); + // checkTransactionGas(transaction.getHash(), gasUsedByTransaction); + // update the coinbase final var coinbase = worldState.getOrCreate(miningBeneficiary); final long usedGas = transaction.getGasLimit() - refundedGas; @@ -552,6 +559,43 @@ public TransactionProcessingResult processTransaction( } } + public static void checkTransactionGas(final Hash transactionHash, final long expectedGas) { + String url = + "https://rpc.verkle-gen-devnet-6.ethpandaops.io/x/eth_getTransactionReceipt/" + + transactionHash.toHexString(); + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).GET().build(); + + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + Pattern pattern = Pattern.compile("
    (.*?)
    ", Pattern.DOTALL); + Matcher matcher = pattern.matcher(response.body()); + if (matcher.find()) { + matcher.find(); + String jsonResponseText = matcher.group(1).replaceAll(""", "\""); + JsonObject jsonResponse = new JsonObject(jsonResponseText); + JsonObject result = jsonResponse.getJsonObject("result"); + long gasUsed = + Long.parseLong(result.getString("gasUsed").substring(2), 16); // Convert hex to decimal + + System.out.println(" expectedGas " + expectedGas); + if (gasUsed != expectedGas) { + System.out.println( + "Gas used (" + + gasUsed + + ") does not match expected gas (" + + expectedGas + + "). Transaction hash: " + + transactionHash); + } + } else { + throw new InterruptedException("invalid regex exception "); + } + } catch (IOException | InterruptedException e) { + // e.printStackTrace(); + } + } + public void process(final MessageFrame frame, final OperationTracer operationTracer) { final AbstractMessageProcessor executor = getMessageProcessor(frame.getType()); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/trielog/TrieLogFactoryImpl.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/trielog/TrieLogFactoryImpl.java index ae1de46e881..1da18d91d4a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/trielog/TrieLogFactoryImpl.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/trielog/TrieLogFactoryImpl.java @@ -76,8 +76,6 @@ public TrieLogLayer create(final TrieLogAccumulator accumulator, final BlockHead // by default do not persist empty reads to the trie log continue; } - - System.out.println(val.getPrior() + " " + val.getUpdated()); layer.addStorageChange(address, slotUpdate.getKey(), val.getPrior(), val.getUpdated()); } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java index 67ce54e7e0a..6a8243b0999 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/stateless/Eip4762AccessWitness.java @@ -10,6 +10,8 @@ import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.trie.verkle.adapter.TrieKeyAdapter; +import org.hyperledger.besu.ethereum.trie.verkle.hasher.PedersenHasher; import java.util.HashMap; import java.util.List; @@ -17,8 +19,6 @@ import java.util.Objects; import org.apache.tuweni.units.bigints.UInt256; -import org.hyperledger.besu.ethereum.trie.verkle.adapter.TrieKeyAdapter; -import org.hyperledger.besu.ethereum.trie.verkle.hasher.PedersenHasher; public class Eip4762AccessWitness implements org.hyperledger.besu.datatypes.AccessWitness { @@ -55,11 +55,17 @@ public List
    keys() { @Override public long touchAndChargeProofOfAbsence(final Address address) { long gas = 0; - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnReadAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = clampedAdd(gas, touchAddressOnReadAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); return gas; } @@ -68,8 +74,11 @@ public long touchAndChargeMessageCall(final Address address) { long gas = 0; - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnReadAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnReadAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); return gas; } @@ -79,8 +88,10 @@ public long touchAndChargeValueTransfer(final Address caller, final Address targ long gas = 0; - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(caller, zeroTreeIndex, BALANCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnWriteAndComputeGas(caller, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); return gas; } @@ -91,11 +102,14 @@ public long touchAndChargeContractCreateInit( long gas = 0; - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); if (createSendsValue) { - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); } return gas; } @@ -105,11 +119,17 @@ public long touchAndChargeContractCreateCompleted(final Address address) { long gas = 0; - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = clampedAdd(gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnWriteAndComputeGas(address, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); return gas; } @@ -120,11 +140,15 @@ public long touchTxOriginAndComputeGas(final Address origin) { long gas = 0; - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, VERSION_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, BALANCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, NONCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); + gas = clampedAdd(gas, touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = clampedAdd(gas, touchAddressOnWriteAndComputeGas(origin, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnReadAndComputeGas(origin, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); // modifying this after update on EIP-4762 to not charge simple transfers @@ -137,15 +161,21 @@ public long touchTxExistingAndComputeGas(final Address target, final boolean sen long gas = 0; - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, VERSION_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, NONCE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); + gas = clampedAdd(gas, touchAddressOnReadAndComputeGas(target, zeroTreeIndex, VERSION_LEAF_KEY)); + gas = clampedAdd(gas, touchAddressOnReadAndComputeGas(target, zeroTreeIndex, NONCE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_SIZE_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnReadAndComputeGas(target, zeroTreeIndex, CODE_KECCAK_LEAF_KEY)); if (sendsValue) { - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = + clampedAdd( + gas, touchAddressOnWriteAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); } else { - gas = clampedAdd(gas,touchAddressOnReadAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); + gas = + clampedAdd(gas, touchAddressOnReadAndComputeGas(target, zeroTreeIndex, BALANCE_LEAF_KEY)); } // modifying this after update on EIP-4762 to not charge simple transfers @@ -156,10 +186,13 @@ public long touchTxExistingAndComputeGas(final Address target, final boolean sen public long touchCodeChunksUponContractCreation(final Address address, final long codeLength) { long gas = 0; for (long i = 0; i < (codeLength + 30) / 31; i++) { - gas = clampedAdd(gas,touchAddressOnWriteAndComputeGas( - address, - CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), - CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH))); + gas = + clampedAdd( + gas, + touchAddressOnWriteAndComputeGas( + address, + CODE_OFFSET.add(i).divide(VERKLE_NODE_WIDTH), + CODE_OFFSET.add(i).mod(VERKLE_NODE_WIDTH))); } return gas; } @@ -213,7 +246,7 @@ public long touchAddressAndChargeGas( boolean logEnabled = false; long gas = 0; if (accessEvent.isBranchRead()) { - gas = clampedAdd(gas,WITNESS_BRANCH_READ_COST); + gas = clampedAdd(gas, WITNESS_BRANCH_READ_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessBranchReadCost " @@ -229,7 +262,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isChunkRead()) { - gas = clampedAdd(gas,WITNESS_CHUNK_READ_COST); + gas = clampedAdd(gas, WITNESS_CHUNK_READ_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessChunkReadCost " @@ -245,7 +278,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isBranchWrite()) { - gas = clampedAdd(gas,WITNESS_BRANCH_WRITE_COST); + gas = clampedAdd(gas, WITNESS_BRANCH_WRITE_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessBranchWriteCost " @@ -261,7 +294,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isChunkWrite()) { - gas = clampedAdd(gas,WITNESS_CHUNK_WRITE_COST); + gas = clampedAdd(gas, WITNESS_CHUNK_WRITE_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessChunkWriteCost " @@ -277,7 +310,7 @@ public long touchAddressAndChargeGas( } } if (accessEvent.isChunkFill()) { - gas = clampedAdd(gas,WITNESS_CHUNK_FILL_COST); + gas = clampedAdd(gas, WITNESS_CHUNK_FILL_COST); if (logEnabled) { System.out.println( "touchAddressAndChargeGas WitnessChunkFillCost " @@ -374,6 +407,8 @@ public ChunkAccessKey( @Override public List getStorageSlotTreeIndexes(final UInt256 storageKey) { - return List.of(TRIE_KEY_ADAPTER.locateStorageKeyOffset(storageKey),TRIE_KEY_ADAPTER.locateStorageKeySuffix(storageKey)); + return List.of( + TRIE_KEY_ADAPTER.locateStorageKeyOffset(storageKey), + TRIE_KEY_ADAPTER.locateStorageKeySuffix(storageKey)); } }