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
4f28c5b6
Commit
4f28c5b6
authored
Feb 14, 2016
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2210 from obscuren/abi-typed-array
accounts/abi: support for typed array
parents
cb859238
6fe917ec
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
114 additions
and
43 deletions
+114
-43
abi.go
accounts/abi/abi.go
+39
-12
abi_test.go
accounts/abi/abi_test.go
+75
-31
No files found.
accounts/abi/abi.go
View file @
4f28c5b6
...
...
@@ -165,7 +165,14 @@ func (abi ABI) Call(executer Executer, v interface{}, name string, args ...inter
return
abi
.
unmarshal
(
v
,
name
,
executer
(
callData
))
}
var
interSlice
=
reflect
.
TypeOf
([]
interface
{}{})
// 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
))
)
// unmarshal output in v according to the abi specification
func
(
abi
ABI
)
unmarshal
(
v
interface
{},
name
string
,
output
[]
byte
)
error
{
...
...
@@ -194,17 +201,14 @@ func (abi ABI) unmarshal(v interface{}, name string, output []byte) error {
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
field
.
Type
.
AssignableTo
(
reflectValue
.
Type
())
{
value
.
Field
(
j
)
.
Set
(
reflectValue
)
break
}
else
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to %v"
,
field
.
Type
,
reflectValue
.
Type
())
if
err
:=
set
(
value
.
Field
(
j
),
reflectValue
,
method
.
Outputs
[
i
]);
err
!=
nil
{
return
err
}
}
}
}
case
reflect
.
Slice
:
if
!
value
.
Type
()
.
AssignableTo
(
interSlice
)
{
if
!
value
.
Type
()
.
AssignableTo
(
r_
interSlice
)
{
return
fmt
.
Errorf
(
"abi: cannot marshal tuple in to slice %T (only []interface{} is supported)"
,
v
)
}
...
...
@@ -228,17 +232,40 @@ func (abi ABI) unmarshal(v interface{}, name string, output []byte) error {
if
err
!=
nil
{
return
err
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
if
typ
.
AssignableTo
(
reflectValue
.
Type
())
{
value
.
Set
(
reflectValue
)
}
else
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to %v"
,
reflectValue
.
Type
(),
value
.
Type
())
if
err
:=
set
(
value
,
reflect
.
ValueOf
(
marshalledValue
),
method
.
Outputs
[
0
]);
err
!=
nil
{
return
err
}
}
return
nil
}
// set attempts to assign src to dst by either setting, copying or otherwise.
//
// set is a bit more lenient when it comes to assignment and doesn't force an as
// strict ruleset as bare `reflect` does.
func
set
(
dst
,
src
reflect
.
Value
,
output
Argument
)
error
{
dstType
:=
dst
.
Type
()
srcType
:=
src
.
Type
()
switch
{
case
dstType
.
AssignableTo
(
src
.
Type
())
:
dst
.
Set
(
src
)
case
dstType
.
Kind
()
==
reflect
.
Array
&&
srcType
.
Kind
()
==
reflect
.
Slice
:
if
!
dstType
.
Elem
()
.
AssignableTo
(
r_byte
)
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to array of elem %v"
,
src
.
Type
(),
dstType
.
Elem
())
}
if
dst
.
Len
()
<
output
.
Type
.
Size
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal src (len=%d) in to dst (len=%d)"
,
output
.
Type
.
Size
,
dst
.
Len
())
}
reflect
.
Copy
(
dst
,
src
)
default
:
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to %v"
,
src
.
Type
(),
dst
.
Type
())
}
return
nil
}
func
(
abi
*
ABI
)
UnmarshalJSON
(
data
[]
byte
)
error
{
var
fields
[]
struct
{
Type
string
...
...
accounts/abi/abi_test.go
View file @
4f28c5b6
...
...
@@ -394,37 +394,6 @@ func TestBytes(t *testing.T) {
}
}
/*
func TestReturn(t *testing.T) {
const definition = `[
{ "type" : "function", "name" : "balance", "const" : true, "inputs" : [], "outputs" : [ { "name": "", "type": "hash" } ] },
{ "type" : "function", "name" : "name", "const" : true, "inputs" : [], "outputs" : [ { "name": "", "type": "address" } ] }]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
t.Fatal(err)
}
r := abi.Call(func([]byte) []byte {
t := make([]byte, 32)
t[0] = 1
return t
}, "balance")
if _, ok := r.(common.Hash); !ok {
t.Errorf("expected type common.Hash, got %T", r)
}
r = abi.Call(func([]byte) []byte {
t := make([]byte, 32)
t[0] = 1
return t
}, "name")
if _, ok := r.(common.Address); !ok {
t.Errorf("expected type common.Address, got %T", r)
}
}
*/
func
TestDefaultFunctionParsing
(
t
*
testing
.
T
)
{
const
definition
=
`[{ "name" : "balance" }]`
...
...
@@ -550,11 +519,71 @@ func TestMultiReturnWithSlice(t *testing.T) {
}
}
func
TestMarshalArrays
(
t
*
testing
.
T
)
{
const
definition
=
`[
{ "name" : "bytes32", "const" : false, "outputs": [ { "type": "bytes32" } ] },
{ "name" : "bytes10", "const" : 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
.
unmarshal
(
&
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
.
unmarshal
(
&
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
.
unmarshal
(
&
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
.
unmarshal
(
&
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
.
unmarshal
(
&
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", "const" : false, "outputs": [ { "type": "uint256" } ] },
{ "name" : "bool", "const" : false, "outputs": [ { "type": "bool" } ] },
{ "name" : "bytes", "const" : false, "outputs": [ { "type": "bytes" } ] },
{ "name" : "fixed", "const" : false, "outputs": [ { "type": "bytes32" } ] },
{ "name" : "multi", "const" : false, "outputs": [ { "type": "bytes" }, { "type": "bytes" } ] },
{ "name" : "mixedBytes", "const" : true, "outputs": [ { "name": "a", "type": "bytes" }, { "name": "b", "type": "bytes32" } ] }]`
...
...
@@ -655,6 +684,21 @@ func TestUnmarshal(t *testing.T) {
t
.
Errorf
(
"expected %x got %x"
,
bytesOut
,
Bytes
)
}
// marshal dynamic bytes length 5
buff
.
Reset
()
buff
.
Write
(
common
.
RightPadBytes
([]
byte
(
"hello"
),
32
))
var
hash
common
.
Hash
err
=
abi
.
unmarshal
(
&
hash
,
"fixed"
,
buff
.
Bytes
())
if
err
!=
nil
{
t
.
Error
(
err
)
}
helloHash
:=
common
.
BytesToHash
(
common
.
RightPadBytes
([]
byte
(
"hello"
),
32
))
if
hash
!=
helloHash
{
t
.
Errorf
(
"Expected %x to equal %x"
,
hash
,
helloHash
)
}
// marshal error
buff
.
Reset
()
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000020"
))
...
...
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