Skip to content

Commit 4880868

Browse files
committed
accounts/abi: fixed string and fixed size bytes packing
1 parent c3d5250 commit 4880868

File tree

6 files changed

+137
-85
lines changed

6 files changed

+137
-85
lines changed

accounts/abi/abi.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,13 @@ func toGoType(i int, t Argument, output []byte) (interface{}, error) {
197197
case reflect.Uint64:
198198
return uint64(bigNum.Uint64()), nil
199199
case reflect.Int8:
200-
return uint8(bigNum.Int64()), nil
200+
return int8(bigNum.Int64()), nil
201201
case reflect.Int16:
202-
return uint16(bigNum.Int64()), nil
202+
return int16(bigNum.Int64()), nil
203203
case reflect.Int32:
204-
return uint32(bigNum.Int64()), nil
204+
return int32(bigNum.Int64()), nil
205205
case reflect.Int64:
206-
return uint64(bigNum.Int64()), nil
206+
return int64(bigNum.Int64()), nil
207207
case reflect.Ptr:
208208
return bigNum, nil
209209
}

accounts/abi/abi_test.go

Lines changed: 120 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package abi
1818

1919
import (
2020
"bytes"
21-
"errors"
2221
"fmt"
2322
"log"
2423
"math/big"
@@ -53,52 +52,52 @@ func TestTypeCheck(t *testing.T) {
5352
for i, test := range []struct {
5453
typ string
5554
input interface{}
56-
err error
55+
err string
5756
}{
58-
{"uint", big.NewInt(1), nil},
59-
{"int", big.NewInt(1), nil},
60-
{"uint30", big.NewInt(1), nil},
61-
{"uint30", uint8(1), varErr(reflect.Ptr, reflect.Uint8)},
62-
{"uint16", uint16(1), nil},
63-
{"uint16", uint8(1), varErr(reflect.Uint16, reflect.Uint8)},
64-
{"uint16[]", []uint16{1, 2, 3}, nil},
65-
{"uint16[]", [3]uint16{1, 2, 3}, nil},
66-
{"uint16[]", []uint32{1, 2, 3}, typeErr(formatSliceString(reflect.Uint16, -1), formatSliceString(reflect.Uint32, -1))},
67-
{"uint16[3]", [3]uint32{1, 2, 3}, typeErr(formatSliceString(reflect.Uint16, 3), formatSliceString(reflect.Uint32, 3))},
68-
{"uint16[3]", [4]uint16{1, 2, 3}, typeErr(formatSliceString(reflect.Uint16, 3), formatSliceString(reflect.Uint16, 4))},
69-
{"uint16[3]", []uint16{1, 2, 3}, nil},
70-
{"uint16[3]", []uint16{1, 2, 3, 4}, typeErr(formatSliceString(reflect.Uint16, 3), formatSliceString(reflect.Uint16, 4))},
71-
{"address[]", []common.Address{common.Address{1}}, nil},
72-
{"address[1]", []common.Address{common.Address{1}}, nil},
73-
{"address[1]", [1]common.Address{common.Address{1}}, nil},
74-
{"address[2]", [1]common.Address{common.Address{1}}, typeErr(formatSliceString(reflect.Array, 2), formatSliceString(reflect.Array, 1))},
75-
{"bytes32", [32]byte{}, nil},
76-
{"bytes32", [33]byte{}, typeErr(formatSliceString(reflect.Uint8, 32), formatSliceString(reflect.Uint8, 33))},
77-
{"bytes32", common.Hash{1}, nil},
78-
{"bytes31", [31]byte{}, nil},
79-
{"bytes31", [32]byte{}, typeErr(formatSliceString(reflect.Uint8, 31), formatSliceString(reflect.Uint8, 32))},
80-
{"bytes", []byte{0, 1}, nil},
81-
{"bytes", [2]byte{0, 1}, nil},
82-
{"bytes", common.Hash{1}, nil},
83-
{"string", "hello world", nil},
84-
{"bytes32[]", [][32]byte{[32]byte{}}, nil},
57+
{"uint", big.NewInt(1), ""},
58+
{"int", big.NewInt(1), ""},
59+
{"uint30", big.NewInt(1), ""},
60+
{"uint30", uint8(1), "abi: cannot use uint8 as type ptr as argument"},
61+
{"uint16", uint16(1), ""},
62+
{"uint16", uint8(1), "abi: cannot use uint8 as type uint16 as argument"},
63+
{"uint16[]", []uint16{1, 2, 3}, ""},
64+
{"uint16[]", [3]uint16{1, 2, 3}, ""},
65+
{"uint16[]", []uint32{1, 2, 3}, "abi: cannot use []uint32 as type []uint16 as argument"},
66+
{"uint16[3]", [3]uint32{1, 2, 3}, "abi: cannot use [3]uint32 as type [3]uint16 as argument"},
67+
{"uint16[3]", [4]uint16{1, 2, 3}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"},
68+
{"uint16[3]", []uint16{1, 2, 3}, ""},
69+
{"uint16[3]", []uint16{1, 2, 3, 4}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"},
70+
{"address[]", []common.Address{common.Address{1}}, ""},
71+
{"address[1]", []common.Address{common.Address{1}}, ""},
72+
{"address[1]", [1]common.Address{common.Address{1}}, ""},
73+
{"address[2]", [1]common.Address{common.Address{1}}, "abi: cannot use [1]array as type [2]array as argument"},
74+
{"bytes32", [32]byte{}, ""},
75+
{"bytes32", [33]byte{}, "abi: cannot use [33]uint8 as type [32]uint8 as argument"},
76+
{"bytes32", common.Hash{1}, ""},
77+
{"bytes31", [31]byte{}, ""},
78+
{"bytes31", [32]byte{}, "abi: cannot use [32]uint8 as type [31]uint8 as argument"},
79+
{"bytes", []byte{0, 1}, ""},
80+
{"bytes", [2]byte{0, 1}, ""},
81+
{"bytes", common.Hash{1}, ""},
82+
{"string", "hello world", ""},
83+
{"bytes32[]", [][32]byte{[32]byte{}}, ""},
8584
} {
8685
typ, err := NewType(test.typ)
8786
if err != nil {
8887
t.Fatal("unexpected parse error:", err)
8988
}
9089

9190
err = typeCheck(typ, reflect.ValueOf(test.input))
92-
if err != nil && test.err == nil {
91+
if err != nil && len(test.err) == 0 {
9392
t.Errorf("%d failed. Expected no err but got: %v", i, err)
9493
continue
9594
}
96-
if err == nil && test.err != nil {
95+
if err == nil && len(test.err) != 0 {
9796
t.Errorf("%d failed. Expected err: %v but got none", i, test.err)
9897
continue
9998
}
10099

101-
if err != nil && test.err != nil && err.Error() != test.err.Error() {
100+
if err != nil && len(test.err) != 0 && err.Error() != test.err {
102101
t.Errorf("%d failed. Expected err: '%v' got err: '%v'", i, test.err, err)
103102
}
104103
}
@@ -110,63 +109,93 @@ func TestSimpleMethodUnpack(t *testing.T) {
110109
marshalledOutput []byte // evm return data
111110
expectedOut interface{} // the expected output
112111
outVar string // the output variable (e.g. uint32, *big.Int, etc)
113-
err error // nil or error if expected
112+
err string // empty or error if expected
114113
}{
115114
{
116115
`[ { "type": "uint32" } ]`,
117116
pad([]byte{1}, 32, true),
118117
uint32(1),
119118
"uint32",
120-
nil,
119+
"",
121120
},
122121
{
123122
`[ { "type": "uint32" } ]`,
124123
pad([]byte{1}, 32, true),
125124
nil,
126125
"uint16",
127-
errors.New("abi: cannot unmarshal uint32 in to uint16"),
126+
"abi: cannot unmarshal uint32 in to uint16",
128127
},
129128
{
130129
`[ { "type": "uint17" } ]`,
131130
pad([]byte{1}, 32, true),
132131
nil,
133132
"uint16",
134-
errors.New("abi: cannot unmarshal *big.Int in to uint16"),
133+
"abi: cannot unmarshal *big.Int in to uint16",
135134
},
136135
{
137136
`[ { "type": "uint17" } ]`,
138137
pad([]byte{1}, 32, true),
139138
big.NewInt(1),
140139
"*big.Int",
140+
"",
141+
},
142+
143+
{
144+
`[ { "type": "int32" } ]`,
145+
pad([]byte{1}, 32, true),
146+
int32(1),
147+
"int32",
148+
"",
149+
},
150+
{
151+
`[ { "type": "int32" } ]`,
152+
pad([]byte{1}, 32, true),
141153
nil,
154+
"int16",
155+
"abi: cannot unmarshal int32 in to int16",
156+
},
157+
{
158+
`[ { "type": "int17" } ]`,
159+
pad([]byte{1}, 32, true),
160+
nil,
161+
"int16",
162+
"abi: cannot unmarshal *big.Int in to int16",
163+
},
164+
{
165+
`[ { "type": "int17" } ]`,
166+
pad([]byte{1}, 32, true),
167+
big.NewInt(1),
168+
"*big.Int",
169+
"",
142170
},
171+
143172
{
144173
`[ { "type": "address" } ]`,
145174
pad(pad([]byte{1}, 20, false), 32, true),
146175
common.Address{1},
147176
"address",
148-
nil,
177+
"",
149178
},
150179
{
151180
`[ { "type": "bytes32" } ]`,
152181
pad([]byte{1}, 32, false),
153182
pad([]byte{1}, 32, false),
154183
"bytes",
155-
nil,
184+
"",
156185
},
157186
{
158187
`[ { "type": "bytes32" } ]`,
159188
pad([]byte{1}, 32, false),
160189
pad([]byte{1}, 32, false),
161190
"hash",
162-
nil,
191+
"",
163192
},
164193
{
165194
`[ { "type": "bytes32" } ]`,
166195
pad([]byte{1}, 32, false),
167196
pad([]byte{1}, 32, false),
168197
"interface",
169-
nil,
198+
"",
170199
},
171200
} {
172201
abiDefinition := fmt.Sprintf(`[{ "name" : "method", "outputs": %s}]`, test.def)
@@ -194,6 +223,22 @@ func TestSimpleMethodUnpack(t *testing.T) {
194223
var v uint64
195224
err = abi.Unpack(&v, "method", test.marshalledOutput)
196225
outvar = v
226+
case "int8":
227+
var v int8
228+
err = abi.Unpack(&v, "method", test.marshalledOutput)
229+
outvar = v
230+
case "int16":
231+
var v int16
232+
err = abi.Unpack(&v, "method", test.marshalledOutput)
233+
outvar = v
234+
case "int32":
235+
var v int32
236+
err = abi.Unpack(&v, "method", test.marshalledOutput)
237+
outvar = v
238+
case "int64":
239+
var v int64
240+
err = abi.Unpack(&v, "method", test.marshalledOutput)
241+
outvar = v
197242
case "*big.Int":
198243
var v *big.Int
199244
err = abi.Unpack(&v, "method", test.marshalledOutput)
@@ -217,15 +262,15 @@ func TestSimpleMethodUnpack(t *testing.T) {
217262
continue
218263
}
219264

220-
if err != nil && test.err == nil {
265+
if err != nil && len(test.err) == 0 {
221266
t.Errorf("%d failed. Expected no err but got: %v", i, err)
222267
continue
223268
}
224-
if err == nil && test.err != nil {
269+
if err == nil && len(test.err) != 0 {
225270
t.Errorf("%d failed. Expected err: %v but got none", i, test.err)
226271
continue
227272
}
228-
if err != nil && test.err != nil && err.Error() != test.err.Error() {
273+
if err != nil && len(test.err) != 0 && err.Error() != test.err {
229274
t.Errorf("%d failed. Expected err: '%v' got err: '%v'", i, test.err, err)
230275
continue
231276
}
@@ -253,6 +298,7 @@ func TestPack(t *testing.T) {
253298
}{
254299
{"uint16", uint16(2), pad([]byte{2}, 32, true)},
255300
{"uint16[]", []uint16{1, 2}, formatSliceOutput([]byte{1}, []byte{2})},
301+
{"bytes20", [20]byte{1}, pad([]byte{1}, 32, false)},
256302
{"uint256[]", []*big.Int{big.NewInt(1), big.NewInt(2)}, formatSliceOutput([]byte{1}, []byte{2})},
257303
{"address[]", []common.Address{common.Address{1}, common.Address{2}}, formatSliceOutput(pad([]byte{1}, 20, false), pad([]byte{2}, 20, false))},
258304
{"bytes32[]", []common.Hash{common.Hash{1}, common.Hash{2}}, formatSliceOutput(pad([]byte{1}, 32, false), pad([]byte{2}, 32, false))},
@@ -346,26 +392,26 @@ func TestMethodPack(t *testing.T) {
346392

347393
const jsondata = `
348394
[
349-
{ "type" : "function", "name" : "balance", "const" : true },
350-
{ "type" : "function", "name" : "send", "const" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
395+
{ "type" : "function", "name" : "balance", "constant" : true },
396+
{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
351397
]`
352398

353399
const jsondata2 = `
354400
[
355-
{ "type" : "function", "name" : "balance", "const" : true },
356-
{ "type" : "function", "name" : "send", "const" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] },
357-
{ "type" : "function", "name" : "test", "const" : false, "inputs" : [ { "name" : "number", "type" : "uint32" } ] },
358-
{ "type" : "function", "name" : "string", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "string" } ] },
359-
{ "type" : "function", "name" : "bool", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "bool" } ] },
360-
{ "type" : "function", "name" : "address", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "address" } ] },
361-
{ "type" : "function", "name" : "uint64[2]", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] },
362-
{ "type" : "function", "name" : "uint64[]", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] },
363-
{ "type" : "function", "name" : "foo", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
364-
{ "type" : "function", "name" : "bar", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
365-
{ "type" : "function", "name" : "slice", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
366-
{ "type" : "function", "name" : "slice256", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
367-
{ "type" : "function", "name" : "sliceAddress", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
368-
{ "type" : "function", "name" : "sliceMultiAddress", "const" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
401+
{ "type" : "function", "name" : "balance", "constant" : true },
402+
{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] },
403+
{ "type" : "function", "name" : "test", "constant" : false, "inputs" : [ { "name" : "number", "type" : "uint32" } ] },
404+
{ "type" : "function", "name" : "string", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "string" } ] },
405+
{ "type" : "function", "name" : "bool", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "bool" } ] },
406+
{ "type" : "function", "name" : "address", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address" } ] },
407+
{ "type" : "function", "name" : "uint64[2]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] },
408+
{ "type" : "function", "name" : "uint64[]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] },
409+
{ "type" : "function", "name" : "foo", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
410+
{ "type" : "function", "name" : "bar", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
411+
{ "type" : "function", "name" : "slice", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
412+
{ "type" : "function", "name" : "slice256", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
413+
{ "type" : "function", "name" : "sliceAddress", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
414+
{ "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
369415
]`
370416

371417
func TestReader(t *testing.T) {
@@ -537,9 +583,9 @@ func ExampleJSON() {
537583

538584
func TestInputVariableInputLength(t *testing.T) {
539585
const definition = `[
540-
{ "type" : "function", "name" : "strOne", "const" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
541-
{ "type" : "function", "name" : "bytesOne", "const" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
542-
{ "type" : "function", "name" : "strTwo", "const" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
586+
{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
587+
{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
588+
{ "type" : "function", "name" : "strTwo", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
543589
]`
544590

545591
abi, err := JSON(strings.NewReader(definition))
@@ -701,7 +747,7 @@ func TestBareEvents(t *testing.T) {
701747

702748
func TestMultiReturnWithStruct(t *testing.T) {
703749
const definition = `[
704-
{ "name" : "multi", "const" : false, "outputs": [ { "name": "Int", "type": "uint256" }, { "name": "String", "type": "string" } ] }]`
750+
{ "name" : "multi", "constant" : false, "outputs": [ { "name": "Int", "type": "uint256" }, { "name": "String", "type": "string" } ] }]`
705751

706752
abi, err := JSON(strings.NewReader(definition))
707753
if err != nil {
@@ -754,7 +800,7 @@ func TestMultiReturnWithStruct(t *testing.T) {
754800

755801
func TestMultiReturnWithSlice(t *testing.T) {
756802
const definition = `[
757-
{ "name" : "multi", "const" : false, "outputs": [ { "name": "Int", "type": "uint256" }, { "name": "String", "type": "string" } ] }]`
803+
{ "name" : "multi", "constant" : false, "outputs": [ { "name": "Int", "type": "uint256" }, { "name": "String", "type": "string" } ] }]`
758804

759805
abi, err := JSON(strings.NewReader(definition))
760806
if err != nil {
@@ -790,8 +836,8 @@ func TestMultiReturnWithSlice(t *testing.T) {
790836

791837
func TestMarshalArrays(t *testing.T) {
792838
const definition = `[
793-
{ "name" : "bytes32", "const" : false, "outputs": [ { "type": "bytes32" } ] },
794-
{ "name" : "bytes10", "const" : false, "outputs": [ { "type": "bytes10" } ] }
839+
{ "name" : "bytes32", "constant" : false, "outputs": [ { "type": "bytes32" } ] },
840+
{ "name" : "bytes10", "constant" : false, "outputs": [ { "type": "bytes10" } ] }
795841
]`
796842

797843
abi, err := JSON(strings.NewReader(definition))
@@ -849,14 +895,14 @@ func TestMarshalArrays(t *testing.T) {
849895

850896
func TestUnmarshal(t *testing.T) {
851897
const definition = `[
852-
{ "name" : "int", "const" : false, "outputs": [ { "type": "uint256" } ] },
853-
{ "name" : "bool", "const" : false, "outputs": [ { "type": "bool" } ] },
854-
{ "name" : "bytes", "const" : false, "outputs": [ { "type": "bytes" } ] },
855-
{ "name" : "fixed", "const" : false, "outputs": [ { "type": "bytes32" } ] },
856-
{ "name" : "multi", "const" : false, "outputs": [ { "type": "bytes" }, { "type": "bytes" } ] },
857-
{ "name" : "addressSliceSingle", "const" : false, "outputs": [ { "type": "address[]" } ] },
858-
{ "name" : "addressSliceDouble", "const" : false, "outputs": [ { "name": "a", "type": "address[]" }, { "name": "b", "type": "address[]" } ] },
859-
{ "name" : "mixedBytes", "const" : true, "outputs": [ { "name": "a", "type": "bytes" }, { "name": "b", "type": "bytes32" } ] }]`
898+
{ "name" : "int", "constant" : false, "outputs": [ { "type": "uint256" } ] },
899+
{ "name" : "bool", "constant" : false, "outputs": [ { "type": "bool" } ] },
900+
{ "name" : "bytes", "constant" : false, "outputs": [ { "type": "bytes" } ] },
901+
{ "name" : "fixed", "constant" : false, "outputs": [ { "type": "bytes32" } ] },
902+
{ "name" : "multi", "constant" : false, "outputs": [ { "type": "bytes" }, { "type": "bytes" } ] },
903+
{ "name" : "addressSliceSingle", "constant" : false, "outputs": [ { "type": "address[]" } ] },
904+
{ "name" : "addressSliceDouble", "constant" : false, "outputs": [ { "name": "a", "type": "address[]" }, { "name": "b", "type": "address[]" } ] },
905+
{ "name" : "mixedBytes", "constant" : true, "outputs": [ { "name": "a", "type": "bytes" }, { "name": "b", "type": "bytes32" } ] }]`
860906

861907
abi, err := JSON(strings.NewReader(definition))
862908
if err != nil {

accounts/abi/error.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func formatSliceString(kind reflect.Kind, sliceSize int) string {
3333
// sliceTypeCheck checks that the given slice can by assigned to the reflection
3434
// type in t.
3535
func sliceTypeCheck(t Type, val reflect.Value) error {
36-
if !(val.Kind() == reflect.Slice || val.Kind() == reflect.Array) {
36+
if val.Kind() != reflect.Slice && val.Kind() != reflect.Array {
3737
return typeErr(formatSliceString(t.Kind, t.SliceSize), val.Type())
3838
}
3939
if t.IsArray && val.Len() != t.SliceSize {
@@ -48,14 +48,13 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
4848
return sliceTypeCheck(*t.Elem, val.Index(0))
4949
}
5050

51-
elemKind := val.Type().Elem().Kind()
52-
if elemKind != t.Elem.Kind {
51+
if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.Kind {
5352
return typeErr(formatSliceString(t.Elem.Kind, t.SliceSize), val.Type())
5453
}
5554
return nil
5655
}
5756

58-
// typeCheck checks that thet given reflection val can be assigned to the reflection
57+
// typeCheck checks that the given reflection value can be assigned to the reflection
5958
// type in t.
6059
func typeCheck(t Type, value reflect.Value) error {
6160
if t.IsSlice || t.IsArray {

0 commit comments

Comments
 (0)