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

allow pool to be blocked #1899

Merged
merged 9 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ MaxConns = 200

[Pool]
FreeClaimGasLimit = 150000
IntervalToRefreshBlockedAddresses = "5m"
[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 @@ -16,6 +16,7 @@ MaxConns = 200

[Pool]
FreeClaimGasLimit = 1500000
IntervalToRefreshBlockedAddresses = "5m"
[Pool.DB]
User = "pool_user"
Password = "pool_password"
Expand Down
1 change: 1 addition & 0 deletions config/environments/public/public.node.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ MaxConns = 200

[Pool]
FreeClaimGasLimit = 1500000
IntervalToRefreshBlockedAddresses = "5m"
[Pool.DB]
User = "pool_user"
Password = "pool_password"
Expand Down
8 changes: 8 additions & 0 deletions db/migrations/pool/0006.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- +migrate Up
CREATE TABLE pool.blocked
(
addr varchar NOT NULL PRIMARY KEY
);

-- +migrate Down
DROP TABLE pool.blocked;
9 changes: 8 additions & 1 deletion pool/config.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package pool

import "github.com/0xPolygonHermez/zkevm-node/db"
import (
"github.com/0xPolygonHermez/zkevm-node/config/types"
"github.com/0xPolygonHermez/zkevm-node/db"
)

// Config is the pool configuration
type Config struct {
// FreeClaimGasLimit is the max gas allowed use to do a free claim
FreeClaimGasLimit uint64 `mapstructure:"FreeClaimGasLimit"`
DB db.Config `mapstructure:"DB"`

// IntervalToRefreshBlockedAddresses is the time it takes to sync the
// blocked address list from db to memory
IntervalToRefreshBlockedAddresses types.Duration `mapstructure:"IntervalToRefreshBlockedAddresses"`
}
3 changes: 3 additions & 0 deletions pool/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ var (
// ErrInvalidSender is returned if the transaction contains an invalid signature.
ErrInvalidSender = errors.New("invalid sender")

// ErrBlockedSender is returned if the transaction is sent by a blocked account.
ErrBlockedSender = errors.New("blocked sender")

// ErrNonceTooLow is returned if the nonce of a transaction is lower than the
// one present in the local chain.
ErrNonceTooLow = errors.New("nonce too low")
Expand Down
2 changes: 2 additions & 0 deletions pool/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type storage interface {
GetTxZkCountersByHash(ctx context.Context, hash common.Hash) (*state.ZKCounters, error)
DeleteTransactionByHash(ctx context.Context, hash common.Hash) error
MarkWIPTxsAsPending(ctx context.Context) error
GetAllAddressesBlocked(ctx context.Context) ([]common.Address, error)
IsAddressBlocked(ctx context.Context, address common.Address) (bool, error)
}

type stateInterface interface {
Expand Down
43 changes: 43 additions & 0 deletions pool/pgpoolstorage/pgpoolstorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,3 +622,46 @@ func (p *PostgresPoolStorage) UpdateTxWIPStatus(ctx context.Context, hash common
}
return nil
}

// GetAllAddressesBlocked get all addresses blocked
func (p *PostgresPoolStorage) GetAllAddressesBlocked(ctx context.Context) ([]common.Address, error) {
sql := `SELECT addr FROM pool.blocked`

rows, err := p.db.Query(ctx, sql)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
} else {
return nil, err
}
}
defer rows.Close()

var addrs []common.Address
for rows.Next() {
var addr string
err := rows.Scan(&addr)
if err != nil {
return nil, err
}
addrs = append(addrs, common.HexToAddress(addr))
}

return addrs, nil
}

// IsAddressBlocked check if an address is added to the blocked table
func (p *PostgresPoolStorage) IsAddressBlocked(ctx context.Context, address common.Address) (bool, error) {
tclemos marked this conversation as resolved.
Show resolved Hide resolved
sql := `SELECT addr FROM pool.blocked WHERE addr = $1`
var addr string
err := p.db.QueryRow(ctx, sql, address.String()).Scan(&addr)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return false, nil
} else {
return false, err
}
}

return true, nil
}
71 changes: 61 additions & 10 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 @@ -45,20 +46,64 @@ var (
// that uses a postgres database to store the data
type Pool struct {
storage
state stateInterface
l2BridgeAddr common.Address
chainID uint64
cfg Config
state stateInterface
l2BridgeAddr common.Address
chainID uint64
cfg Config
blockedAddresses sync.Map
}

// 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,
p := &Pool{
cfg: cfg,
storage: s,
state: st,
l2BridgeAddr: l2BridgeAddr,
chainID: chainID,
blockedAddresses: sync.Map{},
}

p.refreshBlockedAddresses()
go func(cfg *Config, p *Pool) {
for {
time.Sleep(cfg.IntervalToRefreshBlockedAddresses.Duration)
p.refreshBlockedAddresses()
}
}(&cfg, p)
return p
}

// refreshBlockedAddresses refreshes the list of blocked addresses for the provided instance of pool
func (p *Pool) refreshBlockedAddresses() {
blockedAddresses, err := p.storage.GetAllAddressesBlocked(context.Background())
if err != nil {
log.Error("failed to load blocked addresses")
return
}

for _, blockedAddress := range blockedAddresses {
p.blockedAddresses.Store(blockedAddress.String(), 1)
}

unblockedAddresses := []string{}
p.blockedAddresses.Range(func(key, value any) bool {
addrHex := key.(string)
addr := common.HexToAddress(addrHex)
blocked, err := p.storage.IsAddressBlocked(context.Background(), addr)
if err != nil {
log.Error("failed to check if %v is blocked", addrHex)
return true
}

if !blocked {
unblockedAddresses = append(unblockedAddresses, addrHex)
}
return true
})

for _, unblockedAddress := range unblockedAddresses {
p.blockedAddresses.Delete(unblockedAddress)
}
}

Expand Down Expand Up @@ -197,6 +242,12 @@ func (p *Pool) validateTx(ctx context.Context, tx types.Transaction) error {
return ErrInvalidSender
}

// check if sender is blocked
_, blocked := p.blockedAddresses.Load(from.String())
if blocked {
return ErrBlockedSender
}

lastL2BlockNumber, err := p.state.GetLastL2BlockNumber(ctx, nil)
if err != nil {
return err
Expand Down
Loading