Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
968d8ffe
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,发现更多精彩内容 >>
提交
968d8ffe
编写于
3月 31, 2016
作者:
J
Jeffrey Wilcke
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
abi: accept output slices of all supported types
上级
022cbd68
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
143 addition
and
5 deletion
+143
-5
accounts/abi/abi.go
accounts/abi/abi.go
+71
-1
accounts/abi/abi_test.go
accounts/abi/abi_test.go
+70
-1
accounts/abi/type.go
accounts/abi/type.go
+2
-3
未找到文件。
accounts/abi/abi.go
浏览文件 @
968d8ffe
...
...
@@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"io"
"math/big"
"reflect"
"strings"
...
...
@@ -116,11 +117,80 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
return
append
(
method
.
Id
(),
arguments
...
),
nil
}
// toGoSliceType prses 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
)
}
// first we need to create a slice of the type
var
refSlice
reflect
.
Value
switch
t
.
Type
.
T
{
case
IntTy
,
UintTy
,
BoolTy
:
// int, uint, bool can all be of type big int.
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
))
default
:
// no other types are supported
return
nil
,
fmt
.
Errorf
(
"abi: unsupported slice type %v"
,
t
.
Type
.
T
)
}
// get the offset which determines the start of this array ...
offset
:=
int
(
common
.
BytesToBig
(
output
[
index
:
index
+
32
])
.
Uint64
())
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
(
common
.
BytesToBig
(
slice
[
:
32
])
.
Uint64
())
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
)]
for
i
:=
0
;
i
<
size
;
i
++
{
var
(
inter
interface
{}
// interface type
returnOutput
=
slice
[
i
*
32
:
i
*
32
+
32
]
// the return output
)
// set inter to the correct type (cast)
switch
t
.
Type
.
T
{
case
IntTy
,
UintTy
:
inter
=
common
.
BytesToBig
(
returnOutput
)
case
BoolTy
:
inter
=
common
.
BytesToBig
(
returnOutput
)
.
Uint64
()
>
0
case
AddressTy
:
inter
=
common
.
BytesToAddress
(
returnOutput
)
case
HashTy
:
inter
=
common
.
BytesToHash
(
returnOutput
)
}
// append the item to our reflect slice
refSlice
=
reflect
.
Append
(
refSlice
,
reflect
.
ValueOf
(
inter
))
}
// return the interface
return
refSlice
.
Interface
(),
nil
}
// 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
)
{
index
:=
i
*
32
// we need to treat slices differently
if
t
.
Type
.
Kind
==
reflect
.
Slice
{
return
toGoSlice
(
i
,
t
,
output
)
}
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
)
}
...
...
accounts/abi/abi_test.go
浏览文件 @
968d8ffe
...
...
@@ -688,12 +688,15 @@ func TestUnmarshal(t *testing.T) {
{ "name" : "bytes", "const" : false, "outputs": [ { "type": "bytes" } ] },
{ "name" : "fixed", "const" : false, "outputs": [ { "type": "bytes32" } ] },
{ "name" : "multi", "const" : false, "outputs": [ { "type": "bytes" }, { "type": "bytes" } ] },
{ "name" : "addressSliceSingle", "const" : false, "outputs": [ { "type": "address[]" } ] },
{ "name" : "addressSliceDouble", "const" : false, "outputs": [ { "name": "a", "type": "address[]" }, { "name": "b", "type": "address[]" } ] },
{ "name" : "mixedBytes", "const" : true, "outputs": [ { "name": "a", "type": "bytes" }, { "name": "b", "type": "bytes32" } ] }]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
buff
:=
new
(
bytes
.
Buffer
)
// marshal int
var
Int
*
big
.
Int
...
...
@@ -718,7 +721,6 @@ func TestUnmarshal(t *testing.T) {
}
// marshal dynamic bytes max length 32
buff
:=
new
(
bytes
.
Buffer
)
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
bytesOut
:=
common
.
RightPadBytes
([]
byte
(
"hello"
),
32
)
...
...
@@ -837,4 +839,71 @@ func TestUnmarshal(t *testing.T) {
if
!
bytes
.
Equal
(
fixed
,
out
[
1
]
.
([]
byte
))
{
t
.
Errorf
(
"expected %x, got %x"
,
fixed
,
out
[
1
])
}
// marshal address slice
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
// offset
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
))
// size
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000100000000000000000000000000000000000000"
))
var
outAddr
[]
common
.
Address
err
=
abi
.
Unpack
(
&
outAddr
,
"addressSliceSingle"
,
buff
.
Bytes
())
if
err
!=
nil
{
t
.
Fatal
(
"didn't expect error:"
,
err
)
}
if
len
(
outAddr
)
!=
1
{
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddr
))
}
if
outAddr
[
0
]
!=
(
common
.
Address
{
1
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Address
{
1
},
outAddr
[
0
])
}
// marshal multiple address slice
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000040"
))
// offset
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000080"
))
// offset
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
))
// size
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000100000000000000000000000000000000000000"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000002"
))
// size
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000200000000000000000000000000000000000000"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000300000000000000000000000000000000000000"
))
var
outAddrStruct
struct
{
A
[]
common
.
Address
B
[]
common
.
Address
}
err
=
abi
.
Unpack
(
&
outAddrStruct
,
"addressSliceDouble"
,
buff
.
Bytes
())
if
err
!=
nil
{
t
.
Fatal
(
"didn't expect error:"
,
err
)
}
if
len
(
outAddrStruct
.
A
)
!=
1
{
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddrStruct
.
A
))
}
if
outAddrStruct
.
A
[
0
]
!=
(
common
.
Address
{
1
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Address
{
1
},
outAddrStruct
.
A
[
0
])
}
if
len
(
outAddrStruct
.
B
)
!=
2
{
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddrStruct
.
B
))
}
if
outAddrStruct
.
B
[
0
]
!=
(
common
.
Address
{
2
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Address
{
2
},
outAddrStruct
.
B
[
0
])
}
if
outAddrStruct
.
B
[
1
]
!=
(
common
.
Address
{
3
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Address
{
3
},
outAddrStruct
.
B
[
1
])
}
// marshal invalid address slice
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000100"
))
err
=
abi
.
Unpack
(
&
outAddr
,
"addressSliceSingle"
,
buff
.
Bytes
())
if
err
==
nil
{
t
.
Fatal
(
"expected error:"
,
err
)
}
}
accounts/abi/type.go
浏览文件 @
968d8ffe
...
...
@@ -113,7 +113,6 @@ func NewType(t string) (typ Type, err error) {
case
"real"
:
// TODO
typ
.
Kind
=
reflect
.
Invalid
case
"address"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Type
=
address_t
typ
.
Size
=
20
typ
.
T
=
AddressTy
...
...
@@ -125,12 +124,12 @@ func NewType(t string) (typ Type, err error) {
typ
.
Size
=
32
}
case
"hash"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Kind
=
reflect
.
Array
typ
.
Size
=
32
typ
.
Type
=
hash_t
typ
.
T
=
HashTy
case
"bytes"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Kind
=
reflect
.
Array
typ
.
Type
=
byte_ts
typ
.
Size
=
vsize
if
vsize
==
0
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录