Skip to content

Commit

Permalink
[Interop-4844] Data gas accounting (#4998)
Browse files Browse the repository at this point in the history
merge of #4992 into interop feature branch

Signed-off-by: Fabio Di Fabio <[email protected]>
(cherry picked from commit 949e3fe)
(cherry picked from commit 9734c983ce00bda161434506688f12ee07bbd820)
  • Loading branch information
fab-10 authored and jflo committed Jul 5, 2023
1 parent 150e2c6 commit 41254ea
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.BlockTransactionSelector.TransactionSelectionResults;
import org.hyperledger.besu.ethereum.core.Block;
Expand Down Expand Up @@ -232,6 +233,10 @@ protected BlockCreationResult createBlock(

throwIfStopped();

final DataGas newExcessDataGas = computeExcessDataGas(transactionResults, newProtocolSpec);

throwIfStopped();

final SealableBlockHeader sealableBlockHeader =
BlockHeaderBuilder.create()
.populateFrom(processableBlockHeader)
Expand Down Expand Up @@ -362,13 +367,13 @@ private ProcessableBlockHeader createPendingBlockHeader(
final Optional<Bytes32> maybePrevRandao,
final ProtocolSpec protocolSpec) {
final long newBlockNumber = parentHeader.getNumber() + 1;
long gasLimit =
protocolSpec
.getGasLimitCalculator()
.nextGasLimit(
parentHeader.getGasLimit(),
targetGasLimitSupplier.get().orElse(parentHeader.getGasLimit()),
newBlockNumber);
final GasLimitCalculator gasLimitCalculator = protocolSpec.getGasLimitCalculator();

final long gasLimit =
gasLimitCalculator.nextGasLimit(
parentHeader.getGasLimit(),
targetGasLimitSupplier.get().orElse(parentHeader.getGasLimit()),
newBlockNumber);

final DifficultyCalculator difficultyCalculator = protocolSpec.getDifficultyCalculator();
final BigInteger difficulty =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.account.EvmAccount;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
Expand All @@ -50,6 +54,7 @@
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.common.collect.Lists;
import org.slf4j.Logger;
Expand All @@ -76,136 +81,6 @@
* not cleared between executions of buildTransactionListForBlock().
*/
public class BlockTransactionSelector {
public static class TransactionValidationResult {
private final Transaction transaction;
private final ValidationResult<TransactionInvalidReason> validationResult;

public TransactionValidationResult(
final Transaction transaction,
final ValidationResult<TransactionInvalidReason> validationResult) {
this.transaction = transaction;
this.validationResult = validationResult;
}

public Transaction getTransaction() {
return transaction;
}

public ValidationResult<TransactionInvalidReason> getValidationResult() {
return validationResult;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TransactionValidationResult that = (TransactionValidationResult) o;
return Objects.equals(transaction, that.transaction)
&& Objects.equals(validationResult, that.validationResult);
}

@Override
public int hashCode() {
return Objects.hash(transaction, validationResult);
}
}

public static class TransactionSelectionResults {
private final List<Transaction> transactions = Lists.newArrayList();
private final Map<TransactionType, List<Transaction>> transactionsByType =
new EnumMap<>(TransactionType.class);
private final List<TransactionReceipt> receipts = Lists.newArrayList();
private final List<TransactionValidationResult> invalidTransactions = Lists.newArrayList();
private long cumulativeGasUsed = 0;
private long cumulativeDataGasUsed = 0;

private void update(
final Transaction transaction,
final TransactionReceipt receipt,
final long gasUsed,
final long dataGasUsed) {
transactions.add(transaction);
transactionsByType
.computeIfAbsent(transaction.getType(), type -> new ArrayList<>())
.add(transaction);
receipts.add(receipt);
cumulativeGasUsed += gasUsed;
cumulativeDataGasUsed += dataGasUsed;
LOG.atTrace()
.setMessage(
"New selected transaction {}, total transactions {}, cumulative gas used {}, cumulative data gas used {}")
.addArgument(transaction::toTraceLog)
.addArgument(transactions::size)
.addArgument(cumulativeGasUsed)
.addArgument(cumulativeDataGasUsed)
.log();
}

private void updateWithInvalidTransaction(
final Transaction transaction,
final ValidationResult<TransactionInvalidReason> validationResult) {
invalidTransactions.add(new TransactionValidationResult(transaction, validationResult));
}

public List<Transaction> getTransactions() {
return transactions;
}

public List<Transaction> getTransactionsByType(final TransactionType type) {
return transactionsByType.getOrDefault(type, List.of());
}

public List<TransactionReceipt> getReceipts() {
return receipts;
}

public long getCumulativeGasUsed() {
return cumulativeGasUsed;
}

public long getCumulativeDataGasUsed() {
return cumulativeDataGasUsed;
}

public List<TransactionValidationResult> getInvalidTransactions() {
return invalidTransactions;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TransactionSelectionResults that = (TransactionSelectionResults) o;
return cumulativeGasUsed == that.cumulativeGasUsed
&& cumulativeDataGasUsed == that.cumulativeDataGasUsed
&& transactions.equals(that.transactions)
&& receipts.equals(that.receipts)
&& invalidTransactions.equals(that.invalidTransactions);
}

@Override
public int hashCode() {
return Objects.hash(
transactions, receipts, invalidTransactions, cumulativeGasUsed, cumulativeDataGasUsed);
}

public String toTraceLog() {
return "cumulativeGasUsed="
+ cumulativeGasUsed
+ ", cumulativeDataGasUsed="
+ cumulativeDataGasUsed
+ ", transactions="
+ transactions.stream().map(Transaction::toTraceLog).collect(Collectors.joining("; "));
}
}

private static final Logger LOG = LoggerFactory.getLogger(BlockTransactionSelector.class);

Expand Down Expand Up @@ -407,7 +282,13 @@ private List<org.hyperledger.besu.plugin.data.Log> getLogs(final List<Log> logs)

private boolean transactionDataPriceBelowMin(final Transaction transaction) {
if (transaction.getType().supportsBlob()) {
if (transaction.getMaxFeePerDataGas().orElseThrow().lessThan(dataGasPrice)) {
if (transaction
.getMaxFeePerDataGas()
.orElseThrow()
.lessThan(
feeMarket
.getTransactionPriceCalculator()
.dataPrice(transaction, processableBlockHeader))) {
return true;
}
}
Expand Down Expand Up @@ -477,7 +358,6 @@ private void updateTransactionResultTracking(
final Transaction transaction, final TransactionProcessingResult result) {

final long gasUsedByTransaction = transaction.getGasLimit() - result.getGasRemaining();

final long cumulativeGasUsed =
transactionSelectionResult.getCumulativeGasUsed() + gasUsedByTransaction;

Expand Down Expand Up @@ -525,4 +405,140 @@ private boolean blockOccupancyAboveThreshold() {

return occupancyRatio >= minBlockOccupancyRatio;
}

public static class TransactionValidationResult {
private final Transaction transaction;
private final ValidationResult<TransactionInvalidReason> validationResult;

public TransactionValidationResult(
final Transaction transaction,
final ValidationResult<TransactionInvalidReason> validationResult) {
this.transaction = transaction;
this.validationResult = validationResult;
}

public Transaction getTransaction() {
return transaction;
}

public ValidationResult<TransactionInvalidReason> getValidationResult() {
return validationResult;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TransactionValidationResult that = (TransactionValidationResult) o;
return Objects.equals(transaction, that.transaction)
&& Objects.equals(validationResult, that.validationResult);
}

@Override
public int hashCode() {
return Objects.hash(transaction, validationResult);
}
}

public static class TransactionSelectionResults {

private final Map<TransactionType, List<Transaction>> transactionsByType = new HashMap<>();
private final List<TransactionReceipt> receipts = Lists.newArrayList();
private final List<TransactionValidationResult> invalidTransactions = Lists.newArrayList();
private long cumulativeGasUsed = 0;
private long cumulativeDataGasUsed = 0;

private void update(
final Transaction transaction,
final TransactionReceipt receipt,
final long gasUsed,
final long dataGasUsed) {
transactionsByType
.computeIfAbsent(transaction.getType(), type -> new ArrayList<>())
.add(transaction);
receipts.add(receipt);
cumulativeGasUsed += gasUsed;
cumulativeDataGasUsed += dataGasUsed;
traceLambda(
LOG,
"New selected transaction {}, total transactions {}, cumulative gas used {}, cumulative data gas used {}",
transaction::toTraceLog,
() -> transactionsByType.values().stream().mapToInt(List::size).sum(),
() -> cumulativeGasUsed,
() -> cumulativeDataGasUsed);
}

private void updateWithInvalidTransaction(
final Transaction transaction,
final ValidationResult<TransactionInvalidReason> validationResult) {
invalidTransactions.add(new TransactionValidationResult(transaction, validationResult));
}

public List<Transaction> getTransactions() {
return streamAllTransactions().collect(Collectors.toList());
}

public List<Transaction> getTransactionsByType(final TransactionType type) {
return transactionsByType.getOrDefault(type, List.of());
}

public List<TransactionReceipt> getReceipts() {
return receipts;
}

public long getCumulativeGasUsed() {
return cumulativeGasUsed;
}

public long getCumulativeDataGasUsed() {
return cumulativeDataGasUsed;
}

public List<TransactionValidationResult> getInvalidTransactions() {
return invalidTransactions;
}

private Stream<Transaction> streamAllTransactions() {
return transactionsByType.values().stream().flatMap(List::stream);
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TransactionSelectionResults that = (TransactionSelectionResults) o;
return cumulativeGasUsed == that.cumulativeGasUsed
&& cumulativeDataGasUsed == that.cumulativeDataGasUsed
&& transactionsByType.equals(that.transactionsByType)
&& receipts.equals(that.receipts)
&& invalidTransactions.equals(that.invalidTransactions);
}

@Override
public int hashCode() {
return Objects.hash(
transactionsByType,
receipts,
invalidTransactions,
cumulativeGasUsed,
cumulativeDataGasUsed);
}

public String toTraceLog() {
return "cumulativeGasUsed="
+ cumulativeGasUsed
+ ", cumulativeDataGasUsed="
+ cumulativeDataGasUsed
+ ", transactions="
+ streamAllTransactions().map(Transaction::toTraceLog).collect(Collectors.joining("; "));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@ public Transaction(
final SECPSignature signature,
final Bytes payload,
final Address sender,
final Optional<BigInteger> chainId) {
final Optional<BigInteger> chainId,
final Optional<List<Hash>> versionedHashes) {
this(
nonce,
Optional.of(gasPrice),
Expand Down
Loading

0 comments on commit 41254ea

Please sign in to comment.