Skip to content

Commit

Permalink
neorpc: add error codes and response errors
Browse files Browse the repository at this point in the history
Close nspcc-dev#2248

Signed-off-by: Tatiana Nesterenko <[email protected]>
  • Loading branch information
tatiana-nspcc committed Jul 26, 2023
1 parent 4dca4c1 commit 3a647d3
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
2 changes: 1 addition & 1 deletion pkg/neorpc/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const (
ErrUnknownHeightCode = -109
)

// Codes for calls that use a wallet (-300...-304) are currently used in C# node only.
// Codes for calls that use a wallet (-300...-304) are currently used in C# node only. Don't fit neo-go wallet model.
const (
// ErrInsufficientFundsWalletCode is returned on RPC request processing error: Insufficient funds.
// Transaction that sends some assets can't be created because it fails. C# node only.
Expand Down
2 changes: 2 additions & 0 deletions pkg/services/rpcsrv/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,8 @@ func getRelayResult(err error, hash util.Uint256) (any, *neorpc.Error) {
return nil, neorpc.WrapErrorWithData(neorpc.ErrExpiredTransaction, err.Error())
case errors.Is(err, core.ErrAlreadyExists) || errors.Is(err, core.ErrHasConflicts) || errors.Is(err, core.ErrInvalidBlockIndex):
return nil, neorpc.WrapErrorWithData(neorpc.ErrAlreadyExists, err.Error())
case errors.Is(err, core.ErrAlreadyExistsMemPool):
return nil, neorpc.WrapErrorWithData(neorpc.ErrTxAlreadyPooled, err.Error())
case errors.Is(err, core.ErrOOM):
return nil, neorpc.WrapErrorWithData(neorpc.ErrOutOfMemory, err.Error())
case errors.Is(err, core.ErrPolicy):
Expand Down
87 changes: 81 additions & 6 deletions pkg/services/rpcsrv/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2287,27 +2287,102 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
tx.NetworkFee += netFee
size += sizeDelta
tx.NetworkFee += int64(size) * chain.FeePerByte()
tx.NetworkFee *= 2
}

newTx := func() *transaction.Transaction {
newTx := func(code opcode.Opcode, validUntilIncr uint32, systemFee int64, addNetFee bool, addAttr bool) *transaction.Transaction {
height := chain.BlockHeight()
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New([]byte{byte(code)}, 0)
tx.Nonce = height + 1
tx.ValidUntilBlock = height + 10
tx.ValidUntilBlock = height + validUntilIncr
tx.Signers = []transaction.Signer{{Account: acc0.PrivateKey().GetScriptHash()}}
addNetworkFee(tx)
if addNetFee {
addNetworkFee(tx)
}
tx.SystemFee = systemFee
if addAttr {
tx.Attributes = []transaction.Attribute{}
tx.Attributes = append(tx.Attributes, transaction.Attribute{Type: transaction.NotValidBeforeT, Value: &transaction.NotValidBefore{Height: height + 1}})
}
require.NoError(t, acc0.SignTx(testchain.Network(), tx))
return tx
}

t.Run("non-transaction parameter", func(t *testing.T) {
body := doRPCCall(`{"jsonrpc": "2.0", "id": 1, "method": "calculatenetworkfee", "params": ["bm90IGEgdHJhbnNhY3Rpb24K"]}"`, httpSrv.URL, t)
_ = checkErrGetResult(t, body, true, neorpc.InvalidParamsCode, "Invalid Params")
})

t.Run("invalid height", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 2, 0, newTx())
b := testchain.NewBlock(t, chain, 2, 0, newTx(opcode.PUSH1, 10, 0, true, false))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrAlreadyExistsCode)
})

t.Run("invalid script", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx(0xDD, 10, 0, true, false))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrInvalidScriptCode)
})

t.Run("invalid ValidUntilBlock", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx(opcode.PUSH1, 0, 0, true, false))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrExpiredTransactionCode)
})

t.Run("invalid SystemFee", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx(opcode.PUSH1, 10, 999999999999, true, false))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrPolicyFailCode)
})

t.Run("invalid NetworkFee", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx(opcode.PUSH1, 10, 0, false, false))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrInsufficientNetworkFeeCode)
})
t.Run("invalid attribute", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx(opcode.PUSH1, 10, 0, true, true))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrTransactionAttrCode)
})

t.Run("insufficient funds", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx(opcode.PUSH1, 10, 899999999999, true, false))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrInsufficientFundsCode)
})

/*
newTx1 := func(code opcode.Opcode, validUntilIncr uint32, systemFee int64) *transaction.Transaction {
//TxB64 := "AK9KzFu0P5gAAAAAAIjOEgAAAAAA7jAAAAGIDdjSt7aj2J+dktSobkC9j0/CJwEAWwsCAMLrCwwUtXfkIuockX9HAVMNeEuQMxMlYkMMFIgN2NK3tqPYn52S1KhuQL2PT8InFMAfDAh0cmFuc2ZlcgwUz3bii9AGLEpHjuNVYQETGfPPpNJBYn1bUjkBQgxAUiZNae4OTSu2EOGW+6fwslLIpVsczOAR9o6R796tFf2KG+nLzs709tCQ7NELZOQ7zUzfF19ADLvH/efNT4v9LygMIQNT96/wFdPSBO7NUI9Kpn9EffTRXsS6ZJ9PqRvbenijVEFW57Mn"
//benchTx, err := base64.StdEncoding.DecodeString(TxB64)
//require.NoError(t, err)
//tx1, err := transaction.NewTransactionFromBytes(benchTx)
tx1, err := transaction.NewTransactionFromBytes([]byte("bm90IGEgdHJhbnNhY3Rpb24K"))
require.NoError(t, err)
tx := tx1
//tx := transaction.New([]byte{byte(code)}, 0)
height := chain.BlockHeight()
tx.Nonce = height + 1
tx.ValidUntilBlock = height + validUntilIncr
tx.Signers = []transaction.Signer{{Account: acc0.PrivateKey().GetScriptHash()}}
addNetworkFee(tx)
tx.SystemFee = systemFee
require.NoError(t, acc0.SignTx(testchain.Network(), tx))
return tx
}
t.Run("mytry to get ErrInvalidSize", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx1(opcode.PUSH1, 10, 0))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
checkErrGetResult(t, body, true, neorpc.ErrInvalidSizeCode)
})
*/
t.Run("positive", func(t *testing.T) {
b := testchain.NewBlock(t, chain, 1, 0, newTx())
b := testchain.NewBlock(t, chain, 1, 0, newTx(opcode.PUSH1, 10, 0, true, false))
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), httpSrv.URL, t)
data := checkErrGetResult(t, body, false, 0)
var res = new(result.RelayResult)
Expand Down

0 comments on commit 3a647d3

Please sign in to comment.