From b739cb001a2625b5ca8ddcd5ec064ee11a01b2e7 Mon Sep 17 00:00:00 2001 From: Woosang Son Date: Thu, 4 Mar 2021 11:14:46 +0900 Subject: [PATCH 1/6] feat: more prometheus metrics for monitoring performance (#146) (#175) --- mempool/clist_mempool.go | 8 +++++++- mempool/metrics.go | 17 +++++++++++++---- state/execution.go | 27 ++++++++++++++++++++++++--- state/metrics.go | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 9 deletions(-) diff --git a/mempool/clist_mempool.go b/mempool/clist_mempool.go index 3b3709588..8f5786437 100644 --- a/mempool/clist_mempool.go +++ b/mempool/clist_mempool.go @@ -7,6 +7,7 @@ import ( "fmt" "sync" "sync/atomic" + "time" abci "github.com/tendermint/tendermint/abci/types" cfg "github.com/tendermint/tendermint/config" @@ -305,7 +306,7 @@ func (mem *CListMempool) globalCb(req *abci.Request, res *abci.Response) { return } - mem.metrics.RecheckTimes.Add(1) + mem.metrics.RecheckCount.Add(1) mem.resCbRecheck(req, res) // update metrics @@ -610,6 +611,7 @@ func (mem *CListMempool) Update( // Either recheck non-committed txs to see if they became invalid // or just notify there're some txs left. + recheckStartTime := time.Now().UnixNano() if mem.Size() > 0 { if mem.config.Recheck { mem.logger.Debug("recheck txs", "numtxs", mem.Size(), "height", height) @@ -621,6 +623,10 @@ func (mem *CListMempool) Update( mem.notifyTxsAvailable() } } + recheckEndTime := time.Now().UnixNano() + + recheckTimeMs := float64(recheckEndTime-recheckStartTime) / 1000000 + mem.metrics.RecheckTime.Set(recheckTimeMs) // Update metrics mem.metrics.Size.Set(float64(mem.Size())) diff --git a/mempool/metrics.go b/mempool/metrics.go index 5e4eaf5ed..39459de69 100644 --- a/mempool/metrics.go +++ b/mempool/metrics.go @@ -23,7 +23,9 @@ type Metrics struct { // Number of failed transactions. FailedTxs metrics.Counter // Number of times transactions are rechecked in the mempool. - RecheckTimes metrics.Counter + RecheckCount metrics.Counter + // Time of recheck transactions in the mempool. + RecheckTime metrics.Gauge } // PrometheusMetrics returns Metrics build using Prometheus client library. @@ -54,12 +56,18 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "failed_txs", Help: "Number of failed transactions.", }, labels).With(labelsAndValues...), - RecheckTimes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + RecheckCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, - Name: "recheck_times", + Name: "recheck_count", Help: "Number of times transactions are rechecked in the mempool.", }, labels).With(labelsAndValues...), + RecheckTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "recheck_time", + Help: "Time of recheck transactions in the mempool in ms.", + }, labels).With(labelsAndValues...), } } @@ -69,6 +77,7 @@ func NopMetrics() *Metrics { Size: discard.NewGauge(), TxSizeBytes: discard.NewHistogram(), FailedTxs: discard.NewCounter(), - RecheckTimes: discard.NewCounter(), + RecheckCount: discard.NewCounter(), + RecheckTime: discard.NewGauge(), } } diff --git a/state/execution.go b/state/execution.go index 2cc3db6e7..3f49cd0b1 100644 --- a/state/execution.go +++ b/state/execution.go @@ -136,12 +136,16 @@ func (blockExec *BlockExecutor) ApplyBlock( return state, 0, ErrInvalidBlock(err) } - startTime := time.Now().UnixNano() + execStartTime := time.Now().UnixNano() abciResponses, err := execBlockOnProxyApp( blockExec.logger, blockExec.proxyApp, block, blockExec.store, state.InitialHeight, ) - endTime := time.Now().UnixNano() - blockExec.metrics.BlockProcessingTime.Observe(float64(endTime-startTime) / 1000000) + execEndTime := time.Now().UnixNano() + + execTimeMs := float64(execEndTime-execStartTime) / 1000000 + blockExec.metrics.BlockProcessingTime.Observe(execTimeMs) + blockExec.metrics.BlockExecutionTime.Set(execTimeMs) + if err != nil { return state, 0, ErrProxyAppConn(err) } @@ -177,7 +181,13 @@ func (blockExec *BlockExecutor) ApplyBlock( } // Lock mempool, commit app state, update mempoool. + commitStartTime := time.Now().UnixNano() appHash, retainHeight, err := blockExec.Commit(state, block, abciResponses.DeliverTxs) + commitEndTime := time.Now().UnixNano() + + commitTimeMs := float64(commitEndTime-commitStartTime) / 1000000 + blockExec.metrics.BlockCommitTime.Set(commitTimeMs) + if err != nil { return state, 0, fmt.Errorf("commit failed for application: %v", err) } @@ -225,7 +235,13 @@ func (blockExec *BlockExecutor) Commit( } // Commit block, get hash back + appCommitStartTime := time.Now().UnixNano() res, err := blockExec.proxyApp.CommitSync() + appCommitEndTime := time.Now().UnixNano() + + appCommitTimeMs := float64(appCommitEndTime-appCommitStartTime) / 1000000 + blockExec.metrics.BlockAppCommitTime.Set(appCommitTimeMs) + if err != nil { blockExec.logger.Error("client error during proxyAppConn.CommitSync", "err", err) return nil, 0, err @@ -240,6 +256,7 @@ func (blockExec *BlockExecutor) Commit( ) // Update mempool. + updateMempoolStartTime := time.Now().UnixNano() err = blockExec.mempool.Update( block.Height, block.Txs, @@ -247,6 +264,10 @@ func (blockExec *BlockExecutor) Commit( TxPreCheck(state), TxPostCheck(state), ) + updateMempoolEndTime := time.Now().UnixNano() + + updateMempoolTimeMs := float64(updateMempoolEndTime-updateMempoolStartTime) / 1000000 + blockExec.metrics.BlockUpdateMempoolTime.Set(updateMempoolTimeMs) return res.Data, res.RetainHeight, err } diff --git a/state/metrics.go b/state/metrics.go index bcd713f5f..730de6169 100644 --- a/state/metrics.go +++ b/state/metrics.go @@ -17,6 +17,14 @@ const ( type Metrics struct { // Time between BeginBlock and EndBlock. BlockProcessingTime metrics.Histogram + // Time gauge between BeginBlock and EndBlock. + BlockExecutionTime metrics.Gauge + // Time of commit + BlockCommitTime metrics.Gauge + // Time of app commit + BlockAppCommitTime metrics.Gauge + // Time of update mempool + BlockUpdateMempoolTime metrics.Gauge } // PrometheusMetrics returns Metrics build using Prometheus client library. @@ -35,12 +43,40 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Help: "Time between BeginBlock and EndBlock in ms.", Buckets: stdprometheus.LinearBuckets(1, 10, 10), }, labels).With(labelsAndValues...), + BlockExecutionTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_execution_time", + Help: "Time between BeginBlock and EndBlock in ms.", + }, labels).With(labelsAndValues...), + BlockCommitTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_commit_time", + Help: "Time of commit in ms.", + }, labels).With(labelsAndValues...), + BlockAppCommitTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_app_commit_time", + Help: "Time of app commit in ms.", + }, labels).With(labelsAndValues...), + BlockUpdateMempoolTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_update_mempool_time", + Help: "Time of update mempool in ms.", + }, labels).With(labelsAndValues...), } } // NopMetrics returns no-op Metrics. func NopMetrics() *Metrics { return &Metrics{ - BlockProcessingTime: discard.NewHistogram(), + BlockProcessingTime: discard.NewHistogram(), + BlockExecutionTime: discard.NewGauge(), + BlockCommitTime: discard.NewGauge(), + BlockAppCommitTime: discard.NewGauge(), + BlockUpdateMempoolTime: discard.NewGauge(), } } From 48bb17e1f9e69d1e14d033e2d1ecc136b0b2679d Mon Sep 17 00:00:00 2001 From: wetcod <37023735+wetcod@users.noreply.github.com> Date: Wed, 3 Feb 2021 11:23:12 +0900 Subject: [PATCH 2/6] chore: config timeout and connection pool (#150) (#171) --- config/config.go | 38 +++++++++++++++++++++++++- config/toml.go | 25 ++++++++++++++++- node/node.go | 3 ++ rpc/jsonrpc/client/http_json_client.go | 13 +++++++-- rpc/jsonrpc/server/http_server.go | 5 ++++ 5 files changed, 80 insertions(+), 4 deletions(-) diff --git a/config/config.go b/config/config.go index 15b3ab092..325deface 100644 --- a/config/config.go +++ b/config/config.go @@ -332,6 +332,30 @@ type RPCConfig struct { // 1024 - 40 - 10 - 50 = 924 = ~900 MaxOpenConnections int `mapstructure:"max_open_connections"` + // mirrors http.Server#ReadTimeout + // ReadTimeout is the maximum duration for reading the entire + // request, including the body. + // + // Because ReadTimeout does not let Handlers make per-request + // decisions on each request body's acceptable deadline or + // upload rate, most users will prefer to use + // ReadHeaderTimeout. It is valid to use them both. + ReadTimeout time.Duration `mapstructure:"read_timeout"` + + // mirrors http.Server#WriteTimeout + // WriteTimeout is the maximum duration before timing out + // writes of the response. It is reset whenever a new + // request's header is read. Like ReadTimeout, it does not + // let Handlers make decisions on a per-request basis. + WriteTimeout time.Duration `mapstructure:"write_timeout"` + + // mirrors http.Server#IdleTimeout + // IdleTimeout is the maximum amount of time to wait for the + // next request when keep-alives are enabled. If IdleTimeout + // is zero, the value of ReadTimeout is used. If both are + // zero, there is no timeout. + IdleTimeout time.Duration `mapstructure:"idle_timeout"` + // Maximum number of unique clientIDs that can /subscribe // If you're using /broadcast_tx_commit, set to the estimated maximum number // of broadcast_tx_commit calls per block. @@ -343,7 +367,7 @@ type RPCConfig struct { MaxSubscriptionsPerClient int `mapstructure:"max_subscriptions_per_client"` // How long to wait for a tx to be committed during /broadcast_tx_commit - // WARNING: Using a value larger than 10s will result in increasing the + // WARNING: Using a value larger than 'WriteTimeout' will result in increasing the // global HTTP write timeout, which applies to all connections and endpoints. // See https://github.com/tendermint/tendermint/issues/3435 TimeoutBroadcastTxCommit time.Duration `mapstructure:"timeout_broadcast_tx_commit"` @@ -388,6 +412,9 @@ func DefaultRPCConfig() *RPCConfig { Unsafe: false, MaxOpenConnections: 900, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + IdleTimeout: 60 * time.Second, MaxSubscriptionClients: 100, MaxSubscriptionsPerClient: 5, @@ -419,6 +446,15 @@ func (cfg *RPCConfig) ValidateBasic() error { if cfg.MaxOpenConnections < 0 { return errors.New("max_open_connections can't be negative") } + if cfg.ReadTimeout < 0 { + return errors.New("read_timeout can't be negative") + } + if cfg.WriteTimeout < 0 { + return errors.New("write_timeout can't be negative") + } + if cfg.IdleTimeout < 0 { + return errors.New("idle_timeout can't be negative") + } if cfg.MaxSubscriptionClients < 0 { return errors.New("max_subscription_clients can't be negative") } diff --git a/config/toml.go b/config/toml.go index 82ecdda20..50ac822e9 100644 --- a/config/toml.go +++ b/config/toml.go @@ -196,6 +196,29 @@ unsafe = {{ .RPC.Unsafe }} # 1024 - 40 - 10 - 50 = 924 = ~900 max_open_connections = {{ .RPC.MaxOpenConnections }} +# mirrors http.Server#ReadTimeout +# ReadTimeout is the maximum duration for reading the entire +# request, including the body. +# Because ReadTimeout does not let Handlers make per-request +# decisions on each request body's acceptable deadline or +# upload rate, most users will prefer to use +# ReadHeaderTimeout. It is valid to use them both. +read_timeout = "{{ .RPC.ReadTimeout }}" + +# mirrors http.Server#WriteTimeout +# WriteTimeout is the maximum duration before timing out +# writes of the response. It is reset whenever a new +# request's header is read. Like ReadTimeout, it does not +# let Handlers make decisions on a per-request basis. +write_timeout = "{{ .RPC.WriteTimeout }}" + +# mirrors http.Server#IdleTimeout +# IdleTimeout is the maximum amount of time to wait for the +# next request when keep-alives are enabled. If IdleTimeout +# is zero, the value of ReadTimeout is used. If both are +# zero, there is no timeout. +idle_timeout = "{{ .RPC.IdleTimeout }}" + # Maximum number of unique clientIDs that can /subscribe # If you're using /broadcast_tx_commit, set to the estimated maximum number # of broadcast_tx_commit calls per block. @@ -207,7 +230,7 @@ max_subscription_clients = {{ .RPC.MaxSubscriptionClients }} max_subscriptions_per_client = {{ .RPC.MaxSubscriptionsPerClient }} # How long to wait for a tx to be committed during /broadcast_tx_commit. -# WARNING: Using a value larger than 10s will result in increasing the +# WARNING: Using a value larger than 'WriteTimeout' will result in increasing the # global HTTP write timeout, which applies to all connections and endpoints. # See https://github.com/tendermint/tendermint/issues/3435 timeout_broadcast_tx_commit = "{{ .RPC.TimeoutBroadcastTxCommit }}" diff --git a/node/node.go b/node/node.go index b309f995b..eef38e866 100644 --- a/node/node.go +++ b/node/node.go @@ -1011,6 +1011,9 @@ func (n *Node) startRPC() ([]net.Listener, error) { config.MaxBodyBytes = n.config.RPC.MaxBodyBytes config.MaxHeaderBytes = n.config.RPC.MaxHeaderBytes config.MaxOpenConnections = n.config.RPC.MaxOpenConnections + config.ReadTimeout = n.config.RPC.ReadTimeout + config.WriteTimeout = n.config.RPC.WriteTimeout + config.IdleTimeout = n.config.RPC.IdleTimeout // If necessary adjust global WriteTimeout to ensure it's greater than // TimeoutBroadcastTxCommit. // See https://github.com/tendermint/tendermint/issues/3435 diff --git a/rpc/jsonrpc/client/http_json_client.go b/rpc/jsonrpc/client/http_json_client.go index 59727390a..2e3822a3b 100644 --- a/rpc/jsonrpc/client/http_json_client.go +++ b/rpc/jsonrpc/client/http_json_client.go @@ -10,6 +10,7 @@ import ( "net/http" "net/url" "strings" + "time" tmsync "github.com/tendermint/tendermint/libs/sync" types "github.com/tendermint/tendermint/rpc/jsonrpc/types" @@ -21,6 +22,10 @@ const ( protoWSS = "wss" protoWS = "ws" protoTCP = "tcp" + + defaultMaxIdleConns = 10000 + defaultIdleConnTimeout = 60 // sec + defaultExpectContinueTimeout = 1 // sec ) //------------------------------------------------------------- @@ -369,8 +374,12 @@ func DefaultHTTPClient(remoteAddr string) (*http.Client, error) { client := &http.Client{ Transport: &http.Transport{ // Set to true to prevent GZIP-bomb DoS attacks - DisableCompression: true, - Dial: dialFn, + DisableCompression: true, + Dial: dialFn, + MaxIdleConns: defaultMaxIdleConns, + MaxIdleConnsPerHost: defaultMaxIdleConns, + IdleConnTimeout: defaultIdleConnTimeout * time.Second, + ExpectContinueTimeout: defaultExpectContinueTimeout * time.Second, }, } diff --git a/rpc/jsonrpc/server/http_server.go b/rpc/jsonrpc/server/http_server.go index 6799d3665..8b0f247ff 100644 --- a/rpc/jsonrpc/server/http_server.go +++ b/rpc/jsonrpc/server/http_server.go @@ -27,6 +27,8 @@ type Config struct { ReadTimeout time.Duration // mirrors http.Server#WriteTimeout WriteTimeout time.Duration + // mirrors http.Server#IdleTimeout + IdleTimeout time.Duration // MaxBodyBytes controls the maximum number of bytes the // server will read parsing the request body. MaxBodyBytes int64 @@ -40,6 +42,7 @@ func DefaultConfig() *Config { MaxOpenConnections: 0, // unlimited ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, + IdleTimeout: 60 * time.Second, MaxBodyBytes: int64(1000000), // 1MB MaxHeaderBytes: 1 << 20, // same as the net/http default } @@ -56,6 +59,7 @@ func Serve(listener net.Listener, handler http.Handler, logger log.Logger, confi Handler: RecoverAndLogHandler(maxBytesHandler{h: handler, n: config.MaxBodyBytes}, logger), ReadTimeout: config.ReadTimeout, WriteTimeout: config.WriteTimeout, + IdleTimeout: config.IdleTimeout, MaxHeaderBytes: config.MaxHeaderBytes, } err := s.Serve(listener) @@ -81,6 +85,7 @@ func ServeTLS( Handler: RecoverAndLogHandler(maxBytesHandler{h: handler, n: config.MaxBodyBytes}, logger), ReadTimeout: config.ReadTimeout, WriteTimeout: config.WriteTimeout, + IdleTimeout: config.IdleTimeout, MaxHeaderBytes: config.MaxHeaderBytes, } err := s.ServeTLS(listener, certFile, keyFile) From fb983727c9480bd2f82a96b99b1d26c5007ff89b Mon Sep 17 00:00:00 2001 From: wetcod <37023735+wetcod@users.noreply.github.com> Date: Thu, 4 Feb 2021 19:42:02 +0900 Subject: [PATCH 3/6] chore: remove mempool.postCheck (#158) (#181) --- mempool/cache_test.go | 2 +- mempool/clist_mempool.go | 84 +++++++++++++++++++++-------------- mempool/clist_mempool_test.go | 38 +++++++--------- mempool/mempool.go | 25 ----------- mempool/mock/mempool.go | 1 - node/node.go | 1 - node/node_test.go | 1 - state/execution.go | 8 +--- state/tx_filter.go | 6 --- 9 files changed, 67 insertions(+), 99 deletions(-) diff --git a/mempool/cache_test.go b/mempool/cache_test.go index d9a53f475..01cdcb79d 100644 --- a/mempool/cache_test.go +++ b/mempool/cache_test.go @@ -68,7 +68,7 @@ func TestCacheAfterUpdate(t *testing.T) { tx := types.Tx{byte(v)} updateTxs = append(updateTxs, tx) } - err := mempool.Update(int64(tcIndex), updateTxs, abciResponses(len(updateTxs), abci.CodeTypeOK), nil, nil) + err := mempool.Update(int64(tcIndex), updateTxs, abciResponses(len(updateTxs), abci.CodeTypeOK), nil) require.NoError(t, err) for _, v := range tc.reAddIndices { diff --git a/mempool/clist_mempool.go b/mempool/clist_mempool.go index 8f5786437..4ad87c91d 100644 --- a/mempool/clist_mempool.go +++ b/mempool/clist_mempool.go @@ -39,6 +39,10 @@ type CListMempool struct { height int64 // the last block Update()'d to txsBytes int64 // total size of mempool, in bytes + reserved int // the number of checking tx and it should be considered when checking mempool full + reservedBytes int64 // size of checking tx and it should be considered when checking mempool full + reservedMtx sync.Mutex + // notify listeners (ie. consensus) when txs are available notifiedTxsAvailable bool txsAvailable chan struct{} // fires once for each height, when the mempool is not empty @@ -49,7 +53,6 @@ type CListMempool struct { // CheckTx or ReapMaxBytesMaxGas(ReapMaxTxs) methods. updateMtx tmsync.RWMutex preCheck PreCheckFunc - postCheck PostCheckFunc wal *auto.AutoFile // a log of mempool txs txs *clist.CList // concurrent linked-list of good txs @@ -125,13 +128,6 @@ func WithPreCheck(f PreCheckFunc) CListMempoolOption { return func(mem *CListMempool) { mem.preCheck = f } } -// WithPostCheck sets a filter for the mempool to reject a tx if f(tx) returns -// false. This is ran after CheckTx. Only applies to the first created block. -// After that, Update overwrites the existing value. -func WithPostCheck(f PostCheckFunc) CListMempoolOption { - return func(mem *CListMempool) { mem.postCheck = f } -} - // WithMetrics sets the metrics. func WithMetrics(metrics *Metrics) CListMempoolOption { return func(mem *CListMempool) { mem.metrics = metrics } @@ -285,7 +281,16 @@ func (mem *CListMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo Tx return ErrTxInCache } + // END CACHE + + // reserve mempool that should be called just before calling `mem.proxyAppConn.CheckTxAsync()` + if err := mem.reserve(int64(txSize)); err != nil { + // remove from cache + mem.cache.Remove(tx) + return err + } + // CONTRACT: `app.CheckTxAsync()` should check whether `GasWanted` is valid (0 <= GasWanted <= block.masGas) reqRes := mem.proxyAppConn.CheckTxAsync(abci.RequestCheckTx{Tx: tx}) reqRes.SetCallback(mem.reqResCb(tx, txInfo.SenderID, txInfo.SenderP2PID, cb)) @@ -395,6 +400,35 @@ func (mem *CListMempool) isFull(txSize int) error { return nil } +func (mem *CListMempool) reserve(txSize int64) error { + mem.reservedMtx.Lock() + defer mem.reservedMtx.Unlock() + + var ( + memSize = mem.Size() + txsBytes = mem.TxsBytes() + ) + + if memSize+mem.reserved >= mem.config.Size || txSize+mem.reservedBytes+txsBytes > mem.config.MaxTxsBytes { + return ErrMempoolIsFull{ + memSize + mem.reserved, mem.config.Size, + txsBytes + mem.reservedBytes, mem.config.MaxTxsBytes, + } + } + + mem.reserved++ + mem.reservedBytes += txSize + return nil +} + +func (mem *CListMempool) releaseReserve(txSize int64) { + mem.reservedMtx.Lock() + defer mem.reservedMtx.Unlock() + + mem.reserved-- + mem.reservedBytes -= txSize +} + // callback, which is called after the app checked the tx for the first time. // // The case where the app checks the tx for the second and subsequent times is @@ -407,20 +441,7 @@ func (mem *CListMempool) resCbFirstTime( ) { switch r := res.Value.(type) { case *abci.Response_CheckTx: - var postCheckErr error - if mem.postCheck != nil { - postCheckErr = mem.postCheck(tx, r.CheckTx) - } - if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { - // Check mempool isn't full again to reduce the chance of exceeding the - // limits. - if err := mem.isFull(len(tx)); err != nil { - // remove from cache (mempool might have a space later) - mem.cache.Remove(tx) - mem.logger.Error(err.Error()) - return - } - + if r.CheckTx.Code == abci.CodeTypeOK { memTx := &mempoolTx{ height: mem.height, gasWanted: r.CheckTx.GasWanted, @@ -438,13 +459,16 @@ func (mem *CListMempool) resCbFirstTime( } else { // ignore bad transaction mem.logger.Debug("rejected bad transaction", - "tx", txID(tx), "peerID", peerP2PID, "res", r, "err", postCheckErr) + "tx", txID(tx), "peerID", peerP2PID, "res", r, "err") mem.metrics.FailedTxs.Add(1) if !mem.config.KeepInvalidTxsInCache { // remove from cache (it might be good later) mem.cache.Remove(tx) } } + + // release `reserve` regardless it's OK or not (it might be good later) + mem.releaseReserve(int64(len(tx))) default: // ignore other messages } @@ -465,15 +489,11 @@ func (mem *CListMempool) resCbRecheck(req *abci.Request, res *abci.Response) { memTx.tx, tx)) } - var postCheckErr error - if mem.postCheck != nil { - postCheckErr = mem.postCheck(tx, r.CheckTx) - } - if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { + if r.CheckTx.Code == abci.CodeTypeOK { // Good, nothing to do. } else { // Tx became invalidated due to newly committed block. - mem.logger.Debug("tx is no longer valid", "tx", txID(tx), "res", r, "err", postCheckErr) + mem.logger.Debug("tx is no longer valid", "tx", txID(tx), "res", r, "err") // NOTE: we remove tx from the cache because it might be good later mem.removeTx(tx, mem.recheckCursor, !mem.config.KeepInvalidTxsInCache) } @@ -566,13 +586,12 @@ func (mem *CListMempool) ReapMaxTxs(max int) types.Txs { return txs } -// Lock() must be help by the caller during execution. +// Lock() must be held by the caller during execution. func (mem *CListMempool) Update( height int64, txs types.Txs, deliverTxResponses []*abci.ResponseDeliverTx, preCheck PreCheckFunc, - postCheck PostCheckFunc, ) error { // Set height mem.height = height @@ -581,9 +600,6 @@ func (mem *CListMempool) Update( if preCheck != nil { mem.preCheck = preCheck } - if postCheck != nil { - mem.postCheck = postCheck - } for i, tx := range txs { if deliverTxResponses[i].Code == abci.CodeTypeOK { diff --git a/mempool/clist_mempool_test.go b/mempool/clist_mempool_test.go index a40ba69af..bbcf5be52 100644 --- a/mempool/clist_mempool_test.go +++ b/mempool/clist_mempool_test.go @@ -147,30 +147,22 @@ func TestMempoolFilters(t *testing.T) { emptyTxArr := []types.Tx{[]byte{}} nopPreFilter := func(tx types.Tx) error { return nil } - nopPostFilter := func(tx types.Tx, res *abci.ResponseCheckTx) error { return nil } // each table driven test creates numTxsToCreate txs with checkTx, and at the end clears all remaining txs. // each tx has 20 bytes tests := []struct { numTxsToCreate int preFilter PreCheckFunc - postFilter PostCheckFunc expectedNumTxs int }{ - {10, nopPreFilter, nopPostFilter, 10}, - {10, PreCheckMaxBytes(10), nopPostFilter, 0}, - {10, PreCheckMaxBytes(22), nopPostFilter, 10}, - {10, nopPreFilter, PostCheckMaxGas(-1), 10}, - {10, nopPreFilter, PostCheckMaxGas(0), 0}, - {10, nopPreFilter, PostCheckMaxGas(1), 10}, - {10, nopPreFilter, PostCheckMaxGas(3000), 10}, - {10, PreCheckMaxBytes(10), PostCheckMaxGas(20), 0}, - {10, PreCheckMaxBytes(30), PostCheckMaxGas(20), 10}, - {10, PreCheckMaxBytes(22), PostCheckMaxGas(1), 10}, - {10, PreCheckMaxBytes(22), PostCheckMaxGas(0), 0}, + {10, nopPreFilter, 10}, + {10, PreCheckMaxBytes(10), 0}, + {10, PreCheckMaxBytes(20), 0}, + {10, PreCheckMaxBytes(22), 10}, + {10, PreCheckMaxBytes(30), 10}, } for tcIndex, tt := range tests { - err := mempool.Update(1, emptyTxArr, abciResponses(len(emptyTxArr), abci.CodeTypeOK), tt.preFilter, tt.postFilter) + err := mempool.Update(1, emptyTxArr, abciResponses(len(emptyTxArr), abci.CodeTypeOK), tt.preFilter) require.NoError(t, err) checkTxs(t, mempool, tt.numTxsToCreate, UnknownPeerID) require.Equal(t, tt.expectedNumTxs, mempool.Size(), "mempool had the incorrect size, on test case %d", tcIndex) @@ -186,7 +178,7 @@ func TestMempoolUpdate(t *testing.T) { // 1. Adds valid txs to the cache { - err := mempool.Update(1, []types.Tx{[]byte{0x01}}, abciResponses(1, abci.CodeTypeOK), nil, nil) + err := mempool.Update(1, []types.Tx{[]byte{0x01}}, abciResponses(1, abci.CodeTypeOK), nil) require.NoError(t, err) err = mempool.CheckTx([]byte{0x01}, nil, TxInfo{}) if assert.Error(t, err) { @@ -198,7 +190,7 @@ func TestMempoolUpdate(t *testing.T) { { err := mempool.CheckTx([]byte{0x02}, nil, TxInfo{}) require.NoError(t, err) - err = mempool.Update(1, []types.Tx{[]byte{0x02}}, abciResponses(1, abci.CodeTypeOK), nil, nil) + err = mempool.Update(1, []types.Tx{[]byte{0x02}}, abciResponses(1, abci.CodeTypeOK), nil) require.NoError(t, err) assert.Zero(t, mempool.Size()) } @@ -207,7 +199,7 @@ func TestMempoolUpdate(t *testing.T) { { err := mempool.CheckTx([]byte{0x03}, nil, TxInfo{}) require.NoError(t, err) - err = mempool.Update(1, []types.Tx{[]byte{0x03}}, abciResponses(1, 1), nil, nil) + err = mempool.Update(1, []types.Tx{[]byte{0x03}}, abciResponses(1, 1), nil) require.NoError(t, err) assert.Zero(t, mempool.Size()) @@ -239,7 +231,7 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { _ = app.DeliverTx(abci.RequestDeliverTx{Tx: a}) _ = app.DeliverTx(abci.RequestDeliverTx{Tx: b}) err = mempool.Update(1, []types.Tx{a, b}, - []*abci.ResponseDeliverTx{{Code: abci.CodeTypeOK}, {Code: 2}}, nil, nil) + []*abci.ResponseDeliverTx{{Code: abci.CodeTypeOK}, {Code: 2}}, nil) require.NoError(t, err) // a must be added to the cache @@ -294,7 +286,7 @@ func TestTxsAvailable(t *testing.T) { // it should fire once now for the new height // since there are still txs left committedTxs, txs := txs[:50], txs[50:] - if err := mempool.Update(1, committedTxs, abciResponses(len(committedTxs), abci.CodeTypeOK), nil, nil); err != nil { + if err := mempool.Update(1, committedTxs, abciResponses(len(committedTxs), abci.CodeTypeOK), nil); err != nil { t.Error(err) } ensureFire(t, mempool.TxsAvailable(), timeoutMS) @@ -306,7 +298,7 @@ func TestTxsAvailable(t *testing.T) { // now call update with all the txs. it should not fire as there are no txs left committedTxs = append(txs, moreTxs...) //nolint: gocritic - if err := mempool.Update(2, committedTxs, abciResponses(len(committedTxs), abci.CodeTypeOK), nil, nil); err != nil { + if err := mempool.Update(2, committedTxs, abciResponses(len(committedTxs), abci.CodeTypeOK), nil); err != nil { t.Error(err) } ensureNoFire(t, mempool.TxsAvailable(), timeoutMS) @@ -365,7 +357,7 @@ func TestSerialReap(t *testing.T) { binary.BigEndian.PutUint64(txBytes, uint64(i)) txs = append(txs, txBytes) } - if err := mempool.Update(0, txs, abciResponses(len(txs), abci.CodeTypeOK), nil, nil); err != nil { + if err := mempool.Update(0, txs, abciResponses(len(txs), abci.CodeTypeOK), nil); err != nil { t.Error(err) } } @@ -536,7 +528,7 @@ func TestMempoolTxsBytes(t *testing.T) { assert.EqualValues(t, 1, mempool.TxsBytes()) // 3. zero again after tx is removed by Update - err = mempool.Update(1, []types.Tx{[]byte{0x01}}, abciResponses(1, abci.CodeTypeOK), nil, nil) + err = mempool.Update(1, []types.Tx{[]byte{0x01}}, abciResponses(1, abci.CodeTypeOK), nil) require.NoError(t, err) assert.EqualValues(t, 0, mempool.TxsBytes()) @@ -586,7 +578,7 @@ func TestMempoolTxsBytes(t *testing.T) { require.NotEmpty(t, res2.Data) // Pretend like we committed nothing so txBytes gets rechecked and removed. - err = mempool.Update(1, []types.Tx{}, abciResponses(0, abci.CodeTypeOK), nil, nil) + err = mempool.Update(1, []types.Tx{}, abciResponses(0, abci.CodeTypeOK), nil) require.NoError(t, err) assert.EqualValues(t, 0, mempool.TxsBytes()) diff --git a/mempool/mempool.go b/mempool/mempool.go index d01958b53..dca3f44e0 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -43,7 +43,6 @@ type Mempool interface { blockTxs types.Txs, deliverTxResponses []*abci.ResponseDeliverTx, newPreFn PreCheckFunc, - newPostFn PostCheckFunc, ) error // FlushAppConn flushes the mempool connection to ensure async reqResCb calls are @@ -85,11 +84,6 @@ type Mempool interface { // transaction doesn't exceeded the block size. type PreCheckFunc func(types.Tx) error -// PostCheckFunc is an optional filter executed after CheckTx and rejects -// transaction if false is returned. An example would be to ensure a -// transaction doesn't require more gas than available for the block. -type PostCheckFunc func(types.Tx, *abci.ResponseCheckTx) error - // TxInfo are parameters that get passed when attempting to add a tx to the // mempool. type TxInfo struct { @@ -114,22 +108,3 @@ func PreCheckMaxBytes(maxBytes int64) PreCheckFunc { return nil } } - -// PostCheckMaxGas checks that the wanted gas is smaller or equal to the passed -// maxGas. Returns nil if maxGas is -1. -func PostCheckMaxGas(maxGas int64) PostCheckFunc { - return func(tx types.Tx, res *abci.ResponseCheckTx) error { - if maxGas == -1 { - return nil - } - if res.GasWanted < 0 { - return fmt.Errorf("gas wanted %d is negative", - res.GasWanted) - } - if res.GasWanted > maxGas { - return fmt.Errorf("gas wanted %d is greater than max gas %d", - res.GasWanted, maxGas) - } - return nil - } -} diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index be690efaa..9f1b8b1f8 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -25,7 +25,6 @@ func (Mempool) Update( _ types.Txs, _ []*abci.ResponseDeliverTx, _ mempl.PreCheckFunc, - _ mempl.PostCheckFunc, ) error { return nil } diff --git a/node/node.go b/node/node.go index eef38e866..84e82c156 100644 --- a/node/node.go +++ b/node/node.go @@ -322,7 +322,6 @@ func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns, state.LastBlockHeight, mempl.WithMetrics(memplMetrics), mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), ) mempoolLogger := logger.With("module", "mempool") mempoolReactor := mempl.NewReactor(config.Mempool, mempool) diff --git a/node/node_test.go b/node/node_test.go index 8cbf38601..bb9ea44b9 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -248,7 +248,6 @@ func TestCreateProposalBlock(t *testing.T) { state.LastBlockHeight, mempl.WithMetrics(memplMetrics), mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), ) mempool.SetLogger(logger) diff --git a/state/execution.go b/state/execution.go index 3f49cd0b1..57a920f0a 100644 --- a/state/execution.go +++ b/state/execution.go @@ -257,13 +257,7 @@ func (blockExec *BlockExecutor) Commit( // Update mempool. updateMempoolStartTime := time.Now().UnixNano() - err = blockExec.mempool.Update( - block.Height, - block.Txs, - deliverTxResponses, - TxPreCheck(state), - TxPostCheck(state), - ) + err = blockExec.mempool.Update(block.Height, block.Txs, deliverTxResponses, TxPreCheck(state)) updateMempoolEndTime := time.Now().UnixNano() updateMempoolTimeMs := float64(updateMempoolEndTime-updateMempoolStartTime) / 1000000 diff --git a/state/tx_filter.go b/state/tx_filter.go index 52d055966..0a8e08d3c 100644 --- a/state/tx_filter.go +++ b/state/tx_filter.go @@ -14,9 +14,3 @@ func TxPreCheck(state State) mempl.PreCheckFunc { ) return mempl.PreCheckMaxBytes(maxDataBytes) } - -// TxPostCheck returns a function to filter transactions after processing. -// The function limits the gas wanted by a transaction to the block's maximum total gas. -func TxPostCheck(state State) mempl.PostCheckFunc { - return mempl.PostCheckMaxGas(state.ConsensusParams.Block.MaxGas) -} From 21e767d4e4ff7b3c23f22d000ee4ff16cc8e3c95 Mon Sep 17 00:00:00 2001 From: Woosang Son Date: Thu, 4 Mar 2021 14:51:12 +0900 Subject: [PATCH 4/6] chore: linemint image on README (#5) --- README.md | 18 ++++++++---------- docs/linemint-image.jpg | Bin 0 -> 23942 bytes 2 files changed, 8 insertions(+), 10 deletions(-) create mode 100644 docs/linemint-image.jpg diff --git a/README.md b/README.md index ac7241c3b..2737660da 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,18 @@ -# Tendermint +# Linemint -![banner](docs/tendermint-core-image.jpg) +![banner](docs/linemint-image.jpg) [Byzantine-Fault Tolerant](https://en.wikipedia.org/wiki/Byzantine_fault_tolerance) [State Machines](https://en.wikipedia.org/wiki/State_machine_replication). Or [Blockchain](), for short. -[![version](https://img.shields.io/github/tag/tendermint/tendermint.svg)](https://github.com/tendermint/tendermint/releases/latest) -[![API Reference](https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667)](https://pkg.go.dev/github.com/tendermint/tendermint) [![Go version](https://img.shields.io/badge/go-1.15-blue.svg)](https://github.com/moovweb/gvm) -[![Discord chat](https://img.shields.io/discord/669268347736686612.svg)](https://discord.gg/AzefAFd) -[![license](https://img.shields.io/github/license/tendermint/tendermint.svg)](https://github.com/tendermint/tendermint/blob/master/LICENSE) -[![tendermint/tendermint](https://tokei.rs/b1/github/tendermint/tendermint?category=lines)](https://github.com/tendermint/tendermint) -[![Sourcegraph](https://sourcegraph.com/github.com/tendermint/tendermint/-/badge.svg)](https://sourcegraph.com/github.com/tendermint/tendermint?badge) | Branch | Tests | Coverage | Linting | | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | -| master | [![CircleCI](https://circleci.com/gh/tendermint/tendermint/tree/master.svg?style=shield)](https://circleci.com/gh/tendermint/tendermint/tree/master)
![Tests](https://github.com/tendermint/tendermint/workflows/Tests/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/tendermint/tendermint/branch/master/graph/badge.svg)](https://codecov.io/gh/tendermint/tendermint) | ![Lint](https://github.com/tendermint/tendermint/workflows/Lint/badge.svg) | +| ebony | [![CircleCI](https://circleci.com/gh/line/linemint/tree/ebony.svg?style=shield)](https://circleci.com/gh/line/linemint/tree/ebony)
![Tests](https://github.com/tendermint/tendermint/workflows/Tests/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/tendermint/tendermint/branch/master/graph/badge.svg)](https://codecov.io/gh/tendermint/tendermint) | ![Lint](https://github.com/line/linemint/workflows/Lint/badge.svg) | +Linemint Core is derived from Tendermint Core. Tendermint Core is Byzantine Fault Tolerant (BFT) middleware that takes a state transition machine - written in any programming language - and securely replicates it on many machines. @@ -28,7 +23,7 @@ see our recent paper, "[The latest gossip on BFT consensus](https://arxiv.org/ab ## Releases -Please do not depend on master as your production branch. Use [releases](https://github.com/tendermint/tendermint/releases) instead. +Please do not depend on master as your production branch. Use [releases](https://github.com/line/linemint/releases) instead. Tendermint is being used in production in both private and public environments, most notably the blockchains of the [Cosmos Network](https://cosmos.network/). @@ -149,6 +144,9 @@ Additional tooling can be found in [/docs/tools](/docs/tools). ### Applications +- [LBM SDK](http://github.com/line/lbm-sdk); a line blockchain mainnet framework +- [LBM](http://github.com/line/lbm); line blockchain mainnet +- [OSTRACON](http://github.com/line/ostracon); tendermint-based BFT algorithm using VRF random sampling - [Cosmos SDK](http://github.com/cosmos/cosmos-sdk); a cryptocurrency application framework - [Ethermint](http://github.com/cosmos/ethermint); Ethereum on Tendermint - [Many more](https://tendermint.com/ecosystem) diff --git a/docs/linemint-image.jpg b/docs/linemint-image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..208a80b9adc5b98b660874ab0e060340eeca20e2 GIT binary patch literal 23942 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 literal 0 HcmV?d00001 From 673bfca6178192c4ccf19563a914e118194ca0f3 Mon Sep 17 00:00:00 2001 From: Woosang Son Date: Thu, 4 Mar 2021 16:56:10 +0900 Subject: [PATCH 5/6] fix: test failure for postCheck being removed --- consensus/replay_stubs.go | 1 - mempool/reactor_test.go | 4 ++-- node/node_test.go | 1 - test/maverick/consensus/replay_stubs.go | 1 - test/maverick/node/node.go | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index 08974a67e..087727fed 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -28,7 +28,6 @@ func (emptyMempool) Update( _ types.Txs, _ []*abci.ResponseDeliverTx, _ mempl.PreCheckFunc, - _ mempl.PostCheckFunc, ) error { return nil } diff --git a/mempool/reactor_test.go b/mempool/reactor_test.go index bc51bfd9b..68e1223bb 100644 --- a/mempool/reactor_test.go +++ b/mempool/reactor_test.go @@ -102,7 +102,7 @@ func TestReactorConcurrency(t *testing.T) { for i := range txs { deliverTxResponses[i] = &abci.ResponseDeliverTx{Code: 0} } - err := reactors[0].mempool.Update(1, txs, deliverTxResponses, nil, nil) + err := reactors[0].mempool.Update(1, txs, deliverTxResponses, nil) assert.NoError(t, err) }() @@ -114,7 +114,7 @@ func TestReactorConcurrency(t *testing.T) { reactors[1].mempool.Lock() defer reactors[1].mempool.Unlock() - err := reactors[1].mempool.Update(1, []types.Tx{}, make([]*abci.ResponseDeliverTx, 0), nil, nil) + err := reactors[1].mempool.Update(1, []types.Tx{}, make([]*abci.ResponseDeliverTx, 0), nil) assert.NoError(t, err) }() diff --git a/node/node_test.go b/node/node_test.go index bb9ea44b9..91986753b 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -339,7 +339,6 @@ func TestMaxProposalBlockSize(t *testing.T) { state.LastBlockHeight, mempl.WithMetrics(memplMetrics), mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), ) mempool.SetLogger(logger) diff --git a/test/maverick/consensus/replay_stubs.go b/test/maverick/consensus/replay_stubs.go index 08974a67e..087727fed 100644 --- a/test/maverick/consensus/replay_stubs.go +++ b/test/maverick/consensus/replay_stubs.go @@ -28,7 +28,6 @@ func (emptyMempool) Update( _ types.Txs, _ []*abci.ResponseDeliverTx, _ mempl.PreCheckFunc, - _ mempl.PostCheckFunc, ) error { return nil } diff --git a/test/maverick/node/node.go b/test/maverick/node/node.go index 22853de5f..dcb66484b 100644 --- a/test/maverick/node/node.go +++ b/test/maverick/node/node.go @@ -369,7 +369,6 @@ func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns, state.LastBlockHeight, mempl.WithMetrics(memplMetrics), mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), ) mempoolLogger := logger.With("module", "mempool") mempoolReactor := mempl.NewReactor(config.Mempool, mempool) From 0606b9a59a5130fa8da32609b7616a4cc2f22661 Mon Sep 17 00:00:00 2001 From: Woosang Son Date: Mon, 8 Mar 2021 18:50:18 +0900 Subject: [PATCH 6/6] chore: linemint to ostracon in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2737660da..78e4feb7e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Or [Blockchain](), for shor | Branch | Tests | Coverage | Linting | | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | -| ebony | [![CircleCI](https://circleci.com/gh/line/linemint/tree/ebony.svg?style=shield)](https://circleci.com/gh/line/linemint/tree/ebony)
![Tests](https://github.com/tendermint/tendermint/workflows/Tests/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/tendermint/tendermint/branch/master/graph/badge.svg)](https://codecov.io/gh/tendermint/tendermint) | ![Lint](https://github.com/line/linemint/workflows/Lint/badge.svg) | +| ebony | [![CircleCI](https://circleci.com/gh/line/ostracon/tree/ebony.svg?style=shield)](https://circleci.com/gh/line/ostracon/tree/ebony)
![Tests](https://github.com/tendermint/tendermint/workflows/Tests/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/tendermint/tendermint/branch/master/graph/badge.svg)](https://codecov.io/gh/tendermint/tendermint) | ![Lint](https://github.com/line/ostracon/workflows/Lint/badge.svg) | Linemint Core is derived from Tendermint Core. Tendermint Core is Byzantine Fault Tolerant (BFT) middleware that takes a state transition machine - written in any programming language - @@ -23,7 +23,7 @@ see our recent paper, "[The latest gossip on BFT consensus](https://arxiv.org/ab ## Releases -Please do not depend on master as your production branch. Use [releases](https://github.com/line/linemint/releases) instead. +Please do not depend on master as your production branch. Use [releases](https://github.com/line/ostracon/releases) instead. Tendermint is being used in production in both private and public environments, most notably the blockchains of the [Cosmos Network](https://cosmos.network/).