Skip to content

Commit

Permalink
Include baseFee in the calculation of a profitable tx
Browse files Browse the repository at this point in the history
Signed-off-by: Fabio Di Fabio <[email protected]>
  • Loading branch information
fab-10 committed Jun 26, 2024
1 parent 7b634f8 commit 5acea24
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ protected void assertIsProfitable(
"Test",
tx,
profitabilityConf.estimateGasMinMargin(),
baseFee,
estimatedMaxGasPrice,
estimatedGasLimit,
minGasPrice))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,25 @@ public boolean isProfitable(
final String context,
final Transaction transaction,
final double minMargin,
final Wei effectiveGasPrice,
final Wei baseFee,
final Wei payingGasPrice,
final long gas,
final Wei minGasPriceWei) {

final Wei profitablePriorityFee =
profitablePriorityFeePerGas(transaction, minMargin, gas, minGasPriceWei);
final Wei profitableGasPrice = baseFee.add(profitablePriorityFee);

if (effectiveGasPrice.lessThan(profitablePriorityFee)) {
if (payingGasPrice.lessThan(profitableGasPrice)) {
log(
log.atDebug(),
context,
transaction,
minMargin,
effectiveGasPrice,
payingGasPrice,
baseFee,
profitablePriorityFee,
profitableGasPrice,
gas,
minGasPriceWei);
return false;
Expand All @@ -94,8 +98,10 @@ public boolean isProfitable(
context,
transaction,
minMargin,
effectiveGasPrice,
payingGasPrice,
baseFee,
profitablePriorityFee,
profitableGasPrice,
gas,
minGasPriceWei);
return true;
Expand All @@ -111,25 +117,29 @@ private void log(
final String context,
final Transaction transaction,
final double minMargin,
final Wei effectiveGasPrice,
final Wei payingGasPrice,
final Wei baseFee,
final Wei profitablePriorityFee,
final Wei profitableGasPrice,
final long gasUsed,
final Wei minGasPriceWei) {

leb.setMessage(
"Context {}. Transaction {} has a margin of {}, minMargin={}, effectiveGasPrice={},"
+ " profitableGasPrice={}, fixedCostWei={}, variableCostWei={}, "
"Context {}. Transaction {} has a margin of {}, minMargin={}, payingGasPrice={},"
+ " profitableGasPrice={}, baseFee={}, profitablePriorityFee={}, fixedCostWei={}, variableCostWei={}, "
+ " gasUsed={}")
.addArgument(context)
.addArgument(transaction::getHash)
.addArgument(
() ->
effectiveGasPrice.toBigInteger().doubleValue()
/ profitableGasPrice.toBigInteger().doubleValue())
payingGasPrice.toBigInteger().doubleValue()
/ profitablePriorityFee.toBigInteger().doubleValue())
.addArgument(minMargin)
.addArgument(effectiveGasPrice::toHumanReadableString)
.addArgument(payingGasPrice::toHumanReadableString)
.addArgument(profitableGasPrice::toHumanReadableString)
.addArgument(profitabilityConf.fixedCostWei())
.addArgument(baseFee::toHumanReadableString)
.addArgument(profitablePriorityFee::toHumanReadableString)
.addArgument(profitabilityConf::fixedCostWei)
.addArgument(
() ->
profitabilityConf.extraDataPricingEnabled()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,17 @@ public Optional<String> validateTransaction(
&& (isLocal && profitabilityConf.txPoolCheckApiEnabled()
|| !isLocal && profitabilityConf.txPoolCheckP2pEnabled())) {

final Wei baseFee =
blockchainService
.getNextBlockBaseFee()
.orElseThrow(() -> new RuntimeException("We only support a base fee market"));

return profitabilityCalculator.isProfitable(
"Txpool",
transaction,
profitabilityConf.txPoolMinMargin(),
calculateUpfrontGasPrice(transaction),
baseFee,
calculateUpfrontGasPrice(transaction, baseFee),
transaction.getGasLimit(),
besuConfiguration.getMinGasPrice())
? Optional.empty()
Expand All @@ -65,11 +71,7 @@ public Optional<String> validateTransaction(
return Optional.empty();
}

private Wei calculateUpfrontGasPrice(final Transaction transaction) {
final Wei baseFee =
blockchainService
.getNextBlockBaseFee()
.orElseThrow(() -> new RuntimeException("We only support a base fee market"));
private Wei calculateUpfrontGasPrice(final Transaction transaction, final Wei baseFee) {

return transaction
.getMaxFeePerGas()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
import net.consensys.linea.config.LineaTracerConfiguration;
import net.consensys.linea.config.LineaTransactionSelectorConfiguration;
import net.consensys.linea.sequencer.txselection.selectors.LineaTransactionSelector;
import org.hyperledger.besu.plugin.services.BlockchainService;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;

/** Represents a factory for creating transaction selectors. */
public class LineaTransactionSelectorFactory implements PluginTransactionSelectorFactory {
private final BlockchainService blockchainService;
private final LineaTransactionSelectorConfiguration txSelectorConfiguration;
private final LineaL1L2BridgeConfiguration l1L2BridgeConfiguration;
private final LineaProfitabilityConfiguration profitabilityConfiguration;
Expand All @@ -35,11 +37,13 @@ public class LineaTransactionSelectorFactory implements PluginTransactionSelecto
private final Map<String, Integer> limitsMap;

public LineaTransactionSelectorFactory(
final BlockchainService blockchainService,
final LineaTransactionSelectorConfiguration txSelectorConfiguration,
final LineaL1L2BridgeConfiguration l1L2BridgeConfiguration,
final LineaProfitabilityConfiguration profitabilityConfiguration,
final LineaTracerConfiguration tracerConfiguration,
final Map<String, Integer> limitsMap) {
this.blockchainService = blockchainService;
this.txSelectorConfiguration = txSelectorConfiguration;
this.l1L2BridgeConfiguration = l1L2BridgeConfiguration;
this.profitabilityConfiguration = profitabilityConfiguration;
Expand All @@ -50,6 +54,7 @@ public LineaTransactionSelectorFactory(
@Override
public PluginTransactionSelector create() {
return new LineaTransactionSelector(
blockchainService,
txSelectorConfiguration,
l1L2BridgeConfiguration,
profitabilityConfiguration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import net.consensys.linea.AbstractLineaRequiredPlugin;
import org.hyperledger.besu.plugin.BesuContext;
import org.hyperledger.besu.plugin.BesuPlugin;
import org.hyperledger.besu.plugin.services.BlockchainService;
import org.hyperledger.besu.plugin.services.TransactionSelectionService;

/**
Expand All @@ -36,6 +37,7 @@
public class LineaTransactionSelectorPlugin extends AbstractLineaRequiredPlugin {
public static final String NAME = "linea";
private TransactionSelectionService transactionSelectionService;
private BlockchainService blockchainService;

@Override
public Optional<String> getName() {
Expand All @@ -51,13 +53,22 @@ public void doRegister(final BesuContext context) {
() ->
new RuntimeException(
"Failed to obtain TransactionSelectionService from the BesuContext."));

blockchainService =
context
.getService(BlockchainService.class)
.orElseThrow(
() ->
new RuntimeException(
"Failed to obtain BlockchainService from the BesuContext."));
}

@Override
public void beforeExternalServices() {
super.beforeExternalServices();
transactionSelectionService.registerPluginTransactionSelectorFactory(
new LineaTransactionSelectorFactory(
blockchainService,
transactionSelectorConfiguration,
l1L2BridgeConfiguration,
profitabilityConfiguration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.hyperledger.besu.datatypes.PendingTransaction;
import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.BlockchainService;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.TransactionEvaluationContext;
Expand All @@ -37,13 +38,15 @@ public class LineaTransactionSelector implements PluginTransactionSelector {
private final List<PluginTransactionSelector> selectors;

public LineaTransactionSelector(
final BlockchainService blockchainService,
final LineaTransactionSelectorConfiguration txSelectorConfiguration,
final LineaL1L2BridgeConfiguration l1L2BridgeConfiguration,
final LineaProfitabilityConfiguration profitabilityConfiguration,
final LineaTracerConfiguration tracerConfiguration,
final Map<String, Integer> limitsMap) {
this.selectors =
createTransactionSelectors(
blockchainService,
txSelectorConfiguration,
l1L2BridgeConfiguration,
profitabilityConfiguration,
Expand All @@ -54,12 +57,14 @@ public LineaTransactionSelector(
/**
* Creates a list of selectors based on Linea configuration.
*
* @param blockchainService
* @param txSelectorConfiguration The configuration to use.
* @param profitabilityConfiguration
* @param limitsMap The limits map.
* @return A list of selectors.
*/
private List<PluginTransactionSelector> createTransactionSelectors(
final BlockchainService blockchainService,
final LineaTransactionSelectorConfiguration txSelectorConfiguration,
final LineaL1L2BridgeConfiguration l1L2BridgeConfiguration,
final LineaProfitabilityConfiguration profitabilityConfiguration,
Expand All @@ -73,7 +78,8 @@ private List<PluginTransactionSelector> createTransactionSelectors(
return List.of(
new MaxBlockCallDataTransactionSelector(txSelectorConfiguration.maxBlockCallDataSize()),
new MaxBlockGasTransactionSelector(txSelectorConfiguration.maxGasPerBlock()),
new ProfitableTransactionSelector(txSelectorConfiguration, profitabilityConfiguration),
new ProfitableTransactionSelector(
blockchainService, txSelectorConfiguration, profitabilityConfiguration),
traceLineLimitTransactionSelector);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.BlockchainService;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.TransactionEvaluationContext;

Expand All @@ -43,16 +44,22 @@ public class ProfitableTransactionSelector implements PluginTransactionSelector
private final LineaTransactionSelectorConfiguration txSelectorConf;
private final LineaProfitabilityConfiguration profitabilityConf;
private final TransactionProfitabilityCalculator transactionProfitabilityCalculator;
private final Wei baseFee;

private int unprofitableRetries;

public ProfitableTransactionSelector(
final BlockchainService blockchainService,
final LineaTransactionSelectorConfiguration txSelectorConf,
final LineaProfitabilityConfiguration profitabilityConf) {
this.txSelectorConf = txSelectorConf;
this.profitabilityConf = profitabilityConf;
this.transactionProfitabilityCalculator =
new TransactionProfitabilityCalculator(profitabilityConf);
this.baseFee =
blockchainService
.getNextBlockBaseFee()
.orElseThrow(() -> new RuntimeException("We only support a base fee market"));
}

@Override
Expand All @@ -70,6 +77,7 @@ public TransactionSelectionResult evaluateTransactionPreProcessing(
"PreProcessing",
transaction,
profitabilityConf.minMargin(),
baseFee,
evaluationContext.getTransactionGasPrice(),
gasLimit,
minGasPrice)) {
Expand Down Expand Up @@ -110,6 +118,7 @@ public TransactionSelectionResult evaluateTransactionPostProcessing(
"PostProcessing",
transaction,
profitabilityConf.minMargin(),
baseFee,
evaluationContext.getTransactionGasPrice(),
gasUsed,
evaluationContext.getMinGasPrice())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.Optional;

import net.consensys.linea.config.LineaProfitabilityCliOptions;
import net.consensys.linea.config.LineaProfitabilityConfiguration;
import net.consensys.linea.config.LineaTransactionSelectorCliOptions;
Expand All @@ -35,6 +37,7 @@
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.BlockchainService;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -44,6 +47,7 @@ public class ProfitableTransactionSelectorTest {
private static final int VARIABLE_GAS_COST_WEI = 1_000_000;
private static final double MIN_MARGIN = 1.5;
private static final int UNPROFITABLE_CACHE_SIZE = 2;
private static final Wei BASE_FEE = Wei.of(7);
private static final int UNPROFITABLE_RETRY_LIMIT = 1;
private final LineaTransactionSelectorConfiguration txSelectorConf =
LineaTransactionSelectorCliOptions.create().toDomainObject().toBuilder()
Expand All @@ -65,7 +69,10 @@ public void initialize() {
}

private TestableProfitableTransactionSelector newSelectorForNewBlock() {
return new TestableProfitableTransactionSelector(txSelectorConf, profitabilityConf);
final var blockchainService = mock(BlockchainService.class);
when(blockchainService.getNextBlockBaseFee()).thenReturn(Optional.of(BASE_FEE));
return new TestableProfitableTransactionSelector(
blockchainService, txSelectorConf, profitabilityConf);
}

@Test
Expand Down Expand Up @@ -399,9 +406,10 @@ private void notifySelector(
private static class TestableProfitableTransactionSelector extends ProfitableTransactionSelector {

TestableProfitableTransactionSelector(
final BlockchainService blockchainService,
final LineaTransactionSelectorConfiguration txSelectorConf,
final LineaProfitabilityConfiguration profitabilityConf) {
super(txSelectorConf, profitabilityConf);
super(blockchainService, txSelectorConf, profitabilityConf);
}

boolean isUnprofitableTxCached(final Hash txHash) {
Expand Down

0 comments on commit 5acea24

Please sign in to comment.