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
bcdffcf1
Commit
bcdffcf1
authored
Dec 31, 2018
by
vipwzw
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add js test
parent
5a3e37b1
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
546 additions
and
142 deletions
+546
-142
const.go
plugin/dapp/js/executor/const.go
+100
-0
exec.go
plugin/dapp/js/executor/exec.go
+21
-10
exec_del_local.go
plugin/dapp/js/executor/exec_del_local.go
+7
-6
exec_local.go
plugin/dapp/js/executor/exec_local.go
+9
-4
js.go
plugin/dapp/js/executor/js.go
+33
-3
jsvm.go
plugin/dapp/js/executor/jsvm.go
+30
-42
jsvm_test.go
plugin/dapp/js/executor/jsvm_test.go
+81
-41
key.go
plugin/dapp/js/executor/key.go
+16
-0
js.proto
plugin/dapp/js/proto/js.proto
+5
-0
js.go
plugin/dapp/js/types/js.go
+9
-6
js.pb.go
plugin/dapp/js/types/jsproto/js.pb.go
+62
-22
util.go
vendor/github.com/33cn/chain33/system/dapp/util.go
+144
-6
const.go
vendor/github.com/33cn/chain33/types/const.go
+2
-0
db.proto
vendor/github.com/33cn/chain33/types/proto/db.proto
+2
-2
util.go
vendor/github.com/33cn/chain33/util/util.go
+25
-0
No files found.
plugin/dapp/js/executor/const.go
0 → 100644
View file @
bcdffcf1
package
executor
import
"errors"
//ErrInvalidFuncFormat 错误的函数调用格式(没有_)
var
errInvalidFuncFormat
=
errors
.
New
(
"chain33.js: invalid function name format"
)
//ErrInvalidFuncPrefix not exec_ execloal execdellocal
var
errInvalidFuncPrefix
=
errors
.
New
(
"chain33.js: invalid function prefix format"
)
//ErrFuncNotFound 函数没有找到
var
errFuncNotFound
=
errors
.
New
(
"chain33.js: invalid function name not found"
)
var
callcode
=
`
function kvcreator(dbtype) {
this.data = {}
this.kvs = []
this.logs = []
if (dbtype == "exec" || dbtype == "init") {
this.get = getstatedb
} else if (dbtype == "local") {
this.get = getlocaldb
this.list = listdb
}
}
kvcreator.prototype.add = function(k, v) {
var data = JSON.stringify(v)
this.data[k] = data
this.kvs.push({key:k, value: data})
}
kvcreator.prototype.get = function(k) {
var v
if (this.data[k]) {
v = this.data[k]
} else {
v = this.get(k)
}
if (!v) {
return null
}
return JSON.parse(v)
}
kvcreator.prototype.listvalue = function(prefix, key, count, direction) {
var values = this.list(prefix, key, count, direction)
if (!values || values.length == 0) {
return []
}
var objlist = []
for (var i = 0; i < values.length; i++) {
objlist.push(JSON.parse(values[i]))
}
return objlist
}
kvcreator.prototype.addlog = function(log) {
if (this.list) {
throw new Error("local or dellocal can't set log")
}
this.logs.push(JSON.stringify(log))
}
kvcreator.prototype.receipt = function() {
return {kvs: this.kvs, logs: this.logs}
}
function callcode(context, f, args, loglist) {
if (f == "init") {
return Init(context)
}
var farr = f.split("_", 2)
if (farr.length != 2) {
throw new Error("chain33.js: invalid function name format")
}
var prefix = farr[0]
var funcname = farr[1]
var runobj = {}
var logs = []
if (!Array.isArray(loglist)) {
throw new Error("chain33.js: loglist must be array")
}
for (var i = 0; i < loglist.length; i++) {
logs.push(JSON.parse(loglist[i]))
}
if (prefix == "exec") {
runobj = new Exec(JSON.parse(context))
} else if (prefix == "execlocal") {
runobj = new ExecLocal(JSON.parse(context), logs)
} else {
throw new Error("chain33.js: invalid function prefix format")
}
var arg = JSON.parse(args)
if (typeof runobj[funcname] != "function") {
throw new Error("chain33.js: invalid function name not found")
}
return runobj[funcname](arg)
}
`
plugin/dapp/js/executor/exec.go
View file @
bcdffcf1
package
executor
package
executor
import
(
import
(
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
ptypes
"github.com/33cn/plugin/plugin/dapp/js/types"
ptypes
"github.com/33cn/plugin/plugin/dapp/js/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
)
)
func
(
c
*
js
)
Exec_Create
(
payload
*
jsproto
.
Create
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
func
(
c
*
js
)
Exec_Create
(
payload
*
jsproto
.
Create
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
db
:=
c
.
GetStateDB
()
execer
:=
types
.
ExecName
(
"user.js."
+
payload
.
Name
)
_
,
err
:=
db
.
Get
(
calcCodeKey
(
payload
.
Name
))
kvc
:=
dapp
.
NewKVCreator
(
c
.
GetStateDB
(),
calcStatePrefix
([]
byte
(
execer
)),
nil
)
_
,
err
:=
kvc
.
GetNoPrefix
(
calcCodeKey
(
payload
.
Name
))
if
err
!=
nil
&&
err
!=
types
.
ErrNotFound
{
if
err
!=
nil
&&
err
!=
types
.
ErrNotFound
{
return
nil
,
err
return
nil
,
err
}
}
if
err
==
nil
{
if
err
==
nil
{
return
nil
,
ptypes
.
ErrDupName
return
nil
,
ptypes
.
ErrDupName
}
}
r
:=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
}
kvc
.
AddNoPrefix
(
calcCodeKey
(
payload
.
Name
),
[]
byte
(
payload
.
Code
))
//code must be utf-8 encoding
jsvalue
,
err
:=
c
.
callVM
(
"init"
,
&
jsproto
.
Call
{
Name
:
payload
.
Name
},
tx
,
index
,
nil
)
r
.
KV
=
append
(
r
.
KV
,
&
types
.
KeyValue
{
if
err
!=
nil
{
Key
:
calcCodeKey
(
payload
.
Name
),
Value
:
[]
byte
(
payload
.
Code
)})
return
nil
,
err
}
kvs
,
logs
,
err
:=
parseJsReturn
(
jsvalue
)
if
err
!=
nil
{
return
nil
,
err
}
kvc
.
AddList
(
kvs
)
r
:=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kvc
.
KVList
(),
Logs
:
logs
}
return
r
,
nil
return
r
,
nil
}
}
func
(
c
*
js
)
Exec_Call
(
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
func
(
c
*
js
)
Exec_Call
(
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
jsvalue
,
err
:=
c
.
callVM
(
"exec"
,
payload
,
tx
,
index
)
execer
:=
types
.
ExecName
(
"user.js."
+
payload
.
Name
)
kvc
:=
dapp
.
NewKVCreator
(
c
.
GetStateDB
(),
[]
byte
(
execer
),
nil
)
jsvalue
,
err
:=
c
.
callVM
(
"exec"
,
payload
,
tx
,
index
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
r
:=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
}
kvs
,
logs
,
err
:=
parseJsReturn
(
jsvalue
)
kvs
,
err
:=
parseKVS
(
jsvalue
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
r
.
KV
=
kvs
kvc
.
AddList
(
kvs
)
r
:=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kvc
.
KVList
(),
Logs
:
logs
}
return
r
,
nil
return
r
,
nil
}
}
plugin/dapp/js/executor/exec_del_local.go
View file @
bcdffcf1
package
executor
package
executor
import
(
import
(
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
)
)
...
@@ -10,15 +11,15 @@ func (c *js) ExecDelLocal_Create(payload *jsproto.Create, tx *types.Transaction,
...
@@ -10,15 +11,15 @@ func (c *js) ExecDelLocal_Create(payload *jsproto.Create, tx *types.Transaction,
}
}
func
(
c
*
js
)
ExecDelLocal_Call
(
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
func
(
c
*
js
)
ExecDelLocal_Call
(
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
jsvalue
,
err
:=
c
.
callVM
(
"execdellocal"
,
payload
,
tx
,
index
)
krollback
:=
calcRollbackKey
(
tx
.
Hash
())
kvc
:=
dapp
.
NewKVCreator
(
c
.
GetLocalDB
(),
calcLocalPrefix
(
tx
.
Execer
),
krollback
)
kvs
,
err
:=
kvc
.
GetRollbackKVList
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
kvc
.
AddKVListOnly
(
kvs
)
kvc
.
DelRollbackKV
()
r
:=
&
types
.
LocalDBSet
{}
r
:=
&
types
.
LocalDBSet
{}
kvs
,
err
:=
parseKVS
(
jsvalue
)
r
.
KV
=
kvc
.
KVList
()
if
err
!=
nil
{
return
nil
,
err
}
r
.
KV
=
kvs
return
r
,
nil
return
r
,
nil
}
}
plugin/dapp/js/executor/exec_local.go
View file @
bcdffcf1
package
executor
package
executor
import
(
import
(
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
)
)
...
@@ -10,15 +11,19 @@ func (c *js) ExecLocal_Create(payload *jsproto.Create, tx *types.Transaction, re
...
@@ -10,15 +11,19 @@ func (c *js) ExecLocal_Create(payload *jsproto.Create, tx *types.Transaction, re
}
}
func
(
c
*
js
)
ExecLocal_Call
(
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
func
(
c
*
js
)
ExecLocal_Call
(
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
jsvalue
,
err
:=
c
.
callVM
(
"execlocal"
,
payload
,
tx
,
index
)
k
:=
calcRollbackKey
(
tx
.
Hash
())
kvc
:=
dapp
.
NewKVCreator
(
c
.
GetLocalDB
(),
calcLocalPrefix
(
tx
.
Execer
),
k
)
jsvalue
,
err
:=
c
.
callVM
(
"execlocal"
,
payload
,
tx
,
index
,
receiptData
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
r
:=
&
types
.
LocalDBSet
{}
kvs
,
_
,
err
:=
parseJsReturn
(
jsvalue
)
kvs
,
err
:=
parseKVS
(
jsvalue
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
r
.
KV
=
kvs
kvc
.
AddList
(
kvs
)
kvc
.
AddRollbackKV
()
r
:=
&
types
.
LocalDBSet
{}
r
.
KV
=
kvc
.
KVList
()
return
r
,
nil
return
r
,
nil
}
}
plugin/dapp/js/executor/js.go
View file @
bcdffcf1
...
@@ -49,7 +49,8 @@ func (u *js) GetDriverName() string {
...
@@ -49,7 +49,8 @@ func (u *js) GetDriverName() string {
return
driverName
return
driverName
}
}
func
(
u
*
js
)
callVM
(
prefix
string
,
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
index
int
)
(
*
otto
.
Object
,
error
)
{
func
(
u
*
js
)
callVM
(
prefix
string
,
payload
*
jsproto
.
Call
,
tx
*
types
.
Transaction
,
index
int
,
receiptData
*
types
.
ReceiptData
)
(
*
otto
.
Object
,
error
)
{
vm
,
err
:=
u
.
createVM
(
tx
,
index
)
vm
,
err
:=
u
.
createVM
(
tx
,
index
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -59,10 +60,19 @@ func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction,
...
@@ -59,10 +60,19 @@ func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction,
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
loglist
,
err
:=
jslogs
(
receiptData
)
if
err
!=
nil
{
return
nil
,
err
}
vm
.
Set
(
"loglist"
,
loglist
)
vm
.
Set
(
"code"
,
code
)
vm
.
Set
(
"code"
,
code
)
vm
.
Set
(
"f"
,
prefix
+
"_"
+
payload
.
Funcname
)
if
prefix
==
"init"
{
vm
.
Set
(
"f"
,
"init"
)
}
else
{
vm
.
Set
(
"f"
,
prefix
+
"_"
+
payload
.
Funcname
)
}
vm
.
Set
(
"args"
,
payload
.
Args
)
vm
.
Set
(
"args"
,
payload
.
Args
)
callfunc
:=
"callcode(context, f, args)"
callfunc
:=
"callcode(context, f, args
, loglist
)"
jsvalue
,
err
:=
vm
.
Run
(
callcode
+
string
(
code
)
+
"
\n
"
+
callfunc
)
jsvalue
,
err
:=
vm
.
Run
(
callcode
+
string
(
code
)
+
"
\n
"
+
callfunc
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -73,6 +83,26 @@ func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction,
...
@@ -73,6 +83,26 @@ func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction,
return
jsvalue
.
Object
(),
nil
return
jsvalue
.
Object
(),
nil
}
}
func
jslogs
(
receiptData
*
types
.
ReceiptData
)
([]
string
,
error
)
{
data
:=
make
([]
string
,
0
)
if
receiptData
==
nil
{
return
data
,
nil
}
for
i
:=
0
;
i
<
len
(
receiptData
.
Logs
);
i
++
{
logitem
:=
receiptData
.
Logs
[
i
]
if
logitem
.
Ty
!=
ptypes
.
TyLogJs
{
continue
}
var
jslog
jsproto
.
JsLog
err
:=
types
.
Decode
(
logitem
.
Log
,
&
jslog
)
if
err
!=
nil
{
return
nil
,
err
}
data
=
append
(
data
,
jslog
.
Data
)
}
return
data
,
nil
}
func
(
u
*
js
)
getContext
(
tx
*
types
.
Transaction
,
index
int64
)
*
blockContext
{
func
(
u
*
js
)
getContext
(
tx
*
types
.
Transaction
,
index
int64
)
*
blockContext
{
return
&
blockContext
{
return
&
blockContext
{
Height
:
u
.
GetHeight
(),
Height
:
u
.
GetHeight
(),
...
...
plugin/dapp/js/executor/jsvm.go
View file @
bcdffcf1
...
@@ -6,44 +6,10 @@ import (
...
@@ -6,44 +6,10 @@ import (
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
ptypes
"github.com/33cn/plugin/plugin/dapp/js/types"
ptypes
"github.com/33cn/plugin/plugin/dapp/js/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
"github.com/robertkrimen/otto"
"github.com/robertkrimen/otto"
)
)
//ErrInvalidFuncFormat 错误的函数调用格式(没有_)
var
errInvalidFuncFormat
=
errors
.
New
(
"chain33.js: invalid function name format"
)
//ErrInvalidFuncPrefix not exec_ execloal execdellocal
var
errInvalidFuncPrefix
=
errors
.
New
(
"chain33.js: invalid function prefix format"
)
//ErrFuncNotFound 函数没有找到
var
errFuncNotFound
=
errors
.
New
(
"chain33.js: invalid function name not found"
)
var
callcode
=
`
function callcode(context, f, args) {
var farr = f.split("_", 2)
if (farr.length != 2) {
throw new Error("chain33.js: invalid function name format")
}
var prefix = farr[0]
var funcname = farr[1]
var runobj = {}
if (prefix == "exec") {
runobj = new Exec(JSON.parse(context))
} else if (prefix == "execlocal") {
runobj = new ExecLocal(JSON.parse(context))
} else if (prefix == "execdellocal") {
runobj = new ExecDelLocal(JSON.parse(context))
} else {
throw new Error("chain33.js: invalid function prefix format")
}
var arg = JSON.parse(args)
if (typeof runobj[funcname] != "function") {
throw new Error("chain33.js: invalid function name not found")
}
return runobj[funcname](arg)
}
`
type
blockContext
struct
{
type
blockContext
struct
{
Height
int64
`json:"height"`
Height
int64
`json:"height"`
Blocktime
int64
`json:"blocktime"`
Blocktime
int64
`json:"blocktime"`
...
@@ -65,30 +31,52 @@ type listdbReturn struct {
...
@@ -65,30 +31,52 @@ type listdbReturn struct {
Err
string
`json:"err"`
Err
string
`json:"err"`
}
}
func
parseKVS
(
jsvalue
*
otto
.
Object
)
(
kvlist
[]
*
types
.
KeyValue
,
err
error
)
{
func
parseJsReturn
(
jsvalue
*
otto
.
Object
)
(
kvlist
[]
*
types
.
KeyValue
,
logs
[]
*
types
.
ReceiptLog
,
err
error
)
{
//kvs
obj
,
err
:=
getObject
(
jsvalue
,
"kvs"
)
obj
,
err
:=
getObject
(
jsvalue
,
"kvs"
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
ptypes
.
ErrJsReturnKVSFormat
return
nil
,
nil
,
ptypes
.
ErrJsReturnKVSFormat
}
}
if
obj
.
Class
()
!=
"Array"
{
if
obj
.
Class
()
!=
"Array"
{
return
nil
,
ptypes
.
ErrJsReturnKVSFormat
return
nil
,
nil
,
ptypes
.
ErrJsReturnKVSFormat
}
}
size
,
err
:=
getInt
(
obj
,
"length"
)
size
,
err
:=
getInt
(
obj
,
"length"
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
nil
,
err
}
}
for
i
:=
0
;
i
<
int
(
size
);
i
++
{
for
i
:=
0
;
i
<
int
(
size
);
i
++
{
data
,
err
:=
getObject
(
obj
,
fmt
.
Sprint
(
i
))
data
,
err
:=
getObject
(
obj
,
fmt
.
Sprint
(
i
))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
nil
,
err
}
}
kv
,
err
:=
parseKV
(
data
)
kv
,
err
:=
parseKV
(
data
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
nil
,
err
}
}
kvlist
=
append
(
kvlist
,
kv
)
kvlist
=
append
(
kvlist
,
kv
)
}
}
return
kvlist
,
nil
//logs
obj
,
err
=
getObject
(
jsvalue
,
"logs"
)
if
err
!=
nil
{
return
nil
,
nil
,
ptypes
.
ErrJsReturnLogsFormat
}
if
obj
.
Class
()
!=
"Array"
{
return
nil
,
nil
,
ptypes
.
ErrJsReturnLogsFormat
}
size
,
err
=
getInt
(
obj
,
"length"
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
for
i
:=
0
;
i
<
int
(
size
);
i
++
{
data
,
err
:=
getString
(
obj
,
fmt
.
Sprint
(
i
))
if
err
!=
nil
{
return
nil
,
nil
,
err
}
l
:=
&
types
.
ReceiptLog
{
Ty
:
ptypes
.
TyLogJs
,
Log
:
types
.
Encode
(
&
jsproto
.
JsLog
{
Data
:
data
})}
logs
=
append
(
logs
,
l
)
}
return
kvlist
,
logs
,
nil
}
}
func
getString
(
data
*
otto
.
Object
,
key
string
)
(
string
,
error
)
{
func
getString
(
data
*
otto
.
Object
,
key
string
)
(
string
,
error
)
{
...
...
plugin/dapp/js/executor/jsvm_test.go
View file @
bcdffcf1
package
executor
package
executor
import
(
import
(
"encoding/json"
"strings"
"strings"
"testing"
"testing"
"time"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
"github.com/robertkrimen/otto"
"github.com/robertkrimen/otto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/assert"
)
)
var
jscode
=
`
var
jscode
=
`
function Exec(context) {
//数据结构设计
this.context = context
//kvlist [{key:"key1", value:"value1"},{key:"key2", value:"value2"}]
//log 设计 {json data}
function Init(context) {
this.kvc = new kvcreator("init")
this.context = context
this.kvc.add("action", "init")
this.kvc.add("context", this.context)
return this.kvc.receipt()
}
}
function ExecLocal(context) {
function Exec(context) {
this.kvc = new kvcreator("exec")
this.context = context
this.context = context
}
}
function ExecDelLocal(context) {
function ExecLocal(context, logs) {
this.kvc = new kvcreator("local")
this.context = context
this.context = context
this.logs = logs
}
}
Exec.prototype.hello = function(args) {
Exec.prototype.hello = function(args) {
return {args: args, action:"exec", context: this.context}
this.kvc.add("args", args)
this.kvc.add("action", "exec")
this.kvc.add("context", this.context)
this.kvc.addlog('{"key1": "value1"}')
this.kvc.addlog('{"key2": "value2"}')
return this.kvc.receipt()
}
}
ExecLocal.prototype.hello = function(args) {
ExecLocal.prototype.hello = function(args) {
return {args: args, action:"execlocal", context: this.context}
this.kvc.add("args", args)
this.kvc.add("action", "exec")
this.kvc.add("log", this.logs)
this.kvc.add("context", this.context)
return this.kvc.receipt()
}
}
`
func
initExec
(
ldb
db
.
DB
,
kvdb
db
.
KVDB
,
t
*
testing
.
T
)
*
js
{
e
:=
newjs
()
.
(
*
js
)
e
.
SetEnv
(
1
,
time
.
Now
()
.
Unix
(),
1
)
e
.
SetLocalDB
(
kvdb
)
e
.
SetStateDB
(
kvdb
)
ExecDelLocal.prototype.hello = function(args) {
c
,
tx
:=
createCodeTx
(
"test"
,
jscode
)
return {args: args, action:"execdellocal", context: this.context}
receipt
,
err
:=
e
.
Exec_Create
(
c
,
tx
,
0
)
assert
.
Nil
(
t
,
err
)
util
.
SaveKVList
(
ldb
,
receipt
.
KV
)
return
e
}
}
`
func
c
allJsFunc
(
context
*
blockContext
,
code
string
,
f
string
,
args
string
)
(
otto
.
Value
,
error
)
{
func
c
reateCodeTx
(
name
,
jscode
string
)
(
*
jsproto
.
Create
,
*
types
.
Transaction
)
{
data
,
err
:=
json
.
Marshal
(
context
)
data
:=
&
jsproto
.
Create
{
if
err
!=
nil
{
Code
:
jscode
,
return
otto
.
Value
{},
err
Name
:
name
,
}
}
vm
:=
otto
.
New
()
return
data
,
&
types
.
Transaction
{
Execer
:
[]
byte
(
"js"
),
Payload
:
types
.
Encode
(
data
)}
vm
.
Set
(
"context"
,
string
(
data
))
vm
.
Set
(
"code"
,
code
)
vm
.
Set
(
"f"
,
f
)
vm
.
Set
(
"args"
,
args
)
callfunc
:=
"callcode(context, f, args)"
return
vm
.
Run
(
callcode
+
code
+
"
\n
"
+
callfunc
)
}
}
func
callCodeTx
(
name
,
f
,
args
string
)
(
*
jsproto
.
Call
,
*
types
.
Transaction
)
{
data
:=
&
jsproto
.
Call
{
Funcname
:
f
,
Name
:
name
,
Args
:
args
,
}
return
data
,
&
types
.
Transaction
{
Execer
:
[]
byte
(
"js"
),
Payload
:
types
.
Encode
(
data
)}
}
func
TestCallcode
(
t
*
testing
.
T
)
{
func
TestCallcode
(
t
*
testing
.
T
)
{
value
,
err
:=
callJsFunc
(
&
blockContext
{
Height
:
1
},
jscode
,
"exec_hello"
,
`{"hello2":"world2"}`
)
dir
,
ldb
,
kvdb
:=
util
.
CreateTestDB
()
assert
.
Nil
(
t
,
err
)
defer
util
.
CloseTestDB
(
dir
,
ldb
)
assert
.
Equal
(
t
,
true
,
value
.
IsObject
())
e
:=
initExec
(
ldb
,
kvdb
,
t
)
action
,
err
:=
value
.
Object
()
.
Get
(
"action"
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
"exec"
,
action
.
String
())
args
,
err
:=
value
.
Object
()
.
Get
(
"args"
)
assert
.
Nil
(
t
,
err
)
arg
,
err
:=
args
.
Object
()
.
Get
(
"hello2"
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
"world2"
,
arg
.
String
())
context
,
err
:=
value
.
Object
()
.
Get
(
"context"
)
call
,
tx
:=
callCodeTx
(
"test"
,
"hello"
,
`{"hello":"world"}`
)
assert
.
Nil
(
t
,
err
)
receipt
,
err
:=
e
.
Exec_Call
(
call
,
tx
,
0
)
cvalue
,
err
:=
context
.
Object
()
.
Get
(
"height"
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
"1"
,
cvalue
.
String
())
util
.
SaveKVList
(
ldb
,
receipt
.
KV
)
util
.
PrintKV
(
receipt
.
KV
)
}
func
TestCallError
(
t
*
testing
.
T
)
{
dir
,
ldb
,
kvdb
:=
util
.
CreateTestDB
()
defer
util
.
CloseTestDB
(
dir
,
ldb
)
e
:=
initExec
(
ldb
,
kvdb
,
t
)
//test call error(invalid json input)
//test call error(invalid json input)
_
,
err
=
callJsFunc
(
&
blockContext
{
Height
:
1
},
jscode
,
"exec_hello"
,
`{hello2":"world2"}`
)
call
,
tx
:=
callCodeTx
(
"test"
,
"hello"
,
`{hello":"world"}`
)
_
,
err
:=
e
.
callVM
(
"exec"
,
call
,
tx
,
0
,
nil
)
_
,
ok
:=
err
.
(
*
otto
.
Error
)
_
,
ok
:=
err
.
(
*
otto
.
Error
)
assert
.
Equal
(
t
,
true
,
ok
)
assert
.
Equal
(
t
,
true
,
ok
)
assert
.
Equal
(
t
,
true
,
strings
.
Contains
(
err
.
Error
(),
"SyntaxError"
))
assert
.
Equal
(
t
,
true
,
strings
.
Contains
(
err
.
Error
(),
"SyntaxError"
))
_
,
err
=
callJsFunc
(
&
blockContext
{
Height
:
1
},
jscode
,
"hello"
,
`{"hello2":"world2"}`
)
call
,
tx
=
callCodeTx
(
"test"
,
"hello"
,
`{"hello":"world"}`
)
assert
.
Equal
(
t
,
true
,
strings
.
Contains
(
err
.
Error
(),
errInvalidFuncFormat
.
Error
()))
_
,
err
=
e
.
callVM
(
"hello"
,
call
,
tx
,
0
,
nil
)
_
,
err
=
callJsFunc
(
&
blockContext
{
Height
:
1
},
jscode
,
"hello_hello"
,
`{"hello2":"world2"}`
)
_
,
ok
=
err
.
(
*
otto
.
Error
)
assert
.
Equal
(
t
,
true
,
ok
)
assert
.
Equal
(
t
,
true
,
strings
.
Contains
(
err
.
Error
(),
errInvalidFuncPrefix
.
Error
()))
assert
.
Equal
(
t
,
true
,
strings
.
Contains
(
err
.
Error
(),
errInvalidFuncPrefix
.
Error
()))
_
,
err
=
callJsFunc
(
&
blockContext
{
Height
:
1
},
jscode
,
"exec_hello2"
,
`{"hello2":"world2"}`
)
call
,
tx
=
callCodeTx
(
"test"
,
"hello2"
,
`{"hello":"world"}`
)
_
,
err
=
e
.
callVM
(
"exec"
,
call
,
tx
,
0
,
nil
)
_
,
ok
=
err
.
(
*
otto
.
Error
)
assert
.
Equal
(
t
,
true
,
ok
)
assert
.
Equal
(
t
,
true
,
strings
.
Contains
(
err
.
Error
(),
errFuncNotFound
.
Error
()))
assert
.
Equal
(
t
,
true
,
strings
.
Contains
(
err
.
Error
(),
errFuncNotFound
.
Error
()))
}
}
plugin/dapp/js/executor/key.go
View file @
bcdffcf1
package
executor
package
executor
func
calcLocalPrefix
(
execer
[]
byte
)
[]
byte
{
s
:=
append
([]
byte
(
"LODB-"
),
execer
...
)
s
=
append
(
s
,
byte
(
'-'
))
return
s
}
func
calcStatePrefix
(
execer
[]
byte
)
[]
byte
{
s
:=
append
([]
byte
(
"mavl-"
),
execer
...
)
s
=
append
(
s
,
byte
(
'-'
))
return
s
}
func
calcCodeKey
(
name
string
)
[]
byte
{
func
calcCodeKey
(
name
string
)
[]
byte
{
return
append
([]
byte
(
"mavl-js-code-"
),
[]
byte
(
name
)
...
)
return
append
([]
byte
(
"mavl-js-code-"
),
[]
byte
(
name
)
...
)
}
}
func
calcRollbackKey
(
hash
[]
byte
)
[]
byte
{
return
append
([]
byte
(
"LODB-js-rollback-"
),
hash
...
)
}
plugin/dapp/js/proto/js.proto
View file @
bcdffcf1
...
@@ -21,3 +21,7 @@ message JsAction {
...
@@ -21,3 +21,7 @@ message JsAction {
}
}
int32
ty
=
3
;
int32
ty
=
3
;
}
}
message
JsLog
{
string
data
=
1
;
}
\ No newline at end of file
plugin/dapp/js/types/js.go
View file @
bcdffcf1
...
@@ -2,6 +2,7 @@ package types
...
@@ -2,6 +2,7 @@ package types
import
(
import
(
"errors"
"errors"
"reflect"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
...
@@ -15,8 +16,7 @@ const (
...
@@ -15,8 +16,7 @@ const (
//日志类型
//日志类型
const
(
const
(
TyLogJsCreate
=
iota
+
1
TyLogJs
=
10000
TyLogJsCall
)
)
var
(
var
(
...
@@ -24,7 +24,9 @@ var (
...
@@ -24,7 +24,9 @@ var (
"Create"
:
jsActionCreate
,
"Create"
:
jsActionCreate
,
"Call"
:
jsActionCall
,
"Call"
:
jsActionCall
,
}
}
logMap
=
map
[
int64
]
*
types
.
LogInfo
{}
logMap
=
map
[
int64
]
*
types
.
LogInfo
{
TyLogJs
:
{
Ty
:
reflect
.
TypeOf
(
jsproto
.
JsLog
{}),
Name
:
"TyLogJs"
},
}
)
)
//JsX 插件名字
//JsX 插件名字
...
@@ -32,9 +34,10 @@ var JsX = "js"
...
@@ -32,9 +34,10 @@ var JsX = "js"
//错误常量
//错误常量
var
(
var
(
ErrDupName
=
errors
.
New
(
"ErrDupName"
)
ErrDupName
=
errors
.
New
(
"ErrDupName"
)
ErrJsReturnNotObject
=
errors
.
New
(
"ErrJsReturnNotObject"
)
ErrJsReturnNotObject
=
errors
.
New
(
"ErrJsReturnNotObject"
)
ErrJsReturnKVSFormat
=
errors
.
New
(
"ErrJsReturnKVSFormat"
)
ErrJsReturnKVSFormat
=
errors
.
New
(
"ErrJsReturnKVSFormat"
)
ErrJsReturnLogsFormat
=
errors
.
New
(
"ErrJsReturnLogsFormat"
)
)
)
func
init
()
{
func
init
()
{
...
...
plugin/dapp/js/types/jsproto/js.pb.go
View file @
bcdffcf1
...
@@ -31,7 +31,7 @@ func (m *Create) Reset() { *m = Create{} }
...
@@ -31,7 +31,7 @@ func (m *Create) Reset() { *m = Create{} }
func
(
m
*
Create
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
m
*
Create
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
Create
)
ProtoMessage
()
{}
func
(
*
Create
)
ProtoMessage
()
{}
func
(
*
Create
)
Descriptor
()
([]
byte
,
[]
int
)
{
func
(
*
Create
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_js_2
6fa46fa936181bc
,
[]
int
{
0
}
return
fileDescriptor_js_2
5eaf89ab172ea83
,
[]
int
{
0
}
}
}
func
(
m
*
Create
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
func
(
m
*
Create
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
return
xxx_messageInfo_Create
.
Unmarshal
(
m
,
b
)
return
xxx_messageInfo_Create
.
Unmarshal
(
m
,
b
)
...
@@ -79,7 +79,7 @@ func (m *Call) Reset() { *m = Call{} }
...
@@ -79,7 +79,7 @@ func (m *Call) Reset() { *m = Call{} }
func
(
m
*
Call
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
m
*
Call
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
Call
)
ProtoMessage
()
{}
func
(
*
Call
)
ProtoMessage
()
{}
func
(
*
Call
)
Descriptor
()
([]
byte
,
[]
int
)
{
func
(
*
Call
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_js_2
6fa46fa936181bc
,
[]
int
{
1
}
return
fileDescriptor_js_2
5eaf89ab172ea83
,
[]
int
{
1
}
}
}
func
(
m
*
Call
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
func
(
m
*
Call
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
return
xxx_messageInfo_Call
.
Unmarshal
(
m
,
b
)
return
xxx_messageInfo_Call
.
Unmarshal
(
m
,
b
)
...
@@ -135,7 +135,7 @@ func (m *JsAction) Reset() { *m = JsAction{} }
...
@@ -135,7 +135,7 @@ func (m *JsAction) Reset() { *m = JsAction{} }
func
(
m
*
JsAction
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
m
*
JsAction
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
JsAction
)
ProtoMessage
()
{}
func
(
*
JsAction
)
ProtoMessage
()
{}
func
(
*
JsAction
)
Descriptor
()
([]
byte
,
[]
int
)
{
func
(
*
JsAction
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_js_2
6fa46fa936181bc
,
[]
int
{
2
}
return
fileDescriptor_js_2
5eaf89ab172ea83
,
[]
int
{
2
}
}
}
func
(
m
*
JsAction
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
func
(
m
*
JsAction
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
return
xxx_messageInfo_JsAction
.
Unmarshal
(
m
,
b
)
return
xxx_messageInfo_JsAction
.
Unmarshal
(
m
,
b
)
...
@@ -273,27 +273,67 @@ func _JsAction_OneofSizer(msg proto.Message) (n int) {
...
@@ -273,27 +273,67 @@ func _JsAction_OneofSizer(msg proto.Message) (n int) {
return
n
return
n
}
}
type
JsLog
struct
{
Data
string
`protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
}
func
(
m
*
JsLog
)
Reset
()
{
*
m
=
JsLog
{}
}
func
(
m
*
JsLog
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
JsLog
)
ProtoMessage
()
{}
func
(
*
JsLog
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_js_25eaf89ab172ea83
,
[]
int
{
3
}
}
func
(
m
*
JsLog
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
return
xxx_messageInfo_JsLog
.
Unmarshal
(
m
,
b
)
}
func
(
m
*
JsLog
)
XXX_Marshal
(
b
[]
byte
,
deterministic
bool
)
([]
byte
,
error
)
{
return
xxx_messageInfo_JsLog
.
Marshal
(
b
,
m
,
deterministic
)
}
func
(
dst
*
JsLog
)
XXX_Merge
(
src
proto
.
Message
)
{
xxx_messageInfo_JsLog
.
Merge
(
dst
,
src
)
}
func
(
m
*
JsLog
)
XXX_Size
()
int
{
return
xxx_messageInfo_JsLog
.
Size
(
m
)
}
func
(
m
*
JsLog
)
XXX_DiscardUnknown
()
{
xxx_messageInfo_JsLog
.
DiscardUnknown
(
m
)
}
var
xxx_messageInfo_JsLog
proto
.
InternalMessageInfo
func
(
m
*
JsLog
)
GetData
()
string
{
if
m
!=
nil
{
return
m
.
Data
}
return
""
}
func
init
()
{
func
init
()
{
proto
.
RegisterType
((
*
Create
)(
nil
),
"jsproto.Create"
)
proto
.
RegisterType
((
*
Create
)(
nil
),
"jsproto.Create"
)
proto
.
RegisterType
((
*
Call
)(
nil
),
"jsproto.Call"
)
proto
.
RegisterType
((
*
Call
)(
nil
),
"jsproto.Call"
)
proto
.
RegisterType
((
*
JsAction
)(
nil
),
"jsproto.JsAction"
)
proto
.
RegisterType
((
*
JsAction
)(
nil
),
"jsproto.JsAction"
)
}
proto
.
RegisterType
((
*
JsLog
)(
nil
),
"jsproto.JsLog"
)
}
func
init
()
{
proto
.
RegisterFile
(
"js.proto"
,
fileDescriptor_js_26fa46fa936181bc
)
}
func
init
()
{
proto
.
RegisterFile
(
"js.proto"
,
fileDescriptor_js_25eaf89ab172ea83
)
}
var
fileDescriptor_js_26fa46fa936181bc
=
[]
byte
{
// 199 bytes of a gzipped FileDescriptorProto
var
fileDescriptor_js_25eaf89ab172ea83
=
[]
byte
{
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0x4c
,
0x8e
,
0xcd
,
0xae
,
0x82
,
0x30
,
// 215 bytes of a gzipped FileDescriptorProto
0x10
,
0x85
,
0x81
,
0xcb
,
0xdf
,
0x1d
,
0x72
,
0xaf
,
0x49
,
0x57
,
0xc4
,
0x95
,
0xc1
,
0x8d
,
0x6e
,
0x88
,
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0x4c
,
0x8f
,
0xcf
,
0x4e
,
0x86
,
0x30
,
0xc1
,
0x27
,
0x50
,
0x36
,
0x84
,
0x65
,
0xdf
,
0xa0
,
0xd6
,
0x6a
,
0x24
,
0x95
,
0x1a
,
0x5a
,
0x4c
,
0x78
,
0x10
,
0xc4
,
0x3f
,
0x90
,
0x7f
,
0x2e
,
0x51
,
0x93
,
0x9e
,
0x88
,
0x5e
,
0x4c
,
0xbd
,
0xe8
,
0x85
,
0x18
,
0x7b
,
0xd3
,
0x81
,
0x80
,
0xbb
,
0xaf
,
0x73
,
0xbe
,
0xce
,
0x1c
,
0x88
,
0x1b
,
0x9d
,
0xbf
,
0x3a
,
0x65
,
0x7c
,
0x02
,
0xe5
,
0x42
,
0x88
,
0xa7
,
0xbe
,
0xc1
,
0x5a
,
0x2a
,
0x91
,
0x54
,
0x6a
,
0x68
,
0x31
,
0xe1
,
0x14
,
0x89
,
0x1a
,
0x8d
,
0x90
,
0x1d
,
0x20
,
0x2c
,
0x3b
,
0xc1
,
0x8c
,
0x20
,
0x04
,
0x7c
,
0xae
,
0xae
,
0xed
,
0x4d
,
0x17
,
0x84
,
0xef
,
0xf6
,
0xeb
,
0xce
,
0x74
,
0x67
,
0x16
,
0xb2
,
0xc1
,
0x96
,
0x3f
,
0x93
,
0x22
,
0x75
,
0x37
,
0xee
,
0xee
,
0x97
,
0x22
,
0xdb
,
0x59
,
0xcb
,
0x9e
,
0x22
,
0xf5
,
0xc6
,
0x99
,
0xe5
,
0x71
,
0x86
,
0xa5
,
0x83
,
0x25
,
0xe0
,
0xcf
,
0x90
,
0xd4
,
0x93
,
0x42
,
0xa7
,
0x18
,
0x83
,
0x48
,
0x9a
,
0xac
,
0x06
,
0xbf
,
0x64
,
0x52
,
0xce
,
0x99
,
0xbb
,
0x64
,
0x64
,
0x0d
,
0xf1
,
0xad
,
0x6f
,
0xf9
,
0xd7
,
0x4e
,
0x15
,
0xc1
,
0x7d
,
0xf0
,
0x78
,
0x29
,
0x88
,
0xfd
,
0x6c
,
0xc4
,
0x6f
,
0x55
,
0x84
,
0xeb
,
0xcc
,
0x9f
,
0xf9
,
0x6d
,
0x7d
,
0xd6
,
0xdd
,
0x75
,
0xfa
,
0x33
,
0xfa
,
0x96
,
0x33
,
0x0d
,
0x71
,
0xad
,
0x4f
,
0x33
,
0x6f
,
0x21
,
0xaa
,
0x51
,
0xeb
,
0x5d
,
0x0b
,
0x0e
,
0x8d
,
0xdd
,
0x42
,
0xf6
,
0x39
,
0x8f
,
0xf2
,
0xdc
,
0x3c
,
0x54
,
0x4b
,
0xf6
,
0x10
,
0x72
,
0x6c
,
0x82
,
0x1b
,
0x93
,
0x62
,
0x95
,
0x4f
,
0x1d
,
0xf3
,
0xec
,
0xcf
,
0xfe
,
0xf6
,
0x7e
,
0x9c
,
0x7a
,
0x5b
,
0x5c
,
0xac
,
0x7e
,
0xcf
,
0xdc
,
0x42
,
0xd6
,
0xda
,
0xb1
,
0x60
,
0xe5
,
0xd0
,
0x49
,
0x20
,
0x5b
,
0xf0
,
0x39
,
0x93
,
0x12
,
0x4f
,
0x24
,
0xc5
,
0xdf
,
0x22
,
0x57
,
0xe9
,
0xbe
,
0xcc
,
0xc8
,
0x9e
,
0x20
,
0x91
,
0xd4
,
0x84
,
0x36
,
0xe6
,
0xd5
,
0x4d
,
0xb9
,
0x75
,
0x32
,
0x29
,
0x2b
,
0x87
,
0x62
,
0x48
,
0xfe
,
0xc1
,
0x33
,
0x03
,
0x5e
,
0x0b
,
0xa8
,
0x67
,
0x86
,
0x73
,
0x2c
,
0xd7
,
0x82
,
0xcd
,
0x49
,
0x6c
,
0x06
,
0xf6
,
0x00
,
0x91
,
0x44
,
0xad
,
0x29
,
0x22
,
0xaf
,
0xae
,
0x04
,
0xc1
,
0x9b
,
0xc9
,
0x5e
,
0x5c
,
0x42
,
0x94
,
0x8f
,
0x9f
,
0x00
,
0x00
,
0x00
,
0xff
,
0xff
,
0x35
,
0x0e
,
0x23
,
0x6a
,
0xdd
,
0x9c
,
0x04
,
0x89
,
0xec
,
0x1a
,
0x42
,
0xb7
,
0x50
,
0x5a
,
0x2c
,
0x42
,
0xb7
,
0x5c
,
0xc0
,
0x76
,
0x0e
,
0x01
,
0x00
,
0x00
,
0xbc
,
0xa5
,
0x10
,
0xff
,
0xa2
,
0x9e
,
0x15
,
0xbf
,
0x83
,
0xb8
,
0xb5
,
0xef
,
0xa6
,
0xf7
,
0x8d
,
0x3a
,
0x74
,
0xf8
,
0x7f
,
0x81
,
0xe7
,
0x8f
,
0x84
,
0x36
,
0xbd
,
0xfc
,
0x05
,
0x00
,
0x00
,
0xff
,
0xff
,
0xdb
,
0x0d
,
0xa5
,
0xc0
,
0x2b
,
0x01
,
0x00
,
0x00
,
}
}
vendor/github.com/33cn/chain33/system/dapp/util.go
View file @
bcdffcf1
...
@@ -19,16 +19,61 @@ func HeightIndexStr(height, index int64) string {
...
@@ -19,16 +19,61 @@ func HeightIndexStr(height, index int64) string {
//KVCreator 创建KV的辅助工具
//KVCreator 创建KV的辅助工具
type
KVCreator
struct
{
type
KVCreator
struct
{
kvs
[]
*
types
.
KeyValue
kvs
[]
*
types
.
KeyValue
kvdb
db
.
KV
kvdb
db
.
KV
autorollback
bool
prefix
[]
byte
rollbackkey
[]
byte
rollbackkvs
[]
*
types
.
KeyValue
}
}
//NewKVCreator 创建创建者
//NewKVCreator 创建创建者
func
NewKVCreator
(
kv
db
.
KV
)
*
KVCreator
{
//注意: 自动回滚可能会严重影响系统性能
return
&
KVCreator
{
kvdb
:
kv
}
func
NewKVCreator
(
kv
db
.
KV
,
prefix
[]
byte
,
rollbackkey
[]
byte
)
*
KVCreator
{
return
&
KVCreator
{
kvdb
:
kv
,
prefix
:
prefix
,
rollbackkey
:
rollbackkey
,
autorollback
:
rollbackkey
!=
nil
,
}
}
func
(
c
*
KVCreator
)
addPrefix
(
key
[]
byte
)
[]
byte
{
newkey
:=
append
([]
byte
{},
c
.
prefix
...
)
return
append
(
newkey
,
key
...
)
}
}
func
(
c
*
KVCreator
)
add
(
key
,
value
[]
byte
,
set
bool
)
*
KVCreator
{
func
(
c
*
KVCreator
)
add
(
key
,
value
[]
byte
,
set
bool
)
*
KVCreator
{
if
c
.
prefix
!=
nil
{
key
=
c
.
addPrefix
(
key
)
}
return
c
.
addnoprefix
(
key
,
value
,
set
)
}
func
(
c
*
KVCreator
)
addnoprefix
(
key
,
value
[]
byte
,
set
bool
)
*
KVCreator
{
if
c
.
autorollback
{
prev
,
err
:=
c
.
kvdb
.
Get
(
key
)
//数据库发生错误,直接panic (再执行器中会recover)
if
err
!=
nil
&&
err
!=
types
.
ErrNotFound
{
panic
(
err
)
}
if
value
==
nil
{
//del
//不需要做任何处理, 也不用加入 kvs
if
err
==
types
.
ErrNotFound
{
return
c
}
rb
:=
&
types
.
KeyValue
{
Key
:
key
,
Value
:
prev
}
c
.
rollbackkvs
=
append
(
c
.
rollbackkvs
,
rb
)
}
else
{
if
err
==
types
.
ErrNotFound
{
//add
rb
:=
&
types
.
KeyValue
{
Key
:
key
}
c
.
rollbackkvs
=
append
(
c
.
rollbackkvs
,
rb
)
}
else
{
//update
rb
:=
&
types
.
KeyValue
{
Key
:
key
,
Value
:
prev
}
c
.
rollbackkvs
=
append
(
c
.
rollbackkvs
,
rb
)
}
}
}
c
.
kvs
=
append
(
c
.
kvs
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
value
})
c
.
kvs
=
append
(
c
.
kvs
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
value
})
if
set
{
if
set
{
c
.
kvdb
.
Set
(
key
,
value
)
c
.
kvdb
.
Set
(
key
,
value
)
...
@@ -36,17 +81,110 @@ func (c *KVCreator) add(key, value []byte, set bool) *KVCreator {
...
@@ -36,17 +81,110 @@ func (c *KVCreator) add(key, value []byte, set bool) *KVCreator {
return
c
return
c
}
}
//Get 从KV中获取 value
func
(
c
*
KVCreator
)
Get
(
key
[]
byte
)
([]
byte
,
error
)
{
if
c
.
prefix
!=
nil
{
newkey
:=
c
.
addPrefix
(
key
)
return
c
.
kvdb
.
Get
(
newkey
)
}
return
c
.
kvdb
.
Get
(
key
)
}
//GetNoPrefix 从KV中获取 value, 不自动添加前缀
func
(
c
*
KVCreator
)
GetNoPrefix
(
key
[]
byte
)
([]
byte
,
error
)
{
return
c
.
kvdb
.
Get
(
key
)
}
//Add add and set to kvdb
//Add add and set to kvdb
func
(
c
*
KVCreator
)
Add
(
key
,
value
[]
byte
)
*
KVCreator
{
func
(
c
*
KVCreator
)
Add
(
key
,
value
[]
byte
)
*
KVCreator
{
return
c
.
add
(
key
,
value
,
true
)
return
c
.
add
(
key
,
value
,
true
)
}
}
//AddKV only add KV
//AddNoPrefix 不自动添加prefix
func
(
c
*
KVCreator
)
AddKV
(
key
,
value
[]
byte
)
*
KVCreator
{
func
(
c
*
KVCreator
)
AddNoPrefix
(
key
,
value
[]
byte
)
*
KVCreator
{
return
c
.
addnoprefix
(
key
,
value
,
true
)
}
//AddList only add KVList
func
(
c
*
KVCreator
)
AddList
(
list
[]
*
types
.
KeyValue
)
*
KVCreator
{
for
_
,
kv
:=
range
list
{
c
.
add
(
kv
.
Key
,
kv
.
Value
,
true
)
}
return
c
}
//AddKVOnly only add KV(can't auto rollback)
func
(
c
*
KVCreator
)
AddKVOnly
(
key
,
value
[]
byte
)
*
KVCreator
{
if
c
.
autorollback
{
panic
(
"autorollback open, AddKVOnly not allow"
)
}
return
c
.
add
(
key
,
value
,
false
)
return
c
.
add
(
key
,
value
,
false
)
}
}
//AddKVListOnly only add KVList (can't auto rollback)
func
(
c
*
KVCreator
)
AddKVListOnly
(
list
[]
*
types
.
KeyValue
)
*
KVCreator
{
if
c
.
autorollback
{
panic
(
"autorollback open, AddKVListOnly not allow"
)
}
for
_
,
kv
:=
range
list
{
c
.
add
(
kv
.
Key
,
kv
.
Value
,
false
)
}
return
c
}
//KVList 读取所有的kv列表
//KVList 读取所有的kv列表
func
(
c
*
KVCreator
)
KVList
()
[]
*
types
.
KeyValue
{
func
(
c
*
KVCreator
)
KVList
()
[]
*
types
.
KeyValue
{
return
c
.
kvs
return
c
.
kvs
}
}
//AddRollbackKV 添加回滚数据到 KV
func
(
c
*
KVCreator
)
AddRollbackKV
()
{
v
:=
types
.
Encode
(
c
.
rollbackLog
())
c
.
kvs
=
append
(
c
.
kvs
,
&
types
.
KeyValue
{
Key
:
c
.
rollbackkey
,
Value
:
v
})
}
//DelRollbackKV 删除rollback kv
func
(
c
*
KVCreator
)
DelRollbackKV
()
{
c
.
kvs
=
append
(
c
.
kvs
,
&
types
.
KeyValue
{
Key
:
c
.
rollbackkey
})
}
//GetRollbackKVList 获取 rollback 到 Key and Vaue
func
(
c
*
KVCreator
)
GetRollbackKVList
()
([]
*
types
.
KeyValue
,
error
)
{
data
,
err
:=
c
.
kvdb
.
Get
(
c
.
rollbackkey
)
if
err
!=
nil
{
return
nil
,
err
}
var
rollbacklog
types
.
ReceiptLog
err
=
types
.
Decode
(
data
,
&
rollbacklog
)
if
err
!=
nil
{
return
nil
,
err
}
return
c
.
parseRollback
(
&
rollbacklog
)
}
//rollbackLog rollback log
func
(
c
*
KVCreator
)
rollbackLog
()
*
types
.
ReceiptLog
{
data
:=
types
.
Encode
(
&
types
.
LocalDBSet
{
KV
:
c
.
rollbackkvs
})
return
&
types
.
ReceiptLog
{
Ty
:
types
.
TyLogRollback
,
Log
:
data
}
}
//ParseRollback 解析rollback的数据
func
(
c
*
KVCreator
)
parseRollback
(
log
*
types
.
ReceiptLog
)
([]
*
types
.
KeyValue
,
error
)
{
var
data
types
.
LocalDBSet
if
log
.
Ty
!=
types
.
TyLogRollback
{
return
nil
,
types
.
ErrInvalidParam
}
err
:=
types
.
Decode
(
log
.
Log
,
&
data
)
if
err
!=
nil
{
return
nil
,
err
}
return
data
.
KV
,
nil
}
//AddToLogs add not empty log to logs
func
(
c
*
KVCreator
)
AddToLogs
(
logs
[]
*
types
.
ReceiptLog
)
[]
*
types
.
ReceiptLog
{
if
len
(
c
.
rollbackkvs
)
==
0
{
return
logs
}
return
append
(
logs
,
c
.
rollbackLog
())
}
vendor/github.com/33cn/chain33/types/const.go
View file @
bcdffcf1
...
@@ -100,6 +100,7 @@ const (
...
@@ -100,6 +100,7 @@ const (
TyLogExecActive
=
10
TyLogExecActive
=
10
TyLogGenesisTransfer
=
11
TyLogGenesisTransfer
=
11
TyLogGenesisDeposit
=
12
TyLogGenesisDeposit
=
12
TyLogRollback
=
13
)
)
//SystemLog 系统log日志
//SystemLog 系统log日志
...
@@ -116,6 +117,7 @@ var SystemLog = map[int64]*LogInfo{
...
@@ -116,6 +117,7 @@ var SystemLog = map[int64]*LogInfo{
TyLogExecActive
:
{
reflect
.
TypeOf
(
ReceiptExecAccountTransfer
{}),
"LogExecActive"
},
TyLogExecActive
:
{
reflect
.
TypeOf
(
ReceiptExecAccountTransfer
{}),
"LogExecActive"
},
TyLogGenesisTransfer
:
{
reflect
.
TypeOf
(
ReceiptAccountTransfer
{}),
"LogGenesisTransfer"
},
TyLogGenesisTransfer
:
{
reflect
.
TypeOf
(
ReceiptAccountTransfer
{}),
"LogGenesisTransfer"
},
TyLogGenesisDeposit
:
{
reflect
.
TypeOf
(
ReceiptAccountTransfer
{}),
"LogGenesisDeposit"
},
TyLogGenesisDeposit
:
{
reflect
.
TypeOf
(
ReceiptAccountTransfer
{}),
"LogGenesisDeposit"
},
TyLogRollback
:
{
reflect
.
TypeOf
(
LocalDBSet
{}),
"LogRollback"
},
}
}
//exec type
//exec type
...
...
vendor/github.com/33cn/chain33/types/proto/db.proto
View file @
bcdffcf1
...
@@ -108,4 +108,4 @@ message PruneData {
...
@@ -108,4 +108,4 @@ message PruneData {
//用于存储db Pool数据的Value
//用于存储db Pool数据的Value
message
StoreValuePool
{
message
StoreValuePool
{
repeated
bytes
values
=
1
;
repeated
bytes
values
=
1
;
}
}
\ No newline at end of file
\ No newline at end of file
vendor/github.com/33cn/chain33/util/util.go
View file @
bcdffcf1
...
@@ -17,6 +17,7 @@ import (
...
@@ -17,6 +17,7 @@ import (
"testing"
"testing"
"unicode"
"unicode"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db"
...
@@ -428,3 +429,27 @@ func CloseTestDB(dir string, dbm db.DB) {
...
@@ -428,3 +429,27 @@ func CloseTestDB(dir string, dbm db.DB) {
os
.
RemoveAll
(
dir
)
os
.
RemoveAll
(
dir
)
dbm
.
Close
()
dbm
.
Close
()
}
}
//SaveKVList 保存kvs to database
func
SaveKVList
(
kvdb
db
.
DB
,
kvs
[]
*
types
.
KeyValue
)
{
//printKV(kvs)
batch
:=
kvdb
.
NewBatch
(
true
)
for
i
:=
0
;
i
<
len
(
kvs
);
i
++
{
if
kvs
[
i
]
.
Value
==
nil
{
batch
.
Delete
(
kvs
[
i
]
.
Key
)
continue
}
batch
.
Set
(
kvs
[
i
]
.
Key
,
kvs
[
i
]
.
Value
)
}
err
:=
batch
.
Write
()
if
err
!=
nil
{
panic
(
err
)
}
}
//PrintKV 打印KVList
func
PrintKV
(
kvs
[]
*
types
.
KeyValue
)
{
for
i
:=
0
;
i
<
len
(
kvs
);
i
++
{
fmt
.
Printf
(
"KV %d %s(%s)
\n
"
,
i
,
string
(
kvs
[
i
]
.
Key
),
common
.
ToHex
(
kvs
[
i
]
.
Value
))
}
}
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