Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
dec8bba9
Commit
dec8bba9
authored
Oct 17, 2017
by
RJ Catalano
Committed by
Felix Lange
Oct 17, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
accounts/abi: improve type handling, add event support (#14743)
parent
e9295163
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
903 additions
and
847 deletions
+903
-847
abi.go
accounts/abi/abi.go
+16
-99
abi_test.go
accounts/abi/abi_test.go
+1
-20
bind_test.go
accounts/abi/bind/bind_test.go
+1
-1
error.go
accounts/abi/error.go
+12
-12
event.go
accounts/abi/event.go
+91
-0
event_test.go
accounts/abi/event_test.go
+1
-1
method.go
accounts/abi/method.go
+79
-0
numbers.go
accounts/abi/numbers.go
+17
-30
pack.go
accounts/abi/pack.go
+5
-2
pack_test.go
accounts/abi/pack_test.go
+2
-5
reflect.go
accounts/abi/reflect.go
+2
-8
type.go
accounts/abi/type.go
+103
-107
type_test.go
accounts/abi/type_test.go
+170
-45
unpack.go
accounts/abi/unpack.go
+130
-149
unpack_test.go
accounts/abi/unpack_test.go
+273
-368
No files found.
accounts/abi/abi.go
View file @
dec8bba9
...
...
@@ -20,10 +20,6 @@ import (
"encoding/json"
"fmt"
"io"
"reflect"
"strings"
"github.com/ethereum/go-ethereum/common"
)
// The ABI holds information about a contract's context and available
...
...
@@ -76,106 +72,27 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
return
append
(
method
.
Id
(),
arguments
...
),
nil
}
// these variable are used to determine certain types during type assertion for
// assignment.
var
(
r_interSlice
=
reflect
.
TypeOf
([]
interface
{}{})
r_hash
=
reflect
.
TypeOf
(
common
.
Hash
{})
r_bytes
=
reflect
.
TypeOf
([]
byte
{})
r_byte
=
reflect
.
TypeOf
(
byte
(
0
))
)
// Unpack output in v according to the abi specification
func
(
abi
ABI
)
Unpack
(
v
interface
{},
name
string
,
output
[]
byte
)
error
{
var
method
=
abi
.
Methods
[
name
]
if
len
(
output
)
==
0
{
return
fmt
.
Errorf
(
"abi: unmarshalling empty output"
)
}
// make sure the passed value is a pointer
valueOf
:=
reflect
.
ValueOf
(
v
)
if
reflect
.
Ptr
!=
valueOf
.
Kind
()
{
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
func
(
abi
ABI
)
Unpack
(
v
interface
{},
name
string
,
output
[]
byte
)
(
err
error
)
{
if
err
=
bytesAreProper
(
output
);
err
!=
nil
{
return
err
}
var
(
value
=
valueOf
.
Elem
()
typ
=
value
.
Type
()
)
if
len
(
method
.
Outputs
)
>
1
{
switch
value
.
Kind
()
{
// struct will match named return values to the struct's field
// names
case
reflect
.
Struct
:
for
i
:=
0
;
i
<
len
(
method
.
Outputs
);
i
++
{
marshalledValue
,
err
:=
toGoType
(
i
,
method
.
Outputs
[
i
],
output
)
if
err
!=
nil
{
return
err
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
for
j
:=
0
;
j
<
typ
.
NumField
();
j
++
{
field
:=
typ
.
Field
(
j
)
// TODO read tags: `abi:"fieldName"`
if
field
.
Name
==
strings
.
ToUpper
(
method
.
Outputs
[
i
]
.
Name
[
:
1
])
+
method
.
Outputs
[
i
]
.
Name
[
1
:
]
{
if
err
:=
set
(
value
.
Field
(
j
),
reflectValue
,
method
.
Outputs
[
i
]);
err
!=
nil
{
return
err
}
}
}
}
case
reflect
.
Slice
:
if
!
value
.
Type
()
.
AssignableTo
(
r_interSlice
)
{
return
fmt
.
Errorf
(
"abi: cannot marshal tuple in to slice %T (only []interface{} is supported)"
,
v
)
}
// if the slice already contains values, set those instead of the interface slice itself.
if
value
.
Len
()
>
0
{
if
len
(
method
.
Outputs
)
>
value
.
Len
()
{
return
fmt
.
Errorf
(
"abi: cannot marshal in to slices of unequal size (require: %v, got: %v)"
,
len
(
method
.
Outputs
),
value
.
Len
())
}
for
i
:=
0
;
i
<
len
(
method
.
Outputs
);
i
++
{
marshalledValue
,
err
:=
toGoType
(
i
,
method
.
Outputs
[
i
],
output
)
if
err
!=
nil
{
return
err
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
if
err
:=
set
(
value
.
Index
(
i
)
.
Elem
(),
reflectValue
,
method
.
Outputs
[
i
]);
err
!=
nil
{
return
err
}
}
return
nil
}
// create a new slice and start appending the unmarshalled
// values to the new interface slice.
z
:=
reflect
.
MakeSlice
(
typ
,
0
,
len
(
method
.
Outputs
))
for
i
:=
0
;
i
<
len
(
method
.
Outputs
);
i
++
{
marshalledValue
,
err
:=
toGoType
(
i
,
method
.
Outputs
[
i
],
output
)
if
err
!=
nil
{
return
err
}
z
=
reflect
.
Append
(
z
,
reflect
.
ValueOf
(
marshalledValue
))
}
value
.
Set
(
z
)
default
:
return
fmt
.
Errorf
(
"abi: cannot unmarshal tuple in to %v"
,
typ
)
}
// since there can't be naming collisions with contracts and events,
// we need to decide whether we're calling a method or an event
var
unpack
unpacker
if
method
,
ok
:=
abi
.
Methods
[
name
];
ok
{
unpack
=
method
}
else
if
event
,
ok
:=
abi
.
Events
[
name
];
ok
{
unpack
=
event
}
else
{
marshalledValue
,
err
:=
toGoType
(
0
,
method
.
Outputs
[
0
],
output
)
if
err
!=
nil
{
return
err
}
if
err
:=
set
(
value
,
reflect
.
ValueOf
(
marshalledValue
),
method
.
Outputs
[
0
]);
err
!=
nil
{
return
err
}
return
fmt
.
Errorf
(
"abi: could not locate named method or event."
)
}
return
nil
// requires a struct to unpack into for a tuple return...
if
unpack
.
isTupleReturn
()
{
return
unpack
.
tupleUnpack
(
v
,
output
)
}
return
unpack
.
singleUnpack
(
v
,
output
)
}
func
(
abi
*
ABI
)
UnmarshalJSON
(
data
[]
byte
)
error
{
...
...
accounts/abi/abi_test.go
View file @
dec8bba9
...
...
@@ -29,25 +29,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)
// formatSilceOutput add padding to the value and adds a size
func
formatSliceOutput
(
v
...
[]
byte
)
[]
byte
{
off
:=
common
.
LeftPadBytes
(
big
.
NewInt
(
int64
(
len
(
v
)))
.
Bytes
(),
32
)
output
:=
append
(
off
,
make
([]
byte
,
0
,
len
(
v
)
*
32
)
...
)
for
_
,
value
:=
range
v
{
output
=
append
(
output
,
common
.
LeftPadBytes
(
value
,
32
)
...
)
}
return
output
}
// quick helper padding
func
pad
(
input
[]
byte
,
size
int
,
left
bool
)
[]
byte
{
if
left
{
return
common
.
LeftPadBytes
(
input
,
size
)
}
return
common
.
RightPadBytes
(
input
,
size
)
}
const
jsondata
=
`
[
{ "type" : "function", "name" : "balance", "constant" : true },
...
...
@@ -191,7 +172,7 @@ func TestMethodSignature(t *testing.T) {
t
.
Errorf
(
"expected ids to match %x != %x"
,
m
.
Id
(),
idexp
)
}
uintt
,
_
:=
NewType
(
"uint"
)
uintt
,
_
:=
NewType
(
"uint
256
"
)
m
=
Method
{
"foo"
,
false
,
[]
Argument
{{
"bar"
,
uintt
,
false
}},
nil
}
exp
=
"foo(uint256)"
if
m
.
Sig
()
!=
exp
{
...
...
accounts/abi/bind/bind_test.go
View file @
dec8bba9
...
...
@@ -472,7 +472,7 @@ func TestBindings(t *testing.T) {
t
.
Fatalf
(
"failed to create temporary workspace: %v"
,
err
)
}
defer
os
.
RemoveAll
(
ws
)
pkg
:=
filepath
.
Join
(
ws
,
"bindtest"
)
if
err
=
os
.
MkdirAll
(
pkg
,
0700
);
err
!=
nil
{
t
.
Fatalf
(
"failed to create package: %v"
,
err
)
...
...
accounts/abi/error.go
View file @
dec8bba9
...
...
@@ -39,22 +39,23 @@ 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
.
Kind
,
t
.
S
liceS
ize
),
val
.
Type
())
return
typeErr
(
formatSliceString
(
t
.
Kind
,
t
.
Size
),
val
.
Type
())
}
if
t
.
IsArray
&&
val
.
Len
()
!=
t
.
SliceSize
{
return
typeErr
(
formatSliceString
(
t
.
Elem
.
Kind
,
t
.
SliceSize
),
formatSliceString
(
val
.
Type
()
.
Elem
()
.
Kind
(),
val
.
Len
()))
if
t
.
T
==
ArrayTy
&&
val
.
Len
()
!=
t
.
Size
{
return
typeErr
(
formatSliceString
(
t
.
Elem
.
Kind
,
t
.
Size
),
formatSliceString
(
val
.
Type
()
.
Elem
()
.
Kind
(),
val
.
Len
()))
}
if
t
.
Elem
.
IsSlice
{
if
t
.
Elem
.
T
==
SliceTy
{
if
val
.
Len
()
>
0
{
return
sliceTypeCheck
(
*
t
.
Elem
,
val
.
Index
(
0
))
}
}
else
if
t
.
Elem
.
IsArra
y
{
}
else
if
t
.
Elem
.
T
==
ArrayT
y
{
return
sliceTypeCheck
(
*
t
.
Elem
,
val
.
Index
(
0
))
}
if
elemKind
:=
val
.
Type
()
.
Elem
()
.
Kind
();
elemKind
!=
t
.
Elem
.
Kind
{
return
typeErr
(
formatSliceString
(
t
.
Elem
.
Kind
,
t
.
S
liceS
ize
),
val
.
Type
())
return
typeErr
(
formatSliceString
(
t
.
Elem
.
Kind
,
t
.
Size
),
val
.
Type
())
}
return
nil
}
...
...
@@ -62,20 +63,19 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
// typeCheck checks that the given reflection value can be assigned to the reflection
// type in t.
func
typeCheck
(
t
Type
,
value
reflect
.
Value
)
error
{
if
t
.
IsSlice
||
t
.
IsArra
y
{
if
t
.
T
==
SliceTy
||
t
.
T
==
ArrayT
y
{
return
sliceTypeCheck
(
t
,
value
)
}
// Check base type validity. Element types will be checked later on.
if
t
.
Kind
!=
value
.
Kind
()
{
return
typeErr
(
t
.
Kind
,
value
.
Kind
())
}
else
if
t
.
T
==
FixedBytesTy
&&
t
.
Size
!=
value
.
Len
()
{
return
typeErr
(
t
.
Type
,
value
.
Type
())
}
else
{
return
nil
}
return
nil
}
// varErr returns a formatted error.
func
varErr
(
expected
,
got
reflect
.
Kind
)
error
{
return
typeErr
(
expected
,
got
)
}
// typeErr returns a formatted type casting error.
...
...
accounts/abi/event.go
View file @
dec8bba9
...
...
@@ -18,6 +18,7 @@ package abi
import
(
"fmt"
"reflect"
"strings"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -44,3 +45,93 @@ func (e Event) Id() common.Hash {
}
return
common
.
BytesToHash
(
crypto
.
Keccak256
([]
byte
(
fmt
.
Sprintf
(
"%v(%v)"
,
e
.
Name
,
strings
.
Join
(
types
,
","
)))))
}
// unpacks an event return tuple into a struct of corresponding go types
//
// Unpacking can be done into a struct or a slice/array.
func
(
e
Event
)
tupleUnpack
(
v
interface
{},
output
[]
byte
)
error
{
// make sure the passed value is a pointer
valueOf
:=
reflect
.
ValueOf
(
v
)
if
reflect
.
Ptr
!=
valueOf
.
Kind
()
{
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
}
var
(
value
=
valueOf
.
Elem
()
typ
=
value
.
Type
()
)
if
value
.
Kind
()
!=
reflect
.
Struct
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal tuple in to %v"
,
typ
)
}
j
:=
0
for
i
:=
0
;
i
<
len
(
e
.
Inputs
);
i
++
{
input
:=
e
.
Inputs
[
i
]
if
input
.
Indexed
{
// can't read, continue
continue
}
else
if
input
.
Type
.
T
==
ArrayTy
{
// need to move this up because they read sequentially
j
+=
input
.
Type
.
Size
}
marshalledValue
,
err
:=
toGoType
((
i
+
j
)
*
32
,
input
.
Type
,
output
)
if
err
!=
nil
{
return
err
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
switch
value
.
Kind
()
{
case
reflect
.
Struct
:
for
j
:=
0
;
j
<
typ
.
NumField
();
j
++
{
field
:=
typ
.
Field
(
j
)
// TODO read tags: `abi:"fieldName"`
if
field
.
Name
==
strings
.
ToUpper
(
e
.
Inputs
[
i
]
.
Name
[
:
1
])
+
e
.
Inputs
[
i
]
.
Name
[
1
:
]
{
if
err
:=
set
(
value
.
Field
(
j
),
reflectValue
,
e
.
Inputs
[
i
]);
err
!=
nil
{
return
err
}
}
}
case
reflect
.
Slice
,
reflect
.
Array
:
if
value
.
Len
()
<
i
{
return
fmt
.
Errorf
(
"abi: insufficient number of arguments for unpack, want %d, got %d"
,
len
(
e
.
Inputs
),
value
.
Len
())
}
v
:=
value
.
Index
(
i
)
if
v
.
Kind
()
!=
reflect
.
Ptr
&&
v
.
Kind
()
!=
reflect
.
Interface
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to %v"
,
v
.
Type
(),
reflectValue
.
Type
())
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
if
err
:=
set
(
v
.
Elem
(),
reflectValue
,
e
.
Inputs
[
i
]);
err
!=
nil
{
return
err
}
default
:
return
fmt
.
Errorf
(
"abi: cannot unmarshal tuple in to %v"
,
typ
)
}
}
return
nil
}
func
(
e
Event
)
isTupleReturn
()
bool
{
return
len
(
e
.
Inputs
)
>
1
}
func
(
e
Event
)
singleUnpack
(
v
interface
{},
output
[]
byte
)
error
{
// make sure the passed value is a pointer
valueOf
:=
reflect
.
ValueOf
(
v
)
if
reflect
.
Ptr
!=
valueOf
.
Kind
()
{
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
}
if
e
.
Inputs
[
0
]
.
Indexed
{
return
fmt
.
Errorf
(
"abi: attempting to unpack indexed variable into element."
)
}
value
:=
valueOf
.
Elem
()
marshalledValue
,
err
:=
toGoType
(
0
,
e
.
Inputs
[
0
]
.
Type
,
output
)
if
err
!=
nil
{
return
err
}
if
err
:=
set
(
value
,
reflect
.
ValueOf
(
marshalledValue
),
e
.
Inputs
[
0
]);
err
!=
nil
{
return
err
}
return
nil
}
accounts/abi/event_test.go
View file @
dec8bba9
...
...
@@ -31,7 +31,7 @@ func TestEventId(t *testing.T) {
}{
{
definition
:
`[
{ "type" : "event", "name" : "balance", "inputs": [{ "name" : "in", "type": "uint" }] },
{ "type" : "event", "name" : "balance", "inputs": [{ "name" : "in", "type": "uint
256
" }] },
{ "type" : "event", "name" : "check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] }
]`
,
expectations
:
map
[
string
]
common
.
Hash
{
...
...
accounts/abi/method.go
View file @
dec8bba9
...
...
@@ -77,6 +77,85 @@ func (method Method) pack(args ...interface{}) ([]byte, error) {
return
ret
,
nil
}
// unpacks a method return tuple into a struct of corresponding go types
//
// Unpacking can be done into a struct or a slice/array.
func
(
method
Method
)
tupleUnpack
(
v
interface
{},
output
[]
byte
)
error
{
// make sure the passed value is a pointer
valueOf
:=
reflect
.
ValueOf
(
v
)
if
reflect
.
Ptr
!=
valueOf
.
Kind
()
{
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
}
var
(
value
=
valueOf
.
Elem
()
typ
=
value
.
Type
()
)
j
:=
0
for
i
:=
0
;
i
<
len
(
method
.
Outputs
);
i
++
{
toUnpack
:=
method
.
Outputs
[
i
]
if
toUnpack
.
Type
.
T
==
ArrayTy
{
// need to move this up because they read sequentially
j
+=
toUnpack
.
Type
.
Size
}
marshalledValue
,
err
:=
toGoType
((
i
+
j
)
*
32
,
toUnpack
.
Type
,
output
)
if
err
!=
nil
{
return
err
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
switch
value
.
Kind
()
{
case
reflect
.
Struct
:
for
j
:=
0
;
j
<
typ
.
NumField
();
j
++
{
field
:=
typ
.
Field
(
j
)
// TODO read tags: `abi:"fieldName"`
if
field
.
Name
==
strings
.
ToUpper
(
method
.
Outputs
[
i
]
.
Name
[
:
1
])
+
method
.
Outputs
[
i
]
.
Name
[
1
:
]
{
if
err
:=
set
(
value
.
Field
(
j
),
reflectValue
,
method
.
Outputs
[
i
]);
err
!=
nil
{
return
err
}
}
}
case
reflect
.
Slice
,
reflect
.
Array
:
if
value
.
Len
()
<
i
{
return
fmt
.
Errorf
(
"abi: insufficient number of arguments for unpack, want %d, got %d"
,
len
(
method
.
Outputs
),
value
.
Len
())
}
v
:=
value
.
Index
(
i
)
if
v
.
Kind
()
!=
reflect
.
Ptr
&&
v
.
Kind
()
!=
reflect
.
Interface
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to %v"
,
v
.
Type
(),
reflectValue
.
Type
())
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
if
err
:=
set
(
v
.
Elem
(),
reflectValue
,
method
.
Outputs
[
i
]);
err
!=
nil
{
return
err
}
default
:
return
fmt
.
Errorf
(
"abi: cannot unmarshal tuple in to %v"
,
typ
)
}
}
return
nil
}
func
(
method
Method
)
isTupleReturn
()
bool
{
return
len
(
method
.
Outputs
)
>
1
}
func
(
method
Method
)
singleUnpack
(
v
interface
{},
output
[]
byte
)
error
{
// make sure the passed value is a pointer
valueOf
:=
reflect
.
ValueOf
(
v
)
if
reflect
.
Ptr
!=
valueOf
.
Kind
()
{
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
}
value
:=
valueOf
.
Elem
()
marshalledValue
,
err
:=
toGoType
(
0
,
method
.
Outputs
[
0
]
.
Type
,
output
)
if
err
!=
nil
{
return
err
}
if
err
:=
set
(
value
,
reflect
.
ValueOf
(
marshalledValue
),
method
.
Outputs
[
0
]);
err
!=
nil
{
return
err
}
return
nil
}
// Sig returns the methods string signature according to the ABI spec.
//
// Example
...
...
accounts/abi/numbers.go
View file @
dec8bba9
...
...
@@ -25,36 +25,23 @@ import (
)
var
(
big_t
=
reflect
.
TypeOf
(
big
.
Int
{})
ubig_t
=
reflect
.
TypeOf
(
big
.
Int
{})
byte_t
=
reflect
.
TypeOf
(
byte
(
0
))
byte_ts
=
reflect
.
TypeOf
([]
byte
(
nil
))
uint_t
=
reflect
.
TypeOf
(
uint
(
0
))
uint8_t
=
reflect
.
TypeOf
(
uint8
(
0
))
uint16_t
=
reflect
.
TypeOf
(
uint16
(
0
))
uint32_t
=
reflect
.
TypeOf
(
uint32
(
0
))
uint64_t
=
reflect
.
TypeOf
(
uint64
(
0
))
int_t
=
reflect
.
TypeOf
(
int
(
0
))
int8_t
=
reflect
.
TypeOf
(
int8
(
0
))
int16_t
=
reflect
.
TypeOf
(
int16
(
0
))
int32_t
=
reflect
.
TypeOf
(
int32
(
0
))
int64_t
=
reflect
.
TypeOf
(
int64
(
0
))
hash_t
=
reflect
.
TypeOf
(
common
.
Hash
{})
address_t
=
reflect
.
TypeOf
(
common
.
Address
{})
uint_ts
=
reflect
.
TypeOf
([]
uint
(
nil
))
uint8_ts
=
reflect
.
TypeOf
([]
uint8
(
nil
))
uint16_ts
=
reflect
.
TypeOf
([]
uint16
(
nil
))
uint32_ts
=
reflect
.
TypeOf
([]
uint32
(
nil
))
uint64_ts
=
reflect
.
TypeOf
([]
uint64
(
nil
))
ubig_ts
=
reflect
.
TypeOf
([]
*
big
.
Int
(
nil
))
int_ts
=
reflect
.
TypeOf
([]
int
(
nil
))
int8_ts
=
reflect
.
TypeOf
([]
int8
(
nil
))
int16_ts
=
reflect
.
TypeOf
([]
int16
(
nil
))
int32_ts
=
reflect
.
TypeOf
([]
int32
(
nil
))
int64_ts
=
reflect
.
TypeOf
([]
int64
(
nil
))
big_ts
=
reflect
.
TypeOf
([]
*
big
.
Int
(
nil
))
big_t
=
reflect
.
TypeOf
(
&
big
.
Int
{})
derefbig_t
=
reflect
.
TypeOf
(
big
.
Int
{})
uint8_t
=
reflect
.
TypeOf
(
uint8
(
0
))
uint16_t
=
reflect
.
TypeOf
(
uint16
(
0
))
uint32_t
=
reflect
.
TypeOf
(
uint32
(
0
))
uint64_t
=
reflect
.
TypeOf
(
uint64
(
0
))
int_t
=
reflect
.
TypeOf
(
int
(
0
))
int8_t
=
reflect
.
TypeOf
(
int8
(
0
))
int16_t
=
reflect
.
TypeOf
(
int16
(
0
))
int32_t
=
reflect
.
TypeOf
(
int32
(
0
))
int64_t
=
reflect
.
TypeOf
(
int64
(
0
))
address_t
=
reflect
.
TypeOf
(
common
.
Address
{})
int_ts
=
reflect
.
TypeOf
([]
int
(
nil
))
int8_ts
=
reflect
.
TypeOf
([]
int8
(
nil
))
int16_ts
=
reflect
.
TypeOf
([]
int16
(
nil
))
int32_ts
=
reflect
.
TypeOf
([]
int32
(
nil
))
int64_ts
=
reflect
.
TypeOf
([]
int64
(
nil
))
)
// U256 converts a big Int into a 256bit EVM number.
...
...
accounts/abi/pack.go
View file @
dec8bba9
...
...
@@ -61,8 +61,9 @@ func packElement(t Type, reflectValue reflect.Value) []byte {
reflectValue
=
mustArrayToByteSlice
(
reflectValue
)
}
return
common
.
RightPadBytes
(
reflectValue
.
Bytes
(),
32
)
default
:
panic
(
"abi: fatal error"
)
}
panic
(
"abi: fatal error"
)
}
// packNum packs the given number (using the reflect value) and will cast it to appropriate number representation
...
...
@@ -74,6 +75,8 @@ func packNum(value reflect.Value) []byte {
return
U256
(
big
.
NewInt
(
value
.
Int
()))
case
reflect
.
Ptr
:
return
U256
(
value
.
Interface
()
.
(
*
big
.
Int
))
default
:
panic
(
"abi: fatal error"
)
}
return
nil
}
accounts/abi/pack_test.go
View file @
dec8bba9
...
...
@@ -322,12 +322,12 @@ func TestPack(t *testing.T) {
}
{
typ
,
err
:=
NewType
(
test
.
typ
)
if
err
!=
nil
{
t
.
Fatal
(
"unexpected parse error:"
,
err
)
t
.
Fatal
f
(
"%v failed. Unexpected parse error: %v"
,
i
,
err
)
}
output
,
err
:=
typ
.
pack
(
reflect
.
ValueOf
(
test
.
input
))
if
err
!=
nil
{
t
.
Fatal
(
"unexpected pack error:"
,
err
)
t
.
Fatal
f
(
"%v failed. Unexpected pack error: %v"
,
i
,
err
)
}
if
!
bytes
.
Equal
(
output
,
test
.
output
)
{
...
...
@@ -435,7 +435,4 @@ func TestPackNumber(t *testing.T) {
t
.
Errorf
(
"test %d: pack mismatch: have %x, want %x"
,
i
,
packed
,
tt
.
packed
)
}
}
if
packed
:=
packNum
(
reflect
.
ValueOf
(
"string"
));
packed
!=
nil
{
t
.
Errorf
(
"expected 'string' to pack to nil. got %x instead"
,
packed
)
}
}
accounts/abi/reflect.go
View file @
dec8bba9
...
...
@@ -24,7 +24,7 @@ import (
// indirect recursively dereferences the value until it either gets the value
// or finds a big.Int
func
indirect
(
v
reflect
.
Value
)
reflect
.
Value
{
if
v
.
Kind
()
==
reflect
.
Ptr
&&
v
.
Elem
()
.
Type
()
!=
big_t
{
if
v
.
Kind
()
==
reflect
.
Ptr
&&
v
.
Elem
()
.
Type
()
!=
deref
big_t
{
return
indirect
(
v
.
Elem
())
}
return
v
...
...
@@ -73,15 +73,9 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value {
func
set
(
dst
,
src
reflect
.
Value
,
output
Argument
)
error
{
dstType
:=
dst
.
Type
()
srcType
:=
src
.
Type
()
switch
{
case
dstType
.
AssignableTo
(
src
.
Type
()
)
:
case
dstType
.
AssignableTo
(
src
Type
)
:
dst
.
Set
(
src
)
case
dstType
.
Kind
()
==
reflect
.
Array
&&
srcType
.
Kind
()
==
reflect
.
Slice
:
if
dst
.
Len
()
<
output
.
Type
.
SliceSize
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal src (len=%d) in to dst (len=%d)"
,
output
.
Type
.
SliceSize
,
dst
.
Len
())
}
reflect
.
Copy
(
dst
,
src
)
case
dstType
.
Kind
()
==
reflect
.
Interface
:
dst
.
Set
(
src
)
case
dstType
.
Kind
()
==
reflect
.
Ptr
:
...
...
accounts/abi/type.go
View file @
dec8bba9
...
...
@@ -21,6 +21,7 @@ import (
"reflect"
"regexp"
"strconv"
"strings"
)
const
(
...
...
@@ -29,6 +30,7 @@ const (
BoolTy
StringTy
SliceTy
ArrayTy
AddressTy
FixedBytesTy
BytesTy
...
...
@@ -39,9 +41,6 @@ const (
// Type is the reflection of the supported argument type
type
Type
struct
{
IsSlice
,
IsArray
bool
SliceSize
int
Elem
*
Type
Kind
reflect
.
Kind
...
...
@@ -53,118 +52,116 @@ type Type struct {
}
var
(
// fullTypeRegex parses the abi types
//
// Types can be in the format of:
//
// Input = Type [ "[" [ Number ] "]" ] Name .
// Type = [ "u" ] "int" [ Number ] [ x ] [ Number ].
//
// Examples:
//
// string int uint fixed
// string32 int8 uint8 uint[]
// address int256 uint256 fixed128x128[2]
fullTypeRegex
=
regexp
.
MustCompile
(
`([a-zA-Z0-9]+)(\[([0-9]*)\])?`
)
// typeRegex parses the abi sub types
typeRegex
=
regexp
.
MustCompile
(
"([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?"
)
)
// NewType creates a new reflection type of abi type given in t.
func
NewType
(
t
string
)
(
typ
Type
,
err
error
)
{
res
:=
fullTypeRegex
.
FindAllStringSubmatch
(
t
,
-
1
)[
0
]
// check if type is slice and parse type.
switch
{
case
res
[
3
]
!=
""
:
// err is ignored. Already checked for number through the regexp
typ
.
SliceSize
,
_
=
strconv
.
Atoi
(
res
[
3
])
typ
.
IsArray
=
true
case
res
[
2
]
!=
""
:
typ
.
IsSlice
,
typ
.
SliceSize
=
true
,
-
1
case
res
[
0
]
==
""
:
return
Type
{},
fmt
.
Errorf
(
"abi: type parse error: %s"
,
t
)
// check that array brackets are equal if they exist
if
strings
.
Count
(
t
,
"["
)
!=
strings
.
Count
(
t
,
"]"
)
{
return
Type
{},
fmt
.
Errorf
(
"invalid arg type in abi"
)
}
if
typ
.
IsArray
||
typ
.
IsSlice
{
sliceType
,
err
:=
NewType
(
res
[
1
])
typ
.
stringKind
=
t
// if there are brackets, get ready to go into slice/array mode and
// recursively create the type
if
strings
.
Count
(
t
,
"["
)
!=
0
{
i
:=
strings
.
LastIndex
(
t
,
"["
)
// recursively embed the type
embeddedType
,
err
:=
NewType
(
t
[
:
i
])
if
err
!=
nil
{
return
Type
{},
err
}
typ
.
Elem
=
&
sliceType
typ
.
stringKind
=
sliceType
.
stringKind
+
t
[
len
(
res
[
1
])
:
]
// Although we know that this is an array, we cannot return
// as we don't know the type of the element, however, if it
// is still an array, then don't determine the type.
if
typ
.
Elem
.
IsArray
||
typ
.
Elem
.
IsSlice
{
return
typ
,
nil
}
}
// parse the type and size of the abi-type.
parsedType
:=
typeRegex
.
FindAllStringSubmatch
(
res
[
1
],
-
1
)[
0
]
// varSize is the size of the variable
var
varSize
int
if
len
(
parsedType
[
3
])
>
0
{
var
err
error
varSize
,
err
=
strconv
.
Atoi
(
parsedType
[
2
])
if
err
!=
nil
{
return
Type
{},
fmt
.
Errorf
(
"abi: error parsing variable size: %v"
,
err
)
// grab the last cell and create a type from there
sliced
:=
t
[
i
:
]
// grab the slice size with regexp
re
:=
regexp
.
MustCompile
(
"[0-9]+"
)
intz
:=
re
.
FindAllString
(
sliced
,
-
1
)
if
len
(
intz
)
==
0
{
// is a slice
typ
.
T
=
SliceTy
typ
.
Kind
=
reflect
.
Slice
typ
.
Elem
=
&
embeddedType
typ
.
Type
=
reflect
.
SliceOf
(
embeddedType
.
Type
)
}
else
if
len
(
intz
)
==
1
{
// is a array
typ
.
T
=
ArrayTy
typ
.
Kind
=
reflect
.
Array
typ
.
Elem
=
&
embeddedType
typ
.
Size
,
err
=
strconv
.
Atoi
(
intz
[
0
])
if
err
!=
nil
{
return
Type
{},
fmt
.
Errorf
(
"abi: error parsing variable size: %v"
,
err
)
}
typ
.
Type
=
reflect
.
ArrayOf
(
typ
.
Size
,
embeddedType
.
Type
)
}
else
{
return
Type
{},
fmt
.
Errorf
(
"invalid formatting of array type"
)
}
}
// varType is the parsed abi type
varType
:=
parsedType
[
1
]
// substitute canonical integer
if
varSize
==
0
&&
(
varType
==
"int"
||
varType
==
"uint"
)
{
varSize
=
256
t
+=
"256"
}
// only set stringKind if not array or slice, as for those,
// the correct string type has been set
if
!
(
typ
.
IsArray
||
typ
.
IsSlice
)
{
typ
.
stringKind
=
t
}
switch
varType
{
case
"int"
:
typ
.
Kind
,
typ
.
Type
=
reflectIntKindAndType
(
false
,
varSize
)
typ
.
Size
=
varSize
typ
.
T
=
IntTy
case
"uint"
:
typ
.
Kind
,
typ
.
Type
=
reflectIntKindAndType
(
true
,
varSize
)
typ
.
Size
=
varSize
typ
.
T
=
UintTy
case
"bool"
:
typ
.
Kind
=
reflect
.
Bool
typ
.
T
=
BoolTy
case
"address"
:
typ
.
Kind
=
reflect
.
Array
typ
.
Type
=
address_t
typ
.
Size
=
20
typ
.
T
=
AddressTy
case
"string"
:
typ
.
Kind
=
reflect
.
String
typ
.
Size
=
-
1
typ
.
T
=
StringTy
case
"bytes"
:
sliceType
,
_
:=
NewType
(
"uint8"
)
typ
.
Elem
=
&
sliceType
if
varSize
==
0
{
typ
.
IsSlice
=
true
typ
.
T
=
BytesTy
typ
.
SliceSize
=
-
1
return
typ
,
err
}
else
{
// parse the type and size of the abi-type.
parsedType
:=
typeRegex
.
FindAllStringSubmatch
(
t
,
-
1
)[
0
]
// varSize is the size of the variable
var
varSize
int
if
len
(
parsedType
[
3
])
>
0
{
var
err
error
varSize
,
err
=
strconv
.
Atoi
(
parsedType
[
2
])
if
err
!=
nil
{
return
Type
{},
fmt
.
Errorf
(
"abi: error parsing variable size: %v"
,
err
)
}
}
else
{
typ
.
IsArray
=
true
typ
.
T
=
FixedBytesTy
typ
.
SliceSize
=
varSize
if
parsedType
[
0
]
==
"uint"
||
parsedType
[
0
]
==
"int"
{
// this should fail because it means that there's something wrong with
// the abi type (the compiler should always format it to the size...always)
return
Type
{},
fmt
.
Errorf
(
"unsupported arg type: %s"
,
t
)
}
}
// varType is the parsed abi type
varType
:=
parsedType
[
1
]
switch
varType
{
case
"int"
:
typ
.
Kind
,
typ
.
Type
=
reflectIntKindAndType
(
false
,
varSize
)
typ
.
Size
=
varSize
typ
.
T
=
IntTy
case
"uint"
:
typ
.
Kind
,
typ
.
Type
=
reflectIntKindAndType
(
true
,
varSize
)
typ
.
Size
=
varSize
typ
.
T
=
UintTy
case
"bool"
:
typ
.
Kind
=
reflect
.
Bool
typ
.
T
=
BoolTy
typ
.
Type
=
reflect
.
TypeOf
(
bool
(
false
))
case
"address"
:
typ
.
Kind
=
reflect
.
Array
typ
.
Type
=
address_t
typ
.
Size
=
20
typ
.
T
=
AddressTy
case
"string"
:
typ
.
Kind
=
reflect
.
String
typ
.
Type
=
reflect
.
TypeOf
(
""
)
typ
.
T
=
StringTy
case
"bytes"
:
if
varSize
==
0
{
typ
.
T
=
BytesTy
typ
.
Kind
=
reflect
.
Slice
typ
.
Type
=
reflect
.
SliceOf
(
reflect
.
TypeOf
(
byte
(
0
)))
}
else
{
typ
.
T
=
FixedBytesTy
typ
.
Kind
=
reflect
.
Array
typ
.
Size
=
varSize
typ
.
Type
=
reflect
.
ArrayOf
(
varSize
,
reflect
.
TypeOf
(
byte
(
0
)))
}
case
"function"
:
typ
.
Kind
=
reflect
.
Array
typ
.
T
=
FunctionTy
typ
.
Size
=
24
typ
.
Type
=
reflect
.
ArrayOf
(
24
,
reflect
.
TypeOf
(
byte
(
0
)))
default
:
return
Type
{},
fmt
.
Errorf
(
"unsupported arg type: %s"
,
t
)
}
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
)
}
return
...
...
@@ -183,7 +180,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
return
nil
,
err
}
if
(
t
.
IsSlice
||
t
.
IsArray
)
&&
t
.
T
!=
BytesTy
&&
t
.
T
!=
FixedBytesTy
&&
t
.
T
!=
Function
Ty
{
if
t
.
T
==
SliceTy
||
t
.
T
==
Array
Ty
{
var
packed
[]
byte
for
i
:=
0
;
i
<
v
.
Len
();
i
++
{
...
...
@@ -193,18 +190,17 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
}
packed
=
append
(
packed
,
val
...
)
}
if
t
.
IsSlice
{
if
t
.
T
==
SliceTy
{
return
packBytesSlice
(
packed
,
v
.
Len
()),
nil
}
else
if
t
.
IsArra
y
{
}
else
if
t
.
T
==
ArrayT
y
{
return
packed
,
nil
}
}
return
packElement
(
t
,
v
),
nil
}
// requireLengthPrefix returns whether the type requires any sort of length
// prefixing.
func
(
t
Type
)
requiresLengthPrefix
()
bool
{
return
t
.
T
!=
FixedBytesTy
&&
(
t
.
T
==
StringTy
||
t
.
T
==
BytesTy
||
t
.
IsSlice
)
return
t
.
T
==
StringTy
||
t
.
T
==
BytesTy
||
t
.
T
==
SliceTy
}
accounts/abi/type_test.go
View file @
dec8bba9
...
...
@@ -21,6 +21,7 @@ import (
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
)
...
...
@@ -34,51 +35,58 @@ func TestTypeRegexp(t *testing.T) {
blob
string
kind
Type
}{
{
"bool"
,
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
stringKind
:
"bool"
}},
{
"bool[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
stringKind
:
"bool"
},
stringKind
:
"bool[]"
}},
{
"bool[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
stringKind
:
"bool"
},
stringKind
:
"bool[2]"
}},
{
"bool"
,
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
}},
{
"bool[]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
bool
(
nil
)),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[]"
}},
{
"bool[2]"
,
Type
{
Size
:
2
,
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Type
:
reflect
.
TypeOf
([
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[2]"
}},
{
"bool[2][]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([][
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[2]"
},
stringKind
:
"bool[2][]"
}},
{
"bool[][]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([][]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[]"
},
stringKind
:
"bool[][]"
}},
{
"bool[][2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[]"
},
stringKind
:
"bool[][2]"
}},
{
"bool[2][2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[2]"
},
stringKind
:
"bool[2][2]"
}},
{
"bool[2][][2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][][
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([][
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[2]"
},
stringKind
:
"bool[2][]"
},
stringKind
:
"bool[2][][2]"
}},
{
"bool[2][2][2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][
2
][
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[2]"
},
stringKind
:
"bool[2][2]"
},
stringKind
:
"bool[2][2][2]"
}},
{
"bool[][][]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([][][]
bool
{}),
Elem
:
&
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([][]
bool
{}),
Elem
:
&
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[]"
},
stringKind
:
"bool[][]"
},
stringKind
:
"bool[][][]"
}},
{
"bool[][2][]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([][
2
][]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][]
bool
{}),
Elem
:
&
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
bool
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Bool
,
T
:
BoolTy
,
Type
:
reflect
.
TypeOf
(
bool
(
false
)),
stringKind
:
"bool"
},
stringKind
:
"bool[]"
},
stringKind
:
"bool[][2]"
},
stringKind
:
"bool[][2][]"
}},
{
"int8"
,
Type
{
Kind
:
reflect
.
Int8
,
Type
:
int8_t
,
Size
:
8
,
T
:
IntTy
,
stringKind
:
"int8"
}},
{
"int16"
,
Type
{
Kind
:
reflect
.
Int16
,
Type
:
int16_t
,
Size
:
16
,
T
:
IntTy
,
stringKind
:
"int16"
}},
{
"int32"
,
Type
{
Kind
:
reflect
.
Int32
,
Type
:
int32_t
,
Size
:
32
,
T
:
IntTy
,
stringKind
:
"int32"
}},
{
"int64"
,
Type
{
Kind
:
reflect
.
Int64
,
Type
:
int64_t
,
Size
:
64
,
T
:
IntTy
,
stringKind
:
"int64"
}},
{
"int256"
,
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
IntTy
,
stringKind
:
"int256"
}},
{
"int8[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Int8
,
Type
:
int8_t
,
Size
:
8
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int8
,
Type
:
int8_t
,
Size
:
8
,
T
:
IntTy
,
stringKind
:
"int8"
},
stringKind
:
"int8[]"
}},
{
"int8[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Int8
,
Type
:
int8_t
,
Size
:
8
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int8
,
Type
:
int8_t
,
Size
:
8
,
T
:
IntTy
,
stringKind
:
"int8"
},
stringKind
:
"int8[2]"
}},
{
"int16[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Int16
,
Type
:
int16_t
,
Size
:
16
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int16
,
Type
:
int16_t
,
Size
:
16
,
T
:
IntTy
,
stringKind
:
"int16"
},
stringKind
:
"int16[]"
}},
{
"int16[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Int16
,
Type
:
int16_t
,
Size
:
16
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int16
,
Type
:
int16_t
,
Size
:
16
,
T
:
IntTy
,
stringKind
:
"int16"
},
stringKind
:
"int16[2]"
}},
{
"int32[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Int32
,
Type
:
int32_t
,
Size
:
32
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int32
,
Type
:
int32_t
,
Size
:
32
,
T
:
IntTy
,
stringKind
:
"int32"
},
stringKind
:
"int32[]"
}},
{
"int32[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Int32
,
Type
:
int32_t
,
Size
:
32
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int32
,
Type
:
int32_t
,
Size
:
32
,
T
:
IntTy
,
stringKind
:
"int32"
},
stringKind
:
"int32[2]"
}},
{
"int64[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Int64
,
Type
:
int64_t
,
Size
:
64
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int64
,
Type
:
int64_t
,
Size
:
64
,
T
:
IntTy
,
stringKind
:
"int64"
},
stringKind
:
"int64[]"
}},
{
"int64[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Int64
,
Type
:
int64_t
,
Size
:
64
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int64
,
Type
:
int64_t
,
Size
:
64
,
T
:
IntTy
,
stringKind
:
"int64"
},
stringKind
:
"int64[2]"
}},
{
"int256[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
IntTy
,
stringKind
:
"int256"
},
stringKind
:
"int256[]"
}},
{
"int256[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
IntTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
IntTy
,
stringKind
:
"int256"
},
stringKind
:
"int256[2]"
}},
{
"int8[]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
int8
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int8
,
Type
:
int8_t
,
Size
:
8
,
T
:
IntTy
,
stringKind
:
"int8"
},
stringKind
:
"int8[]"
}},
{
"int8[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
int8
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int8
,
Type
:
int8_t
,
Size
:
8
,
T
:
IntTy
,
stringKind
:
"int8"
},
stringKind
:
"int8[2]"
}},
{
"int16[]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
int16
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int16
,
Type
:
int16_t
,
Size
:
16
,
T
:
IntTy
,
stringKind
:
"int16"
},
stringKind
:
"int16[]"
}},
{
"int16[2]"
,
Type
{
Size
:
2
,
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Type
:
reflect
.
TypeOf
([
2
]
int16
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int16
,
Type
:
int16_t
,
Size
:
16
,
T
:
IntTy
,
stringKind
:
"int16"
},
stringKind
:
"int16[2]"
}},
{
"int32[]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
int32
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int32
,
Type
:
int32_t
,
Size
:
32
,
T
:
IntTy
,
stringKind
:
"int32"
},
stringKind
:
"int32[]"
}},
{
"int32[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
int32
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int32
,
Type
:
int32_t
,
Size
:
32
,
T
:
IntTy
,
stringKind
:
"int32"
},
stringKind
:
"int32[2]"
}},
{
"int64[]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
int64
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int64
,
Type
:
int64_t
,
Size
:
64
,
T
:
IntTy
,
stringKind
:
"int64"
},
stringKind
:
"int64[]"
}},
{
"int64[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
int64
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Int64
,
Type
:
int64_t
,
Size
:
64
,
T
:
IntTy
,
stringKind
:
"int64"
},
stringKind
:
"int64[2]"
}},
{
"int256[]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
*
big
.
Int
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
IntTy
,
stringKind
:
"int256"
},
stringKind
:
"int256[]"
}},
{
"int256[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
*
big
.
Int
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
IntTy
,
stringKind
:
"int256"
},
stringKind
:
"int256[2]"
}},
{
"uint8"
,
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
}},
{
"uint16"
,
Type
{
Kind
:
reflect
.
Uint16
,
Type
:
uint16_t
,
Size
:
16
,
T
:
UintTy
,
stringKind
:
"uint16"
}},
{
"uint32"
,
Type
{
Kind
:
reflect
.
Uint32
,
Type
:
uint32_t
,
Size
:
32
,
T
:
UintTy
,
stringKind
:
"uint32"
}},
{
"uint64"
,
Type
{
Kind
:
reflect
.
Uint64
,
Type
:
uint64_t
,
Size
:
64
,
T
:
UintTy
,
stringKind
:
"uint64"
}},
{
"uint256"
,
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
UintTy
,
stringKind
:
"uint256"
}},
{
"uint8[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
stringKind
:
"uint8[]"
}},
{
"uint8[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
stringKind
:
"uint8[2]"
}},
{
"uint16[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Uint16
,
Type
:
uint16_t
,
Size
:
16
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint16
,
Type
:
uint16_t
,
Size
:
16
,
T
:
UintTy
,
stringKind
:
"uint16"
},
stringKind
:
"uint16[]"
}},
{
"uint16[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Uint16
,
Type
:
uint16_t
,
Size
:
16
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint16
,
Type
:
uint16_t
,
Size
:
16
,
T
:
UintTy
,
stringKind
:
"uint16"
},
stringKind
:
"uint16[2]"
}},
{
"uint32[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Uint32
,
Type
:
uint32_t
,
Size
:
32
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint32
,
Type
:
uint32_t
,
Size
:
32
,
T
:
UintTy
,
stringKind
:
"uint32"
},
stringKind
:
"uint32[]"
}},
{
"uint32[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Uint32
,
Type
:
uint32_t
,
Size
:
32
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint32
,
Type
:
uint32_t
,
Size
:
32
,
T
:
UintTy
,
stringKind
:
"uint32"
},
stringKind
:
"uint32[2]"
}},
{
"uint64[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Uint64
,
Type
:
uint64_t
,
Size
:
64
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint64
,
Type
:
uint64_t
,
Size
:
64
,
T
:
UintTy
,
stringKind
:
"uint64"
},
stringKind
:
"uint64[]"
}},
{
"uint64[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Uint64
,
Type
:
uint64_t
,
Size
:
64
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint64
,
Type
:
uint64_t
,
Size
:
64
,
T
:
UintTy
,
stringKind
:
"uint64"
},
stringKind
:
"uint64[2]"
}},
{
"uint256[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
UintTy
,
stringKind
:
"uint256"
},
stringKind
:
"uint256[]"
}},
{
"uint256[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
UintTy
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
UintTy
,
stringKind
:
"uint256"
},
stringKind
:
"uint256[2]"
}},
{
"bytes32"
,
Type
{
IsArray
:
true
,
SliceSize
:
32
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
T
:
FixedBytesTy
,
stringKind
:
"bytes32"
}},
{
"bytes[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Elem
:
&
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
}
,
T
:
BytesTy
,
stringKind
:
"bytes"
},
stringKind
:
"bytes[]"
}},
{
"bytes[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Elem
:
&
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
T
:
BytesTy
,
stringKind
:
"bytes"
},
stringKind
:
"bytes[2]"
}},
{
"bytes32[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Elem
:
&
Type
{
IsArray
:
true
,
SliceSize
:
32
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
T
:
FixedBytesTy
,
stringKind
:
"bytes32"
},
stringKind
:
"bytes32[]"
}},
{
"bytes32[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Elem
:
&
Type
{
IsArray
:
true
,
SliceSize
:
32
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
T
:
FixedBytesTy
,
stringKind
:
"bytes32"
},
stringKind
:
"bytes32[2]"
}},
{
"string"
,
Type
{
Kind
:
reflect
.
String
,
Size
:
-
1
,
T
:
StringTy
,
stringKind
:
"string"
}},
{
"string[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
String
,
T
:
StringTy
,
Size
:
-
1
,
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
T
:
StringTy
,
Size
:
-
1
,
stringKind
:
"string"
},
stringKind
:
"string[]"
}},
{
"string[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
String
,
T
:
StringTy
,
Size
:
-
1
,
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
T
:
StringTy
,
Size
:
-
1
,
stringKind
:
"string"
},
stringKind
:
"string[2]"
}},
{
"uint8[]"
,
Type
{
Kind
:
reflect
.
Slice
,
T
:
SliceTy
,
Type
:
reflect
.
TypeOf
([]
uint8
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
stringKind
:
"uint8[]"
}},
{
"uint8[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
uint8
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint8
,
Type
:
uint8_t
,
Size
:
8
,
T
:
UintTy
,
stringKind
:
"uint8"
},
stringKind
:
"uint8[2]"
}},
{
"uint16[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
uint16
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint16
,
Type
:
uint16_t
,
Size
:
16
,
T
:
UintTy
,
stringKind
:
"uint16"
},
stringKind
:
"uint16[]"
}},
{
"uint16[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
uint16
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint16
,
Type
:
uint16_t
,
Size
:
16
,
T
:
UintTy
,
stringKind
:
"uint16"
},
stringKind
:
"uint16[2]"
}},
{
"uint32[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
uint32
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint32
,
Type
:
uint32_t
,
Size
:
32
,
T
:
UintTy
,
stringKind
:
"uint32"
},
stringKind
:
"uint32[]"
}},
{
"uint32[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
uint32
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint32
,
Type
:
uint32_t
,
Size
:
32
,
T
:
UintTy
,
stringKind
:
"uint32"
},
stringKind
:
"uint32[2]"
}},
{
"uint64[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
uint64
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint64
,
Type
:
uint64_t
,
Size
:
64
,
T
:
UintTy
,
stringKind
:
"uint64"
},
stringKind
:
"uint64[]"
}},
{
"uint64[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
uint64
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Uint64
,
Type
:
uint64_t
,
Size
:
64
,
T
:
UintTy
,
stringKind
:
"uint64"
},
stringKind
:
"uint64[2]"
}},
{
"uint256[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
*
big
.
Int
{})
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
UintTy
,
stringKind
:
"uint256"
},
stringKind
:
"uint256[]"
}},
{
"uint256[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Type
:
reflect
.
TypeOf
([
2
]
*
big
.
Int
{}),
Size
:
2
,
Elem
:
&
Type
{
Kind
:
reflect
.
Ptr
,
Type
:
big_t
,
Size
:
256
,
T
:
UintTy
,
stringKind
:
"uint256"
},
stringKind
:
"uint256[2]"
}},
{
"bytes32"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
FixedBytesTy
,
Size
:
32
,
Type
:
reflect
.
TypeOf
([
32
]
byte
{})
,
stringKind
:
"bytes32"
}},
{
"bytes[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([][]
byte
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
byte
{})
,
T
:
BytesTy
,
stringKind
:
"bytes"
},
stringKind
:
"bytes[]"
}},
{
"bytes[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][]
byte
{}),
Elem
:
&
Type
{
T
:
BytesTy
,
Type
:
reflect
.
TypeOf
([]
byte
{}),
Kind
:
reflect
.
Slice
,
stringKind
:
"bytes"
},
stringKind
:
"bytes[2]"
}},
{
"bytes32[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([][
32
]
byte
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
reflect
.
TypeOf
([
32
]
byte
{}),
T
:
FixedBytesTy
,
Size
:
32
,
stringKind
:
"bytes32"
},
stringKind
:
"bytes32[]"
}},
{
"bytes32[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
][
32
]
byte
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
T
:
FixedBytesTy
,
Size
:
32
,
Type
:
reflect
.
TypeOf
([
32
]
byte
{})
,
stringKind
:
"bytes32"
},
stringKind
:
"bytes32[2]"
}},
{
"string"
,
Type
{
Kind
:
reflect
.
String
,
T
:
StringTy
,
Type
:
reflect
.
TypeOf
(
""
)
,
stringKind
:
"string"
}},
{
"string[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
string
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
Type
:
reflect
.
TypeOf
(
""
),
T
:
StringTy
,
stringKind
:
"string"
},
stringKind
:
"string[]"
}},
{
"string[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
string
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
T
:
StringTy
,
Type
:
reflect
.
TypeOf
(
""
)
,
stringKind
:
"string"
},
stringKind
:
"string[2]"
}},
{
"address"
,
Type
{
Kind
:
reflect
.
Array
,
Type
:
address_t
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
}},
{
"address[]"
,
Type
{
IsSlice
:
true
,
SliceSize
:
-
1
,
Kind
:
reflect
.
Array
,
Type
:
address_t
,
T
:
AddressTy
,
Size
:
20
,
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
address_t
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[]"
}},
{
"address[2]"
,
Type
{
IsArray
:
true
,
SliceSize
:
2
,
Kind
:
reflect
.
Array
,
Type
:
address_t
,
T
:
AddressTy
,
Size
:
20
,
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
address_t
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[2]"
}},
{
"address[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
common
.
Address
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
address_t
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[]"
}},
{
"address[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
common
.
Address
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
address_t
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[2]"
}},
// TODO when fixed types are implemented properly
// {"fixed", Type{}},
// {"fixed128x128", Type{}},
...
...
@@ -87,13 +95,14 @@ func TestTypeRegexp(t *testing.T) {
// {"fixed128x128[]", Type{}},
// {"fixed128x128[2]", Type{}},
}
for
i
,
tt
:=
range
tests
{
for
_
,
tt
:=
range
tests
{
typ
,
err
:=
NewType
(
tt
.
blob
)
if
err
!=
nil
{
t
.
Errorf
(
"type %
d: failed to parse type string: %v"
,
i
,
err
)
t
.
Errorf
(
"type %
q: failed to parse type string: %v"
,
tt
.
blob
,
err
)
}
if
!
reflect
.
DeepEqual
(
typ
,
tt
.
kind
)
{
t
.
Errorf
(
"type %
d: parsed type mismatch:
\n
have %+v
\n
want %+v"
,
i
,
typeWithoutStringer
(
typ
),
typeWithoutStringer
(
tt
.
kind
))
t
.
Errorf
(
"type %
q: parsed type mismatch:
\n
GOT %s
\n
WANT %s "
,
tt
.
blob
,
spew
.
Sdump
(
typeWithoutStringer
(
typ
)),
spew
.
Sdump
(
typeWithoutStringer
(
tt
.
kind
)
))
}
}
}
...
...
@@ -104,15 +113,90 @@ func TestTypeCheck(t *testing.T) {
input
interface
{}
err
string
}{
{
"uint"
,
big
.
NewInt
(
1
),
""
},
{
"int"
,
big
.
NewInt
(
1
),
""
},
{
"uint30"
,
big
.
NewInt
(
1
),
""
},
{
"uint"
,
big
.
NewInt
(
1
),
"unsupported arg type: uint"
},
{
"int"
,
big
.
NewInt
(
1
),
"unsupported arg type: int"
},
{
"uint256"
,
big
.
NewInt
(
1
),
""
},
{
"uint256[][3][]"
,
[][
3
][]
*
big
.
Int
{{{}}},
""
},
{
"uint256[][][3]"
,
[
3
][][]
*
big
.
Int
{{{}}},
""
},
{
"uint256[3][][]"
,
[][][
3
]
*
big
.
Int
{{{}}},
""
},
{
"uint256[3][3][3]"
,
[
3
][
3
][
3
]
*
big
.
Int
{{{}}},
""
},
{
"uint8[][]"
,
[][]
uint8
{},
""
},
{
"int256"
,
big
.
NewInt
(
1
),
""
},
{
"uint8"
,
uint8
(
1
),
""
},
{
"uint16"
,
uint16
(
1
),
""
},
{
"uint32"
,
uint32
(
1
),
""
},
{
"uint64"
,
uint64
(
1
),
""
},
{
"int8"
,
int8
(
1
),
""
},
{
"int16"
,
int16
(
1
),
""
},
{
"int32"
,
int32
(
1
),
""
},
{
"int64"
,
int64
(
1
),
""
},
{
"uint24"
,
big
.
NewInt
(
1
),
""
},
{
"uint40"
,
big
.
NewInt
(
1
),
""
},
{
"uint48"
,
big
.
NewInt
(
1
),
""
},
{
"uint56"
,
big
.
NewInt
(
1
),
""
},
{
"uint72"
,
big
.
NewInt
(
1
),
""
},
{
"uint80"
,
big
.
NewInt
(
1
),
""
},
{
"uint88"
,
big
.
NewInt
(
1
),
""
},
{
"uint96"
,
big
.
NewInt
(
1
),
""
},
{
"uint104"
,
big
.
NewInt
(
1
),
""
},
{
"uint112"
,
big
.
NewInt
(
1
),
""
},
{
"uint120"
,
big
.
NewInt
(
1
),
""
},
{
"uint128"
,
big
.
NewInt
(
1
),
""
},
{
"uint136"
,
big
.
NewInt
(
1
),
""
},
{
"uint144"
,
big
.
NewInt
(
1
),
""
},
{
"uint152"
,
big
.
NewInt
(
1
),
""
},
{
"uint160"
,
big
.
NewInt
(
1
),
""
},
{
"uint168"
,
big
.
NewInt
(
1
),
""
},
{
"uint176"
,
big
.
NewInt
(
1
),
""
},
{
"uint184"
,
big
.
NewInt
(
1
),
""
},
{
"uint192"
,
big
.
NewInt
(
1
),
""
},
{
"uint200"
,
big
.
NewInt
(
1
),
""
},
{
"uint208"
,
big
.
NewInt
(
1
),
""
},
{
"uint216"
,
big
.
NewInt
(
1
),
""
},
{
"uint224"
,
big
.
NewInt
(
1
),
""
},
{
"uint232"
,
big
.
NewInt
(
1
),
""
},
{
"uint240"
,
big
.
NewInt
(
1
),
""
},
{
"uint248"
,
big
.
NewInt
(
1
),
""
},
{
"int24"
,
big
.
NewInt
(
1
),
""
},
{
"int40"
,
big
.
NewInt
(
1
),
""
},
{
"int48"
,
big
.
NewInt
(
1
),
""
},
{
"int56"
,
big
.
NewInt
(
1
),
""
},
{
"int72"
,
big
.
NewInt
(
1
),
""
},
{
"int80"
,
big
.
NewInt
(
1
),
""
},
{
"int88"
,
big
.
NewInt
(
1
),
""
},
{
"int96"
,
big
.
NewInt
(
1
),
""
},
{
"int104"
,
big
.
NewInt
(
1
),
""
},
{
"int112"
,
big
.
NewInt
(
1
),
""
},
{
"int120"
,
big
.
NewInt
(
1
),
""
},
{
"int128"
,
big
.
NewInt
(
1
),
""
},
{
"int136"
,
big
.
NewInt
(
1
),
""
},
{
"int144"
,
big
.
NewInt
(
1
),
""
},
{
"int152"
,
big
.
NewInt
(
1
),
""
},
{
"int160"
,
big
.
NewInt
(
1
),
""
},
{
"int168"
,
big
.
NewInt
(
1
),
""
},
{
"int176"
,
big
.
NewInt
(
1
),
""
},
{
"int184"
,
big
.
NewInt
(
1
),
""
},
{
"int192"
,
big
.
NewInt
(
1
),
""
},
{
"int200"
,
big
.
NewInt
(
1
),
""
},
{
"int208"
,
big
.
NewInt
(
1
),
""
},
{
"int216"
,
big
.
NewInt
(
1
),
""
},
{
"int224"
,
big
.
NewInt
(
1
),
""
},
{
"int232"
,
big
.
NewInt
(
1
),
""
},
{
"int240"
,
big
.
NewInt
(
1
),
""
},
{
"int248"
,
big
.
NewInt
(
1
),
""
},
{
"uint30"
,
uint8
(
1
),
"abi: cannot use uint8 as type ptr as argument"
},
{
"uint8"
,
uint16
(
1
),
"abi: cannot use uint16 as type uint8 as argument"
},
{
"uint8"
,
uint32
(
1
),
"abi: cannot use uint32 as type uint8 as argument"
},
{
"uint8"
,
uint64
(
1
),
"abi: cannot use uint64 as type uint8 as argument"
},
{
"uint8"
,
int8
(
1
),
"abi: cannot use int8 as type uint8 as argument"
},
{
"uint8"
,
int16
(
1
),
"abi: cannot use int16 as type uint8 as argument"
},
{
"uint8"
,
int32
(
1
),
"abi: cannot use int32 as type uint8 as argument"
},
{
"uint8"
,
int64
(
1
),
"abi: cannot use int64 as type uint8 as argument"
},
{
"uint16"
,
uint16
(
1
),
""
},
{
"uint16"
,
uint8
(
1
),
"abi: cannot use uint8 as type uint16 as argument"
},
{
"uint16[]"
,
[]
uint16
{
1
,
2
,
3
},
""
},
{
"uint16[]"
,
[
3
]
uint16
{
1
,
2
,
3
},
""
},
{
"uint16[]"
,
[]
uint32
{
1
,
2
,
3
},
"abi: cannot use []uint32 as type []uint16 as argument"
},
{
"uint16[]"
,
[]
uint32
{
1
,
2
,
3
},
"abi: cannot use []uint32 as type [
0
]uint16 as argument"
},
{
"uint16[3]"
,
[
3
]
uint32
{
1
,
2
,
3
},
"abi: cannot use [3]uint32 as type [3]uint16 as argument"
},
{
"uint16[3]"
,
[
4
]
uint16
{
1
,
2
,
3
},
"abi: cannot use [4]uint16 as type [3]uint16 as argument"
},
{
"uint16[3]"
,
[]
uint16
{
1
,
2
,
3
},
""
},
...
...
@@ -122,20 +206,61 @@ func TestTypeCheck(t *testing.T) {
{
"address[1]"
,
[
1
]
common
.
Address
{{
1
}},
""
},
{
"address[2]"
,
[
1
]
common
.
Address
{{
1
}},
"abi: cannot use [1]array as type [2]array as argument"
},
{
"bytes32"
,
[
32
]
byte
{},
""
},
{
"bytes31"
,
[
31
]
byte
{},
""
},
{
"bytes30"
,
[
30
]
byte
{},
""
},
{
"bytes29"
,
[
29
]
byte
{},
""
},
{
"bytes28"
,
[
28
]
byte
{},
""
},
{
"bytes27"
,
[
27
]
byte
{},
""
},
{
"bytes26"
,
[
26
]
byte
{},
""
},
{
"bytes25"
,
[
25
]
byte
{},
""
},
{
"bytes24"
,
[
24
]
byte
{},
""
},
{
"bytes23"
,
[
23
]
byte
{},
""
},
{
"bytes22"
,
[
22
]
byte
{},
""
},
{
"bytes21"
,
[
21
]
byte
{},
""
},
{
"bytes20"
,
[
20
]
byte
{},
""
},
{
"bytes19"
,
[
19
]
byte
{},
""
},
{
"bytes18"
,
[
18
]
byte
{},
""
},
{
"bytes17"
,
[
17
]
byte
{},
""
},
{
"bytes16"
,
[
16
]
byte
{},
""
},
{
"bytes15"
,
[
15
]
byte
{},
""
},
{
"bytes14"
,
[
14
]
byte
{},
""
},
{
"bytes13"
,
[
13
]
byte
{},
""
},
{
"bytes12"
,
[
12
]
byte
{},
""
},
{
"bytes11"
,
[
11
]
byte
{},
""
},
{
"bytes10"
,
[
10
]
byte
{},
""
},
{
"bytes9"
,
[
9
]
byte
{},
""
},
{
"bytes8"
,
[
8
]
byte
{},
""
},
{
"bytes7"
,
[
7
]
byte
{},
""
},
{
"bytes6"
,
[
6
]
byte
{},
""
},
{
"bytes5"
,
[
5
]
byte
{},
""
},
{
"bytes4"
,
[
4
]
byte
{},
""
},
{
"bytes3"
,
[
3
]
byte
{},
""
},
{
"bytes2"
,
[
2
]
byte
{},
""
},
{
"bytes1"
,
[
1
]
byte
{},
""
},
{
"bytes32"
,
[
33
]
byte
{},
"abi: cannot use [33]uint8 as type [32]uint8 as argument"
},
{
"bytes32"
,
common
.
Hash
{
1
},
""
},
{
"bytes31"
,
[
31
]
byte
{},
"
"
},
{
"bytes31"
,
common
.
Hash
{
1
},
"abi: cannot use common.Hash as type [31]uint8 as argument
"
},
{
"bytes31"
,
[
32
]
byte
{},
"abi: cannot use [32]uint8 as type [31]uint8 as argument"
},
{
"bytes"
,
[]
byte
{
0
,
1
},
""
},
{
"bytes"
,
[
2
]
byte
{
0
,
1
},
""
},
{
"bytes"
,
common
.
Hash
{
1
},
""
},
{
"bytes"
,
[
2
]
byte
{
0
,
1
},
"
abi: cannot use array as type slice as argument
"
},
{
"bytes"
,
common
.
Hash
{
1
},
"
abi: cannot use array as type slice as argument
"
},
{
"string"
,
"hello world"
,
""
},
{
"string"
,
string
(
""
),
""
},
{
"string"
,
[]
byte
{},
"abi: cannot use slice as type string as argument"
},
{
"bytes32[]"
,
[][
32
]
byte
{{}},
""
},
{
"function"
,
[
24
]
byte
{},
""
},
{
"bytes20"
,
common
.
Address
{},
""
},
{
"address"
,
[
20
]
byte
{},
""
},
{
"address"
,
common
.
Address
{},
""
},
}
{
typ
,
err
:=
NewType
(
test
.
typ
)
if
err
!=
nil
{
if
err
!=
nil
&&
len
(
test
.
err
)
==
0
{
t
.
Fatal
(
"unexpected parse error:"
,
err
)
}
else
if
err
!=
nil
&&
len
(
test
.
err
)
!=
0
{
if
err
.
Error
()
!=
test
.
err
{
t
.
Errorf
(
"%d failed. Expected err: '%v' got err: '%v'"
,
i
,
test
.
err
,
err
)
}
continue
}
err
=
typeCheck
(
typ
,
reflect
.
ValueOf
(
test
.
input
))
...
...
accounts/abi/unpack.go
View file @
dec8bba9
...
...
@@ -25,118 +25,16 @@ import (
"github.com/ethereum/go-ethereum/common"
)
// toGoSliceType parses the input and casts it to the proper slice defined by the ABI
// argument in T.
func
toGoSlice
(
i
int
,
t
Argument
,
output
[]
byte
)
(
interface
{},
error
)
{
index
:=
i
*
32
// The slice must, at very least be large enough for the index+32 which is exactly the size required
// for the [offset in output, size of offset].
if
index
+
32
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go slice: insufficient size output %d require %d"
,
len
(
output
),
index
+
32
)
}
elem
:=
t
.
Type
.
Elem
// first we need to create a slice of the type
var
refSlice
reflect
.
Value
switch
elem
.
T
{
case
IntTy
,
UintTy
,
BoolTy
:
// create a new reference slice matching the element type
switch
t
.
Type
.
Kind
{
case
reflect
.
Bool
:
refSlice
=
reflect
.
ValueOf
([]
bool
(
nil
))
case
reflect
.
Uint8
:
refSlice
=
reflect
.
ValueOf
([]
uint8
(
nil
))
case
reflect
.
Uint16
:
refSlice
=
reflect
.
ValueOf
([]
uint16
(
nil
))
case
reflect
.
Uint32
:
refSlice
=
reflect
.
ValueOf
([]
uint32
(
nil
))
case
reflect
.
Uint64
:
refSlice
=
reflect
.
ValueOf
([]
uint64
(
nil
))
case
reflect
.
Int8
:
refSlice
=
reflect
.
ValueOf
([]
int8
(
nil
))
case
reflect
.
Int16
:
refSlice
=
reflect
.
ValueOf
([]
int16
(
nil
))
case
reflect
.
Int32
:
refSlice
=
reflect
.
ValueOf
([]
int32
(
nil
))
case
reflect
.
Int64
:
refSlice
=
reflect
.
ValueOf
([]
int64
(
nil
))
default
:
refSlice
=
reflect
.
ValueOf
([]
*
big
.
Int
(
nil
))
}
case
AddressTy
:
// address must be of slice Address
refSlice
=
reflect
.
ValueOf
([]
common
.
Address
(
nil
))
case
HashTy
:
// hash must be of slice hash
refSlice
=
reflect
.
ValueOf
([]
common
.
Hash
(
nil
))
case
FixedBytesTy
:
refSlice
=
reflect
.
ValueOf
([][]
byte
(
nil
))
default
:
// no other types are supported
return
nil
,
fmt
.
Errorf
(
"abi: unsupported slice type %v"
,
elem
.
T
)
}
var
slice
[]
byte
var
size
int
var
offset
int
if
t
.
Type
.
IsSlice
{
// get the offset which determines the start of this array ...
offset
=
int
(
binary
.
BigEndian
.
Uint64
(
output
[
index
+
24
:
index
+
32
]))
if
offset
+
32
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go slice: offset %d would go over slice boundary (len=%d)"
,
len
(
output
),
offset
+
32
)
}
slice
=
output
[
offset
:
]
// ... starting with the size of the array in elements ...
size
=
int
(
binary
.
BigEndian
.
Uint64
(
slice
[
24
:
32
]))
slice
=
slice
[
32
:
]
// ... and make sure that we've at the very least the amount of bytes
// available in the buffer.
if
size
*
32
>
len
(
slice
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go slice: insufficient size output %d require %d"
,
len
(
output
),
offset
+
32
+
size
*
32
)
}
// reslice to match the required size
slice
=
slice
[
:
size
*
32
]
}
else
if
t
.
Type
.
IsArray
{
//get the number of elements in the array
size
=
t
.
Type
.
SliceSize
//check to make sure array size matches up
if
index
+
32
*
size
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)"
,
len
(
output
),
index
+
32
*
size
)
}
//slice is there for a fixed amount of times
slice
=
output
[
index
:
index
+
size
*
32
]
}
for
i
:=
0
;
i
<
size
;
i
++
{
var
(
inter
interface
{}
// interface type
returnOutput
=
slice
[
i
*
32
:
i
*
32
+
32
]
// the return output
err
error
)
// set inter to the correct type (cast)
switch
elem
.
T
{
case
IntTy
,
UintTy
:
inter
=
readInteger
(
t
.
Type
.
Kind
,
returnOutput
)
case
BoolTy
:
inter
,
err
=
readBool
(
returnOutput
)
if
err
!=
nil
{
return
nil
,
err
}
case
AddressTy
:
inter
=
common
.
BytesToAddress
(
returnOutput
)
case
HashTy
:
inter
=
common
.
BytesToHash
(
returnOutput
)
case
FixedBytesTy
:
inter
=
returnOutput
}
// append the item to our reflect slice
refSlice
=
reflect
.
Append
(
refSlice
,
reflect
.
ValueOf
(
inter
))
}
// return the interface
return
refSlice
.
Interface
(),
nil
// unpacker is a utility interface that enables us to have
// abstraction between events and methods and also to properly
// "unpack" them; e.g. events use Inputs, methods use Outputs.
type
unpacker
interface
{
tupleUnpack
(
v
interface
{},
output
[]
byte
)
error
singleUnpack
(
v
interface
{},
output
[]
byte
)
error
isTupleReturn
()
bool
}
// reads the integer based on its kind
func
readInteger
(
kind
reflect
.
Kind
,
b
[]
byte
)
interface
{}
{
switch
kind
{
case
reflect
.
Uint8
:
...
...
@@ -160,13 +58,10 @@ func readInteger(kind reflect.Kind, b []byte) interface{} {
}
}
// reads a bool
func
readBool
(
word
[]
byte
)
(
bool
,
error
)
{
if
len
(
word
)
!=
32
{
return
false
,
fmt
.
Errorf
(
"abi: fatal error: incorrect word length"
)
}
for
i
,
b
:=
range
word
{
if
b
!=
0
&&
i
!=
31
{
for
_
,
b
:=
range
word
[
:
31
]
{
if
b
!=
0
{
return
false
,
errBadBool
}
}
...
...
@@ -178,58 +73,144 @@ func readBool(word []byte) (bool, error) {
default
:
return
false
,
errBadBool
}
}
// A function type is simply the address with the function selection signature at the end.
// This enforces that standard by always presenting it as a 24-array (address + sig = 24 bytes)
func
readFunctionType
(
t
Type
,
word
[]
byte
)
(
funcTy
[
24
]
byte
,
err
error
)
{
if
t
.
T
!=
FunctionTy
{
return
[
24
]
byte
{},
fmt
.
Errorf
(
"abi: invalid type in call to make function type byte array."
)
}
if
garbage
:=
binary
.
BigEndian
.
Uint64
(
word
[
24
:
32
]);
garbage
!=
0
{
err
=
fmt
.
Errorf
(
"abi: got improperly encoded function type, got %v"
,
word
)
}
else
{
copy
(
funcTy
[
:
],
word
[
0
:
24
])
}
return
}
// toGoType parses the input and casts it to the proper type defined by the ABI
// 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
&&
t
.
Type
.
T
!=
FunctionTy
{
return
toGoSlice
(
i
,
t
,
output
)
// through reflection, creates a fixed array to be read from
func
readFixedBytes
(
t
Type
,
word
[]
byte
)
(
interface
{},
error
)
{
if
t
.
T
!=
FixedBytesTy
{
return
nil
,
fmt
.
Errorf
(
"abi: invalid type in call to make fixed byte array."
)
}
// convert
array
:=
reflect
.
New
(
t
.
Type
)
.
Elem
()
index
:=
i
*
32
if
index
+
32
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go type: length insufficient %d require %d"
,
len
(
output
),
index
+
32
)
reflect
.
Copy
(
array
,
reflect
.
ValueOf
(
word
[
0
:
t
.
Size
]))
return
array
.
Interface
(),
nil
}
// iteratively unpack elements
func
forEachUnpack
(
t
Type
,
output
[]
byte
,
start
,
size
int
)
(
interface
{},
error
)
{
if
start
+
32
*
size
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)"
,
len
(
output
),
start
+
32
*
size
)
}
// Parse the given index output and check whether we need to read
// a different offset and length based on the type (i.e. string, bytes)
var
returnOutput
[]
byte
switch
t
.
Type
.
T
{
case
StringTy
,
BytesTy
:
// variable arrays are written at the end of the return bytes
// parse offset from which we should start reading
offset
:=
int
(
binary
.
BigEndian
.
Uint64
(
output
[
index
+
24
:
index
+
32
]))
if
offset
+
32
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go type: length insufficient %d require %d"
,
len
(
output
),
offset
+
32
)
// this value will become our slice or our array, depending on the type
var
refSlice
reflect
.
Value
slice
:=
output
[
start
:
start
+
size
*
32
]
if
t
.
T
==
SliceTy
{
// declare our slice
refSlice
=
reflect
.
MakeSlice
(
t
.
Type
,
size
,
size
)
}
else
if
t
.
T
==
ArrayTy
{
// declare our array
refSlice
=
reflect
.
New
(
t
.
Type
)
.
Elem
()
}
else
{
return
nil
,
fmt
.
Errorf
(
"abi: invalid type in array/slice unpacking stage"
)
}
for
i
,
j
:=
start
,
0
;
j
*
32
<
len
(
slice
);
i
,
j
=
i
+
32
,
j
+
1
{
// this corrects the arrangement so that we get all the underlying array values
if
t
.
Elem
.
T
==
ArrayTy
&&
j
!=
0
{
i
=
start
+
t
.
Elem
.
Size
*
32
*
j
}
// parse the size up until we should be reading
size
:=
int
(
binary
.
BigEndian
.
Uint64
(
output
[
offset
+
24
:
offset
+
32
]))
if
offset
+
32
+
size
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go type: length insufficient %d require %d"
,
len
(
output
),
offset
+
32
+
size
)
inter
,
err
:=
toGoType
(
i
,
*
t
.
Elem
,
output
)
if
err
!=
nil
{
return
nil
,
err
}
// append the item to our reflect slice
refSlice
.
Index
(
j
)
.
Set
(
reflect
.
ValueOf
(
inter
))
}
// get the bytes for this return value
returnOutput
=
output
[
offset
+
32
:
offset
+
32
+
size
]
default
:
// return the interface
return
refSlice
.
Interface
(),
nil
}
// toGoType parses the output bytes and recursively assigns the value of these bytes
// into a go type with accordance with the ABI spec.
func
toGoType
(
index
int
,
t
Type
,
output
[]
byte
)
(
interface
{},
error
)
{
if
index
+
32
>
len
(
output
)
{
return
nil
,
fmt
.
Errorf
(
"abi: cannot marshal in to go type: length insufficient %d require %d"
,
len
(
output
),
index
+
32
)
}
var
(
returnOutput
[]
byte
begin
,
end
int
err
error
)
// if we require a length prefix, find the beginning word and size returned.
if
t
.
requiresLengthPrefix
()
{
begin
,
end
,
err
=
lengthPrefixPointsTo
(
index
,
output
)
if
err
!=
nil
{
return
nil
,
err
}
}
else
{
returnOutput
=
output
[
index
:
index
+
32
]
}
// convert the bytes to whatever is specified by the ABI.
switch
t
.
Type
.
T
{
switch
t
.
T
{
case
SliceTy
:
return
forEachUnpack
(
t
,
output
,
begin
,
end
)
case
ArrayTy
:
return
forEachUnpack
(
t
,
output
,
index
,
t
.
Size
)
case
StringTy
:
// variable arrays are written at the end of the return bytes
return
string
(
output
[
begin
:
begin
+
end
]),
nil
case
IntTy
,
UintTy
:
return
readInteger
(
t
.
Type
.
Kind
,
returnOutput
),
nil
return
readInteger
(
t
.
Kind
,
returnOutput
),
nil
case
BoolTy
:
return
readBool
(
returnOutput
)
case
AddressTy
:
return
common
.
BytesToAddress
(
returnOutput
),
nil
case
HashTy
:
return
common
.
BytesToHash
(
returnOutput
),
nil
case
BytesTy
,
FixedBytesTy
,
FunctionTy
:
return
returnOutput
,
nil
case
StringTy
:
return
string
(
returnOutput
),
nil
case
BytesTy
:
return
output
[
begin
:
begin
+
end
],
nil
case
FixedBytesTy
:
return
readFixedBytes
(
t
,
returnOutput
)
case
FunctionTy
:
return
readFunctionType
(
t
,
returnOutput
)
default
:
return
nil
,
fmt
.
Errorf
(
"abi: unknown type %v"
,
t
.
T
)
}
}
// interprets a 32 byte slice as an offset and then determines which indice to look to decode the type.
func
lengthPrefixPointsTo
(
index
int
,
output
[]
byte
)
(
start
int
,
length
int
,
err
error
)
{
offset
:=
int
(
binary
.
BigEndian
.
Uint64
(
output
[
index
+
24
:
index
+
32
]))
if
offset
+
32
>
len
(
output
)
{
return
0
,
0
,
fmt
.
Errorf
(
"abi: cannot marshal in to go slice: offset %d would go over slice boundary (len=%d)"
,
len
(
output
),
offset
+
32
)
}
length
=
int
(
binary
.
BigEndian
.
Uint64
(
output
[
offset
+
24
:
offset
+
32
]))
if
offset
+
32
+
length
>
len
(
output
)
{
return
0
,
0
,
fmt
.
Errorf
(
"abi: cannot marshal in to go type: length insufficient %d require %d"
,
len
(
output
),
offset
+
32
+
length
)
}
start
=
offset
+
32
//fmt.Printf("LENGTH PREFIX INFO: \nsize: %v\noffset: %v\nstart: %v\n", length, offset, start)
return
}
// checks for proper formatting of byte output
func
bytesAreProper
(
output
[]
byte
)
error
{
if
len
(
output
)
==
0
{
return
fmt
.
Errorf
(
"abi: unmarshalling empty output"
)
}
else
if
len
(
output
)
%
32
!=
0
{
return
fmt
.
Errorf
(
"abi: improperly formatted output"
)
}
else
{
return
nil
}
return
nil
,
fmt
.
Errorf
(
"abi: unknown type %v"
,
t
.
Type
.
T
)
}
accounts/abi/unpack_test.go
View file @
dec8bba9
...
...
@@ -18,6 +18,7 @@ package abi
import
(
"bytes"
"encoding/hex"
"fmt"
"math/big"
"reflect"
...
...
@@ -27,263 +28,261 @@ import (
"github.com/ethereum/go-ethereum/common"
)
func
TestSimpleMethodUnpack
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
[]
struct
{
def
string
// definition of the **output** ABI params
marshalledOutput
[]
byte
// evm return data
expectedOut
interface
{}
// the expected output
outVar
string
// the output variable (e.g. uint32, *big.Int, etc)
err
string
// empty or error if expected
}{
{
`[ { "type": "bool" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
bool
(
true
),
"bool"
,
""
,
},
{
`[ { "type": "uint32" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
uint32
(
1
),
"uint32"
,
""
,
},
{
`[ { "type": "uint32" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
nil
,
"uint16"
,
"abi: cannot unmarshal uint32 in to uint16"
,
},
{
`[ { "type": "uint17" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
nil
,
"uint16"
,
"abi: cannot unmarshal *big.Int in to uint16"
,
},
{
`[ { "type": "uint17" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
big
.
NewInt
(
1
),
"*big.Int"
,
""
,
},
{
`[ { "type": "int32" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
int32
(
1
),
"int32"
,
""
,
},
{
`[ { "type": "int32" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
nil
,
"int16"
,
"abi: cannot unmarshal int32 in to int16"
,
},
{
`[ { "type": "int17" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
nil
,
"int16"
,
"abi: cannot unmarshal *big.Int in to int16"
,
},
{
`[ { "type": "int17" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
big
.
NewInt
(
1
),
"*big.Int"
,
""
,
},
{
`[ { "type": "address" } ]`
,
common
.
Hex2Bytes
(
"0000000000000000000000000100000000000000000000000000000000000000"
),
common
.
Address
{
1
},
"address"
,
""
,
},
{
`[ { "type": "bytes32" } ]`
,
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
"bytes"
,
""
,
},
{
`[ { "type": "bytes32" } ]`
,
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
"hash"
,
""
,
},
{
`[ { "type": "bytes32" } ]`
,
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
"interface"
,
""
,
},
{
`[ { "type": "function" } ]`
,
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
[
24
]
byte
{
1
},
"function"
,
""
,
},
}
{
abiDefinition
:=
fmt
.
Sprintf
(
`[{ "name" : "method", "outputs": %s}]`
,
test
.
def
)
abi
,
err
:=
JSON
(
strings
.
NewReader
(
abiDefinition
))
if
err
!=
nil
{
t
.
Errorf
(
"%d failed. %v"
,
i
,
err
)
continue
}
type
unpackTest
struct
{
def
string
// ABI definition JSON
enc
string
// evm return data
want
interface
{}
// the expected output
err
string
// empty or error if expected
}
var
outvar
interface
{}
switch
test
.
outVar
{
case
"bool"
:
var
v
bool
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"uint8"
:
var
v
uint8
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"uint16"
:
var
v
uint16
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"uint32"
:
var
v
uint32
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"uint64"
:
var
v
uint64
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"int8"
:
var
v
int8
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"int16"
:
var
v
int16
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"int32"
:
var
v
int32
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"int64"
:
var
v
int64
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"*big.Int"
:
var
v
*
big
.
Int
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"address"
:
var
v
common
.
Address
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"bytes"
:
var
v
[]
byte
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
case
"hash"
:
var
v
common
.
Hash
err
=
abi
.
Unpack
(
&
v
,
"method"
,
test
.
marshalledOutput
)
outvar
=
v
.
Bytes
()[
:
]
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
:
t
.
Errorf
(
"unsupported type '%v' please add it to the switch statement in this test"
,
test
.
outVar
)
continue
func
(
test
unpackTest
)
checkError
(
err
error
)
error
{
if
err
!=
nil
{
if
len
(
test
.
err
)
==
0
{
return
fmt
.
Errorf
(
"expected no err but got: %v"
,
err
)
}
else
if
err
.
Error
()
!=
test
.
err
{
return
fmt
.
Errorf
(
"expected err: '%v' got err: %q"
,
test
.
err
,
err
)
}
}
else
if
len
(
test
.
err
)
>
0
{
return
fmt
.
Errorf
(
"expected err: %v but got none"
,
test
.
err
)
}
return
nil
}
if
err
!=
nil
&&
len
(
test
.
err
)
==
0
{
t
.
Errorf
(
"%d failed. Expected no err but got: %v"
,
i
,
err
)
continue
var
unpackTests
=
[]
unpackTest
{
{
def
:
`[{ "type": "bool" }]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
true
,
},
{
def
:
`[{"type": "uint32"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
uint32
(
1
),
},
{
def
:
`[{"type": "uint32"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
uint16
(
0
),
err
:
"abi: cannot unmarshal uint32 in to uint16"
,
},
{
def
:
`[{"type": "uint17"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
uint16
(
0
),
err
:
"abi: cannot unmarshal *big.Int in to uint16"
,
},
{
def
:
`[{"type": "uint17"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
big
.
NewInt
(
1
),
},
{
def
:
`[{"type": "int32"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
int32
(
1
),
},
{
def
:
`[{"type": "int32"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
int16
(
0
),
err
:
"abi: cannot unmarshal int32 in to int16"
,
},
{
def
:
`[{"type": "int17"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
int16
(
0
),
err
:
"abi: cannot unmarshal *big.Int in to int16"
,
},
{
def
:
`[{"type": "int17"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001"
,
want
:
big
.
NewInt
(
1
),
},
{
def
:
`[{"type": "address"}]`
,
enc
:
"0000000000000000000000000100000000000000000000000000000000000000"
,
want
:
common
.
Address
{
1
},
},
{
def
:
`[{"type": "bytes32"}]`
,
enc
:
"0100000000000000000000000000000000000000000000000000000000000000"
,
want
:
[
32
]
byte
{
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
},
},
{
def
:
`[{"type": "bytes"}]`
,
enc
:
"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200100000000000000000000000000000000000000000000000000000000000000"
,
want
:
common
.
Hex2Bytes
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
},
{
def
:
`[{"type": "bytes"}]`
,
enc
:
"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200100000000000000000000000000000000000000000000000000000000000000"
,
want
:
[
32
]
byte
{},
err
:
"abi: cannot unmarshal []uint8 in to [32]uint8"
,
},
{
def
:
`[{"type": "bytes32"}]`
,
enc
:
"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200100000000000000000000000000000000000000000000000000000000000000"
,
want
:
[]
byte
(
nil
),
err
:
"abi: cannot unmarshal [32]uint8 in to []uint8"
,
},
{
def
:
`[{"type": "bytes32"}]`
,
enc
:
"0100000000000000000000000000000000000000000000000000000000000000"
,
want
:
common
.
HexToHash
(
"0100000000000000000000000000000000000000000000000000000000000000"
),
},
{
def
:
`[{"type": "function"}]`
,
enc
:
"0100000000000000000000000000000000000000000000000000000000000000"
,
want
:
[
24
]
byte
{
1
},
},
// slices
{
def
:
`[{"type": "uint8[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
uint8
{
1
,
2
},
},
{
def
:
`[{"type": "uint8[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
uint8
{
1
,
2
},
},
// multi dimensional, if these pass, all types that don't require length prefix should pass
{
def
:
`[{"type": "uint8[][]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[][]
uint8
{{
1
,
2
},
{
1
,
2
}},
},
{
def
:
`[{"type": "uint8[2][2]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
][
2
]
uint8
{{
1
,
2
},
{
1
,
2
}},
},
{
def
:
`[{"type": "uint8[][2]"}]`
,
enc
:
"000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"
,
want
:
[
2
][]
uint8
{{
1
},
{
1
}},
},
{
def
:
`[{"type": "uint8[2][]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[][
2
]
uint8
{{
1
,
2
}},
},
{
def
:
`[{"type": "uint16[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
uint16
{
1
,
2
},
},
{
def
:
`[{"type": "uint16[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
uint16
{
1
,
2
},
},
{
def
:
`[{"type": "uint32[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
uint32
{
1
,
2
},
},
{
def
:
`[{"type": "uint32[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
uint32
{
1
,
2
},
},
{
def
:
`[{"type": "uint64[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
uint64
{
1
,
2
},
},
{
def
:
`[{"type": "uint64[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
uint64
{
1
,
2
},
},
{
def
:
`[{"type": "uint256[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
*
big
.
Int
{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
)},
},
{
def
:
`[{"type": "uint256[3]"}]`
,
enc
:
"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"
,
want
:
[
3
]
*
big
.
Int
{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
),
big
.
NewInt
(
3
)},
},
{
def
:
`[{"type": "int8[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
int8
{
1
,
2
},
},
{
def
:
`[{"type": "int8[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
int8
{
1
,
2
},
},
{
def
:
`[{"type": "int16[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
int16
{
1
,
2
},
},
{
def
:
`[{"type": "int16[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
int16
{
1
,
2
},
},
{
def
:
`[{"type": "int32[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
int32
{
1
,
2
},
},
{
def
:
`[{"type": "int32[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
int32
{
1
,
2
},
},
{
def
:
`[{"type": "int64[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
int64
{
1
,
2
},
},
{
def
:
`[{"type": "int64[2]"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[
2
]
int64
{
1
,
2
},
},
{
def
:
`[{"type": "int256[]"}]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
[]
*
big
.
Int
{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
)},
},
{
def
:
`[{"type": "int256[3]"}]`
,
enc
:
"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"
,
want
:
[
3
]
*
big
.
Int
{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
),
big
.
NewInt
(
3
)},
},
}
func
TestUnpack
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
unpackTests
{
def
:=
fmt
.
Sprintf
(
`[{ "name" : "method", "outputs": %s}]`
,
test
.
def
)
abi
,
err
:=
JSON
(
strings
.
NewReader
(
def
))
if
err
!=
nil
{
t
.
Fatalf
(
"invalid ABI definition %s: %v"
,
def
,
err
)
}
if
err
==
nil
&&
len
(
test
.
err
)
!=
0
{
t
.
Errorf
(
"%d failed. Expected err: %v but got none"
,
i
,
test
.
err
)
continue
encb
,
err
:=
hex
.
DecodeString
(
test
.
enc
)
if
err
!=
nil
{
t
.
Fatalf
(
"invalid hex: %s"
+
test
.
enc
)
}
if
err
!=
nil
&&
len
(
test
.
err
)
!=
0
&&
err
.
Error
()
!=
test
.
err
{
t
.
Errorf
(
"%d failed. Expected err: '%v' got err: '%v'"
,
i
,
test
.
err
,
err
)
outptr
:=
reflect
.
New
(
reflect
.
TypeOf
(
test
.
want
))
err
=
abi
.
Unpack
(
outptr
.
Interface
(),
"method"
,
encb
)
if
err
:=
test
.
checkError
(
err
);
err
!=
nil
{
t
.
Errorf
(
"test %d (%v) failed: %v"
,
i
,
test
.
def
,
err
)
continue
}
if
err
==
nil
{
if
!
reflect
.
DeepEqual
(
test
.
expectedOut
,
outvar
)
{
t
.
Errorf
(
"%d failed. Output error: expected %v, got %v"
,
i
,
test
.
expectedOut
,
outvar
)
}
out
:=
outptr
.
Elem
()
.
Interface
()
if
!
reflect
.
DeepEqual
(
test
.
want
,
out
)
{
t
.
Errorf
(
"test %d (%v) failed: expected %v, got %v"
,
i
,
test
.
def
,
test
.
want
,
out
)
}
}
}
func
TestUnpackSetInterfaceSlice
(
t
*
testing
.
T
)
{
var
(
var1
=
new
(
uint8
)
var2
=
new
(
uint8
)
)
out
:=
[]
interface
{}{
var1
,
var2
}
abi
,
err
:=
JSON
(
strings
.
NewReader
(
`[{"type":"function", "name":"ints", "outputs":[{"type":"uint8"}, {"type":"uint8"}]}]`
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
marshalledReturn
:=
append
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000002"
)
...
)
err
=
abi
.
Unpack
(
&
out
,
"ints"
,
marshalledReturn
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
*
var1
!=
1
{
t
.
Error
(
"expected var1 to be 1, got"
,
*
var1
)
}
if
*
var2
!=
2
{
t
.
Error
(
"expected var2 to be 2, got"
,
*
var2
)
}
out
=
[]
interface
{}{
var1
}
err
=
abi
.
Unpack
(
&
out
,
"ints"
,
marshalledReturn
)
expErr
:=
"abi: cannot marshal in to slices of unequal size (require: 2, got: 1)"
if
err
==
nil
||
err
.
Error
()
!=
expErr
{
t
.
Error
(
"expected err:"
,
expErr
,
"Got:"
,
err
)
}
}
func
TestUnpackSetInterfaceArrayOutput
(
t
*
testing
.
T
)
{
var
(
var1
=
new
([
1
]
uint32
)
var2
=
new
([
1
]
uint32
)
)
out
:=
[]
interface
{}{
var1
,
var2
}
abi
,
err
:=
JSON
(
strings
.
NewReader
(
`[{"type":"function", "name":"ints", "outputs":[{"type":"uint32[1]"}, {"type":"uint32[1]"}]}]`
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
marshalledReturn
:=
append
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
),
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000002"
)
...
)
err
=
abi
.
Unpack
(
&
out
,
"ints"
,
marshalledReturn
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
*
var1
!=
[
1
]
uint32
{
1
}
{
t
.
Error
(
"expected var1 to be [1], got"
,
*
var1
)
}
if
*
var2
!=
[
1
]
uint32
{
2
}
{
t
.
Error
(
"expected var2 to be [2], got"
,
*
var2
)
}
}
func
TestMultiReturnWithStruct
(
t
*
testing
.
T
)
{
const
definition
=
`[
{ "name" : "multi", "constant" : false, "outputs": [ { "name": "Int", "type": "uint256" }, { "name": "String", "type": "string" } ] }]`
...
...
@@ -337,101 +336,6 @@ func TestMultiReturnWithStruct(t *testing.T) {
}
}
func
TestMultiReturnWithSlice
(
t
*
testing
.
T
)
{
const
definition
=
`[
{ "name" : "multi", "constant" : false, "outputs": [ { "name": "Int", "type": "uint256" }, { "name": "String", "type": "string" } ] }]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// using buff to make the code readable
buff
:=
new
(
bytes
.
Buffer
)
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000040"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000005"
))
stringOut
:=
"hello"
buff
.
Write
(
common
.
RightPadBytes
([]
byte
(
stringOut
),
32
))
var
inter
[]
interface
{}
err
=
abi
.
Unpack
(
&
inter
,
"multi"
,
buff
.
Bytes
())
if
err
!=
nil
{
t
.
Error
(
err
)
}
if
len
(
inter
)
!=
2
{
t
.
Fatal
(
"expected 2 results got"
,
len
(
inter
))
}
if
num
,
ok
:=
inter
[
0
]
.
(
*
big
.
Int
);
!
ok
||
num
.
Cmp
(
big
.
NewInt
(
1
))
!=
0
{
t
.
Error
(
"expected index 0 to be 1 got"
,
num
)
}
if
str
,
ok
:=
inter
[
1
]
.
(
string
);
!
ok
||
str
!=
stringOut
{
t
.
Error
(
"expected index 1 to be"
,
stringOut
,
"got"
,
str
)
}
}
func
TestMarshalArrays
(
t
*
testing
.
T
)
{
const
definition
=
`[
{ "name" : "bytes32", "constant" : false, "outputs": [ { "type": "bytes32" } ] },
{ "name" : "bytes10", "constant" : false, "outputs": [ { "type": "bytes10" } ] }
]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
output
:=
common
.
LeftPadBytes
([]
byte
{
1
},
32
)
var
bytes10
[
10
]
byte
err
=
abi
.
Unpack
(
&
bytes10
,
"bytes32"
,
output
)
if
err
==
nil
||
err
.
Error
()
!=
"abi: cannot unmarshal src (len=32) in to dst (len=10)"
{
t
.
Error
(
"expected error or bytes32 not be assignable to bytes10:"
,
err
)
}
var
bytes32
[
32
]
byte
err
=
abi
.
Unpack
(
&
bytes32
,
"bytes32"
,
output
)
if
err
!=
nil
{
t
.
Error
(
"didn't expect error:"
,
err
)
}
if
!
bytes
.
Equal
(
bytes32
[
:
],
output
)
{
t
.
Error
(
"expected bytes32[31] to be 1 got"
,
bytes32
[
31
])
}
type
(
B10
[
10
]
byte
B32
[
32
]
byte
)
var
b10
B10
err
=
abi
.
Unpack
(
&
b10
,
"bytes32"
,
output
)
if
err
==
nil
||
err
.
Error
()
!=
"abi: cannot unmarshal src (len=32) in to dst (len=10)"
{
t
.
Error
(
"expected error or bytes32 not be assignable to bytes10:"
,
err
)
}
var
b32
B32
err
=
abi
.
Unpack
(
&
b32
,
"bytes32"
,
output
)
if
err
!=
nil
{
t
.
Error
(
"didn't expect error:"
,
err
)
}
if
!
bytes
.
Equal
(
b32
[
:
],
output
)
{
t
.
Error
(
"expected bytes32[31] to be 1 got"
,
bytes32
[
31
])
}
output
[
10
]
=
1
var
shortAssignLong
[
32
]
byte
err
=
abi
.
Unpack
(
&
shortAssignLong
,
"bytes10"
,
output
)
if
err
!=
nil
{
t
.
Error
(
"didn't expect error:"
,
err
)
}
if
!
bytes
.
Equal
(
output
,
shortAssignLong
[
:
])
{
t
.
Errorf
(
"expected %x to be %x"
,
shortAssignLong
,
output
)
}
}
func
TestUnmarshal
(
t
*
testing
.
T
)
{
const
definition
=
`[
{ "name" : "int", "constant" : false, "outputs": [ { "type": "uint256" } ] },
...
...
@@ -450,6 +354,29 @@ func TestUnmarshal(t *testing.T) {
}
buff
:=
new
(
bytes
.
Buffer
)
// marshall mixed bytes (mixedBytes)
p0
,
p0Exp
:=
[]
byte
{},
common
.
Hex2Bytes
(
"01020000000000000000"
)
p1
,
p1Exp
:=
[
32
]
byte
{},
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000ddeeff"
)
mixedBytes
:=
[]
interface
{}{
&
p0
,
&
p1
}
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000040"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000ddeeff"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"000000000000000000000000000000000000000000000000000000000000000a"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0102000000000000000000000000000000000000000000000000000000000000"
))
err
=
abi
.
Unpack
(
&
mixedBytes
,
"mixedBytes"
,
buff
.
Bytes
())
if
err
!=
nil
{
t
.
Error
(
err
)
}
else
{
if
bytes
.
Compare
(
p0
,
p0Exp
)
!=
0
{
t
.
Errorf
(
"unexpected value unpacked: want %x, got %x"
,
p0Exp
,
p0
)
}
if
bytes
.
Compare
(
p1
[
:
],
p1Exp
)
!=
0
{
t
.
Errorf
(
"unexpected value unpacked: want %x, got %x"
,
p1Exp
,
p1
)
}
}
// marshal int
var
Int
*
big
.
Int
err
=
abi
.
Unpack
(
&
Int
,
"int"
,
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
))
...
...
@@ -473,6 +400,7 @@ func TestUnmarshal(t *testing.T) {
}
// marshal dynamic bytes max length 32
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
bytesOut
:=
common
.
RightPadBytes
([]
byte
(
"hello"
),
32
)
...
...
@@ -504,11 +432,11 @@ func TestUnmarshal(t *testing.T) {
t
.
Errorf
(
"expected %x got %x"
,
bytesOut
,
Bytes
)
}
// marshall dynamic bytes max length 6
3
// marshall dynamic bytes max length 6
4
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"000000000000000000000000000000000000000000000000000000000000003f"
))
bytesOut
=
common
.
RightPadBytes
([]
byte
(
"hello"
),
6
3
)
bytesOut
=
common
.
RightPadBytes
([]
byte
(
"hello"
),
6
4
)
buff
.
Write
(
bytesOut
)
err
=
abi
.
Unpack
(
&
Bytes
,
"bytes"
,
buff
.
Bytes
())
...
...
@@ -516,8 +444,8 @@ func TestUnmarshal(t *testing.T) {
t
.
Error
(
err
)
}
if
!
bytes
.
Equal
(
Bytes
,
bytesOut
)
{
t
.
Errorf
(
"expected %x got %x"
,
bytesOut
,
Bytes
)
if
!
bytes
.
Equal
(
Bytes
,
bytesOut
[
:
len
(
bytesOut
)
-
1
]
)
{
t
.
Errorf
(
"expected %x got %x"
,
bytesOut
[
:
len
(
bytesOut
)
-
1
]
,
Bytes
)
}
// marshal dynamic bytes output empty
...
...
@@ -569,29 +497,6 @@ func TestUnmarshal(t *testing.T) {
t
.
Error
(
"expected error"
)
}
// marshal mixed bytes
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000040"
))
fixed
:=
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
)
buff
.
Write
(
fixed
)
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
bytesOut
=
common
.
RightPadBytes
([]
byte
(
"hello"
),
32
)
buff
.
Write
(
bytesOut
)
var
out
[]
interface
{}
err
=
abi
.
Unpack
(
&
out
,
"mixedBytes"
,
buff
.
Bytes
())
if
err
!=
nil
{
t
.
Fatal
(
"didn't expect error:"
,
err
)
}
if
!
bytes
.
Equal
(
bytesOut
,
out
[
0
]
.
([]
byte
))
{
t
.
Errorf
(
"expected %x, got %x"
,
bytesOut
,
out
[
0
])
}
if
!
bytes
.
Equal
(
fixed
,
out
[
1
]
.
([]
byte
))
{
t
.
Errorf
(
"expected %x, got %x"
,
fixed
,
out
[
1
])
}
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000002"
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment