Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
dec8bba9
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
dec8bba9
编写于
10月 17, 2017
作者:
R
RJ Catalano
提交者:
Felix Lange
10月 17, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
accounts/abi: improve type handling, add event support (#14743)
上级
e9295163
变更
15
展开全部
隐藏空白更改
内联
并排
Showing
15 changed file
with
903 addition
and
847 deletion
+903
-847
accounts/abi/abi.go
accounts/abi/abi.go
+16
-99
accounts/abi/abi_test.go
accounts/abi/abi_test.go
+1
-20
accounts/abi/bind/bind_test.go
accounts/abi/bind/bind_test.go
+1
-1
accounts/abi/error.go
accounts/abi/error.go
+12
-12
accounts/abi/event.go
accounts/abi/event.go
+91
-0
accounts/abi/event_test.go
accounts/abi/event_test.go
+1
-1
accounts/abi/method.go
accounts/abi/method.go
+79
-0
accounts/abi/numbers.go
accounts/abi/numbers.go
+17
-30
accounts/abi/pack.go
accounts/abi/pack.go
+5
-2
accounts/abi/pack_test.go
accounts/abi/pack_test.go
+2
-5
accounts/abi/reflect.go
accounts/abi/reflect.go
+2
-8
accounts/abi/type.go
accounts/abi/type.go
+103
-107
accounts/abi/type_test.go
accounts/abi/type_test.go
+170
-45
accounts/abi/unpack.go
accounts/abi/unpack.go
+130
-149
accounts/abi/unpack_test.go
accounts/abi/unpack_test.go
+273
-368
未找到文件。
accounts/abi/abi.go
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
dec8bba9
此差异已折叠。
点击以展开。
accounts/abi/unpack.go
浏览文件 @
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
浏览文件 @
dec8bba9
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录