Просмотр исходного кода

accounts/abi: add support for function types (#3405)

RJ 8 лет назад
Родитель
Сommit
2126d81488
4 измененных файлов с 24 добавлено и 4 удалено
  1. 2 2
      accounts/abi/abi.go
  2. 13 0
      accounts/abi/abi_test.go
  3. 1 1
      accounts/abi/packing.go
  4. 8 1
      accounts/abi/type.go

+ 2 - 2
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

+ 13 - 0
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 {

+ 1 - 1
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)
 		}

+ 8 - 1
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++ {