From b82953a78b99c0b7011d1de7b886de982991629e Mon Sep 17 00:00:00 2001 From: Luis Pinto Date: Sat, 30 Nov 2024 22:35:05 +0000 Subject: [PATCH] EIP-7709 Implement gas costs for BLOCKHASH implementation with system contract Signed-off-by: Luis Pinto --- .../mainnet/MainnetProtocolSpecs.java | 3 ++- .../ethereum/vm/Eip7709BlockHashLookup.java | 22 +++++++++++++++++++ ethereum/referencetests/build.gradle | 2 +- .../evm/operation/BlockHashOperation.java | 9 +++++++- 4 files changed, 33 insertions(+), 3 deletions(-) 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 766ae81a7aa..a7d8422fd7b 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 @@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.mainnet.ClearEmptyAccountStrategy.NotClearEmptyAccount; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder.BlockValidatorBuilder; import org.hyperledger.besu.ethereum.mainnet.blockhash.CancunBlockHashProcessor; +import org.hyperledger.besu.ethereum.mainnet.blockhash.Eip7709BlockHashProcessor; import org.hyperledger.besu.ethereum.mainnet.blockhash.FrontierBlockHashProcessor; import org.hyperledger.besu.ethereum.mainnet.blockhash.PragueBlockHashProcessor; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; @@ -991,7 +992,7 @@ static ProtocolSpecBuilder verkleDefinition( CoinbaseFeePriceCalculator.eip1559())) .withdrawalsProcessor(new WithdrawalsProcessor(clearEmptyAccountStrategy)) .executionWitnessValidator(new ExecutionWitnessValidator.AllowedExecutionWitness()) - .blockHashProcessor(new PragueBlockHashProcessor()) + .blockHashProcessor(new Eip7709BlockHashProcessor()) .blockHeaderFunctions(new VerkleDevnetBlockHeaderFunctions()) .name("Verkle"); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java index 0627a416109..8b939df9cf0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java @@ -37,6 +37,7 @@ public class Eip7709BlockHashLookup implements BlockHashLookup { private static final Logger LOG = LoggerFactory.getLogger(Eip7709BlockHashLookup.class); private static final long BLOCKHASH_SERVE_WINDOW = 256L; + private static final long WARM_STORAGE_READ_COST = 100L; private final Address contractAddress; private final long historyServeWindow; @@ -81,6 +82,12 @@ public Hash apply(final MessageFrame frame, final Long blockNumber) { return ZERO; } + final long cost = cost(frame, blockNumber); + if (frame.getRemainingGas() < cost) { + return Hash.EMPTY; + } + frame.decrementRemainingGas(cost); + final Hash cachedHash = hashByNumber.get(blockNumber); if (cachedHash != null) { return cachedHash; @@ -105,4 +112,19 @@ public Hash apply(final MessageFrame frame, final Long blockNumber) { hashByNumber.put(blockNumber, blockHash); return blockHash; } + + private long cost(final MessageFrame frame, final long blockNumber) { + final UInt256 key = UInt256.valueOf(blockNumber % BLOCKHASH_SERVE_WINDOW); + long gas = frame.getAccessWitness().touchAndChargeStorageLoad(contractAddress, key); + + if (gas == 0) { + return getWarmStorageReadCost(); + } + + return gas; + } + + protected long getWarmStorageReadCost() { + return WARM_STORAGE_READ_COST; + } } diff --git a/ethereum/referencetests/build.gradle b/ethereum/referencetests/build.gradle index a1d3a6ea8e9..e795fa901f9 100644 --- a/ethereum/referencetests/build.gradle +++ b/ethereum/referencetests/build.gradle @@ -260,7 +260,7 @@ dependencies { } verkleRefTestImplemention dependencies.create('ethereum:execution-spec-tests') { version { - strictly 'verkle@v0.0.8' + strictly 'verkle@v0.0.9-alpha-1' } artifact { name = 'fixtures' diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java index c88dc137093..b1d90e45897 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java @@ -50,11 +50,18 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { return new OperationResult(cost, null); } + final long remainingGas = frame.getRemainingGas(); final BlockHashLookup blockHashLookup = frame.getBlockHashLookup(); final Hash blockHash = blockHashLookup.apply(frame, blockArg.toLong()); + final long lookupCost = remainingGas - frame.getRemainingGas(); + if (Hash.EMPTY.equals(blockHash)) { + return new OperationResult(lookupCost, ExceptionalHaltReason.INSUFFICIENT_GAS); + } + // give lookupCost back as it will be taken after + frame.incrementRemainingGas(lookupCost); frame.pushStackItem(blockHash); - return new OperationResult(cost, null); + return new OperationResult(cost + lookupCost, null); } /**