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
781721f6
Commit
781721f6
authored
Nov 26, 2018
by
Litian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
evm 支持abi代码逻辑基本完成
parent
d33e674d
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
427 additions
and
309 deletions
+427
-309
raft.go
plugin/consensus/raft/raft.go
+1
-1
scp.go
plugin/consensus/raft/tools/scripts/go-scp/scp.go
+1
-1
abi.go
plugin/dapp/evm/executor/abi/abi.go
+5
-5
abi_test.go
plugin/dapp/evm/executor/abi/abi_test.go
+0
-0
api.go
plugin/dapp/evm/executor/abi/api.go
+26
-9
api_test.go
plugin/dapp/evm/executor/abi/api_test.go
+4
-3
argument.go
plugin/dapp/evm/executor/abi/argument.go
+6
-5
error.go
plugin/dapp/evm/executor/abi/error.go
+2
-2
event.go
plugin/dapp/evm/executor/abi/event.go
+2
-2
event_test.go
plugin/dapp/evm/executor/abi/event_test.go
+30
-30
method.go
plugin/dapp/evm/executor/abi/method.go
+2
-1
pack.go
plugin/dapp/evm/executor/abi/pack.go
+2
-2
pack_test.go
plugin/dapp/evm/executor/abi/pack_test.go
+7
-7
reflect.go
plugin/dapp/evm/executor/abi/reflect.go
+8
-8
type_test.go
plugin/dapp/evm/executor/abi/type_test.go
+7
-7
unpack.go
plugin/dapp/evm/executor/abi/unpack.go
+2
-2
unpack_test.go
plugin/dapp/evm/executor/abi/unpack_test.go
+30
-30
exec.go
plugin/dapp/evm/executor/exec.go
+49
-62
query.go
plugin/dapp/evm/executor/query.go
+89
-28
evm_test.go
plugin/dapp/evm/executor/tests/evm_test.go
+2
-2
util_test.go
plugin/dapp/evm/executor/tests/util_test.go
+1
-1
address.go
plugin/dapp/evm/executor/vm/common/address.go
+3
-10
crypto.go
plugin/dapp/evm/executor/vm/common/crypto/crypto.go
+1
-2
evm.go
plugin/dapp/evm/executor/vm/runtime/evm.go
+5
-1
instructions.go
plugin/dapp/evm/executor/vm/runtime/instructions.go
+1
-1
account.go
plugin/dapp/evm/executor/vm/state/account.go
+25
-0
interface.go
plugin/dapp/evm/executor/vm/state/interface.go
+7
-0
snapshot.go
plugin/dapp/evm/executor/vm/state/snapshot.go
+23
-0
statedb.go
plugin/dapp/evm/executor/vm/state/statedb.go
+23
-0
evmcontract.proto
plugin/dapp/evm/proto/evmcontract.proto
+31
-0
evm.go
plugin/dapp/evm/types/evm.go
+30
-87
evmcontract.pb.go
plugin/dapp/evm/types/evmcontract.pb.go
+0
-0
tx.go
plugin/dapp/evm/types/tx.go
+2
-0
No files found.
plugin/consensus/raft/raft.go
View file @
781721f6
...
@@ -294,7 +294,7 @@ func (rc *raftNode) updateValidator() {
...
@@ -294,7 +294,7 @@ func (rc *raftNode) updateValidator() {
rlog
.
Debug
(
fmt
.
Sprintf
(
"==============This is %s node!=============="
,
status
.
RaftState
.
String
()))
rlog
.
Debug
(
fmt
.
Sprintf
(
"==============This is %s node!=============="
,
status
.
RaftState
.
String
()))
continue
continue
}
else
{
}
else
{
// 获取到leader I
d
,选主成功
// 获取到leader I
D
,选主成功
if
rc
.
id
==
int
(
status
.
Lead
)
{
if
rc
.
id
==
int
(
status
.
Lead
)
{
//leader选举出来之后即可添加addReadOnlyPeers
//leader选举出来之后即可添加addReadOnlyPeers
if
!
flag
&&
!
isRestart
{
if
!
flag
&&
!
isRestart
{
...
...
plugin/consensus/raft/tools/scripts/go-scp/scp.go
View file @
781721f6
...
@@ -236,7 +236,7 @@ func main() {
...
@@ -236,7 +236,7 @@ func main() {
}
}
////读取当前目录下的文件
////读取当前目录下的文件
//dir_list, e := ioutil.ReadDir("D:/Repository/src/github.com/33cn/chain33/consensus/drivers/raft/tools/scripts")
//dir_list, e := ioutil.ReadDir("
I
D:/Repository/src/github.com/33cn/chain33/consensus/drivers/raft/tools/scripts")
//if e != nil {
//if e != nil {
// fmt.Println("read dir error")
// fmt.Println("read dir error")
// return
// return
...
...
plugin/dapp/evm/executor/abi/abi.go
View file @
781721f6
...
@@ -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
...
@@ -70,7 +70,7 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
...
@@ -70,7 +70,7 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
return
nil
,
err
return
nil
,
err
}
}
// Pack up the method ID too if not a constructor and return
// Pack up the method ID too if not a constructor and return
return
append
(
method
.
I
d
(),
arguments
...
),
nil
return
append
(
method
.
I
D
(),
arguments
...
),
nil
}
}
// Unpack output in v according to the abi specification
// Unpack output in v according to the abi specification
...
@@ -134,14 +134,14 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
...
@@ -134,14 +134,14 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
return
nil
return
nil
}
}
// MethodByI
d
looks up a method by the 4-byte id
// MethodByI
D
looks up a method by the 4-byte id
// returns nil if none found
// returns nil if none found
func
(
abi
*
ABI
)
MethodByI
d
(
sigdata
[]
byte
)
(
*
Method
,
error
)
{
func
(
abi
*
ABI
)
MethodByI
D
(
sigdata
[]
byte
)
(
*
Method
,
error
)
{
if
len
(
sigdata
)
<
4
{
if
len
(
sigdata
)
<
4
{
return
nil
,
fmt
.
Errorf
(
"data too short (% bytes) for abi method lookup"
,
len
(
sigdata
))
return
nil
,
fmt
.
Errorf
(
"data too short (% bytes) for abi method lookup"
,
len
(
sigdata
))
}
}
for
_
,
method
:=
range
abi
.
Methods
{
for
_
,
method
:=
range
abi
.
Methods
{
if
bytes
.
Equal
(
method
.
I
d
(),
sigdata
[
:
4
])
{
if
bytes
.
Equal
(
method
.
I
D
(),
sigdata
[
:
4
])
{
return
&
method
,
nil
return
&
method
,
nil
}
}
}
}
...
...
plugin/dapp/evm/executor/abi/abi_test.go
View file @
781721f6
This diff is collapsed.
Click to expand it.
plugin/dapp/evm/executor/abi/api.go
View file @
781721f6
...
@@ -3,19 +3,22 @@ package abi
...
@@ -3,19 +3,22 @@ package abi
import
(
import
(
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/golang-collections/collections/stack"
"math/big"
"math/big"
"reflect"
"reflect"
"strconv"
"strconv"
"strings"
"strings"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/golang-collections/collections/stack"
"github.com/kataras/iris/core/errors"
)
)
// Pack 使用ABI方式调用时,将调用方式转换为EVM底层处理的十六进制编码
// Pack 使用ABI方式调用时,将调用方式转换为EVM底层处理的十六进制编码
// abiData 完整的ABI定义
// abiData 完整的ABI定义
// param 调用方法及参数
// param 调用方法及参数
// readOnly 是否只读,如果调用的方法不为只读,则报错
// 调用方式: foo(param1,param2)
// 调用方式: foo(param1,param2)
func
Pack
(
param
,
abiData
string
)
(
methodName
string
,
packData
[]
byte
,
err
error
)
{
func
Pack
(
param
,
abiData
string
,
readOnly
bool
)
(
methodName
string
,
packData
[]
byte
,
err
error
)
{
// 首先解析参数字符串,分析出方法名以及个参数取值
// 首先解析参数字符串,分析出方法名以及个参数取值
methodName
,
params
,
err
:=
procFuncCall
(
param
)
methodName
,
params
,
err
:=
procFuncCall
(
param
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -35,6 +38,13 @@ func Pack(param, abiData string) (methodName string, packData []byte, err error)
...
@@ -35,6 +38,13 @@ func Pack(param, abiData string) (methodName string, packData []byte, err error)
return
methodName
,
packData
,
err
return
methodName
,
packData
,
err
}
}
if
readOnly
&&
!
method
.
Const
{
return
methodName
,
packData
,
errors
.
New
(
"method is not readonly"
)
}
if
len
(
params
)
!=
method
.
Inputs
.
LengthNonIndexed
()
{
err
=
fmt
.
Errorf
(
"function params error:%v"
,
params
)
return
methodName
,
packData
,
err
}
// 获取方法参数对象,遍历解析各参数,获得参数的Go取值
// 获取方法参数对象,遍历解析各参数,获得参数的Go取值
paramVals
:=
[]
interface
{}{}
paramVals
:=
[]
interface
{}{}
if
len
(
params
)
!=
0
{
if
len
(
params
)
!=
0
{
...
@@ -62,7 +72,9 @@ func Pack(param, abiData string) (methodName string, packData []byte, err error)
...
@@ -62,7 +72,9 @@ func Pack(param, abiData string) (methodName string, packData []byte, err error)
// data 合约方法返回值
// data 合约方法返回值
// abiData 完整的ABI定义
// abiData 完整的ABI定义
func
Unpack
(
data
[]
byte
,
methodName
,
abiData
string
)
(
output
string
,
err
error
)
{
func
Unpack
(
data
[]
byte
,
methodName
,
abiData
string
)
(
output
string
,
err
error
)
{
if
len
(
data
)
==
0
{
return
output
,
err
}
// 解析ABI数据结构,获取本次调用的方法对象
// 解析ABI数据结构,获取本次调用的方法对象
abi
,
err
:=
JSON
(
strings
.
NewReader
(
abiData
))
abi
,
err
:=
JSON
(
strings
.
NewReader
(
abiData
))
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -75,6 +87,10 @@ func Unpack(data []byte, methodName, abiData string) (output string, err error)
...
@@ -75,6 +87,10 @@ func Unpack(data []byte, methodName, abiData string) (output string, err error)
return
output
,
fmt
.
Errorf
(
"function %v not exists"
,
methodName
)
return
output
,
fmt
.
Errorf
(
"function %v not exists"
,
methodName
)
}
}
if
method
.
Outputs
.
LengthNonIndexed
()
==
0
{
return
output
,
err
}
values
,
err
:=
method
.
Outputs
.
UnpackValues
(
data
)
values
,
err
:=
method
.
Outputs
.
UnpackValues
(
data
)
if
err
!=
nil
{
if
err
!=
nil
{
return
output
,
err
return
output
,
err
...
@@ -95,9 +111,13 @@ func Unpack(data []byte, methodName, abiData string) (output string, err error)
...
@@ -95,9 +111,13 @@ func Unpack(data []byte, methodName, abiData string) (output string, err error)
return
string
(
jsondata
),
err
return
string
(
jsondata
),
err
}
}
// Param 返回值参数结构定义
type
Param
struct
{
type
Param
struct
{
// Name 参数名称
Name
string
`json:"name"`
Name
string
`json:"name"`
// Type 参数类型
Type
string
`json:"type"`
Type
string
`json:"type"`
// Value 参数取值
Value
interface
{}
`json:"value"`
Value
interface
{}
`json:"value"`
}
}
...
@@ -143,11 +163,10 @@ func str2GoValue(typ Type, val string) (res interface{}, err error) {
...
@@ -143,11 +163,10 @@ func str2GoValue(typ Type, val string) (res interface{}, err error) {
return
res
,
err
return
res
,
err
}
}
return
convertInt
(
x
,
typ
.
Kind
),
nil
return
convertInt
(
x
,
typ
.
Kind
),
nil
}
else
{
}
b
:=
new
(
big
.
Int
)
b
:=
new
(
big
.
Int
)
b
.
SetString
(
val
,
10
)
b
.
SetString
(
val
,
10
)
return
b
,
err
return
b
,
err
}
case
UintTy
:
case
UintTy
:
if
typ
.
Size
<
256
{
if
typ
.
Size
<
256
{
x
,
err
:=
strconv
.
ParseUint
(
val
,
10
,
typ
.
Size
)
x
,
err
:=
strconv
.
ParseUint
(
val
,
10
,
typ
.
Size
)
...
@@ -155,11 +174,10 @@ func str2GoValue(typ Type, val string) (res interface{}, err error) {
...
@@ -155,11 +174,10 @@ func str2GoValue(typ Type, val string) (res interface{}, err error) {
return
res
,
err
return
res
,
err
}
}
return
convertUint
(
x
,
typ
.
Kind
),
nil
return
convertUint
(
x
,
typ
.
Kind
),
nil
}
else
{
}
b
:=
new
(
big
.
Int
)
b
:=
new
(
big
.
Int
)
b
.
SetString
(
val
,
10
)
b
.
SetString
(
val
,
10
)
return
b
,
err
return
b
,
err
}
case
BoolTy
:
case
BoolTy
:
x
,
err
:=
strconv
.
ParseBool
(
val
)
x
,
err
:=
strconv
.
ParseBool
(
val
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -230,7 +248,6 @@ func str2GoValue(typ Type, val string) (res interface{}, err error) {
...
@@ -230,7 +248,6 @@ func str2GoValue(typ Type, val string) (res interface{}, err error) {
default
:
default
:
return
res
,
fmt
.
Errorf
(
"not support type: %v"
,
typ
.
stringKind
)
return
res
,
fmt
.
Errorf
(
"not support type: %v"
,
typ
.
stringKind
)
}
}
return
res
,
nil
}
}
// 本方法可以将一个表示数组的字符串,经过处理后,返回数组内的字面元素;
// 本方法可以将一个表示数组的字符串,经过处理后,返回数组内的字面元素;
...
...
plugin/dapp/evm/executor/abi/api_test.go
View file @
781721f6
...
@@ -3,10 +3,11 @@ package abi
...
@@ -3,10 +3,11 @@ package abi
import
(
import
(
"bytes"
"bytes"
"fmt"
"fmt"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/stretchr/testify/assert"
"reflect"
"reflect"
"testing"
"testing"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/stretchr/testify/assert"
)
)
func
TestABI_Pack
(
t
*
testing
.
T
)
{
func
TestABI_Pack
(
t
*
testing
.
T
)
{
...
@@ -33,7 +34,7 @@ func TestABI_Pack(t *testing.T) {
...
@@ -33,7 +34,7 @@ func TestABI_Pack(t *testing.T) {
"0x60fe47b10000000000000000000000000000000000000000000000000000000000000064"
,
"0x60fe47b10000000000000000000000000000000000000000000000000000000000000064"
,
},
},
}
{
}
{
data
,
err
:=
Pack
(
test
.
input
,
abiData
)
_
,
data
,
err
:=
Pack
(
test
.
input
,
abiData
,
false
)
assert
.
NoError
(
t
,
err
)
assert
.
NoError
(
t
,
err
)
assert
.
EqualValues
(
t
,
test
.
output
,
common
.
Bytes2Hex
(
data
))
assert
.
EqualValues
(
t
,
test
.
output
,
common
.
Bytes2Hex
(
data
))
}
}
...
...
plugin/dapp/evm/executor/abi/argument.go
View file @
781721f6
...
@@ -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
...
@@ -31,6 +31,7 @@ type Argument struct {
...
@@ -31,6 +31,7 @@ type Argument struct {
Indexed
bool
// indexed is only used by events
Indexed
bool
// indexed is only used by events
}
}
// Arguments Argument slice type
type
Arguments
[]
Argument
type
Arguments
[]
Argument
// UnmarshalJSON implements json.Unmarshaler interface
// UnmarshalJSON implements json.Unmarshaler interface
...
@@ -86,7 +87,7 @@ func (arguments Arguments) isTuple() bool {
...
@@ -86,7 +87,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 +153,10 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
...
@@ -152,10 +153,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 +268,7 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
...
@@ -267,7 +268,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 @
781721f6
...
@@ -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.go
View file @
781721f6
...
@@ -44,9 +44,9 @@ func (e Event) String() string {
...
@@ -44,9 +44,9 @@ func (e Event) String() string {
return
fmt
.
Sprintf
(
"e %v(%v)"
,
e
.
Name
,
strings
.
Join
(
inputs
,
", "
))
return
fmt
.
Sprintf
(
"e %v(%v)"
,
e
.
Name
,
strings
.
Join
(
inputs
,
", "
))
}
}
// I
d
returns the canonical representation of the event's signature used by the
// I
D
returns the canonical representation of the event's signature used by the
// abi definition to identify event names and types.
// abi definition to identify event names and types.
func
(
e
Event
)
I
d
()
common
.
Hash
{
func
(
e
Event
)
I
D
()
common
.
Hash
{
types
:=
make
([]
string
,
len
(
e
.
Inputs
))
types
:=
make
([]
string
,
len
(
e
.
Inputs
))
i
:=
0
i
:=
0
for
_
,
input
:=
range
e
.
Inputs
{
for
_
,
input
:=
range
e
.
Inputs
{
...
...
plugin/dapp/evm/executor/abi/event_test.go
View file @
781721f6
...
@@ -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)"
)),
...
@@ -104,8 +104,8 @@ func TestEventId(t *testing.T) {
...
@@ -104,8 +104,8 @@ func TestEventId(t *testing.T) {
}
}
for
name
,
event
:=
range
abi
.
Events
{
for
name
,
event
:=
range
abi
.
Events
{
if
event
.
I
d
()
!=
test
.
expectations
[
name
]
{
if
event
.
I
D
()
!=
test
.
expectations
[
name
]
{
t
.
Errorf
(
"expected id to be %x, got %x"
,
test
.
expectations
[
name
],
event
.
I
d
())
t
.
Errorf
(
"expected id to be %x, got %x"
,
test
.
expectations
[
name
],
event
.
I
D
())
}
}
}
}
}
}
...
@@ -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
,
...
@@ -242,7 +242,7 @@ func TestEventTupleUnpack(t *testing.T) {
...
@@ -242,7 +242,7 @@ func TestEventTupleUnpack(t *testing.T) {
"Can unpack Pledge event into structure"
,
"Can unpack Pledge event into structure"
,
},
{
},
{
pledgeData1
,
pledgeData1
,
&
[]
interface
{}{
&
common
.
Hash160Address
{},
&
bigint
,
&
[
3
]
byte
{}},
&
[]
interface
{}{
&
common
.
Hash160Address
{},
&
bigint
,
&
[
3
]
byte
{}},
&
[]
interface
{}{
&
[]
interface
{}{
&
addr
,
&
addr
,
&
bigintExpected2
,
&
bigintExpected2
,
...
@@ -252,7 +252,7 @@ func TestEventTupleUnpack(t *testing.T) {
...
@@ -252,7 +252,7 @@ func TestEventTupleUnpack(t *testing.T) {
"Can unpack Pledge event into slice"
,
"Can unpack Pledge event into slice"
,
},
{
},
{
pledgeData1
,
pledgeData1
,
&
[
3
]
interface
{}{
&
common
.
Hash160Address
{},
&
bigint
,
&
[
3
]
byte
{}},
&
[
3
]
interface
{}{
&
common
.
Hash160Address
{},
&
bigint
,
&
[
3
]
byte
{}},
&
[
3
]
interface
{}{
&
[
3
]
interface
{}{
&
addr
,
&
addr
,
&
bigintExpected2
,
&
bigintExpected2
,
...
@@ -276,7 +276,7 @@ func TestEventTupleUnpack(t *testing.T) {
...
@@ -276,7 +276,7 @@ func TestEventTupleUnpack(t *testing.T) {
"Can not unpack Pledge event into struct with wrong filed types"
,
"Can not unpack Pledge event into struct with wrong filed types"
,
},
{
},
{
pledgeData1
,
pledgeData1
,
&
[]
interface
{}{
common
.
Hash160Address
{},
new
(
big
.
Int
)},
&
[]
interface
{}{
common
.
Hash160Address
{},
new
(
big
.
Int
)},
&
[]
interface
{}{},
&
[]
interface
{}{},
jsonEventPledge
,
jsonEventPledge
,
"abi: insufficient number of elements in the list/array for unpack, want 3, got 2"
,
"abi: insufficient number of elements in the list/array for unpack, want 3, got 2"
,
...
@@ -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/method.go
View file @
781721f6
...
@@ -72,6 +72,7 @@ func (method Method) String() string {
...
@@ -72,6 +72,7 @@ func (method Method) String() string {
return
fmt
.
Sprintf
(
"function %v(%v) %sreturns(%v)"
,
method
.
Name
,
strings
.
Join
(
inputs
,
", "
),
constant
,
strings
.
Join
(
outputs
,
", "
))
return
fmt
.
Sprintf
(
"function %v(%v) %sreturns(%v)"
,
method
.
Name
,
strings
.
Join
(
inputs
,
", "
),
constant
,
strings
.
Join
(
outputs
,
", "
))
}
}
func
(
method
Method
)
Id
()
[]
byte
{
// ID method name hash
func
(
method
Method
)
ID
()
[]
byte
{
return
crypto
.
Keccak256
([]
byte
(
method
.
Sig
()))[
:
4
]
return
crypto
.
Keccak256
([]
byte
(
method
.
Sig
()))[
:
4
]
}
}
plugin/dapp/evm/executor/abi/pack.go
View file @
781721f6
...
@@ -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/pack_test.go
View file @
781721f6
...
@@ -306,7 +306,7 @@ func TestPack(t *testing.T) {
...
@@ -306,7 +306,7 @@ func TestPack(t *testing.T) {
},
},
{
{
"address[]"
,
"address[]"
,
[]
common
.
Hash160Address
{{
1
},
{
2
}},
[]
common
.
Hash160Address
{{
1
},
{
2
}},
common
.
Hex2Bytes
(
"000000000000000000000000000000000000000000000000000000000000000200000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000"
),
common
.
Hex2Bytes
(
"000000000000000000000000000000000000000000000000000000000000000200000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000"
),
},
},
{
{
...
@@ -347,7 +347,7 @@ func TestMethodPack(t *testing.T) {
...
@@ -347,7 +347,7 @@ func TestMethodPack(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
sig
:=
abi
.
Methods
[
"slice"
]
.
I
d
()
sig
:=
abi
.
Methods
[
"slice"
]
.
I
D
()
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
1
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
1
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
...
@@ -361,13 +361,13 @@ func TestMethodPack(t *testing.T) {
...
@@ -361,13 +361,13 @@ func TestMethodPack(t *testing.T) {
}
}
var
addrA
,
addrB
=
common
.
Hash160Address
{
1
},
common
.
Hash160Address
{
2
}
var
addrA
,
addrB
=
common
.
Hash160Address
{
1
},
common
.
Hash160Address
{
2
}
sig
=
abi
.
Methods
[
"sliceAddress"
]
.
I
d
()
sig
=
abi
.
Methods
[
"sliceAddress"
]
.
I
D
()
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
32
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
32
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrA
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrA
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrB
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrB
[
:
],
32
)
...
)
packed
,
err
=
abi
.
Pack
(
"sliceAddress"
,
[]
common
.
Hash160Address
{
addrA
,
addrB
})
packed
,
err
=
abi
.
Pack
(
"sliceAddress"
,
[]
common
.
Hash160Address
{
addrA
,
addrB
})
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -376,7 +376,7 @@ func TestMethodPack(t *testing.T) {
...
@@ -376,7 +376,7 @@ func TestMethodPack(t *testing.T) {
}
}
var
addrC
,
addrD
=
common
.
Hash160Address
{
3
},
common
.
Hash160Address
{
4
}
var
addrC
,
addrD
=
common
.
Hash160Address
{
3
},
common
.
Hash160Address
{
4
}
sig
=
abi
.
Methods
[
"sliceMultiAddress"
]
.
I
d
()
sig
=
abi
.
Methods
[
"sliceMultiAddress"
]
.
I
D
()
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
64
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
64
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
160
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
160
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
...
@@ -386,7 +386,7 @@ func TestMethodPack(t *testing.T) {
...
@@ -386,7 +386,7 @@ func TestMethodPack(t *testing.T) {
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrC
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrC
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrD
[
:
],
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
(
addrD
[
:
],
32
)
...
)
packed
,
err
=
abi
.
Pack
(
"sliceMultiAddress"
,
[]
common
.
Hash160Address
{
addrA
,
addrB
},
[]
common
.
Hash160Address
{
addrC
,
addrD
})
packed
,
err
=
abi
.
Pack
(
"sliceMultiAddress"
,
[]
common
.
Hash160Address
{
addrA
,
addrB
},
[]
common
.
Hash160Address
{
addrC
,
addrD
})
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -394,7 +394,7 @@ func TestMethodPack(t *testing.T) {
...
@@ -394,7 +394,7 @@ func TestMethodPack(t *testing.T) {
t
.
Errorf
(
"expected %x got %x"
,
sig
,
packed
)
t
.
Errorf
(
"expected %x got %x"
,
sig
,
packed
)
}
}
sig
=
abi
.
Methods
[
"slice256"
]
.
I
d
()
sig
=
abi
.
Methods
[
"slice256"
]
.
I
D
()
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
1
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
1
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
sig
=
append
(
sig
,
common
.
LeftPadBytes
([]
byte
{
2
},
32
)
...
)
...
...
plugin/dapp/evm/executor/abi/reflect.go
View file @
781721f6
...
@@ -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/type_test.go
View file @
781721f6
...
@@ -84,8 +84,8 @@ func TestTypeRegexp(t *testing.T) {
...
@@ -84,8 +84,8 @@ func TestTypeRegexp(t *testing.T) {
{
"string[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
string
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
Type
:
reflect
.
TypeOf
(
""
),
T
:
StringTy
,
stringKind
:
"string"
},
stringKind
:
"string[]"
}},
{
"string[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
string
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
Type
:
reflect
.
TypeOf
(
""
),
T
:
StringTy
,
stringKind
:
"string"
},
stringKind
:
"string[]"
}},
{
"string[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
string
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
T
:
StringTy
,
Type
:
reflect
.
TypeOf
(
""
),
stringKind
:
"string"
},
stringKind
:
"string[2]"
}},
{
"string[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
string
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
String
,
T
:
StringTy
,
Type
:
reflect
.
TypeOf
(
""
),
stringKind
:
"string"
},
stringKind
:
"string[2]"
}},
{
"address"
,
Type
{
Kind
:
reflect
.
Array
,
Type
:
addressT
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
}},
{
"address"
,
Type
{
Kind
:
reflect
.
Array
,
Type
:
addressT
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
}},
{
"address[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
common
.
Hash160Address
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
addressT
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[]"
}},
{
"address[]"
,
Type
{
T
:
SliceTy
,
Kind
:
reflect
.
Slice
,
Type
:
reflect
.
TypeOf
([]
common
.
Hash160Address
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
addressT
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[]"
}},
{
"address[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
common
.
Hash160Address
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
addressT
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[2]"
}},
{
"address[2]"
,
Type
{
Kind
:
reflect
.
Array
,
T
:
ArrayTy
,
Size
:
2
,
Type
:
reflect
.
TypeOf
([
2
]
common
.
Hash160Address
{}),
Elem
:
&
Type
{
Kind
:
reflect
.
Array
,
Type
:
addressT
,
Size
:
20
,
T
:
AddressTy
,
stringKind
:
"address"
},
stringKind
:
"address[2]"
}},
// TODO when fixed types are implemented properly
// TODO when fixed types are implemented properly
// {"fixed", Type{}},
// {"fixed", Type{}},
// {"fixed128x128", Type{}},
// {"fixed128x128", Type{}},
...
@@ -102,7 +102,7 @@ func TestTypeRegexp(t *testing.T) {
...
@@ -102,7 +102,7 @@ func TestTypeRegexp(t *testing.T) {
}
}
if
!
reflect
.
DeepEqual
(
typ
,
tt
.
kind
)
{
if
!
reflect
.
DeepEqual
(
typ
,
tt
.
kind
)
{
//t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", tt.blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(tt.kind)))
//t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", tt.blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(tt.kind)))
t
.
Errorf
(
"type %q: parsed type mismatch:
\n
GOT %s
\n
WANT %s "
,
tt
.
blob
,
typ
eWithoutStringer
(
typ
),
typeWithoutStringer
(
tt
.
kind
)
)
t
.
Errorf
(
"type %q: parsed type mismatch:
\n
GOT %s
\n
WANT %s "
,
tt
.
blob
,
typ
,
tt
.
kind
)
}
}
}
}
}
}
...
@@ -201,10 +201,10 @@ func TestTypeCheck(t *testing.T) {
...
@@ -201,10 +201,10 @@ func TestTypeCheck(t *testing.T) {
{
"uint16[3]"
,
[
4
]
uint16
{
1
,
2
,
3
},
"abi: cannot use [4]uint16 as type [3]uint16 as argument"
},
{
"uint16[3]"
,
[
4
]
uint16
{
1
,
2
,
3
},
"abi: cannot use [4]uint16 as type [3]uint16 as argument"
},
{
"uint16[3]"
,
[]
uint16
{
1
,
2
,
3
},
""
},
{
"uint16[3]"
,
[]
uint16
{
1
,
2
,
3
},
""
},
{
"uint16[3]"
,
[]
uint16
{
1
,
2
,
3
,
4
},
"abi: cannot use [4]uint16 as type [3]uint16 as argument"
},
{
"uint16[3]"
,
[]
uint16
{
1
,
2
,
3
,
4
},
"abi: cannot use [4]uint16 as type [3]uint16 as argument"
},
{
"address[]"
,
[]
common
.
Hash160Address
{{
1
}},
""
},
{
"address[]"
,
[]
common
.
Hash160Address
{{
1
}},
""
},
{
"address[1]"
,
[]
common
.
Hash160Address
{{
1
}},
""
},
{
"address[1]"
,
[]
common
.
Hash160Address
{{
1
}},
""
},
{
"address[1]"
,
[
1
]
common
.
Hash160Address
{{
1
}},
""
},
{
"address[1]"
,
[
1
]
common
.
Hash160Address
{{
1
}},
""
},
{
"address[2]"
,
[
1
]
common
.
Hash160Address
{{
1
}},
"abi: cannot use [1]array as type [2]array as argument"
},
{
"address[2]"
,
[
1
]
common
.
Hash160Address
{{
1
}},
"abi: cannot use [1]array as type [2]array as argument"
},
{
"bytes32"
,
[
32
]
byte
{},
""
},
{
"bytes32"
,
[
32
]
byte
{},
""
},
{
"bytes31"
,
[
31
]
byte
{},
""
},
{
"bytes31"
,
[
31
]
byte
{},
""
},
{
"bytes30"
,
[
30
]
byte
{},
""
},
{
"bytes30"
,
[
30
]
byte
{},
""
},
...
...
plugin/dapp/evm/executor/abi/unpack.go
View file @
781721f6
...
@@ -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 @
781721f6
...
@@ -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
)
}
}
}
}
...
@@ -689,7 +689,7 @@ func TestUnmarshal(t *testing.T) {
...
@@ -689,7 +689,7 @@ func TestUnmarshal(t *testing.T) {
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
))
// size
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000001"
))
// size
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000100000000000000000000000000000000000000"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000100000000000000000000000000000000000000"
))
var
outAddr
[]
common
.
Hash160Address
var
outAddr
[]
common
.
Hash160Address
err
=
abi
.
Unpack
(
&
outAddr
,
"addressSliceSingle"
,
buff
.
Bytes
())
err
=
abi
.
Unpack
(
&
outAddr
,
"addressSliceSingle"
,
buff
.
Bytes
())
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
"didn't expect error:"
,
err
)
t
.
Fatal
(
"didn't expect error:"
,
err
)
...
@@ -699,7 +699,7 @@ func TestUnmarshal(t *testing.T) {
...
@@ -699,7 +699,7 @@ func TestUnmarshal(t *testing.T) {
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddr
))
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddr
))
}
}
if
outAddr
[
0
]
!=
(
common
.
Hash160Address
{
1
})
{
if
outAddr
[
0
]
!=
(
common
.
Hash160Address
{
1
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
1
},
outAddr
[
0
])
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
1
},
outAddr
[
0
])
}
}
...
@@ -714,8 +714,8 @@ func TestUnmarshal(t *testing.T) {
...
@@ -714,8 +714,8 @@ func TestUnmarshal(t *testing.T) {
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000300000000000000000000000000000000000000"
))
buff
.
Write
(
common
.
Hex2Bytes
(
"0000000000000000000000000300000000000000000000000000000000000000"
))
var
outAddrStruct
struct
{
var
outAddrStruct
struct
{
A
[]
common
.
Hash160Address
A
[]
common
.
Hash160Address
B
[]
common
.
Hash160Address
B
[]
common
.
Hash160Address
}
}
err
=
abi
.
Unpack
(
&
outAddrStruct
,
"addressSliceDouble"
,
buff
.
Bytes
())
err
=
abi
.
Unpack
(
&
outAddrStruct
,
"addressSliceDouble"
,
buff
.
Bytes
())
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -726,7 +726,7 @@ func TestUnmarshal(t *testing.T) {
...
@@ -726,7 +726,7 @@ func TestUnmarshal(t *testing.T) {
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddrStruct
.
A
))
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddrStruct
.
A
))
}
}
if
outAddrStruct
.
A
[
0
]
!=
(
common
.
Hash160Address
{
1
})
{
if
outAddrStruct
.
A
[
0
]
!=
(
common
.
Hash160Address
{
1
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
1
},
outAddrStruct
.
A
[
0
])
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
1
},
outAddrStruct
.
A
[
0
])
}
}
...
@@ -734,10 +734,10 @@ func TestUnmarshal(t *testing.T) {
...
@@ -734,10 +734,10 @@ func TestUnmarshal(t *testing.T) {
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddrStruct
.
B
))
t
.
Fatal
(
"expected 1 item, got"
,
len
(
outAddrStruct
.
B
))
}
}
if
outAddrStruct
.
B
[
0
]
!=
(
common
.
Hash160Address
{
2
})
{
if
outAddrStruct
.
B
[
0
]
!=
(
common
.
Hash160Address
{
2
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
2
},
outAddrStruct
.
B
[
0
])
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
2
},
outAddrStruct
.
B
[
0
])
}
}
if
outAddrStruct
.
B
[
1
]
!=
(
common
.
Hash160Address
{
3
})
{
if
outAddrStruct
.
B
[
1
]
!=
(
common
.
Hash160Address
{
3
})
{
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
3
},
outAddrStruct
.
B
[
1
])
t
.
Errorf
(
"expected %x, got %x"
,
common
.
Hash160Address
{
3
},
outAddrStruct
.
B
[
1
])
}
}
...
@@ -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 @
781721f6
...
@@ -9,7 +9,6 @@ import (
...
@@ -9,7 +9,6 @@ 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"
...
@@ -28,7 +27,12 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -28,7 +27,12 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
return
evm
.
innerExec
(
msg
,
tx
.
Hash
(),
index
,
tx
.
Fee
,
false
)
}
// 通用的EVM合约执行逻辑封装
// readOnly 是否只读调用,仅执行evm abi查询时为true
func
(
evm
*
EVMExecutor
)
innerExec
(
msg
*
common
.
Message
,
txHash
[]
byte
,
index
int
,
txFee
int64
,
readOnly
bool
)
(
receipt
*
types
.
Receipt
,
err
error
)
{
// 获取当前区块的上下文信息构造EVM上下文
// 获取当前区块的上下文信息构造EVM上下文
context
:=
evm
.
NewEVMContext
(
msg
)
context
:=
evm
.
NewEVMContext
(
msg
)
...
@@ -42,7 +46,6 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -42,7 +46,6 @@ 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
abiData
string
methodName
string
methodName
string
)
)
...
@@ -50,38 +53,38 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -50,38 +53,38 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
// 为了方便计费,即使合约为新生成,也将地址的初始化放到外面操作
// 为了方便计费,即使合约为新生成,也将地址的初始化放到外面操作
if
isCreate
{
if
isCreate
{
// 使用随机生成的地址作为合约地址(这个可以保证每次创建的合约地址不会重复,不存在冲突的情况)
// 使用随机生成的地址作为合约地址(这个可以保证每次创建的合约地址不会重复,不存在冲突的情况)
contractAddr
=
evm
.
getNewAddr
(
tx
.
Hash
()
)
contractAddr
=
evm
.
getNewAddr
(
tx
Hash
)
if
!
env
.
StateDB
.
Empty
(
contractAddr
.
String
())
{
if
!
env
.
StateDB
.
Empty
(
contractAddr
.
String
())
{
return
nil
,
model
.
ErrContractAddressCollision
return
receipt
,
model
.
ErrContractAddressCollision
}
}
// 只有新创建的合约才能生成合约名称
// 只有新创建的合约才能生成合约名称
execName
=
fmt
.
Sprintf
(
"%s%s"
,
types
.
ExecName
(
evmtypes
.
EvmPrefix
),
common
.
BytesToHash
(
tx
.
Hash
()
)
.
Hex
())
execName
=
fmt
.
Sprintf
(
"%s%s"
,
types
.
ExecName
(
evmtypes
.
EvmPrefix
),
common
.
BytesToHash
(
tx
Hash
)
.
Hex
())
}
else
{
}
else
{
contractAddr
=
*
msg
.
To
()
contractAddr
=
*
msg
.
To
()
}
}
// 状态机中设置当前交易状态
// 状态机中设置当前交易状态
evm
.
mStateDB
.
Prepare
(
common
.
BytesToHash
(
tx
.
Hash
()
),
index
)
evm
.
mStateDB
.
Prepare
(
common
.
BytesToHash
(
tx
Hash
),
index
)
if
isCreate
{
if
isCreate
{
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
contractAddr
,
msg
.
Data
(),
context
.
GasLimit
,
execName
,
msg
.
Alias
())
// 如果携带ABI数据,则对数据合法性进行检查
}
else
{
if
len
(
msg
.
ABI
())
>
0
&&
types
.
IsDappFork
(
evm
.
GetHeight
(),
"evm"
,
"ForkEVMABI"
)
{
inData
:=
msg
.
Data
()
_
,
err
=
abi
.
JSON
(
strings
.
NewReader
(
abiData
))
//TODO 在这里进行ABI和十六进制的调用参数转换
if
bytes
.
HasPrefix
(
msg
.
Data
(),
evmtypes
.
ABICallPrefix
)
{
abiCall
=
true
callData
:=
msg
.
Data
()[
len
(
evmtypes
.
ABICallPrefix
)
:
]
abiDataBin
,
err
:=
evm
.
GetStateDB
()
.
Get
(
getABIKey
(
*
msg
.
To
()))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
receipt
,
err
}
}
abiData
=
string
(
abiDataBin
)
}
funcName
,
packData
,
err
:=
abi
.
Pack
(
string
(
callData
),
abiData
)
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
contractAddr
,
msg
.
Data
(),
context
.
GasLimit
,
execName
,
msg
.
Alias
(),
msg
.
ABI
())
}
else
{
inData
:=
msg
.
Data
()
// 在这里进行ABI和十六进制的调用参数转换
if
len
(
msg
.
ABI
())
>
0
&&
types
.
IsDappFork
(
evm
.
GetHeight
(),
"evm"
,
"ForkEVMABI"
)
{
funcName
,
packData
,
err
:=
abi
.
Pack
(
msg
.
ABI
(),
evm
.
mStateDB
.
GetAbi
(
msg
.
To
()
.
String
()),
readOnly
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
receipt
,
err
}
}
methodName
=
funcName
inData
=
packData
inData
=
packData
methodName
=
funcName
}
}
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Call
(
runtime
.
AccountRef
(
msg
.
From
()),
*
msg
.
To
(),
inData
,
context
.
GasLimit
,
msg
.
Value
())
ret
,
snapshot
,
leftOverGas
,
vmerr
=
env
.
Call
(
runtime
.
AccountRef
(
msg
.
From
()),
*
msg
.
To
(),
inData
,
context
.
GasLimit
,
msg
.
Value
())
}
}
...
@@ -98,34 +101,40 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -98,34 +101,40 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
if
vmerr
!=
nil
{
if
vmerr
!=
nil
{
log
.
Error
(
"evm contract exec error"
,
"error info"
,
vmerr
)
log
.
Error
(
"evm contract exec error"
,
"error info"
,
vmerr
)
return
nil
,
vmerr
return
receipt
,
vmerr
}
}
// 计算消耗了多少费用(实际消耗的费用)
// 计算消耗了多少费用(实际消耗的费用)
usedFee
,
overflow
:=
common
.
SafeMul
(
usedGas
,
uint64
(
msg
.
GasPrice
()))
usedFee
,
overflow
:=
common
.
SafeMul
(
usedGas
,
uint64
(
msg
.
GasPrice
()))
// 费用消耗溢出,执行失败
// 费用消耗溢出,执行失败
if
overflow
||
usedFee
>
uint64
(
tx
.
Fee
)
{
if
overflow
||
usedFee
>
uint64
(
txFee
)
{
// 如果操作没有回滚,则在这里处理
// 如果操作没有回滚,则在这里处理
if
curVer
!=
nil
&&
snapshot
>=
curVer
.
GetID
()
&&
curVer
.
GetID
()
>
-
1
{
if
curVer
!=
nil
&&
snapshot
>=
curVer
.
GetID
()
&&
curVer
.
GetID
()
>
-
1
{
evm
.
mStateDB
.
RevertToSnapshot
(
snapshot
)
evm
.
mStateDB
.
RevertToSnapshot
(
snapshot
)
}
}
return
nil
,
model
.
ErrOutOfGas
return
receipt
,
model
.
ErrOutOfGas
}
}
// 打印合约中生成的日志
// 打印合约中生成的日志
evm
.
mStateDB
.
PrintLogs
()
evm
.
mStateDB
.
PrintLogs
()
// 没有任何数据变更
if
curVer
==
nil
{
if
curVer
==
nil
{
return
nil
,
nil
return
receipt
,
nil
}
}
// 从状态机中获取数据变更和变更日志
data
,
logs
:=
evm
.
mStateDB
.
GetChangedData
(
curVer
.
GetID
())
// TODO 在这里进行调用结果的转换
// 从状态机中获取数据变更和变更日志
if
abiCall
{
kvSet
,
logs
:=
evm
.
mStateDB
.
GetChangedData
(
curVer
.
GetID
())
}
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
}
// 这里进行ABI调用结果格式化
if
len
(
methodName
)
>
0
&&
len
(
msg
.
ABI
())
>
0
&&
types
.
IsDappFork
(
evm
.
GetHeight
(),
"evm"
,
"ForkEVMABI"
)
{
jsonRet
,
err
:=
abi
.
Unpack
(
ret
,
methodName
,
evm
.
mStateDB
.
GetAbi
(
msg
.
To
()
.
String
()))
if
err
!=
nil
{
// 这里出错不影响整体执行,只打印错误信息
log
.
Error
(
"unpack evm return error"
,
"error"
,
err
)
}
contractReceipt
.
JsonRet
=
jsonRet
}
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
())
...
)
...
@@ -133,21 +142,11 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -133,21 +142,11 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
// 将执行时生成的合约状态数据变更信息也计算哈希并保存
// 将执行时生成的合约状态数据变更信息也计算哈希并保存
hashKV
:=
evm
.
calcKVHash
(
contractAddr
,
logs
)
hashKV
:=
evm
.
calcKVHash
(
contractAddr
,
logs
)
if
hashKV
!=
nil
{
if
hashKV
!=
nil
{
data
=
append
(
data
,
hashKV
)
kvSet
=
append
(
kvSet
,
hashKV
)
}
}
// 尝试从交易备注中获取ABI数据
if
isCreate
&&
types
.
IsDappFork
(
evm
.
GetHeight
(),
"evm"
,
"ForkEVMABI"
)
{
_
,
err
=
abi
.
JSON
(
strings
.
NewReader
(
msg
.
ABI
()))
if
err
==
nil
{
data
=
append
(
data
,
evm
.
getABIKV
(
contractAddr
,
msg
.
ABI
()))
}
else
{
log
.
Debug
(
"invalid abi data in transaction note"
,
"note"
,
msg
.
ABI
())
}
}
}
}
receipt
:=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
data
,
Logs
:
logs
}
receipt
=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kvSet
,
Logs
:
logs
}
// 返回之前,把本次交易在区块中生成的合约日志集中打印出来
// 返回之前,把本次交易在区块中生成的合约日志集中打印出来
if
evm
.
mStateDB
!=
nil
{
if
evm
.
mStateDB
!=
nil
{
...
@@ -155,9 +154,10 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
...
@@ -155,9 +154,10 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
}
}
// 替换导致分叉的执行数据信息
// 替换导致分叉的执行数据信息
state
.
ProcessFork
(
evm
.
GetHeight
(),
tx
.
Hash
(),
receipt
)
state
.
ProcessFork
(
evm
.
GetHeight
(),
txHash
,
receipt
)
evm
.
collectEvmTxLog
(
txHash
,
contractReceipt
,
receipt
)
evm
.
collectEvmTxLog
(
tx
,
contractReceipt
,
receipt
)
return
receipt
,
nil
return
receipt
,
nil
}
}
...
@@ -173,22 +173,17 @@ func (evm *EVMExecutor) GetMessage(tx *types.Transaction) (msg *common.Message,
...
@@ -173,22 +173,17 @@ func (evm *EVMExecutor) GetMessage(tx *types.Transaction) (msg *common.Message,
var
action
evmtypes
.
EVMContractAction
var
action
evmtypes
.
EVMContractAction
err
=
types
.
Decode
(
tx
.
Payload
,
&
action
)
err
=
types
.
Decode
(
tx
.
Payload
,
&
action
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
msg
,
err
}
}
// 此处暂时不考虑消息发送签名的处理,chain33在mempool中对签名做了检查
// 此处暂时不考虑消息发送签名的处理,chain33在mempool中对签名做了检查
from
:=
getCaller
(
tx
)
from
:=
getCaller
(
tx
)
to
:=
getReceiver
(
tx
)
to
:=
getReceiver
(
tx
)
if
to
==
nil
{
if
to
==
nil
{
return
nil
,
types
.
ErrInvalidAddress
return
msg
,
types
.
ErrInvalidAddress
}
}
// 注意Transaction中的payload内容同时包含转账金额和合约代码
// payload[:8]为转账金额,payload[8:]为合约代码
amount
:=
action
.
Amount
gasLimit
:=
action
.
GasLimit
gasLimit
:=
action
.
GasLimit
gasPrice
:=
action
.
GasPrice
gasPrice
:=
action
.
GasPrice
code
:=
action
.
Code
if
gasLimit
==
0
{
if
gasLimit
==
0
{
gasLimit
=
uint64
(
tx
.
Fee
)
gasLimit
=
uint64
(
tx
.
Fee
)
}
}
...
@@ -197,13 +192,13 @@ func (evm *EVMExecutor) GetMessage(tx *types.Transaction) (msg *common.Message,
...
@@ -197,13 +192,13 @@ func (evm *EVMExecutor) GetMessage(tx *types.Transaction) (msg *common.Message,
}
}
// 合约的GasLimit即为调用者为本次合约调用准备支付的手续费
// 合约的GasLimit即为调用者为本次合约调用准备支付的手续费
msg
=
common
.
NewMessage
(
from
,
to
,
tx
.
Nonce
,
a
mount
,
gasLimit
,
gasPrice
,
code
,
action
.
GetAlias
(),
action
.
Note
)
msg
=
common
.
NewMessage
(
from
,
to
,
tx
.
Nonce
,
a
ction
.
Amount
,
gasLimit
,
gasPrice
,
action
.
Code
,
action
.
GetAlias
(),
action
.
Abi
)
return
msg
,
nil
return
msg
,
err
}
}
func
(
evm
*
EVMExecutor
)
collectEvmTxLog
(
tx
*
types
.
Transaction
,
cr
*
evmtypes
.
ReceiptEVMContract
,
receipt
*
types
.
Receipt
)
{
func
(
evm
*
EVMExecutor
)
collectEvmTxLog
(
tx
Hash
[]
byte
,
cr
*
evmtypes
.
ReceiptEVMContract
,
receipt
*
types
.
Receipt
)
{
log
.
Debug
(
"evm collect begin"
)
log
.
Debug
(
"evm collect begin"
)
log
.
Debug
(
"Tx info"
,
"txHash"
,
common
.
Bytes2Hex
(
tx
.
Hash
()
),
"height"
,
evm
.
GetHeight
())
log
.
Debug
(
"Tx info"
,
"txHash"
,
common
.
Bytes2Hex
(
tx
Hash
),
"height"
,
evm
.
GetHeight
())
log
.
Debug
(
"ReceiptEVMContract"
,
"data"
,
fmt
.
Sprintf
(
"caller=%v, name=%v, addr=%v, usedGas=%v, ret=%v"
,
cr
.
Caller
,
cr
.
ContractName
,
cr
.
ContractAddr
,
cr
.
UsedGas
,
common
.
Bytes2Hex
(
cr
.
Ret
)))
log
.
Debug
(
"ReceiptEVMContract"
,
"data"
,
fmt
.
Sprintf
(
"caller=%v, name=%v, addr=%v, usedGas=%v, ret=%v"
,
cr
.
Caller
,
cr
.
ContractName
,
cr
.
ContractAddr
,
cr
.
UsedGas
,
common
.
Bytes2Hex
(
cr
.
Ret
)))
log
.
Debug
(
"receipt data"
,
"type"
,
receipt
.
Ty
)
log
.
Debug
(
"receipt data"
,
"type"
,
receipt
.
Ty
)
for
_
,
kv
:=
range
receipt
.
KV
{
for
_
,
kv
:=
range
receipt
.
KV
{
...
@@ -232,18 +227,10 @@ func (evm *EVMExecutor) calcKVHash(addr common.Address, logs []*types.ReceiptLog
...
@@ -232,18 +227,10 @@ func (evm *EVMExecutor) calcKVHash(addr common.Address, logs []*types.ReceiptLog
return
nil
return
nil
}
}
func
(
evm
*
EVMExecutor
)
getABIKV
(
addr
common
.
Address
,
data
string
)
(
kv
*
types
.
KeyValue
)
{
return
&
types
.
KeyValue
{
Key
:
getABIKey
(
addr
),
Value
:
[]
byte
(
data
)}
}
func
getDataHashKey
(
addr
common
.
Address
)
[]
byte
{
func
getDataHashKey
(
addr
common
.
Address
)
[]
byte
{
return
[]
byte
(
fmt
.
Sprintf
(
"mavl-%v-data-hash:%v"
,
evmtypes
.
ExecutorName
,
addr
))
return
[]
byte
(
fmt
.
Sprintf
(
"mavl-%v-data-hash:%v"
,
evmtypes
.
ExecutorName
,
addr
))
}
}
func
getABIKey
(
addr
common
.
Address
)
[]
byte
{
return
[]
byte
(
fmt
.
Sprintf
(
"mavl-%v-data-abi:%v"
,
evmtypes
.
ExecutorName
,
addr
))
}
// 从交易信息中获取交易发起人地址
// 从交易信息中获取交易发起人地址
func
getCaller
(
tx
*
types
.
Transaction
)
common
.
Address
{
func
getCaller
(
tx
*
types
.
Transaction
)
common
.
Address
{
return
*
common
.
StringToAddress
(
tx
.
From
())
return
*
common
.
StringToAddress
(
tx
.
From
())
...
...
plugin/dapp/evm/executor/query.go
View file @
781721f6
...
@@ -12,9 +12,8 @@ import (
...
@@ -12,9 +12,8 @@ import (
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/model"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/model"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/runtime"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/state"
evmtypes
"github.com/33cn/plugin/plugin/dapp/evm/types"
evmtypes
"github.com/33cn/plugin/plugin/dapp/evm/types"
"github.com/kataras/iris/core/errors"
)
)
// Query_CheckAddrExists 检查合约地址是否存在,此操作不会改变任何状态,所以可以直接从statedb查询
// Query_CheckAddrExists 检查合约地址是否存在,此操作不会改变任何状态,所以可以直接从statedb查询
...
@@ -56,7 +55,6 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types
...
@@ -56,7 +55,6 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types
evm
.
CheckInit
()
evm
.
CheckInit
()
var
(
var
(
caller
common
.
Address
caller
common
.
Address
to
*
common
.
Address
)
)
// 如果未指定调用地址,则直接使用一个虚拟的地址发起调用
// 如果未指定调用地址,则直接使用一个虚拟的地址发起调用
...
@@ -69,35 +67,36 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types
...
@@ -69,35 +67,36 @@ func (evm *EVMExecutor) Query_EstimateGas(in *evmtypes.EstimateEVMGasReq) (types
caller
=
common
.
ExecAddress
(
types
.
ExecName
(
evmtypes
.
ExecutorName
))
caller
=
common
.
ExecAddress
(
types
.
ExecName
(
evmtypes
.
ExecutorName
))
}
}
isCreate
:=
strings
.
EqualFold
(
in
.
To
,
EvmAddress
)
msg
:=
common
.
NewMessage
(
caller
,
nil
,
0
,
in
.
Amount
,
evmtypes
.
MaxGasLimit
,
1
,
in
.
Code
,
"estimateGas"
,
in
.
Abi
)
msg
:=
common
.
NewMessage
(
caller
,
nil
,
0
,
in
.
Amount
,
evmtypes
.
MaxGasLimit
,
1
,
in
.
Code
,
"estimateGas"
,
""
)
context
:=
evm
.
NewEVMContext
(
msg
)
// 创建EVM运行时对象
evm
.
mStateDB
=
state
.
NewMemoryStateDB
(
evm
.
GetStateDB
(),
evm
.
GetLocalDB
(),
evm
.
GetCoinsAccount
(),
evm
.
GetHeight
())
env
:=
runtime
.
NewEVM
(
context
,
evm
.
mStateDB
,
*
evm
.
vmCfg
)
evm
.
mStateDB
.
Prepare
(
common
.
BigToHash
(
big
.
NewInt
(
evmtypes
.
MaxGasLimit
)),
0
)
var
(
vmerr
error
leftOverGas
uint64
contractAddr
common
.
Address
execName
string
)
if
isCreate
{
txHash
:=
common
.
BigToHash
(
big
.
NewInt
(
evmtypes
.
MaxGasLimit
))
.
Bytes
()
txHash
:=
common
.
BigToHash
(
big
.
NewInt
(
evmtypes
.
MaxGasLimit
))
.
Bytes
()
contractAddr
=
evm
.
getNewAddr
(
txHash
)
execName
=
fmt
.
Sprintf
(
"%s%s"
,
types
.
ExecName
(
evmtypes
.
EvmPrefix
),
common
.
BytesToHash
(
txHash
)
.
Hex
())
receipt
,
err
:=
evm
.
innerExec
(
msg
,
txHash
,
1
,
evmtypes
.
MaxGasLimit
,
false
)
_
,
_
,
leftOverGas
,
vmerr
=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
contractAddr
,
msg
.
Data
(),
context
.
GasLimit
,
execName
,
"estimateGas"
)
if
err
!=
nil
{
}
else
{
return
nil
,
err
to
=
common
.
StringToAddress
(
in
.
To
)
_
,
_
,
leftOverGas
,
vmerr
=
env
.
Call
(
runtime
.
AccountRef
(
msg
.
From
()),
*
to
,
msg
.
Data
(),
context
.
GasLimit
,
msg
.
Value
())
}
}
if
receipt
.
Ty
==
types
.
ExecOk
{
callData
:=
getCallReceipt
(
receipt
.
GetLogs
())
if
callData
!=
nil
{
result
:=
&
evmtypes
.
EstimateEVMGasResp
{}
result
:=
&
evmtypes
.
EstimateEVMGasResp
{}
result
.
Gas
=
evmtypes
.
MaxGasLimit
-
leftOverGas
result
.
Gas
=
callData
.
UsedGas
return
result
,
vmerr
return
result
,
nil
}
}
return
nil
,
errors
.
New
(
"contract call error"
)
}
// 从日志中查找调用结果
func
getCallReceipt
(
logs
[]
*
types
.
ReceiptLog
)
(
res
*
evmtypes
.
ReceiptEVMContract
)
{
if
len
(
logs
)
==
0
{
return
res
}
for
_
,
v
:=
range
logs
{
if
v
.
Ty
==
evmtypes
.
TyLogCallContract
{
types
.
Decode
(
v
.
Log
,
res
)
}
}
return
res
}
}
// Query_EvmDebug 此方法用来估算合约消耗的Gas,不能修改原有执行器的状态数据
// Query_EvmDebug 此方法用来估算合约消耗的Gas,不能修改原有执行器的状态数据
...
@@ -113,3 +112,65 @@ func (evm *EVMExecutor) Query_EvmDebug(in *evmtypes.EvmDebugReq) (types.Message,
...
@@ -113,3 +112,65 @@ func (evm *EVMExecutor) Query_EvmDebug(in *evmtypes.EvmDebugReq) (types.Message,
ret
:=
&
evmtypes
.
EvmDebugResp
{
DebugStatus
:
fmt
.
Sprintf
(
"%v"
,
evmDebug
)}
ret
:=
&
evmtypes
.
EvmDebugResp
{
DebugStatus
:
fmt
.
Sprintf
(
"%v"
,
evmDebug
)}
return
ret
,
nil
return
ret
,
nil
}
}
// Query_Query 此方法用来调用合约的只读接口,不修改原有执行器的状态数据
func
(
evm
*
EVMExecutor
)
Query_Query
(
in
*
evmtypes
.
EvmQueryReq
)
(
types
.
Message
,
error
)
{
evm
.
CheckInit
()
ret
:=
&
evmtypes
.
EvmQueryResp
{}
ret
.
Address
=
in
.
Address
ret
.
Input
=
in
.
Input
ret
.
Caller
=
in
.
Caller
var
(
caller
common
.
Address
)
to
:=
common
.
StringToAddress
(
in
.
Address
)
if
to
==
nil
{
ret
.
JsonData
=
fmt
.
Sprintf
(
"invalid address:%v"
,
in
.
Address
)
return
ret
,
nil
}
// 如果未指定调用地址,则直接使用一个虚拟的地址发起调用
if
len
(
in
.
Caller
)
>
0
{
callAddr
:=
common
.
StringToAddress
(
in
.
Caller
)
if
callAddr
!=
nil
{
caller
=
*
callAddr
}
}
else
{
caller
=
common
.
ExecAddress
(
types
.
ExecName
(
evmtypes
.
ExecutorName
))
}
msg
:=
common
.
NewMessage
(
caller
,
common
.
StringToAddress
(
in
.
Address
),
0
,
0
,
evmtypes
.
MaxGasLimit
,
1
,
nil
,
"estimateGas"
,
in
.
Input
)
txHash
:=
common
.
BigToHash
(
big
.
NewInt
(
evmtypes
.
MaxGasLimit
))
.
Bytes
()
receipt
,
err
:=
evm
.
innerExec
(
msg
,
txHash
,
1
,
evmtypes
.
MaxGasLimit
,
true
)
if
err
!=
nil
{
ret
.
JsonData
=
fmt
.
Sprintf
(
"%v"
,
err
)
return
ret
,
nil
}
if
receipt
.
Ty
==
types
.
ExecOk
{
callData
:=
getCallReceipt
(
receipt
.
GetLogs
())
if
callData
!=
nil
{
ret
.
RawData
=
callData
.
Ret
ret
.
JsonData
=
callData
.
JsonRet
return
ret
,
nil
}
}
return
ret
,
nil
}
// Query_QueryABI 此方法用来查询合约绑定的ABI数据,不修改原有执行器的状态数据
func
(
evm
*
EVMExecutor
)
Query_QueryABI
(
in
*
evmtypes
.
EvmQueryAbiReq
)
(
types
.
Message
,
error
)
{
evm
.
CheckInit
()
addr
:=
common
.
StringToAddress
(
in
.
GetAddress
())
if
addr
==
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid address: %v"
,
in
.
GetAddress
())
}
abiData
:=
evm
.
mStateDB
.
GetAbi
(
addr
.
String
())
return
&
evmtypes
.
EvmQueryAbiResp
{
Address
:
in
.
GetAddress
(),
Abi
:
abiData
},
nil
}
plugin/dapp/evm/executor/tests/evm_test.go
View file @
781721f6
...
@@ -137,7 +137,7 @@ func runCase(tt *testing.T, c VMCase, file string) {
...
@@ -137,7 +137,7 @@ func runCase(tt *testing.T, c VMCase, file string) {
ret
,
_
,
_
,
err
=
env
.
Call
(
runtime
.
AccountRef
(
msg
.
From
()),
*
common
.
StringToAddress
(
c
.
exec
.
address
),
msg
.
Data
(),
msg
.
GasLimit
(),
msg
.
Value
())
ret
,
_
,
_
,
err
=
env
.
Call
(
runtime
.
AccountRef
(
msg
.
From
()),
*
common
.
StringToAddress
(
c
.
exec
.
address
),
msg
.
Data
(),
msg
.
GasLimit
(),
msg
.
Value
())
}
else
{
}
else
{
addr
:=
crypto
.
RandomContractAddress
()
addr
:=
crypto
.
RandomContractAddress
()
ret
,
_
,
_
,
err
=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
*
addr
,
msg
.
Data
(),
msg
.
GasLimit
(),
"testExecName"
,
""
)
ret
,
_
,
_
,
err
=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
*
addr
,
msg
.
Data
(),
msg
.
GasLimit
(),
"testExecName"
,
""
,
""
)
}
}
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -200,5 +200,5 @@ func buildMsg(c VMCase) *common.Message {
...
@@ -200,5 +200,5 @@ func buildMsg(c VMCase) *common.Message {
addr2
:=
common
.
StringToAddress
(
c
.
exec
.
address
)
addr2
:=
common
.
StringToAddress
(
c
.
exec
.
address
)
gasLimit
:=
uint64
(
210000000
)
gasLimit
:=
uint64
(
210000000
)
gasPrice
:=
c
.
exec
.
gasPrice
gasPrice
:=
c
.
exec
.
gasPrice
return
common
.
NewMessage
(
*
addr1
,
addr2
,
int64
(
1
),
uint64
(
c
.
exec
.
value
),
gasLimit
,
uint32
(
gasPrice
),
code
,
""
)
return
common
.
NewMessage
(
*
addr1
,
addr2
,
int64
(
1
),
uint64
(
c
.
exec
.
value
),
gasLimit
,
uint32
(
gasPrice
),
code
,
""
,
""
)
}
}
plugin/dapp/evm/executor/tests/util_test.go
View file @
781721f6
...
@@ -271,7 +271,7 @@ func createContract(mdb *db.GoMemDB, tx types.Transaction, maxCodeSize int) (ret
...
@@ -271,7 +271,7 @@ func createContract(mdb *db.GoMemDB, tx types.Transaction, maxCodeSize int) (ret
}
}
addr
:=
*
crypto2
.
RandomContractAddress
()
addr
:=
*
crypto2
.
RandomContractAddress
()
ret
,
_
,
leftGas
,
err
:=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
addr
,
msg
.
Data
(),
msg
.
GasLimit
(),
fmt
.
Sprintf
(
"%s%s"
,
evmtypes
.
EvmPrefix
,
common
.
BytesToHash
(
tx
.
Hash
())
.
Hex
()),
""
)
ret
,
_
,
leftGas
,
err
:=
env
.
Create
(
runtime
.
AccountRef
(
msg
.
From
()),
addr
,
msg
.
Data
(),
msg
.
GasLimit
(),
fmt
.
Sprintf
(
"%s%s"
,
evmtypes
.
EvmPrefix
,
common
.
BytesToHash
(
tx
.
Hash
())
.
Hex
()),
""
,
""
)
return
ret
,
addr
,
leftGas
,
statedb
,
err
return
ret
,
addr
,
leftGas
,
statedb
,
err
}
}
plugin/dapp/evm/executor/vm/common/address.go
View file @
781721f6
...
@@ -7,11 +7,12 @@ package common
...
@@ -7,11 +7,12 @@ package common
import
(
import
(
"math/big"
"math/big"
"encoding/hex"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto/sha3"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
"encoding/hex"
"github.com/33cn/chain33/common/crypto/sha3"
)
)
// Address 封装地址结构体,并提供各种常用操作封装
// Address 封装地址结构体,并提供各种常用操作封装
...
@@ -116,14 +117,6 @@ func BytesToHash160Address(b []byte) Hash160Address {
...
@@ -116,14 +117,6 @@ func BytesToHash160Address(b []byte) Hash160Address {
return
h
return
h
}
}
// BytesToAddress 字节向地址转换
func
Hash160ToAddress
(
h
Hash160Address
)
Address
{
a
:=
new
(
address
.
Address
)
a
.
Version
=
0
a
.
Hash160
=
copyBytes
(
h
[
:
])
return
Address
{
addr
:
a
}
}
// StringToAddress 字符串转换为地址
// StringToAddress 字符串转换为地址
func
StringToAddress
(
s
string
)
*
Address
{
func
StringToAddress
(
s
string
)
*
Address
{
addr
,
err
:=
address
.
NewAddrFromString
(
s
)
addr
,
err
:=
address
.
NewAddrFromString
(
s
)
...
...
plugin/dapp/evm/executor/vm/common/crypto/crypto.go
View file @
781721f6
...
@@ -69,8 +69,7 @@ func Keccak256(data ...[]byte) []byte {
...
@@ -69,8 +69,7 @@ func Keccak256(data ...[]byte) []byte {
return
d
.
Sum
(
nil
)
return
d
.
Sum
(
nil
)
}
}
// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
// NewKeccak256Hash calculates and returns the Keccak256 hash of the input data,
// converting it to an internal Hash data structure.
// converting it to an internal Hash data structure.
func
Keccak256Hash
(
data
...
[]
byte
)
(
h
common
.
Hash
)
{
func
Keccak256Hash
(
data
...
[]
byte
)
(
h
common
.
Hash
)
{
d
:=
sha3
.
NewLegacyKeccak256
()
d
:=
sha3
.
NewLegacyKeccak256
()
...
...
plugin/dapp/evm/executor/vm/runtime/evm.go
View file @
781721f6
...
@@ -356,7 +356,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
...
@@ -356,7 +356,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// 使用传入的部署代码创建新的合约;
// 使用传入的部署代码创建新的合约;
// 目前chain33为了保证账户安全,不允许合约中涉及到外部账户的转账操作,
// 目前chain33为了保证账户安全,不允许合约中涉及到外部账户的转账操作,
// 所以,本步骤不接收转账金额参数
// 所以,本步骤不接收转账金额参数
func
(
evm
*
EVM
)
Create
(
caller
ContractRef
,
contractAddr
common
.
Address
,
code
[]
byte
,
gas
uint64
,
execName
,
alias
string
)
(
ret
[]
byte
,
snapshot
int
,
leftOverGas
uint64
,
err
error
)
{
func
(
evm
*
EVM
)
Create
(
caller
ContractRef
,
contractAddr
common
.
Address
,
code
[]
byte
,
gas
uint64
,
execName
,
alias
,
abi
string
)
(
ret
[]
byte
,
snapshot
int
,
leftOverGas
uint64
,
err
error
)
{
pass
,
err
:=
evm
.
preCheck
(
caller
,
contractAddr
,
0
)
pass
,
err
:=
evm
.
preCheck
(
caller
,
contractAddr
,
0
)
if
!
pass
{
if
!
pass
{
return
nil
,
-
1
,
gas
,
err
return
nil
,
-
1
,
gas
,
err
...
@@ -386,6 +386,10 @@ func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []b
...
@@ -386,6 +386,10 @@ func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []b
createDataGas
:=
uint64
(
len
(
ret
))
*
params
.
CreateDataGas
createDataGas
:=
uint64
(
len
(
ret
))
*
params
.
CreateDataGas
if
contract
.
UseGas
(
createDataGas
)
{
if
contract
.
UseGas
(
createDataGas
)
{
evm
.
StateDB
.
SetCode
(
contractAddr
.
String
(),
ret
)
evm
.
StateDB
.
SetCode
(
contractAddr
.
String
(),
ret
)
// 设置 ABI (如果有的话),这个动作不单独计费
if
len
(
abi
)
>
0
&&
types
.
IsDappFork
(
evm
.
StateDB
.
GetBlockHeight
(),
"evm"
,
"ForkEVMKVHash"
)
{
evm
.
StateDB
.
SetAbi
(
contractAddr
.
String
(),
abi
)
}
}
else
{
}
else
{
// 如果Gas不足,返回这个错误,让外部程序处理
// 如果Gas不足,返回这个错误,让外部程序处理
err
=
model
.
ErrCodeStoreOutOfGas
err
=
model
.
ErrCodeStoreOutOfGas
...
...
plugin/dapp/evm/executor/vm/runtime/instructions.go
View file @
781721f6
...
@@ -717,7 +717,7 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *mm.Memory, stack
...
@@ -717,7 +717,7 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *mm.Memory, stack
// 调用合约创建逻辑
// 调用合约创建逻辑
addr
:=
crypto
.
RandomContractAddress
()
addr
:=
crypto
.
RandomContractAddress
()
res
,
_
,
returnGas
,
suberr
:=
evm
.
Create
(
contract
,
*
addr
,
inPut
,
gas
,
"innerContract"
,
""
)
res
,
_
,
returnGas
,
suberr
:=
evm
.
Create
(
contract
,
*
addr
,
inPut
,
gas
,
"innerContract"
,
""
,
""
)
// 出错时压栈0,否则压栈创建出来的合约对象的地址
// 出错时压栈0,否则压栈创建出来的合约对象的地址
if
suberr
!=
nil
&&
suberr
!=
model
.
ErrCodeStoreOutOfGas
{
if
suberr
!=
nil
&&
suberr
!=
model
.
ErrCodeStoreOutOfGas
{
...
...
plugin/dapp/evm/executor/vm/state/account.go
View file @
781721f6
...
@@ -165,6 +165,14 @@ func (ca *ContractAccount) LoadContract(db db.KV) {
...
@@ -165,6 +165,14 @@ func (ca *ContractAccount) LoadContract(db db.KV) {
return
return
}
}
ca
.
resotreState
(
data
)
ca
.
resotreState
(
data
)
// 加载 ABI (如果有的话)
if
types
.
IsDappFork
(
ca
.
mdb
.
GetBlockHeight
(),
"evm"
,
"ForkEVMABI"
)
{
data
,
err
:=
db
.
Get
(
ca
.
GetAbiKey
())
if
err
==
nil
{
ca
.
Data
.
Abi
=
string
(
data
)
}
}
}
}
// SetCode 设置合约二进制代码
// SetCode 设置合约二进制代码
...
@@ -181,6 +189,18 @@ func (ca *ContractAccount) SetCode(code []byte) {
...
@@ -181,6 +189,18 @@ func (ca *ContractAccount) SetCode(code []byte) {
ca
.
Data
.
CodeHash
=
common
.
ToHash
(
code
)
.
Bytes
()
ca
.
Data
.
CodeHash
=
common
.
ToHash
(
code
)
.
Bytes
()
}
}
// SetAbi 设置合约绑定的ABI数据
func
(
ca
*
ContractAccount
)
SetAbi
(
abi
string
)
{
if
types
.
IsDappFork
(
ca
.
mdb
.
GetBlockHeight
(),
"evm"
,
"ForkEVMABI"
)
{
ca
.
mdb
.
addChange
(
abiChange
{
baseChange
:
baseChange
{},
account
:
ca
.
Addr
,
prevabi
:
ca
.
Data
.
Abi
,
})
ca
.
Data
.
Abi
=
abi
}
}
// SetCreator 设置创建者
// SetCreator 设置创建者
func
(
ca
*
ContractAccount
)
SetCreator
(
creator
string
)
{
func
(
ca
*
ContractAccount
)
SetCreator
(
creator
string
)
{
if
len
(
creator
)
==
0
{
if
len
(
creator
)
==
0
{
...
@@ -272,6 +292,11 @@ func (ca *ContractAccount) GetDataKey() []byte {
...
@@ -272,6 +292,11 @@ func (ca *ContractAccount) GetDataKey() []byte {
return
[]
byte
(
"mavl-"
+
evmtypes
.
ExecutorName
+
"-data: "
+
ca
.
Addr
)
return
[]
byte
(
"mavl-"
+
evmtypes
.
ExecutorName
+
"-data: "
+
ca
.
Addr
)
}
}
// GetAbiKey 获取Abi数据KEY,ABI数据使用单独的KEY存储
func
(
ca
*
ContractAccount
)
GetAbiKey
()
[]
byte
{
return
[]
byte
(
"mavl-"
+
evmtypes
.
ExecutorName
+
"-abi: "
+
ca
.
Addr
)
}
// GetStateKey 获取状态key
// GetStateKey 获取状态key
func
(
ca
*
ContractAccount
)
GetStateKey
()
[]
byte
{
func
(
ca
*
ContractAccount
)
GetStateKey
()
[]
byte
{
return
[]
byte
(
"mavl-"
+
evmtypes
.
ExecutorName
+
"-state: "
+
ca
.
Addr
)
return
[]
byte
(
"mavl-"
+
evmtypes
.
ExecutorName
+
"-state: "
+
ca
.
Addr
)
...
...
plugin/dapp/evm/executor/vm/state/interface.go
View file @
781721f6
...
@@ -37,6 +37,10 @@ type EVMStateDB interface {
...
@@ -37,6 +37,10 @@ type EVMStateDB interface {
SetCode
(
string
,
[]
byte
)
SetCode
(
string
,
[]
byte
)
// GetCodeSize 获取指定地址合约代码大小
// GetCodeSize 获取指定地址合约代码大小
GetCodeSize
(
string
)
int
GetCodeSize
(
string
)
int
// SetAbi 设置ABI内容
SetAbi
(
addr
,
abi
string
)
// GetAbi 获取ABI
GetAbi
(
addr
string
)
string
// AddRefund 合约Gas奖励回馈
// AddRefund 合约Gas奖励回馈
AddRefund
(
uint64
)
AddRefund
(
uint64
)
...
@@ -74,4 +78,7 @@ type EVMStateDB interface {
...
@@ -74,4 +78,7 @@ type EVMStateDB interface {
CanTransfer
(
sender
,
recipient
string
,
amount
uint64
)
bool
CanTransfer
(
sender
,
recipient
string
,
amount
uint64
)
bool
// Transfer 转账交易
// Transfer 转账交易
Transfer
(
sender
,
recipient
string
,
amount
uint64
)
bool
Transfer
(
sender
,
recipient
string
,
amount
uint64
)
bool
// GetBlockHeight 返回当前区块高度
GetBlockHeight
()
int64
}
}
plugin/dapp/evm/executor/vm/state/snapshot.go
View file @
781721f6
...
@@ -123,6 +123,13 @@ type (
...
@@ -123,6 +123,13 @@ type (
prevcode
,
prevhash
[]
byte
prevcode
,
prevhash
[]
byte
}
}
// 合约ABI变更事件
abiChange
struct
{
baseChange
account
string
prevabi
string
}
// 返还金额变更事件
// 返还金额变更事件
refundChange
struct
{
refundChange
struct
{
baseChange
baseChange
...
@@ -236,6 +243,22 @@ func (ch codeChange) getData(mdb *MemoryStateDB) (kvset []*types.KeyValue) {
...
@@ -236,6 +243,22 @@ func (ch codeChange) getData(mdb *MemoryStateDB) (kvset []*types.KeyValue) {
return
nil
return
nil
}
}
func
(
ch
abiChange
)
revert
(
mdb
*
MemoryStateDB
)
{
acc
:=
mdb
.
accounts
[
ch
.
account
]
if
acc
!=
nil
{
acc
.
Data
.
Abi
=
ch
.
prevabi
}
}
func
(
ch
abiChange
)
getData
(
mdb
*
MemoryStateDB
)
(
kvset
[]
*
types
.
KeyValue
)
{
acc
:=
mdb
.
accounts
[
ch
.
account
]
if
acc
!=
nil
{
kvset
=
append
(
kvset
,
acc
.
GetDataKV
()
...
)
return
kvset
}
return
nil
}
func
(
ch
storageChange
)
revert
(
mdb
*
MemoryStateDB
)
{
func
(
ch
storageChange
)
revert
(
mdb
*
MemoryStateDB
)
{
acc
:=
mdb
.
accounts
[
ch
.
account
]
acc
:=
mdb
.
accounts
[
ch
.
account
]
if
acc
!=
nil
{
if
acc
!=
nil
{
...
...
plugin/dapp/evm/executor/vm/state/statedb.go
View file @
781721f6
...
@@ -193,6 +193,24 @@ func (mdb *MemoryStateDB) SetCode(addr string, code []byte) {
...
@@ -193,6 +193,24 @@ func (mdb *MemoryStateDB) SetCode(addr string, code []byte) {
}
}
}
}
// SetAbi 设置ABI内容
func
(
mdb
*
MemoryStateDB
)
SetAbi
(
addr
,
abi
string
)
{
acc
:=
mdb
.
GetAccount
(
addr
)
if
acc
!=
nil
{
mdb
.
dataDirty
[
addr
]
=
true
acc
.
SetAbi
(
abi
)
}
}
// GetAbi 获取ABI
func
(
mdb
*
MemoryStateDB
)
GetAbi
(
addr
string
)
string
{
acc
:=
mdb
.
GetAccount
(
addr
)
if
acc
!=
nil
{
return
acc
.
Data
.
GetAbi
()
}
return
""
}
// GetCodeSize 获取合约代码自身的大小
// GetCodeSize 获取合约代码自身的大小
// 对应 EXTCODESIZE 操作码
// 对应 EXTCODESIZE 操作码
func
(
mdb
*
MemoryStateDB
)
GetCodeSize
(
addr
string
)
int
{
func
(
mdb
*
MemoryStateDB
)
GetCodeSize
(
addr
string
)
int
{
...
@@ -686,3 +704,8 @@ func (mdb *MemoryStateDB) ResetDatas() {
...
@@ -686,3 +704,8 @@ func (mdb *MemoryStateDB) ResetDatas() {
mdb
.
currentVer
=
nil
mdb
.
currentVer
=
nil
mdb
.
snapshots
=
mdb
.
snapshots
[
:
0
]
mdb
.
snapshots
=
mdb
.
snapshots
[
:
0
]
}
}
// GetBlockHeight 返回当前区块高度
func
(
mdb
*
MemoryStateDB
)
GetBlockHeight
()
int64
{
return
mdb
.
blockHeight
}
plugin/dapp/evm/proto/evmcontract.proto
View file @
781721f6
...
@@ -17,6 +17,8 @@ message EVMContractData {
...
@@ -17,6 +17,8 @@ message EVMContractData {
string
addr
=
4
;
string
addr
=
4
;
bytes
code
=
5
;
bytes
code
=
5
;
bytes
codeHash
=
6
;
bytes
codeHash
=
6
;
// 绑定ABI数据 ForkEVMABI
string
abi
=
7
;
}
}
// 存放合约变化数据
// 存放合约变化数据
...
@@ -41,6 +43,8 @@ message EVMContractAction {
...
@@ -41,6 +43,8 @@ message EVMContractAction {
string
alias
=
5
;
string
alias
=
5
;
// 交易备注
// 交易备注
string
note
=
6
;
string
note
=
6
;
// 创建或调用合约时携带的ABI数据 ForkEVMABI
string
abi
=
7
;
}
}
// 合约创建/调用日志
// 合约创建/调用日志
...
@@ -51,6 +55,8 @@ message ReceiptEVMContract {
...
@@ -51,6 +55,8 @@ message ReceiptEVMContract {
uint64
usedGas
=
4
;
uint64
usedGas
=
4
;
// 创建合约返回的代码
// 创建合约返回的代码
bytes
ret
=
5
;
bytes
ret
=
5
;
// json格式化后的返回值
string
jsonRet
=
6
;
}
}
// 用于保存EVM只能合约中的状态数据变更
// 用于保存EVM只能合约中的状态数据变更
...
@@ -104,6 +110,7 @@ message EstimateEVMGasReq {
...
@@ -104,6 +110,7 @@ message EstimateEVMGasReq {
bytes
code
=
2
;
bytes
code
=
2
;
string
caller
=
3
;
string
caller
=
3
;
uint64
amount
=
4
;
uint64
amount
=
4
;
string
abi
=
5
;
}
}
message
EstimateEVMGasResp
{
message
EstimateEVMGasResp
{
uint64
gas
=
1
;
uint64
gas
=
1
;
...
@@ -117,3 +124,26 @@ message EvmDebugReq {
...
@@ -117,3 +124,26 @@ message EvmDebugReq {
message
EvmDebugResp
{
message
EvmDebugResp
{
string
debugStatus
=
1
;
string
debugStatus
=
1
;
}
}
message
EvmQueryAbiReq
{
string
address
=
1
;
}
message
EvmQueryAbiResp
{
string
address
=
1
;
string
abi
=
2
;
}
message
EvmQueryReq
{
string
address
=
1
;
string
input
=
2
;
string
caller
=
3
;
}
message
EvmQueryResp
{
string
address
=
1
;
string
input
=
2
;
string
caller
=
3
;
bytes
rawData
=
4
;
string
jsonData
=
5
;
}
\ No newline at end of file
plugin/dapp/evm/types/evm.go
View file @
781721f6
...
@@ -12,7 +12,6 @@ import (
...
@@ -12,7 +12,6 @@ import (
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/address"
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"
ecommon
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
)
)
var
(
var
(
...
@@ -22,8 +21,6 @@ var (
...
@@ -22,8 +21,6 @@ var (
"EvmCreate"
:
EvmCreateAction
,
"EvmCreate"
:
EvmCreateAction
,
"EvmCall"
:
EvmCallAction
,
"EvmCall"
:
EvmCallAction
,
}
}
ABICallPrefix
=
ecommon
.
FromHex
(
"0x00000000"
)
)
)
func
init
()
{
func
init
()
{
...
@@ -102,23 +99,6 @@ func (evm EvmType) CreateTx(action string, message json.RawMessage) (*types.Tran
...
@@ -102,23 +99,6 @@ func (evm EvmType) CreateTx(action string, message json.RawMessage) (*types.Tran
}
}
return
createEvmTx
(
&
param
)
return
createEvmTx
(
&
param
)
}
}
//else if action == "BindABI" {
// var param BindABI
// err := json.Unmarshal(message, ¶m)
// if err != nil {
// elog.Error("Create BindABI", "Error", err)
// return nil, types.ErrInvalidParam
// }
// return createBindABITx(¶m)
//} else if action == "ABICall" {
// var param ABICall
// err := json.Unmarshal(message, ¶m)
// if err != nil {
// elog.Error("Create ABICall", "Error", err)
// return nil, types.ErrInvalidParam
// }
// return createABICallTx(¶m)
//}
return
nil
,
types
.
ErrNotSupport
return
nil
,
types
.
ErrNotSupport
}
}
...
@@ -127,64 +107,6 @@ func (evm *EvmType) GetLogMap() map[int64]*types.LogInfo {
...
@@ -127,64 +107,6 @@ func (evm *EvmType) GetLogMap() map[int64]*types.LogInfo {
return
logInfo
return
logInfo
}
}
//func createBindABITx(param *BindABI) (*types.Transaction, error) {
// if param == nil {
// elog.Error("createBindABITx", "param", param)
// return nil, types.ErrInvalidParam
// }
//
// code := []byte(param.Data)
// code = append(BindABIPrefix, code...)
//
// action := &EVMContractAction{
// Code: code,
// Note: param.Note,
// }
//
// return createRawTx(action, param.Name)
//}
//
//func createABICallTx(param *ABICall) (*types.Transaction, error) {
// if param == nil {
// elog.Error("createABICallTx", "param", param)
// return nil, types.ErrInvalidParam
// }
//
// code := []byte(param.Data)
// code = append(ABICallPrefix, code...)
//
// action := &EVMContractAction{
// Code: code,
// Amount: param.Amount,
// }
//
// return createRawTx(action, param.Name)
//
// return nil, nil
//}
func
createRawTx
(
action
*
EVMContractAction
,
name
string
)
(
*
types
.
Transaction
,
error
)
{
tx
:=
&
types
.
Transaction
{}
if
len
(
name
)
==
0
{
tx
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
types
.
ExecName
(
ExecutorName
)),
Payload
:
types
.
Encode
(
action
),
To
:
address
.
ExecAddress
(
types
.
ExecName
(
ExecutorName
)),
}
}
else
{
tx
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
types
.
ExecName
(
name
)),
Payload
:
types
.
Encode
(
action
),
To
:
address
.
ExecAddress
(
types
.
ExecName
(
name
)),
}
}
tx
,
err
:=
types
.
FormatTx
(
string
(
tx
.
Execer
),
tx
)
if
err
!=
nil
{
return
nil
,
err
}
return
tx
,
nil
}
func
createEvmTx
(
param
*
CreateCallTx
)
(
*
types
.
Transaction
,
error
)
{
func
createEvmTx
(
param
*
CreateCallTx
)
(
*
types
.
Transaction
,
error
)
{
if
param
==
nil
{
if
param
==
nil
{
elog
.
Error
(
"createEvmTx"
,
"param"
,
param
)
elog
.
Error
(
"createEvmTx"
,
"param"
,
param
)
...
@@ -194,7 +116,6 @@ func createEvmTx(param *CreateCallTx) (*types.Transaction, error) {
...
@@ -194,7 +116,6 @@ func createEvmTx(param *CreateCallTx) (*types.Transaction, error) {
// 调用格式判断规则:
// 调用格式判断规则:
// 十六进制格式默认使用原方式调用,其它格式,使用ABI方式调用
// 十六进制格式默认使用原方式调用,其它格式,使用ABI方式调用
// 为了方便区分,在ABI格式前加0x00000000
// 为了方便区分,在ABI格式前加0x00000000
bCode
,
err
:=
common
.
FromHex
(
param
.
Code
)
action
:=
&
EVMContractAction
{
action
:=
&
EVMContractAction
{
Amount
:
param
.
Amount
,
Amount
:
param
.
Amount
,
...
@@ -203,20 +124,42 @@ func createEvmTx(param *CreateCallTx) (*types.Transaction, error) {
...
@@ -203,20 +124,42 @@ func createEvmTx(param *CreateCallTx) (*types.Transaction, error) {
Note
:
param
.
Note
,
Note
:
param
.
Note
,
Alias
:
param
.
Alias
,
Alias
:
param
.
Alias
,
}
}
// Abi数据和二进制代码必须指定一个,优先判断ABI
if
param
.
IsCreate
{
if
len
(
param
.
Abi
)
>
0
{
action
.
Abi
=
strings
.
TrimSpace
(
param
.
Abi
)
}
else
{
bCode
,
err
:=
common
.
FromHex
(
param
.
Code
)
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"create evm
create Tx
"
,
"param.Code"
,
param
.
Code
)
elog
.
Error
(
"create evm
Tx error, code is invalid
"
,
"param.Code"
,
param
.
Code
)
return
nil
,
err
return
nil
,
err
}
}
action
.
Code
=
bCode
action
.
Code
=
bCode
}
if
param
.
IsCreate
{
return
createRawTx
(
action
,
""
)
return
createRawTx
(
action
,
""
)
}
else
{
if
err
!=
nil
{
elog
.
Info
(
"evm call data is invalid hex data, process it as abi data"
,
"param.Code"
,
param
.
Code
)
bCode
=
[]
byte
(
param
.
Code
)
bCode
=
append
(
ABICallPrefix
,
bCode
...
)
}
}
return
createRawTx
(
action
,
param
.
Name
)
return
createRawTx
(
action
,
param
.
Name
)
}
func
createRawTx
(
action
*
EVMContractAction
,
name
string
)
(
*
types
.
Transaction
,
error
)
{
tx
:=
&
types
.
Transaction
{}
if
len
(
name
)
==
0
{
tx
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
types
.
ExecName
(
ExecutorName
)),
Payload
:
types
.
Encode
(
action
),
To
:
address
.
ExecAddress
(
types
.
ExecName
(
ExecutorName
)),
}
}
else
{
tx
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
types
.
ExecName
(
name
)),
Payload
:
types
.
Encode
(
action
),
To
:
address
.
ExecAddress
(
types
.
ExecName
(
name
)),
}
}
}
tx
,
err
:=
types
.
FormatTx
(
string
(
tx
.
Execer
),
tx
)
if
err
!=
nil
{
return
nil
,
err
}
return
tx
,
nil
}
}
plugin/dapp/evm/types/evmcontract.pb.go
View file @
781721f6
This diff is collapsed.
Click to expand it.
plugin/dapp/evm/types/tx.go
View file @
781721f6
...
@@ -24,4 +24,6 @@ type CreateCallTx struct {
...
@@ -24,4 +24,6 @@ type CreateCallTx struct {
Name
string
`json:"name"`
Name
string
`json:"name"`
// IsCreate 是否创建合约
// IsCreate 是否创建合约
IsCreate
bool
`json:"isCreate"`
IsCreate
bool
`json:"isCreate"`
// Abi 创建合约或调用合约时附带的ABI数据
Abi
string
`json:"abi"`
}
}
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