diff --git a/config/src/main/java/org/hyperledger/besu/config/OptimismConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/OptimismConfigOptions.java index 5d201da91eb..008dd16e969 100644 --- a/config/src/main/java/org/hyperledger/besu/config/OptimismConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/OptimismConfigOptions.java @@ -45,7 +45,7 @@ public class OptimismConfigOptions { * @return the EIP1559 elasticity */ public OptionalLong getEIP1559Elasticity() { - return JsonUtil.getLong(optimismConfigRoot, "eip1559Elasticity"); + return JsonUtil.getLong(optimismConfigRoot, "eip1559elasticity"); } /** @@ -54,7 +54,7 @@ public OptionalLong getEIP1559Elasticity() { * @return the EIP1559 denominator */ public OptionalLong getEIP1559Denominator() { - return JsonUtil.getLong(optimismConfigRoot, "eip1559Denominator"); + return JsonUtil.getLong(optimismConfigRoot, "eip1559denominator"); } /** @@ -63,7 +63,7 @@ public OptionalLong getEIP1559Denominator() { * @return the EIP1559 denominatorCanyon */ public OptionalLong getEIP1559DenominatorCanyon() { - return JsonUtil.getLong(optimismConfigRoot, "eip1559DenominatorCanyon"); + return JsonUtil.getLong(optimismConfigRoot, "eip1559denominatorcanyon"); } /** diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java index ffe3b96b05a..17cfcb96cd9 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java @@ -42,6 +42,7 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; +import java.util.OptionalLong; import java.util.stream.LongStream; import java.util.stream.Stream; @@ -138,7 +139,8 @@ public JsonRpcResponse response(final JsonRpcRequestContext request) { explicitlyRequestedBaseFees.get( explicitlyRequestedBaseFees.size() - 1), lastBlockHeader.getGasUsed(), - feeMarket.targetGasUsed(lastBlockHeader)); + feeMarket.targetGasUsed(lastBlockHeader), + OptionalLong.of(chainHeadHeader.getTimestamp())); }) .orElse(Wei.ZERO)); diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index 586a11b20e2..de5fc5bd286 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -61,6 +61,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.OptionalLong; import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -445,7 +446,8 @@ private ProcessableBlockHeader createPendingBlockHeader( newBlockNumber, parentHeader.getBaseFee().orElse(Wei.ZERO), parentHeader.getGasUsed(), - feeMarket.targetGasUsed(parentHeader))) + feeMarket.targetGasUsed(parentHeader), + OptionalLong.of(timestamp))) .orElse(null); final Bytes32 prevRandao = maybePrevRandao.orElse(null); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index 6ba75ea625c..46abea708d1 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -316,7 +316,8 @@ public Wei getEffectivePriorityFeePerGas(final Optional maybeBaseFee) { .map( baseFee -> { if (getType().supports1559FeeMarket()) { - if (baseFee.greaterOrEqualThan(getMaxFeePerGas().get())) { + if (getType().equals(TransactionType.OPTIMISM_DEPOSIT) + || baseFee.greaterOrEqualThan(getMaxFeePerGas().get())) { return Wei.ZERO; } return UInt256s.min( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/feemarket/BaseFee.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/feemarket/BaseFee.java index 010d94a174c..23ca0175eef 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/feemarket/BaseFee.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/feemarket/BaseFee.java @@ -17,6 +17,8 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; +import java.util.OptionalLong; + public class BaseFee { private final Wei value; private final Wei delta; @@ -25,7 +27,7 @@ public class BaseFee { public BaseFee(final BaseFeeMarket feeMarket, final Wei value) { this.value = value; - this.delta = value.divide(feeMarket.getBasefeeMaxChangeDenominator()); + this.delta = value.divide(feeMarket.getBasefeeMaxChangeDenominator(OptionalLong.empty())); this.minNextValue = value.subtract(delta); this.maxNextValue = value.add(delta); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java index 62629dde665..19a0ce37184 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BaseFeeBlockBodyValidator.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet; +import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.Block; @@ -59,6 +60,9 @@ boolean validateTransactionGasPrice(final Block block) { .getTransactionPriceCalculator(); for (final Transaction transaction : transactions) { + if (transaction.getType().equals(TransactionType.OPTIMISM_DEPOSIT)) { + continue; + } final Optional baseFee = block.getHeader().getBaseFee(); final Wei price = transactionPriceCalculator.price(transaction, baseFee); if (price.compareTo(baseFee.orElseThrow()) < 0) { 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 6719b632e3b..d8221c9e27d 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 @@ -443,7 +443,10 @@ static ProtocolSpecBuilder londonDefinition( final BaseFeeMarket londonFeeMarket = genesisConfigOptions.isZeroBaseFee() ? FeeMarket.zeroBaseFee(londonForkBlockNumber) - : FeeMarket.london(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas()); + : FeeMarket.london( + londonForkBlockNumber, + genesisConfigOptions.getBaseFeePerGas(), + Optional.of(genesisConfigOptions)); return berlinDefinition( chainId, configContractSizeLimit, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/BaseFeeMarket.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/BaseFeeMarket.java index 4678092003d..a82aff96754 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/BaseFeeMarket.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/BaseFeeMarket.java @@ -17,6 +17,8 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; +import java.util.OptionalLong; + public interface BaseFeeMarket extends FeeMarket { enum ValidationMode { @@ -30,7 +32,7 @@ default boolean implementsBaseFee() { return true; } - long getBasefeeMaxChangeDenominator(); + long getBasefeeMaxChangeDenominator(OptionalLong time); Wei getInitialBasefee(); @@ -51,7 +53,8 @@ Wei computeBaseFee( final long blockNumber, final Wei parentBaseFee, final long parentBlockGasUsed, - final long targetGasUsed); + final long targetGasUsed, + final OptionalLong time); ValidationMode baseFeeValidationMode(final long blockNumber); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/CancunFeeMarket.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/CancunFeeMarket.java index ab46beadca5..25899f5a4a6 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/CancunFeeMarket.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/CancunFeeMarket.java @@ -30,7 +30,7 @@ public class CancunFeeMarket extends LondonFeeMarket { public CancunFeeMarket( final long londonForkBlockNumber, final Optional baseFeePerGasOverride) { - super(londonForkBlockNumber, baseFeePerGasOverride); + super(londonForkBlockNumber, baseFeePerGasOverride, Optional.empty()); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/FeeMarket.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/FeeMarket.java index 637ffb471ec..1829737ae99 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/FeeMarket.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/FeeMarket.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet.feemarket; +import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Transaction; @@ -36,12 +37,14 @@ default boolean implementsDataFee() { boolean satisfiesFloorTxFee(Transaction txn); static BaseFeeMarket london(final long londonForkBlockNumber) { - return london(londonForkBlockNumber, Optional.empty()); + return london(londonForkBlockNumber, Optional.empty(), Optional.empty()); } static BaseFeeMarket london( - final long londonForkBlockNumber, final Optional baseFeePerGasOverride) { - return new LondonFeeMarket(londonForkBlockNumber, baseFeePerGasOverride); + final long londonForkBlockNumber, + final Optional baseFeePerGasOverride, + final Optional chainOptions) { + return new LondonFeeMarket(londonForkBlockNumber, baseFeePerGasOverride, chainOptions); } static BaseFeeMarket cancun( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java index 2fff3a629fa..e98f1bcc76d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java @@ -15,11 +15,13 @@ package org.hyperledger.besu.ethereum.mainnet.feemarket; import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.feemarket.TransactionPriceCalculator; import java.util.Optional; +import java.util.OptionalLong; import org.apache.tuweni.units.bigints.UInt256s; import org.slf4j.Logger; @@ -39,28 +41,48 @@ public class LondonFeeMarket implements BaseFeeMarket { private final long londonForkBlockNumber; private final TransactionPriceCalculator txPriceCalculator; private final Wei baseFeeFloor; + private final Optional chainOptions; public LondonFeeMarket(final long londonForkBlockNumber) { - this(londonForkBlockNumber, Optional.empty()); + this(londonForkBlockNumber, Optional.empty(), Optional.empty()); } public LondonFeeMarket( - final long londonForkBlockNumber, final Optional baseFeePerGasOverride) { - this(TransactionPriceCalculator.eip1559(), londonForkBlockNumber, baseFeePerGasOverride); + final long londonForkBlockNumber, + final Optional baseFeePerGasOverride, + final Optional chainOptions) { + this( + TransactionPriceCalculator.eip1559(), + londonForkBlockNumber, + baseFeePerGasOverride, + chainOptions); } protected LondonFeeMarket( final TransactionPriceCalculator txPriceCalculator, final long londonForkBlockNumber, - final Optional baseFeePerGasOverride) { + final Optional baseFeePerGasOverride, + final Optional chainOptions) { this.txPriceCalculator = txPriceCalculator; this.londonForkBlockNumber = londonForkBlockNumber; this.baseFeeInitialValue = baseFeePerGasOverride.orElse(DEFAULT_BASEFEE_INITIAL_VALUE); this.baseFeeFloor = baseFeeInitialValue.isZero() ? Wei.ZERO : DEFAULT_BASEFEE_FLOOR; + this.chainOptions = chainOptions; } @Override - public long getBasefeeMaxChangeDenominator() { + public long getBasefeeMaxChangeDenominator(final OptionalLong time) { + if (time.isPresent() && this.chainOptions.isPresent()) { + if (this.chainOptions.get().isCanyon(time.getAsLong())) { + return chainOptions + .get() + .getOptimismConfigOptions() + .getEIP1559DenominatorCanyon() + .orElseThrow(); + } else { + return chainOptions.get().getOptimismConfigOptions().getEIP1559Denominator().orElseThrow(); + } + } return DEFAULT_BASEFEE_MAX_CHANGE_DENOMINATOR; } @@ -71,6 +93,9 @@ public Wei getInitialBasefee() { @Override public long getSlackCoefficient() { + if (chainOptions.isPresent() && chainOptions.get().isOptimism()) { + return chainOptions.get().getOptimismConfigOptions().getEIP1559Elasticity().orElseThrow(); + } return DEFAULT_SLACK_COEFFICIENT; } @@ -94,7 +119,8 @@ public Wei computeBaseFee( final long blockNumber, final Wei parentBaseFee, final long parentBlockGasUsed, - final long targetGasUsed) { + final long targetGasUsed, + final OptionalLong time) { if (londonForkBlockNumber == blockNumber) { return getInitialBasefee(); } @@ -105,16 +131,16 @@ public Wei computeBaseFee( return parentBaseFee; } else if (parentBlockGasUsed > targetGasUsed) { gasDelta = parentBlockGasUsed - targetGasUsed; - final long denominator = getBasefeeMaxChangeDenominator(); + final long denominator = getBasefeeMaxChangeDenominator(time); feeDelta = UInt256s.max( parentBaseFee.multiply(gasDelta).divide(targetGasUsed).divide(denominator), Wei.ONE); baseFee = parentBaseFee.add(feeDelta); } else { gasDelta = targetGasUsed - parentBlockGasUsed; - final long denominator = getBasefeeMaxChangeDenominator(); + final long denominator = getBasefeeMaxChangeDenominator(time); feeDelta = parentBaseFee.multiply(gasDelta).divide(targetGasUsed).divide(denominator); - baseFee = parentBaseFee.subtract(feeDelta); + baseFee = UInt256s.max(parentBaseFee.subtract(feeDelta), Wei.ZERO); } LOG.trace( "block #{} parentBaseFee: {} parentGasUsed: {} parentGasTarget: {} baseFee: {}", diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarket.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarket.java index c2f406cad04..26e2aa7e99e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarket.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarket.java @@ -17,11 +17,12 @@ import org.hyperledger.besu.datatypes.Wei; import java.util.Optional; +import java.util.OptionalLong; public class ZeroBaseFeeMarket extends LondonFeeMarket { public ZeroBaseFeeMarket(final long londonForkBlockNumber) { - super(londonForkBlockNumber, Optional.of(Wei.ZERO)); + super(londonForkBlockNumber, Optional.of(Wei.ZERO), Optional.empty()); } @Override @@ -29,7 +30,8 @@ public Wei computeBaseFee( final long blockNumber, final Wei parentBaseFee, final long parentBlockGasUsed, - final long targetGasUsed) { + final long targetGasUsed, + final OptionalLong time) { return Wei.ZERO; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BaseFeeMarketBlockHeaderGasPriceValidationRule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BaseFeeMarketBlockHeaderGasPriceValidationRule.java index 4a972868389..c7ab92f0a20 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BaseFeeMarketBlockHeaderGasPriceValidationRule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BaseFeeMarketBlockHeaderGasPriceValidationRule.java @@ -22,6 +22,8 @@ import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; +import java.util.OptionalLong; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +61,11 @@ public boolean validate(final BlockHeader header, final BlockHeader parent) { final long targetGasUsed = baseFeeMarket.targetGasUsed(parent); final Wei expectedBaseFee = baseFeeMarket.computeBaseFee( - header.getNumber(), parentBaseFee, parent.getGasUsed(), targetGasUsed); + header.getNumber(), + parentBaseFee, + parent.getGasUsed(), + targetGasUsed, + OptionalLong.of(header.getTimestamp())); if (!expectedBaseFee.equals(currentBaseFee)) { LOG.info( "Invalid block header: basefee {} does not equal expected basefee {}", diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarketTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarketTest.java index 4047c647aec..abc3423dd08 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarketTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/feemarket/ZeroBaseFeeMarketTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.TransactionTestFixture; import java.util.Optional; +import java.util.OptionalLong; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -43,7 +44,7 @@ public void setUp() throws Exception { @Test public void getBasefeeMaxChangeDenominatorShouldUseLondonDefault() { - assertThat(zeroBaseFeeMarket.getBasefeeMaxChangeDenominator()) + assertThat(zeroBaseFeeMarket.getBasefeeMaxChangeDenominator(OptionalLong.empty())) .isEqualTo(LondonFeeMarket.DEFAULT_BASEFEE_MAX_CHANGE_DENOMINATOR); } @@ -100,7 +101,8 @@ public void satisfiesFloorTxCostWhenGasFeeIsZero() { @Test public void computeBaseFeeReturnsZero() { - assertThat(zeroBaseFeeMarket.computeBaseFee(1L, Wei.of(8), 1L, 2L)).isEqualTo(Wei.ZERO); + assertThat(zeroBaseFeeMarket.computeBaseFee(1L, Wei.of(8), 1L, 2L, OptionalLong.empty())) + .isEqualTo(Wei.ZERO); } @Test diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java index f5ee0de2ae4..c7093ebcbeb 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java @@ -27,6 +27,7 @@ import java.util.Comparator; import java.util.Optional; +import java.util.OptionalLong; import java.util.function.BiFunction; import java.util.function.Supplier; @@ -137,7 +138,8 @@ private Wei calculateNextBlockBaseFee(final FeeMarket feeMarket, final BlockHead blockHeader.getNumber() + 1, blockHeader.getBaseFee().orElse(Wei.ZERO), blockHeader.getGasUsed(), - baseFeeMarket.targetGasUsed(blockHeader)); + baseFeeMarket.targetGasUsed(blockHeader), + OptionalLong.of(blockHeader.getTimestamp())); } return Wei.ZERO; }