Skip to content

Commit e5710c3

Browse files
committed
accounts, abi: method signature fix and some other fixes
1 parent fb75910 commit e5710c3

File tree

7 files changed

+401
-311
lines changed

7 files changed

+401
-311
lines changed

accounts/abi/abi_test.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,10 @@ import (
2222
"fmt"
2323
"log"
2424
"math/big"
25+
"reflect"
2526
"strings"
2627
"testing"
2728

28-
"reflect"
29-
3029
"github.com/ethereum/go-ethereum/common"
3130
"github.com/ethereum/go-ethereum/crypto"
3231
)
@@ -198,6 +197,25 @@ func TestMethodSignature(t *testing.T) {
198197
if m.Sig() != exp {
199198
t.Error("signature mismatch", exp, "!=", m.Sig())
200199
}
200+
201+
// Method with tuple arguments
202+
s, _ := NewType("tuple", []ArgumentMarshaling{
203+
{Name: "a", Type: "int256"},
204+
{Name: "b", Type: "int256[]"},
205+
{Name: "c", Type: "tuple[]", Components: []ArgumentMarshaling{
206+
{Name: "x", Type: "int256"},
207+
{Name: "y", Type: "int256"},
208+
}},
209+
{Name: "d", Type: "tuple[2]", Components: []ArgumentMarshaling{
210+
{Name: "x", Type: "int256"},
211+
{Name: "y", Type: "int256"},
212+
}},
213+
})
214+
m = Method{"foo", false, []Argument{{"s", s, false}, {"bar", String, false}}, nil}
215+
exp = "foo((int256,int256[],(int256,int256)[],(int256,int256)[2]),string)"
216+
if m.Sig() != exp {
217+
t.Error("signature mismatch", exp, "!=", m.Sig())
218+
}
201219
}
202220

