Unverified Commit e32ee6ac authored by Marius van der Wijden's avatar Marius van der Wijden Committed by GitHub

accounts/abi: added abi test cases, minor bug fixes (#20903)

* accounts/abi: added documentation

* accounts/abi: reduced usage of arguments.LengthNonIndexed

* accounts/abi: simplified reflection logic

* accounts/abi: moved testjson data into global declaration

* accounts/abi: removed duplicate test cases

* accounts/abi: reworked abi tests

* accounts/abi: added more tests for abi packing

* accounts/abi/bind: refactored base tests

* accounts/abi: run pack tests as subtests

* accounts/abi: removed duplicate tests

* accounts/abi: removed unnused arguments.LengthNonIndexed

Due to refactors to the code, we do not need the arguments.LengthNonIndexed function anymore.
You can still get the length by calling len(arguments.NonIndexed())

* accounts/abi: added type test

* accounts/abi: modified unpack test to pack test

* accounts/abi: length check on arrayTy

* accounts/abi: test invalid abi

* accounts/abi: fixed rebase error

* accounts/abi: fixed rebase errors

* accounts/abi: removed unused definition

* accounts/abi: merged packing/unpacking tests

* accounts/abi: fixed [][][32]bytes encoding

* accounts/abi: added tuple test cases

* accounts/abi: renamed getMockLog -> newMockLog

* accounts/abi: removed duplicate test

* accounts/abi: bools -> booleans
parent 40283d05
This diff is collapsed.
...@@ -59,18 +59,6 @@ func (argument *Argument) UnmarshalJSON(data []byte) error { ...@@ -59,18 +59,6 @@ func (argument *Argument) UnmarshalJSON(data []byte) error {
return nil return nil
} }
// LengthNonIndexed returns the number of arguments when not counting 'indexed' ones. Only events
// can ever have 'indexed' arguments, it should always be false on arguments for method input/output
func (arguments Arguments) LengthNonIndexed() int {
out := 0
for _, arg := range arguments {
if !arg.Indexed {
out++
}
}
return out
}
// NonIndexed returns the arguments with indexed arguments filtered out // NonIndexed returns the arguments with indexed arguments filtered out
func (arguments Arguments) NonIndexed() Arguments { func (arguments Arguments) NonIndexed() Arguments {
var ret []Argument var ret []Argument
...@@ -205,10 +193,11 @@ func unpack(t *Type, dst interface{}, src interface{}) error { ...@@ -205,10 +193,11 @@ func unpack(t *Type, dst interface{}, src interface{}) error {
// unpackAtomic unpacks ( hexdata -> go ) a single value // unpackAtomic unpacks ( hexdata -> go ) a single value
func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error { func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
if arguments.LengthNonIndexed() == 0 { nonIndexedArgs := arguments.NonIndexed()
if len(nonIndexedArgs) == 0 {
return nil return nil
} }
argument := arguments.NonIndexed()[0] argument := nonIndexedArgs[0]
elem := reflect.ValueOf(v).Elem() elem := reflect.ValueOf(v).Elem()
if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy { if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy {
...@@ -282,9 +271,10 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa ...@@ -282,9 +271,10 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
// without supplying a struct to unpack into. Instead, this method returns a list containing the // without supplying a struct to unpack into. Instead, this method returns a list containing the
// values. An atomic argument will be a list with one element. // values. An atomic argument will be a list with one element.
func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
retval := make([]interface{}, 0, arguments.LengthNonIndexed()) nonIndexedArgs := arguments.NonIndexed()
retval := make([]interface{}, 0, len(nonIndexedArgs))
virtualArgs := 0 virtualArgs := 0
for index, arg := range arguments.NonIndexed() { for index, arg := range nonIndexedArgs {
marshalledValue, err := ToGoType((index+virtualArgs)*32, arg.Type, data) marshalledValue, err := ToGoType((index+virtualArgs)*32, arg.Type, data)
if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) { if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
// If we have a static array, like [3]uint256, these are coded as // If we have a static array, like [3]uint256, these are coded as
......
This diff is collapsed.
...@@ -46,12 +46,10 @@ func sliceTypeCheck(t Type, val reflect.Value) error { ...@@ -46,12 +46,10 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
return typeErr(formatSliceString(t.Elem.Kind, t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len())) return typeErr(formatSliceString(t.Elem.Kind, t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len()))
} }
if t.Elem.T == SliceTy { if t.Elem.T == SliceTy || t.Elem.T == ArrayTy {
if val.Len() > 0 { if val.Len() > 0 {
return sliceTypeCheck(*t.Elem, val.Index(0)) return sliceTypeCheck(*t.Elem, val.Index(0))
} }
} else if t.Elem.T == ArrayTy {
return sliceTypeCheck(*t.Elem, val.Index(0))
} }
if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.Kind { if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.Kind {
......
...@@ -39,6 +39,7 @@ var ( ...@@ -39,6 +39,7 @@ var (
) )
// U256 converts a big Int into a 256bit EVM number. // U256 converts a big Int into a 256bit EVM number.
// This operation is destructive.
func U256(n *big.Int) []byte { func U256(n *big.Int) []byte {
return math.PaddedBigBytes(math.U256(n), 32) return math.PaddedBigBytes(math.U256(n), 32)
} }
This diff is collapsed.
This diff is collapsed.
...@@ -42,26 +42,26 @@ func indirectInterfaceOrPtr(v reflect.Value) reflect.Value { ...@@ -42,26 +42,26 @@ func indirectInterfaceOrPtr(v reflect.Value) reflect.Value {
// reflectIntKind returns the reflect using the given size and // reflectIntKind returns the reflect using the given size and
// unsignedness. // unsignedness.
func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) { func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) {
switch size { if unsigned {
case 8: switch size {
if unsigned { case 8:
return reflect.Uint8, uint8T return reflect.Uint8, uint8T
case 16:
return reflect.Uint16, uint16T
case 32:
return reflect.Uint32, uint32T
case 64:
return reflect.Uint64, uint64T
} }
}
switch size {
case 8:
return reflect.Int8, int8T return reflect.Int8, int8T
case 16: case 16:
if unsigned {
return reflect.Uint16, uint16T
}
return reflect.Int16, int16T return reflect.Int16, int16T
case 32: case 32:
if unsigned {
return reflect.Uint32, uint32T
}
return reflect.Int32, int32T return reflect.Int32, int32T
case 64: case 64:
if unsigned {
return reflect.Uint64, uint64T
}
return reflect.Int64, int64T return reflect.Int64, int64T
} }
return reflect.Ptr, bigT return reflect.Ptr, bigT
...@@ -88,8 +88,8 @@ func set(dst, src reflect.Value) error { ...@@ -88,8 +88,8 @@ func set(dst, src reflect.Value) error {
return set(dst.Elem(), src) return set(dst.Elem(), src)
case srcType.AssignableTo(dstType) && dst.CanSet(): case srcType.AssignableTo(dstType) && dst.CanSet():
dst.Set(src) dst.Set(src)
case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice: case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice && dst.CanSet():
return setSlice(dst, src) setSlice(dst, src)
default: default:
return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type()) return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type())
} }
...@@ -98,15 +98,13 @@ func set(dst, src reflect.Value) error { ...@@ -98,15 +98,13 @@ func set(dst, src reflect.Value) error {
// setSlice attempts to assign src to dst when slices are not assignable by default // setSlice attempts to assign src to dst when slices are not assignable by default
// e.g. src: [][]byte -> dst: [][15]byte // e.g. src: [][]byte -> dst: [][15]byte
func setSlice(dst, src reflect.Value) error { // setSlice ignores if we cannot copy all of src' elements.
func setSlice(dst, src reflect.Value) {
slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len()) slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len())
for i := 0; i < src.Len(); i++ { for i := 0; i < src.Len(); i++ {
v := src.Index(i) reflect.Copy(slice.Index(i), src.Index(i))
reflect.Copy(slice.Index(i), v)
} }
dst.Set(slice) dst.Set(slice)
return nil
} }
// requireAssignable assures that `dest` is a pointer and it's not an interface. // requireAssignable assures that `dest` is a pointer and it's not an interface.
......
...@@ -306,3 +306,28 @@ func TestTypeCheck(t *testing.T) { ...@@ -306,3 +306,28 @@ func TestTypeCheck(t *testing.T) {
} }
} }
} }
func TestInternalType(t *testing.T) {
components := []ArgumentMarshaling{{Name: "a", Type: "int64"}}
internalType := "struct a.b[]"
kind := Type{
Kind: reflect.Struct,
T: TupleTy,
Type: reflect.TypeOf(struct {
A int64 `json:"a"`
}{}),
stringKind: "(int64)",
TupleRawName: "ab[]",
TupleElems: []*Type{{Kind: reflect.Int64, T: IntTy, Type: reflect.TypeOf(int64(0)), Size: 64, stringKind: "int64"}},
TupleRawNames: []string{"a"},
}
blob := "tuple"
typ, err := NewType(blob, internalType, components)
if err != nil {
t.Errorf("type %q: failed to parse type string: %v", blob, err)
}
if !reflect.DeepEqual(typ, kind) {
t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(kind)))
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment