From 347f7ed576d33aa74a749c906bfbe33e47ed9bac Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 23 Mar 2021 22:50:15 +0300 Subject: [PATCH] rpc: move all `top*FromStack` client functions to a separate file Some of them are shared between multiple RPC client APIs, so let's keep them in a separate place for better maintainability. --- pkg/rpc/client/helper.go | 77 ++++++++++++++++++++++++++++++++++++++++ pkg/rpc/client/native.go | 27 -------------- pkg/rpc/client/nep17.go | 32 ----------------- pkg/rpc/client/policy.go | 11 ------ 4 files changed, 77 insertions(+), 70 deletions(-) create mode 100644 pkg/rpc/client/helper.go diff --git a/pkg/rpc/client/helper.go b/pkg/rpc/client/helper.go new file mode 100644 index 000000000..421f18c52 --- /dev/null +++ b/pkg/rpc/client/helper.go @@ -0,0 +1,77 @@ +package client + +import ( + "crypto/elliptic" + "errors" + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" +) + +// getInvocationError returns an error in case of bad VM state or empty stack. +func getInvocationError(result *result.Invoke) error { + if result.State != "HALT" { + return fmt.Errorf("invocation failed: %s", result.FaultException) + } + if len(result.Stack) == 0 { + return errors.New("result stack is empty") + } + return nil +} + +// topBoolFromStack returns the top boolean value from stack. +func topBoolFromStack(st []stackitem.Item) (bool, error) { + index := len(st) - 1 // top stack element is last in the array + result, ok := st[index].Value().(bool) + if !ok { + return false, fmt.Errorf("invalid stack item type: %s", st[index].Type()) + } + return result, nil +} + +// topIntFromStack returns the top integer value from stack. +func topIntFromStack(st []stackitem.Item) (int64, error) { + index := len(st) - 1 // top stack element is last in the array + bi, err := st[index].TryInteger() + if err != nil { + return 0, err + } + return bi.Int64(), nil +} + +// topPublicKeysFromStack returns the top array of public keys from stack. +func topPublicKeysFromStack(st []stackitem.Item) (keys.PublicKeys, error) { + index := len(st) - 1 // top stack element is last in the array + var ( + pks keys.PublicKeys + err error + ) + items, ok := st[index].Value().([]stackitem.Item) + if !ok { + return nil, fmt.Errorf("invalid stack item type: %s", st[index].Type()) + } + pks = make(keys.PublicKeys, len(items)) + for i, item := range items { + val, ok := item.Value().([]byte) + if !ok { + return nil, fmt.Errorf("invalid array element #%d: %s", i, item.Type()) + } + pks[i], err = keys.NewPublicKeyFromBytes(val, elliptic.P256()) + if err != nil { + return nil, err + } + } + return pks, nil +} + +// top string from stack returns the top string from stack. +func topStringFromStack(st []stackitem.Item) (string, error) { + index := len(st) - 1 // top stack element is last in the array + bs, err := st[index].TryBytes() + if err != nil { + return "", err + } + return string(bs), nil +} diff --git a/pkg/rpc/client/native.go b/pkg/rpc/client/native.go index 883910354..770139790 100644 --- a/pkg/rpc/client/native.go +++ b/pkg/rpc/client/native.go @@ -3,14 +3,12 @@ package client // Various non-policy things from native contracts. import ( - "crypto/elliptic" "fmt" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // GetOraclePrice invokes `getPrice` method on a native Oracle contract. @@ -65,28 +63,3 @@ func (c *Client) GetDesignatedByRole(role noderoles.Role, index uint32) (keys.Pu } return topPublicKeysFromStack(result.Stack) } - -// topPublicKeysFromStack returns the top array of public keys from stack. -func topPublicKeysFromStack(st []stackitem.Item) (keys.PublicKeys, error) { - index := len(st) - 1 // top stack element is last in the array - var ( - pks keys.PublicKeys - err error - ) - items, ok := st[index].Value().([]stackitem.Item) - if !ok { - return nil, fmt.Errorf("invalid stack item type: %s", st[index].Type()) - } - pks = make(keys.PublicKeys, len(items)) - for i, item := range items { - val, ok := item.Value().([]byte) - if !ok { - return nil, fmt.Errorf("invalid array element #%d: %s", i, item.Type()) - } - pks[i], err = keys.NewPublicKeyFromBytes(val, elliptic.P256()) - if err != nil { - return nil, err - } - } - return pks, nil -} diff --git a/pkg/rpc/client/nep17.go b/pkg/rpc/client/nep17.go index 1c0cf5e4b..7aba4cdab 100644 --- a/pkg/rpc/client/nep17.go +++ b/pkg/rpc/client/nep17.go @@ -1,19 +1,16 @@ package client import ( - "errors" "fmt" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/wallet" ) @@ -221,32 +218,3 @@ func (c *Client) MultiTransferNEP17(acc *wallet.Account, gas int64, recipients [ return c.SendRawTransaction(tx) } - -func topIntFromStack(st []stackitem.Item) (int64, error) { - index := len(st) - 1 // top stack element is last in the array - bi, err := st[index].TryInteger() - if err != nil { - return 0, err - } - return bi.Int64(), nil -} - -func topStringFromStack(st []stackitem.Item) (string, error) { - index := len(st) - 1 // top stack element is last in the array - bs, err := st[index].TryBytes() - if err != nil { - return "", err - } - return string(bs), nil -} - -// getInvocationError returns an error in case of bad VM state or empty stack. -func getInvocationError(result *result.Invoke) error { - if result.State != "HALT" { - return fmt.Errorf("invocation failed: %s", result.FaultException) - } - if len(result.Stack) == 0 { - return errors.New("result stack is empty") - } - return nil -} diff --git a/pkg/rpc/client/policy.go b/pkg/rpc/client/policy.go index 674d7314e..e8644a025 100644 --- a/pkg/rpc/client/policy.go +++ b/pkg/rpc/client/policy.go @@ -6,7 +6,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // GetFeePerByte invokes `getFeePerByte` method on a native Policy contract. @@ -80,13 +79,3 @@ func (c *Client) IsBlocked(hash util.Uint160) (bool, error) { } return topBoolFromStack(result.Stack) } - -// topBoolFromStack returns the top boolean value from stack -func topBoolFromStack(st []stackitem.Item) (bool, error) { - index := len(st) - 1 // top stack element is last in the array - result, ok := st[index].Value().(bool) - if !ok { - return false, fmt.Errorf("invalid stack item type: %s", st[index].Type()) - } - return result, nil -}