Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate Java structs #7

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion accounts/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
// we need to decide whether we're calling a method or an event
if method, ok := abi.Methods[name]; ok {
if len(data)%32 != 0 {
return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data)
return fmt.Errorf("abi: improperly formatted output: length: %d - %s - Bytes: [%+v]", len(data), string(data), data)
}
return method.Outputs.Unpack(v, data)
}
Expand Down
5 changes: 0 additions & 5 deletions accounts/abi/bind/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ package bind

import (
"bytes"
"errors"
"fmt"
"go/format"
"regexp"
Expand Down Expand Up @@ -165,10 +164,6 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
if evmABI.HasReceive() {
receive = &tmplMethod{Original: evmABI.Receive}
}
// There is no easy way to pass arbitrary java objects to the Go side.
if len(structs) > 0 && lang == LangJava {
return "", errors.New("java binding for tuple arguments is not supported yet")
}

contracts[types[i]] = &tmplContract{
Type: capitalise(types[i]),
Expand Down
17 changes: 16 additions & 1 deletion accounts/abi/bind/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2150,7 +2150,7 @@ public class Test {
for _, line := range lines {
if strings.TrimSpace(line) != "" {
lines[index] = line
index += 1
index++
}
}
lines = lines[:index]
Expand All @@ -2163,3 +2163,18 @@ public class Test {
}
}
}

// Tests binding the bindTests succeeds (does not execute test cases, only checks binding errors)
func TestGenerateBindingingJava(t *testing.T) {
// Generate the test suite for all the contracts
for _, tt := range bindTests {
bind, err := Bind([]string{tt.name}, tt.abi, tt.bytecode, nil, "bindtest", LangJava, nil, tt.aliases)
if err != nil {
t.Fatalf("test %s: failed to generate binding: %v", tt.name, err)
}
if err := ioutil.WriteFile("/home/matematik/j-bindings/"+tt.name, []byte(bind), 0600); err != nil {
t.Fatal(err)
}

}
}
8 changes: 8 additions & 0 deletions accounts/abi/bind/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,14 @@ import java.util.*;
this(Geth.bindContract(address, ABI, client));
}

{{range $structs}}
// {{capitalise .Name}} is an auto generated low-level Java binding around an user-defined struct.
public class {{capitalise .Name}} {
{{range $index, $item := .Fields}}public {{$item.Type}} {{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}};
{{end}}
}
{{end}}

