From 2126d8148806b6d8597d6a1c761080e9dc98d745 Mon Sep 17 00:00:00 2001 From: RJ Date: Thu, 5 Jan 2017 04:46:44 -0600 Subject: [PATCH] accounts/abi: add support for function types (#3405) --- accounts/abi/abi.go | 4 ++-- accounts/abi/abi_test.go | 13 +++++++++++++ accounts/abi/packing.go | 2 +- accounts/abi/type.go | 9 ++++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go index 4e02ae5f19..c3d49da66e 100644 --- a/accounts/abi/abi.go +++ b/accounts/abi/abi.go @@ -169,7 +169,7 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) { // argument in T. func toGoType(i int, t Argument, output []byte) (interface{}, error) { // we need to treat slices differently - if (t.Type.IsSlice || t.Type.IsArray) && t.Type.T != BytesTy && t.Type.T != StringTy && t.Type.T != FixedBytesTy { + if (t.Type.IsSlice || t.Type.IsArray) && t.Type.T != BytesTy && t.Type.T != StringTy && t.Type.T != FixedBytesTy && t.Type.T != FunctionTy { return toGoSlice(i, t, output) } @@ -233,7 +233,7 @@ func toGoType(i int, t Argument, output []byte) (interface{}, error) { return common.BytesToAddress(returnOutput), nil case HashTy: return common.BytesToHash(returnOutput), nil - case BytesTy, FixedBytesTy: + case BytesTy, FixedBytesTy, FunctionTy: return returnOutput, nil case StringTy: return string(returnOutput), nil diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go index 99c46df0d4..b1bfcb012a 100644 --- a/accounts/abi/abi_test.go +++ b/accounts/abi/abi_test.go @@ -81,6 +81,7 @@ func TestTypeCheck(t *testing.T) { {"bytes", common.Hash{1}, ""}, {"string", "hello world", ""}, {"bytes32[]", [][32]byte{[32]byte{}}, ""}, + {"function", [24]byte{}, ""}, } { typ, err := NewType(test.typ) if err != nil { @@ -197,6 +198,13 @@ func TestSimpleMethodUnpack(t *testing.T) { "interface", "", }, + { + `[ { "type": "function" } ]`, + pad([]byte{1}, 32, false), + [24]byte{1}, + "function", + "", + }, } { abiDefinition := fmt.Sprintf(`[{ "name" : "method", "outputs": %s}]`, test.def) abi, err := JSON(strings.NewReader(abiDefinition)) @@ -255,6 +263,10 @@ func TestSimpleMethodUnpack(t *testing.T) { var v common.Hash err = abi.Unpack(&v, "method", test.marshalledOutput) outvar = v + case "function": + var v [24]byte + err = abi.Unpack(&v, "method", test.marshalledOutput) + outvar = v case "interface": err = abi.Unpack(&outvar, "method", test.marshalledOutput) default: @@ -333,6 +345,7 @@ func TestPack(t *testing.T) { {"uint256[]", []*big.Int{big.NewInt(1), big.NewInt(2)}, formatSliceOutput([]byte{1}, []byte{2})}, {"address[]", []common.Address{common.Address{1}, common.Address{2}}, formatSliceOutput(pad([]byte{1}, 20, false), pad([]byte{2}, 20, false))}, {"bytes32[]", []common.Hash{common.Hash{1}, common.Hash{2}}, formatSliceOutput(pad([]byte{1}, 32, false), pad([]byte{2}, 32, false))}, + {"function", [24]byte{1}, pad([]byte{1}, 32, false)}, } { typ, err := NewType(test.typ) if err != nil { diff --git a/accounts/abi/packing.go b/accounts/abi/packing.go index 0c37edf174..5054dcf138 100644 --- a/accounts/abi/packing.go +++ b/accounts/abi/packing.go @@ -54,7 +54,7 @@ func packElement(t Type, reflectValue reflect.Value) []byte { reflectValue = mustArrayToByteSlice(reflectValue) } return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()) - case FixedBytesTy: + case FixedBytesTy, FunctionTy: if reflectValue.Kind() == reflect.Array { reflectValue = mustArrayToByteSlice(reflectValue) } diff --git a/accounts/abi/type.go b/accounts/abi/type.go index 32089ce693..7af7ff386f 100644 --- a/accounts/abi/type.go +++ b/accounts/abi/type.go @@ -34,6 +34,7 @@ const ( BytesTy HashTy FixedpointTy + FunctionTy ) // Type is the reflection of the supported argument type @@ -148,6 +149,12 @@ func NewType(t string) (typ Type, err error) { typ.T = FixedBytesTy typ.SliceSize = varSize } + case "function": + sliceType, _ := NewType("uint8") + typ.Elem = &sliceType + typ.IsArray = true + typ.T = FunctionTy + typ.SliceSize = 24 default: return Type{}, fmt.Errorf("unsupported arg type: %s", t) } @@ -168,7 +175,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) { return nil, err } - if (t.IsSlice || t.IsArray) && t.T != BytesTy && t.T != FixedBytesTy { + if (t.IsSlice || t.IsArray) && t.T != BytesTy && t.T != FixedBytesTy && t.T != FunctionTy { var packed []byte for i := 0; i < v.Len(); i++ {