Skip to content

Commit

Permalink
Gas price estimator (0xPolygonHermez#393)
Browse files Browse the repository at this point in the history
* implemented simplest gas price estimator

* adding default and lastNBlocks gas price estimation strategy

* added comments to the function

* added setting to default gpe

* deleted auto rebases

* fixing lint errors

* fixing naming DefaultGasPriceWei

* deleted redundant field from sequencer config

* split gaspriceestimator.go file to different

* renamed newXXXEstimator functions names

* fixed config names

* fixing Federico pr comments

* added dots to cmd/run.go comments
  • Loading branch information
Mikelle authored Feb 16, 2022
1 parent 81df820 commit 49c3519
Show file tree
Hide file tree
Showing 21 changed files with 386 additions and 47 deletions.
5 changes: 0 additions & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ jobs:
go-version: 1.16.x
- name: Checkout code
uses: actions/checkout@v2
- name: Automatic Rebase
uses: cirrus-actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: github.event_name == 'pull_request'
- name: Lint
run: |
make install-linter
Expand Down
5 changes: 0 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Automatic Rebase
uses: cirrus-actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: github.event_name == 'pull_request'
- name: Install Go
uses: actions/setup-go@v1
with:
Expand Down
33 changes: 27 additions & 6 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/hermeznetwork/hermez-core/config"
"github.com/hermeznetwork/hermez-core/db"
"github.com/hermeznetwork/hermez-core/etherman"
"github.com/hermeznetwork/hermez-core/gasprice"
"github.com/hermeznetwork/hermez-core/jsonrpc"
"github.com/hermeznetwork/hermez-core/log"
"github.com/hermeznetwork/hermez-core/pool"
Expand Down Expand Up @@ -70,9 +71,10 @@ func start(ctx *cli.Context) error {
c.Sequencer.DefaultChainID = c.NetworkConfig.L2DefaultChainID
seq := createSequencer(c.Sequencer, etherman, pool, st)

go runSynchronizer(c.NetworkConfig, etherman, st, c.Synchronizer)
gpe := createGasPriceEstimator(c.GasPriceEstimator, st, pool)
go runSynchronizer(c.NetworkConfig, etherman, st, c.Synchronizer, gpe)
go seq.Start()
go runJSONRpcServer(*c, pool, st, seq.ChainID)
go runJSONRpcServer(*c, pool, st, seq.ChainID, gpe)

proverClient, conn := newProverClient(c.Prover)
go runAggregator(c.Aggregator, etherman, proverClient, st)
Expand Down Expand Up @@ -117,7 +119,7 @@ func newProverClient(c proverclient.Config) (proverclient.ZKProverClient, *grpc.
return proverClient, conn
}

func runSynchronizer(networkConfig config.NetworkConfig, etherman *etherman.ClientEtherMan, st state.State, cfg synchronizer.Config) {
func runSynchronizer(networkConfig config.NetworkConfig, etherman *etherman.ClientEtherMan, st state.State, cfg synchronizer.Config, gpe gasPriceEstimator) {
genesisBlock, err := etherman.EtherClient.BlockByNumber(context.Background(), big.NewInt(0).SetUint64(networkConfig.GenBlockNumber))
if err != nil {
log.Fatal(err)
Expand All @@ -126,7 +128,7 @@ func runSynchronizer(networkConfig config.NetworkConfig, etherman *etherman.Clie
Block: genesisBlock,
Balances: networkConfig.Balances,
}
sy, err := synchronizer.NewSynchronizer(etherman, st, networkConfig.GenBlockNumber, genesis, cfg)
sy, err := synchronizer.NewSynchronizer(etherman, st, networkConfig.GenBlockNumber, genesis, cfg, gpe)
if err != nil {
log.Fatal(err)
}
Expand All @@ -135,7 +137,7 @@ func runSynchronizer(networkConfig config.NetworkConfig, etherman *etherman.Clie
}
}

func runJSONRpcServer(c config.Config, pool *pool.PostgresPool, st state.State, chainID uint64) {
func runJSONRpcServer(c config.Config, pool *pool.PostgresPool, st state.State, chainID uint64, gpe gasPriceEstimator) {
var err error
key, err := newKeyFromKeystore(c.Etherman.PrivateKeyPath, c.Etherman.PrivateKeyPassword)
if err != nil {
Expand All @@ -144,7 +146,7 @@ func runJSONRpcServer(c config.Config, pool *pool.PostgresPool, st state.State,

seqAddress := key.Address

if err := jsonrpc.NewServer(c.RPC, c.NetworkConfig.L2DefaultChainID, seqAddress, pool, st, chainID).Start(); err != nil {
if err := jsonrpc.NewServer(c.RPC, c.NetworkConfig.L2DefaultChainID, seqAddress, pool, st, chainID, gpe).Start(); err != nil {
log.Fatal(err)
}
}
Expand All @@ -165,6 +167,25 @@ func runAggregator(c aggregator.Config, etherman *etherman.ClientEtherMan, prove
agg.Start()
}

// gasPriceEstimator interface for gas price estimator.
type gasPriceEstimator interface {
GetAvgGasPrice() (*big.Int, error)
UpdateGasPriceAvg(newValue *big.Int)
}

// createGasPriceEstimator init gas price gasPriceEstimator based on type in config.
func createGasPriceEstimator(cfg gasprice.Config, state state.State, pool *pool.PostgresPool) gasPriceEstimator {
switch cfg.Type {
case gasprice.AllBatchesType:
return gasprice.NewEstimatorAllBatches()
case gasprice.LastNBatchesType:
return gasprice.NewEstimatorLastNBatches(cfg, state)
case gasprice.DefaultType:
return gasprice.NewDefaultEstimator(cfg, pool)
}
return nil
}

func waitSignal(conn *grpc.ClientConn) {
//func waitSignal() {
signals := make(chan os.Signal, 1)
Expand Down
5 changes: 4 additions & 1 deletion config/config.debug.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ SyncChunkSize = 100
AllowNonRegistered = "false"
IntervalToProposeBatch = "15s"
SyncedBlockDif = 1
DefaultGasPriceWei = 1000000000
[Sequencer.Strategy]
[Sequencer.Strategy.TxSelector]
Type = "acceptall"
Expand All @@ -40,6 +39,10 @@ IntervalToConsolidateState = "10s"
TxProfitabilityCheckerType = "acceptall"
TxProfitabilityMinReward = "1.1"

[GasPriceEstimator]
Type = "default"
DefaultGasPriceWei = 1000000000

[Prover]
ProverURI = "localhost:50051"

Expand Down
22 changes: 12 additions & 10 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/hermeznetwork/hermez-core/aggregator"
"github.com/hermeznetwork/hermez-core/db"
"github.com/hermeznetwork/hermez-core/etherman"
"github.com/hermeznetwork/hermez-core/gasprice"
"github.com/hermeznetwork/hermez-core/jsonrpc"
"github.com/hermeznetwork/hermez-core/log"
"github.com/hermeznetwork/hermez-core/proverclient"
Expand All @@ -21,16 +22,17 @@ import (

// Config represents the configuration of the entire Hermez Node
type Config struct {
Log log.Config
Database db.Config
Etherman etherman.Config
RPC jsonrpc.Config
Synchronizer synchronizer.Config
Sequencer sequencer.Config
Aggregator aggregator.Config
Prover proverclient.Config
NetworkConfig NetworkConfig
MTService tree.Config
Log log.Config
Database db.Config
Etherman etherman.Config
RPC jsonrpc.Config
Synchronizer synchronizer.Config
Sequencer sequencer.Config
Aggregator aggregator.Config
Prover proverclient.Config
NetworkConfig NetworkConfig
GasPriceEstimator gasprice.Config
MTService tree.Config
}

// Load loads the configuration
Expand Down
5 changes: 4 additions & 1 deletion config/config.local.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ SyncChunkSize = 100
AllowNonRegistered = "false"
IntervalToProposeBatch = "15s"
SyncedBlockDif = 1
DefaultGasPriceWei = 1000000000
[Sequencer.Strategy]
[Sequencer.Strategy.TxSelector]
Type = "acceptall"
Expand All @@ -35,6 +34,10 @@ DefaultGasPriceWei = 1000000000
Type = "acceptall"
MinReward = "1.1"

[GasPriceEstimator]
Type = "default"
DefaultGasPriceWei = 1000000000

[Aggregator]
IntervalToConsolidateState = "10s"
TxProfitabilityCheckerType = "acceptall"
Expand Down
2 changes: 1 addition & 1 deletion config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func Test_Defaults(t *testing.T) {
expectedValue: false,
},
{
path: "Sequencer.DefaultGasPriceWei",
path: "GasPriceEstimator.DefaultGasPriceWei",
expectedValue: uint64(1000000000),
},
{
Expand Down
5 changes: 4 additions & 1 deletion config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ SyncChunkSize = 100
[Sequencer]
AllowNonRegistered = "false"
IntervalToProposeBatch = "15s"
DefaultGasPriceWei = 1000000000
SyncedBlockDif = 1
[Sequencer.Strategy]
[Sequencer.Strategy.TxSelector]
Expand All @@ -45,6 +44,10 @@ IntervalToConsolidateState = "3s"
TxProfitabilityCheckerType = "acceptall"
TxProfitabilityMinReward = "1.1"
[GasPriceEstimator]
Type = "default"
DefaultGasPriceWei = 1000000000
[Prover]
ProverURI = "0.0.0.0:50051"
Expand Down
42 changes: 42 additions & 0 deletions gasprice/allbatches.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package gasprice

import (
"math/big"
"sync"
)

// AllBatches struct for all batches avg price strategy.
type AllBatches struct {
// Average gas price (rolling average)
averageGasPrice *big.Int // The average gas price that gets queried
averageGasPriceCount *big.Int // Param used in the avg. gas price calculation

agpMux sync.Mutex // Mutex for the averageGasPrice calculation
}

// NewEstimatorAllBatches init gas price estimator for all batches strategy.
func NewEstimatorAllBatches() *AllBatches {
return &AllBatches{
averageGasPrice: big.NewInt(0),
averageGasPriceCount: big.NewInt(0),
}
}

// UpdateGasPriceAvg Updates the rolling average value of the gas price.
func (g *AllBatches) UpdateGasPriceAvg(newValue *big.Int) {
g.agpMux.Lock()

g.averageGasPriceCount.Add(g.averageGasPriceCount, big.NewInt(1))

differential := big.NewInt(0)
differential.Div(newValue.Sub(newValue, g.averageGasPrice), g.averageGasPriceCount)

g.averageGasPrice.Add(g.averageGasPrice, differential)

g.agpMux.Unlock()
}

// GetAvgGasPrice get avg gas price from all blocks.
func (g *AllBatches) GetAvgGasPrice() (*big.Int, error) {
return g.averageGasPrice, nil
}
28 changes: 28 additions & 0 deletions gasprice/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package gasprice

import (
"math/big"
)

// EstimatorType different gas estimator types.
type EstimatorType string

const (
// DefaultType default gas price from config is set.
DefaultType EstimatorType = "default"
// AllBatchesType calculate average gas used from all batches.
AllBatchesType EstimatorType = "allbatches"
// LastNBatchesType calculate average gas tip from last n batches.
LastNBatchesType EstimatorType = "lastnbatches"
)

// Config for gas price estimator.
type Config struct {
Type EstimatorType `mapstructure:"Type"`

DefaultGasPriceWei uint64 `mapstructure:"DefaultGasPriceWei"`
MaxPrice *big.Int `mapstructure:"MaxPrice"`
IgnorePrice *big.Int `mapstructure:"IgnorePrice"`
CheckBlocks int `mapstructure:"CheckBlocks"`
Percentile int `mapstructure:"Percentile"`
}
46 changes: 46 additions & 0 deletions gasprice/default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package gasprice

import (
"context"
"errors"
"fmt"
"math/big"

"github.com/hermeznetwork/hermez-core/state"
)

// Default gas price from config is set.
type Default struct {
cfg Config
pool pool
}

// GetAvgGasPrice get default gas price from the pool.
func (d *Default) GetAvgGasPrice() (*big.Int, error) {
ctx := context.Background()
gasPrice, err := d.pool.GetGasPrice(ctx)
if errors.Is(err, state.ErrNotFound) {
return big.NewInt(0), nil
} else if err != nil {
return nil, err
}
return new(big.Int).SetUint64(gasPrice), nil
}

// UpdateGasPriceAvg not needed for default strategy.
func (d *Default) UpdateGasPriceAvg(newValue *big.Int) {}

func (d *Default) setDefaultGasPrice() {
ctx := context.Background()
err := d.pool.SetGasPrice(ctx, d.cfg.DefaultGasPriceWei)
if err != nil {
panic(fmt.Errorf("failed to set default gas price, err: %v", err))
}
}

// NewDefaultEstimator init default gas price estimator.
func NewDefaultEstimator(cfg Config, pool pool) *Default {
gpe := &Default{cfg: cfg, pool: pool}
gpe.setDefaultGasPrice()
return gpe
}
8 changes: 8 additions & 0 deletions gasprice/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gasprice

import "context"

type pool interface {
SetGasPrice(ctx context.Context, gasPrice uint64) error
GetGasPrice(ctx context.Context) (uint64, error)
}
Loading

0 comments on commit 49c3519

Please sign in to comment.