203221
func TestMultiPack(t *testing.T) {
@@ -567,11 +585,13 @@ func TestBareEvents(t *testing.T) {
567585
const definition = `[
568586
{ "type" : "event", "name" : "balance" },
569587
{ "type" : "event", "name" : "anon", "anonymous" : true},
570-
{ "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] }
588+
{ "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] },
589+
{ "type" : "event", "name" : "tuple", "inputs" : [{ "indexed":false, "name":"t", "type":"tuple", "components":[{"name":"a", "type":"uint256"}] }, { "indexed":true, "name":"arg1", "type":"address" }] }
571590
]`
572591

573592
arg0, _ := NewType("uint256", nil)
574593
arg1, _ := NewType("address", nil)
594+
tuple, _ := NewType("tuple", []ArgumentMarshaling{{Name: "a", Type: "uint256"}})
575595

576596
expectedEvents := map[string]struct {
577597
Anonymous bool
@@ -583,6 +603,10 @@ func TestBareEvents(t *testing.T) {
583603
{Name: "arg0", Type: arg0, Indexed: false},
584604
{Name: "arg1", Type: arg1, Indexed: true},
585605
}},
606+
"tuple": {false, []Argument{
607+
{Name: "t", Type: tuple, Indexed: false},
608+
{Name: "arg1", Type: arg1, Indexed: true},
609+
}},
586610
}
587611

588612
abi, err := JSON(strings.NewReader(definition))
@@ -649,9 +673,9 @@ func TestUnpackEvent(t *testing.T) {
649673
}
650674

651675
type ReceivedEvent struct {
652-
Address common.Address
653-
Amount *big.Int
654-
Memo []byte
676+
Sender common.Address
677+
Amount *big.Int
678+
Memo []byte
655679
}
656680
var ev ReceivedEvent
657681

accounts/abi/argument.go

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,18 @@ type ArgumentMarshaling struct {
4242

4343
// UnmarshalJSON implements json.Unmarshaler interface
4444
func (argument *Argument) UnmarshalJSON(data []byte) error {
45-
var dec ArgumentMarshaling
46-
err := json.Unmarshal(data, &dec)
45+
var arg ArgumentMarshaling
46+
err := json.Unmarshal(data, &arg)
4747
if err != nil {
4848
return fmt.Errorf("argument json err: %v", err)
4949
}
5050

51-
argument.Type, err = NewType(dec.Type, dec.Components)
51+
argument.Type, err = NewType(arg.Type, arg.Components)
5252
if err != nil {
5353
return err
5454
}
55-
argument.Name = dec.Name
56-
argument.Indexed = dec.Indexed
55+
argument.Name = arg.Name
56+
argument.Indexed = arg.Indexed
5757

5858
return nil
5959
}
@@ -97,13 +97,13 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error {
9797
return err
9898
}
9999
if arguments.isTuple() {
100-
return unpackTuple(arguments, v, marshalledValues)
100+
return arguments.unpackTuple(v, marshalledValues)
101101
}
102-
return unpackAtomic(arguments[0], v, marshalledValues[0])
102+
return arguments.unpackAtomic(v, marshalledValues[0])
103103
}
104104

105105
// unpack sets the unmarshalled value to go format.
106-
// Note the dst here must is settable.
106+
// Note the dst here must be settable.
107107
func unpack(t *Type, dst interface{}, src interface{}) error {
108108
var (
109109
dstVal = reflect.ValueOf(dst).Elem()
@@ -119,13 +119,17 @@ func unpack(t *Type, dst interface{}, src interface{}) error {
119119
if dstVal.Kind() != reflect.Struct {
120120
return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind())
121121
}
122+
fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal)
123+
if err != nil {
124+
return err
125+
}
122126
for i, elem := range t.TupleElems {
123-
fname := t.Type.Field(i).Name
127+
fname := fieldmap[t.TupleRawNames[i]]
124128
field := dstVal.FieldByName(fname)
125129
if !field.IsValid() {
126-
return fmt.Errorf("abi: field %s can't found in the given value", fname)
130+
return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i])
127131
}
128-
if err := unpack(elem, field.Addr().Interface(), srcVal.FieldByName(fname).Interface()); err != nil {
132+
if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil {
129133
return err
130134
}
131135
}
@@ -156,15 +160,20 @@ func unpack(t *Type, dst interface{}, src interface{}) error {
156160
return nil
157161
}
158162

159-
func unpackAtomic(argument Argument, v interface{}, marshalledValues interface{}) error {
163+
// unpackAtomic unpacks ( hexdata -> go ) a single value
164+
func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
165+
if arguments.LengthNonIndexed() == 0 {
166+
return nil
167+
}
168+
argument := arguments.NonIndexed()[0]
160169
elem := reflect.ValueOf(v).Elem()
161170

162171
if elem.Kind() == reflect.Struct {
163-
structMap, err := mapToStructFields([]string{argument.Name}, elem)
172+
fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem)
164173
if err != nil {
165174
return err
166175
}
167-
field := elem.FieldByName(structMap[argument.Name])
176+
field := elem.FieldByName(fieldmap[argument.Name])
168177
if !field.IsValid() {
169178
return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name)
170179
}
@@ -173,7 +182,8 @@ func unpackAtomic(argument Argument, v interface{}, marshalledValues interface{}
173182
return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues)
174183
}
175184

