From 82e52c4f6d23c427aeafef1f8ed3f0cd83d8a35f Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 18 Mar 2024 18:05:19 +0300 Subject: [PATCH] rpcsrv: fix RPC error codes proposal compatibility mempool.ErrInsufficientFunds is used when sender doesn't have enough balance to pay the submitted transaction fees (-511 code according to https://github.com/neo-project/proposals/pull/156). mempool.ErrConflict is used when sender is not able to pay the overall transactions fee sum in the pool (generic -500 error according to the proposal). This bugfix is kind of breaking change for those users who relied on the old -511 code previously returning "insufficient funds" error. Signed-off-by: Anna Shaleva --- pkg/services/rpcsrv/server.go | 2 +- pkg/services/rpcsrv/server_test.go | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index 6430a2ffe..545418234 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -2657,7 +2657,7 @@ func getRelayResult(err error, hash util.Uint256) (any, *neorpc.Error) { return nil, neorpc.WrapErrorWithData(neorpc.ErrInsufficientNetworkFee, err.Error()) case errors.Is(err, core.ErrInvalidAttribute): return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidAttribute, err.Error()) - case errors.Is(err, core.ErrInsufficientFunds): + case errors.Is(err, core.ErrMemPoolConflict): return nil, neorpc.WrapErrorWithData(neorpc.ErrInsufficientFunds, err.Error()) case errors.Is(err, core.ErrInvalidSignature): return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidSignature, err.Error()) diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index 81625cab3..1b275d92c 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -2659,7 +2659,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] t.Run("insufficient funds", func(t *testing.T) { b := testchain.NewBlock(t, chain, 1, 0, newTxWithParams(t, chain, opcode.PUSH1, 10, 899999999999, 1, false)) body := doRPCCall(fmt.Sprintf(rpc, encodeBinaryToString(t, b)), httpSrv.URL, t) - checkErrGetResult(t, body, true, neorpc.ErrInsufficientFundsCode) + checkErrGetResult(t, body, true, neorpc.ErrVerificationFailedCode) }) t.Run("positive", func(t *testing.T) { b := testchain.NewBlock(t, chain, 1, 0, newTxWithParams(t, chain, opcode.PUSH1, 10, 0, 1, false)) @@ -3341,6 +3341,23 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] body2 := doRPCCall(fmt.Sprintf(rpc, rawTx2), httpSrv.URL, t) checkErrGetResult(t, body2, true, neorpc.ErrMempoolCapReachedCode) }) + t.Run("mempool conflict", func(t *testing.T) { + chain, _, httpSrv := initClearServerWithCustomConfig(t, func(c *config.Config) { + c.ProtocolConfiguration.MemPoolSize = 2 + }) + + // Create and push the first transaction with large network fee. + tx := newTxWithParams(t, chain, opcode.PUSH1, 10, 1, 25, false) + rawTx := encodeBinaryToString(t, tx) + body := doRPCCall(fmt.Sprintf(rpc, rawTx), httpSrv.URL, t) + checkErrGetResult(t, body, false, 0) + + // Create and push the second transaction, sender doesn't have enough balance to pay for two transactions. + tx2 := newTxWithParams(t, chain, opcode.PUSH1, 10, 1, 25, false) + rawTx2 := encodeBinaryToString(t, tx2) + body2 := doRPCCall(fmt.Sprintf(rpc, rawTx2), httpSrv.URL, t) + checkErrGetResult(t, body2, true, neorpc.ErrInsufficientFundsCode) + }) }) t.Run("test functions with unsupported states", func(t *testing.T) { chain, _, httpSrv := initClearServerWithCustomConfig(t, func(c *config.Config) {