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
022cbd68
Commit
022cbd68
authored
Mar 30, 2016
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
abi: accept input slices of all supported types
parent
96c7c39a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
106 additions
and
145 deletions
+106
-145
abi.go
accounts/abi/abi.go
+3
-4
abi_test.go
accounts/abi/abi_test.go
+47
-72
numbers.go
accounts/abi/numbers.go
+0
-2
numbers_test.go
accounts/abi/numbers_test.go
+0
-4
type.go
accounts/abi/type.go
+56
-63
No files found.
accounts/abi/abi.go
View file @
022cbd68
...
...
@@ -63,9 +63,8 @@ func (abi ABI) pack(method Method, args ...interface{}) ([]byte, error) {
return
nil
,
fmt
.
Errorf
(
"`%s` %v"
,
method
.
Name
,
err
)
}
// check for a string or bytes input type
switch
input
.
Type
.
T
{
case
StringTy
,
BytesTy
:
// check for a slice type (string, bytes, slice)
if
input
.
Type
.
T
==
StringTy
||
input
.
Type
.
T
==
BytesTy
||
input
.
Type
.
IsSlice
{
// calculate the offset
offset
:=
len
(
method
.
Inputs
)
*
32
+
len
(
variableInput
)
// set the offset
...
...
@@ -73,7 +72,7 @@ func (abi ABI) pack(method Method, args ...interface{}) ([]byte, error) {
// Append the packed output to the variable input. The variable input
// will be appended at the end of the input.
variableInput
=
append
(
variableInput
,
packed
...
)
default
:
}
else
{
// append the packed value to the input
ret
=
append
(
ret
,
packed
...
)
}
...
...
accounts/abi/abi_test.go
View file @
022cbd68
...
...
@@ -49,7 +49,9 @@ const jsondata2 = `
{ "type" : "function", "name" : "foo", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
{ "type" : "function", "name" : "bar", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
{ "type" : "function", "name" : "slice", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
{ "type" : "function", "name" : "slice256", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] }
{ "type" : "function", "name" : "slice256", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
{ "type" : "function", "name" : "sliceAddress", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
{ "type" : "function", "name" : "sliceMultiAddress", "const" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
]`
func
TestType
(
t
*
testing
.
T
)
{
...
...
@@ -68,7 +70,7 @@ func TestType(t *testing.T) {
if
typ
.
Kind
!=
reflect
.
Slice
{
t
.
Error
(
"expected uint32[] to have type slice"
)
}
if
typ
.
Type
!=
ubig_t
s
{
if
typ
.
Type
!=
ubig_t
{
t
.
Error
(
"expcted uith32[] to have type uint64"
)
}
...
...
@@ -79,7 +81,7 @@ func TestType(t *testing.T) {
if
typ
.
Kind
!=
reflect
.
Slice
{
t
.
Error
(
"expected uint32[2] to have kind slice"
)
}
if
typ
.
Type
!=
ubig_t
s
{
if
typ
.
Type
!=
ubig_t
{
t
.
Error
(
"expcted uith32[2] to have type uint64"
)
}
if
typ
.
Size
!=
2
{
...
...
@@ -202,16 +204,6 @@ func TestTestSlice(t *testing.T) {
t
.
FailNow
()
}
addr
:=
make
([]
byte
,
20
)
if
_
,
err
:=
abi
.
Pack
(
"address"
,
addr
);
err
!=
nil
{
t
.
Error
(
err
)
}
addr
=
make
([]
byte
,
21
)
if
_
,
err
:=
abi
.
Pack
(
"address"
,
addr
);
err
==
nil
{
t
.
Error
(
"expected address of 21 width to throw"
)
}
slice
:=
make
([]
byte
,
2
)
if
_
,
err
:=
abi
.
Pack
(
"uint64[2]"
,
slice
);
err
!=
nil
{
t
.
Error
(
err
)
...
...
@@ -222,19 +214,6 @@ func TestTestSlice(t *testing.T) {
}
}
func
TestTestAddress
(
t
*
testing
.
T
)
{
abi
,
err
:=
JSON
(
strings
.
NewReader
(
jsondata2
))
if
err
!=
nil
{
t
.
Error
(
err
)
t
.
FailNow
()
}
addr
:=
make
([]
byte
,
20
)
if
_
,
err
:=
abi
.
Pack
(
"address"
,
addr
);
err
!=
nil
{
t
.
Error
(
err
)
}
}
func
TestMethodSignature
(
t
*
testing
.
T
)
{
String
,
_
:=
NewType
(
"string"
)
String32
,
_
:=
NewType
(
"string32"
)
...
...
@@ -310,44 +289,69 @@ func TestPackSlice(t *testing.T) {
}
sig
:=
crypto
.
Keccak256
([]
byte
(
"slice(uint32[2])"
))[
:
4
]
sig
=
append
(
sig
,
make
([]
byte
,
64
)
...
)
sig
[
35
]
=
1
sig
[
67
]
=
2
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
32
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
1
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
packed
,
err
:=
abi
.
Pack
(
"slice"
,
[]
uint32
{
1
,
2
})
if
err
!=
nil
{
t
.
Error
(
err
)
t
.
FailNow
()
}
if
!
bytes
.
Equal
(
packed
,
sig
)
{
t
.
Errorf
(
"expected %x got %x"
,
sig
,
packed
)
}
}
func
TestPackSliceBig
(
t
*
testing
.
T
)
{
abi
,
err
:=
JSON
(
strings
.
NewReader
(
jsondata2
))
var
addrA
,
addrB
=
common
.
Address
{
1
},
common
.
Address
{
2
}
sig
=
abi
.
Methods
[
"sliceAddress"
]
.
Id
()
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
32
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrA
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrB
[
:
],
32
)
...
)
packed
,
err
=
abi
.
Pack
(
"sliceAddress"
,
[]
common
.
Address
{
addrA
,
addrB
})
if
err
!=
nil
{
t
.
Error
(
err
)
t
.
FailNow
()
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
packed
,
sig
)
{
t
.
Errorf
(
"expected %x got %x"
,
sig
,
packed
)
}
sig
:=
crypto
.
Keccak256
([]
byte
(
"slice256(uint256[2])"
))[
:
4
]
sig
=
append
(
sig
,
make
([]
byte
,
64
)
...
)
sig
[
35
]
=
1
sig
[
67
]
=
2
var
addrC
,
addrD
=
common
.
Address
{
3
},
common
.
Address
{
4
}
sig
=
abi
.
Methods
[
"sliceMultiAddress"
]
.
Id
()
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
64
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
160
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrA
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrB
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrC
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrD
[
:
],
32
)
...
)
packed
,
err
=
abi
.
Pack
(
"sliceMultiAddress"
,
[]
common
.
Address
{
addrA
,
addrB
},
[]
common
.
Address
{
addrC
,
addrD
})
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
packed
,
sig
)
{
t
.
Errorf
(
"expected %x got %x"
,
sig
,
packed
)
}
packed
,
err
:=
abi
.
Pack
(
"slice256"
,
[]
*
big
.
Int
{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
)})
sig
=
crypto
.
Keccak256
([]
byte
(
"slice256(uint256[2])"
))[
:
4
]
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
32
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
1
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
packed
,
err
=
abi
.
Pack
(
"slice256"
,
[]
*
big
.
Int
{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
)})
if
err
!=
nil
{
t
.
Error
(
err
)
t
.
FailNow
()
}
if
!
bytes
.
Equal
(
packed
,
sig
)
{
t
.
Errorf
(
"expected %x got %x"
,
sig
,
packed
)
}
}
func
ExampleJSON
()
{
const
definition
=
`[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]`
...
...
@@ -370,7 +374,7 @@ func TestInputVariableInputLength(t *testing.T) {
{ "type" : "function", "name" : "strOne", "const" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
{ "type" : "function", "name" : "bytesOne", "const" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
{ "type" : "function", "name" : "strTwo", "const" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
]`
]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
...
...
@@ -493,35 +497,6 @@ func TestInputVariableInputLength(t *testing.T) {
}
}
func
TestBytes
(
t
*
testing
.
T
)
{
const
definition
=
`[
{ "type" : "function", "name" : "balance", "const" : true, "inputs" : [ { "name" : "address", "type" : "bytes20" } ] },
{ "type" : "function", "name" : "send", "const" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
ok
:=
make
([]
byte
,
20
)
_
,
err
=
abi
.
Pack
(
"balance"
,
ok
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
toosmall
:=
make
([]
byte
,
19
)
_
,
err
=
abi
.
Pack
(
"balance"
,
toosmall
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
toobig
:=
make
([]
byte
,
21
)
_
,
err
=
abi
.
Pack
(
"balance"
,
toobig
)
if
err
==
nil
{
t
.
Error
(
"expected error"
)
}
}
func
TestDefaultFunctionParsing
(
t
*
testing
.
T
)
{
const
definition
=
`[{ "name" : "balance" }]`
...
...
accounts/abi/numbers.go
View file @
022cbd68
...
...
@@ -117,8 +117,6 @@ func packNum(value reflect.Value, to byte) []byte {
// checks whether the given reflect value is signed. This also works for slices with a number type
func
isSigned
(
v
reflect
.
Value
)
bool
{
switch
v
.
Type
()
{
case
ubig_ts
,
big_ts
,
big_t
,
ubig_t
:
return
true
case
int_ts
,
int8_ts
,
int16_ts
,
int32_ts
,
int64_ts
,
int_t
,
int8_t
,
int16_t
,
int32_t
,
int64_t
:
return
true
}
...
...
accounts/abi/numbers_test.go
View file @
022cbd68
...
...
@@ -81,8 +81,4 @@ func TestSigned(t *testing.T) {
if
!
isSigned
(
reflect
.
ValueOf
(
int
(
10
)))
{
t
.
Error
()
}
if
!
isSigned
(
reflect
.
ValueOf
(
big
.
NewInt
(
10
)))
{
t
.
Error
()
}
}
accounts/abi/type.go
View file @
022cbd68
...
...
@@ -96,63 +96,57 @@ func NewType(t string) (typ Type, err error) {
t
+=
"256"
}
if
isslice
{
switch
vtype
{
case
"int"
:
typ
.
Kind
=
reflect
.
Ptr
typ
.
Type
=
big_t
typ
.
Size
=
256
typ
.
T
=
IntTy
case
"uint"
:
typ
.
Kind
=
reflect
.
Ptr
typ
.
Type
=
ubig_t
typ
.
Size
=
256
typ
.
T
=
UintTy
case
"bool"
:
typ
.
Kind
=
reflect
.
Bool
typ
.
T
=
BoolTy
case
"real"
:
// TODO
typ
.
Kind
=
reflect
.
Invalid
case
"address"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Size
=
size
switch
vtype
{
case
"int"
:
typ
.
Type
=
big_ts
case
"uint"
:
typ
.
Type
=
ubig_ts
default
:
return
Type
{},
fmt
.
Errorf
(
"unsupported arg slice type: %s"
,
t
)
}
}
else
{
switch
vtype
{
case
"int"
:
typ
.
Kind
=
reflect
.
Ptr
typ
.
Type
=
big_t
typ
.
Size
=
256
typ
.
T
=
IntTy
case
"uint"
:
typ
.
Kind
=
reflect
.
Ptr
typ
.
Type
=
ubig_t
typ
.
Size
=
256
typ
.
T
=
UintTy
case
"bool"
:
typ
.
Kind
=
reflect
.
Bool
typ
.
T
=
BoolTy
case
"real"
:
// TODO
typ
.
Kind
=
reflect
.
Invalid
case
"address"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Type
=
address_t
typ
.
Size
=
20
typ
.
T
=
AddressTy
case
"string"
:
typ
.
Kind
=
reflect
.
String
typ
.
Size
=
-
1
typ
.
T
=
StringTy
if
vsize
>
0
{
typ
.
Size
=
32
}
case
"hash"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Type
=
address_t
typ
.
Size
=
20
typ
.
T
=
AddressTy
case
"string"
:
typ
.
Kind
=
reflect
.
String
typ
.
Size
=
-
1
typ
.
T
=
StringTy
if
vsize
>
0
{
typ
.
Size
=
32
typ
.
Type
=
hash_t
typ
.
T
=
HashTy
case
"bytes"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Type
=
byte_ts
typ
.
Size
=
vsize
if
vsize
==
0
{
typ
.
T
=
BytesTy
}
else
{
typ
.
T
=
FixedBytesTy
}
default
:
return
Type
{},
fmt
.
Errorf
(
"unsupported arg type: %s"
,
t
)
}
case
"hash"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Size
=
32
typ
.
Type
=
hash_t
typ
.
T
=
HashTy
case
"bytes"
:
typ
.
Kind
=
reflect
.
Slice
typ
.
Type
=
byte_ts
typ
.
Size
=
vsize
if
vsize
==
0
{
typ
.
T
=
BytesTy
}
else
{
typ
.
T
=
FixedBytesTy
}
default
:
return
Type
{},
fmt
.
Errorf
(
"unsupported arg type: %s"
,
t
)
}
// if the type is a slice we must set Kind to a reflect.Slice
// so that serialisation can be determined based on this kind.
if
isslice
{
typ
.
Kind
=
reflect
.
Slice
typ
.
Size
=
size
}
typ
.
stringKind
=
t
...
...
@@ -203,7 +197,7 @@ func (t Type) pack(v interface{}) ([]byte, error) {
return
packBytesSlice
([]
byte
(
value
.
String
()),
value
.
Len
()),
nil
case
reflect
.
Slice
:
//
if the param is a bytes type, pack the slice up as a string
//
Byte slice is a special case, it gets treated as a single value
if
t
.
T
==
BytesTy
{
return
packBytesSlice
(
value
.
Bytes
(),
value
.
Len
()),
nil
}
...
...
@@ -212,21 +206,20 @@ func (t Type) pack(v interface{}) ([]byte, error) {
return
nil
,
fmt
.
Errorf
(
"%v out of bound. %d for %d"
,
value
.
Kind
(),
value
.
Len
(),
t
.
Size
)
}
// Address is a special slice. The slice acts as one rather than a list of elements.
if
t
.
T
==
AddressTy
{
return
common
.
LeftPadBytes
(
v
.
([]
byte
),
32
),
nil
}
// Signed / Unsigned check
if
(
t
.
T
!=
IntTy
&&
isSigned
(
value
))
||
(
t
.
T
==
UintTy
&&
isSigned
(
value
))
{
if
value
.
Type
()
==
big_t
&&
(
t
.
T
!=
IntTy
&&
isSigned
(
value
))
||
(
t
.
T
==
UintTy
&&
isSigned
(
value
))
{
return
nil
,
fmt
.
Errorf
(
"slice of incompatible types."
)
}
var
packed
[]
byte
for
i
:=
0
;
i
<
value
.
Len
();
i
++
{
packed
=
append
(
packed
,
packNum
(
value
.
Index
(
i
),
t
.
T
)
...
)
val
,
err
:=
t
.
pack
(
value
.
Index
(
i
)
.
Interface
())
if
err
!=
nil
{
return
nil
,
err
}
packed
=
append
(
packed
,
val
...
)
}
return
pack
ed
,
nil
return
pack
BytesSlice
(
packed
,
value
.
Len
())
,
nil
case
reflect
.
Bool
:
if
value
.
Bool
()
{
return
common
.
LeftPadBytes
(
common
.
Big1
.
Bytes
(),
32
),
nil
...
...
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