Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
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
link33
plugin
Commits
d33e674d
Commit
d33e674d
authored
Nov 23, 2018
by
Litian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
evm abi 解析逻辑初步完成
parent
9cc23096
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
303 additions
and
146 deletions
+303
-146
abi.go
plugin/dapp/evm/executor/abi/abi.go
+1
-1
abi_test.go
plugin/dapp/evm/executor/abi/abi_test.go
+0
-0
api.go
plugin/dapp/evm/executor/abi/api.go
+200
-69
api_test.go
plugin/dapp/evm/executor/abi/api_test.go
+0
-0
argument.go
plugin/dapp/evm/executor/abi/argument.go
+5
-5
error.go
plugin/dapp/evm/executor/abi/error.go
+2
-2
event_test.go
plugin/dapp/evm/executor/abi/event_test.go
+25
-25
pack.go
plugin/dapp/evm/executor/abi/pack.go
+2
-2
reflect.go
plugin/dapp/evm/executor/abi/reflect.go
+8
-8
unpack.go
plugin/dapp/evm/executor/abi/unpack.go
+2
-2
unpack_test.go
plugin/dapp/evm/executor/abi/unpack_test.go
+23
-23
exec.go
plugin/dapp/evm/executor/exec.go
+26
-3
address.go
plugin/dapp/evm/executor/vm/common/address.go
+5
-0
evm.go
plugin/dapp/evm/types/evm.go
+4
-6
No files found.
plugin/dapp/evm/executor/abi/abi.go
View file @
d33e674d
...
@@ -44,7 +44,7 @@ func JSON(reader io.Reader) (ABI, error) {
...
@@ -44,7 +44,7 @@ func JSON(reader io.Reader) (ABI, error) {
return
abi
,
nil
return
abi
,
nil
}
}
// Pack the given method
n
ame to conform the ABI. Method call's data
// Pack the given method
N
ame to conform the ABI. Method call's data
// will consist of method_id, args0, arg1, ... argN. Method id consists
// will consist of method_id, args0, arg1, ... argN. Method id consists
// of 4 bytes and arguments are all 32 bytes.
// of 4 bytes and arguments are all 32 bytes.
// Method ids are created from the first 4 bytes of the hash of the
// Method ids are created from the first 4 bytes of the hash of the
...
...
plugin/dapp/evm/executor/abi/abi_test.go
View file @
d33e674d
This diff is collapsed.
Click to expand it.
plugin/dapp/evm/executor/abi/api.go
View file @
d33e674d
package
abi
package
abi
import
(
import
(
"encoding/json"
"fmt"
"fmt"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/golang-collections/collections/stack"
"github.com/golang-collections/collections/stack"
"math/big"
"reflect"
"reflect"
"strconv"
"strconv"
"strings"
)
)
// Pack 使用ABI方式调用时,将调用方式转换为EVM底层处理的十六进制编码
// Pack 使用ABI方式调用时,将调用方式转换为EVM底层处理的十六进制编码
// abiData 完整的ABI定义
// abiData 完整的ABI定义
// param 调用方法及参数
// param 调用方法及参数
func
Pack
(
param
,
abiData
string
)
([]
byte
,
error
)
{
// 调用方式: foo(param1,param2)
return
nil
,
nil
func
Pack
(
param
,
abiData
string
)
(
methodName
string
,
packData
[]
byte
,
err
error
)
{
// 首先解析参数字符串,分析出方法名以及个参数取值
methodName
,
params
,
err
:=
procFuncCall
(
param
)
if
err
!=
nil
{
return
methodName
,
packData
,
err
}
// 解析ABI数据结构,获取本次调用的方法对象
abi
,
err
:=
JSON
(
strings
.
NewReader
(
abiData
))
if
err
!=
nil
{
return
methodName
,
packData
,
err
}
var
method
Method
var
ok
bool
if
method
,
ok
=
abi
.
Methods
[
methodName
];
!
ok
{
err
=
fmt
.
Errorf
(
"function %v not exists"
,
methodName
)
return
methodName
,
packData
,
err
}
// 获取方法参数对象,遍历解析各参数,获得参数的Go取值
paramVals
:=
[]
interface
{}{}
if
len
(
params
)
!=
0
{
// 首先检查参数个数和ABI中定义的是否一致
if
method
.
Inputs
.
LengthNonIndexed
()
!=
len
(
params
)
{
err
=
fmt
.
Errorf
(
"function Params count error: %v"
,
param
)
return
methodName
,
packData
,
err
}
for
i
,
v
:=
range
method
.
Inputs
.
NonIndexed
()
{
paramVal
,
err
:=
str2GoValue
(
v
.
Type
,
params
[
i
])
if
err
!=
nil
{
return
methodName
,
packData
,
err
}
paramVals
=
append
(
paramVals
,
paramVal
)
}
}
// 使用Abi对象将方法和参数进行打包
packData
,
err
=
abi
.
Pack
(
methodName
,
paramVals
...
)
return
methodName
,
packData
,
err
}
}
// Unpack 将调用返回结果按照ABI的格式序列化为json
// Unpack 将调用返回结果按照ABI的格式序列化为json
// data 合约方法返回值
// data 合约方法返回值
// abiData 完整的ABI定义
// abiData 完整的ABI定义
func
Unpack
(
data
[]
byte
,
abiData
string
)
(
string
,
error
)
{
func
Unpack
(
data
[]
byte
,
methodName
,
abiData
string
)
(
output
string
,
err
error
)
{
return
""
,
nil
// 解析ABI数据结构,获取本次调用的方法对象
abi
,
err
:=
JSON
(
strings
.
NewReader
(
abiData
))
if
err
!=
nil
{
return
output
,
err
}
var
method
Method
var
ok
bool
if
method
,
ok
=
abi
.
Methods
[
methodName
];
!
ok
{
return
output
,
fmt
.
Errorf
(
"function %v not exists"
,
methodName
)
}
values
,
err
:=
method
.
Outputs
.
UnpackValues
(
data
)
if
err
!=
nil
{
return
output
,
err
}
outputs
:=
[]
*
Param
{}
for
i
,
v
:=
range
values
{
arg
:=
method
.
Outputs
[
i
]
pval
:=
&
Param
{
Name
:
arg
.
Name
,
Type
:
arg
.
Type
.
String
(),
Value
:
v
}
outputs
=
append
(
outputs
,
pval
)
}
jsondata
,
err
:=
json
.
Marshal
(
outputs
)
if
err
!=
nil
{
return
output
,
err
}
return
string
(
jsondata
),
err
}
type
Param
struct
{
Name
string
`json:"name"`
Type
string
`json:"type"`
Value
interface
{}
`json:"value"`
}
func
convertUint
(
val
uint64
,
kind
reflect
.
Kind
)
interface
{}
{
switch
kind
{
case
reflect
.
Uint
:
return
uint
(
val
)
case
reflect
.
Uint8
:
return
uint8
(
val
)
case
reflect
.
Uint16
:
return
uint16
(
val
)
case
reflect
.
Uint32
:
return
uint32
(
val
)
case
reflect
.
Uint64
:
return
uint64
(
val
)
}
return
val
}
func
convertInt
(
val
int64
,
kind
reflect
.
Kind
)
interface
{}
{
switch
kind
{
case
reflect
.
Int
:
return
int
(
val
)
case
reflect
.
Int8
:
return
int8
(
val
)
case
reflect
.
Int16
:
return
int16
(
val
)
case
reflect
.
Int32
:
return
int32
(
val
)
case
reflect
.
Int64
:
return
int64
(
val
)
}
return
val
}
}
// 从字符串格式的输入参数取值(单个),获取Go类型的
// 从字符串格式的输入参数取值(单个),获取Go类型的
func
g
oValue
(
typ
Type
,
val
string
)
(
res
interface
{},
err
error
)
{
func
str2G
oValue
(
typ
Type
,
val
string
)
(
res
interface
{},
err
error
)
{
switch
typ
.
T
{
switch
typ
.
T
{
case
IntTy
:
case
IntTy
:
bitSize
:=
0
if
typ
.
Size
<
256
{
pos
:=
uint
(
typ
.
Kind
-
reflect
.
Int
)
x
,
err
:=
strconv
.
ParseInt
(
val
,
10
,
typ
.
Size
)
if
pos
>
0
{
if
err
!=
nil
{
bitSize
=
(
2
<<
pos
)
*
2
return
res
,
err
}
}
x
,
err
:=
strconv
.
ParseInt
(
val
,
10
,
bitSize
)
return
convertInt
(
x
,
typ
.
Kind
),
nil
if
err
!=
nil
{
}
else
{
return
res
,
err
b
:=
new
(
big
.
Int
)
b
.
SetString
(
val
,
10
)
return
b
,
err
}
}
return
x
,
nil
case
UintTy
:
case
UintTy
:
bitSize
:=
0
if
typ
.
Size
<
256
{
pos
:=
uint
(
typ
.
Kind
-
reflect
.
Uint
)
x
,
err
:=
strconv
.
ParseUint
(
val
,
10
,
typ
.
Size
)
if
pos
>
0
{
if
err
!=
nil
{
bitSize
=
(
2
<<
pos
)
*
2
return
res
,
err
}
}
x
,
err
:=
strconv
.
ParseUint
(
val
,
10
,
bitSize
)
return
convertUint
(
x
,
typ
.
Kind
),
nil
if
err
!=
nil
{
}
else
{
return
res
,
err
b
:=
new
(
big
.
Int
)
b
.
SetString
(
val
,
10
)
return
b
,
err
}
}
return
x
,
nil
case
BoolTy
:
case
BoolTy
:
x
,
err
:=
strconv
.
ParseBool
(
val
)
x
,
err
:=
strconv
.
ParseBool
(
val
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -55,34 +168,34 @@ func goValue(typ Type, val string) (res interface{}, err error) {
...
@@ -55,34 +168,34 @@ func goValue(typ Type, val string) (res interface{}, err error) {
return
x
,
nil
return
x
,
nil
case
StringTy
:
case
StringTy
:
return
val
,
nil
return
val
,
nil
//
case SliceTy:
case
SliceTy
:
// var data []interface{}
subs
,
err
:=
procArrayItem
(
val
)
// subs, err := getSubArrayStr(val)
if
err
!=
nil
{
// if err != nil {
return
res
,
err
// return res, err
}
// }
rval
:=
reflect
.
MakeSlice
(
typ
.
Type
,
len
(
subs
),
len
(
subs
))
//
for idx, sub := range subs {
for
idx
,
sub
:=
range
subs
{
// subVal, er := g
oValue(*typ.Elem, sub)
subVal
,
er
:=
str2G
oValue
(
*
typ
.
Elem
,
sub
)
//
if er != nil {
if
er
!=
nil
{
//
return res, er
return
res
,
er
//
}
}
// data[idx] = subVal
rval
.
Index
(
idx
)
.
Set
(
reflect
.
ValueOf
(
subVal
))
//
}
}
// return data
, nil
return
rval
.
Interface
()
,
nil
//
case ArrayTy:
case
ArrayTy
:
// var data [typ.Size]interface{}
rval
:=
reflect
.
New
(
typ
.
Type
)
.
Elem
()
// subs, err := getSubArrayStr
(val)
subs
,
err
:=
procArrayItem
(
val
)
//
if err != nil {
if
err
!=
nil
{
//
return res, err
return
res
,
err
//
}
}
//
for idx, sub := range subs {
for
idx
,
sub
:=
range
subs
{
// subVal, er := g
oValue(*typ.Elem, sub)
subVal
,
er
:=
str2G
oValue
(
*
typ
.
Elem
,
sub
)
//
if er != nil {
if
er
!=
nil
{
//
return res, er
return
res
,
er
//
}
}
// data[idx] = subVal
rval
.
Index
(
idx
)
.
Set
(
reflect
.
ValueOf
(
subVal
))
//
}
}
// return data
, nil
return
rval
.
Interface
()
,
nil
case
AddressTy
:
case
AddressTy
:
addr
:=
common
.
StringToAddress
(
val
)
addr
:=
common
.
StringToAddress
(
val
)
if
addr
==
nil
{
if
addr
==
nil
{
...
@@ -90,25 +203,23 @@ func goValue(typ Type, val string) (res interface{}, err error) {
...
@@ -90,25 +203,23 @@ func goValue(typ Type, val string) (res interface{}, err error) {
}
}
return
addr
.
ToHash160
(),
nil
return
addr
.
ToHash160
(),
nil
case
FixedBytesTy
:
case
FixedBytesTy
:
//rtype := reflect.ArrayOf(typ.Size, reflect.TypeOf(byte(0)))
//value := reflect.New(rtype).Elem()
//value.SetBytes(x)
// 固定长度多字节,输入时以十六进制方式表示,如 0xabcd00ff
// 固定长度多字节,输入时以十六进制方式表示,如 0xabcd00ff
//x, err := common.HexToBytes(val)
x
,
err
:=
common
.
HexToBytes
(
val
)
//if err != nil {
if
err
!=
nil
{
// return res, err
return
res
,
err
//}
}
//var data [typ.Size]byte
rval
:=
reflect
.
New
(
typ
.
Type
)
.
Elem
()
//copy(data[:], x)
for
i
,
b
:=
range
x
{
//return data, nil
rval
.
Index
(
i
)
.
Set
(
reflect
.
ValueOf
(
b
))
}
return
rval
.
Interface
(),
nil
case
BytesTy
:
case
BytesTy
:
// 单个字节,输入时以十六进制方式表示,如 0xab
// 单个字节,输入时以十六进制方式表示,如 0xab
x
,
err
:=
common
.
HexToBytes
(
val
)
x
,
err
:=
common
.
HexToBytes
(
val
)
if
err
!=
nil
{
if
err
!=
nil
{
return
res
,
err
return
res
,
err
}
}
return
x
[
0
]
,
nil
return
x
,
nil
case
HashTy
:
case
HashTy
:
// 哈希类型,也是以十六进制为输入,如:0xabcdef
// 哈希类型,也是以十六进制为输入,如:0xabcdef
x
,
err
:=
common
.
HexToBytes
(
val
)
x
,
err
:=
common
.
HexToBytes
(
val
)
...
@@ -134,13 +245,13 @@ func procArrayItem(val string) (res []string, err error) {
...
@@ -134,13 +245,13 @@ func procArrayItem(val string) (res []string, err error) {
switch
b
{
switch
b
{
case
' '
:
case
' '
:
// 只有字符串元素中间的空格才是有效的
// 只有字符串元素中间的空格才是有效的
if
ss
.
Len
()
>
0
&&
stackPeek
(
ss
)
==
'"'
{
if
ss
.
Len
()
>
0
&&
peekRune
(
ss
)
==
'"'
{
data
=
append
(
data
,
b
)
data
=
append
(
data
,
b
)
}
}
case
','
:
case
','
:
// 逗号有可能是多级数组里面的分隔符,我们只处理最外层数组的分隔,
// 逗号有可能是多级数组里面的分隔符,我们只处理最外层数组的分隔,
// 因此,需要判断当前栈中是否只有一个'[',否则就当做普通内容对待
// 因此,需要判断当前栈中是否只有一个'[',否则就当做普通内容对待
if
ss
.
Len
()
==
1
&&
stackPeek
(
ss
)
==
'['
{
if
ss
.
Len
()
==
1
&&
peekRune
(
ss
)
==
'['
{
// 当前元素结束
// 当前元素结束
res
=
append
(
res
,
string
(
data
))
res
=
append
(
res
,
string
(
data
))
data
=
[]
rune
{}
data
=
[]
rune
{}
...
@@ -166,7 +277,7 @@ func procArrayItem(val string) (res []string, err error) {
...
@@ -166,7 +277,7 @@ func procArrayItem(val string) (res []string, err error) {
ss
.
Push
(
b
)
ss
.
Push
(
b
)
case
']'
:
case
']'
:
// 只有当栈中只有一个']'时,才会被当做数组结束,否则就当做普通内容对待
// 只有当栈中只有一个']'时,才会被当做数组结束,否则就当做普通内容对待
if
ss
.
Len
()
==
1
&&
stackPeek
(
ss
)
==
'['
{
if
ss
.
Len
()
==
1
&&
peekRune
(
ss
)
==
'['
{
// 整个数组结束
// 整个数组结束
res
=
append
(
res
,
string
(
data
))
res
=
append
(
res
,
string
(
data
))
}
else
{
}
else
{
...
@@ -185,6 +296,27 @@ func procArrayItem(val string) (res []string, err error) {
...
@@ -185,6 +296,27 @@ func procArrayItem(val string) (res []string, err error) {
return
res
,
err
return
res
,
err
}
}
func
stackPeek
(
ss
*
stack
.
Stack
)
rune
{
func
peekRune
(
ss
*
stack
.
Stack
)
rune
{
return
ss
.
Peek
()
.
(
rune
)
return
ss
.
Peek
()
.
(
rune
)
}
}
\ No newline at end of file
// 解析方法调用字符串,返回方法名以及方法参数
// 例如:foo(param1,param2) -> [foo,param1,param2]
func
procFuncCall
(
param
string
)
(
funcName
string
,
res
[]
string
,
err
error
)
{
lidx
:=
strings
.
Index
(
param
,
"("
)
ridx
:=
strings
.
LastIndex
(
param
,
")"
)
if
lidx
==
-
1
||
ridx
==
-
1
{
return
funcName
,
res
,
fmt
.
Errorf
(
"invalid function signature:%v"
,
param
)
}
funcName
=
strings
.
TrimSpace
(
param
[
:
lidx
])
params
:=
strings
.
TrimSpace
(
param
[
lidx
+
1
:
ridx
])
// 将方法参数转换为数组形式,重用数组内容解析逻辑,获得各个具体的参数
if
len
(
params
)
>
0
{
res
,
err
=
procArrayItem
(
fmt
.
Sprintf
(
"[%v]"
,
params
))
}
return
funcName
,
res
,
err
}
plugin/dapp/evm/executor/abi/api_test.go
View file @
d33e674d
This diff is collapsed.
Click to expand it.
plugin/dapp/evm/executor/abi/argument.go
View file @
d33e674d
...
@@ -23,7 +23,7 @@ import (
...
@@ -23,7 +23,7 @@ import (
"strings"
"strings"
)
)
// Argument holds the
n
ame of the argument and the corresponding type.
// Argument holds the
N
ame of the argument and the corresponding type.
// Types are used when packing and testing arguments.
// Types are used when packing and testing arguments.
type
Argument
struct
{
type
Argument
struct
{
Name
string
Name
string
...
@@ -86,7 +86,7 @@ func (arguments Arguments) isTuple() bool {
...
@@ -86,7 +86,7 @@ func (arguments Arguments) isTuple() bool {
// Unpack performs the operation hexdata -> Go format
// Unpack performs the operation hexdata -> Go format
func
(
arguments
Arguments
)
Unpack
(
v
interface
{},
data
[]
byte
)
error
{
func
(
arguments
Arguments
)
Unpack
(
v
interface
{},
data
[]
byte
)
error
{
// make sure the passed
v
alue is arguments pointer
// make sure the passed
V
alue is arguments pointer
if
reflect
.
Ptr
!=
reflect
.
ValueOf
(
v
)
.
Kind
()
{
if
reflect
.
Ptr
!=
reflect
.
ValueOf
(
v
)
.
Kind
()
{
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
}
}
...
@@ -152,10 +152,10 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
...
@@ -152,10 +152,10 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
return
nil
return
nil
}
}
// unpackAtomic unpacks ( hexdata -> go ) a single
v
alue
// unpackAtomic unpacks ( hexdata -> go ) a single
V
alue
func
(
arguments
Arguments
)
unpackAtomic
(
v
interface
{},
marshalledValues
[]
interface
{})
error
{
func
(
arguments
Arguments
)
unpackAtomic
(
v
interface
{},
marshalledValues
[]
interface
{})
error
{
if
len
(
marshalledValues
)
!=
1
{
if
len
(
marshalledValues
)
!=
1
{
return
fmt
.
Errorf
(
"abi: wrong length, expected single
v
alue, got %d"
,
len
(
marshalledValues
))
return
fmt
.
Errorf
(
"abi: wrong length, expected single
V
alue, got %d"
,
len
(
marshalledValues
))
}
}
elem
:=
reflect
.
ValueOf
(
v
)
.
Elem
()
elem
:=
reflect
.
ValueOf
(
v
)
.
Elem
()
...
@@ -267,7 +267,7 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
...
@@ -267,7 +267,7 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
// will be appended at the end of the input.
// will be appended at the end of the input.
variableInput
=
append
(
variableInput
,
packed
...
)
variableInput
=
append
(
variableInput
,
packed
...
)
}
else
{
}
else
{
// append the packed
v
alue to the input
// append the packed
V
alue to the input
ret
=
append
(
ret
,
packed
...
)
ret
=
append
(
ret
,
packed
...
)
}
}
}
}
...
...
plugin/dapp/evm/executor/abi/error.go
View file @
d33e674d
...
@@ -23,7 +23,7 @@ import (
...
@@ -23,7 +23,7 @@ import (
)
)
var
(
var
(
errBadBool
=
errors
.
New
(
"abi: improperly encoded boolean
v
alue"
)
errBadBool
=
errors
.
New
(
"abi: improperly encoded boolean
V
alue"
)
)
)
// formatSliceString formats the reflection kind with the given slice size
// formatSliceString formats the reflection kind with the given slice size
...
@@ -60,7 +60,7 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
...
@@ -60,7 +60,7 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
return
nil
return
nil
}
}
// typeCheck checks that the given reflection
v
alue can be assigned to the reflection
// typeCheck checks that the given reflection
V
alue can be assigned to the reflection
// type in t.
// type in t.
func
typeCheck
(
t
Type
,
value
reflect
.
Value
)
error
{
func
typeCheck
(
t
Type
,
value
reflect
.
Value
)
error
{
if
t
.
T
==
SliceTy
||
t
.
T
==
ArrayTy
{
if
t
.
T
==
SliceTy
||
t
.
T
==
ArrayTy
{
...
...
plugin/dapp/evm/executor/abi/event_test.go
View file @
d33e674d
...
@@ -35,39 +35,39 @@ var jsonEventTransfer = []byte(`{
...
@@ -35,39 +35,39 @@ var jsonEventTransfer = []byte(`{
"anonymous": false,
"anonymous": false,
"inputs": [
"inputs": [
{
{
"indexed": true, "
n
ame": "from", "type": "address"
"indexed": true, "
N
ame": "from", "type": "address"
}, {
}, {
"indexed": true, "
n
ame": "to", "type": "address"
"indexed": true, "
N
ame": "to", "type": "address"
}, {
}, {
"indexed": false, "
name": "v
alue", "type": "uint256"
"indexed": false, "
Name": "V
alue", "type": "uint256"
}],
}],
"
n
ame": "Transfer",
"
N
ame": "Transfer",
"type": "event"
"type": "event"
}`
)
}`
)
var
jsonEventPledge
=
[]
byte
(
`{
var
jsonEventPledge
=
[]
byte
(
`{
"anonymous": false,
"anonymous": false,
"inputs": [{
"inputs": [{
"indexed": false, "
n
ame": "who", "type": "address"
"indexed": false, "
N
ame": "who", "type": "address"
}, {
}, {
"indexed": false, "
n
ame": "wad", "type": "uint128"
"indexed": false, "
N
ame": "wad", "type": "uint128"
}, {
}, {
"indexed": false, "
n
ame": "currency", "type": "bytes3"
"indexed": false, "
N
ame": "currency", "type": "bytes3"
}],
}],
"
n
ame": "Pledge",
"
N
ame": "Pledge",
"type": "event"
"type": "event"
}`
)
}`
)
var
jsonEventMixedCase
=
[]
byte
(
`{
var
jsonEventMixedCase
=
[]
byte
(
`{
"anonymous": false,
"anonymous": false,
"inputs": [{
"inputs": [{
"indexed": false, "
name": "v
alue", "type": "uint256"
"indexed": false, "
Name": "V
alue", "type": "uint256"
}, {
}, {
"indexed": false, "
n
ame": "_value", "type": "uint256"
"indexed": false, "
N
ame": "_value", "type": "uint256"
}, {
}, {
"indexed": false, "
n
ame": "Value", "type": "uint256"
"indexed": false, "
N
ame": "Value", "type": "uint256"
}],
}],
"
n
ame": "MixedCase",
"
N
ame": "MixedCase",
"type": "event"
"type": "event"
}`
)
}`
)
...
@@ -87,8 +87,8 @@ func TestEventId(t *testing.T) {
...
@@ -87,8 +87,8 @@ func TestEventId(t *testing.T) {
}{
}{
{
{
definition
:
`[
definition
:
`[
{ "type" : "event", "
name" : "balance", "inputs": [{ "n
ame" : "in", "type": "uint256" }] },
{ "type" : "event", "
Name" : "balance", "inputs": [{ "N
ame" : "in", "type": "uint256" }] },
{ "type" : "event", "
name" : "check", "inputs": [{ "name" : "t", "type": "address" }, { "n
ame": "b", "type": "uint256" }] }
{ "type" : "event", "
Name" : "check", "inputs": [{ "Name" : "t", "type": "address" }, { "N
ame": "b", "type": "uint256" }] }
]`
,
]`
,
expectations
:
map
[
string
]
common
.
Hash
{
expectations
:
map
[
string
]
common
.
Hash
{
"balance"
:
crypto
.
Keccak256Hash
([]
byte
(
"balance(uint256)"
)),
"balance"
:
crypto
.
Keccak256Hash
([]
byte
(
"balance(uint256)"
)),
...
@@ -113,7 +113,7 @@ func TestEventId(t *testing.T) {
...
@@ -113,7 +113,7 @@ func TestEventId(t *testing.T) {
// TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
// TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
func
TestEventMultiValueWithArrayUnpack
(
t
*
testing
.
T
)
{
func
TestEventMultiValueWithArrayUnpack
(
t
*
testing
.
T
)
{
definition
:=
`[{"
name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "n
ame":"value2", "type":"uint8"}]}]`
definition
:=
`[{"
Name": "test", "type": "event", "inputs": [{"indexed": false, "Name":"value1", "type":"uint8[2]"},{"indexed": false, "N
ame":"value2", "type":"uint8"}]}]`
type
testStruct
struct
{
type
testStruct
struct
{
Value1
[
2
]
uint8
Value1
[
2
]
uint8
Value2
uint8
Value2
uint8
...
@@ -138,20 +138,20 @@ func TestEventTupleUnpack(t *testing.T) {
...
@@ -138,20 +138,20 @@ func TestEventTupleUnpack(t *testing.T) {
}
}
type
EventTransferWithTag
struct
{
type
EventTransferWithTag
struct
{
// this is valid because `
v
alue` is not exportable,
// this is valid because `
V
alue` is not exportable,
// so
v
alue is only unmarshalled into `Value1`.
// so
V
alue is only unmarshalled into `Value1`.
value
*
big
.
Int
value
*
big
.
Int
Value1
*
big
.
Int
`abi:"
v
alue"`
Value1
*
big
.
Int
`abi:"
V
alue"`
}
}
type
BadEventTransferWithSameFieldAndTag
struct
{
type
BadEventTransferWithSameFieldAndTag
struct
{
Value
*
big
.
Int
Value
*
big
.
Int
Value1
*
big
.
Int
`abi:"
v
alue"`
Value1
*
big
.
Int
`abi:"
V
alue"`
}
}
type
BadEventTransferWithDuplicatedTag
struct
{
type
BadEventTransferWithDuplicatedTag
struct
{
Value1
*
big
.
Int
`abi:"
v
alue"`
Value1
*
big
.
Int
`abi:"
V
alue"`
Value2
*
big
.
Int
`abi:"
v
alue"`
Value2
*
big
.
Int
`abi:"
V
alue"`
}
}
type
BadEventTransferWithEmptyTag
struct
{
type
BadEventTransferWithEmptyTag
struct
{
...
@@ -171,7 +171,7 @@ func TestEventTupleUnpack(t *testing.T) {
...
@@ -171,7 +171,7 @@ func TestEventTupleUnpack(t *testing.T) {
}
}
type
EventMixedCase
struct
{
type
EventMixedCase
struct
{
Value1
*
big
.
Int
`abi:"
v
alue"`
Value1
*
big
.
Int
`abi:"
V
alue"`
Value2
*
big
.
Int
`abi:"_value"`
Value2
*
big
.
Int
`abi:"_value"`
Value3
*
big
.
Int
`abi:"Value"`
Value3
*
big
.
Int
`abi:"Value"`
}
}
...
@@ -221,7 +221,7 @@ func TestEventTupleUnpack(t *testing.T) {
...
@@ -221,7 +221,7 @@ func TestEventTupleUnpack(t *testing.T) {
&
BadEventTransferWithSameFieldAndTag
{},
&
BadEventTransferWithSameFieldAndTag
{},
&
BadEventTransferWithSameFieldAndTag
{},
&
BadEventTransferWithSameFieldAndTag
{},
jsonEventTransfer
,
jsonEventTransfer
,
"abi: multiple variables maps to the same abi field '
v
alue'"
,
"abi: multiple variables maps to the same abi field '
V
alue'"
,
"Can not unpack ERC20 Transfer event with a field and a tag mapping to the same abi variable"
,
"Can not unpack ERC20 Transfer event with a field and a tag mapping to the same abi variable"
,
},
{
},
{
transferData1
,
transferData1
,
...
@@ -357,7 +357,7 @@ func (tc testCase) encoded(intType, arrayType Type) []byte {
...
@@ -357,7 +357,7 @@ func (tc testCase) encoded(intType, arrayType Type) []byte {
// TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
// TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
func
TestEventUnpackIndexed
(
t
*
testing
.
T
)
{
func
TestEventUnpackIndexed
(
t
*
testing
.
T
)
{
definition
:=
`[{"
name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "n
ame":"value2", "type":"uint8"}]}]`
definition
:=
`[{"
Name": "test", "type": "event", "inputs": [{"indexed": true, "Name":"value1", "type":"uint8"},{"indexed": false, "N
ame":"value2", "type":"uint8"}]}]`
type
testStruct
struct
{
type
testStruct
struct
{
Value1
uint8
Value1
uint8
Value2
uint8
Value2
uint8
...
@@ -374,7 +374,7 @@ func TestEventUnpackIndexed(t *testing.T) {
...
@@ -374,7 +374,7 @@ func TestEventUnpackIndexed(t *testing.T) {
// TestEventIndexedWithArrayUnpack verifies that decoder will not overlow when static array is indexed input.
// TestEventIndexedWithArrayUnpack verifies that decoder will not overlow when static array is indexed input.
func
TestEventIndexedWithArrayUnpack
(
t
*
testing
.
T
)
{
func
TestEventIndexedWithArrayUnpack
(
t
*
testing
.
T
)
{
definition
:=
`[{"
name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "n
ame":"value2", "type":"string"}]}]`
definition
:=
`[{"
Name": "test", "type": "event", "inputs": [{"indexed": true, "Name":"value1", "type":"uint8[2]"},{"indexed": false, "N
ame":"value2", "type":"string"}]}]`
type
testStruct
struct
{
type
testStruct
struct
{
Value1
[
2
]
uint8
Value1
[
2
]
uint8
Value2
string
Value2
string
...
...
plugin/dapp/evm/executor/abi/pack.go
View file @
d33e674d
...
@@ -30,7 +30,7 @@ func packBytesSlice(bytes []byte, l int) []byte {
...
@@ -30,7 +30,7 @@ func packBytesSlice(bytes []byte, l int) []byte {
return
append
(
len
,
common
.
RightPadBytes
(
bytes
,
(
l
+
31
)
/
32
*
32
)
...
)
return
append
(
len
,
common
.
RightPadBytes
(
bytes
,
(
l
+
31
)
/
32
*
32
)
...
)
}
}
// packElement packs the given reflect
v
alue according to the abi specification in
// packElement packs the given reflect
V
alue according to the abi specification in
// t.
// t.
func
packElement
(
t
Type
,
reflectValue
reflect
.
Value
)
[]
byte
{
func
packElement
(
t
Type
,
reflectValue
reflect
.
Value
)
[]
byte
{
switch
t
.
T
{
switch
t
.
T
{
...
@@ -64,7 +64,7 @@ func packElement(t Type, reflectValue reflect.Value) []byte {
...
@@ -64,7 +64,7 @@ func packElement(t Type, reflectValue reflect.Value) []byte {
}
}
}
}
// packNum packs the given number (using the reflect
v
alue) and will cast it to appropriate number representation
// packNum packs the given number (using the reflect
V
alue) and will cast it to appropriate number representation
func
packNum
(
value
reflect
.
Value
)
[]
byte
{
func
packNum
(
value
reflect
.
Value
)
[]
byte
{
switch
kind
:=
value
.
Kind
();
kind
{
switch
kind
:=
value
.
Kind
();
kind
{
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
:
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
:
...
...
plugin/dapp/evm/executor/abi/reflect.go
View file @
d33e674d
...
@@ -22,7 +22,7 @@ import (
...
@@ -22,7 +22,7 @@ import (
"strings"
"strings"
)
)
// indirect recursively dereferences the
value until it either gets the v
alue
// indirect recursively dereferences the
Value until it either gets the V
alue
// or finds a big.Int
// or finds a big.Int
func
indirect
(
v
reflect
.
Value
)
reflect
.
Value
{
func
indirect
(
v
reflect
.
Value
)
reflect
.
Value
{
if
v
.
Kind
()
==
reflect
.
Ptr
&&
v
.
Elem
()
.
Type
()
!=
derefbigT
{
if
v
.
Kind
()
==
reflect
.
Ptr
&&
v
.
Elem
()
.
Type
()
!=
derefbigT
{
...
@@ -59,8 +59,8 @@ func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type)
...
@@ -59,8 +59,8 @@ func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type)
return
reflect
.
Ptr
,
bigT
return
reflect
.
Ptr
,
bigT
}
}
// mustArrayToBytesSlice creates a new byte slice with the exact same size as
v
alue
// mustArrayToBytesSlice creates a new byte slice with the exact same size as
V
alue
// and copies the bytes in
v
alue to the new slice.
// and copies the bytes in
V
alue to the new slice.
func
mustArrayToByteSlice
(
value
reflect
.
Value
)
reflect
.
Value
{
func
mustArrayToByteSlice
(
value
reflect
.
Value
)
reflect
.
Value
{
slice
:=
reflect
.
MakeSlice
(
reflect
.
TypeOf
([]
byte
{}),
value
.
Len
(),
value
.
Len
())
slice
:=
reflect
.
MakeSlice
(
reflect
.
TypeOf
([]
byte
{}),
value
.
Len
(),
value
.
Len
())
reflect
.
Copy
(
slice
,
value
)
reflect
.
Copy
(
slice
,
value
)
...
@@ -114,7 +114,7 @@ func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind,
...
@@ -114,7 +114,7 @@ func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind,
// mapAbiToStringField maps abi to struct fields.
// mapAbiToStringField maps abi to struct fields.
// first round: for each Exportable field that contains a `abi:""` tag
// first round: for each Exportable field that contains a `abi:""` tag
// and this field
n
ame exists in the arguments, pair them together.
// and this field
N
ame exists in the arguments, pair them together.
// second round: for each argument field that has not been already linked,
// second round: for each argument field that has not been already linked,
// find what variable is expected to be mapped into, if it exists and has not been
// find what variable is expected to be mapped into, if it exists and has not been
// used, pair them.
// used, pair them.
...
@@ -178,9 +178,9 @@ func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]strin
...
@@ -178,9 +178,9 @@ func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]strin
}
}
// this abi has already been paired, skip it... unless there exists another, yet unassigned
// this abi has already been paired, skip it... unless there exists another, yet unassigned
// struct field with the same field
n
ame. If so, raise an error:
// struct field with the same field
N
ame. If so, raise an error:
// abi: [ { "
name": "v
alue" } ]
// abi: [ { "
Name": "V
alue" } ]
// struct { Value *big.Int , Value1 *big.Int `abi:"
v
alue"`}
// struct { Value *big.Int , Value1 *big.Int `abi:"
V
alue"`}
if
abi2struct
[
abiFieldName
]
!=
""
{
if
abi2struct
[
abiFieldName
]
!=
""
{
if
abi2struct
[
abiFieldName
]
!=
structFieldName
&&
if
abi2struct
[
abiFieldName
]
!=
structFieldName
&&
struct2abi
[
structFieldName
]
==
""
&&
struct2abi
[
structFieldName
]
==
""
&&
...
@@ -201,7 +201,7 @@ func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]strin
...
@@ -201,7 +201,7 @@ func mapAbiToStructFields(args Arguments, value reflect.Value) (map[string]strin
struct2abi
[
structFieldName
]
=
abiFieldName
struct2abi
[
structFieldName
]
=
abiFieldName
}
else
{
}
else
{
// not paired, but annotate as used, to detect cases like
// not paired, but annotate as used, to detect cases like
// abi : [ { "
name": "value" }, { "n
ame": "_value" } ]
// abi : [ { "
Name": "Value" }, { "N
ame": "_value" } ]
// struct { Value *big.Int }
// struct { Value *big.Int }
struct2abi
[
structFieldName
]
=
abiFieldName
struct2abi
[
structFieldName
]
=
abiFieldName
}
}
...
...
plugin/dapp/evm/executor/abi/unpack.go
View file @
d33e674d
...
@@ -135,7 +135,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
...
@@ -135,7 +135,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
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
)
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
)
}
}
// this
v
alue will become our slice or our array, depending on the type
// this
V
alue will become our slice or our array, depending on the type
var
refSlice
reflect
.
Value
var
refSlice
reflect
.
Value
if
t
.
T
==
SliceTy
{
if
t
.
T
==
SliceTy
{
...
@@ -170,7 +170,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
...
@@ -170,7 +170,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
return
refSlice
.
Interface
(),
nil
return
refSlice
.
Interface
(),
nil
}
}
// toGoType parses the output bytes and recursively assigns the
v
alue of these bytes
// toGoType parses the output bytes and recursively assigns the
V
alue of these bytes
// into a go type with accordance with the ABI spec.
// into a go type with accordance with the ABI spec.
func
toGoType
(
index
int
,
t
Type
,
output
[]
byte
)
(
interface
{},
error
)
{
func
toGoType
(
index
int
,
t
Type
,
output
[]
byte
)
(
interface
{},
error
)
{
if
index
+
32
>
len
(
output
)
{
if
index
+
32
>
len
(
output
)
{
...
...
plugin/dapp/evm/executor/abi/unpack_test.go
View file @
d33e674d
...
@@ -65,13 +65,13 @@ var unpackTests = []unpackTest{
...
@@ -65,13 +65,13 @@ var unpackTests = []unpackTest{
def
:
`[{ "type": "bool" }]`
,
def
:
`[{ "type": "bool" }]`
,
enc
:
"0000000000000000000000000000000000000000000000000001000000000001"
,
enc
:
"0000000000000000000000000000000000000000000000000001000000000001"
,
want
:
false
,
want
:
false
,
err
:
"abi: improperly encoded boolean
v
alue"
,
err
:
"abi: improperly encoded boolean
V
alue"
,
},
},
{
{
def
:
`[{ "type": "bool" }]`
,
def
:
`[{ "type": "bool" }]`
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000003"
,
enc
:
"0000000000000000000000000000000000000000000000000000000000000003"
,
want
:
false
,
want
:
false
,
err
:
"abi: improperly encoded boolean
v
alue"
,
err
:
"abi: improperly encoded boolean
V
alue"
,
},
},
{
{
def
:
`[{"type": "uint32"}]`
,
def
:
`[{"type": "uint32"}]`
,
...
@@ -288,7 +288,7 @@ var unpackTests = []unpackTest{
...
@@ -288,7 +288,7 @@ var unpackTests = []unpackTest{
},
},
// struct outputs
// struct outputs
{
{
def
:
`[{"
name":"int1","type":"int256"},{"n
ame":"int2","type":"int256"}]`
,
def
:
`[{"
Name":"int1","type":"int256"},{"N
ame":"int2","type":"int256"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
struct
{
want
:
struct
{
Int1
*
big
.
Int
Int1
*
big
.
Int
...
@@ -296,7 +296,7 @@ var unpackTests = []unpackTest{
...
@@ -296,7 +296,7 @@ var unpackTests = []unpackTest{
}{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
)},
}{
big
.
NewInt
(
1
),
big
.
NewInt
(
2
)},
},
},
{
{
def
:
`[{"
name":"int","type":"int256"},{"n
ame":"Int","type":"int256"}]`
,
def
:
`[{"
Name":"int","type":"int256"},{"N
ame":"Int","type":"int256"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
struct
{
want
:
struct
{
Int1
*
big
.
Int
Int1
*
big
.
Int
...
@@ -305,7 +305,7 @@ var unpackTests = []unpackTest{
...
@@ -305,7 +305,7 @@ var unpackTests = []unpackTest{
err
:
"abi: multiple outputs mapping to the same struct field 'Int'"
,
err
:
"abi: multiple outputs mapping to the same struct field 'Int'"
,
},
},
{
{
def
:
`[{"
name":"int","type":"int256"},{"n
ame":"_int","type":"int256"}]`
,
def
:
`[{"
Name":"int","type":"int256"},{"N
ame":"_int","type":"int256"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
struct
{
want
:
struct
{
Int1
*
big
.
Int
Int1
*
big
.
Int
...
@@ -314,7 +314,7 @@ var unpackTests = []unpackTest{
...
@@ -314,7 +314,7 @@ var unpackTests = []unpackTest{
err
:
"abi: multiple outputs mapping to the same struct field 'Int'"
,
err
:
"abi: multiple outputs mapping to the same struct field 'Int'"
,
},
},
{
{
def
:
`[{"
name":"Int","type":"int256"},{"n
ame":"_int","type":"int256"}]`
,
def
:
`[{"
Name":"Int","type":"int256"},{"N
ame":"_int","type":"int256"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
struct
{
want
:
struct
{
Int1
*
big
.
Int
Int1
*
big
.
Int
...
@@ -323,7 +323,7 @@ var unpackTests = []unpackTest{
...
@@ -323,7 +323,7 @@ var unpackTests = []unpackTest{
err
:
"abi: multiple outputs mapping to the same struct field 'Int'"
,
err
:
"abi: multiple outputs mapping to the same struct field 'Int'"
,
},
},
{
{
def
:
`[{"
name":"Int","type":"int256"},{"n
ame":"_","type":"int256"}]`
,
def
:
`[{"
Name":"Int","type":"int256"},{"N
ame":"_","type":"int256"}]`
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
enc
:
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
,
want
:
struct
{
want
:
struct
{
Int1
*
big
.
Int
Int1
*
big
.
Int
...
@@ -336,7 +336,7 @@ var unpackTests = []unpackTest{
...
@@ -336,7 +336,7 @@ var unpackTests = []unpackTest{
func
TestUnpack
(
t
*
testing
.
T
)
{
func
TestUnpack
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
unpackTests
{
for
i
,
test
:=
range
unpackTests
{
t
.
Run
(
strconv
.
Itoa
(
i
),
func
(
t
*
testing
.
T
)
{
t
.
Run
(
strconv
.
Itoa
(
i
),
func
(
t
*
testing
.
T
)
{
def
:=
fmt
.
Sprintf
(
`[{ "
n
ame" : "method", "outputs": %s}]`
,
test
.
def
)
def
:=
fmt
.
Sprintf
(
`[{ "
N
ame" : "method", "outputs": %s}]`
,
test
.
def
)
abi
,
err
:=
JSON
(
strings
.
NewReader
(
def
))
abi
,
err
:=
JSON
(
strings
.
NewReader
(
def
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"invalid ABI definition %s: %v"
,
def
,
err
)
t
.
Fatalf
(
"invalid ABI definition %s: %v"
,
def
,
err
)
...
@@ -366,7 +366,7 @@ type methodMultiOutput struct {
...
@@ -366,7 +366,7 @@ type methodMultiOutput struct {
func
methodMultiReturn
(
require
*
require
.
Assertions
)
(
ABI
,
[]
byte
,
methodMultiOutput
)
{
func
methodMultiReturn
(
require
*
require
.
Assertions
)
(
ABI
,
[]
byte
,
methodMultiOutput
)
{
const
definition
=
`[
const
definition
=
`[
{ "
name" : "multi", "constant" : false, "outputs": [ { "name": "Int", "type": "uint256" }, { "n
ame": "String", "type": "string" } ] }]`
{ "
Name" : "multi", "constant" : false, "outputs": [ { "Name": "Int", "type": "uint256" }, { "N
ame": "String", "type": "string" } ] }]`
var
expected
=
methodMultiOutput
{
big
.
NewInt
(
1
),
"hello"
}
var
expected
=
methodMultiOutput
{
big
.
NewInt
(
1
),
"hello"
}
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
...
@@ -440,7 +440,7 @@ func TestMethodMultiReturn(t *testing.T) {
...
@@ -440,7 +440,7 @@ func TestMethodMultiReturn(t *testing.T) {
}
}
func
TestMultiReturnWithArray
(
t
*
testing
.
T
)
{
func
TestMultiReturnWithArray
(
t
*
testing
.
T
)
{
const
definition
=
`[{"
n
ame" : "multi", "outputs": [{"type": "uint64[3]"}, {"type": "uint64"}]}]`
const
definition
=
`[{"
N
ame" : "multi", "outputs": [{"type": "uint64[3]"}, {"type": "uint64"}]}]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -467,7 +467,7 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
...
@@ -467,7 +467,7 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
// values of nested static arrays count towards the size as well, and any element following
// values of nested static arrays count towards the size as well, and any element following
// after such nested array argument should be read with the correct offset,
// after such nested array argument should be read with the correct offset,
// so that it does not read content from the previous array argument.
// so that it does not read content from the previous array argument.
const
definition
=
`[{"
n
ame" : "multi", "outputs": [{"type": "uint64[3][2][4]"}, {"type": "uint64"}]}]`
const
definition
=
`[{"
N
ame" : "multi", "outputs": [{"type": "uint64[3][2][4]"}, {"type": "uint64"}]}]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -504,15 +504,15 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
...
@@ -504,15 +504,15 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
func
TestUnmarshal
(
t
*
testing
.
T
)
{
func
TestUnmarshal
(
t
*
testing
.
T
)
{
const
definition
=
`[
const
definition
=
`[
{ "
n
ame" : "int", "constant" : false, "outputs": [ { "type": "uint256" } ] },
{ "
N
ame" : "int", "constant" : false, "outputs": [ { "type": "uint256" } ] },
{ "
n
ame" : "bool", "constant" : false, "outputs": [ { "type": "bool" } ] },
{ "
N
ame" : "bool", "constant" : false, "outputs": [ { "type": "bool" } ] },
{ "
n
ame" : "bytes", "constant" : false, "outputs": [ { "type": "bytes" } ] },
{ "
N
ame" : "bytes", "constant" : false, "outputs": [ { "type": "bytes" } ] },
{ "
n
ame" : "fixed", "constant" : false, "outputs": [ { "type": "bytes32" } ] },
{ "
N
ame" : "fixed", "constant" : false, "outputs": [ { "type": "bytes32" } ] },
{ "
n
ame" : "multi", "constant" : false, "outputs": [ { "type": "bytes" }, { "type": "bytes" } ] },
{ "
N
ame" : "multi", "constant" : false, "outputs": [ { "type": "bytes" }, { "type": "bytes" } ] },
{ "
n
ame" : "intArraySingle", "constant" : false, "outputs": [ { "type": "uint256[3]" } ] },
{ "
N
ame" : "intArraySingle", "constant" : false, "outputs": [ { "type": "uint256[3]" } ] },
{ "
n
ame" : "addressSliceSingle", "constant" : false, "outputs": [ { "type": "address[]" } ] },
{ "
N
ame" : "addressSliceSingle", "constant" : false, "outputs": [ { "type": "address[]" } ] },
{ "
name" : "addressSliceDouble", "constant" : false, "outputs": [ { "name": "a", "type": "address[]" }, { "n
ame": "b", "type": "address[]" } ] },
{ "
Name" : "addressSliceDouble", "constant" : false, "outputs": [ { "Name": "a", "type": "address[]" }, { "N
ame": "b", "type": "address[]" } ] },
{ "
name" : "mixedBytes", "constant" : true, "outputs": [ { "name": "a", "type": "bytes" }, { "n
ame": "b", "type": "bytes32" } ] }]`
{ "
Name" : "mixedBytes", "constant" : true, "outputs": [ { "Name": "a", "type": "bytes" }, { "N
ame": "b", "type": "bytes32" } ] }]`
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
abi
,
err
:=
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -535,11 +535,11 @@ func TestUnmarshal(t *testing.T) {
...
@@ -535,11 +535,11 @@ func TestUnmarshal(t *testing.T) {
t
.
Error
(
err
)
t
.
Error
(
err
)
}
else
{
}
else
{
if
!
bytes
.
Equal
(
p0
,
p0Exp
)
{
if
!
bytes
.
Equal
(
p0
,
p0Exp
)
{
t
.
Errorf
(
"unexpected
v
alue unpacked: want %x, got %x"
,
p0Exp
,
p0
)
t
.
Errorf
(
"unexpected
V
alue unpacked: want %x, got %x"
,
p0Exp
,
p0
)
}
}
if
!
bytes
.
Equal
(
p1
[
:
],
p1Exp
)
{
if
!
bytes
.
Equal
(
p1
[
:
],
p1Exp
)
{
t
.
Errorf
(
"unexpected
v
alue unpacked: want %x, got %x"
,
p1Exp
,
p1
)
t
.
Errorf
(
"unexpected
V
alue unpacked: want %x, got %x"
,
p1Exp
,
p1
)
}
}
}
}
...
@@ -805,7 +805,7 @@ func TestOOMMaliciousInput(t *testing.T) {
...
@@ -805,7 +805,7 @@ func TestOOMMaliciousInput(t *testing.T) {
},
},
}
}
for
i
,
test
:=
range
oomTests
{
for
i
,
test
:=
range
oomTests
{
def
:=
fmt
.
Sprintf
(
`[{ "
n
ame" : "method", "outputs": %s}]`
,
test
.
def
)
def
:=
fmt
.
Sprintf
(
`[{ "
N
ame" : "method", "outputs": %s}]`
,
test
.
def
)
abi
,
err
:=
JSON
(
strings
.
NewReader
(
def
))
abi
,
err
:=
JSON
(
strings
.
NewReader
(
def
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"invalid ABI definition %s: %v"
,
def
,
err
)
t
.
Fatalf
(
"invalid ABI definition %s: %v"
,
def
,
err
)
...
...
plugin/dapp/evm/executor/exec.go
View file @
d33e674d
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"strings"
"strings"
"bytes"
log
"github.com/33cn/chain33/common/log/log15"
log
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
"github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
...
@@ -41,6 +42,9 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -41,6 +42,9 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
contractAddr
common
.
Address
contractAddr
common
.
Address
snapshot
int
snapshot
int
execName
string
execName
string
abiCall
bool
abiData
string
methodName
string
)
)
// 为了方便计费,即使合约为新生成,也将地址的初始化放到外面操作
// 为了方便计费,即使合约为新生成,也将地址的初始化放到外面操作
...
@@ -62,9 +66,24 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -62,9 +66,24 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
if
isCreate
{
if
isCreate
{
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
contractAddr
,
msg
.
Data
(),
context
.
GasLimit
,
execName
,
msg
.
Alias
())
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
contractAddr
,
msg
.
Data
(),
context
.
GasLimit
,
execName
,
msg
.
Alias
())
}
else
{
}
else
{
inData
:=
msg
.
Data
()
//TODO 在这里进行ABI和十六进制的调用参数转换
//TODO 在这里进行ABI和十六进制的调用参数转换
if
bytes
.
HasPrefix
(
msg
.
Data
(),
evmtypes
.
ABICallPrefix
)
{
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Call
(
runtime
.
AccountRef
(
msg
.
From
()),
*
msg
.
To
(),
msg
.
Data
(),
context
.
GasLimit
,
msg
.
Value
())
abiCall
=
true
callData
:=
msg
.
Data
()[
len
(
evmtypes
.
ABICallPrefix
)
:
]
abiDataBin
,
err
:=
evm
.
GetStateDB
()
.
Get
(
getABIKey
(
*
msg
.
To
()))
if
err
!=
nil
{
return
nil
,
err
}
abiData
=
string
(
abiDataBin
)
funcName
,
packData
,
err
:=
abi
.
Pack
(
string
(
callData
),
abiData
)
if
err
!=
nil
{
return
nil
,
err
}
methodName
=
funcName
inData
=
packData
}
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Call
(
runtime
.
AccountRef
(
msg
.
From
()),
*
msg
.
To
(),
inData
,
context
.
GasLimit
,
msg
.
Value
())
}
}
log
.
Debug
(
"call(create) contract "
,
"input"
,
common
.
Bytes2Hex
(
msg
.
Data
()))
log
.
Debug
(
"call(create) contract "
,
"input"
,
common
.
Bytes2Hex
(
msg
.
Data
()))
...
@@ -103,7 +122,9 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -103,7 +122,9 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
data
,
logs
:=
evm
.
mStateDB
.
GetChangedData
(
curVer
.
GetID
())
data
,
logs
:=
evm
.
mStateDB
.
GetChangedData
(
curVer
.
GetID
())
// TODO 在这里进行调用结果的转换
// TODO 在这里进行调用结果的转换
if
abiCall
{
}
contractReceipt
:=
&
evmtypes
.
ReceiptEVMContract
{
Caller
:
msg
.
From
()
.
String
(),
ContractName
:
execName
,
ContractAddr
:
contractAddr
.
String
(),
UsedGas
:
usedGas
,
Ret
:
ret
}
contractReceipt
:=
&
evmtypes
.
ReceiptEVMContract
{
Caller
:
msg
.
From
()
.
String
(),
ContractName
:
execName
,
ContractAddr
:
contractAddr
.
String
(),
UsedGas
:
usedGas
,
Ret
:
ret
}
logs
=
append
(
logs
,
&
types
.
ReceiptLog
{
Ty
:
evmtypes
.
TyLogCallContract
,
Log
:
types
.
Encode
(
contractReceipt
)})
logs
=
append
(
logs
,
&
types
.
ReceiptLog
{
Ty
:
evmtypes
.
TyLogCallContract
,
Log
:
types
.
Encode
(
contractReceipt
)})
logs
=
append
(
logs
,
evm
.
mStateDB
.
GetReceiptLogs
(
contractAddr
.
String
())
...
)
logs
=
append
(
logs
,
evm
.
mStateDB
.
GetReceiptLogs
(
contractAddr
.
String
())
...
)
...
@@ -121,6 +142,8 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -121,6 +142,8 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
_
,
err
=
abi
.
JSON
(
strings
.
NewReader
(
msg
.
ABI
()))
_
,
err
=
abi
.
JSON
(
strings
.
NewReader
(
msg
.
ABI
()))
if
err
==
nil
{
if
err
==
nil
{
data
=
append
(
data
,
evm
.
getABIKV
(
contractAddr
,
msg
.
ABI
()))
data
=
append
(
data
,
evm
.
getABIKV
(
contractAddr
,
msg
.
ABI
()))
}
else
{
log
.
Debug
(
"invalid abi data in transaction note"
,
"note"
,
msg
.
ABI
())
}
}
}
}
...
...
plugin/dapp/evm/executor/vm/common/address.go
View file @
d33e674d
...
@@ -84,6 +84,11 @@ func (h Hash160Address) Hex() string {
...
@@ -84,6 +84,11 @@ func (h Hash160Address) Hex() string {
return
"0x"
+
string
(
result
)
return
"0x"
+
string
(
result
)
}
}
// ToAddress 返回Chain33格式的地址
func
(
h
Hash160Address
)
ToAddress
()
Address
{
return
BytesToAddress
(
h
[
:
])
}
// NewAddress xHash生成EVM合约地址
// NewAddress xHash生成EVM合约地址
func
NewAddress
(
txHash
[]
byte
)
Address
{
func
NewAddress
(
txHash
[]
byte
)
Address
{
execAddr
:=
address
.
GetExecAddress
(
types
.
ExecName
(
"user.evm."
)
+
BytesToHash
(
txHash
)
.
Hex
())
execAddr
:=
address
.
GetExecAddress
(
types
.
ExecName
(
"user.evm."
)
+
BytesToHash
(
txHash
)
.
Hex
())
...
...
plugin/dapp/evm/types/evm.go
View file @
d33e674d
...
@@ -23,8 +23,7 @@ var (
...
@@ -23,8 +23,7 @@ var (
"EvmCall"
:
EvmCallAction
,
"EvmCall"
:
EvmCallAction
,
}
}
BindABIPrefix
=
ecommon
.
FromHex
(
"0x00000000"
)
ABICallPrefix
=
ecommon
.
FromHex
(
"0x00000000"
)
ABICallPrefix
=
ecommon
.
FromHex
(
"0xffffffff"
)
)
)
func
init
()
{
func
init
()
{
...
@@ -214,10 +213,10 @@ func createEvmTx(param *CreateCallTx) (*types.Transaction, error) {
...
@@ -214,10 +213,10 @@ func createEvmTx(param *CreateCallTx) (*types.Transaction, error) {
return
createRawTx
(
action
,
""
)
return
createRawTx
(
action
,
""
)
}
else
{
}
else
{
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Debug
(
"create evm call Tx as abi
"
,
"param.Code"
,
param
.
Code
)
elog
.
Info
(
"evm call data is invalid hex data, process it as abi data
"
,
"param.Code"
,
param
.
Code
)
bCode
=
[]
byte
(
param
.
Code
)
bCode
=
[]
byte
(
param
.
Code
)
bCode
=
append
(
BindABI
Prefix
,
bCode
...
)
bCode
=
append
(
ABICall
Prefix
,
bCode
...
)
}
}
return
createRawTx
(
action
,
param
.
Name
)
return
createRawTx
(
action
,
param
.
Name
)
}
}
}
}
\ No newline at end of file
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