Skip to content

Commit

Permalink
3D pricing metrics (#107)
Browse files Browse the repository at this point in the history
* Introduce profitablePriorityFeeCache

Signed-off-by: Fabio Di Fabio <[email protected]>

* Add block listener and transaction selector handler

- Introduce block listener in LineaTransactionSelectorPlugin to handle transaction profitability
- Integrate transaction selector handler for processing transactions from the latest block
- Extract profitability calculation into a separate method for clarity and maintainability

Signed-off-by: Ade Lucas <[email protected]>

* Removed unused import

Signed-off-by: Ade Lucas <[email protected]>

* Move profitability metrics during tx selection in a dedicated class

Signed-off-by: Fabio Di Fabio <[email protected]>

* Improve the log of the future metric

Signed-off-by: Fabio Di Fabio <[email protected]>

* Organize the profitability cache by block

Signed-off-by: Fabio Di Fabio <[email protected]>

* Refctor to respect the requirement

Signed-off-by: Fabio Di Fabio <[email protected]>

* Add block added listener and handler into LineaTransactionPoolValidatorPlugin

- Implement: Node's perception on Profitability levels of TxPool's contents (lo, hi, avg of TransactionProfitabilityCalculator.profitablePriorityFeePerGas(transaction) / transaction.priorityFeePerGas).

Signed-off-by: Ade Lucas <[email protected]>

* Add block added listener and handler into LineaTransactionPoolValidatorPlugin

- Implement: Node's perception on Profitability levels of TxPool's contents (lo, hi, avg of TransactionProfitabilityCalculator.profitablePriorityFeePerGas(transaction) / transaction.priorityFeePerGas).

Signed-off-by: Ade Lucas <[email protected]>

* Add missing import in ValidatorProfitabilityMetrics.java

Signed-off-by: Ade Lucas <[email protected]>

* Use histogram and txpool get content api

Signed-off-by: Fabio Di Fabio <[email protected]>

* Add min and max metrics to selection profitability metrics

Signed-off-by: Fabio Di Fabio <[email protected]>

* Deleted ValidatorProfitabilityMetrics.java as part of 3D pricing metrics work

Signed-off-by: Ade Lucas <[email protected]>

* Run './gradlew :sequencer:spotlessApply' to fix ProfitableTransactionSelectorTest.java

Signed-off-by: Ade Lucas <[email protected]>

* Restore non-local dev settings for besuVersion in gradle.properties.

Signed-off-by: Ade Lucas <[email protected]>

* Generalize histogram metrics in a single class and check for category enabled

Signed-off-by: Fabio Di Fabio <[email protected]>

* Make profitability histogram metric buckets configurable

Signed-off-by: Fabio Di Fabio <[email protected]>

* Update versions

Signed-off-by: Fabio Di Fabio <[email protected]>

* Fix tests

Signed-off-by: Fabio Di Fabio <[email protected]>

* Apply suggestions from code review

Signed-off-by: Fabio Di Fabio <[email protected]>

* Update DEFAULT_PROFITABILITY_METRICS_BUCKETS

Signed-off-by: Fabio Di Fabio <[email protected]>

* Update Linea Besu and Tracer

Signed-off-by: Fabio Di Fabio <[email protected]>

---------

Signed-off-by: Fabio Di Fabio <[email protected]>
Signed-off-by: Ade Lucas <[email protected]>
Signed-off-by: Ade Lucas <[email protected]>
Co-authored-by: Fabio Di Fabio <[email protected]>
  • Loading branch information
cloudspores and fab-10 authored Nov 29, 2024
1 parent dcec695 commit ab849c5
Show file tree
Hide file tree
Showing 16 changed files with 571 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

package linea.plugin.acc.test;

import static net.consensys.linea.metrics.LineaMetricCategory.PRICING_CONF;
import static net.consensys.linea.metrics.LineaMetricCategory.SEQUENCER_PROFITABILITY;
import static net.consensys.linea.metrics.LineaMetricCategory.TX_POOL_PROFITABILITY;
import static org.assertj.core.api.Assertions.*;

import java.io.IOException;
Expand All @@ -40,7 +43,6 @@
import linea.plugin.acc.test.tests.web3j.generated.RevertExample;
import linea.plugin.acc.test.tests.web3j.generated.SimpleStorage;
import lombok.extern.slf4j.Slf4j;
import net.consensys.linea.metrics.LineaMetricCategory;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
Expand Down Expand Up @@ -136,7 +138,8 @@ private BesuNode createCliqueNodeWithExtraCliOptionsAndRpcApis(
.metricsConfiguration(
MetricsConfiguration.builder()
.enabled(true)
.metricCategories(Set.of(LineaMetricCategory.PROFITABILITY))
.metricCategories(
Set.of(PRICING_CONF, SEQUENCER_PROFITABILITY, TX_POOL_PROFITABILITY))
.build())
.requestedPlugins(
List.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package linea.plugin.acc.test.extradata;

import static java.util.Map.entry;
import static net.consensys.linea.metrics.LineaMetricCategory.PRICING_CONF;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
Expand All @@ -23,7 +24,6 @@

import linea.plugin.acc.test.LineaPluginTestBase;
import linea.plugin.acc.test.TestCommandLineOptionsBuilder;
import net.consensys.linea.metrics.LineaMetricCategory;
import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
Expand Down Expand Up @@ -125,24 +125,17 @@ public void updateProfitabilityParamsViaExtraData() throws IOException, Interrup
assertThat(getTxPoolContent()).isEmpty();

final var fixedCostMetric =
getMetricValue(
LineaMetricCategory.PROFITABILITY, "conf", List.of(entry("field", "fixed_cost_wei")));
getMetricValue(PRICING_CONF, "values", List.of(entry("field", "fixed_cost_wei")));

assertThat(fixedCostMetric).isEqualTo(MIN_GAS_PRICE.multiply(2).getValue().doubleValue());

final var variableCostMetric =
getMetricValue(
LineaMetricCategory.PROFITABILITY,
"conf",
List.of(entry("field", "variable_cost_wei")));
getMetricValue(PRICING_CONF, "values", List.of(entry("field", "variable_cost_wei")));

assertThat(variableCostMetric).isEqualTo(MIN_GAS_PRICE.getValue().doubleValue());

final var ethGasPriceMetric =
getMetricValue(
LineaMetricCategory.PROFITABILITY,
"conf",
List.of(entry("field", "eth_gas_price_wei")));
getMetricValue(PRICING_CONF, "values", List.of(entry("field", "eth_gas_price_wei")));

assertThat(ethGasPriceMetric).isEqualTo(MIN_GAS_PRICE.getValue().doubleValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import net.consensys.linea.config.LineaTransactionPoolValidatorConfiguration;
import net.consensys.linea.config.LineaTransactionSelectorCliOptions;
import net.consensys.linea.config.LineaTransactionSelectorConfiguration;
import net.consensys.linea.metrics.LineaMetricCategory;
import net.consensys.linea.plugins.AbstractLineaSharedOptionsPlugin;
import net.consensys.linea.plugins.LineaOptionsPluginConfiguration;
import org.hyperledger.besu.plugin.ServiceManager;
Expand All @@ -59,6 +58,7 @@ public abstract class AbstractLineaSharedPrivateOptionsPlugin
extends AbstractLineaSharedOptionsPlugin {
protected static BlockchainService blockchainService;
protected static MetricsSystem metricsSystem;
protected static MetricCategoryRegistry metricCategoryRegistry;

private static final AtomicBoolean sharedRegisterTasksDone = new AtomicBoolean(false);
private static final AtomicBoolean sharedStartTasksDone = new AtomicBoolean(false);
Expand Down Expand Up @@ -143,13 +143,13 @@ protected static void performSharedRegisterTasksOnce(final ServiceManager servic
new RuntimeException(
"Failed to obtain BlockchainService from the ServiceManager."));

serviceManager
.getService(MetricCategoryRegistry.class)
.orElseThrow(
() ->
new RuntimeException(
"Failed to obtain MetricCategoryRegistry from the ServiceManager."))
.addMetricCategory(LineaMetricCategory.PROFITABILITY);
metricCategoryRegistry =
serviceManager
.getService(MetricCategoryRegistry.class)
.orElseThrow(
() ->
new RuntimeException(
"Failed to obtain MetricCategoryRegistry from the ServiceManager."));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,28 @@ public boolean isProfitable(

final Wei profitablePriorityFee =
profitablePriorityFeePerGas(transaction, minMargin, gas, minGasPriceWei);

return isProfitable(
context,
profitablePriorityFee,
transaction,
minMargin,
baseFee,
payingGasPrice,
gas,
minGasPriceWei);
}

public boolean isProfitable(
final String context,
final Wei profitablePriorityFee,
final Transaction transaction,
final double minMargin,
final Wei baseFee,
final Wei payingGasPrice,
final long gas,
final Wei minGasPriceWei) {

final Wei profitableGasPrice = baseFee.add(profitablePriorityFee);

if (payingGasPrice.lessThan(profitableGasPrice)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ public class LineaProfitabilityCliOptions implements LineaCliOptions {
"--plugin-linea-extra-data-set-min-gas-price-enabled";
public static final boolean DEFAULT_EXTRA_DATA_SET_MIN_GAS_PRICE_ENABLED = true;

public static final String PROFITABILITY_METRICS_BUCKETS =
"--plugin-linea-profitability-metrics-buckets";
public static final double[] DEFAULT_PROFITABILITY_METRICS_BUCKETS = {
0.1, 0.3, 0.5, 0.7, 0.9, 1.0, 1.1, 1.2, 1.5, 2.0, 5.0, 10.0
};

@Positive
@CommandLine.Option(
names = {FIXED_GAS_COST_WEI},
Expand Down Expand Up @@ -135,6 +141,17 @@ public class LineaProfitabilityCliOptions implements LineaCliOptions {
"Enable setting min gas price runtime value via extra data field (default: ${DEFAULT-VALUE})")
private boolean extraDataSetMinGasPriceEnabled = DEFAULT_EXTRA_DATA_SET_MIN_GAS_PRICE_ENABLED;

@CommandLine.Option(
names = {PROFITABILITY_METRICS_BUCKETS},
arity = "1..*",
split = ",",
hidden = true,
paramLabel = "<FLOAT[]>",
description =
"List of buckets to use to create the histogram for ratio between the effective priority fee "
+ "and the calculate profitable priority of the tx (default: ${DEFAULT-VALUE})")
private double[] profitabilityMetricsBuckets = DEFAULT_PROFITABILITY_METRICS_BUCKETS;

private LineaProfitabilityCliOptions() {}

/**
Expand Down Expand Up @@ -164,6 +181,7 @@ public static LineaProfitabilityCliOptions fromConfig(
options.txPoolCheckP2pEnabled = config.txPoolCheckP2pEnabled();
options.extraDataPricingEnabled = config.extraDataPricingEnabled();
options.extraDataSetMinGasPriceEnabled = config.extraDataSetMinGasPriceEnabled();
options.profitabilityMetricsBuckets = config.profitabilityMetricsBuckets();
return options;
}

Expand All @@ -184,6 +202,7 @@ public LineaProfitabilityConfiguration toDomainObject() {
.txPoolCheckP2pEnabled(txPoolCheckP2pEnabled)
.extraDataPricingEnabled(extraDataPricingEnabled)
.extraDataSetMinGasPriceEnabled(extraDataSetMinGasPriceEnabled)
.profitabilityMetricsBuckets(profitabilityMetricsBuckets)
.build();
}

Expand All @@ -199,6 +218,7 @@ public String toString() {
.add(TX_POOL_ENABLE_CHECK_P2P, txPoolCheckP2pEnabled)
.add(EXTRA_DATA_PRICING_ENABLED, extraDataPricingEnabled)
.add(EXTRA_DATA_SET_MIN_GAS_PRICE_ENABLED, extraDataSetMinGasPriceEnabled)
.add(PROFITABILITY_METRICS_BUCKETS, profitabilityMetricsBuckets)
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class LineaProfitabilityConfiguration implements LineaOptionsConfiguratio
/** It is safe to keep this as long, since it will store value <= max_int * 1000 */
private long variableCostWei;

/** It is safe to keep this as long, since it will store value <= max_int * 1000 */
private long ethGasPriceWei;

private double minMargin;
Expand All @@ -42,6 +43,7 @@ public class LineaProfitabilityConfiguration implements LineaOptionsConfiguratio
private boolean txPoolCheckP2pEnabled;
private boolean extraDataPricingEnabled;
private boolean extraDataSetMinGasPriceEnabled;
private double[] profitabilityMetricsBuckets;

/**
* These 2 parameters must be atomically updated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@

package net.consensys.linea.extradata;

import static net.consensys.linea.metrics.LineaMetricCategory.PRICING_CONF;

import java.util.concurrent.atomic.AtomicBoolean;

import com.google.auto.service.AutoService;
import lombok.extern.slf4j.Slf4j;
import net.consensys.linea.AbstractLineaRequiredPlugin;
import net.consensys.linea.config.LineaProfitabilityConfiguration;
import net.consensys.linea.metrics.LineaMetricCategory;
import org.hyperledger.besu.plugin.BesuPlugin;
import org.hyperledger.besu.plugin.ServiceManager;
import org.hyperledger.besu.plugin.data.AddedBlockContext;
Expand All @@ -46,6 +47,8 @@ public void doRegister(final ServiceManager context) {
() ->
new RuntimeException(
"Failed to obtain RpcEndpointService from the ServiceManager."));

metricCategoryRegistry.addMetricCategory(PRICING_CONF);
}

/**
Expand Down Expand Up @@ -95,16 +98,15 @@ public synchronized void onInitialSyncRestart() {
});
}

initMetrics(profitabilityConfiguration());
if (metricCategoryRegistry.isMetricCategoryEnabled(PRICING_CONF)) {
initMetrics(profitabilityConfiguration());
}
}

private void initMetrics(final LineaProfitabilityConfiguration lineaProfitabilityConfiguration) {
final var confLabelledGauge =
metricsSystem.createLabelledSuppliedGauge(
LineaMetricCategory.PROFITABILITY,
"conf",
"Profitability configuration values at runtime",
"field");
PRICING_CONF, "values", "Profitability configuration values at runtime", "field");
confLabelledGauge.labels(lineaProfitabilityConfiguration::fixedCostWei, "fixed_cost_wei");
confLabelledGauge.labels(lineaProfitabilityConfiguration::variableCostWei, "variable_cost_wei");
confLabelledGauge.labels(lineaProfitabilityConfiguration::ethGasPriceWei, "eth_gas_price_wei");
Expand Down
Loading

0 comments on commit ab849c5

Please sign in to comment.