Skip to content

Commit

Permalink
add innertx cache db (#147)
Browse files Browse the repository at this point in the history
* add innertx cache db

* add pool

* add duration of insert

* add jsonb

* add tx

* add mock pool xlayer

* add log

* add log

* add switch

* add log

* add metrics

* add comment

* insert db

* add metrics add error count

* add metircs
  • Loading branch information
giskook authored Mar 25, 2024
1 parent 86965a6 commit 2e28dc1
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions docs/config-file/node-config-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,7 @@ FreeClaimGasLimit=150000
| - [DisableAPIs](#RPC_DisableAPIs ) | No | array of string | No | - | DisableAPIs disable some API |
| - [RateLimit](#RPC_RateLimit ) | No | object | No | - | RateLimit enable rate limit |
| - [DynamicGP](#RPC_DynamicGP ) | No | object | No | - | DynamicGP defines the config of dynamic gas price |
| - [EnableInnerTxCacheDB](#RPC_EnableInnerTxCacheDB ) | No | boolean | No | - | EnableInnerTxCacheDB enables the inner tx cache db |

### <a name="RPC_Host"></a>8.1. `RPC.Host`

Expand Down Expand Up @@ -2136,6 +2137,20 @@ MinPrice=0
UpdatePeriod="0s"
```

### <a name="RPC_EnableInnerTxCacheDB"></a>8.25. `RPC.EnableInnerTxCacheDB`

**Type:** : `boolean`

**Default:** `false`

**Description:** EnableInnerTxCacheDB enables the inner tx cache db

**Example setting the default value** (false):
```
[RPC]
EnableInnerTxCacheDB=false
```

## <a name="Synchronizer"></a>9. `[Synchronizer]`

**Type:** : `object`
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 @@ -804,6 +804,11 @@
"additionalProperties": false,
"type": "object",
"description": "DynamicGP defines the config of dynamic gas price"
},
"EnableInnerTxCacheDB": {
"type": "boolean",
"description": "EnableInnerTxCacheDB enables the inner tx cache db",
"default": false
}
},
"additionalProperties": false,
Expand Down
3 changes: 3 additions & 0 deletions jsonrpc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type Config struct {

// DynamicGP defines the config of dynamic gas price
DynamicGP DynamicGPConfig `mapstructure:"DynamicGP"`

// EnableInnerTxCacheDB enables the inner tx cache db
EnableInnerTxCacheDB bool `mapstructure:"EnableInnerTxCacheDB"`
}

// ZKCountersLimits defines the ZK Counter limits
Expand Down
31 changes: 31 additions & 0 deletions jsonrpc/endpoints_eth_xlayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"strconv"
"strings"
"sync"
"time"

"github.com/0xPolygonHermez/zkevm-node/jsonrpc/metrics"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/types"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/0xPolygonHermez/zkevm-node/state"
Expand All @@ -32,6 +34,21 @@ func (e *EthEndpoints) GetInternalTransactions(hash types.ArgHash) (interface{},
state: e.state,
}
})
if e.cfg.EnableInnerTxCacheDB {
dbCtx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond) //nolint:gomnd
defer cancel()
if ret, err := e.pool.GetInnerTx(dbCtx, hash.Hash()); err == nil {
var innerTxs []*InnerTx
err = json.Unmarshal([]byte(ret), &innerTxs)
if err == nil {
metrics.RequestInnerTxCachedCount()
return innerTxs, nil
} else {
log.Errorf("failed to unmarshal inner txs: %v", err)
}
}
}

return debugEndPoints.txMan.NewDbTxScope(debugEndPoints.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) {
ret, err := debugEndPoints.buildInnerTransaction(ctx, hash.Hash(), dbTx)
if err != nil {
Expand All @@ -52,6 +69,20 @@ func (e *EthEndpoints) GetInternalTransactions(hash types.ArgHash) (interface{},
return nil, types.NewRPCError(types.ParserErrorCode, stderr.Error())
}
result := internalTxTraceToInnerTxs(of)
metrics.RequestInnerTxExecutedCount()

if e.cfg.EnableInnerTxCacheDB {
// Add inner txs to the pool
if innerTxBlob, err := json.Marshal(result); err == nil {
go func() {
dbContext, c := context.WithTimeout(context.Background(), 3*time.Second) //nolint:gomnd
defer c()
if err := e.pool.AddInnerTx(dbContext, hash.Hash(), innerTxBlob); err != nil {
metrics.RequestInnerTxAddErrorCount()
}
}()
}
}

return result, nil
})
Expand Down
43 changes: 41 additions & 2 deletions jsonrpc/metrics/metrics_xlayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
)

var (
requestMethodName = requestPrefix + "method"
requestMethodDurationName = requestPrefix + "method_duration"
requestMethodName = requestPrefix + "method"
requestMethodDurationName = requestPrefix + "method_duration"
requestInnerTxCachedName = requestPrefix + "inner_tx_cached"
requestInnerTxExecutedName = requestPrefix + "inner_tx_executed"
requestInnerTxAddErrorCount = requestPrefix + "inner_tx_error_count"

wsRequestPrefix = prefix + "ws_request_"
requestWsMethodName = wsRequestPrefix + "method"
Expand Down Expand Up @@ -52,6 +55,27 @@ var (
},
Labels: []string{requestMethodLabelName},
},
{
CounterOpts: prometheus.CounterOpts{
Name: requestInnerTxCachedName,
Help: "[JSONRPC] number of cached innertx requests",
},
Labels: []string{},
},
{
CounterOpts: prometheus.CounterOpts{
Name: requestInnerTxExecutedName,
Help: "[JSONRPC] number of executed innertx requests",
},
Labels: []string{},
},
{
CounterOpts: prometheus.CounterOpts{
Name: requestInnerTxAddErrorCount,
Help: "[JSONRPC] number of add innertx count",
},
Labels: []string{},
},
}
)

Expand All @@ -78,3 +102,18 @@ func RequestMethodDuration(method string, start time.Time) {
func RequestMethodCount(method string) {
metrics.CounterVecInc(requestMethodName, method)
}

// RequestInnerTxExecutedCount increments the inner tx executed counter vector by one.
func RequestInnerTxExecutedCount() {
metrics.CounterInc(requestInnerTxExecutedName)
}

// RequestInnerTxCachedCount increments the inner tx cached counter vector by one.
func RequestInnerTxCachedCount() {
metrics.CounterInc(requestInnerTxCachedName)
}

// RequestInnerTxAddErrorCount increments the inner tx add error counter vector by one.
func RequestInnerTxAddErrorCount() {
metrics.CounterInc(requestInnerTxAddErrorCount)
}
55 changes: 55 additions & 0 deletions jsonrpc/mocks/mock_pool_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package mocks

import (
"context"

"github.com/ethereum/go-ethereum/common"
)

// AddInnerTx provides a mock function with given fields: ctx, txHash, innerTx
func (_m *PoolMock) AddInnerTx(ctx context.Context, txHash common.Hash, innerTx []byte) error {
ret := _m.Called(ctx, txHash, innerTx)

if len(ret) == 0 {
panic("no return value specified for AddTx")
}

var r0 error
if rf, ok := ret.Get(0).(func(context.Context, common.Hash, []byte) error); ok {
r0 = rf(ctx, txHash, innerTx)
} else {
r0 = ret.Error(0)
}

return r0
}

// GetInnerTx provides a mock function with given fields: ctx, txHash
func (_m *PoolMock) GetInnerTx(ctx context.Context, txHash common.Hash) (string, error) {
ret := _m.Called(ctx, txHash)

if len(ret) == 0 {
panic("no return value specified for GetPendingTxs")
}

var r0 string
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (string, error)); ok {
return rf(ctx, txHash)
}
if rf, ok := ret.Get(0).(func(context.Context, common.Hash) string); ok {
r0 = rf(ctx, txHash)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(string)
}
}

if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok {
r1 = rf(ctx, txHash)
} else {
r1 = ret.Error(1)
}

return r0, r1
}
2 changes: 2 additions & 0 deletions jsonrpc/types/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type PoolInterface interface {
CalculateEffectiveGasPrice(rawTx []byte, txGasPrice *big.Int, txGasUsed uint64, l1GasPrice uint64, l2GasPrice uint64) (*big.Int, error)
CalculateEffectiveGasPricePercentage(gasPrice *big.Int, effectiveGasPrice *big.Int) (uint8, error)
EffectiveGasPriceEnabled() bool
AddInnerTx(ctx context.Context, txHash common.Hash, innerTx []byte) error
GetInnerTx(ctx context.Context, txHash common.Hash) (string, error)
}

// StateInterface gathers the methods required to interact with the state.
Expand Down
2 changes: 2 additions & 0 deletions pool/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ type storage interface {
GetAllAddressesWhitelisted(ctx context.Context) ([]common.Address, error)
MinL2GasPriceSince(ctx context.Context, timestamp time.Time) (uint64, error)
GetEarliestProcessedTx(ctx context.Context) (common.Hash, error)
AddInnerTx(ctx context.Context, txHash common.Hash, innerTx []byte) error
GetInnerTx(ctx context.Context, txHash common.Hash) (string, error)
}

type stateInterface interface {
Expand Down
31 changes: 31 additions & 0 deletions pool/pgpoolstorage/pgpoolstorage_xlayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,34 @@ func (p *PostgresPoolStorage) GetAllAddressesWhitelisted(ctx context.Context) ([

return addrs, nil
}

// CREATE TABLE pool.innertx (
// hash VARCHAR(128) PRIMARY KEY NOT NULL,
// innertx text,
// created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
// );

// AddInnerTx add inner tx
func (p *PostgresPoolStorage) AddInnerTx(ctx context.Context, txHash common.Hash, innerTx []byte) error {
sql := `INSERT INTO pool.innertx(hash, innertx) VALUES ($1, $2)`

_, err := p.db.Exec(ctx, sql, txHash.Hex(), innerTx)
if err != nil {
return err
}

return nil
}

// GetInnerTx get inner tx
func (p *PostgresPoolStorage) GetInnerTx(ctx context.Context, txHash common.Hash) (string, error) {
sql := `SELECT innertx FROM pool.innertx WHERE hash = $1`

var innerTx string
err := p.db.QueryRow(ctx, sql, txHash.Hex()).Scan(&innerTx)
if err != nil {
return "", err
}

return innerTx, nil
}

0 comments on commit 2e28dc1

Please sign in to comment.