Skip to content

Commit

Permalink
feat(pkg/scale): add use of pkg/error Wrap for error handling (#2708)
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardmack authored Oct 18, 2022
1 parent 4813232 commit 08c4281
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 49 deletions.
2 changes: 1 addition & 1 deletion dot/rpc/modules/author_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestAuthorModule_HasSessionKeys(t *testing.T) {
req: &HasSessionKeyRequest{"0x01"},
},
exp: false,
expErr: errors.New("unsupported Option value: 4, bytes: [1]"),
expErr: errors.New("unsupported option: value: 4, bytes: [1]"),
},
{
name: "happy path",
Expand Down
13 changes: 8 additions & 5 deletions lib/babe/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,10 @@ func Test_getAuthorityIndex(t *testing.T) {
expErr: errors.New("first digest item is not pre-runtime digest"),
},
{
name: "Invalid Preruntime Digest Type",
args: args{headerInvalidPre},
expErr: errors.New("cannot decode babe header from pre-digest: EOF, field: 0"),
name: "Invalid Preruntime Digest Type",
args: args{headerInvalidPre},
expErr: errors.New("cannot decode babe header from pre-digest: decoding struct: unmarshalling field at" +
" index 0: EOF"),
},
{
name: "BabePrimaryPreDigest Type",
Expand Down Expand Up @@ -382,7 +383,8 @@ func Test_verifier_verifyPreRuntimeDigest(t *testing.T) {
name: "Invalid PreRuntimeDigest",
verifier: verifier{},
args: args{&types.PreRuntimeDigest{Data: []byte{0}}},
expErr: errors.New("unable to find VaryingDataTypeValue with index: 0"),
expErr: errors.New(
"unable to find VaryingDataTypeValue with index: for key 0"),
},
{
name: "Invalid BlockProducer Index",
Expand Down Expand Up @@ -615,7 +617,8 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) {
name: "invalid preruntime digest data",
verifier: verifier{},
header: header2,
expErr: errors.New("failed to verify pre-runtime digest: EOF, field: 0"),
expErr: errors.New("failed to verify pre-runtime digest: decoding struct: unmarshalling field at index" +
" 0: EOF"),
},
{
name: "invalid seal length",
Expand Down
4 changes: 2 additions & 2 deletions lib/grandpa/message_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1286,8 +1286,8 @@ func TestService_VerifyBlockJustification(t *testing.T) {
justification: []byte{1, 2, 3},
},
want: nil,
wantErr: errors.New("EOF, field: 0x0000000000000000000000000000000000000000000000000000000000000000, " +
"field: {Hash:0x0000000000000000000000000000000000000000000000000000000000000000 Number:0 Precommits:[]}"),
wantErr: errors.New("decoding struct: unmarshalling field at index 1: decoding struct: unmarshalling" +
" field at index 0: EOF"),
},
"valid justification": {
fields: fields{
Expand Down
3 changes: 2 additions & 1 deletion lib/runtime/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"errors"
"fmt"
"io"

"github.com/ChainSafe/gossamer/pkg/scale"
)
Expand Down Expand Up @@ -69,7 +70,7 @@ func DecodeVersion(encoded []byte) (version Version, err error) {
for _, optionalField := range optionalFields {
err = decoder.Decode(optionalField.value)
if err != nil {
if err.Error() == "EOF" {
if errors.Is(err, io.EOF) {
return version, nil
}
return Version{}, fmt.Errorf("%w %s: %s", ErrDecodingVersionField, optionalField.name, err)
Expand Down
41 changes: 15 additions & 26 deletions pkg/scale/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,15 @@ func indirect(dstv reflect.Value) (elem reflect.Value) {
func Unmarshal(data []byte, dst interface{}) (err error) {
dstv := reflect.ValueOf(dst)
if dstv.Kind() != reflect.Ptr || dstv.IsNil() {
err = fmt.Errorf("unsupported dst: %T, must be a pointer to a destination", dst)
err = fmt.Errorf("%w: %T", ErrUnsupportedDestination, dst)
return
}

elem := indirect(dstv)
if err != nil {
return
}

buf := &bytes.Buffer{}
ds := decodeState{}
_, err = buf.Write(data)
if err != nil {
return
}
ds.Reader = buf

err = ds.unmarshal(elem)
ds.Reader = bytes.NewBuffer(data)

err = ds.unmarshal(indirect(dstv))
if err != nil {
return
}
Expand All @@ -93,15 +84,15 @@ type Decoder struct {
func (d *Decoder) Decode(dst interface{}) (err error) {
dstv := reflect.ValueOf(dst)
if dstv.Kind() != reflect.Ptr || dstv.IsNil() {
err = fmt.Errorf("unsupported dst: %T, must be a pointer to a destination", dst)
err = fmt.Errorf("%w: %T", ErrUnsupportedDestination, dst)
return
}

elem := indirect(dstv)
err = d.unmarshal(indirect(dstv))
if err != nil {
return
}
return d.unmarshal(elem)
return nil
}

// NewDecoder is constructor for Decoder
Expand Down Expand Up @@ -160,7 +151,7 @@ func (ds *decodeState) unmarshal(dstv reflect.Value) (err error) {
case reflect.Slice:
err = ds.decodeSlice(dstv)
default:
err = fmt.Errorf("unsupported type: %T", in)
err = fmt.Errorf("%w: %T", ErrUnsupportedType, in)
}
}
return
Expand Down Expand Up @@ -244,7 +235,7 @@ func (ds *decodeState) decodeCustomPrimitive(dstv reflect.Value) (err error) {
break
}
default:
err = fmt.Errorf("unsupported type for custom primitive: %T", in)
err = fmt.Errorf("%w: %T", ErrUnsupportedType, in)
return
}
dstv.Set(temp.Elem().Convert(inType))
Expand Down Expand Up @@ -291,7 +282,7 @@ func (ds *decodeState) decodeResult(dstv reflect.Value) (err error) {
dstv.Set(reflect.ValueOf(res))
default:
bytes, _ := io.ReadAll(ds.Reader)
err = fmt.Errorf("unsupported Result value: %v, bytes: %v", rb, bytes)
err = fmt.Errorf("%w: value: %v, bytes: %v", ErrUnsupportedResult, rb, bytes)
}
return
}
Expand Down Expand Up @@ -324,7 +315,7 @@ func (ds *decodeState) decodePointer(dstv reflect.Value) (err error) {
}
default:
bytes, _ := io.ReadAll(ds.Reader)
err = fmt.Errorf("unsupported Option value: %v, bytes: %v", rb, bytes)
err = fmt.Errorf("%w: value: %v, bytes: %v", errUnsupportedOption, rb, bytes)
}
return
}
Expand Down Expand Up @@ -372,7 +363,7 @@ func (ds *decodeState) decodeVaryingDataType(dstv reflect.Value) (err error) {
vdt := dstv.Interface().(VaryingDataType)
val, ok := vdt.cache[uint(b)]
if !ok {
err = fmt.Errorf("unable to find VaryingDataTypeValue with index: %d", uint(b))
err = fmt.Errorf("%w: for key %d", errUnknownVaryingDataTypeValue, uint(b))
return
}

Expand Down Expand Up @@ -448,8 +439,7 @@ func (ds *decodeState) decodeStruct(dstv reflect.Value) (err error) {
}
err = ds.unmarshal(field)
if err != nil {
err = fmt.Errorf("%s, field: %+v", err, field)
return
return fmt.Errorf("decoding struct: unmarshalling field at index %d: %w", i.fieldIndex, err)
}
}
dstv.Set(temp.Elem())
Expand All @@ -470,7 +460,7 @@ func (ds *decodeState) decodeBool(dstv reflect.Value) (err error) {
case 0x01:
b = true
default:
err = fmt.Errorf("could not decode invalid bool")
err = fmt.Errorf("%w", errDecodeBool)
}
dstv.Set(reflect.ValueOf(b))
return
Expand Down Expand Up @@ -538,7 +528,6 @@ func (ds *decodeState) decodeUint(dstv reflect.Value) (err error) {
}
default:
return fmt.Errorf("%w: %d", ErrCompactUintPrefixUnknown, prefix)

}
}
temp.Elem().Set(reflect.ValueOf(value).Convert(reflect.TypeOf(in)))
Expand Down Expand Up @@ -636,7 +625,7 @@ func (ds *decodeState) decodeBigInt(dstv reflect.Value) (err error) {
buf := make([]byte, byteLen)
_, err = ds.Read(buf)
if err != nil {
err = fmt.Errorf("could not decode invalid big.Int: %v", err)
err = fmt.Errorf("reading bytes: %w", err)
break
}
o := reverseBytes(buf)
Expand Down
15 changes: 9 additions & 6 deletions pkg/scale/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (es *encodeState) marshal(in interface{}) (err error) {
case reflect.Slice:
err = es.encodeSlice(in)
default:
err = fmt.Errorf("unsupported type: %T", in)
err = fmt.Errorf("%w: %T", ErrUnsupportedType, in)
}
}
return
Expand Down Expand Up @@ -140,7 +140,7 @@ func (es *encodeState) encodeCustomPrimitive(in interface{}) (err error) {
case reflect.Uint64:
in = reflect.ValueOf(in).Convert(reflect.TypeOf(uint64(0))).Interface()
default:
err = fmt.Errorf("unsupported type for custom primitive: %T", in)
err = fmt.Errorf("%w: %T", ErrUnsupportedCustomPrimitive, in)
return
}
err = es.marshal(in)
Expand All @@ -149,7 +149,7 @@ func (es *encodeState) encodeCustomPrimitive(in interface{}) (err error) {

func (es *encodeState) encodeResult(res Result) (err error) {
if !res.IsSet() {
err = fmt.Errorf("Result is not set: %+v", res)
err = fmt.Errorf("%w: %+v", ErrResultNotSet, res)
return
}

Expand Down Expand Up @@ -230,7 +230,7 @@ func (es *encodeState) encodeArray(in interface{}) (err error) {
func (es *encodeState) encodeBigInt(i *big.Int) (err error) {
switch {
case i == nil:
err = fmt.Errorf("nil *big.Int")
err = fmt.Errorf("%w", errBigIntIsNil)
case i.Cmp(new(big.Int).Lsh(big.NewInt(1), 6)) < 0:
err = binary.Write(es, binary.LittleEndian, uint8(i.Int64()<<2))
case i.Cmp(new(big.Int).Lsh(big.NewInt(1), 14)) < 0:
Expand All @@ -247,6 +247,9 @@ func (es *encodeState) encodeBigInt(i *big.Int) (err error) {
if err == nil {
// write integer itself
err = binary.Write(es, binary.LittleEndian, reverseBytes(i.Bytes()))
if err != nil {
err = fmt.Errorf("writing bytes %s: %w", i, err)
}
}
}
return
Expand Down Expand Up @@ -299,7 +302,7 @@ func (es *encodeState) encodeFixedWidthInt(i interface{}) (err error) {
case uint64:
err = binary.Write(es, binary.LittleEndian, i)
default:
err = fmt.Errorf("could not encode fixed width integer, invalid type: %T", i)
err = fmt.Errorf("invalid type: %T", i)
}
return
}
Expand Down Expand Up @@ -374,7 +377,7 @@ func (es *encodeState) encodeUint(i uint) (err error) {
// encodeUint128 encodes a Uint128
func (es *encodeState) encodeUint128(i *Uint128) (err error) {
if i == nil {
err = fmt.Errorf("uint128 is nil: %v", i)
err = fmt.Errorf("%w", errUint128IsNil)
return
}
err = binary.Write(es, binary.LittleEndian, padBytes(i.Bytes(), binary.LittleEndian))
Expand Down
15 changes: 14 additions & 1 deletion pkg/scale/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,18 @@ package scale
import "errors"

var (
ErrVaryingDataTypeNotSet = errors.New("VaryingDataTypeValue has not been set")
ErrUnsupportedDestination = errors.New("must be a non-nil pointer to a destination")
errDecodeBool = errors.New("invalid byte for bool")
ErrUnsupportedType = errors.New("unsupported type")
ErrUnsupportedResult = errors.New("unsupported result")
errUnsupportedOption = errors.New("unsupported option")
errUnknownVaryingDataTypeValue = errors.New("unable to find VaryingDataTypeValue with index")
errUint128IsNil = errors.New("uint128 in nil")
ErrResultNotSet = errors.New("result not set")
ErrResultAlreadySet = errors.New("result already has an assigned value")
ErrUnsupportedVaryingDataTypeValue = errors.New("unsupported VaryingDataTypeValue")
ErrMustProvideVaryingDataTypeValue = errors.New("must provide at least one VaryingDataTypeValue")
errBigIntIsNil = errors.New("big int is nil")
ErrVaryingDataTypeNotSet = errors.New("varying data type not set")
ErrUnsupportedCustomPrimitive = errors.New("unsupported type for custom primitive")
)
3 changes: 0 additions & 3 deletions pkg/scale/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
package scale

import (
"errors"
"fmt"
"reflect"
)

var ErrResultAlreadySet = errors.New("result already has an assigned value")

// ResultMode is the mode the Result is set to
type ResultMode int

Expand Down
2 changes: 1 addition & 1 deletion pkg/scale/uint128.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (u *Uint128) UnmarshalJSON(data []byte) error {

dec, err := NewUint128(intVal)
if err != nil {
return err
return fmt.Errorf("creating uint128 from big integer: %w", err)
}
u.Upper = dec.Upper
u.Lower = dec.Lower
Expand Down
7 changes: 4 additions & 3 deletions pkg/scale/varying_data_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func (vdts *VaryingDataTypeSlice) Add(values ...VaryingDataTypeValue) (err error
copied := vdts.VaryingDataType
err = copied.Set(val)
if err != nil {
err = fmt.Errorf("setting VaryingDataTypeValue: %w", err)
return
}
vdts.Types = append(vdts.Types, copied)
Expand All @@ -43,7 +44,7 @@ func mustNewVaryingDataTypeSliceAndSet(vdt VaryingDataType,
values ...VaryingDataTypeValue) (vdts VaryingDataTypeSlice) {
vdts = NewVaryingDataTypeSlice(vdt)
if err := vdts.Add(values...); err != nil {
panic(err)
panic(fmt.Sprintf("adding varying data type value: %s", err))
}
return
}
Expand All @@ -58,7 +59,7 @@ type VaryingDataType struct {
func (vdt *VaryingDataType) Set(value VaryingDataTypeValue) (err error) {
_, ok := vdt.cache[value.Index()]
if !ok {
err = fmt.Errorf("unable to append VaryingDataTypeValue: %T, not in cache", value)
err = fmt.Errorf("%w: %v (%T)", ErrUnsupportedVaryingDataTypeValue, value, value)
return
}
vdt.value = value
Expand All @@ -76,7 +77,7 @@ func (vdt *VaryingDataType) Value() (VaryingDataTypeValue, error) {
// NewVaryingDataType is constructor for VaryingDataType
func NewVaryingDataType(values ...VaryingDataTypeValue) (vdt VaryingDataType, err error) {
if len(values) == 0 {
err = fmt.Errorf("must provide atleast one VaryingDataTypeValue")
err = fmt.Errorf("%w", ErrMustProvideVaryingDataTypeValue)
return
}
vdt.cache = make(map[uint]VaryingDataTypeValue)
Expand Down

0 comments on commit 08c4281

Please sign in to comment.