aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-01-09 17:49:17 +0800
committerGitHub <noreply@github.com>2017-01-09 17:49:17 +0800
commit88cc1ca55a57f6024bedd9499288f870d4b12df4 (patch)
treef300d80b32a3b06f15d60b2edfeb20f673ddb0ce
parent808310a5692cb372754064ade6ed21e92f5c7342 (diff)
parent1bd9769111133f01faa20b8665c7adf916b6d50a (diff)
downloaddexon-88cc1ca55a57f6024bedd9499288f870d4b12df4.tar
dexon-88cc1ca55a57f6024bedd9499288f870d4b12df4.tar.gz
dexon-88cc1ca55a57f6024bedd9499288f870d4b12df4.tar.bz2
dexon-88cc1ca55a57f6024bedd9499288f870d4b12df4.tar.lz
dexon-88cc1ca55a57f6024bedd9499288f870d4b12df4.tar.xz
dexon-88cc1ca55a57f6024bedd9499288f870d4b12df4.tar.zst
dexon-88cc1ca55a57f6024bedd9499288f870d4b12df4.zip
Merge pull request #3533 from karalabe/modum-io-develop-2
accounts/abi: support custom int slice types
-rw-r--r--accounts/abi/abi.go48
-rw-r--r--accounts/abi/abi_test.go24
-rw-r--r--accounts/abi/type.go14
-rw-r--r--accounts/abi/type_test.go24
4 files changed, 93 insertions, 17 deletions
diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go
index c3d49da66..627a2a0c4 100644
--- a/accounts/abi/abi.go
+++ b/accounts/abi/abi.go
@@ -91,8 +91,30 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
// first we need to create a slice of the type
var refSlice reflect.Value
switch elem.T {
- case IntTy, UintTy, BoolTy: // int, uint, bool can all be of type big int.
- refSlice = reflect.ValueOf([]*big.Int(nil))
+ case IntTy, UintTy, BoolTy:
+ // create a new reference slice matching the element type
+ switch t.Type.Kind {
+ case reflect.Bool:
+ refSlice = reflect.ValueOf([]bool(nil))
+ case reflect.Uint8:
+ refSlice = reflect.ValueOf([]uint8(nil))
+ case reflect.Uint16:
+ refSlice = reflect.ValueOf([]uint16(nil))
+ case reflect.Uint32:
+ refSlice = reflect.ValueOf([]uint32(nil))
+ case reflect.Uint64:
+ refSlice = reflect.ValueOf([]uint64(nil))
+ case reflect.Int8:
+ refSlice = reflect.ValueOf([]int8(nil))
+ case reflect.Int16:
+ refSlice = reflect.ValueOf([]int16(nil))
+ case reflect.Int32:
+ refSlice = reflect.ValueOf([]int32(nil))
+ case reflect.Int64:
+ refSlice = reflect.ValueOf([]int64(nil))
+ default:
+ refSlice = reflect.ValueOf([]*big.Int(nil))
+ }
case AddressTy: // address must be of slice Address
refSlice = reflect.ValueOf([]common.Address(nil))
case HashTy: // hash must be of slice hash
@@ -147,7 +169,27 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
// set inter to the correct type (cast)
switch elem.T {
case IntTy, UintTy:
- inter = common.BytesToBig(returnOutput)
+ bigNum := common.BytesToBig(returnOutput)
+ switch t.Type.Kind {
+ case reflect.Uint8:
+ inter = uint8(bigNum.Uint64())
+ case reflect.Uint16:
+ inter = uint16(bigNum.Uint64())
+ case reflect.Uint32:
+ inter = uint32(bigNum.Uint64())
+ case reflect.Uint64:
+ inter = bigNum.Uint64()
+ case reflect.Int8:
+ inter = int8(bigNum.Int64())
+ case reflect.Int16:
+ inter = int16(bigNum.Int64())
+ case reflect.Int32:
+ inter = int32(bigNum.Int64())
+ case reflect.Int64:
+ inter = bigNum.Int64()
+ default:
+ inter = common.BytesToBig(returnOutput)
+ }
case BoolTy:
inter = common.BytesToBig(returnOutput).Uint64() > 0
case AddressTy:
diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go
index 1e5ee0efe..a45bd6cc0 100644
--- a/accounts/abi/abi_test.go
+++ b/accounts/abi/abi_test.go
@@ -332,6 +332,30 @@ func TestUnpackSetInterfaceSlice(t *testing.T) {
}
}
+func TestUnpackSetInterfaceArrayOutput(t *testing.T) {
+ var (
+ var1 = new([1]uint32)
+ var2 = new([1]uint32)
+ )
+ out := []interface{}{var1, var2}
+ abi, err := JSON(strings.NewReader(`[{"type":"function", "name":"ints", "outputs":[{"type":"uint32[1]"}, {"type":"uint32[1]"}]}]`))
+ if err != nil {
+ t.Fatal(err)
+ }
+ marshalledReturn := append(pad([]byte{1}, 32, true), pad([]byte{2}, 32, true)...)
+ err = abi.Unpack(&out, "ints", marshalledReturn)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if *var1 != [1]uint32{1} {
+ t.Error("expected var1 to be [1], got", *var1)
+ }
+ if *var2 != [1]uint32{2} {
+ t.Error("expected var2 to be [2], got", *var2)
+ }
+}
+
func TestPack(t *testing.T) {
for i, test := range []struct {
typ string
diff --git a/accounts/abi/type.go b/accounts/abi/type.go
index 2bd341bd2..ed3e33f39 100644
--- a/accounts/abi/type.go
+++ b/accounts/abi/type.go
@@ -91,7 +91,12 @@ func NewType(t string) (typ Type, err error) {
}
typ.Elem = &sliceType
typ.stringKind = sliceType.stringKind + t[len(res[1]):]
- return typ, nil
+ // Altough we know that this is an array, we cannot return
+ // as we don't know the type of the element, however, if it
+ // is still an array, then don't determine the type.
+ if typ.Elem.IsArray || typ.Elem.IsSlice {
+ return typ, nil
+ }
}
// parse the type and size of the abi-type.
@@ -112,7 +117,12 @@ func NewType(t string) (typ Type, err error) {
varSize = 256
t += "256"
}
- typ.stringKind = t
+
+ // only set stringKind if not array or slice, as for those,
+ // the correct string type has been set
+ if !(typ.IsArray || typ.IsSlice) {
+ typ.stringKind = t
+ }
switch varType {
case "int":
diff --git a/accounts/abi/type_test.go b/accounts/abi/type_test.go
index bf776cf09..1557c2a41 100644
--- a/accounts/abi/type_test.go
+++ b/accounts/abi/type_test.go
@@ -34,17 +34,17 @@ func TestTypeRegexp(t *testing.T) {
{"int", Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}},
{"int8", Type{Kind: reflect.Int8, Type: big_t, Size: 8, T: IntTy, stringKind: "int8"}},
{"int256", Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}},
- {"int[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}},
- {"int[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}},
- {"int32[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}},
- {"int32[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}},
+ {"int[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}},
+ {"int[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}},
+ {"int32[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, Elem: &Type{Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}},
+ {"int32[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, Elem: &Type{Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}},
{"uint", Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}},
{"uint8", Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}},
{"uint256", Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}},
- {"uint[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}},
- {"uint[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}},
- {"uint32[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Uint32, Type: big_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}},
- {"uint32[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{Kind: reflect.Uint32, Type: big_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}},
+ {"uint[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, Elem: &Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}},
+ {"uint[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, Elem: &Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}},
+ {"uint32[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Uint32, Type: ubig_t, Size: 32, T: UintTy, Elem: &Type{Kind: reflect.Uint32, Type: big_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}},
+ {"uint32[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Uint32, Type: ubig_t, Size: 32, T: UintTy, Elem: &Type{Kind: reflect.Uint32, Type: big_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}},
{"bytes", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: BytesTy, stringKind: "bytes"}},
{"bytes32", Type{IsArray: true, SliceSize: 32, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: FixedBytesTy, stringKind: "bytes32"}},
{"bytes[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[]"}},
@@ -52,11 +52,11 @@ func TestTypeRegexp(t *testing.T) {
{"bytes32[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{IsArray: true, SliceSize: 32, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: FixedBytesTy, stringKind: "bytes32"}, stringKind: "bytes32[]"}},
{"bytes32[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{IsArray: true, SliceSize: 32, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: FixedBytesTy, stringKind: "bytes32"}, stringKind: "bytes32[2]"}},
{"string", Type{Kind: reflect.String, Size: -1, T: StringTy, stringKind: "string"}},
- {"string[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.String, Size: -1, T: StringTy, stringKind: "string"}, stringKind: "string[]"}},
- {"string[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{Kind: reflect.String, Size: -1, T: StringTy, stringKind: "string"}, stringKind: "string[2]"}},
+ {"string[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.String, T: StringTy, Size: -1, Elem: &Type{Kind: reflect.String, T: StringTy, Size: -1, stringKind: "string"}, stringKind: "string[]"}},
+ {"string[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.String, T: StringTy, Size: -1, Elem: &Type{Kind: reflect.String, T: StringTy, Size: -1, stringKind: "string"}, stringKind: "string[2]"}},
{"address", Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}},
- {"address[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}},
- {"address[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}},
+ {"address[]", Type{IsSlice: true, SliceSize: -1,Kind: reflect.Array, Type:address_t, T: AddressTy, Size:20, Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}},
+ {"address[2]", Type{IsArray: true, SliceSize: 2,Kind: reflect.Array, Type:address_t, T: AddressTy, Size:20, Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}},
// TODO when fixed types are implemented properly
// {"fixed", Type{}},