Merge branch 'main' into zkbesu

This commit is contained in:
Fabio Di Fabio
2024-12-06 13:51:27 +01:00
61 changed files with 1223 additions and 500 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
/**

View File

@@ -47,15 +47,16 @@ public class AccessListOperationTracer extends EstimateGasOperationTracer {
* @return the access list
*/
public List<AccessListEntry> getAccessList() {
final List<AccessListEntry> list = new ArrayList<>();
if (warmedUpStorage != null && !warmedUpStorage.isEmpty()) {
final List<AccessListEntry> list = new ArrayList<>(warmedUpStorage.size());
warmedUpStorage
.rowMap()
.forEach(
(address, storageKeys) ->
list.add(new AccessListEntry(address, new ArrayList<>(storageKeys.keySet()))));
return list;
}
return list;
return List.of();
}
/**

View File

@@ -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));
}

View File

@@ -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));
}
}