From 455ea1013cacd2540d2e2e721a85a08d0bbd77b9 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 5 Sep 2024 13:32:20 +0700 Subject: [PATCH 1/3] fix tests which were broken by new flag `--allow-insecure-unlock` --- integration_test_util/chain_suite.go | 2 ++ rpc/backend/backend.go | 1 + rpc/backend/backend_suite_test.go | 1 + rpc/backend/node_info.go | 9 +++++++++ 4 files changed, 13 insertions(+) diff --git a/integration_test_util/chain_suite.go b/integration_test_util/chain_suite.go index 620a6cdb42..85617548e7 100644 --- a/integration_test_util/chain_suite.go +++ b/integration_test_util/chain_suite.go @@ -480,6 +480,8 @@ func (suite *ChainIntegrationTestSuite) RpcBackendAt(height int64) *rpcbackend.B Elem(). Set(reflect.ValueOf(queryClients.Rpc)) + rpcBackend.AllowInsecureUnlock(true) + return rpcBackend } diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 0564e4417f..8c4c055c19 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -51,6 +51,7 @@ type EVMBackend interface { ListAccounts() ([]common.Address, error) NewMnemonic(uid string, language keyring.Language, hdPath, bip39Passphrase string, algo keyring.SignatureAlgo) (*keyring.Record, error) UnprotectedAllowed() bool + AllowInsecureUnlock(allow bool) RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection RPCTxFeeCap() float64 // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for send-transaction variants. The unit is ether. diff --git a/rpc/backend/backend_suite_test.go b/rpc/backend/backend_suite_test.go index 581a125fce..8599e54e63 100644 --- a/rpc/backend/backend_suite_test.go +++ b/rpc/backend/backend_suite_test.go @@ -88,6 +88,7 @@ func (suite *BackendTestSuite) SetupTest() { suite.backend.queryClient.FeeMarket = mocks.NewFeeMarketQueryClient(suite.T()) suite.backend.ctx = rpctypes.ContextWithHeight(1) suite.backend.indexer = mocks.NewEVMTxIndexer(suite.T()) + suite.backend.AllowInsecureUnlock(true) // Add codec encCfg := encoding.MakeConfig(app.ModuleBasics) diff --git a/rpc/backend/node_info.go b/rpc/backend/node_info.go index 77bd91f68b..5b3c48b37e 100644 --- a/rpc/backend/node_info.go +++ b/rpc/backend/node_info.go @@ -301,6 +301,15 @@ func (b Backend) UnprotectedAllowed() bool { return b.allowUnprotectedTxs } +func (b *Backend) AllowInsecureUnlock(allow bool) { + if b.cfg.JSONRPC.AllowInsecureUnlock == allow { + return + } + + jsonRpc := &b.cfg.JSONRPC + jsonRpc.AllowInsecureUnlock = true +} + // RPCGasCap is the global gas cap for eth-call variants. func (b *Backend) RPCGasCap() uint64 { return b.cfg.JSONRPC.GasCap From 68aa6503aafc2fb9c6efdf5bf7769296c0ada534 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 5 Sep 2024 13:41:13 +0700 Subject: [PATCH 2/3] refactor JSON config allow-unprotected-txs in RPC backend --- integration_test_util/chain_suite.go | 2 +- rpc/apis.go | 22 +++++++------------ rpc/backend/backend.go | 33 +++++++++++++--------------- rpc/backend/backend_suite_test.go | 3 +-- rpc/backend/call_tx.go | 2 +- rpc/backend/call_tx_test.go | 8 +++---- rpc/backend/node_info.go | 15 ++++++++----- rpc/backend/sign_tx.go | 2 +- server/json_rpc.go | 3 +-- 9 files changed, 42 insertions(+), 48 deletions(-) diff --git a/integration_test_util/chain_suite.go b/integration_test_util/chain_suite.go index 85617548e7..104bce77c5 100644 --- a/integration_test_util/chain_suite.go +++ b/integration_test_util/chain_suite.go @@ -469,7 +469,7 @@ func (suite *ChainIntegrationTestSuite) RpcBackendAt(height int64) *rpcbackend.B queryClients := suite.QueryClientsAt(height) rpcServerCtx := server.NewDefaultContext() - rpcBackend := rpcbackend.NewBackend(rpcServerCtx, rpcServerCtx.Logger, queryClients.ClientQueryCtx, false, suite.EvmTxIndexer) + rpcBackend := rpcbackend.NewBackend(rpcServerCtx, rpcServerCtx.Logger, queryClients.ClientQueryCtx, suite.EvmTxIndexer) // override the query client with the mock query client, for changing query context getFieldQueryClient := func() reflect.Value { diff --git a/rpc/apis.go b/rpc/apis.go index 03ce8d75e4..7d89de1e2e 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -46,7 +46,6 @@ type APICreator = func( ctx *server.Context, clientCtx client.Context, tendermintWebsocketClient *rpcclient.WSClient, - allowUnprotectedTxs bool, indexer types.EVMTxIndexer, ) []rpc.API @@ -58,10 +57,9 @@ func init() { EthNamespace: func(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, - allowUnprotectedTxs bool, indexer types.EVMTxIndexer, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, indexer) return []rpc.API{ { Namespace: EthNamespace, @@ -77,7 +75,7 @@ func init() { }, } }, - Web3Namespace: func(*server.Context, client.Context, *rpcclient.WSClient, bool, types.EVMTxIndexer) []rpc.API { + Web3Namespace: func(*server.Context, client.Context, *rpcclient.WSClient, types.EVMTxIndexer) []rpc.API { return []rpc.API{ { Namespace: Web3Namespace, @@ -87,7 +85,7 @@ func init() { }, } }, - NetNamespace: func(_ *server.Context, clientCtx client.Context, _ *rpcclient.WSClient, _ bool, _ types.EVMTxIndexer) []rpc.API { + NetNamespace: func(_ *server.Context, clientCtx client.Context, _ *rpcclient.WSClient, _ types.EVMTxIndexer) []rpc.API { return []rpc.API{ { Namespace: NetNamespace, @@ -100,10 +98,9 @@ func init() { PersonalNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient, - allowUnprotectedTxs bool, indexer types.EVMTxIndexer, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, indexer) return []rpc.API{ { Namespace: PersonalNamespace, @@ -113,7 +110,7 @@ func init() { }, } }, - TxPoolNamespace: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient, _ bool, _ types.EVMTxIndexer) []rpc.API { + TxPoolNamespace: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient, _ types.EVMTxIndexer) []rpc.API { return []rpc.API{ { Namespace: TxPoolNamespace, @@ -126,10 +123,9 @@ func init() { DebugNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient, - allowUnprotectedTxs bool, indexer types.EVMTxIndexer, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, indexer) return []rpc.API{ { Namespace: DebugNamespace, @@ -142,10 +138,9 @@ func init() { MinerNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient, - allowUnprotectedTxs bool, indexer types.EVMTxIndexer, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, indexer) return []rpc.API{ { Namespace: MinerNamespace, @@ -162,7 +157,6 @@ func init() { func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, - allowUnprotectedTxs bool, indexer types.EVMTxIndexer, selectedAPIs []string, ) []rpc.API { @@ -170,7 +164,7 @@ func GetRPCAPIs(ctx *server.Context, for _, ns := range selectedAPIs { if creator, ok := apiCreators[ns]; ok { - apis = append(apis, creator(ctx, clientCtx, tmWSClient, allowUnprotectedTxs, indexer)...) + apis = append(apis, creator(ctx, clientCtx, tmWSClient, indexer)...) } else { ctx.Logger.Error("invalid namespace value", "namespace", ns) } diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 8c4c055c19..fd273966eb 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -50,7 +50,7 @@ type EVMBackend interface { ImportRawKey(privkey, password string) (common.Address, error) ListAccounts() ([]common.Address, error) NewMnemonic(uid string, language keyring.Language, hdPath, bip39Passphrase string, algo keyring.SignatureAlgo) (*keyring.Record, error) - UnprotectedAllowed() bool + AllowUnprotectedTxs(allow bool) AllowInsecureUnlock(allow bool) RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection @@ -130,14 +130,13 @@ var _ BackendI = (*Backend)(nil) // Backend implements the BackendI interface type Backend struct { - ctx context.Context - clientCtx client.Context - queryClient *rpctypes.QueryClient // gRPC query client - logger log.Logger - chainID *big.Int - cfg config.Config - allowUnprotectedTxs bool - indexer evertypes.EVMTxIndexer + ctx context.Context + clientCtx client.Context + queryClient *rpctypes.QueryClient // gRPC query client + logger log.Logger + chainID *big.Int + cfg config.Config + indexer evertypes.EVMTxIndexer } // NewBackend creates a new Backend instance for cosmos and ethereum namespaces @@ -145,7 +144,6 @@ func NewBackend( ctx *server.Context, logger log.Logger, clientCtx client.Context, - allowUnprotectedTxs bool, indexer evertypes.EVMTxIndexer, ) *Backend { chainID, err := evertypes.ParseChainID(clientCtx.ChainID) @@ -163,13 +161,12 @@ func NewBackend( } return &Backend{ - ctx: context.Background(), - clientCtx: clientCtx, - queryClient: rpctypes.NewQueryClient(clientCtx), - logger: logger.With("module", "backend"), - chainID: chainID, - cfg: appConf, - allowUnprotectedTxs: allowUnprotectedTxs, - indexer: indexer, + ctx: context.Background(), + clientCtx: clientCtx, + queryClient: rpctypes.NewQueryClient(clientCtx), + logger: logger.With("module", "backend"), + chainID: chainID, + cfg: appConf, + indexer: indexer, } } diff --git a/rpc/backend/backend_suite_test.go b/rpc/backend/backend_suite_test.go index 8599e54e63..996816258c 100644 --- a/rpc/backend/backend_suite_test.go +++ b/rpc/backend/backend_suite_test.go @@ -79,10 +79,9 @@ func (suite *BackendTestSuite) SetupTest() { WithKeyring(keyRing). WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts}) - allowUnprotectedTxs := false idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx) - suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer) + suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, idxer) suite.backend.queryClient.QueryClient = mocks.NewEVMQueryClient(suite.T()) suite.backend.clientCtx.Client = mocks.NewClient(suite.T()) suite.backend.queryClient.FeeMarket = mocks.NewFeeMarketQueryClient(suite.T()) diff --git a/rpc/backend/call_tx.go b/rpc/backend/call_tx.go index 27ad71370d..f4e79ed0f1 100644 --- a/rpc/backend/call_tx.go +++ b/rpc/backend/call_tx.go @@ -110,7 +110,7 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { } // check the local node config in case unprotected txs are disabled - if !b.UnprotectedAllowed() && !tx.Protected() { + if !b.cfg.JSONRPC.AllowUnprotectedTxs && !tx.Protected() { // Ensure only eip155 signed transactions are submitted if EIP155Required is set. return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC") } diff --git a/rpc/backend/call_tx_test.go b/rpc/backend/call_tx_test.go index 6a7ed9a503..7e9075d480 100644 --- a/rpc/backend/call_tx_test.go +++ b/rpc/backend/call_tx_test.go @@ -349,7 +349,7 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { "fail - unprotected transactions", func() { queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - suite.backend.allowUnprotectedTxs = false + suite.backend.AllowUnprotectedTxs(false) RegisterParamsWithoutHeaderError(queryClient, 1) }, rlpEncodedBz, @@ -360,7 +360,7 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { "fail - failed to get evm params", func() { queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - suite.backend.allowUnprotectedTxs = true + suite.backend.AllowUnprotectedTxs(true) RegisterParamsWithoutHeaderError(queryClient, 1) }, rlpEncodedBz, @@ -372,7 +372,7 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { func() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - suite.backend.allowUnprotectedTxs = true + suite.backend.AllowUnprotectedTxs(true) RegisterParamsWithoutHeader(queryClient, 1) RegisterBroadcastTxError(client, txBytes) }, @@ -385,7 +385,7 @@ func (suite *BackendTestSuite) TestSendRawTransaction() { func() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - suite.backend.allowUnprotectedTxs = true + suite.backend.AllowUnprotectedTxs(true) RegisterParamsWithoutHeader(queryClient, 1) RegisterBroadcastTx(client, txBytes) }, diff --git a/rpc/backend/node_info.go b/rpc/backend/node_info.go index 5b3c48b37e..c070c0d54f 100644 --- a/rpc/backend/node_info.go +++ b/rpc/backend/node_info.go @@ -295,19 +295,24 @@ func (b *Backend) SetGasPrice(gasPrice hexutil.Big) bool { return true } -// UnprotectedAllowed returns the node configuration value for allowing -// unprotected transactions (i.e not replay-protected) -func (b Backend) UnprotectedAllowed() bool { - return b.allowUnprotectedTxs +// AllowUnprotectedTxs should be used for testing purpose only. +func (b *Backend) AllowUnprotectedTxs(allow bool) { + if b.cfg.JSONRPC.AllowUnprotectedTxs == allow { + return + } + + jsonRpc := &b.cfg.JSONRPC + jsonRpc.AllowUnprotectedTxs = allow } +// AllowInsecureUnlock should be used for testing purpose only. func (b *Backend) AllowInsecureUnlock(allow bool) { if b.cfg.JSONRPC.AllowInsecureUnlock == allow { return } jsonRpc := &b.cfg.JSONRPC - jsonRpc.AllowInsecureUnlock = true + jsonRpc.AllowInsecureUnlock = allow } // RPCGasCap is the global gas cap for eth-call variants. diff --git a/rpc/backend/sign_tx.go b/rpc/backend/sign_tx.go index 886f269d7f..9fbd4902c7 100644 --- a/rpc/backend/sign_tx.go +++ b/rpc/backend/sign_tx.go @@ -89,7 +89,7 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e ethTx := msg.AsTransaction() // check the local node config in case unprotected txs are disabled - if !b.UnprotectedAllowed() && !ethTx.Protected() { + if !b.cfg.JSONRPC.AllowUnprotectedTxs && !ethTx.Protected() { // Ensure only eip155 signed transactions are submitted if EIP155Required is set. return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC") } diff --git a/server/json_rpc.go b/server/json_rpc.go index ef921111c1..09823d3974 100644 --- a/server/json_rpc.go +++ b/server/json_rpc.go @@ -43,10 +43,9 @@ func StartJSONRPC(ctx *server.Context, rpcServer := ethrpc.NewServer() - allowUnprotectedTxs := config.JSONRPC.AllowUnprotectedTxs rpcAPIArr := config.JSONRPC.API - apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, allowUnprotectedTxs, indexer, rpcAPIArr) + apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, indexer, rpcAPIArr) for _, api := range apis { if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil { From 5be2a6e11cd9a701edff159fa6afdda1cdcff5d1 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 5 Sep 2024 13:42:25 +0700 Subject: [PATCH 3/3] update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45145b9e9c..dfaed44f89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ - (rpc) [#135](https://github.com/EscanBE/evermint/pull/135) Build tx receipt to response for txs aborted due to block gas limit - (evm) [#136](https://github.com/EscanBE/evermint/pull/136) Correct block bloom, receipt bloom computation and some other minor issues of transient data - (rpc+indexer) [#137](https://github.com/EscanBE/evermint/pull/137) Exclude txs dropped pre-AnteHandle due to gas limit from RPC results +- (rpc) [#145](https://github.com/EscanBE/evermint/pull/145) Fix broken tests caused by `--allow-insecure-unlock` and minor refactor RPC backend ### Client Breaking