accounts/abi: support user defined types of solidity (#15592)

1. deploy contract that has user defined type
2. code generation ignore these functions that have user defined type argument.
This commit is contained in:
nkbai 2018-01-14 13:15:47 +08:00
parent 3f40b22dac
commit 2ab506e40e
3 changed files with 100 additions and 11 deletions

View file

@ -55,6 +55,87 @@ const jsondata2 = `
{ "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] } { "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
]` ]`
const NettingChannelLibraryABI = `
[
{
"constant": false,
"inputs": [
{
"name": "locked_encoded",
"type": "bytes"
},
{
"name": "merkle_proof",
"type": "bytes"
},
{
"name": "secret",
"type": "bytes32"
}
],
"name": "withdraw",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "self",
"type": "NettingChannelLibrary.Data storage"
},
{
"name": "amount",
"type": "uint256"
}
],
"name": "deposit",
"outputs": [
{
"name": "success",
"type": "bool"
},
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "contract_version",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
`
func TestNewUserType(t *testing.T) {
_, err := NewType("NettingChannelLibrary.Data storage")
if err != nil {
t.Error(err)
}
abi, err := JSON(strings.NewReader(NettingChannelLibraryABI))
if err != nil {
t.Error(err)
}
if _, err := abi.Pack("withdraw", []byte{1, 2, 3}, []byte{1, 2, 3}, [32]byte{1, 2, 3}); err != nil {
t.Error(err)
}
}
func TestReader(t *testing.T) { func TestReader(t *testing.T) {
Uint256, _ := NewType("uint256") Uint256, _ := NewType("uint256")
exp := ABI{ exp := ABI{

View file

@ -26,7 +26,6 @@ import (
"regexp" "regexp"
"strings" "strings"
"text/template" "text/template"
"unicode"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"golang.org/x/tools/imports" "golang.org/x/tools/imports"
@ -55,20 +54,22 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
if err != nil { if err != nil {
return "", err return "", err
} }
// Strip any whitespace from the JSON ABI
strippedABI := strings.Map(func(r rune) rune {
if unicode.IsSpace(r) {
return -1
}
return r
}, abis[i])
// Extract the call and transact methods, and sort them alphabetically // Extract the call and transact methods, and sort them alphabetically
var ( var (
calls = make(map[string]*tmplMethod) calls = make(map[string]*tmplMethod)
transacts = make(map[string]*tmplMethod) transacts = make(map[string]*tmplMethod)
) )
for _, original := range evmABI.Methods { for _, original := range evmABI.Methods {
skipMethodWithUserType := false
for _, input := range original.Inputs {
if input.Type.T == abi.UserTy {
skipMethodWithUserType = true
break
}
}
if skipMethodWithUserType {
continue //skip this method
}
// Normalize the method for capital cases and non-anonymous inputs/outputs // Normalize the method for capital cases and non-anonymous inputs/outputs
normalized := original normalized := original
normalized.Name = methodNormalizer[lang](original.Name) normalized.Name = methodNormalizer[lang](original.Name)
@ -96,7 +97,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
} }
contracts[types[i]] = &tmplContract{ contracts[types[i]] = &tmplContract{
Type: capitalise(types[i]), Type: capitalise(types[i]),
InputABI: strings.Replace(strippedABI, "\"", "\\\"", -1), InputABI: strings.Replace(abis[i], "\"", "\\\"", -1),
InputBin: strings.TrimSpace(bytecodes[i]), InputBin: strings.TrimSpace(bytecodes[i]),
Constructor: evmABI.Constructor, Constructor: evmABI.Constructor,
Calls: calls, Calls: calls,

View file

@ -38,6 +38,7 @@ const (
HashTy HashTy
FixedPointTy FixedPointTy
FunctionTy FunctionTy
UserTy
) )
// Type is the reflection of the supported argument type // Type is the reflection of the supported argument type
@ -159,7 +160,13 @@ func NewType(t string) (typ Type, err error) {
typ.Size = 24 typ.Size = 24
typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0))) typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
default: default:
return Type{}, fmt.Errorf("unsupported arg type: %s", t) //user defined types
typ.Kind = reflect.Struct
typ.T = UserTy
typ.Size = -1
typ.Type = reflect.TypeOf(struct{}{})
//default:
// return Type{}, fmt.Errorf("unsupported arg type: %s", t)
} }
return return