Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixing comments. #1914

Merged
merged 3 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ func start(cliCtx *cli.Context) error {
case RPC:
log.Info("Running JSON-RPC server")
poolInstance := createPool(c.Pool, c.NetworkConfig.L2BridgeAddr, l2ChainID, st)
if c.RPC.EnableL2SuggestedGasPricePolling {
// Needed for rejecting transactions with too low gas price
poolInstance.StartPollingMinSuggestedGasPrice(ctx)
}
apis := map[string]bool{}
for _, a := range cliCtx.StringSlice(config.FlagHTTPAPI) {
apis[a] = true
Expand Down
14 changes: 12 additions & 2 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,19 @@ func Test_Defaults(t *testing.T) {
path: "Pool.MaxTxDataBytesSize",
expectedValue: 30000,
},

{
path: "Pool.MinGasPrice",
path: "Pool.DefaultMinGasPriceAllowed",
expectedValue: uint64(1000000000),
},
{
path: "Pool.MinSuggestedGasPriceInterval",
path: "Pool.MinAllowedGasPriceInterval",
expectedValue: types.NewDuration(5 * time.Minute),
},
{
path: "Pool.PollMinAllowedGasPriceInterval",
expectedValue: types.NewDuration(15 * time.Second),
},
{
path: "Pool.DB.User",
expectedValue: "pool_user",
Expand Down Expand Up @@ -329,6 +334,11 @@ func Test_Defaults(t *testing.T) {
path: "RPC.WebSockets.Enabled",
expectedValue: false,
},

{
path: "RPC.EnableL2SuggestedGasPricePolling",
expectedValue: true,
},
{
path: "RPC.WebSockets.Port",
expectedValue: 8133,
Expand Down
6 changes: 4 additions & 2 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ MaxConns = 200
FreeClaimGasLimit = 150000
MaxTxBytesSize=30132
MaxTxDataBytesSize=30000
MinGasPrice = 1000000000
MinSuggestedGasPriceInterval = "5m"
DefaultMinGasPriceAllowed = 1000000000
MinAllowedGasPriceInterval = "5m"
PollMinAllowedGasPriceInterval = "15s"
[Pool.DB]
User = "pool_user"
Password = "pool_password"
Expand Down Expand Up @@ -57,6 +58,7 @@ MaxRequestsPerIPAndSecond = 50
SequencerNodeURI = ""
BroadcastURI = "127.0.0.1:61090"
DefaultSenderAddress = "0x1111111111111111111111111111111111111111"
EnableL2SuggestedGasPricePolling = true
[RPC.WebSockets]
Enabled = false
Port = 8133
Expand Down
6 changes: 4 additions & 2 deletions config/environments/local/local.node.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ MaxConns = 200
FreeClaimGasLimit = 1500000
MaxTxBytesSize=30132
MaxTxDataBytesSize=30000
MinGasPrice = 1000000000
MinSuggestedGasPriceInterval = "5m"
DefaultMinGasPriceAllowed = 1000000000
MinAllowedGasPriceInterval = "5m"
PollMinAllowedGasPriceInterval = "15s"
[Pool.DB]
User = "pool_user"
Password = "pool_password"
Expand Down Expand Up @@ -48,6 +49,7 @@ MaxRequestsPerIPAndSecond = 5000
SequencerNodeURI = "https://internal.zkevm-test.net:2083/"
BroadcastURI = "internal.zkevm-test.net:61090"
DefaultSenderAddress = "0x1111111111111111111111111111111111111111"
EnableL2SuggestedGasPricePolling = true
[RPC.WebSockets]
Enabled = true
Port = 8546
Expand Down
6 changes: 4 additions & 2 deletions config/environments/public/public.node.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ MaxConns = 200
FreeClaimGasLimit = 1500000
MaxTxBytesSize=30132
MaxTxDataBytesSize=30000
MinGasPrice = 1000000000
MinSuggestedGasPriceInterval = "5m"
DefaultMinGasPriceAllowed = 1000000000
MinAllowedGasPriceInterval = "5m"
PollMinAllowedGasPriceInterval = "15s"
[Pool.DB]
User = "pool_user"
Password = "pool_password"
Expand Down Expand Up @@ -46,6 +47,7 @@ MaxRequestsPerIPAndSecond = 5000
SequencerNodeURI = "https://rpc.public.zkevm-test.net/"
BroadcastURI = "public-grpc.zkevm-test.net:61090"
DefaultSenderAddress = "0x1111111111111111111111111111111111111111"
EnableL2SuggestedGasPricePolling = false
[RPC.WebSockets]
Enabled = true
Port = 8546
Expand Down
3 changes: 3 additions & 0 deletions jsonrpc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ type Config struct {

// Websockets
WebSockets WebSocketsConfig `mapstructure:"WebSockets"`

// EnableL2SuggestedGasPricePolling enables polling of the L2 gas price to block tx in the RPC with lower gas price.
EnableL2SuggestedGasPricePolling bool `mapstructure:"EnableL2SuggestedGasPricePolling"`
}

// WebSocketsConfig has parameters to config the rpc websocket support
Expand Down
11 changes: 7 additions & 4 deletions pool/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ type Config struct {
// DB is the database configuration
DB db.Config `mapstructure:"DB"`

// MinGasPrice is the minimum gas price allowed for a tx
MinGasPrice uint64 `mapstructure:"MinGasPrice"`
// DefaultMinGasPriceAllowed is the default min gas price to suggest
DefaultMinGasPriceAllowed uint64 `mapstructure:"DefaultMinGasPriceAllowed"`

// MinSuggestedGasPriceInterval is the interval to look back of the suggested min gas price for a tx
MinSuggestedGasPriceInterval types.Duration `mapstructure:"MinSuggestedGasPriceInterval"`
// MinAllowedGasPriceInterval is the interval to look back of the suggested min gas price for a tx
MinAllowedGasPriceInterval types.Duration `mapstructure:"MinAllowedGasPriceInterval"`

// PollMinAllowedGasPriceInterval is the interval to poll the suggested min gas price for a tx
PollMinAllowedGasPriceInterval types.Duration `mapstructure:"PollMinAllowedGasPriceInterval"`
}
4 changes: 2 additions & 2 deletions pool/pgpoolstorage/pgpoolstorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,10 +436,10 @@ func (p *PostgresPoolStorage) GetGasPrice(ctx context.Context) (uint64, error) {

// MinGasPriceSince returns the min gas price after given timestamp
func (p *PostgresPoolStorage) MinGasPriceSince(ctx context.Context, timestamp time.Time) (uint64, error) {
sql := "SELECT MIN(price) FROM pool.gas_price WHERE \"timestamp\" >= $1 LIMIT 1"
sql := "SELECT COALESCE(MIN(price), 0) FROM pool.gas_price WHERE \"timestamp\" >= $1 LIMIT 1"
var gasPrice uint64
err := p.db.QueryRow(ctx, sql, timestamp).Scan(&gasPrice)
if errors.Is(err, pgx.ErrNoRows) {
if gasPrice == 0 || errors.Is(err, pgx.ErrNoRows) {
return 0, state.ErrNotFound
} else if err != nil {
return 0, err
Expand Down
82 changes: 60 additions & 22 deletions pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"math/big"
"sync"
"time"

"github.com/0xPolygonHermez/zkevm-node/log"
Expand Down Expand Up @@ -33,25 +34,41 @@ var (
// that uses a postgres database to store the data
type Pool struct {
storage
state stateInterface
l2BridgeAddr common.Address
chainID uint64
cfg Config
minGasPrice *big.Int
state stateInterface
l2BridgeAddr common.Address
chainID uint64
cfg Config
minSuggestedGasPrice *big.Int
minSuggestedGasPriceMux *sync.RWMutex
}

// NewPool creates and initializes an instance of Pool
func NewPool(cfg Config, s storage, st stateInterface, l2BridgeAddr common.Address, chainID uint64) *Pool {
return &Pool{
cfg: cfg,
storage: s,
state: st,
l2BridgeAddr: l2BridgeAddr,
chainID: chainID,
minGasPrice: big.NewInt(0).SetUint64(cfg.MinGasPrice),
cfg: cfg,
storage: s,
state: st,
l2BridgeAddr: l2BridgeAddr,
chainID: chainID,
minSuggestedGasPriceMux: new(sync.RWMutex),
}
}

// StartPollingMinSuggestedGasPrice starts polling the minimum suggested gas price
func (p *Pool) StartPollingMinSuggestedGasPrice(ctx context.Context) {
p.pollMinSuggestedGasPrice(ctx)
go func() {
for {
select {
case <-ctx.Done():
return
case <-time.After(p.cfg.PollMinAllowedGasPriceInterval.Duration):
p.pollMinSuggestedGasPrice(ctx)
}
}
}()
}

// AddTx adds a transaction to the pool with the pending state
func (p *Pool) AddTx(ctx context.Context, tx types.Transaction, ip string) error {
if err := p.validateTx(ctx, tx); err != nil {
Expand Down Expand Up @@ -169,23 +186,20 @@ func (p *Pool) validateTx(ctx context.Context, tx types.Transaction) error {
if tx.Type() != types.LegacyTxType {
return ErrTxTypeNotSupported
}

// Reject transactions over defined size to prevent DOS attacks
if tx.Size() > p.cfg.MaxTxBytesSize {
return ErrOversizedData
}
if tx.GasPrice().Cmp(p.minGasPrice) == -1 {

// Reject transactions with a gas price lower than the minimum gas price
p.minSuggestedGasPriceMux.RLock()
gasPriceCmp := tx.GasPrice().Cmp(p.minSuggestedGasPrice)
p.minSuggestedGasPriceMux.RUnlock()
if gasPriceCmp == -1 {
return ErrGasPrice
} else {
fromTimestamp := time.Now().UTC().Add(-p.cfg.MinSuggestedGasPriceInterval.Duration)
gasPrice, err := p.storage.MinGasPriceSince(ctx, fromTimestamp)
if err == state.ErrNotFound {
log.Warnf("No suggested min gas price since: %v", fromTimestamp)
} else if err != nil {
return err
} else if tx.GasPrice().Cmp(big.NewInt(0).SetUint64(gasPrice)) == -1 {
return ErrGasPrice
}
}

// Transactions can't be negative. This may never happen using RLP decoded
// transactions but may occur if you create a transaction using the RPC.
if tx.Value().Sign() < 0 {
Expand Down Expand Up @@ -271,6 +285,30 @@ func (p *Pool) validateTx(ctx context.Context, tx types.Transaction) error {
return nil
}

func (p *Pool) pollMinSuggestedGasPrice(ctx context.Context) {
fromTimestamp := time.Now().UTC().Add(-p.cfg.MinAllowedGasPriceInterval.Duration)
gasPrice, err := p.storage.MinGasPriceSince(ctx, fromTimestamp)
if err != nil {
p.minSuggestedGasPriceMux.Lock()
// Ensuring we always have suggested minimum gas price
if p.minSuggestedGasPrice == nil {
p.minSuggestedGasPrice = big.NewInt(0).SetUint64(p.cfg.DefaultMinGasPriceAllowed)
log.Infof("Min allowed gas price updated to: %d", p.cfg.DefaultMinGasPriceAllowed)
}
p.minSuggestedGasPriceMux.Unlock()
if err == state.ErrNotFound {
log.Warnf("No suggested min gas price since: %v", fromTimestamp)
} else {
log.Errorf("Error getting min gas price since: %v", fromTimestamp)
}
} else {
p.minSuggestedGasPriceMux.Lock()
agnusmor marked this conversation as resolved.
Show resolved Hide resolved
p.minSuggestedGasPrice = big.NewInt(0).SetUint64(gasPrice)
p.minSuggestedGasPriceMux.Unlock()
log.Infof("Min allowed gas price updated to: %d", gasPrice)
}
}

// checkTxFieldCompatibilityWithExecutor checks the field sizes of the transaction to make sure
// they ar compatible with the Executor needs
// GasLimit: 256 bits
Expand Down
Loading