Skip to content

Commit d405aa5

Browse files
chengzhineiylsGit
andauthored
support init freegas (#207)
* support init free gas * support prior pack tx * init initFreeAddress * txTracker gp use default gp * start bridge service on testing * Update Makefile * Update docker-compose.yml * update config * and bridge ui * start bridge ui * Update docker-compose.yml * Update docker-compose.yml * Update docker-compose.yml * Update Makefile * opt code * Update docker-compose.yml * Update docker-compose.yml * Update test.bridge.config.toml * add cfg of nonce * Update Makefile * Update test.node.config.toml * Update docker-compose.yml * create table pool.free_gas * rename FreeGasNonce to FreeGasCountPerAddr * Update test.node.config.toml * get addr from input * fix addr * del log * add cfg of free gaslimit * fix lint and json * fix UT * Update test.node.config.toml * Update test.node.config.toml * Update pool.go * and free gas config * fix * add dgp * add AddDynamicGp * fix lint * add GetDynamicGasPrice * fix rpc * test * fix ut * test * log error * fix ut * fix ut * fix ut * fix ut * fix ut * test * test * fix ut * use dgp * fix ut * update error msg * opt code * opt code * opt code * opt code * opt code * Update pool_xlayer.go * Update pool_xlayer.go * Update pool_xlayer.go * opt code * fix lint --------- Co-authored-by: ylsGit <[email protected]>
1 parent 8100533 commit d405aa5

26 files changed

+750
-37
lines changed

db/migrations/pool/1004.sql

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- +migrate Up
2+
CREATE TABLE IF NOT EXISTS pool.free_gas (
3+
addr varchar NOT NULL PRIMARY KEY
4+
);
5+
6+
-- +migrate Down
7+
DROP TABLE IF EXISTS pool.free_gas;

docs/config-file/node-config-doc.html

+2-2
Large diffs are not rendered by default.

docs/config-file/node-config-doc.md

+67-1
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,10 @@ SecretKey=""
709709
| - [FreeGasAddress](#Pool_FreeGasAddress ) | No | array of string | No | - | XLayer config<br />FreeGasAddress is the default free gas address |
710710
| - [FreeClaimGasLimit](#Pool_FreeClaimGasLimit ) | No | integer | No | - | FreeClaimGasLimit is the max gas allowed use to do a free claim |
711711
| - [BridgeClaimMethodSigs](#Pool_BridgeClaimMethodSigs ) | No | array of string | No | - | BridgeClaimMethodSignature for tracking BridgeClaimMethodSignature method |
712+
| - [EnableFreeGasByNonce](#Pool_EnableFreeGasByNonce ) | No | boolean | No | - | EnableFreeGasByNonce enable free gas |
713+
| - [FreeGasExAddress](#Pool_FreeGasExAddress ) | No | array of string | No | - | FreeGasExAddress is the ex address which can be free gas for the transfer receiver |
714+
| - [FreeGasCountPerAddr](#Pool_FreeGasCountPerAddr ) | No | integer | No | - | FreeGasCountPerAddr is the count limit of free gas tx per address |
715+
| - [FreeGasLimit](#Pool_FreeGasLimit ) | No | integer | No | - | FreeGasLimit is the max gas allowed use to do a free gas tx |
712716

713717
### <a name="Pool_IntervalToRefreshBlockedAddresses"></a>7.1. `Pool.IntervalToRefreshBlockedAddresses`
714718

@@ -1248,6 +1252,53 @@ FreeClaimGasLimit=150000
12481252
**Type:** : `array of string`
12491253
**Description:** BridgeClaimMethodSignature for tracking BridgeClaimMethodSignature method
12501254

1255+
### <a name="Pool_EnableFreeGasByNonce"></a>7.18. `Pool.EnableFreeGasByNonce`
1256+
1257+
**Type:** : `boolean`
1258+
1259+
**Default:** `false`
1260+
1261+
**Description:** EnableFreeGasByNonce enable free gas
1262+
1263+
**Example setting the default value** (false):
1264+
```
1265+
[Pool]
1266+
EnableFreeGasByNonce=false
1267+
```
1268+
1269+
### <a name="Pool_FreeGasExAddress"></a>7.19. `Pool.FreeGasExAddress`
1270+
1271+
**Type:** : `array of string`
1272+
**Description:** FreeGasExAddress is the ex address which can be free gas for the transfer receiver
1273+
1274+
### <a name="Pool_FreeGasCountPerAddr"></a>7.20. `Pool.FreeGasCountPerAddr`
1275+
1276+
**Type:** : `integer`
1277+
1278+
**Default:** `0`
1279+
1280+
**Description:** FreeGasCountPerAddr is the count limit of free gas tx per address
1281+
1282+
**Example setting the default value** (0):
1283+
```
1284+
[Pool]
1285+
FreeGasCountPerAddr=0
1286+
```
1287+
1288+
### <a name="Pool_FreeGasLimit"></a>7.21. `Pool.FreeGasLimit`
1289+
1290+
**Type:** : `integer`
1291+
1292+
**Default:** `0`
1293+
1294+
**Description:** FreeGasLimit is the max gas allowed use to do a free gas tx
1295+
1296+
**Example setting the default value** (0):
1297+
```
1298+
[Pool]
1299+
FreeGasLimit=0
1300+
```
1301+
12511302
## <a name="RPC"></a>8. `[RPC]`
12521303

12531304
**Type:** : `object`
@@ -2885,6 +2936,7 @@ CheckLastL2BlockHashOnCloseBatch=true
28852936
| - [StreamServer](#Sequencer_StreamServer ) | No | object | No | - | StreamServerCfg is the config for the stream server |
28862937
| - [PackBatchSpacialList](#Sequencer_PackBatchSpacialList ) | No | array of string | No | - | XLayer config<br />PackBatchSpacialList is the list of addresses that will have a special gas price |
28872938
| - [GasPriceMultiple](#Sequencer_GasPriceMultiple ) | No | number | No | - | GasPriceMultiple is the multiple of the gas price |
2939+
| - [InitGasPriceMultiple](#Sequencer_InitGasPriceMultiple ) | No | number | No | - | InitGasPriceMultiple is the multiple of the gas price for init free gas tx |
28882940
| - [QueryPendingTxsLimit](#Sequencer_QueryPendingTxsLimit ) | No | integer | No | - | QueryPendingTxsLimit is used to limit amount txs from the db |
28892941

28902942
### <a name="Sequencer_DeletePoolTxsL1BlockConfirmations"></a>10.1. `Sequencer.DeletePoolTxsL1BlockConfirmations`
@@ -3572,7 +3624,21 @@ PackBatchSpacialList is the list of addresses that will have a special gas price
35723624
GasPriceMultiple=0
35733625
```
35743626

3575-
### <a name="Sequencer_QueryPendingTxsLimit"></a>10.11. `Sequencer.QueryPendingTxsLimit`
3627+
### <a name="Sequencer_InitGasPriceMultiple"></a>10.11. `Sequencer.InitGasPriceMultiple`
3628+
3629+
**Type:** : `number`
3630+
3631+
**Default:** `0`
3632+
3633+
**Description:** InitGasPriceMultiple is the multiple of the gas price for init free gas tx
3634+
3635+
**Example setting the default value** (0):
3636+
```
3637+
[Sequencer]
3638+
InitGasPriceMultiple=0
3639+
```
3640+
3641+
### <a name="Sequencer_QueryPendingTxsLimit"></a>10.12. `Sequencer.QueryPendingTxsLimit`
35763642

35773643
**Type:** : `integer`
35783644

docs/config-file/node-config-schema.json

+27
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,28 @@
471471
},
472472
"type": "array",
473473
"description": "BridgeClaimMethodSignature for tracking BridgeClaimMethodSignature method"
474+
},
475+
"EnableFreeGasByNonce": {
476+
"type": "boolean",
477+
"description": "EnableFreeGasByNonce enable free gas",
478+
"default": false
479+
},
480+
"FreeGasExAddress": {
481+
"items": {
482+
"type": "string"
483+
},
484+
"type": "array",
485+
"description": "FreeGasExAddress is the ex address which can be free gas for the transfer receiver"
486+
},
487+
"FreeGasCountPerAddr": {
488+
"type": "integer",
489+
"description": "FreeGasCountPerAddr is the count limit of free gas tx per address",
490+
"default": 0
491+
},
492+
"FreeGasLimit": {
493+
"type": "integer",
494+
"description": "FreeGasLimit is the max gas allowed use to do a free gas tx",
495+
"default": 0
474496
}
475497
},
476498
"additionalProperties": false,
@@ -1391,6 +1413,11 @@
13911413
"description": "GasPriceMultiple is the multiple of the gas price",
13921414
"default": 0
13931415
},
1416+
"InitGasPriceMultiple": {
1417+
"type": "number",
1418+
"description": "InitGasPriceMultiple is the multiple of the gas price for init free gas tx",
1419+
"default": 0
1420+
},
13941421
"QueryPendingTxsLimit": {
13951422
"type": "integer",
13961423
"description": "QueryPendingTxsLimit is used to limit amount txs from the db",

jsonrpc/endpoints_eth.go

+3
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,9 @@ func (e *EthEndpoints) tryToAddTxToPool(input, ip string) (interface{}, types.Er
10431043
return RPCErrorResponse(types.InvalidParamsErrorCode, "invalid tx input", err, false)
10441044
}
10451045
log.Infof("adding TX to the pool: %v", tx.Hash().Hex())
1046+
1047+
dgp := getDynamicGp(e.cfg.DynamicGP.Enabled, e.dgpMan.lastPrice)
1048+
e.pool.AddDynamicGp(dgp)
10461049
if err := e.pool.AddTx(context.Background(), *tx, ip); err != nil {
10471050
// it's not needed to log the error here, because we check and log if needed
10481051
// for each specific case during the "pool.AddTx" internal steps

jsonrpc/endpoints_eth_xlayer.go

+7
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,10 @@ func (e *EthEndpoints) GetPendingStat() (interface{}, types.Error) {
420420
ReadyTxCount: readyTxCount,
421421
}, nil
422422
}
423+
424+
func getDynamicGp(enableDgp bool, dgp *big.Int) *big.Int {
425+
if !enableDgp || dgp == nil {
426+
return big.NewInt(0)
427+
}
428+
return dgp
429+
}

jsonrpc/mocks/mock_pool.go

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jsonrpc/types/interfaces.go

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
// PoolInterface contains the methods required to interact with the tx pool.
1717
type PoolInterface interface {
1818
AddTx(ctx context.Context, tx types.Transaction, ip string) error
19+
AddDynamicGp(dgp *big.Int)
1920
GetGasPrices(ctx context.Context) (pool.GasPrices, error)
2021
GetNonce(ctx context.Context, address common.Address) (uint64, error)
2122
GetPendingTxHashesSince(ctx context.Context, since time.Time) ([]common.Hash, error)

pool/apollo_xlayer.go

+57
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ type apolloConfig struct {
1616
BridgeClaimMethods []string
1717
EnablePendingStat bool
1818

19+
EnableFreeGasByNonce bool
20+
FreeGasExAddress []string
21+
FreeGasCountPerAddr uint64
22+
FreeGasLimit uint64
23+
1924
sync.RWMutex
2025
}
2126

@@ -44,6 +49,14 @@ func (c *apolloConfig) setFreeGasAddresses(freeGasAddrs []string) {
4449
copy(c.FreeGasAddresses, freeGasAddrs)
4550
}
4651

52+
func (c *apolloConfig) setFreeGasExAddresses(freeGasExAddrs []string) {
53+
if c == nil || !c.EnableApollo {
54+
return
55+
}
56+
c.FreeGasExAddress = make([]string, len(freeGasExAddrs))
57+
copy(c.FreeGasExAddress, freeGasExAddrs)
58+
}
59+
4760
func (c *apolloConfig) setBridgeClaimMethods(bridgeClaimMethods []string) {
4861
if c == nil || !c.EnableApollo {
4962
return
@@ -66,6 +79,12 @@ func UpdateConfig(apolloConfig Config) {
6679
getApolloConfig().setFreeGasAddresses(apolloConfig.FreeGasAddress)
6780
getApolloConfig().EnableWhitelist = apolloConfig.EnableWhitelist
6881
getApolloConfig().setBridgeClaimMethods(apolloConfig.BridgeClaimMethodSigs)
82+
83+
getApolloConfig().EnableFreeGasByNonce = apolloConfig.EnableFreeGasByNonce
84+
getApolloConfig().setFreeGasExAddresses(apolloConfig.FreeGasExAddress)
85+
getApolloConfig().FreeGasCountPerAddr = apolloConfig.FreeGasCountPerAddr
86+
getApolloConfig().FreeGasLimit = apolloConfig.FreeGasLimit
87+
6988
getApolloConfig().Unlock()
7089
}
7190

@@ -95,6 +114,44 @@ func isFreeGasAddress(localFreeGasAddrs []string, address common.Address) bool {
95114
return contains(localFreeGasAddrs, address)
96115
}
97116

117+
func getEnableFreeGasByNonce(enableFreeGasByNonce bool) bool {
118+
if getApolloConfig().enable() {
119+
getApolloConfig().RLock()
120+
defer getApolloConfig().RUnlock()
121+
return getApolloConfig().EnableFreeGasByNonce
122+
}
123+
124+
return enableFreeGasByNonce
125+
}
126+
127+
func isFreeGasExAddress(localFreeGasExAddrs []string, address common.Address) bool {
128+
if getApolloConfig().enable() {
129+
getApolloConfig().RLock()
130+
defer getApolloConfig().RUnlock()
131+
return contains(getApolloConfig().FreeGasExAddress, address)
132+
}
133+
134+
return contains(localFreeGasExAddrs, address)
135+
}
136+
137+
func getFreeGasCountPerAddr(localFreeGasCountPerAddr uint64) uint64 {
138+
if getApolloConfig().enable() {
139+
getApolloConfig().RLock()
140+
defer getApolloConfig().RUnlock()
141+
return getApolloConfig().FreeGasCountPerAddr
142+
}
143+
return localFreeGasCountPerAddr
144+
}
145+
146+
func getFreeGasLimit(localFreeGasLimit uint64) uint64 {
147+
if getApolloConfig().enable() {
148+
getApolloConfig().RLock()
149+
defer getApolloConfig().RUnlock()
150+
return getApolloConfig().FreeGasLimit
151+
}
152+
return localFreeGasLimit
153+
}
154+
98155
func getGlobalQueue(globalQueue uint64) uint64 {
99156
if getApolloConfig().enable() {
100157
getApolloConfig().RLock()

pool/config.go

+9
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ type Config struct {
5757
FreeClaimGasLimit uint64 `mapstructure:"FreeClaimGasLimit"`
5858
// BridgeClaimMethodSignature for tracking BridgeClaimMethodSignature method
5959
BridgeClaimMethodSigs []string `mapstructure:"BridgeClaimMethodSigs"`
60+
61+
// EnableFreeGasByNonce enable free gas
62+
EnableFreeGasByNonce bool `mapstructure:"EnableFreeGasByNonce"`
63+
// FreeGasExAddress is the ex address which can be free gas for the transfer receiver
64+
FreeGasExAddress []string `mapstructure:"FreeGasExAddress"`
65+
// FreeGasCountPerAddr is the count limit of free gas tx per address
66+
FreeGasCountPerAddr uint64 `mapstructure:"FreeGasCountPerAddr"`
67+
// FreeGasLimit is the max gas allowed use to do a free gas tx
68+
FreeGasLimit uint64 `mapstructure:"FreeGasLimit"`
6069
}
6170

6271
// EffectiveGasPriceCfg contains the configuration properties for the effective gas price

pool/interfaces.go

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ type storage interface {
4444
GetInnerTx(ctx context.Context, txHash common.Hash) (string, error)
4545
UpdateReadyTxCount(ctx context.Context, count uint64) error
4646
GetReadyTxCount(ctx context.Context) (uint64, error)
47+
AddFreeGasAddr(ctx context.Context, addr common.Address) error
48+
IsFreeGasAddr(ctx context.Context, addr common.Address) (bool, error)
4749
}
4850

4951
type stateInterface interface {

pool/pgpoolstorage/pgpoolstorage_xlayer.go

+26
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package pgpoolstorage
22

33
import (
44
"context"
5+
"database/sql"
56
"errors"
67
"time"
78

@@ -98,3 +99,28 @@ func (p *PostgresPoolStorage) GetReadyTxCount(ctx context.Context) (uint64, erro
9899

99100
return count, nil
100101
}
102+
103+
// IsFreeGasAddr determines if the address is free gas or
104+
// not.
105+
func (p *PostgresPoolStorage) IsFreeGasAddr(ctx context.Context, addr common.Address) (bool, error) {
106+
var exists bool
107+
req := "SELECT exists (SELECT 1 FROM pool.free_gas WHERE addr = $1)"
108+
err := p.db.QueryRow(ctx, req, addr.String()).Scan(&exists)
109+
if err != nil && err != sql.ErrNoRows {
110+
return false, err
111+
}
112+
113+
return exists, nil
114+
}
115+
116+
// AddFreeGasAddr add free gas address
117+
func (p *PostgresPoolStorage) AddFreeGasAddr(ctx context.Context, addr common.Address) error {
118+
sql := `INSERT INTO pool.free_gas(addr) VALUES ($1)`
119+
120+
_, err := p.db.Exec(ctx, sql, addr.String())
121+
if err != nil {
122+
return err
123+
}
124+
125+
return nil
126+
}

pool/pool.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ type Pool struct {
5151
gasPrices GasPrices
5252
gasPricesMux *sync.RWMutex
5353
effectiveGasPrice *EffectiveGasPrice
54+
dynamicGasPrice *big.Int
55+
dgpMux *sync.RWMutex
5456
}
5557

5658
type preExecutionResponse struct {
@@ -87,6 +89,7 @@ func NewPool(cfg Config, batchConstraintsCfg state.BatchConstraintsCfg, s storag
8789
gasPrices: GasPrices{0, 0},
8890
gasPricesMux: new(sync.RWMutex),
8991
effectiveGasPrice: NewEffectiveGasPrice(cfg.EffectiveGasPrice),
92+
dgpMux: new(sync.RWMutex),
9093
}
9194
p.refreshGasPrices()
9295
go func(cfg *Config, p *Pool) {
@@ -535,8 +538,12 @@ func (p *Pool) validateTx(ctx context.Context, poolTx Transaction) error {
535538
}
536539
}
537540

538-
// Reject transactions with a gas price lower than the minimum gas price
539-
if !isFreeGasAddress(p.cfg.FreeGasAddress, from) || !poolTx.IsClaims { // XLayer handle
541+
freeGp, err := p.checkFreeGp(ctx, poolTx, from)
542+
if err != nil {
543+
return err
544+
}
545+
546+
if !freeGp { // XLayer handle
540547
p.minSuggestedGasPriceMux.RLock()
541548
gasPriceCmp := poolTx.GasPrice().Cmp(p.minSuggestedGasPrice)
542549
if gasPriceCmp == -1 {
@@ -604,6 +611,12 @@ func (p *Pool) validateTx(ctx context.Context, poolTx Transaction) error {
604611
return err
605612
}
606613

614+
if getEnableFreeGasByNonce(p.cfg.EnableFreeGasByNonce) {
615+
if err := p.checkAndUpdateFreeGasAddr(ctx, poolTx, from, lastL2Block.Root()); err != nil {
616+
return err
617+
}
618+
}
619+
607620
return nil
608621
}
609622

0 commit comments

Comments
 (0)