176-
func unpackTuple(arguments Arguments, v interface{}, marshalledValues []interface{}) error {
185+
// unpackTuple unpacks ( hexdata -> go ) a batch of values.
186+
func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
177187
var (
178188
value = reflect.ValueOf(v).Elem()
179189
typ = value.Type()
@@ -184,16 +194,16 @@ func unpackTuple(arguments Arguments, v interface{}, marshalledValues []interfac
184194
}
185195

186196
// If the interface is a struct, get of abi->struct_field mapping
187-
var (
188-
abi2struct map[string]string
189-
err error
190-
)
197+
var abi2struct map[string]string
191198
if kind == reflect.Struct {
192-
var argNames []string
193-
for _, arg := range arguments {
199+
var (
200+
argNames []string
201+
err error
202+
)
203+
for _, arg := range arguments.NonIndexed() {
194204
argNames = append(argNames, arg.Name)
195205
}
196-
abi2struct, err = mapToStructFields(argNames, value)
206+
abi2struct, err = mapArgNamesToStructFields(argNames, value)
197207
if err != nil {
198208
return err
199209
}

accounts/abi/pack_test.go

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -481,12 +481,12 @@ func TestPack(t *testing.T) {
481481
{Name: "f", Type: "address[]"},
482482
},
483483
struct {
484-
A string
485-
B int64
486-
C []byte
487-
D []string
488-
E []*big.Int
489-
F []common.Address
484+
FieldA string `abi:"a"` // Test whether abi tag works
485+
FieldB int64 `abi:"b"`
486+
C []byte
487+
D []string
488+
E []*big.Int
489+
F []common.Address
490490
}{"foobar", 1, []byte{1}, []string{"foo", "bar"}, []*big.Int{big.NewInt(1), big.NewInt(-1)}, []common.Address{{1}, {2}}},
491491
common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000c0" + // struct[a] offset
492492
"0000000000000000000000000000000000000000000000000000000000000001" + // struct[b]
@@ -521,14 +521,14 @@ func TestPack(t *testing.T) {
521521
},
522522
struct {
523523
A struct {
524-
A *big.Int
525-
B []*big.Int
524+
FieldA *big.Int `abi:"a"`
525+
B []*big.Int
526526
}
527527
B []*big.Int
528528
}{
529529
A: struct {
530-
A *big.Int
531-
B []*big.Int
530+
FieldA *big.Int `abi:"a"` // Test whether abi tag works for nested tuple
531+
B []*big.Int
532532
}{big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(0)}},
533533
B: []*big.Int{big.NewInt(1), big.NewInt(0)}},
534534
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040" + // a offset
@@ -589,6 +589,29 @@ func TestPack(t *testing.T) {
589589
"0000000000000000000000000000000000000000000000000000000000000001" + // tuple[1].a
590590
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), // tuple[1].b
591591
},
592+
{
593+
// dynamic tuple array
594+
"tuple[2]",
595+
[]ArgumentMarshaling{
596+
{Name: "a", Type: "int256[]"},
597+
},
598+
[2]struct {
599+
A []*big.Int
600+
}{
601+
{[]*big.Int{big.NewInt(-1), big.NewInt(1)}},
602+
{[]*big.Int{big.NewInt(1), big.NewInt(-1)}},
603+
},
604+
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040" + // tuple[0] offset
605+
"00000000000000000000000000000000000000000000000000000000000000c0" + // tuple[1] offset
606+
"0000000000000000000000000000000000000000000000000000000000000020" + // tuple[0].A offset
607+
"0000000000000000000000000000000000000000000000000000000000000002" + // tuple[0].A length
608+
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + // tuple[0].A[0]
609+
"0000000000000000000000000000000000000000000000000000000000000001" + // tuple[0].A[1]
610+
"0000000000000000000000000000000000000000000000000000000000000020" + // tuple[1].A offset
611+
"0000000000000000000000000000000000000000000000000000000000000002" + // tuple[1].A length
612+
"0000000000000000000000000000000000000000000000000000000000000001" + // tuple[1].A[0]
613+
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), // tuple[1].A[1]
614+
},
592615
} {
593616
typ, err := NewType(test.typ, test.components)
594617
if err != nil {
@@ -716,7 +739,6 @@ func TestMethodPack(t *testing.T) {
716739
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
717740
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
718741
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
719-
720742
packed, err = abi.Pack("nestedSlice", [][]uint8{{1, 2}, {1, 2}})
721743
if err != nil {
722744
t.Fatal(err)

accounts/abi/reflect.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,14 @@ func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind,
126126
return nil
127127
}
128128

129-
// mapToStringField maps a slice of argument names to struct fields.
129+
// mapArgNamesToStructFields maps a slice of argument names to struct fields.
130130
// first round: for each Exportable field that contains a `abi:""` tag
131131
// and this field name exists in the given argument name list, pair them together.
132132
// second round: for each argument name that has not been already linked,
133133
// find what variable is expected to be mapped into, if it exists and has not been
134134
// used, pair them.
135135
// Note this function assumes the given value is a struct value.
136-
func mapToStructFields(argNames []string, value reflect.Value) (map[string]string, error) {
136+
func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[string]string, error) {
137137
typ := value.Type()
138138

139139
abi2struct := make(map[string]string)

0 commit comments

Comments
 (0)