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

account/abi: remove superfluous type checking (#21022)

* accounts/abi: added getType func to Type struct

* accounts/abi: fixed tuple unpack

* accounts/abi: removed type.Type

* accounts/abi: added comment

* accounts/abi: removed unused types

* accounts/abi: removed superfluous declarations

* accounts/abi: typo
parent 44a3b8c0
...@@ -39,11 +39,11 @@ func formatSliceString(kind reflect.Kind, sliceSize int) string { ...@@ -39,11 +39,11 @@ func formatSliceString(kind reflect.Kind, sliceSize int) string {
// type in t. // type in t.
func sliceTypeCheck(t Type, val reflect.Value) error { func sliceTypeCheck(t Type, val reflect.Value) error {
if val.Kind() != reflect.Slice && val.Kind() != reflect.Array { if val.Kind() != reflect.Slice && val.Kind() != reflect.Array {
return typeErr(formatSliceString(t.Type.Kind(), t.Size), val.Type()) return typeErr(formatSliceString(t.getType().Kind(), t.Size), val.Type())
} }
if t.T == ArrayTy && val.Len() != t.Size { if t.T == ArrayTy && val.Len() != t.Size {
return typeErr(formatSliceString(t.Elem.Type.Kind(), t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len())) return typeErr(formatSliceString(t.Elem.getType().Kind(), t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len()))
} }
if t.Elem.T == SliceTy || t.Elem.T == ArrayTy { if t.Elem.T == SliceTy || t.Elem.T == ArrayTy {
...@@ -52,8 +52,8 @@ func sliceTypeCheck(t Type, val reflect.Value) error { ...@@ -52,8 +52,8 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
} }
} }
if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.Type.Kind() { if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.getType().Kind() {
return typeErr(formatSliceString(t.Elem.Type.Kind(), t.Size), val.Type()) return typeErr(formatSliceString(t.Elem.getType().Kind(), t.Size), val.Type())
} }
return nil return nil
} }
...@@ -66,10 +66,10 @@ func typeCheck(t Type, value reflect.Value) error { ...@@ -66,10 +66,10 @@ func typeCheck(t Type, value reflect.Value) error {
} }
// Check base type validity. Element types will be checked later on. // Check base type validity. Element types will be checked later on.
if t.Type.Kind() != value.Kind() { if t.getType().Kind() != value.Kind() {
return typeErr(t.Type.Kind(), value.Kind()) return typeErr(t.getType().Kind(), value.Kind())
} else if t.T == FixedBytesTy && t.Size != value.Len() { } else if t.T == FixedBytesTy && t.Size != value.Len() {
return typeErr(t.Type, value.Type()) return typeErr(t.getType(), value.Type())
} else { } else {
return nil return nil
} }
......
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi
import (
"math/big"
"reflect"
"github.com/ethereum/go-ethereum/common"
)
var (
bigT = reflect.TypeOf(&big.Int{})
derefbigT = reflect.TypeOf(big.Int{})
uint8T = reflect.TypeOf(uint8(0))
uint16T = reflect.TypeOf(uint16(0))
uint32T = reflect.TypeOf(uint32(0))
uint64T = reflect.TypeOf(uint64(0))
int8T = reflect.TypeOf(int8(0))
int16T = reflect.TypeOf(int16(0))
int32T = reflect.TypeOf(int32(0))
int64T = reflect.TypeOf(int64(0))
addressT = reflect.TypeOf(common.Address{})
)
...@@ -18,6 +18,7 @@ package abi ...@@ -18,6 +18,7 @@ package abi
import ( import (
"fmt" "fmt"
"math/big"
"reflect" "reflect"
"strings" "strings"
) )
...@@ -25,7 +26,7 @@ import ( ...@@ -25,7 +26,7 @@ import (
// indirect recursively dereferences the value until it either gets the value // indirect recursively dereferences the value until it either gets the value
// or finds a big.Int // or finds a big.Int
func indirect(v reflect.Value) reflect.Value { func indirect(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbigT { if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeOf(big.Int{}) {
return indirect(v.Elem()) return indirect(v.Elem())
} }
return v return v
...@@ -45,26 +46,26 @@ func reflectIntType(unsigned bool, size int) reflect.Type { ...@@ -45,26 +46,26 @@ func reflectIntType(unsigned bool, size int) reflect.Type {
if unsigned { if unsigned {
switch size { switch size {
case 8: case 8:
return uint8T return reflect.TypeOf(uint8(0))
case 16: case 16:
return uint16T return reflect.TypeOf(uint16(0))
case 32: case 32:
return uint32T return reflect.TypeOf(uint32(0))
case 64: case 64:
return uint64T return reflect.TypeOf(uint64(0))
} }
} }
switch size { switch size {
case 8: case 8:
return int8T return reflect.TypeOf(int8(0))
case 16: case 16:
return int16T return reflect.TypeOf(int16(0))
case 32: case 32:
return int32T return reflect.TypeOf(int32(0))
case 64: case 64:
return int64T return reflect.TypeOf(int64(0))
} }
return bigT return reflect.TypeOf(&big.Int{})
} }
// mustArrayToBytesSlice creates a new byte slice with the exact same size as value // mustArrayToBytesSlice creates a new byte slice with the exact same size as value
...@@ -84,7 +85,7 @@ func set(dst, src reflect.Value) error { ...@@ -84,7 +85,7 @@ func set(dst, src reflect.Value) error {
switch { switch {
case dstType.Kind() == reflect.Interface && dst.Elem().IsValid(): case dstType.Kind() == reflect.Interface && dst.Elem().IsValid():
return set(dst.Elem(), src) return set(dst.Elem(), src)
case dstType.Kind() == reflect.Ptr && dstType.Elem() != derefbigT: case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}):
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)
......
...@@ -23,6 +23,8 @@ import ( ...@@ -23,6 +23,8 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"github.com/ethereum/go-ethereum/common"
) )
// Type enumerator // Type enumerator
...@@ -45,7 +47,6 @@ const ( ...@@ -45,7 +47,6 @@ const (
// Type is the reflection of the supported argument type // Type is the reflection of the supported argument type
type Type struct { type Type struct {
Elem *Type Elem *Type
Type reflect.Type
Size int Size int
T byte // Our own type checking T byte // Our own type checking
...@@ -55,6 +56,7 @@ type Type struct { ...@@ -55,6 +56,7 @@ type Type struct {
TupleRawName string // Raw struct name defined in source code, may be empty. TupleRawName string // Raw struct name defined in source code, may be empty.
TupleElems []*Type // Type information of all tuple fields TupleElems []*Type // Type information of all tuple fields
TupleRawNames []string // Raw field name of all tuple fields TupleRawNames []string // Raw field name of all tuple fields
TupleType reflect.Type // Underlying struct of the tuple
} }
var ( var (
...@@ -94,7 +96,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty ...@@ -94,7 +96,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
// is a slice // is a slice
typ.T = SliceTy typ.T = SliceTy
typ.Elem = &embeddedType typ.Elem = &embeddedType
typ.Type = reflect.SliceOf(embeddedType.Type)
typ.stringKind = embeddedType.stringKind + sliced typ.stringKind = embeddedType.stringKind + sliced
} else if len(intz) == 1 { } else if len(intz) == 1 {
// is a array // is a array
...@@ -104,7 +105,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty ...@@ -104,7 +105,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
if err != nil { if err != nil {
return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
} }
typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type)
typ.stringKind = embeddedType.stringKind + sliced typ.stringKind = embeddedType.stringKind + sliced
} else { } else {
return Type{}, fmt.Errorf("invalid formatting of array type") return Type{}, fmt.Errorf("invalid formatting of array type")
...@@ -136,31 +136,24 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty ...@@ -136,31 +136,24 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
// varType is the parsed abi type // varType is the parsed abi type
switch varType := parsedType[1]; varType { switch varType := parsedType[1]; varType {
case "int": case "int":
typ.Type = reflectIntType(false, varSize)
typ.Size = varSize typ.Size = varSize
typ.T = IntTy typ.T = IntTy
case "uint": case "uint":
typ.Type = reflectIntType(true, varSize)
typ.Size = varSize typ.Size = varSize
typ.T = UintTy typ.T = UintTy
case "bool": case "bool":
typ.T = BoolTy typ.T = BoolTy
typ.Type = reflect.TypeOf(bool(false))
case "address": case "address":
typ.Type = addressT
typ.Size = 20 typ.Size = 20
typ.T = AddressTy typ.T = AddressTy
case "string": case "string":
typ.Type = reflect.TypeOf("")
typ.T = StringTy typ.T = StringTy
case "bytes": case "bytes":
if varSize == 0 { if varSize == 0 {
typ.T = BytesTy typ.T = BytesTy
typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0)))
} else { } else {
typ.T = FixedBytesTy typ.T = FixedBytesTy
typ.Size = varSize typ.Size = varSize
typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0)))
} }
case "tuple": case "tuple":
var ( var (
...@@ -180,7 +173,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty ...@@ -180,7 +173,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
} }
fields = append(fields, reflect.StructField{ fields = append(fields, reflect.StructField{
Name: ToCamelCase(c.Name), // reflect.StructOf will panic for any exported field. Name: ToCamelCase(c.Name), // reflect.StructOf will panic for any exported field.
Type: cType.Type, Type: cType.getType(),
Tag: reflect.StructTag("json:\"" + c.Name + "\""), Tag: reflect.StructTag("json:\"" + c.Name + "\""),
}) })
elems = append(elems, &cType) elems = append(elems, &cType)
...@@ -191,7 +184,8 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty ...@@ -191,7 +184,8 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
} }
} }
expression += ")" expression += ")"
typ.Type = reflect.StructOf(fields)
typ.TupleType = reflect.StructOf(fields)
typ.TupleElems = elems typ.TupleElems = elems
typ.TupleRawNames = names typ.TupleRawNames = names
typ.T = TupleTy typ.T = TupleTy
...@@ -210,7 +204,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty ...@@ -210,7 +204,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
case "function": case "function":
typ.T = FunctionTy typ.T = FunctionTy
typ.Size = 24 typ.Size = 24
typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
default: default:
return Type{}, fmt.Errorf("unsupported arg type: %s", t) return Type{}, fmt.Errorf("unsupported arg type: %s", t)
} }
...@@ -218,6 +211,41 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty ...@@ -218,6 +211,41 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
return return
} }
func (t Type) getType() reflect.Type {
switch t.T {
case IntTy:
return reflectIntType(false, t.Size)
case UintTy:
return reflectIntType(true, t.Size)
case BoolTy:
return reflect.TypeOf(false)
case StringTy:
return reflect.TypeOf("")
case SliceTy:
return reflect.SliceOf(t.Elem.getType())
case ArrayTy:
return reflect.ArrayOf(t.Size, t.Elem.getType())
case TupleTy:
return t.TupleType
case AddressTy:
return reflect.TypeOf(common.Address{})
case FixedBytesTy:
return reflect.ArrayOf(t.Size, reflect.TypeOf(byte(0)))
case BytesTy:
return reflect.SliceOf(reflect.TypeOf(byte(0)))
case HashTy:
// hashtype currently not used
return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
case FixedPointTy:
// fixedpoint type currently not used
return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
case FunctionTy:
return reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
default:
panic("Invalid type")
}
}
// String implements Stringer // String implements Stringer
func (t Type) String() (out string) { func (t Type) String() (out string) {
return t.stringKind return t.stringKind
......
This diff is collapsed.
...@@ -34,32 +34,36 @@ var ( ...@@ -34,32 +34,36 @@ var (
// ReadInteger reads the integer based on its kind and returns the appropriate value // ReadInteger reads the integer based on its kind and returns the appropriate value
func ReadInteger(typ Type, b []byte) interface{} { func ReadInteger(typ Type, b []byte) interface{} {
switch typ.Type { if typ.T == UintTy {
case uint8T: switch typ.Size {
case 8:
return b[len(b)-1] return b[len(b)-1]
case uint16T: case 16:
return binary.BigEndian.Uint16(b[len(b)-2:]) return binary.BigEndian.Uint16(b[len(b)-2:])
case uint32T: case 32:
return binary.BigEndian.Uint32(b[len(b)-4:]) return binary.BigEndian.Uint32(b[len(b)-4:])
case uint64T: case 64:
return binary.BigEndian.Uint64(b[len(b)-8:]) return binary.BigEndian.Uint64(b[len(b)-8:])
case int8T: default:
// the only case left for unsigned integer is uint256.
return new(big.Int).SetBytes(b)
}
}
switch typ.Size {
case 8:
return int8(b[len(b)-1]) return int8(b[len(b)-1])
case int16T: case 16:
return int16(binary.BigEndian.Uint16(b[len(b)-2:])) return int16(binary.BigEndian.Uint16(b[len(b)-2:]))
case int32T: case 32:
return int32(binary.BigEndian.Uint32(b[len(b)-4:])) return int32(binary.BigEndian.Uint32(b[len(b)-4:]))
case int64T: case 64:
return int64(binary.BigEndian.Uint64(b[len(b)-8:])) return int64(binary.BigEndian.Uint64(b[len(b)-8:]))
default: default:
// the only case left for integer is int256/uint256. // the only case left for integer is int256
ret := new(big.Int).SetBytes(b)
if typ.T == UintTy {
return ret
}
// big.SetBytes can't tell if a number is negative or positive in itself. // big.SetBytes can't tell if a number is negative or positive in itself.
// On EVM, if the returned number > max int256, it is negative. // On EVM, if the returned number > max int256, it is negative.
// A number is > max int256 if the bit at position 255 is set. // A number is > max int256 if the bit at position 255 is set.
ret := new(big.Int).SetBytes(b)
if ret.Bit(255) == 1 { if ret.Bit(255) == 1 {
ret.Add(MaxUint256, new(big.Int).Neg(ret)) ret.Add(MaxUint256, new(big.Int).Neg(ret))
ret.Add(ret, common.Big1) ret.Add(ret, common.Big1)
...@@ -106,7 +110,7 @@ func ReadFixedBytes(t Type, word []byte) (interface{}, error) { ...@@ -106,7 +110,7 @@ func ReadFixedBytes(t Type, word []byte) (interface{}, error) {
return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array") return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array")
} }
// convert // convert
array := reflect.New(t.Type).Elem() array := reflect.New(t.getType()).Elem()
reflect.Copy(array, reflect.ValueOf(word[0:t.Size])) reflect.Copy(array, reflect.ValueOf(word[0:t.Size]))
return array.Interface(), nil return array.Interface(), nil
...@@ -127,10 +131,10 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) ...@@ -127,10 +131,10 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
if t.T == SliceTy { if t.T == SliceTy {
// declare our slice // declare our slice
refSlice = reflect.MakeSlice(t.Type, size, size) refSlice = reflect.MakeSlice(t.getType(), size, size)
} else if t.T == ArrayTy { } else if t.T == ArrayTy {
// declare our array // declare our array
refSlice = reflect.New(t.Type).Elem() refSlice = reflect.New(t.getType()).Elem()
} else { } else {
return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage") return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage")
} }
...@@ -154,7 +158,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) ...@@ -154,7 +158,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
} }
func forTupleUnpack(t Type, output []byte) (interface{}, error) { func forTupleUnpack(t Type, output []byte) (interface{}, error) {
retval := reflect.New(t.Type).Elem() retval := reflect.New(t.getType()).Elem()
virtualArgs := 0 virtualArgs := 0
for index, elem := range t.TupleElems { for index, elem := range t.TupleElems {
marshalledValue, err := ToGoType((index+virtualArgs)*32, *elem, output) marshalledValue, err := ToGoType((index+virtualArgs)*32, *elem, output)
......
...@@ -33,7 +33,7 @@ import ( ...@@ -33,7 +33,7 @@ import (
// TestUnpack tests the general pack/unpack tests in packing_test.go // TestUnpack tests the general pack/unpack tests in packing_test.go
func TestUnpack(t *testing.T) { func TestUnpack(t *testing.T) {
for i, test := range packUnpackTests { for i, test := range packUnpackTests {
t.Run(strconv.Itoa(i), func(t *testing.T) { t.Run(strconv.Itoa(i)+" "+test.def, func(t *testing.T) {
//Unpack //Unpack
def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def) def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def)
abi, err := JSON(strings.NewReader(def)) abi, err := JSON(strings.NewReader(def))
......
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