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
968d8ffe
Commit
968d8ffe
authored
Mar 31, 2016
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
abi: accept output slices of all supported types
parent
022cbd68
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
143 additions
and
5 deletions
+143
-5
abi.go
accounts/abi/abi.go
+71
-1
abi_test.go
accounts/abi/abi_test.go
+70
-1
type.go
accounts/abi/type.go
+2
-3
No files found.
accounts/abi/abi.go
View file @
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
View file @
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
View file @
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
{
...
...
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