Skip to content

Commit

Permalink
Added L2GasPriceSuggesterFactor config parameter to simulate estimate…
Browse files Browse the repository at this point in the history
…d L2 gas price (EGP disabled) (0xPolygonHermez#2777) (0xPolygonHermez#2805)

* added L2GasPriceSuggesterFactor config parameter to "simulate" estimated l2 gas price when egp is disabled

* fix L2GasPriceSuggesterFactor value in test config file

* fix L2GasPriceSuggesterFactor value in test config file

* update doc
  • Loading branch information
agnusmor authored Nov 20, 2023
1 parent b7e59ae commit 5fcffeb
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 63 deletions.
1 change: 1 addition & 0 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ GlobalQueue = 1024
NetProfit = 1
BreakEvenFactor = 1.1
FinalDeviationPct = 10
L2GasPriceSuggesterFactor = 0.5
[Pool.DB]
User = "pool_user"
Password = "pool_password"
Expand Down
1 change: 1 addition & 0 deletions config/environments/local/local.node.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GlobalQueue = 1024
NetProfit = 1
BreakEvenFactor = 1.1
FinalDeviationPct = 10
L2GasPriceSuggesterFactor = 0.5
[Pool.DB]
User = "pool_user"
Password = "pool_password"
Expand Down
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html

Large diffs are not rendered by default.

34 changes: 18 additions & 16 deletions docs/config-file/node-config-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -720,15 +720,16 @@ GlobalQueue=1024
**Type:** : `object`
**Description:** EffectiveGasPrice is the config for the effective gas price calculation

| Property | Pattern | Type | Deprecated | Definition | Title/Description |
| ----------------------------------------------------------------- | ------- | ------- | ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
| - [Enabled](#Pool_EffectiveGasPrice_Enabled ) | No | boolean | No | - | Enabled is a flag to enable/disable the effective gas price |
| - [L1GasPriceFactor](#Pool_EffectiveGasPrice_L1GasPriceFactor ) | No | number | No | - | L1GasPriceFactor is the percentage of the L1 gas price that will be used as the L2 min gas price |
| - [ByteGasCost](#Pool_EffectiveGasPrice_ByteGasCost ) | No | integer | No | - | ByteGasCost is the gas cost per byte that is not 0 |
| - [ZeroByteGasCost](#Pool_EffectiveGasPrice_ZeroByteGasCost ) | No | integer | No | - | ZeroByteGasCost is the gas cost per byte that is 0 |
| - [NetProfit](#Pool_EffectiveGasPrice_NetProfit ) | No | number | No | - | NetProfit is the profit margin to apply to the calculated breakEvenGasPrice |
| - [BreakEvenFactor](#Pool_EffectiveGasPrice_BreakEvenFactor ) | No | number | No | - | BreakEvenFactor is the factor to apply to the calculated breakevenGasPrice when comparing it with the gasPriceSigned of a tx |
| - [FinalDeviationPct](#Pool_EffectiveGasPrice_FinalDeviationPct ) | No | integer | No | - | FinalDeviationPct is the max allowed deviation percentage BreakEvenGasPrice on re-calculation |
| Property | Pattern | Type | Deprecated | Definition | Title/Description |
| --------------------------------------------------------------------------------- | ------- | ------- | ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - [Enabled](#Pool_EffectiveGasPrice_Enabled ) | No | boolean | No | - | Enabled is a flag to enable/disable the effective gas price |
| - [L1GasPriceFactor](#Pool_EffectiveGasPrice_L1GasPriceFactor ) | No | number | No | - | L1GasPriceFactor is the percentage of the L1 gas price that will be used as the L2 min gas price |
| - [ByteGasCost](#Pool_EffectiveGasPrice_ByteGasCost ) | No | integer | No | - | ByteGasCost is the gas cost per byte that is not 0 |
| - [ZeroByteGasCost](#Pool_EffectiveGasPrice_ZeroByteGasCost ) | No | integer | No | - | ZeroByteGasCost is the gas cost per byte that is 0 |
| - [NetProfit](#Pool_EffectiveGasPrice_NetProfit ) | No | number | No | - | NetProfit is the profit margin to apply to the calculated breakEvenGasPrice |
| - [BreakEvenFactor](#Pool_EffectiveGasPrice_BreakEvenFactor ) | No | number | No | - | BreakEvenFactor is the factor to apply to the calculated breakevenGasPrice when comparing it with the gasPriceSigned of a tx |
| - [FinalDeviationPct](#Pool_EffectiveGasPrice_FinalDeviationPct ) | No | integer | No | - | FinalDeviationPct is the max allowed deviation percentage BreakEvenGasPrice on re-calculation |
| - [L2GasPriceSuggesterFactor](#Pool_EffectiveGasPrice_L2GasPriceSuggesterFactor ) | No | number | No | - | L2GasPriceSuggesterFactor is the factor to apply to L1 gas price to get the suggested L2 gas price used in the<br />calculations when the effective gas price is disabled (testing/metrics purposes) |

#### <a name="Pool_EffectiveGasPrice_Enabled"></a>7.11.1. `Pool.EffectiveGasPrice.Enabled`

Expand Down Expand Up @@ -828,18 +829,19 @@ BreakEvenFactor=1.1
FinalDeviationPct=10
```

### <a name="Pool_ForkID"></a>7.12. `Pool.ForkID`
#### <a name="Pool_EffectiveGasPrice_L2GasPriceSuggesterFactor"></a>7.11.8. `Pool.EffectiveGasPrice.L2GasPriceSuggesterFactor`

**Type:** : `integer`
**Type:** : `number`

**Default:** `0`
**Default:** `0.5`

**Description:** ForkID is the current fork ID of the chain
**Description:** L2GasPriceSuggesterFactor is the factor to apply to L1 gas price to get the suggested L2 gas price used in the
calculations when the effective gas price is disabled (testing/metrics purposes)

**Example setting the default value** (0):
**Example setting the default value** (0.5):
```
[Pool]
ForkID=0
[Pool.EffectiveGasPrice]
L2GasPriceSuggesterFactor=0.5
```

## <a name="RPC"></a>8. `[RPC]`
Expand Down
5 changes: 5 additions & 0 deletions docs/config-file/node-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,11 @@
"type": "integer",
"description": "FinalDeviationPct is the max allowed deviation percentage BreakEvenGasPrice on re-calculation",
"default": 10
},
"L2GasPriceSuggesterFactor": {
"type": "number",
"description": "L2GasPriceSuggesterFactor is the factor to apply to L1 gas price to get the suggested L2 gas price used in the\ncalculations when the effective gas price is disabled (testing/metrics purposes)",
"default": 0.5
}
},
"additionalProperties": false,
Expand Down
4 changes: 4 additions & 0 deletions pool/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,8 @@ type EffectiveGasPriceCfg struct {

// FinalDeviationPct is the max allowed deviation percentage BreakEvenGasPrice on re-calculation
FinalDeviationPct uint64 `mapstructure:"FinalDeviationPct"`

// L2GasPriceSuggesterFactor is the factor to apply to L1 gas price to get the suggested L2 gas price used in the
// calculations when the effective gas price is disabled (testing/metrics purposes)
L2GasPriceSuggesterFactor float64 `mapstructure:"L2GasPriceSuggesterFactor"`
}
12 changes: 12 additions & 0 deletions pool/effectivegasprice.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ func (e *EffectiveGasPrice) GetFinalDeviation() uint64 {
return e.cfg.FinalDeviationPct
}

// GetTxAndL2GasPrice return the tx gas price and l2 suggested gas price to use in egp calculations
// If egp is disabled we will use a "simulated" tx and l2 gas price, that is calculated using the L2GasPriceSuggesterFactor config param
func (e *EffectiveGasPrice) GetTxAndL2GasPrice(txGasPrice *big.Int, l1GasPrice uint64, l2GasPrice uint64) (egpTxGasPrice *big.Int, egpL2GasPrice uint64) {
if !e.cfg.Enabled {
// If egp is not enabled we use the L2GasPriceSuggesterFactor to calculate the "simulated" suggested L2 gas price
gp := new(big.Int).SetUint64(uint64(e.cfg.L2GasPriceSuggesterFactor * float64(l1GasPrice)))
return gp, gp.Uint64()
} else {
return txGasPrice, l2GasPrice
}
}

// CalculateBreakEvenGasPrice calculates the break even gas price for a transaction
func (e *EffectiveGasPrice) CalculateBreakEvenGasPrice(rawTx []byte, txGasPrice *big.Int, txGasUsed uint64, l1GasPrice uint64) (*big.Int, error) {
const (
Expand Down
15 changes: 8 additions & 7 deletions pool/effectivegasprice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ const (

var (
egpCfg = EffectiveGasPriceCfg{
Enabled: true,
L1GasPriceFactor: 0.25,
ByteGasCost: 16,
ZeroByteGasCost: 4,
NetProfit: 1,
BreakEvenFactor: 1.1,
FinalDeviationPct: 10,
Enabled: true,
L1GasPriceFactor: 0.25,
ByteGasCost: 16,
ZeroByteGasCost: 4,
NetProfit: 1,
BreakEvenFactor: 1.1,
FinalDeviationPct: 10,
L2GasPriceSuggesterFactor: 0.5,
}
)

Expand Down
15 changes: 9 additions & 6 deletions pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,10 @@ func (p *Pool) StoreTx(ctx context.Context, tx types.Transaction, ip string, isW

// ValidateBreakEvenGasPrice validates the effective gas price
func (p *Pool) ValidateBreakEvenGasPrice(ctx context.Context, tx types.Transaction, preExecutionGasUsed uint64, gasPrices GasPrices) error {
breakEvenGasPrice, err := p.effectiveGasPrice.CalculateBreakEvenGasPrice(tx.Data(), tx.GasPrice(), preExecutionGasUsed, gasPrices.L1GasPrice)
// Get the tx gas price we will use in the egp calculation. If egp is disabled we will use a "simulated" tx gas price
txGasPrice, _ := p.effectiveGasPrice.GetTxAndL2GasPrice(tx.GasPrice(), gasPrices.L1GasPrice, gasPrices.L2GasPrice)

breakEvenGasPrice, err := p.effectiveGasPrice.CalculateBreakEvenGasPrice(tx.Data(), txGasPrice, preExecutionGasUsed, gasPrices.L1GasPrice)
if err != nil {
if p.cfg.EffectiveGasPrice.Enabled {
log.Errorf("error calculating BreakEvenGasPrice: %v", err)
Expand All @@ -262,20 +265,20 @@ func (p *Pool) ValidateBreakEvenGasPrice(ctx context.Context, tx types.Transacti
breakEvenGasPriceWithFactor := new(big.Int)
tmpFactor.Int(breakEvenGasPriceWithFactor)

if breakEvenGasPriceWithFactor.Cmp(tx.GasPrice()) == 1 { // breakEvenGasPriceWithMargin > tx.GasPrice()
if breakEvenGasPriceWithFactor.Cmp(txGasPrice) == 1 { // breakEvenGasPriceWithMargin > txGasPrice
// check against L2GasPrice now
L2GasPrice := big.NewInt(0).SetUint64(gasPrices.L2GasPrice)
if tx.GasPrice().Cmp(L2GasPrice) == -1 { // tx.GasPrice() < gasPrices.L2GasPrice
if txGasPrice.Cmp(L2GasPrice) == -1 { // txGasPrice < gasPrices.L2GasPrice
// reject tx
reject = true
} else {
// accept loss
loss = loss.Sub(breakEvenGasPriceWithFactor, tx.GasPrice())
loss = loss.Sub(breakEvenGasPriceWithFactor, txGasPrice)
}
}

log.Infof("egp-log: tx.GasPrice(): %v, breakEvenGasPrice: %v, breakEvenGasPriceWithFactor: %v, gasUsed: %v, reject: %t, loss: %v, L1GasPrice: %d, L2GasPrice: %d, Enabled: %t, tx: %s",
tx.GasPrice(), breakEvenGasPrice, breakEvenGasPriceWithFactor, preExecutionGasUsed, reject, loss, gasPrices.L1GasPrice, gasPrices.L2GasPrice, p.cfg.EffectiveGasPrice.Enabled, tx.Hash().String())
log.Infof("egp-log: txGasPrice(): %v, breakEvenGasPrice: %v, breakEvenGasPriceWithFactor: %v, gasUsed: %v, reject: %t, loss: %v, L1GasPrice: %d, L2GasPrice: %d, Enabled: %t, tx: %s",
txGasPrice, breakEvenGasPrice, breakEvenGasPriceWithFactor, preExecutionGasUsed, reject, loss, gasPrices.L1GasPrice, gasPrices.L2GasPrice, p.cfg.EffectiveGasPrice.Enabled, tx.Hash().String())

// Reject transaction if EffectiveGasPrice is enabled
if p.cfg.EffectiveGasPrice.Enabled && reject {
Expand Down
15 changes: 8 additions & 7 deletions pool/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,14 @@ var (
AccountQueue: 15,
GlobalQueue: 20,
EffectiveGasPrice: pool.EffectiveGasPriceCfg{
Enabled: true,
L1GasPriceFactor: 0.25,
ByteGasCost: 16,
ZeroByteGasCost: 4,
NetProfit: 1,
BreakEvenFactor: 1.1,
FinalDeviationPct: 10,
Enabled: true,
L1GasPriceFactor: 0.25,
ByteGasCost: 16,
ZeroByteGasCost: 4,
NetProfit: 1,
BreakEvenFactor: 1.1,
FinalDeviationPct: 10,
L2GasPriceSuggesterFactor: 0.5,
},
}
gasPrice = big.NewInt(1000000000)
Expand Down
48 changes: 29 additions & 19 deletions sequencer/finalizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,19 +608,23 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
f.processRequest.Transactions = tx.RawTx
hashStr = tx.HashStr

txGasPrice := tx.GasPrice

// If it is the first time we process this tx then we calculate the EffectiveGasPrice
if firstTxProcess {
// Get L1 gas price and store in txTracker to make it consistent during the lifespan of the transaction
tx.L1GasPrice, tx.L2GasPrice = f.dbManager.GetL1AndL2GasPrice()
log.Infof("tx.L1GasPrice = %d, tx.L2GasPrice = %d", tx.L1GasPrice, tx.L2GasPrice)
// Get the tx and l2 gas price we will use in the egp calculation. If egp is disabled we will use a "simulated" tx gas price
txGasPrice, txL2GasPrice := f.effectiveGasPrice.GetTxAndL2GasPrice(tx.GasPrice, tx.L1GasPrice, tx.L2GasPrice)

// Save values for later logging
tx.EGPLog.GasUsedFirst = tx.BatchResources.ZKCounters.CumulativeGasUsed
tx.EGPLog.GasPrice.Set(tx.GasPrice)
tx.EGPLog.L1GasPrice = tx.L1GasPrice
tx.EGPLog.L2GasPrice = tx.L2GasPrice
tx.EGPLog.L2GasPrice = txL2GasPrice
tx.EGPLog.GasUsedFirst = tx.BatchResources.ZKCounters.CumulativeGasUsed
tx.EGPLog.GasPrice.Set(txGasPrice)

// Calculate EffectiveGasPrice
egp, err := f.effectiveGasPrice.CalculateEffectiveGasPrice(tx.RawTx, tx.GasPrice, tx.BatchResources.ZKCounters.CumulativeGasUsed, tx.L1GasPrice, tx.L2GasPrice)
egp, err := f.effectiveGasPrice.CalculateEffectiveGasPrice(tx.RawTx, txGasPrice, tx.BatchResources.ZKCounters.CumulativeGasUsed, tx.L1GasPrice, txL2GasPrice)
if err != nil {
if f.effectiveGasPrice.IsEnabled() {
return nil, err
Expand All @@ -634,22 +638,22 @@ func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker, first
// Save first EffectiveGasPrice for later logging
tx.EGPLog.ValueFirst.Set(tx.EffectiveGasPrice)

// If EffectiveGasPrice >= tx.GasPrice, we process the tx with tx.GasPrice
if tx.EffectiveGasPrice.Cmp(tx.GasPrice) >= 0 {
tx.EffectiveGasPrice.Set(tx.GasPrice)
// If EffectiveGasPrice >= txGasPrice, we process the tx with tx.GasPrice
if tx.EffectiveGasPrice.Cmp(txGasPrice) >= 0 {
tx.EffectiveGasPrice.Set(txGasPrice)

loss := new(big.Int).Sub(tx.EffectiveGasPrice, tx.GasPrice)
loss := new(big.Int).Sub(tx.EffectiveGasPrice, txGasPrice)
// If loss > 0 the warning message indicating we loss fee for thix tx
if loss.Cmp(new(big.Int).SetUint64(0)) == 1 {
log.Warnf("egp-loss: gasPrice: %d, effectiveGasPrice1: %d, loss: %d, txHash: %s", tx.GasPrice, tx.EffectiveGasPrice, loss, tx.HashStr)
log.Warnf("egp-loss: gasPrice: %d, effectiveGasPrice1: %d, loss: %d, txHash: %s", txGasPrice, tx.EffectiveGasPrice, loss, tx.HashStr)
}

tx.IsLastExecution = true
}
}
}

effectivePercentage, err := f.effectiveGasPrice.CalculateEffectiveGasPricePercentage(tx.GasPrice, tx.EffectiveGasPrice)
effectivePercentage, err := f.effectiveGasPrice.CalculateEffectiveGasPricePercentage(txGasPrice, tx.EffectiveGasPrice)
if err != nil {
if f.effectiveGasPrice.IsEnabled() {
return nil, err
Expand Down Expand Up @@ -741,7 +745,10 @@ func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *Tx
if !tx.IsLastExecution {
tx.IsLastExecution = true

newEffectiveGasPrice, err := f.effectiveGasPrice.CalculateEffectiveGasPrice(tx.RawTx, tx.GasPrice, result.Responses[0].GasUsed, tx.L1GasPrice, tx.L2GasPrice)
// Get the tx gas price we will use in the egp calculation. If egp is disabled we will use a "simulated" tx gas price
txGasPrice, txL2GasPrice := f.effectiveGasPrice.GetTxAndL2GasPrice(tx.GasPrice, tx.L1GasPrice, tx.L2GasPrice)

newEffectiveGasPrice, err := f.effectiveGasPrice.CalculateEffectiveGasPrice(tx.RawTx, txGasPrice, result.Responses[0].GasUsed, tx.L1GasPrice, txL2GasPrice)
if err != nil {
if egpEnabled {
log.Errorf("failed to calculate EffectiveGasPrice with new gasUsed for tx %s, error: %s", tx.HashStr, err.Error())
Expand All @@ -759,7 +766,7 @@ func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *Tx

// If EffectiveGasPrice is disabled we will calculate the percentage and save it for later logging
if !egpEnabled {
effectivePercentage, err := f.effectiveGasPrice.CalculateEffectiveGasPricePercentage(tx.GasPrice, tx.EffectiveGasPrice)
effectivePercentage, err := f.effectiveGasPrice.CalculateEffectiveGasPricePercentage(txGasPrice, tx.EffectiveGasPrice)
if err != nil {
log.Warnf("EffectiveGasPrice is disabled, but failed to CalculateEffectiveGasPricePercentage#2: %s", err)
tx.EGPLog.Error = fmt.Sprintf("%s, CalculateEffectiveGasPricePercentage#2: %s", tx.EGPLog.Error, err)
Expand Down Expand Up @@ -860,6 +867,9 @@ func (f *finalizer) handleForcedTxsProcessResp(ctx context.Context, request stat
// It returns ErrEffectiveGasPriceReprocess if the tx needs to be reprocessed with
// the tx.EffectiveGasPrice updated, otherwise it returns nil
func (f *finalizer) CompareTxEffectiveGasPrice(ctx context.Context, tx *TxTracker, newEffectiveGasPrice *big.Int, hasGasPriceOC bool, hasBalanceOC bool) error {
// Get the tx gas price we will use in the egp calculation. If egp is disabled we will use a "simulated" tx gas price
txGasPrice, _ := f.effectiveGasPrice.GetTxAndL2GasPrice(tx.GasPrice, tx.L1GasPrice, tx.L2GasPrice)

// Compute the absolute difference between tx.EffectiveGasPrice - newEffectiveGasPrice
diff := new(big.Int).Abs(new(big.Int).Sub(tx.EffectiveGasPrice, newEffectiveGasPrice))
// Compute max deviation allowed of newEffectiveGasPrice
Expand All @@ -871,20 +881,20 @@ func (f *finalizer) CompareTxEffectiveGasPrice(ctx context.Context, tx *TxTracke

// if (diff > finalDeviation)
if diff.Cmp(maxDeviation) == 1 {
// if newEfectiveGasPrice < tx.GasPrice
if newEffectiveGasPrice.Cmp(tx.GasPrice) == -1 {
// if newEfectiveGasPrice < txGasPrice
if newEffectiveGasPrice.Cmp(txGasPrice) == -1 {
if hasGasPriceOC || hasBalanceOC {
tx.EffectiveGasPrice.Set(tx.GasPrice)
tx.EffectiveGasPrice.Set(txGasPrice)
} else {
tx.EffectiveGasPrice.Set(newEffectiveGasPrice)
}
} else {
tx.EffectiveGasPrice.Set(tx.GasPrice)
tx.EffectiveGasPrice.Set(txGasPrice)

loss := new(big.Int).Sub(newEffectiveGasPrice, tx.GasPrice)
loss := new(big.Int).Sub(newEffectiveGasPrice, txGasPrice)
// If loss > 0 the warning message indicating we loss fee for thix tx
if loss.Cmp(new(big.Int).SetUint64(0)) == 1 {
log.Warnf("egp-loss: gasPrice: %d, EffectiveGasPrice2: %d, loss: %d, txHash: %s", tx.GasPrice, newEffectiveGasPrice, loss, tx.HashStr)
log.Warnf("egp-loss: gasPrice: %d, EffectiveGasPrice2: %d, loss: %d, txHash: %s", txGasPrice, newEffectiveGasPrice, loss, tx.HashStr)
}
}

Expand Down
Loading

0 comments on commit 5fcffeb

Please sign in to comment.