Skip to content

Commit

Permalink
Merge PR: refactor tx signature cache (#1595)
Browse files Browse the repository at this point in the history
* refactor tx signature cache

* fix ut

* optimize code

Co-authored-by: Zhong Qiu <[email protected]>
  • Loading branch information
ilovers and zhongqiuwood authored Feb 25, 2022
1 parent 4abdcfb commit 4ceaea0
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 88 deletions.
6 changes: 5 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package app

import (
"fmt"
"github.com/okex/exchain/app/utils/sanity"
"io"
"math/big"
"os"
"sync"

"github.com/okex/exchain/app/utils/sanity"

"github.com/okex/exchain/app/ante"
okexchaincodec "github.com/okex/exchain/app/codec"
appconfig "github.com/okex/exchain/app/config"
Expand Down Expand Up @@ -607,5 +608,8 @@ func PreRun(ctx *server.Context) error {
if viper.GetBool(FlagEnableRepairState) {
repairStateOnStart(ctx)
}

// init tx signature cache
tmtypes.InitSignatureCache()
return nil
}
3 changes: 2 additions & 1 deletion app/elapse_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (e *ElapsedTimeInfos) Dump(logger log.Logger) {
}
}

info := fmt.Sprintf("%s<%s>, %s<%s>, %s<%s>, %s<%s>, %s<%s>, %s<%s>, %s[%s], %s[%s], %s<%s>, %s<%s>",
info := fmt.Sprintf("%s<%s>, %s<%s>, %s<%s>, %s<%s>, %s<%s>, %s<%s>, %s[%s], %s[%s], %s<%s>, %s<%s>, %s<%s>",
trace.Height, e.infoMap[trace.Height],
trace.Tx, e.infoMap[trace.Tx],
trace.BlockSize, e.infoMap[trace.BlockSize],
Expand All @@ -111,6 +111,7 @@ func (e *ElapsedTimeInfos) Dump(logger log.Logger) {
trace.Prerun, e.infoMap[trace.Prerun],
trace.MempoolCheckTxCnt, e.infoMap[trace.MempoolCheckTxCnt],
trace.MempoolTxsCnt, e.infoMap[trace.MempoolTxsCnt],
trace.SigCacheRatio, e.infoMap[trace.SigCacheRatio],
)

if len(detailInfo) > 0 {
Expand Down
2 changes: 2 additions & 0 deletions cmd/client/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/okex/exchain/app/utils/sanity"
"github.com/okex/exchain/libs/tendermint/consensus"
"github.com/okex/exchain/libs/tendermint/libs/automation"
tmtypes "github.com/okex/exchain/libs/tendermint/types"
tmdb "github.com/okex/exchain/libs/tm-db"
"github.com/okex/exchain/x/common/analyzer"
evmtypes "github.com/okex/exchain/x/evm/types"
Expand Down Expand Up @@ -109,4 +110,5 @@ func RegisterAppFlag(cmd *cobra.Command) {

cmd.Flags().Bool(analyzer.FlagEnableAnalyzer, true, "Enable auto open log analyzer")
cmd.Flags().Bool(sanity.FlagDisableSanity, false, "Disable sanity check")
cmd.Flags().Int(tmtypes.FlagSigCacheSize, 200000, "Maximum number of signatures in the cache")
}
4 changes: 4 additions & 0 deletions libs/cosmos-sdk/baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ func (app *BaseApp) Commit(req abci.RequestCommit) abci.ResponseCommit {

trace.GetElapsedInfo().AddInfo(trace.WtxRatio, fmt.Sprintf("%.2f", wtx/(wtx+rtx)))

readCache := float64(tmtypes.SignatureCache().ReadCount())
hitCache := float64(tmtypes.SignatureCache().HitCount())
trace.GetElapsedInfo().AddInfo(trace.SigCacheRatio, fmt.Sprintf("%.2f", hitCache/readCache))

trace.GetElapsedInfo().AddInfo(trace.AnteChainDetail, app.anteTracer.FormatRepeatingPins(sdk.AnteTerminatorTag))

app.cms.ResetCount()
Expand Down
3 changes: 3 additions & 0 deletions libs/tendermint/mempool/clist_mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,9 @@ func (mem *CListMempool) Update(
if mem.pendingPool != nil {
mem.pendingPool.removeTxByHash(txID(tx, height))
}

// remove tx signature cache
types.SignatureCache().Remove(types.Bytes2Hash(tx, height))
}
mem.metrics.GasUsed.Set(float64(gasUsed))
trace.GetElapsedInfo().AddInfo(trace.GasUsed, fmt.Sprintf("%d", gasUsed))
Expand Down
1 change: 1 addition & 0 deletions libs/tendermint/trace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
Iavl = "Iavl"
FlatKV = "FlatKV"
WtxRatio = "WtxRatio"
SigCacheRatio = "SigCacheRatio"
DeliverTxs = "DeliverTxs"
EvmHandlerDetail = "EvmHandlerDetail"
RunAnteDetail = "RunAnteDetail"
Expand Down
122 changes: 122 additions & 0 deletions libs/tendermint/types/tx_signature_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package types

import (
"sync/atomic"

"github.com/spf13/viper"

ethcmn "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"

lru "github.com/hashicorp/golang-lru"
)

var (
signatureCache *Cache
)

const FlagSigCacheSize = "signature-cache-size"

func init() {
// used for ut
defaultCache := &Cache{
data: nil,
readCount: 0,
hitCount: 0,
}
signatureCache = defaultCache
}

func InitSignatureCache() {
lruCache, err := lru.New(viper.GetInt(FlagSigCacheSize))
if err != nil {
panic(err)
}
signatureCache = &Cache{
data: lruCache,
}
}

func SignatureCache() *Cache {
return signatureCache
}

type Cache struct {
data *lru.Cache
readCount int64
hitCount int64
}

func (c *Cache) Get(key string) (*TxSigCache, bool) {
// validate
if !c.validate(key) {
return nil, false
}
atomic.AddInt64(&c.readCount, 1)
// get cache
value, ok := c.data.Get(key)
if ok {
sigCache, ok := value.(*TxSigCache)
if ok {
atomic.AddInt64(&c.hitCount, 1)
return sigCache, true
}
}
return nil, false
}

func (c *Cache) Add(key string, value *TxSigCache) {
// validate
if !c.validate(key) {
return
}
// add cache
c.data.Add(key, value)
}

func (c *Cache) Remove(key string) {
// validate
if !c.validate(key) {
return
}
c.data.Remove(key)
}

func (c *Cache) ReadCount() int64 {
return atomic.LoadInt64(&c.readCount)
}

func (c *Cache) HitCount() int64 {
return atomic.LoadInt64(&c.hitCount)
}

func (c *Cache) validate(key string) bool {
// validate key
if key == "" {
return false
}
// validate lru cache
if c.data == nil {
return false
}
return true
}

// TxSignatureCache is used to cache the derived sender and contains the signer used
// to derive it.
type TxSigCache struct {
Signer ethtypes.Signer
From ethcmn.Address
}

func (s TxSigCache) GetFrom() ethcmn.Address {
return s.From
}

func (s TxSigCache) GetSigner() ethtypes.Signer {
return s.Signer
}

func (s TxSigCache) EqualSiger(siger ethtypes.Signer) bool {
return s.Signer.Equal(siger)
}
39 changes: 10 additions & 29 deletions x/evm/types/msg_evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (tx MsgEthereumTx) GetType() sdk.TransactionType {

func (tx *MsgEthereumTx) SetFrom(addr string) {
// only cache from but not signer
tx.from.Store(&ethSigCache{from: ethcmn.HexToAddress(addr)})
tx.from.Store(&tmtypes.TxSigCache{From: ethcmn.HexToAddress(addr)})
}

func (msg MsgEthereumTx) GetFee() sdk.Coins {
Expand All @@ -70,25 +70,6 @@ func (msg MsgEthereumTx) FeePayer(ctx sdk.Context) sdk.AccAddress {
return msg.From()
}

// ethSigCache is used to cache the derived sender and contains the signer used
// to derive it.
type ethSigCache struct {
signer ethtypes.Signer
from ethcmn.Address
}

func (s ethSigCache) GetFrom() ethcmn.Address {
return s.from
}

func (s ethSigCache) GetSigner() ethtypes.Signer {
return s.signer
}

func (s ethSigCache) EqualSiger(siger ethtypes.Signer) bool {
return s.signer.Equal(siger)
}

// NewMsgEthereumTx returns a reference to a new Ethereum transaction message.
func NewMsgEthereumTx(
nonce uint64, to *ethcmn.Address, amount *big.Int,
Expand Down Expand Up @@ -282,7 +263,7 @@ func (msg *MsgEthereumTx) VerifySig(chainID *big.Int, height int64, txBytes []by
// get sender from cache
if txBytes != nil {
cacheKey = tmtypes.Bytes2Hash(txBytes, height)
if sigCache, ok := verifySigCache.Get(cacheKey); ok {
if sigCache, ok := tmtypes.SignatureCache().Get(cacheKey); ok {
msg.from.Store(sigCache)
return sigCache, nil
}
Expand All @@ -299,11 +280,11 @@ func (msg *MsgEthereumTx) VerifySig(chainID *big.Int, height int64, txBytes []by
signer = ethtypes.HomesteadSigner{}
}
if sc := msg.from.Load(); sc != nil {
sigCache := sc.(*ethSigCache)
sigCache := sc.(*tmtypes.TxSigCache)
// If the signer used to derive from in a previous call is not the same as
// used current, invalidate the cache.
if sigCache.signer.Equal(signer) {
verifySigCache.Add(cacheKey, sigCache)
if sigCache.Signer.Equal(signer) {
tmtypes.SignatureCache().Add(cacheKey, sigCache)
return sigCache, nil
}
}
Expand Down Expand Up @@ -331,9 +312,9 @@ func (msg *MsgEthereumTx) VerifySig(chainID *big.Int, height int64, txBytes []by
if err != nil {
return nil, err
}
sigCache := &ethSigCache{signer: signer, from: sender}
sigCache := &tmtypes.TxSigCache{Signer: signer, From: sender}
msg.from.Store(sigCache)
verifySigCache.Add(cacheKey, sigCache)
tmtypes.SignatureCache().Add(cacheKey, sigCache)
return sigCache, nil
}

Expand Down Expand Up @@ -383,13 +364,13 @@ func (msg *MsgEthereumTx) From() sdk.AccAddress {
return nil
}

sigCache := sc.(*ethSigCache)
sigCache := sc.(*tmtypes.TxSigCache)

if len(sigCache.from.Bytes()) == 0 {
if len(sigCache.From.Bytes()) == 0 {
return nil
}

return sdk.AccAddress(sigCache.from.Bytes())
return sdk.AccAddress(sigCache.From.Bytes())
}

// deriveChainID derives the chain id from the given v parameter
Expand Down
57 changes: 0 additions & 57 deletions x/evm/types/msg_sig_cache.go

This file was deleted.

0 comments on commit 4ceaea0

Please sign in to comment.