{{range .Calls}}
{{if gt (len .Normalized.Outputs) 1}}
// {{capitalise .Normalized.Name}}Results is the output of a call to {{.Normalized.Name}}.
Expand Down
14 changes: 7 additions & 7 deletions accounts/abi/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ func formatSliceString(kind reflect.Kind, sliceSize int) string {
// type in t.
func sliceTypeCheck(t Type, val reflect.Value) error {
if val.Kind() != reflect.Slice && val.Kind() != reflect.Array {
return typeErr(formatSliceString(t.getType().Kind(), t.Size), val.Type())
return typeErr(formatSliceString(t.GetType().Kind(), t.Size), val.Type())
}

if t.T == ArrayTy && val.Len() != t.Size {
return typeErr(formatSliceString(t.Elem.getType().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 {
Expand All @@ -52,8 +52,8 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
}
}

if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.getType().Kind() {
return typeErr(formatSliceString(t.Elem.getType().Kind(), t.Size), val.Type())
if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.GetType().Kind() {
return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), val.Type())
}
return nil
}
Expand All @@ -66,10 +66,10 @@ func typeCheck(t Type, value reflect.Value) error {
}

// Check base type validity. Element types will be checked later on.
if t.getType().Kind() != value.Kind() {
return typeErr(t.getType().Kind(), value.Kind())
if t.GetType().Kind() != value.Kind() {
return typeErr(t.GetType().Kind(), value.Kind())
} else if t.T == FixedBytesTy && t.Size != value.Len() {
return typeErr(t.getType(), value.Type())
return typeErr(t.GetType(), value.Type())
} else {
return nil
}
Expand Down
8 changes: 4 additions & 4 deletions accounts/abi/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
}
fields = append(fields, reflect.StructField{
Name: ToCamelCase(c.Name), // reflect.StructOf will panic for any exported field.
Type: cType.getType(),
Type: cType.GetType(),
Tag: reflect.StructTag("json:\"" + c.Name + "\""),
})
elems = append(elems, &cType)
Expand Down Expand Up @@ -211,7 +211,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
return
}

func (t Type) getType() reflect.Type {
func (t Type) GetType() reflect.Type {
switch t.T {
case IntTy:
return reflectIntType(false, t.Size)
Expand All @@ -222,9 +222,9 @@ func (t Type) getType() reflect.Type {
case StringTy:
return reflect.TypeOf("")
case SliceTy:
return reflect.SliceOf(t.Elem.getType())
return reflect.SliceOf(t.Elem.GetType())
case ArrayTy:
return reflect.ArrayOf(t.Size, t.Elem.getType())
return reflect.ArrayOf(t.Size, t.Elem.GetType())
case TupleTy:
return t.TupleType
case AddressTy:
Expand Down
8 changes: 4 additions & 4 deletions accounts/abi/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,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")
}
// convert
array := reflect.New(t.getType()).Elem()
array := reflect.New(t.GetType()).Elem()

reflect.Copy(array, reflect.ValueOf(word[0:t.Size]))
return array.Interface(), nil
Expand All @@ -131,10 +131,10 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)

if t.T == SliceTy {
// declare our slice
refSlice = reflect.MakeSlice(t.getType(), size, size)
refSlice = reflect.MakeSlice(t.GetType(), size, size)
} else if t.T == ArrayTy {
// declare our array
refSlice = reflect.New(t.getType()).Elem()
refSlice = reflect.New(t.GetType()).Elem()
} else {
return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage")
}
Expand All @@ -158,7 +158,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
}

func forTupleUnpack(t Type, output []byte) (interface{}, error) {
retval := reflect.New(t.getType()).Elem()
retval := reflect.New(t.GetType()).Elem()
virtualArgs := 0
for index, elem := range t.TupleElems {
marshalledValue, err := ToGoType((index+virtualArgs)*32, *elem, output)
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ require (
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
golang.org/x/mobile v0.0.0-20200329125638-4c31acba0007 // indirect
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 // indirect
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f
golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
golang.org/x/text v0.3.2
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
Expand Down
24 changes: 24 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
Expand Down Expand Up @@ -188,16 +189,32 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20200329125638-4c31acba0007 h1:JxsyO7zPDWn1rBZW8FV5RFwCKqYeXnyaS/VQPLpXu6I=
golang.org/x/mobile v0.0.0-20200329125638-4c31acba0007/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd h1:ePuNC7PZ6O5BzgPn9bZayERXBdfZjUYoXEf5BTfDfh8=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -210,6 +227,13 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69 h1:yBHHx+XZqXJBm6Exke3N7V9gnlsyXxoCPEb1yVenjfk=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
Expand Down
77 changes: 71 additions & 6 deletions mobile/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
package geth

import (
"encoding/json"
"errors"
"math/big"
"reflect"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)

Expand Down Expand Up @@ -116,8 +119,9 @@ func (i *Interface) SetUint64s(bigints *BigInts) {
}
i.object = &ints
}
func (i *Interface) SetBigInt(bigint *BigInt) { i.object = &bigint.bigint }
func (i *Interface) SetBigInts(bigints *BigInts) { i.object = &bigints.bigints }
func (i *Interface) SetBigInt(bigint *BigInt) { i.object = &bigint.bigint }
func (i *Interface) SetBigInts(bigints *BigInts) { i.object = &bigints.bigints }
func (i *Interface) SetInterfaces(ifaces *Interfaces) { i.object = &ifaces.objects }

func (i *Interface) SetDefaultBool() { i.object = new(bool) }
func (i *Interface) SetDefaultBools() { i.object = new([]bool) }
Expand Down Expand Up @@ -238,8 +242,9 @@ func (i *Interface) GetUint64s() *BigInts {
}
return bigints
}
func (i *Interface) GetBigInt() *BigInt { return &BigInt{*i.object.(**big.Int)} }
func (i *Interface) GetBigInts() *BigInts { return &BigInts{*i.object.(*[]*big.Int)} }
func (i *Interface) GetBigInt() *BigInt { return &BigInt{*i.object.(**big.Int)} }
func (i *Interface) GetBigInts() *BigInts { return &BigInts{*i.object.(*[]*big.Int)} }
func (i *Interface) GetInterfaces() *Interfaces { return &Interfaces{*i.object.(*[]interface{})} }

// Interfaces is a slices of wrapped generic objects.
type Interfaces struct {
Expand All @@ -251,12 +256,66 @@ func NewInterfaces(size int) *Interfaces {
return &Interfaces{objects: make([]interface{}, size)}
}

// NewInterfacesFromJSON creates a new Interface slice that contains the
// prototype of types defined in the input json.
func NewInterfacesFromJSON(definition string, data *Interfaces) (*Interface, error) {
tuple, err := tupleFromJSON(definition)
if err != nil {
return nil, err
}

fld := tuple.Elem().Field(0)
for idx, elem := range data.objects {
fieldValue := fld.Field(idx)
if fieldValue.IsValid() {
val := reflect.Indirect(reflect.ValueOf(elem))
fieldValue.Set(val)
} else {
return nil, errors.New("Could not find field, json does not match provided struct")
}
}

return &Interface{fld.Interface()}, nil
}

// NewInterfacesFromJSONDefault creates a new Interface slice that contains the
// prototype of types defined in the input json.
func NewInterfacesFromJSONDefault(definition string) (*Interface, error) {
tuple, err := tupleFromJSON(definition)
if err != nil {
return nil, err
}

fld := tuple.Elem().Field(0)
return &Interface{fld.Addr().Interface()}, nil
}

// tupleFromJSON creates a new tuple as defined in the definition
func tupleFromJSON(definition string) (reflect.Value, error) {
var field struct {
Inputs abi.Arguments
}
if err := json.Unmarshal([]byte(definition), &field); err != nil {
return reflect.Value{}, err
}

var structFields []reflect.StructField
for _, in := range field.Inputs {
structFields = append(structFields, reflect.StructField{
Name: abi.ToCamelCase(in.Name), // reflect.StructOf will panic for any exported field.
Type: in.Type.GetType(),
Tag: reflect.StructTag("json:\"" + in.Name + "\""),
})
}
return reflect.New(reflect.StructOf(structFields)), nil
}

// Size returns the number of interfaces in the slice.
func (i *Interfaces) Size() int {
return len(i.objects)
}

// Get returns the bigint at the given index from the slice.
// Get returns the interface at the given index from the slice.
// Notably the returned value can be changed without affecting the
// interfaces itself.
func (i *Interfaces) Get(index int) (iface *Interface, _ error) {
Expand All @@ -266,11 +325,17 @@ func (i *Interfaces) Get(index int) (iface *Interface, _ error) {
return &Interface{object: i.objects[index]}, nil
}

// Set sets the big int at the given index in the slice.
// Set sets the interface at the given index in the slice.
func (i *Interfaces) Set(index int, object *Interface) error {
if index < 0 || index >= len(i.objects) {
return errors.New("index out of bounds")
}
i.objects[index] = object.object
return nil
}

func (i *Interfaces) SetInterfaces(index int, objects *Interfaces) error {
var in Interface
in.SetInterfaces(objects)
return i.Set(index, &in)
}
Loading