mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 15:37:54 -05:00
EIP-7742 - gas calculation using target_blobs_per_block (#7823)
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
This commit is contained in:
@@ -16,10 +16,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -124,7 +121,6 @@ public class TransactionTracerTest {
|
||||
when(blockchain.getChainHeadHeader()).thenReturn(blockHeader);
|
||||
when(protocolSpec.getGasCalculator()).thenReturn(gasCalculator);
|
||||
when(protocolContext.getBadBlockManager()).thenReturn(badBlockManager);
|
||||
lenient().when(gasCalculator.computeExcessBlobGas(anyLong(), anyInt())).thenReturn(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.blockcreation.txselection.selectors;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -61,7 +61,7 @@ class BlobSizeTransactionSelectorTest {
|
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
|
||||
private static final KeyPair KEYS = SIGNATURE_ALGORITHM.get().generateKeyPair();
|
||||
|
||||
private static final long BLOB_GAS_PER_BLOB = CancunGasCalculator.BLOB_GAS_PER_BLOB;
|
||||
private static final long BLOB_GAS_PER_BLOB = new CancunGasCalculator().getBlobGasPerBlob();
|
||||
private static final int MAX_BLOBS = 6;
|
||||
private static final long MAX_BLOB_GAS = BLOB_GAS_PER_BLOB * MAX_BLOBS;
|
||||
|
||||
@@ -89,8 +89,8 @@ class BlobSizeTransactionSelectorTest {
|
||||
@Test
|
||||
void firstBlobTransactionIsSelected() {
|
||||
when(blockSelectionContext.gasLimitCalculator().currentBlobGasLimit()).thenReturn(MAX_BLOB_GAS);
|
||||
when(blockSelectionContext.gasCalculator().blobGasCost(anyInt()))
|
||||
.thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Integer.class));
|
||||
when(blockSelectionContext.gasCalculator().blobGasCost(anyLong()))
|
||||
.thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Long.class));
|
||||
|
||||
final var selector = new BlobSizeTransactionSelector(blockSelectionContext);
|
||||
|
||||
@@ -131,8 +131,8 @@ class BlobSizeTransactionSelectorTest {
|
||||
@Test
|
||||
void returnsTooLargeForRemainingBlobGas() {
|
||||
when(blockSelectionContext.gasLimitCalculator().currentBlobGasLimit()).thenReturn(MAX_BLOB_GAS);
|
||||
when(blockSelectionContext.gasCalculator().blobGasCost(anyInt()))
|
||||
.thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Integer.class));
|
||||
when(blockSelectionContext.gasCalculator().blobGasCost(anyLong()))
|
||||
.thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Long.class));
|
||||
|
||||
final var selector = new BlobSizeTransactionSelector(blockSelectionContext);
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
|
||||
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
||||
import org.hyperledger.besu.evm.operation.BlockHashOperation;
|
||||
import org.hyperledger.besu.evm.tracing.OperationTracer;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldState;
|
||||
@@ -174,7 +173,8 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
|
||||
currentGasUsed += transaction.getGasLimit() - transactionProcessingResult.getGasRemaining();
|
||||
if (transaction.getVersionedHashes().isPresent()) {
|
||||
currentBlobGasUsed +=
|
||||
(transaction.getVersionedHashes().get().size() * CancunGasCalculator.BLOB_GAS_PER_BLOB);
|
||||
(transaction.getVersionedHashes().get().size()
|
||||
* protocolSpec.getGasCalculator().getBlobGasPerBlob());
|
||||
}
|
||||
|
||||
final TransactionReceipt transactionReceipt =
|
||||
|
||||
@@ -36,7 +36,8 @@ public class ExcessBlobGasCalculator {
|
||||
.getGasCalculator()
|
||||
.computeExcessBlobGas(
|
||||
parentHeader.getExcessBlobGas().map(BlobGas::toLong).orElse(0L),
|
||||
parentHeader.getBlobGasUsed().orElse(0L));
|
||||
parentHeader.getBlobGasUsed().orElse(0L),
|
||||
parentHeader.getTargetBlobsPerBlock());
|
||||
return BlobGas.of(headerExcess);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.hyperledger.besu.ethereum.mainnet.headervalidationrules;
|
||||
import org.hyperledger.besu.datatypes.BlobGas;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule;
|
||||
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -45,7 +44,8 @@ public class BlobGasValidationRule implements DetachedBlockHeaderValidationRule
|
||||
long parentBlobGasUsed = parent.getBlobGasUsed().orElse(0L);
|
||||
|
||||
long calculatedExcessBlobGas =
|
||||
gasCalculator.computeExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed);
|
||||
gasCalculator.computeExcessBlobGas(
|
||||
parentExcessBlobGas, parentBlobGasUsed, parent.getTargetBlobsPerBlock());
|
||||
|
||||
if (headerExcessBlobGas != calculatedExcessBlobGas) {
|
||||
LOG.info(
|
||||
@@ -55,10 +55,9 @@ public class BlobGasValidationRule implements DetachedBlockHeaderValidationRule
|
||||
return false;
|
||||
}
|
||||
long headerBlobGasUsed = header.getBlobGasUsed().orElse(0L);
|
||||
if (headerBlobGasUsed % CancunGasCalculator.BLOB_GAS_PER_BLOB != 0) {
|
||||
if (headerBlobGasUsed % gasCalculator.getBlobGasPerBlob() != 0) {
|
||||
LOG.info(
|
||||
"blob gas used must be multiple of GAS_PER_BLOB ({})",
|
||||
CancunGasCalculator.BLOB_GAS_PER_BLOB);
|
||||
"blob gas used must be multiple of GAS_PER_BLOB ({})", gasCalculator.getBlobGasPerBlob());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -24,7 +24,7 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -589,7 +589,7 @@ public class MainnetTransactionValidatorTest {
|
||||
|
||||
@Test
|
||||
public void shouldAcceptTransactionWithAtLeastOneBlob() {
|
||||
when(gasCalculator.blobGasCost(anyInt())).thenReturn(2L);
|
||||
when(gasCalculator.blobGasCost(anyLong())).thenReturn(2L);
|
||||
final TransactionValidator validator =
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
|
||||
@@ -20,26 +20,37 @@ import org.hyperledger.besu.datatypes.BlobGas;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
||||
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests for the {@link BlobGasValidationRule} class. */
|
||||
public class BlobGasValidationRuleTest {
|
||||
|
||||
private CancunGasCalculator gasCalculator;
|
||||
private BlobGasValidationRule blobGasValidationRule;
|
||||
private CancunGasCalculator cancunGasCalculator;
|
||||
private BlobGasValidationRule cancunBlobGasValidationRule;
|
||||
|
||||
private PragueGasCalculator pragueGasCalculator;
|
||||
private BlobGasValidationRule pragueBlobGasValidationRule;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
gasCalculator = new CancunGasCalculator();
|
||||
blobGasValidationRule = new BlobGasValidationRule(gasCalculator);
|
||||
cancunGasCalculator = new CancunGasCalculator();
|
||||
cancunBlobGasValidationRule = new BlobGasValidationRule(cancunGasCalculator);
|
||||
|
||||
pragueGasCalculator = new PragueGasCalculator();
|
||||
pragueBlobGasValidationRule = new BlobGasValidationRule(pragueGasCalculator);
|
||||
}
|
||||
|
||||
/** Tests that the header blob gas matches the calculated blob gas and passes validation. */
|
||||
/**
|
||||
* Cancun EIP-4844 - Tests that the header blob gas matches the calculated blob gas and passes
|
||||
* validation.
|
||||
*/
|
||||
@Test
|
||||
public void validateHeader_BlobGasMatchesCalculated_SuccessValidation() {
|
||||
long target = gasCalculator.getTargetBlobGasPerBlock();
|
||||
long target = cancunGasCalculator.getTargetBlobGasPerBlock();
|
||||
|
||||
// Create parent header
|
||||
final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture();
|
||||
@@ -52,15 +63,16 @@ public class BlobGasValidationRuleTest {
|
||||
headerBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
final BlockHeader header = headerBuilder.buildHeader();
|
||||
|
||||
assertThat(blobGasValidationRule.validate(header, parentHeader)).isTrue();
|
||||
assertThat(cancunBlobGasValidationRule.validate(header, parentHeader)).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the header blob gas is different from the calculated blob gas and fails validation.
|
||||
* Cancun EIP-4844 - Tests that the header blob gas is different from the calculated blob gas and
|
||||
* fails validation.
|
||||
*/
|
||||
@Test
|
||||
public void validateHeader_BlobGasDifferentFromCalculated_FailsValidation() {
|
||||
long target = gasCalculator.getTargetBlobGasPerBlock();
|
||||
long target = cancunGasCalculator.getTargetBlobGasPerBlock();
|
||||
|
||||
// Create parent header
|
||||
final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture();
|
||||
@@ -72,6 +84,48 @@ public class BlobGasValidationRuleTest {
|
||||
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
|
||||
final BlockHeader header = headerBuilder.buildHeader();
|
||||
|
||||
assertThat(blobGasValidationRule.validate(header, parentHeader)).isFalse();
|
||||
assertThat(cancunBlobGasValidationRule.validate(header, parentHeader)).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prague EIP-7742 - Tests that the header blob gas matches the calculated blob gas and passes
|
||||
* validation.
|
||||
*/
|
||||
@Test
|
||||
public void validateHeader_BlobGasMatchesCalculated_SuccessValidation_Prague_Target3() {
|
||||
// Create parent header
|
||||
final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture();
|
||||
parentBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
parentBuilder.blobGasUsed(pragueGasCalculator.blobGasCost(3));
|
||||
parentBuilder.targetBlobsPerBlock(UInt64.valueOf(3));
|
||||
final BlockHeader parentHeader = parentBuilder.buildHeader();
|
||||
|
||||
// Create block header with matching excessBlobGas
|
||||
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
|
||||
headerBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
final BlockHeader header = headerBuilder.buildHeader();
|
||||
|
||||
assertThat(pragueBlobGasValidationRule.validate(header, parentHeader)).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prague EIP-7742 - Tests that the header blob gas matches the calculated blob gas and passes
|
||||
* validation.
|
||||
*/
|
||||
@Test
|
||||
public void validateHeader_BlobGasMatchesCalculated_SuccessValidation_Prague_Target4() {
|
||||
// Create parent header
|
||||
final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture();
|
||||
parentBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
parentBuilder.blobGasUsed(pragueGasCalculator.blobGasCost(4));
|
||||
parentBuilder.targetBlobsPerBlock(UInt64.valueOf(4));
|
||||
final BlockHeader parentHeader = parentBuilder.buildHeader();
|
||||
|
||||
// Create block header with matching excessBlobGas
|
||||
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
|
||||
headerBuilder.excessBlobGas(BlobGas.of(1L));
|
||||
final BlockHeader header = headerBuilder.buildHeader();
|
||||
|
||||
assertThat(pragueBlobGasValidationRule.validate(header, parentHeader)).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,13 +44,13 @@ public class CancunGasCalculator extends ShanghaiGasCalculator {
|
||||
private static final long TSTORE_GAS = WARM_STORAGE_READ_COST;
|
||||
|
||||
/**
|
||||
* The blob gas cost per blob. This is the gas cost for each blob of blob that is added to the
|
||||
* The blob gas cost per blob. This is the gas cost for each blob of data that is added to the
|
||||
* block.
|
||||
*/
|
||||
public static final long BLOB_GAS_PER_BLOB = 1 << 17;
|
||||
private static final long BLOB_GAS_PER_BLOB = 1 << 17;
|
||||
|
||||
/** The target blob gas per block. */
|
||||
public static final long TARGET_BLOB_GAS_PER_BLOCK = 0x60000;
|
||||
static final long TARGET_BLOB_GAS_PER_BLOCK = 0x60000;
|
||||
|
||||
// EIP-1153
|
||||
@Override
|
||||
@@ -64,8 +64,13 @@ public class CancunGasCalculator extends ShanghaiGasCalculator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long blobGasCost(final int blobCount) {
|
||||
return BLOB_GAS_PER_BLOB * blobCount;
|
||||
public long blobGasCost(final long blobCount) {
|
||||
return getBlobGasPerBlob() * blobCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBlobGasPerBlob() {
|
||||
return BLOB_GAS_PER_BLOB;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,35 +81,4 @@ public class CancunGasCalculator extends ShanghaiGasCalculator {
|
||||
public long getTargetBlobGasPerBlock() {
|
||||
return TARGET_BLOB_GAS_PER_BLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the excess blob gas for a given block based on the parent's excess blob gas and blob
|
||||
* gas used. If the sum of parent's excess blob gas and parent's blob gas used is less than the
|
||||
* target blob gas per block, the excess blob gas is calculated as 0. Otherwise, it is computed as
|
||||
* the difference between the sum and the target blob gas per block.
|
||||
*
|
||||
* @param parentExcessBlobGas The excess blob gas of the parent block.
|
||||
* @param newBlobs blob gas incurred by current block
|
||||
* @return The excess blob gas for the current block.
|
||||
*/
|
||||
@Override
|
||||
public long computeExcessBlobGas(final long parentExcessBlobGas, final int newBlobs) {
|
||||
final long consumedBlobGas = blobGasCost(newBlobs);
|
||||
final long currentExcessBlobGas = parentExcessBlobGas + consumedBlobGas;
|
||||
|
||||
if (currentExcessBlobGas < TARGET_BLOB_GAS_PER_BLOCK) {
|
||||
return 0L;
|
||||
}
|
||||
return currentExcessBlobGas - TARGET_BLOB_GAS_PER_BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long computeExcessBlobGas(final long parentExcessBlobGas, final long parentBlobGasUsed) {
|
||||
final long currentExcessBlobGas = parentExcessBlobGas + parentBlobGasUsed;
|
||||
|
||||
if (currentExcessBlobGas < TARGET_BLOB_GAS_PER_BLOCK) {
|
||||
return 0L;
|
||||
}
|
||||
return currentExcessBlobGas - TARGET_BLOB_GAS_PER_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,10 +40,12 @@ import org.hyperledger.besu.evm.precompile.SHA256PrecompiledContract;
|
||||
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
|
||||
|
||||
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;
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
|
||||
/**
|
||||
* Provides various gas cost lookups and calculations used during block processing.
|
||||
@@ -613,37 +615,51 @@ public interface GasCalculator {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blob gas cost per blob. This is the gas cost for each blob of data that is added to
|
||||
* the block.
|
||||
*
|
||||
* @return the blob gas cost per blob
|
||||
*/
|
||||
default long getBlobGasPerBlob() {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the gas cost given the number of blobs
|
||||
*
|
||||
* @param blobCount the number of blobs
|
||||
* @return the total gas cost
|
||||
*/
|
||||
default long blobGasCost(final int blobCount) {
|
||||
default long blobGasCost(final long blobCount) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the new value for the excess blob gas, given the parent value and the count of new
|
||||
* blobs
|
||||
* Compute the new value for the excess blob gas, given the parent value, the parent blob gas used
|
||||
* and the parent target blobs per block, if present. Used from Cancun onwards. Presence of
|
||||
* parentTargetBlobsPerBlock implies EIP-7442/Prague enabled. Default to Cancun constant target
|
||||
* gas value if parentTargetBlobsPerBlock is not present.
|
||||
*
|
||||
* @param parentExcessBlobGas excess blob gas from the parent
|
||||
* @param newBlobs count of new blobs
|
||||
* @param parentBlobGasUsed blob gas used from the parent
|
||||
* @param parentTargetBlobsPerBlock the optional target blobs per block from the parent
|
||||
* @return the new excess blob gas value
|
||||
*/
|
||||
default long computeExcessBlobGas(final long parentExcessBlobGas, final int newBlobs) {
|
||||
return 0L;
|
||||
}
|
||||
default long computeExcessBlobGas(
|
||||
final long parentExcessBlobGas,
|
||||
final long parentBlobGasUsed,
|
||||
final Optional<UInt64> parentTargetBlobsPerBlock) {
|
||||
final long parentTargetBlobGas =
|
||||
parentTargetBlobsPerBlock
|
||||
.map(blobCount -> blobGasCost(blobCount.toLong()))
|
||||
.orElse(CancunGasCalculator.TARGET_BLOB_GAS_PER_BLOCK);
|
||||
final long currentExcessBlobGas = parentExcessBlobGas + parentBlobGasUsed;
|
||||
|
||||
/**
|
||||
* Compute the new value for the excess blob gas, given the parent value and the blob gas used
|
||||
*
|
||||
* @param parentExcessBlobGas excess blob gas from the parent
|
||||
* @param blobGasUsed blob gas used
|
||||
* @return the new excess blob gas value
|
||||
*/
|
||||
default long computeExcessBlobGas(final long parentExcessBlobGas, final long blobGasUsed) {
|
||||
return 0L;
|
||||
if (currentExcessBlobGas < parentTargetBlobGas) {
|
||||
return 0L;
|
||||
}
|
||||
return currentExcessBlobGas - parentTargetBlobGas;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,31 +17,37 @@ package org.hyperledger.besu.evm.gascalculator;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class CancunGasCalculatorTest {
|
||||
|
||||
private final CancunGasCalculator gasCalculator = new CancunGasCalculator();
|
||||
private final CancunGasCalculator cancunGasCalculator = new CancunGasCalculator();
|
||||
|
||||
@ParameterizedTest(name = "{index} - parent gas {0}, used gas {1}, new excess {2}")
|
||||
@MethodSource("blobGasses")
|
||||
public void shouldCalculateExcessBlobGasCorrectly(
|
||||
final long parentExcess, final long used, final long expected) {
|
||||
assertThat(gasCalculator.computeExcessBlobGas(parentExcess, (int) used)).isEqualTo(expected);
|
||||
final long usedBlobGas = cancunGasCalculator.blobGasCost(used);
|
||||
assertThat(
|
||||
cancunGasCalculator.computeExcessBlobGas(parentExcess, usedBlobGas, Optional.empty()))
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
static Iterable<Arguments> blobGasses() {
|
||||
Iterable<Arguments> blobGasses() {
|
||||
long targetGasPerBlock = CancunGasCalculator.TARGET_BLOB_GAS_PER_BLOCK;
|
||||
return List.of(
|
||||
Arguments.of(0L, 0L, 0L),
|
||||
Arguments.of(targetGasPerBlock, 0L, 0L),
|
||||
Arguments.of(0L, 3, 0L),
|
||||
Arguments.of(1, 3, 1),
|
||||
Arguments.of(targetGasPerBlock, 1, CancunGasCalculator.BLOB_GAS_PER_BLOB),
|
||||
Arguments.of(targetGasPerBlock, 1, cancunGasCalculator.getBlobGasPerBlob()),
|
||||
Arguments.of(targetGasPerBlock, 3, targetGasPerBlock));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,13 +18,65 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.units.bigints.UInt64;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class PragueGasCalculatorTest {
|
||||
|
||||
private final PragueGasCalculator pragueGasCalculator = new PragueGasCalculator();
|
||||
|
||||
@Test
|
||||
void testPrecompileSize() {
|
||||
PragueGasCalculator subject = new PragueGasCalculator();
|
||||
assertThat(subject.isPrecompile(Address.precompiled(0x14))).isFalse();
|
||||
assertThat(subject.isPrecompile(Address.BLS12_MAP_FP2_TO_G2)).isTrue();
|
||||
}
|
||||
|
||||
@ParameterizedTest(
|
||||
name = "{index} - parent gas {0}, used gas {1}, blob target {2} new excess {3}")
|
||||
@MethodSource("blobGasses")
|
||||
public void shouldCalculateExcessBlobGasCorrectly(
|
||||
final long parentExcess, final long used, final long target, final long expected) {
|
||||
final long usedBlobGas = pragueGasCalculator.blobGasCost(used);
|
||||
assertThat(
|
||||
pragueGasCalculator.computeExcessBlobGas(
|
||||
parentExcess, usedBlobGas, Optional.of(UInt64.valueOf(target))))
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
Iterable<Arguments> blobGasses() {
|
||||
long threeBlobTargetGas = CancunGasCalculator.TARGET_BLOB_GAS_PER_BLOCK;
|
||||
long cancunTargetCount = 3;
|
||||
long newTargetCount = 4;
|
||||
|
||||
return List.of(
|
||||
// If blob target count remains at 3
|
||||
Arguments.of(0L, 0L, cancunTargetCount, 0L),
|
||||
Arguments.of(threeBlobTargetGas, 0L, cancunTargetCount, 0L),
|
||||
Arguments.of(0L, cancunTargetCount, cancunTargetCount, 0L),
|
||||
Arguments.of(1L, cancunTargetCount, cancunTargetCount, 1L),
|
||||
Arguments.of(
|
||||
threeBlobTargetGas, 1L, cancunTargetCount, pragueGasCalculator.getBlobGasPerBlob()),
|
||||
Arguments.of(threeBlobTargetGas, 3L, cancunTargetCount, threeBlobTargetGas),
|
||||
// New target count
|
||||
Arguments.of(0L, 0L, newTargetCount, 0L),
|
||||
Arguments.of(threeBlobTargetGas, 0L, newTargetCount, 0L),
|
||||
Arguments.of(newTargetCount, 0L, newTargetCount, 0L),
|
||||
Arguments.of(0L, newTargetCount, newTargetCount, 0L),
|
||||
Arguments.of(1L, newTargetCount, newTargetCount, 1L),
|
||||
Arguments.of(
|
||||
pragueGasCalculator.blobGasCost(newTargetCount),
|
||||
1L,
|
||||
newTargetCount,
|
||||
pragueGasCalculator.getBlobGasPerBlob()),
|
||||
Arguments.of(threeBlobTargetGas, newTargetCount, newTargetCount, threeBlobTargetGas));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user