mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 03:41:34 +00:00
*: return errors.ErrUnsupported where appropriate
Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
parent
97506fb48d
commit
6d4ebdcef3
9 changed files with 43 additions and 36 deletions
|
@ -21,10 +21,6 @@ type TrieStore struct {
|
|||
trie *Trie
|
||||
}
|
||||
|
||||
// ErrForbiddenTrieStoreOperation is returned when operation is not supposed to
|
||||
// be performed over MPT-based Store.
|
||||
var ErrForbiddenTrieStoreOperation = errors.New("operation is not allowed to be performed over TrieStore")
|
||||
|
||||
// NewTrieStore returns a new ready to use MPT-backed storage.
|
||||
func NewTrieStore(root util.Uint256, mode TrieMode, backed storage.Store) *TrieStore {
|
||||
cache, ok := backed.(*storage.MemCachedStore)
|
||||
|
@ -37,10 +33,11 @@ func NewTrieStore(root util.Uint256, mode TrieMode, backed storage.Store) *TrieS
|
|||
}
|
||||
}
|
||||
|
||||
// Get implements the Store interface.
|
||||
// Get implements the Store interface. It can return [errors.ErrUnsupported]
|
||||
// for unsupported operations.
|
||||
func (m *TrieStore) Get(key []byte) ([]byte, error) {
|
||||
if len(key) == 0 {
|
||||
return nil, fmt.Errorf("%w: Get is supported only for contract storage items", ErrForbiddenTrieStoreOperation)
|
||||
return nil, fmt.Errorf("%w: Get is supported only for contract storage items", errors.ErrUnsupported)
|
||||
}
|
||||
switch storage.KeyPrefix(key[0]) {
|
||||
case storage.STStorage, storage.STTempStorage:
|
||||
|
@ -51,22 +48,23 @@ func (m *TrieStore) Get(key []byte) ([]byte, error) {
|
|||
}
|
||||
return res, err
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: Get is supported only for contract storage items", ErrForbiddenTrieStoreOperation)
|
||||
return nil, fmt.Errorf("%w: Get is supported only for contract storage items", errors.ErrUnsupported)
|
||||
}
|
||||
}
|
||||
|
||||
// PutChangeSet implements the Store interface.
|
||||
// PutChangeSet implements the Store interface. It's not supported, so it
|
||||
// always returns [errors.ErrUnsupported].
|
||||
func (m *TrieStore) PutChangeSet(puts map[string][]byte, stor map[string][]byte) error {
|
||||
// Only Get and Seek should be supported, as TrieStore is read-only and is always
|
||||
// should be wrapped by MemCachedStore to properly support put operations (if any).
|
||||
return fmt.Errorf("%w: PutChangeSet is not supported", ErrForbiddenTrieStoreOperation)
|
||||
return fmt.Errorf("%w: PutChangeSet is not supported", errors.ErrUnsupported)
|
||||
}
|
||||
|
||||
// Seek implements the Store interface.
|
||||
func (m *TrieStore) Seek(rng storage.SeekRange, f func(k, v []byte) bool) {
|
||||
prefix := storage.KeyPrefix(rng.Prefix[0])
|
||||
if prefix != storage.STStorage && prefix != storage.STTempStorage { // Prefix is always non-empty.
|
||||
panic(fmt.Errorf("%w: Seek is supported only for contract storage items", ErrForbiddenTrieStoreOperation))
|
||||
panic(fmt.Errorf("%w: Seek is supported only for contract storage items", errors.ErrUnsupported))
|
||||
}
|
||||
prefixP := toNibbles(rng.Prefix[1:])
|
||||
fromP := []byte{}
|
||||
|
@ -113,9 +111,10 @@ func (m *TrieStore) Seek(rng storage.SeekRange, f func(k, v []byte) bool) {
|
|||
}
|
||||
}
|
||||
|
||||
// SeekGC implements the Store interface.
|
||||
// SeekGC implements the Store interface. It's not supported, so it always
|
||||
// returns [errors.ErrUnsupported].
|
||||
func (m *TrieStore) SeekGC(rng storage.SeekRange, keep func(k, v []byte) bool) error {
|
||||
return fmt.Errorf("%w: SeekGC is not supported", ErrForbiddenTrieStoreOperation)
|
||||
return fmt.Errorf("%w: SeekGC is not supported", errors.ErrUnsupported)
|
||||
}
|
||||
|
||||
// Close implements the Store interface.
|
||||
|
|
|
@ -2,6 +2,7 @@ package mpt
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||
|
@ -15,10 +16,10 @@ func TestTrieStore_TestTrieOperations(t *testing.T) {
|
|||
st := NewTrieStore(source.root.Hash(), ModeAll, backed)
|
||||
|
||||
t.Run("forbidden operations", func(t *testing.T) {
|
||||
require.ErrorIs(t, st.SeekGC(storage.SeekRange{}, nil), ErrForbiddenTrieStoreOperation)
|
||||
require.ErrorIs(t, st.SeekGC(storage.SeekRange{}, nil), errors.ErrUnsupported)
|
||||
_, err := st.Get([]byte{byte(storage.STTokenTransferInfo)})
|
||||
require.ErrorIs(t, err, ErrForbiddenTrieStoreOperation)
|
||||
require.ErrorIs(t, st.PutChangeSet(nil, nil), ErrForbiddenTrieStoreOperation)
|
||||
require.ErrorIs(t, err, errors.ErrUnsupported)
|
||||
require.ErrorIs(t, st.PutChangeSet(nil, nil), errors.ErrUnsupported)
|
||||
})
|
||||
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
|
|
|
@ -201,16 +201,16 @@ func curveHasherFromStackitem(si stackitem.Item, allowKeccak bool) (elliptic.Cur
|
|||
return elliptic.P256(), hash.Sha256, nil
|
||||
case int64(Secp256k1Keccak256):
|
||||
if !allowKeccak {
|
||||
return nil, nil, errors.New("unsupported hash type")
|
||||
return nil, nil, fmt.Errorf("%w: keccak hash", errors.ErrUnsupported)
|
||||
}
|
||||
return secp256k1.S256(), Keccak256, nil
|
||||
case int64(Secp256r1Keccak256):
|
||||
if !allowKeccak {
|
||||
return nil, nil, errors.New("unsupported hash type")
|
||||
return nil, nil, fmt.Errorf("%w: keccak hash", errors.ErrUnsupported)
|
||||
}
|
||||
return elliptic.P256(), Keccak256, nil
|
||||
default:
|
||||
return nil, nil, errors.New("unsupported curve/hash type")
|
||||
return nil, nil, fmt.Errorf("%w: unknown curve/hash", errors.ErrUnsupported)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ var (
|
|||
// of transaction awaiting process and no result was received yet.
|
||||
ErrContextDone = errors.New("waiter context done")
|
||||
// ErrAwaitingNotSupported is returned from Wait method if Waiter instance
|
||||
// doesn't support transaction awaiting.
|
||||
ErrAwaitingNotSupported = errors.New("awaiting not supported")
|
||||
// doesn't support transaction awaiting. It's compatible with [errors.ErrUnsupported].
|
||||
ErrAwaitingNotSupported = fmt.Errorf("%w: awaiting", errors.ErrUnsupported)
|
||||
// ErrMissedEvent is returned when RPCEventBased closes receiver channel
|
||||
// which happens if missed event was received from the RPC server.
|
||||
ErrMissedEvent = errors.New("some event was missed")
|
||||
|
|
|
@ -14,7 +14,8 @@ import (
|
|||
)
|
||||
|
||||
// ExpandFuncParameterIntoScript pushes provided FuncParam parameter
|
||||
// into the given buffer.
|
||||
// into the given buffer. Returns [errors.ErrUnsupported] for types it can't
|
||||
// process.
|
||||
func ExpandFuncParameterIntoScript(script *io.BinWriter, fp FuncParam) error {
|
||||
switch fp.Type {
|
||||
case smartcontract.ByteArrayType:
|
||||
|
@ -92,7 +93,7 @@ func ExpandFuncParameterIntoScript(script *io.BinWriter, fp FuncParam) error {
|
|||
emit.Opcodes(script, opcode.PUSHNULL)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("parameter type %v is not supported", fp.Type)
|
||||
return fmt.Errorf("%w: parameter type %v", errors.ErrUnsupported, fp.Type)
|
||||
}
|
||||
return script.Err
|
||||
}
|
||||
|
|
|
@ -200,7 +200,8 @@ func (p *Parameter) UnmarshalJSON(data []byte) (err error) {
|
|||
// NewParameterFromString returns a new Parameter initialized from the given
|
||||
// string in neo-go-specific format. It is intended to be used in user-facing
|
||||
// interfaces and has some heuristics in it to simplify parameter passing. The exact
|
||||
// syntax is documented in the cli documentation.
|
||||
// syntax is documented in the cli documentation. [errors.ErrUnsupported] will be
|
||||
// returned in case of unsupported parameter types.
|
||||
func NewParameterFromString(in string) (*Parameter, error) {
|
||||
var (
|
||||
char rune
|
||||
|
@ -227,7 +228,7 @@ func NewParameterFromString(in string) (*Parameter, error) {
|
|||
}
|
||||
// We currently do not support following types:
|
||||
if res.Type == ArrayType || res.Type == MapType || res.Type == InteropInterfaceType || res.Type == VoidType {
|
||||
return nil, fmt.Errorf("unsupported parameter type %s", res.Type)
|
||||
return nil, fmt.Errorf("%w: type %s", errors.ErrUnsupported, res.Type)
|
||||
}
|
||||
buf.Reset()
|
||||
hadType = true
|
||||
|
@ -264,7 +265,8 @@ func NewParameterFromString(in string) (*Parameter, error) {
|
|||
// NewParameterFromValue infers Parameter type from the value given and adjusts
|
||||
// the value if needed. It does not copy the value if it can avoid doing so. All
|
||||
// regular integers, util.*, keys.PublicKey*, string and bool types are supported,
|
||||
// slice of byte slices is accepted and converted as well.
|
||||
// slice of byte slices is accepted and converted as well. [errors.ErrUnsupported]
|
||||
// will be returned for types that can't be used now.
|
||||
func NewParameterFromValue(value any) (Parameter, error) {
|
||||
var result = Parameter{
|
||||
Value: value,
|
||||
|
@ -373,7 +375,7 @@ func NewParameterFromValue(value any) (Parameter, error) {
|
|||
case nil:
|
||||
result.Type = AnyType
|
||||
default:
|
||||
return result, fmt.Errorf("unsupported parameter %T", value)
|
||||
return result, fmt.Errorf("%w: %T type", errors.ErrUnsupported, value)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
@ -396,6 +398,7 @@ func NewParametersFromValues(values ...any) ([]Parameter, error) {
|
|||
// ExpandParameterToEmitable converts a parameter to a type which can be handled as
|
||||
// an array item by emit.Array. It correlates with the way an RPC server handles
|
||||
// FuncParams for invoke* calls inside the request.ExpandArrayIntoScript function.
|
||||
// [errors.ErrUnsupported] is returned for unsupported types.
|
||||
func ExpandParameterToEmitable(param Parameter) (any, error) {
|
||||
var err error
|
||||
switch t := param.Type; t {
|
||||
|
@ -410,7 +413,7 @@ func ExpandParameterToEmitable(param Parameter) (any, error) {
|
|||
}
|
||||
return res, nil
|
||||
case MapType, InteropInterfaceType, UnknownType, VoidType:
|
||||
return nil, fmt.Errorf("unsupported parameter type: %s", t.String())
|
||||
return nil, fmt.Errorf("%w: %s type", errors.ErrUnsupported, t.String())
|
||||
default:
|
||||
return param.Value, nil
|
||||
}
|
||||
|
|
|
@ -787,11 +787,11 @@ func TestParameterFromValue(t *testing.T) {
|
|||
},
|
||||
{
|
||||
value: make(map[string]int),
|
||||
err: "unsupported parameter map[string]int",
|
||||
err: "unsupported operation: map[string]int type",
|
||||
},
|
||||
{
|
||||
value: []any{1, 2, make(map[string]int)},
|
||||
err: "unsupported parameter map[string]int",
|
||||
err: "unsupported operation: map[string]int type",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,8 @@ func Array(w *io.BinWriter, es ...any) {
|
|||
// - stackitem.Convertible, stackitem.Item
|
||||
// - nil
|
||||
// - []any
|
||||
//
|
||||
// [errors.ErrUnsupported] is returned for unsupported types.
|
||||
func Any(w *io.BinWriter, something any) {
|
||||
switch e := something.(type) {
|
||||
case []any:
|
||||
|
@ -181,7 +183,7 @@ func Any(w *io.BinWriter, something any) {
|
|||
StackItem(w, e)
|
||||
default:
|
||||
if something != nil {
|
||||
w.Err = fmt.Errorf("unsupported type: %T", e)
|
||||
w.Err = fmt.Errorf("%w: %T type", errors.ErrUnsupported, e)
|
||||
return
|
||||
}
|
||||
Opcodes(w, opcode.PUSHNULL)
|
||||
|
@ -199,14 +201,15 @@ func Convertible(w *io.BinWriter, c stackitem.Convertible) {
|
|||
StackItem(w, si)
|
||||
}
|
||||
|
||||
// StackItem emits provided stackitem.Item to the given buffer.
|
||||
// StackItem emits provided stackitem.Item to the given buffer. If it can't
|
||||
// be emitted [errors.ErrUnsupported] is returned.
|
||||
func StackItem(w *io.BinWriter, si stackitem.Item) {
|
||||
switch t := si.Type(); t {
|
||||
case stackitem.AnyT:
|
||||
if si.Value() == nil {
|
||||
Opcodes(w, opcode.PUSHNULL)
|
||||
} else {
|
||||
w.Err = fmt.Errorf("only nil value supported for %s", t)
|
||||
w.Err = fmt.Errorf("%w: %s can only be nil", errors.ErrUnsupported, t)
|
||||
return
|
||||
}
|
||||
case stackitem.BooleanT:
|
||||
|
@ -240,7 +243,7 @@ func StackItem(w *io.BinWriter, si stackitem.Item) {
|
|||
Int(w, int64(len(arr)))
|
||||
Opcodes(w, opcode.PACKMAP)
|
||||
default:
|
||||
w.Err = fmt.Errorf("%s is unsuppoted", t)
|
||||
w.Err = fmt.Errorf("%w: %s type", errors.ErrUnsupported, t)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -547,7 +547,7 @@ func TestEmitStackitem(t *testing.T) {
|
|||
for _, si := range itms {
|
||||
buf := io.NewBufBinWriter()
|
||||
StackItem(buf.BinWriter, si)
|
||||
require.Error(t, buf.Err)
|
||||
require.ErrorIs(t, buf.Err, errors.ErrUnsupported)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -555,8 +555,8 @@ func TestEmitStackitem(t *testing.T) {
|
|||
buf := io.NewBufBinWriter()
|
||||
StackItem(buf.BinWriter, StrangeStackItem{})
|
||||
actualErr := buf.Err
|
||||
require.Error(t, actualErr)
|
||||
require.True(t, strings.Contains(actualErr.Error(), "only nil value supported"), actualErr.Error())
|
||||
require.ErrorIs(t, actualErr, errors.ErrUnsupported)
|
||||
require.True(t, strings.Contains(actualErr.Error(), "Any can only be nil"), actualErr.Error())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue