prague fee market for blob gas (#8064)

* prague fee market for blob gas

Signed-off-by: garyschulte <garyschulte@gmail.com>

* Fix wiring and unit test

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

---------

Signed-off-by: garyschulte <garyschulte@gmail.com>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
This commit is contained in:
garyschulte
2024-12-21 11:42:20 -08:00
committed by GitHub
parent b3b33da540
commit 2909ea4776
6 changed files with 146 additions and 5 deletions

View File

@@ -15,7 +15,6 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -323,8 +322,7 @@ public class EthGetTransactionReceiptTest {
}
private void mockProtocolSpec(final BlockHeader blockHeader) {
FeeMarket feeMarket = mock(CancunFeeMarket.class);
when(feeMarket.blobGasPricePerGas(any())).thenCallRealMethod();
FeeMarket feeMarket = new CancunFeeMarket(0, Optional.empty());
ProtocolSpec spec = mock(ProtocolSpec.class);
when(spec.getFeeMarket()).thenReturn(feeMarket);
when(spec.getGasCalculator()).thenReturn(new CancunGasCalculator());

View File

@@ -815,6 +815,18 @@ public abstract class MainnetProtocolSpecs {
final java.util.function.Supplier<GasCalculator> pragueGasCalcSupplier =
() -> new PragueGasCalculator(pragueBlobSchedule.getTarget());
final BaseFeeMarket pragueFeeMarket;
if (genesisConfigOptions.isZeroBaseFee()) {
pragueFeeMarket = FeeMarket.zeroBaseFee(londonForkBlockNumber);
} else if (genesisConfigOptions.isFixedBaseFee()) {
pragueFeeMarket =
FeeMarket.fixedBaseFee(
londonForkBlockNumber, miningConfiguration.getMinTransactionGasPrice());
} else {
pragueFeeMarket =
FeeMarket.prague(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas());
}
return cancunDefinition(
chainId,
enableRevertReason,
@@ -823,6 +835,7 @@ public abstract class MainnetProtocolSpecs {
miningConfiguration,
isParallelTxProcessingEnabled,
metricsSystem)
.feeMarket(pragueFeeMarket)
.gasCalculator(pragueGasCalcSupplier)
// EIP-7840 Blob schedule | EIP-7691 6/9 blob increase
.gasLimitCalculatorBuilder(

View File

@@ -25,7 +25,7 @@ import org.slf4j.LoggerFactory;
public class CancunFeeMarket extends LondonFeeMarket {
private static final Logger LOG = LoggerFactory.getLogger(CancunFeeMarket.class);
private static final BigInteger BLOB_GAS_PRICE = BigInteger.ONE;
protected static final BigInteger BLOB_GAS_PRICE = BigInteger.ONE;
private static final BigInteger BLOB_GAS_PRICE_UPDATE_FRACTION = BigInteger.valueOf(3338477);
public CancunFeeMarket(
@@ -53,7 +53,7 @@ public class CancunFeeMarket extends LondonFeeMarket {
return blobGasPrice;
}
private BigInteger fakeExponential(
protected BigInteger fakeExponential(
final BigInteger factor, final BigInteger numerator, final BigInteger denominator) {
int i = 1;
BigInteger output = BigInteger.ZERO;

View File

@@ -49,6 +49,11 @@ public interface FeeMarket {
return new CancunFeeMarket(londonForkBlockNumber, baseFeePerGasOverride);
}
static BaseFeeMarket prague(
final long londonForkBlockNumber, final Optional<Wei> baseFeePerGasOverride) {
return new PragueFeeMarket(londonForkBlockNumber, baseFeePerGasOverride);
}
static BaseFeeMarket zeroBaseFee(final long londonForkBlockNumber) {
return new ZeroBaseFeeMarket(londonForkBlockNumber);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright contributors to Besu.
*
* 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.ethereum.mainnet.feemarket;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
import java.math.BigInteger;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PragueFeeMarket extends CancunFeeMarket {
private static final BigInteger BLOB_BASE_FEE_UPDATE_FRACTION_ELECTRA =
BigInteger.valueOf(5007716);
private static final Logger LOG = LoggerFactory.getLogger(PragueFeeMarket.class);
public PragueFeeMarket(
final long londonForkBlockNumber, final Optional<Wei> baseFeePerGasOverride) {
super(londonForkBlockNumber, baseFeePerGasOverride);
}
@Override
public Wei blobGasPricePerGas(final BlobGas excessBlobGas) {
final var blobGasPrice =
Wei.of(
fakeExponential(
BLOB_GAS_PRICE,
excessBlobGas.toBigInteger(),
BLOB_BASE_FEE_UPDATE_FRACTION_ELECTRA));
LOG.atTrace()
.setMessage("parentExcessBlobGas: {} blobGasPrice: {}")
.addArgument(excessBlobGas::toShortHexString)
.addArgument(blobGasPrice::toHexString)
.log();
return blobGasPrice;
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.ethereum.mainnet.feemarket;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.hyperledger.besu.datatypes.BlobGas;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
class PragueFeeMarketTest {
private static final int BLOB_GAS_PER_BLOB = 131072;
/**
* from: https://eips.ethereum.org/EIPS/eip-7691 The BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE value in
* this EIP is chosen as the mid-point between keeping the responsiveness to full blobs and no
* blobs constant:
*
* <p>full blobs: basefee increases by ~8.2% no blobs: basefee decreases by ~14.5%
*/
@Test
void dataPricePerGas() {
PragueFeeMarket pragueFeeMarket = new PragueFeeMarket(0, Optional.empty());
// when no excess blob gas, data price per gas is 1
assertEquals(1, pragueFeeMarket.blobGasPricePerGas(BlobGas.ZERO).getAsBigInteger().intValue());
record BlobGasPricing(long excess, long price) {}
List<BlobGasPricing> testVector = new ArrayList<>();
int numBlobs = 1;
long price = 1;
while (price <= 1000) {
price = blobGasPrice(BlobGas.of(numBlobs * BLOB_GAS_PER_BLOB));
var testCase = new BlobGasPricing(numBlobs * BLOB_GAS_PER_BLOB, price);
testVector.add(testCase);
numBlobs++;
}
testVector.stream()
.forEach(
blobGasPricing -> {
assertEquals(
blobGasPricing.price,
pragueFeeMarket
.blobGasPricePerGas(BlobGas.of(blobGasPricing.excess))
.getAsBigInteger()
.intValue());
});
}
private long blobGasPrice(final BlobGas excess) {
double dgufDenominator = 5007716;
double fakeExpo = excess.getValue().longValue() / dgufDenominator;
return (long) (1 * Math.exp(fakeExpo));
}
}