From 2427f30e9a63102dc036996ad535cd85d9aa6165 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Thu, 2 May 2024 11:46:58 -0400 Subject: [PATCH 1/4] [EVM] Fix contract deploy receipts (#1618) fix contract deploy receipts --- evmrpc/tx.go | 7 +++++-- evmrpc/tx_test.go | 11 +++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/evmrpc/tx.go b/evmrpc/tx.go index 3863506be..e789cffc2 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -268,13 +268,13 @@ func encodeReceipt(receipt *types.Receipt, decoder sdk.TxDecoder, block *coretyp } bloom := ethtypes.Bloom{} bloom.SetBytes(receipt.LogsBloom) + fields := map[string]interface{}{ "blockHash": bh, "blockNumber": hexutil.Uint64(receipt.BlockNumber), "transactionHash": common.HexToHash(receipt.TxHashHex), "transactionIndex": hexutil.Uint64(evmTxIndex), "from": common.HexToAddress(receipt.From), - "to": common.HexToAddress(receipt.To), "gasUsed": hexutil.Uint64(receipt.GasUsed), "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), "logs": logs, @@ -283,10 +283,13 @@ func encodeReceipt(receipt *types.Receipt, decoder sdk.TxDecoder, block *coretyp "effectiveGasPrice": (*hexutil.Big)(big.NewInt(int64(receipt.EffectiveGasPrice))), "status": hexutil.Uint(receipt.Status), } - if receipt.ContractAddress != "" { + if receipt.ContractAddress != "" && receipt.To == "" { fields["contractAddress"] = common.HexToAddress(receipt.ContractAddress) } else { fields["contractAddress"] = nil } + if receipt.To != "" { + fields["to"] = common.HexToAddress(receipt.To) + } return fields, nil } diff --git a/evmrpc/tx_test.go b/evmrpc/tx_test.go index e45863341..50a26c373 100644 --- a/evmrpc/tx_test.go +++ b/evmrpc/tx_test.go @@ -21,6 +21,11 @@ import ( ) func TestGetTxReceipt(t *testing.T) { + receipt, err := EVMKeeper.GetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e")) + require.Nil(t, err) + receipt.To = "" + EVMKeeper.SetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e"), receipt) + body := "{\"jsonrpc\": \"2.0\",\"method\": \"eth_getTransactionReceipt\",\"params\":[\"0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e\"],\"id\":\"test\"}" req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s:%d", TestAddr, TestPort), strings.NewReader(body)) require.Nil(t, err) @@ -53,15 +58,16 @@ func TestGetTxReceipt(t *testing.T) { require.Equal(t, "0x0", log["logIndex"].(string)) require.False(t, log["removed"].(bool)) require.Equal(t, "0x0", resObj["status"].(string)) - require.Equal(t, "0x1234567890123456789012345678901234567890", resObj["to"].(string)) + require.Equal(t, nil, resObj["to"]) require.Equal(t, "0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e", resObj["transactionHash"].(string)) require.Equal(t, "0x0", resObj["transactionIndex"].(string)) require.Equal(t, "0x1", resObj["type"].(string)) require.Equal(t, "0x1234567890123456789012345678901234567890", resObj["contractAddress"].(string)) - receipt, err := EVMKeeper.GetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e")) + receipt, err = EVMKeeper.GetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e")) require.Nil(t, err) receipt.ContractAddress = "" + receipt.To = "0x1234567890123456789012345678901234567890" EVMKeeper.SetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e"), receipt) body = "{\"jsonrpc\": \"2.0\",\"method\": \"eth_getTransactionReceipt\",\"params\":[\"0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e\"],\"id\":\"test\"}" req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s:%d", TestAddr, TestPort), strings.NewReader(body)) @@ -75,6 +81,7 @@ func TestGetTxReceipt(t *testing.T) { require.Nil(t, json.Unmarshal(resBody, &resObj)) resObj = resObj["result"].(map[string]interface{}) require.Nil(t, resObj["contractAddress"]) + require.Equal(t, "0x1234567890123456789012345678901234567890", resObj["to"].(string)) req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s:%d", TestAddr, TestBadPort), strings.NewReader(body)) require.Nil(t, err) From e8e4b3bf43a99e47ea2d7ca287089cd1fc0ff47e Mon Sep 17 00:00:00 2001 From: codchen Date: Fri, 3 May 2024 02:19:35 +0800 Subject: [PATCH 2/4] Limit number of subscriptions (#1619) * Limit number of subscriptions * Fix tests --------- Co-authored-by: Steven Landers Co-authored-by: Philip Su --- cmd/seid/cmd/root.go | 3 ++ evmrpc/config.go | 86 ++++++++++++++++++++++++------------------- evmrpc/config_test.go | 43 ++++++++++++---------- evmrpc/server.go | 2 +- evmrpc/subscribe.go | 15 +++++--- 5 files changed, 86 insertions(+), 63 deletions(-) diff --git a/cmd/seid/cmd/root.go b/cmd/seid/cmd/root.go index be5337671..c04d5e11f 100644 --- a/cmd/seid/cmd/root.go +++ b/cmd/seid/cmd/root.go @@ -501,6 +501,9 @@ max_log_no_block = {{ .EVM.MaxLogNoBlock }} # max number of blocks to query logs for max_blocks_for_log = {{ .EVM.MaxBlocksForLog }} +# max number of concurrent NewHead subscriptions +max_subscriptions_new_head = {{ .EVM.MaxSubscriptionsNewHead }} + [eth_replay] eth_replay_enabled = {{ .ETHReplay.Enabled }} eth_rpc = "{{ .ETHReplay.EthRPC }}" diff --git a/evmrpc/config.go b/evmrpc/config.go index ea5278838..00e2a2725 100644 --- a/evmrpc/config.go +++ b/evmrpc/config.go @@ -79,50 +79,55 @@ type Config struct { // max number of blocks to query logs for MaxBlocksForLog int64 `mapstructure:"max_blocks_for_log"` + + // max number of concurrent NewHead subscriptions + MaxSubscriptionsNewHead uint64 `mapstructure:"max_subscriptions_new_head"` } var DefaultConfig = Config{ - HTTPEnabled: true, - HTTPPort: 8545, - WSEnabled: true, - WSPort: 8546, - ReadTimeout: rpc.DefaultHTTPTimeouts.ReadTimeout, - ReadHeaderTimeout: rpc.DefaultHTTPTimeouts.ReadHeaderTimeout, - WriteTimeout: rpc.DefaultHTTPTimeouts.WriteTimeout, - IdleTimeout: rpc.DefaultHTTPTimeouts.IdleTimeout, - SimulationGasLimit: 10_000_000, // 10M - SimulationEVMTimeout: 60 * time.Second, - CORSOrigins: "*", - WSOrigins: "*", - FilterTimeout: 120 * time.Second, - CheckTxTimeout: 5 * time.Second, - MaxTxPoolTxs: 1000, - Slow: false, - DenyList: make([]string, 0), - MaxLogNoBlock: 10000, - MaxBlocksForLog: 2000, + HTTPEnabled: true, + HTTPPort: 8545, + WSEnabled: true, + WSPort: 8546, + ReadTimeout: rpc.DefaultHTTPTimeouts.ReadTimeout, + ReadHeaderTimeout: rpc.DefaultHTTPTimeouts.ReadHeaderTimeout, + WriteTimeout: rpc.DefaultHTTPTimeouts.WriteTimeout, + IdleTimeout: rpc.DefaultHTTPTimeouts.IdleTimeout, + SimulationGasLimit: 10_000_000, // 10M + SimulationEVMTimeout: 60 * time.Second, + CORSOrigins: "*", + WSOrigins: "*", + FilterTimeout: 120 * time.Second, + CheckTxTimeout: 5 * time.Second, + MaxTxPoolTxs: 1000, + Slow: false, + DenyList: make([]string, 0), + MaxLogNoBlock: 10000, + MaxBlocksForLog: 2000, + MaxSubscriptionsNewHead: 10000, } const ( - flagHTTPEnabled = "evm.http_enabled" - flagHTTPPort = "evm.http_port" - flagWSEnabled = "evm.ws_enabled" - flagWSPort = "evm.ws_port" - flagReadTimeout = "evm.read_timeout" - flagReadHeaderTimeout = "evm.read_header_timeout" - flagWriteTimeout = "evm.write_timeout" - flagIdleTimeout = "evm.idle_timeout" - flagSimulationGasLimit = "evm.simulation_gas_limit" - flagSimulationEVMTimeout = "evm.simulation_evm_timeout" - flagCORSOrigins = "evm.cors_origins" - flagWSOrigins = "evm.ws_origins" - flagFilterTimeout = "evm.filter_timeout" - flagMaxTxPoolTxs = "evm.max_tx_pool_txs" - flagCheckTxTimeout = "evm.checktx_timeout" - flagSlow = "evm.slow" - flagDenyList = "evm.deny_list" - flagMaxLogNoBlock = "evm.max_log_no_block" - flagMaxBlocksForLog = "evm.max_blocks_for_log" + flagHTTPEnabled = "evm.http_enabled" + flagHTTPPort = "evm.http_port" + flagWSEnabled = "evm.ws_enabled" + flagWSPort = "evm.ws_port" + flagReadTimeout = "evm.read_timeout" + flagReadHeaderTimeout = "evm.read_header_timeout" + flagWriteTimeout = "evm.write_timeout" + flagIdleTimeout = "evm.idle_timeout" + flagSimulationGasLimit = "evm.simulation_gas_limit" + flagSimulationEVMTimeout = "evm.simulation_evm_timeout" + flagCORSOrigins = "evm.cors_origins" + flagWSOrigins = "evm.ws_origins" + flagFilterTimeout = "evm.filter_timeout" + flagMaxTxPoolTxs = "evm.max_tx_pool_txs" + flagCheckTxTimeout = "evm.checktx_timeout" + flagSlow = "evm.slow" + flagDenyList = "evm.deny_list" + flagMaxLogNoBlock = "evm.max_log_no_block" + flagMaxBlocksForLog = "evm.max_blocks_for_log" + flagMaxSubscriptionsNewHead = "evm.max_subscriptions_new_head" ) func ReadConfig(opts servertypes.AppOptions) (Config, error) { @@ -223,5 +228,10 @@ func ReadConfig(opts servertypes.AppOptions) (Config, error) { return cfg, err } } + if v := opts.Get(flagMaxSubscriptionsNewHead); v != nil { + if cfg.MaxSubscriptionsNewHead, err = cast.ToUint64E(v); err != nil { + return cfg, err + } + } return cfg, nil } diff --git a/evmrpc/config_test.go b/evmrpc/config_test.go index c29d53bc0..6cc99b370 100644 --- a/evmrpc/config_test.go +++ b/evmrpc/config_test.go @@ -9,25 +9,26 @@ import ( ) type opts struct { - httpEnabled interface{} - httpPort interface{} - wsEnabled interface{} - wsPort interface{} - readTimeout interface{} - readHeaderTimeout interface{} - writeTimeout interface{} - idleTimeout interface{} - simulationGasLimit interface{} - simulationEVMTimeout interface{} - corsOrigins interface{} - wsOrigins interface{} - filterTimeout interface{} - checkTxTimeout interface{} - maxTxPoolTxs interface{} - slow interface{} - denyList interface{} - maxLogNoBlock interface{} - maxBlocksForLog interface{} + httpEnabled interface{} + httpPort interface{} + wsEnabled interface{} + wsPort interface{} + readTimeout interface{} + readHeaderTimeout interface{} + writeTimeout interface{} + idleTimeout interface{} + simulationGasLimit interface{} + simulationEVMTimeout interface{} + corsOrigins interface{} + wsOrigins interface{} + filterTimeout interface{} + checkTxTimeout interface{} + maxTxPoolTxs interface{} + slow interface{} + denyList interface{} + maxLogNoBlock interface{} + maxBlocksForLog interface{} + maxSubscriptionsNewHead interface{} } func (o *opts) Get(k string) interface{} { @@ -88,6 +89,9 @@ func (o *opts) Get(k string) interface{} { if k == "evm.max_blocks_for_log" { return o.maxBlocksForLog } + if k == "evm.max_subscriptions_new_head" { + return o.maxSubscriptionsNewHead + } panic("unknown key") } @@ -112,6 +116,7 @@ func TestReadConfig(t *testing.T) { make([]string, 0), 20000, 1000, + 10000, } _, err := evmrpc.ReadConfig(&goodOpts) require.Nil(t, err) diff --git a/evmrpc/server.go b/evmrpc/server.go index b69a23bde..74234d14e 100644 --- a/evmrpc/server.go +++ b/evmrpc/server.go @@ -154,7 +154,7 @@ func NewEVMWebSocketServer( }, { Namespace: "eth", - Service: NewSubscriptionAPI(tmClient, &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider}, &SubscriptionConfig{subscriptionCapacity: 100}, &FilterConfig{timeout: config.FilterTimeout, maxLog: config.MaxLogNoBlock, maxBlock: config.MaxBlocksForLog}), + Service: NewSubscriptionAPI(tmClient, &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider}, &SubscriptionConfig{subscriptionCapacity: 100, newHeadLimit: config.MaxSubscriptionsNewHead}, &FilterConfig{timeout: config.FilterTimeout, maxLog: config.MaxLogNoBlock, maxBlock: config.MaxBlocksForLog}), }, { Namespace: "web3", diff --git a/evmrpc/subscribe.go b/evmrpc/subscribe.go index 6789bc1d8..44a7385d7 100644 --- a/evmrpc/subscribe.go +++ b/evmrpc/subscribe.go @@ -2,6 +2,7 @@ package evmrpc import ( "context" + "errors" "fmt" "math/big" "sync" @@ -26,12 +27,13 @@ type SubscriptionAPI struct { subscriptonConfig *SubscriptionConfig logFetcher *LogFetcher - newHeadListenersMtx *sync.Mutex + newHeadListenersMtx *sync.RWMutex newHeadListeners map[rpc.ID]chan map[string]interface{} } type SubscriptionConfig struct { subscriptionCapacity int + newHeadLimit uint64 } func NewSubscriptionAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, subscriptionConfig *SubscriptionConfig, filterConfig *FilterConfig) *SubscriptionAPI { @@ -41,7 +43,7 @@ func NewSubscriptionAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, subsc subscriptionManager: NewSubscriptionManager(tmClient), subscriptonConfig: subscriptionConfig, logFetcher: logFetcher, - newHeadListenersMtx: &sync.Mutex{}, + newHeadListenersMtx: &sync.RWMutex{}, newHeadListeners: make(map[rpc.ID]chan map[string]interface{}), } id, subCh, err := api.subscriptionManager.Subscribe(context.Background(), NewHeadQueryBuilder(), api.subscriptonConfig.subscriptionCapacity) @@ -87,6 +89,12 @@ func (a *SubscriptionAPI) NewHeads(ctx context.Context) (s *rpc.Subscription, er rpcSub := notifier.CreateSubscription() listener := make(chan map[string]interface{}) + a.newHeadListenersMtx.Lock() + defer a.newHeadListenersMtx.Unlock() + if uint64(len(a.newHeadListeners)) >= a.subscriptonConfig.newHeadLimit { + return nil, errors.New("no new subscription can be created") + } + a.newHeadListeners[rpcSub.ID] = listener go func() { OUTER: @@ -108,9 +116,6 @@ func (a *SubscriptionAPI) NewHeads(ctx context.Context) (s *rpc.Subscription, er delete(a.newHeadListeners, rpcSub.ID) close(listener) }() - a.newHeadListenersMtx.Lock() - defer a.newHeadListenersMtx.Unlock() - a.newHeadListeners[rpcSub.ID] = listener return rpcSub, nil } From 33ec0990b4d409697f3c07936b7eb6887f5b2633 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Thu, 2 May 2024 15:49:42 -0400 Subject: [PATCH 3/4] [EVM] Add websocket metrics (#1621) * add websocket connection metrics * add websocket metrics by request * go imports --- evmrpc/association.go | 21 +++++++++-------- evmrpc/block.go | 23 ++++++++++--------- evmrpc/filter.go | 36 +++++++++++++++-------------- evmrpc/info.go | 27 +++++++++++----------- evmrpc/info_test.go | 2 +- evmrpc/net.go | 15 ++++++------ evmrpc/rpcstack.go | 13 ++++------- evmrpc/rpcstack_test.go | 15 ------------ evmrpc/send.go | 38 ++++++++++++++++--------------- evmrpc/server.go | 43 +++++++++++++++++++---------------- evmrpc/simulate.go | 13 +++++++---- evmrpc/state.go | 21 +++++++++-------- evmrpc/state_test.go | 2 +- evmrpc/subscribe.go | 8 ++++--- evmrpc/tracers.go | 21 +++++++++-------- evmrpc/tx.go | 31 +++++++++++++------------ evmrpc/tx_test.go | 4 ++-- evmrpc/txpool.go | 17 +++++++------- evmrpc/utils.go | 6 ++--- evmrpc/websockets.go | 20 ++++++++++++++++ utils/metrics/metrics_util.go | 22 +++++++++++++++--- 21 files changed, 218 insertions(+), 180 deletions(-) create mode 100644 evmrpc/websockets.go diff --git a/evmrpc/association.go b/evmrpc/association.go index c3d14a937..fb3fda479 100644 --- a/evmrpc/association.go +++ b/evmrpc/association.go @@ -18,15 +18,16 @@ import ( ) type AssociationAPI struct { - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - txDecoder sdk.TxDecoder - sendAPI *SendAPI + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + txDecoder sdk.TxDecoder + sendAPI *SendAPI + connectionType ConnectionType } -func NewAssociationAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, sendAPI *SendAPI) *AssociationAPI { - return &AssociationAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, sendAPI: sendAPI} +func NewAssociationAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, sendAPI *SendAPI, connectionType ConnectionType) *AssociationAPI { + return &AssociationAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, sendAPI: sendAPI, connectionType: connectionType} } type AssociateRequest struct { @@ -38,7 +39,7 @@ type AssociateRequest struct { func (t *AssociationAPI) Associate(ctx context.Context, req *AssociateRequest) (returnErr error) { startTime := time.Now() - defer recordMetrics("sei_associate", startTime, returnErr == nil) + defer recordMetrics("sei_associate", t.connectionType, startTime, returnErr == nil) rBytes, err := decodeHexString(req.R) if err != nil { return err @@ -86,7 +87,7 @@ func (t *AssociationAPI) Associate(ctx context.Context, req *AssociateRequest) ( func (t *AssociationAPI) GetSeiAddress(_ context.Context, ethAddress common.Address) (result string, returnErr error) { startTime := time.Now() - defer recordMetrics("sei_getSeiAddress", startTime, returnErr == nil) + defer recordMetrics("sei_getSeiAddress", t.connectionType, startTime, returnErr == nil) seiAddress, found := t.keeper.GetSeiAddress(t.ctxProvider(LatestCtxHeight), ethAddress) if !found { return "", fmt.Errorf("failed to find Sei address for %s", ethAddress.Hex()) @@ -97,7 +98,7 @@ func (t *AssociationAPI) GetSeiAddress(_ context.Context, ethAddress common.Addr func (t *AssociationAPI) GetEVMAddress(_ context.Context, seiAddress string) (result string, returnErr error) { startTime := time.Now() - defer recordMetrics("sei_getEVMAddress", startTime, returnErr == nil) + defer recordMetrics("sei_getEVMAddress", t.connectionType, startTime, returnErr == nil) seiAddr, err := sdk.AccAddressFromBech32(seiAddress) if err != nil { return "", err diff --git a/evmrpc/block.go b/evmrpc/block.go index 246d2726b..81f834594 100644 --- a/evmrpc/block.go +++ b/evmrpc/block.go @@ -22,19 +22,20 @@ import ( ) type BlockAPI struct { - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - txConfig client.TxConfig + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + txConfig client.TxConfig + connectionType ConnectionType } -func NewBlockAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txConfig client.TxConfig) *BlockAPI { - return &BlockAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig} +func NewBlockAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txConfig client.TxConfig, connectionType ConnectionType) *BlockAPI { + return &BlockAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig, connectionType: connectionType} } func (a *BlockAPI) GetBlockTransactionCountByNumber(ctx context.Context, number rpc.BlockNumber) (result *hexutil.Uint, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getBlockTransactionCountByNumber", startTime, returnErr == nil) + defer recordMetrics("eth_getBlockTransactionCountByNumber", a.connectionType, startTime, returnErr == nil) numberPtr, err := getBlockNumber(ctx, a.tmClient, number) if err != nil { return nil, err @@ -48,7 +49,7 @@ func (a *BlockAPI) GetBlockTransactionCountByNumber(ctx context.Context, number func (a *BlockAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) (result *hexutil.Uint, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getBlockTransactionCountByHash", startTime, returnErr == nil) + defer recordMetrics("eth_getBlockTransactionCountByHash", a.connectionType, startTime, returnErr == nil) block, err := blockByHashWithRetry(ctx, a.tmClient, blockHash[:], 1) if err != nil { return nil, err @@ -58,7 +59,7 @@ func (a *BlockAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash func (a *BlockAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (result map[string]interface{}, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getBlockByHash", startTime, returnErr == nil) + defer recordMetrics("eth_getBlockByHash", a.connectionType, startTime, returnErr == nil) block, err := blockByHashWithRetry(ctx, a.tmClient, blockHash[:], 1) if err != nil { return nil, err @@ -72,7 +73,7 @@ func (a *BlockAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fu func (a *BlockAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (result map[string]interface{}, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getBlockByNumber", startTime, returnErr == nil) + defer recordMetrics("eth_getBlockByNumber", a.connectionType, startTime, returnErr == nil) numberPtr, err := getBlockNumber(ctx, a.tmClient, number) if err != nil { return nil, err @@ -90,7 +91,7 @@ func (a *BlockAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, func (a *BlockAPI) GetBlockReceipts(ctx context.Context, number rpc.BlockNumber) (result []map[string]interface{}, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getBlockReceipts", startTime, returnErr == nil) + defer recordMetrics("eth_getBlockReceipts", a.connectionType, startTime, returnErr == nil) // Get height from params heightPtr, err := getBlockNumber(ctx, a.tmClient, number) if err != nil { diff --git a/evmrpc/filter.go b/evmrpc/filter.go index 0cc359084..a8abee155 100644 --- a/evmrpc/filter.go +++ b/evmrpc/filter.go @@ -43,11 +43,12 @@ type filter struct { } type FilterAPI struct { - tmClient rpcclient.Client - filtersMu sync.Mutex - filters map[ethrpc.ID]filter - filterConfig *FilterConfig - logFetcher *LogFetcher + tmClient rpcclient.Client + filtersMu sync.Mutex + filters map[ethrpc.ID]filter + filterConfig *FilterConfig + logFetcher *LogFetcher + connectionType ConnectionType } type FilterConfig struct { @@ -61,15 +62,16 @@ type EventItemDataWrapper struct { Value json.RawMessage `json:"value"` } -func NewFilterAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, filterConfig *FilterConfig) *FilterAPI { +func NewFilterAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, filterConfig *FilterConfig, connectionType ConnectionType) *FilterAPI { logFetcher.filterConfig = filterConfig filters := make(map[ethrpc.ID]filter) api := &FilterAPI{ - tmClient: tmClient, - filtersMu: sync.Mutex{}, - filters: filters, - filterConfig: filterConfig, - logFetcher: logFetcher, + tmClient: tmClient, + filtersMu: sync.Mutex{}, + filters: filters, + filterConfig: filterConfig, + logFetcher: logFetcher, + connectionType: connectionType, } go api.timeoutLoop(filterConfig.timeout) @@ -99,7 +101,7 @@ func (a *FilterAPI) NewFilter( _ context.Context, crit filters.FilterCriteria, ) (id ethrpc.ID, err error) { - defer recordMetrics("eth_newFilter", time.Now(), err == nil) + defer recordMetrics("eth_newFilter", a.connectionType, time.Now(), err == nil) a.filtersMu.Lock() defer a.filtersMu.Unlock() curFilterID := ethrpc.NewID() @@ -115,7 +117,7 @@ func (a *FilterAPI) NewFilter( func (a *FilterAPI) NewBlockFilter( _ context.Context, ) (id ethrpc.ID, err error) { - defer recordMetrics("eth_newBlockFilter", time.Now(), err == nil) + defer recordMetrics("eth_newBlockFilter", a.connectionType, time.Now(), err == nil) a.filtersMu.Lock() defer a.filtersMu.Unlock() curFilterID := ethrpc.NewID() @@ -131,7 +133,7 @@ func (a *FilterAPI) GetFilterChanges( ctx context.Context, filterID ethrpc.ID, ) (res interface{}, err error) { - defer recordMetrics("eth_getFilterChanges", time.Now(), err == nil) + defer recordMetrics("eth_getFilterChanges", a.connectionType, time.Now(), err == nil) a.filtersMu.Lock() defer a.filtersMu.Unlock() filter, ok := a.filters[filterID] @@ -182,7 +184,7 @@ func (a *FilterAPI) GetFilterLogs( ctx context.Context, filterID ethrpc.ID, ) (res []*ethtypes.Log, err error) { - defer recordMetrics("eth_getFilterLogs", time.Now(), err == nil) + defer recordMetrics("eth_getFilterLogs", a.connectionType, time.Now(), err == nil) a.filtersMu.Lock() defer a.filtersMu.Unlock() filter, ok := a.filters[filterID] @@ -211,7 +213,7 @@ func (a *FilterAPI) GetLogs( ctx context.Context, crit filters.FilterCriteria, ) (res []*ethtypes.Log, err error) { - defer recordMetrics("eth_getLogs", time.Now(), err == nil) + defer recordMetrics("eth_getLogs", a.connectionType, time.Now(), err == nil) logs, _, err := a.logFetcher.GetLogsByFilters(ctx, crit, 0) return logs, err } @@ -258,7 +260,7 @@ func (a *FilterAPI) UninstallFilter( _ context.Context, filterID ethrpc.ID, ) (res bool) { - defer recordMetrics("eth_uninstallFilter", time.Now(), res) + defer recordMetrics("eth_uninstallFilter", a.connectionType, time.Now(), res) a.filtersMu.Lock() defer a.filtersMu.Unlock() _, found := a.filters[filterID] diff --git a/evmrpc/info.go b/evmrpc/info.go index e165cc3cf..89e391ad7 100644 --- a/evmrpc/info.go +++ b/evmrpc/info.go @@ -18,15 +18,16 @@ import ( ) type InfoAPI struct { - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - txDecoder sdk.TxDecoder - homeDir string + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + txDecoder sdk.TxDecoder + homeDir string + connectionType ConnectionType } -func NewInfoAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, homeDir string) *InfoAPI { - return &InfoAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, homeDir: homeDir} +func NewInfoAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, homeDir string, connectionType ConnectionType) *InfoAPI { + return &InfoAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, homeDir: homeDir, connectionType: connectionType} } type FeeHistoryResult struct { @@ -38,26 +39,26 @@ type FeeHistoryResult struct { func (i *InfoAPI) BlockNumber() hexutil.Uint64 { startTime := time.Now() - defer recordMetrics("eth_BlockNumber", startTime, true) + defer recordMetrics("eth_BlockNumber", i.connectionType, startTime, true) return hexutil.Uint64(i.ctxProvider(LatestCtxHeight).BlockHeight()) } //nolint:revive func (i *InfoAPI) ChainId() *hexutil.Big { startTime := time.Now() - defer recordMetrics("eth_ChainId", startTime, true) + defer recordMetrics("eth_ChainId", i.connectionType, startTime, true) return (*hexutil.Big)(i.keeper.ChainID(i.ctxProvider(LatestCtxHeight))) } func (i *InfoAPI) Coinbase() (common.Address, error) { startTime := time.Now() - defer recordMetrics("eth_Coinbase", startTime, true) + defer recordMetrics("eth_Coinbase", i.connectionType, startTime, true) return i.keeper.GetFeeCollectorAddress(i.ctxProvider(LatestCtxHeight)) } func (i *InfoAPI) Accounts() (result []common.Address, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_Accounts", startTime, returnErr == nil) + defer recordMetrics("eth_Accounts", i.connectionType, startTime, returnErr == nil) kb, err := getTestKeyring(i.homeDir) if err != nil { return []common.Address{}, err @@ -70,7 +71,7 @@ func (i *InfoAPI) Accounts() (result []common.Address, returnErr error) { func (i *InfoAPI) GasPrice(ctx context.Context) (result *hexutil.Big, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_GasPrice", startTime, returnErr == nil) + defer recordMetrics("eth_GasPrice", i.connectionType, startTime, returnErr == nil) // get fee history of the most recent block with 50% reward percentile feeHist, err := i.FeeHistory(ctx, 1, rpc.LatestBlockNumber, []float64{0.5}) if err != nil { @@ -89,7 +90,7 @@ func (i *InfoAPI) GasPrice(ctx context.Context) (result *hexutil.Big, returnErr // lastBlock is inclusive func (i *InfoAPI) FeeHistory(ctx context.Context, blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (result *FeeHistoryResult, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_feeHistory", startTime, returnErr == nil) + defer recordMetrics("eth_feeHistory", i.connectionType, startTime, returnErr == nil) result = &FeeHistoryResult{} // validate reward percentiles diff --git a/evmrpc/info_test.go b/evmrpc/info_test.go index 33fb2fe3a..4abe20680 100644 --- a/evmrpc/info_test.go +++ b/evmrpc/info_test.go @@ -28,7 +28,7 @@ func TestChainID(t *testing.T) { func TestAccounts(t *testing.T) { homeDir := t.TempDir() - api := evmrpc.NewInfoAPI(nil, nil, nil, nil, homeDir) + api := evmrpc.NewInfoAPI(nil, nil, nil, nil, homeDir, evmrpc.ConnectionTypeHTTP) clientCtx := client.Context{}.WithViper("").WithHomeDir(homeDir) clientCtx, err := config.ReadFromClientConfig(clientCtx) require.Nil(t, err) diff --git a/evmrpc/net.go b/evmrpc/net.go index 9bc603cc8..4db5d6ec9 100644 --- a/evmrpc/net.go +++ b/evmrpc/net.go @@ -10,18 +10,19 @@ import ( ) type NetAPI struct { - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - txDecoder sdk.TxDecoder + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + txDecoder sdk.TxDecoder + connectionType ConnectionType } -func NewNetAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder) *NetAPI { - return &NetAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder} +func NewNetAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, connectionType ConnectionType) *NetAPI { + return &NetAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, connectionType: connectionType} } func (i *NetAPI) Version() string { startTime := time.Now() - defer recordMetrics("net_version", startTime, true) + defer recordMetrics("net_version", i.connectionType, startTime, true) return fmt.Sprintf("%d", i.keeper.ChainID(i.ctxProvider(LatestCtxHeight)).Uint64()) } diff --git a/evmrpc/rpcstack.go b/evmrpc/rpcstack.go index 847495aac..a1ec50835 100644 --- a/evmrpc/rpcstack.go +++ b/evmrpc/rpcstack.go @@ -31,6 +31,7 @@ import ( "time" "github.com/ethereum/go-ethereum/rpc" + "github.com/gorilla/websocket" "github.com/rs/cors" "github.com/tendermint/tendermint/libs/log" ) @@ -202,7 +203,7 @@ func (h *HTTPServer) Start() error { func (h *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { // check if ws request and serve if ws enabled ws := h.wsHandler.Load().(*rpcHandler) - if ws != nil && IsWebsocket(r) { + if ws != nil && websocket.IsWebSocketUpgrade(r) { if CheckPath(r, h.WsConfig.prefix) { ws.ServeHTTP(w, r) } @@ -374,12 +375,6 @@ func (h *HTTPServer) wsAllowed() bool { return h.wsHandler.Load().(*rpcHandler) != nil } -// IsWebsocket checks the header of an http request for a websocket upgrade request. -func IsWebsocket(r *http.Request) bool { - return strings.EqualFold(r.Header.Get("Upgrade"), "websocket") && - strings.Contains(strings.ToLower(r.Header.Get("Connection")), "upgrade") -} - // NewHTTPHandlerStack returns wrapped http-related handlers func NewHTTPHandlerStack(srv http.Handler, cors []string, vhosts []string, JwtSecret []byte) http.Handler { // Wrap the CORS-handler within a host-handler @@ -394,9 +389,9 @@ func NewHTTPHandlerStack(srv http.Handler, cors []string, vhosts []string, JwtSe // NewWSHandlerStack returns a wrapped ws-related handler. func NewWSHandlerStack(srv http.Handler, JwtSecret []byte) http.Handler { if len(JwtSecret) != 0 { - return newJWTHandler(JwtSecret, srv) + return NewWSConnectionHandler(newJWTHandler(JwtSecret, srv)) } - return srv + return NewWSConnectionHandler(srv) } func newCorsHandler(srv http.Handler, allowedOrigins []string) http.Handler { diff --git a/evmrpc/rpcstack_test.go b/evmrpc/rpcstack_test.go index b080d08d2..774928e78 100644 --- a/evmrpc/rpcstack_test.go +++ b/evmrpc/rpcstack_test.go @@ -165,21 +165,6 @@ func TestWebsocketOrigins(t *testing.T) { } } -// Testevmrpc.IsWebsocket tests if an incoming websocket upgrade request is handled properly. -func TestIsWebsocket(t *testing.T) { - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - assert.False(t, evmrpc.IsWebsocket(r)) - r.Header.Set("upgrade", "websocket") - assert.False(t, evmrpc.IsWebsocket(r)) - r.Header.Set("connection", "upgrade") - assert.True(t, evmrpc.IsWebsocket(r)) - r.Header.Set("connection", "upgrade,keep-alive") - assert.True(t, evmrpc.IsWebsocket(r)) - r.Header.Set("connection", " UPGRADE,keep-alive") - assert.True(t, evmrpc.IsWebsocket(r)) -} - func Test_CheckPath(t *testing.T) { tests := []struct { req *http.Request diff --git a/evmrpc/send.go b/evmrpc/send.go index ec388d84c..7bbb7e508 100644 --- a/evmrpc/send.go +++ b/evmrpc/send.go @@ -20,34 +20,36 @@ import ( ) type SendAPI struct { - tmClient rpcclient.Client - txConfig client.TxConfig - sendConfig *SendConfig - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - homeDir string - backend *Backend + tmClient rpcclient.Client + txConfig client.TxConfig + sendConfig *SendConfig + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + homeDir string + backend *Backend + connectionType ConnectionType } type SendConfig struct { slow bool } -func NewSendAPI(tmClient rpcclient.Client, txConfig client.TxConfig, sendConfig *SendConfig, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, homeDir string, simulateConfig *SimulateConfig) *SendAPI { +func NewSendAPI(tmClient rpcclient.Client, txConfig client.TxConfig, sendConfig *SendConfig, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, homeDir string, simulateConfig *SimulateConfig, connectionType ConnectionType) *SendAPI { return &SendAPI{ - tmClient: tmClient, - txConfig: txConfig, - sendConfig: sendConfig, - keeper: k, - ctxProvider: ctxProvider, - homeDir: homeDir, - backend: NewBackend(ctxProvider, k, txConfig.TxDecoder(), tmClient, simulateConfig), + tmClient: tmClient, + txConfig: txConfig, + sendConfig: sendConfig, + keeper: k, + ctxProvider: ctxProvider, + homeDir: homeDir, + backend: NewBackend(ctxProvider, k, txConfig.TxDecoder(), tmClient, simulateConfig), + connectionType: connectionType, } } func (s *SendAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (hash common.Hash, err error) { startTime := time.Now() - defer recordMetrics("eth_sendRawTransaction", startTime, err == nil) + defer recordMetrics("eth_sendRawTransaction", s.connectionType, startTime, err == nil) tx := new(ethtypes.Transaction) if err = tx.UnmarshalBinary(input); err != nil { return @@ -94,7 +96,7 @@ func (s *SendAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) ( func (s *SendAPI) SignTransaction(_ context.Context, args apitypes.SendTxArgs, _ *string) (result *ethapi.SignTransactionResult, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_signTransaction", startTime, returnErr == nil) + defer recordMetrics("eth_signTransaction", s.connectionType, startTime, returnErr == nil) var unsignedTx = args.ToTransaction() signedTx, err := s.signTransaction(unsignedTx, args.From.Address().Hex()) if err != nil { @@ -109,7 +111,7 @@ func (s *SendAPI) SignTransaction(_ context.Context, args apitypes.SendTxArgs, _ func (s *SendAPI) SendTransaction(ctx context.Context, args ethapi.TransactionArgs) (result common.Hash, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_sendTransaction", startTime, returnErr == nil) + defer recordMetrics("eth_sendTransaction", s.connectionType, startTime, returnErr == nil) if err := args.SetDefaults(ctx, s.backend); err != nil { return common.Hash{}, err } diff --git a/evmrpc/server.go b/evmrpc/server.go index 74234d14e..dfa7156eb 100644 --- a/evmrpc/server.go +++ b/evmrpc/server.go @@ -11,6 +11,11 @@ import ( rpcclient "github.com/tendermint/tendermint/rpc/client" ) +type ConnectionType string + +var ConnectionTypeWS ConnectionType = "websocket" +var ConnectionTypeHTTP ConnectionType = "http" + const LocalAddress = "0.0.0.0" type EVMServer interface { @@ -36,7 +41,7 @@ func NewEVMHTTPServer( return nil, err } simulateConfig := &SimulateConfig{GasCap: config.SimulationGasLimit, EVMTimeout: config.SimulationEVMTimeout} - sendAPI := NewSendAPI(tmClient, txConfig, &SendConfig{slow: config.Slow}, k, ctxProvider, homeDir, simulateConfig) + sendAPI := NewSendAPI(tmClient, txConfig, &SendConfig{slow: config.Slow}, k, ctxProvider, homeDir, simulateConfig, ConnectionTypeHTTP) apis := []rpc.API{ { Namespace: "echo", @@ -44,19 +49,19 @@ func NewEVMHTTPServer( }, { Namespace: "eth", - Service: NewBlockAPI(tmClient, k, ctxProvider, txConfig), + Service: NewBlockAPI(tmClient, k, ctxProvider, txConfig, ConnectionTypeHTTP), }, { Namespace: "eth", - Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir), + Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeHTTP), }, { Namespace: "eth", - Service: NewStateAPI(tmClient, k, ctxProvider), + Service: NewStateAPI(tmClient, k, ctxProvider, ConnectionTypeHTTP), }, { Namespace: "eth", - Service: NewInfoAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), homeDir), + Service: NewInfoAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), homeDir, ConnectionTypeHTTP), }, { Namespace: "eth", @@ -64,23 +69,23 @@ func NewEVMHTTPServer( }, { Namespace: "eth", - Service: NewSimulationAPI(ctxProvider, k, txConfig.TxDecoder(), tmClient, simulateConfig), + Service: NewSimulationAPI(ctxProvider, k, txConfig.TxDecoder(), tmClient, simulateConfig, ConnectionTypeHTTP), }, { Namespace: "net", - Service: NewNetAPI(tmClient, k, ctxProvider, txConfig.TxDecoder()), + Service: NewNetAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), ConnectionTypeHTTP), }, { Namespace: "eth", - Service: NewFilterAPI(tmClient, &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider}, &FilterConfig{timeout: config.FilterTimeout, maxLog: config.MaxLogNoBlock, maxBlock: config.MaxBlocksForLog}), + Service: NewFilterAPI(tmClient, &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider}, &FilterConfig{timeout: config.FilterTimeout, maxLog: config.MaxLogNoBlock, maxBlock: config.MaxBlocksForLog}, ConnectionTypeHTTP), }, { Namespace: "sei", - Service: NewAssociationAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), sendAPI), + Service: NewAssociationAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), sendAPI, ConnectionTypeHTTP), }, { Namespace: "txpool", - Service: NewTxPoolAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), &TxPoolConfig{maxNumTxs: int(config.MaxTxPoolTxs)}), + Service: NewTxPoolAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), &TxPoolConfig{maxNumTxs: int(config.MaxTxPoolTxs)}, ConnectionTypeHTTP), }, { Namespace: "web3", @@ -88,7 +93,7 @@ func NewEVMHTTPServer( }, { Namespace: "debug", - Service: NewDebugAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), simulateConfig), + Service: NewDebugAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), simulateConfig, ConnectionTypeHTTP), }, } if err := httpServer.EnableRPC(apis, HTTPConfig{ @@ -126,35 +131,35 @@ func NewEVMWebSocketServer( }, { Namespace: "eth", - Service: NewBlockAPI(tmClient, k, ctxProvider, txConfig), + Service: NewBlockAPI(tmClient, k, ctxProvider, txConfig, ConnectionTypeWS), }, { Namespace: "eth", - Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir), + Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeWS), }, { Namespace: "eth", - Service: NewStateAPI(tmClient, k, ctxProvider), + Service: NewStateAPI(tmClient, k, ctxProvider, ConnectionTypeWS), }, { Namespace: "eth", - Service: NewInfoAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), homeDir), + Service: NewInfoAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), homeDir, ConnectionTypeWS), }, { Namespace: "eth", - Service: NewSendAPI(tmClient, txConfig, &SendConfig{slow: config.Slow}, k, ctxProvider, homeDir, simulateConfig), + Service: NewSendAPI(tmClient, txConfig, &SendConfig{slow: config.Slow}, k, ctxProvider, homeDir, simulateConfig, ConnectionTypeWS), }, { Namespace: "eth", - Service: NewSimulationAPI(ctxProvider, k, txConfig.TxDecoder(), tmClient, simulateConfig), + Service: NewSimulationAPI(ctxProvider, k, txConfig.TxDecoder(), tmClient, simulateConfig, ConnectionTypeWS), }, { Namespace: "net", - Service: NewNetAPI(tmClient, k, ctxProvider, txConfig.TxDecoder()), + Service: NewNetAPI(tmClient, k, ctxProvider, txConfig.TxDecoder(), ConnectionTypeWS), }, { Namespace: "eth", - Service: NewSubscriptionAPI(tmClient, &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider}, &SubscriptionConfig{subscriptionCapacity: 100, newHeadLimit: config.MaxSubscriptionsNewHead}, &FilterConfig{timeout: config.FilterTimeout, maxLog: config.MaxLogNoBlock, maxBlock: config.MaxBlocksForLog}), + Service: NewSubscriptionAPI(tmClient, &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider}, &SubscriptionConfig{subscriptionCapacity: 100, newHeadLimit: config.MaxSubscriptionsNewHead}, &FilterConfig{timeout: config.FilterTimeout, maxLog: config.MaxLogNoBlock, maxBlock: config.MaxBlocksForLog}, ConnectionTypeWS), }, { Namespace: "web3", diff --git a/evmrpc/simulate.go b/evmrpc/simulate.go index 971c21542..f5067ccf8 100644 --- a/evmrpc/simulate.go +++ b/evmrpc/simulate.go @@ -32,7 +32,8 @@ import ( ) type SimulationAPI struct { - backend *Backend + backend *Backend + connectionType ConnectionType } func NewSimulationAPI( @@ -41,9 +42,11 @@ func NewSimulationAPI( txDecoder sdk.TxDecoder, tmClient rpcclient.Client, config *SimulateConfig, + connectionType ConnectionType, ) *SimulationAPI { return &SimulationAPI{ - backend: NewBackend(ctxProvider, keeper, txDecoder, tmClient, config), + backend: NewBackend(ctxProvider, keeper, txDecoder, tmClient, config), + connectionType: connectionType, } } @@ -55,7 +58,7 @@ type AccessListResult struct { func (s *SimulationAPI) CreateAccessList(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (result *AccessListResult, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_createAccessList", startTime, returnErr == nil) + defer recordMetrics("eth_createAccessList", s.connectionType, startTime, returnErr == nil) bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) if blockNrOrHash != nil { bNrOrHash = *blockNrOrHash @@ -73,7 +76,7 @@ func (s *SimulationAPI) CreateAccessList(ctx context.Context, args ethapi.Transa func (s *SimulationAPI) EstimateGas(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *ethapi.StateOverride) (result hexutil.Uint64, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_estimateGas", startTime, returnErr == nil) + defer recordMetrics("eth_estimateGas", s.connectionType, startTime, returnErr == nil) bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) if blockNrOrHash != nil { bNrOrHash = *blockNrOrHash @@ -84,7 +87,7 @@ func (s *SimulationAPI) EstimateGas(ctx context.Context, args ethapi.Transaction func (s *SimulationAPI) Call(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *ethapi.StateOverride, blockOverrides *ethapi.BlockOverrides) (result hexutil.Bytes, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_call", startTime, returnErr == nil) + defer recordMetrics("eth_call", s.connectionType, startTime, returnErr == nil) if blockNrOrHash == nil { latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) blockNrOrHash = &latest diff --git a/evmrpc/state.go b/evmrpc/state.go index 7b5a73f63..fb9ac389b 100644 --- a/evmrpc/state.go +++ b/evmrpc/state.go @@ -24,18 +24,19 @@ import ( ) type StateAPI struct { - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + connectionType ConnectionType } -func NewStateAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context) *StateAPI { - return &StateAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider} +func NewStateAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, connectionType ConnectionType) *StateAPI { + return &StateAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, connectionType: connectionType} } func (a *StateAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (result *hexutil.Big, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getBalance", startTime, returnErr == nil) + defer recordMetrics("eth_getBalance", a.connectionType, startTime, returnErr == nil) block, err := GetBlockNumberByNrOrHash(ctx, a.tmClient, blockNrOrHash) if err != nil { return nil, err @@ -53,7 +54,7 @@ func (a *StateAPI) GetBalance(ctx context.Context, address common.Address, block func (a *StateAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (result hexutil.Bytes, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getCode", startTime, returnErr == nil) + defer recordMetrics("eth_getCode", a.connectionType, startTime, returnErr == nil) block, err := GetBlockNumberByNrOrHash(ctx, a.tmClient, blockNrOrHash) if err != nil { return nil, err @@ -71,7 +72,7 @@ func (a *StateAPI) GetCode(ctx context.Context, address common.Address, blockNrO func (a *StateAPI) GetStorageAt(ctx context.Context, address common.Address, hexKey string, blockNrOrHash rpc.BlockNumberOrHash) (result hexutil.Bytes, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getStorageAt", startTime, returnErr == nil) + defer recordMetrics("eth_getStorageAt", a.connectionType, startTime, returnErr == nil) block, err := GetBlockNumberByNrOrHash(ctx, a.tmClient, blockNrOrHash) if err != nil { return nil, err @@ -103,7 +104,7 @@ type ProofResult struct { func (a *StateAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (result *ProofResult, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getProof", startTime, returnErr == nil) + defer recordMetrics("eth_getProof", a.connectionType, startTime, returnErr == nil) var block *coretypes.ResultBlock var err error if blockNr, ok := blockNrOrHash.Number(); ok { @@ -158,7 +159,7 @@ OUTER: func (a *StateAPI) GetNonce(_ context.Context, address common.Address) uint64 { startTime := time.Now() - defer recordMetrics("eth_getNonce", startTime, true) + defer recordMetrics("eth_getNonce", a.connectionType, startTime, true) return a.keeper.GetNonce(a.ctxProvider(LatestCtxHeight), address) } diff --git a/evmrpc/state_test.go b/evmrpc/state_test.go index a6801984f..abcd6c9d8 100644 --- a/evmrpc/state_test.go +++ b/evmrpc/state_test.go @@ -216,7 +216,7 @@ func TestGetProof(t *testing.T) { _, err := testApp.Commit(context.Background()) require.Nil(t, err) } - stateAPI := evmrpc.NewStateAPI(&MockClient{}, &testApp.EvmKeeper, func(int64) sdk.Context { return testApp.GetCheckCtx() }) + stateAPI := evmrpc.NewStateAPI(&MockClient{}, &testApp.EvmKeeper, func(int64) sdk.Context { return testApp.GetCheckCtx() }, evmrpc.ConnectionTypeHTTP) require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000616263", testApp.EvmKeeper.GetState(testApp.GetCheckCtx(), evmAddr, common.BytesToHash(key)).Hex()) tests := []struct { key string diff --git a/evmrpc/subscribe.go b/evmrpc/subscribe.go index 44a7385d7..b2abb4303 100644 --- a/evmrpc/subscribe.go +++ b/evmrpc/subscribe.go @@ -29,6 +29,7 @@ type SubscriptionAPI struct { logFetcher *LogFetcher newHeadListenersMtx *sync.RWMutex newHeadListeners map[rpc.ID]chan map[string]interface{} + connectionType ConnectionType } type SubscriptionConfig struct { @@ -36,7 +37,7 @@ type SubscriptionConfig struct { newHeadLimit uint64 } -func NewSubscriptionAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, subscriptionConfig *SubscriptionConfig, filterConfig *FilterConfig) *SubscriptionAPI { +func NewSubscriptionAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, subscriptionConfig *SubscriptionConfig, filterConfig *FilterConfig, connectionType ConnectionType) *SubscriptionAPI { logFetcher.filterConfig = filterConfig api := &SubscriptionAPI{ tmClient: tmClient, @@ -45,6 +46,7 @@ func NewSubscriptionAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, subsc logFetcher: logFetcher, newHeadListenersMtx: &sync.RWMutex{}, newHeadListeners: make(map[rpc.ID]chan map[string]interface{}), + connectionType: connectionType, } id, subCh, err := api.subscriptionManager.Subscribe(context.Background(), NewHeadQueryBuilder(), api.subscriptonConfig.subscriptionCapacity) if err != nil { @@ -81,7 +83,7 @@ func NewSubscriptionAPI(tmClient rpcclient.Client, logFetcher *LogFetcher, subsc } func (a *SubscriptionAPI) NewHeads(ctx context.Context) (s *rpc.Subscription, err error) { - defer recordMetrics("eth_newHeads", time.Now(), err == nil) + defer recordMetrics("eth_newHeads", a.connectionType, time.Now(), err == nil) notifier, supported := rpc.NotifierFromContext(ctx) if !supported { return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported @@ -121,7 +123,7 @@ func (a *SubscriptionAPI) NewHeads(ctx context.Context) (s *rpc.Subscription, er } func (a *SubscriptionAPI) Logs(ctx context.Context, filter *filters.FilterCriteria) (s *rpc.Subscription, err error) { - defer recordMetrics("eth_logs", time.Now(), err == nil) + defer recordMetrics("eth_logs", a.connectionType, time.Now(), err == nil) notifier, supported := rpc.NotifierFromContext(ctx) if !supported { return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported diff --git a/evmrpc/tracers.go b/evmrpc/tracers.go index 303f41d82..0f46916b8 100644 --- a/evmrpc/tracers.go +++ b/evmrpc/tracers.go @@ -14,33 +14,34 @@ import ( ) type DebugAPI struct { - tracersAPI *tracers.API - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - txDecoder sdk.TxDecoder + tracersAPI *tracers.API + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + txDecoder sdk.TxDecoder + connectionType ConnectionType } -func NewDebugAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, config *SimulateConfig) *DebugAPI { +func NewDebugAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, config *SimulateConfig, connectionType ConnectionType) *DebugAPI { backend := NewBackend(ctxProvider, k, txDecoder, tmClient, config) tracersAPI := tracers.NewAPI(backend) - return &DebugAPI{tracersAPI: tracersAPI, tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder} + return &DebugAPI{tracersAPI: tracersAPI, tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, connectionType: connectionType} } func (api *DebugAPI) TraceTransaction(ctx context.Context, hash common.Hash, config *tracers.TraceConfig) (interface{}, error) { startTime := time.Now() - defer recordMetrics("debug_traceTransaction", startTime, true) + defer recordMetrics("debug_traceTransaction", api.connectionType, startTime, true) return api.tracersAPI.TraceTransaction(ctx, hash, config) } func (api *DebugAPI) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *tracers.TraceConfig) (interface{}, error) { startTime := time.Now() - defer recordMetrics("debug_traceBlockByNumber", startTime, true) + defer recordMetrics("debug_traceBlockByNumber", api.connectionType, startTime, true) return api.tracersAPI.TraceBlockByNumber(ctx, number, config) } func (api *DebugAPI) TraceBlockByHash(ctx context.Context, hash common.Hash, config *tracers.TraceConfig) (interface{}, error) { startTime := time.Now() - defer recordMetrics("debug_traceBlockByHash", startTime, true) + defer recordMetrics("debug_traceBlockByHash", api.connectionType, startTime, true) return api.tracersAPI.TraceBlockByHash(ctx, hash, config) } diff --git a/evmrpc/tx.go b/evmrpc/tx.go index e789cffc2..16164cfa7 100644 --- a/evmrpc/tx.go +++ b/evmrpc/tx.go @@ -26,20 +26,21 @@ const UnconfirmedTxQueryMaxPage = 20 const UnconfirmedTxQueryPerPage = 30 type TransactionAPI struct { - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - txConfig client.TxConfig - homeDir string + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + txConfig client.TxConfig + homeDir string + connectionType ConnectionType } -func NewTransactionAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txConfig client.TxConfig, homeDir string) *TransactionAPI { - return &TransactionAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig, homeDir: homeDir} +func NewTransactionAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txConfig client.TxConfig, homeDir string, connectionType ConnectionType) *TransactionAPI { + return &TransactionAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig, homeDir: homeDir, connectionType: connectionType} } func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (result map[string]interface{}, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getTransactionReceipt", startTime, returnErr == nil) + defer recordMetrics("eth_getTransactionReceipt", t.connectionType, startTime, returnErr == nil) receipt, err := t.keeper.GetReceipt(t.ctxProvider(LatestCtxHeight), hash) if err != nil { if strings.Contains(err.Error(), "not found") { @@ -59,7 +60,7 @@ func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. func (t *TransactionAPI) GetVMError(hash common.Hash) (result string, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getVMError", startTime, true) + defer recordMetrics("eth_getVMError", t.connectionType, startTime, true) receipt, err := t.keeper.GetReceipt(t.ctxProvider(LatestCtxHeight), hash) if err != nil { return "", err @@ -69,7 +70,7 @@ func (t *TransactionAPI) GetVMError(hash common.Hash) (result string, returnErr func (t *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (result *RPCTransaction, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getTransactionByBlockNumberAndIndex", startTime, returnErr == nil) + defer recordMetrics("eth_getTransactionByBlockNumberAndIndex", t.connectionType, startTime, returnErr == nil) blockNumber, err := getBlockNumber(ctx, t.tmClient, blockNr) if err != nil { return nil, err @@ -83,7 +84,7 @@ func (t *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context func (t *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (result *RPCTransaction, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getTransactionByBlockHashAndIndex", startTime, returnErr == nil) + defer recordMetrics("eth_getTransactionByBlockHashAndIndex", t.connectionType, startTime, returnErr == nil) block, err := blockByHash(ctx, t.tmClient, blockHash[:]) if err != nil { return nil, err @@ -93,7 +94,7 @@ func (t *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, func (t *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (result *RPCTransaction, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getTransactionByHash", startTime, returnErr == nil) + defer recordMetrics("eth_getTransactionByHash", t.connectionType, startTime, returnErr == nil) sdkCtx := t.ctxProvider(LatestCtxHeight) // first try get from mempool for page := 1; page <= UnconfirmedTxQueryMaxPage; page++ { @@ -143,7 +144,7 @@ func (t *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H func (t *TransactionAPI) GetTransactionErrorByHash(_ context.Context, hash common.Hash) (result string, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getTransactionErrorByHash", startTime, returnErr == nil) + defer recordMetrics("eth_getTransactionErrorByHash", t.connectionType, startTime, returnErr == nil) receipt, err := t.keeper.GetReceipt(t.ctxProvider(LatestCtxHeight), hash) if err != nil { if strings.Contains(err.Error(), "not found") { @@ -156,7 +157,7 @@ func (t *TransactionAPI) GetTransactionErrorByHash(_ context.Context, hash commo func (t *TransactionAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (result *hexutil.Uint64, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_getTransactionCount", startTime, returnErr == nil) + defer recordMetrics("eth_getTransactionCount", t.connectionType, startTime, returnErr == nil) sdkCtx := t.ctxProvider(LatestCtxHeight) var pending bool @@ -198,7 +199,7 @@ func (t *TransactionAPI) getTransactionWithBlock(block *coretypes.ResultBlock, i func (t *TransactionAPI) Sign(addr common.Address, data hexutil.Bytes) (result hexutil.Bytes, returnErr error) { startTime := time.Now() - defer recordMetrics("eth_sign", startTime, returnErr == nil) + defer recordMetrics("eth_sign", t.connectionType, startTime, returnErr == nil) kb, err := getTestKeyring(t.homeDir) if err != nil { return nil, err diff --git a/evmrpc/tx_test.go b/evmrpc/tx_test.go index 50a26c373..cb88886c0 100644 --- a/evmrpc/tx_test.go +++ b/evmrpc/tx_test.go @@ -225,8 +225,8 @@ func TestGetTransactionError(t *testing.T) { func TestSign(t *testing.T) { homeDir := t.TempDir() - txApi := evmrpc.NewTransactionAPI(nil, nil, nil, nil, homeDir) - infoApi := evmrpc.NewInfoAPI(nil, nil, nil, nil, homeDir) + txApi := evmrpc.NewTransactionAPI(nil, nil, nil, nil, homeDir, evmrpc.ConnectionTypeHTTP) + infoApi := evmrpc.NewInfoAPI(nil, nil, nil, nil, homeDir, evmrpc.ConnectionTypeHTTP) clientCtx := client.Context{}.WithViper("").WithHomeDir(homeDir) clientCtx, err := config.ReadFromClientConfig(clientCtx) require.Nil(t, err) diff --git a/evmrpc/txpool.go b/evmrpc/txpool.go index 48f8f8f16..8f77d996a 100644 --- a/evmrpc/txpool.go +++ b/evmrpc/txpool.go @@ -14,25 +14,26 @@ import ( ) type TxPoolAPI struct { - tmClient rpcclient.Client - keeper *keeper.Keeper - ctxProvider func(int64) sdk.Context - txDecoder sdk.TxDecoder - txPoolConfig *TxPoolConfig + tmClient rpcclient.Client + keeper *keeper.Keeper + ctxProvider func(int64) sdk.Context + txDecoder sdk.TxDecoder + txPoolConfig *TxPoolConfig + connectionType ConnectionType } type TxPoolConfig struct { maxNumTxs int } -func NewTxPoolAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, txPoolConfig *TxPoolConfig) *TxPoolAPI { - return &TxPoolAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, txPoolConfig: txPoolConfig} +func NewTxPoolAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txDecoder sdk.TxDecoder, txPoolConfig *TxPoolConfig, connectionType ConnectionType) *TxPoolAPI { + return &TxPoolAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txDecoder: txDecoder, txPoolConfig: txPoolConfig, connectionType: connectionType} } // For now, we put all unconfirmed txs in pending and none in queued func (t *TxPoolAPI) Content(ctx context.Context) (result map[string]map[string]map[string]*RPCTransaction, returnErr error) { startTime := time.Now() - defer recordMetrics("sei_content", startTime, returnErr == nil) + defer recordMetrics("sei_content", t.connectionType, startTime, returnErr == nil) content := map[string]map[string]map[string]*RPCTransaction{ "pending": make(map[string]map[string]*RPCTransaction), "queued": make(map[string]map[string]*RPCTransaction), diff --git a/evmrpc/utils.go b/evmrpc/utils.go index f39bf9b3c..7b4c84aae 100644 --- a/evmrpc/utils.go +++ b/evmrpc/utils.go @@ -278,9 +278,9 @@ func blockByHashWithRetry(ctx context.Context, client rpcclient.Client, hash byt return blockRes, err } -func recordMetrics(apiMethod string, startTime time.Time, success bool) { - metrics.IncrementRpcRequestCounter(apiMethod, success) - metrics.MeasureRpcRequestLatency(apiMethod, startTime) +func recordMetrics(apiMethod string, connectionType ConnectionType, startTime time.Time, success bool) { + metrics.IncrementRpcRequestCounter(apiMethod, string(connectionType), success) + metrics.MeasureRpcRequestLatency(apiMethod, string(connectionType), startTime) } func CheckVersion(ctx sdk.Context, k *keeper.Keeper) error { diff --git a/evmrpc/websockets.go b/evmrpc/websockets.go new file mode 100644 index 000000000..a822c4650 --- /dev/null +++ b/evmrpc/websockets.go @@ -0,0 +1,20 @@ +package evmrpc + +import ( + "net/http" + + "github.com/sei-protocol/sei-chain/utils/metrics" +) + +type wsConnectionHandler struct { + underlying http.Handler +} + +func (h *wsConnectionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + metrics.IncWebsocketConnects() + h.underlying.ServeHTTP(w, r) +} + +func NewWSConnectionHandler(handler http.Handler) http.Handler { + return &wsConnectionHandler{underlying: handler} +} diff --git a/utils/metrics/metrics_util.go b/utils/metrics/metrics_util.go index ae9d625ae..ebe51bc6b 100644 --- a/utils/metrics/metrics_util.go +++ b/utils/metrics/metrics_util.go @@ -164,6 +164,18 @@ func SetThroughputMetric(metricName string, value float32) { ) } +// Measures number of new websocket connects +// Metric Name: +// +// sei_websocket_connect +func IncWebsocketConnects() { + telemetry.IncrCounterWithLabels( + []string{"sei", "websocket", "connect"}, + 1, + nil, + ) +} + // Measures number of times a denom's price is updated // Metric Name: // @@ -252,12 +264,13 @@ func IncrementOptimisticProcessingCounter(enabled bool) { // Metric Name: // // sei_rpc_request_counter -func IncrementRpcRequestCounter(endpoint string, success bool) { +func IncrementRpcRequestCounter(endpoint string, connectionType string, success bool) { telemetry.IncrCounterWithLabels( []string{"sei", "rpc", "request", "counter"}, float32(1), []metrics.Label{ telemetry.NewLabel("endpoint", endpoint), + telemetry.NewLabel("connection", connectionType), telemetry.NewLabel("success", strconv.FormatBool(success)), }, ) @@ -267,11 +280,14 @@ func IncrementRpcRequestCounter(endpoint string, success bool) { // Metric Name: // // sei_rpc_request_latency_ms -func MeasureRpcRequestLatency(endpoint string, startTime time.Time) { +func MeasureRpcRequestLatency(endpoint string, connectionType string, startTime time.Time) { metrics.MeasureSinceWithLabels( []string{"sei", "rpc", "request", "latency_ms"}, startTime.UTC(), - []metrics.Label{telemetry.NewLabel("endpoint", endpoint)}, + []metrics.Label{ + telemetry.NewLabel("endpoint", endpoint), + telemetry.NewLabel("connection", connectionType), + }, ) } From adfcc526eb286405541c7ba19f1577a007849478 Mon Sep 17 00:00:00 2001 From: Philip Su Date: Thu, 2 May 2024 15:00:39 -0700 Subject: [PATCH 4/4] V5.2.0 release (#1623) * add upgrade * [EVM] Add websocket metrics (#1621) * add websocket connection metrics * add websocket metrics by request * go imports * Add changelog --------- Co-authored-by: Steven Landers --- CHANGELOG.md | 20 ++++++++++++++++++++ app/upgrades.go | 1 + 2 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0f6613a1..928df9d37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,26 @@ Ref: https://keepachangelog.com/en/1.0.0/ --> # Changelog +## v5.2.0 +sei-chain +* [#1621](https://github.com/sei-protocol/sei-chain/pull/1621) Add websocket metrics +* [#1619](https://github.com/sei-protocol/sei-chain/pull/1619) Limit number of subscriptions +* [#1618](https://github.com/sei-protocol/sei-chain/pull/1618) Fix contract deploy receipts +* [#1615](https://github.com/sei-protocol/sei-chain/pull/1615) Optimize websocket newHead by reusing tendermint subscription +* [#1609](https://github.com/sei-protocol/sei-chain/pull/1609) Add association logic to simulate endpoints +* [#1605](https://github.com/sei-protocol/sei-chain/pull/1605) Disallow sr25519 addresses for evm functions +* [#1606](https://github.com/sei-protocol/sei-chain/pull/1606) SKip evm antehandler on sr25519 signatures + +sei-cosmos: +* [#495](https://github.com/sei-protocol/sei-cosmos/pull/495) Fix seid keys list by ignoring evm-addr for sr25519 +* [#493](https://github.com/sei-protocol/sei-cosmos/pull/493) Remove non-multiplier gas meter + +sei-tendermint: +* [#235](https://github.com/sei-protocol/sei-tendermint/pull/235) Check removed including wrapped tx state + +sei-db: +* [#63](https://github.com/sei-protocol/sei-db/pull/63) Fix edge case for iterating over tombstoned value + ## v5.0.1 sei-chain [#1577](https://github.com/sei-protocol/sei-chain/pull/1577) Re-enable Cancun diff --git a/app/upgrades.go b/app/upgrades.go index 5c1f471e7..f0bf59d4e 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -93,6 +93,7 @@ var upgradesList = []string{ "v5.0.0", "v5.0.1", "v5.1.0", + "v5.2.0", } // if there is an override list, use that instead, for integration tests