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
17ec8479
Commit
17ec8479
authored
Jan 06, 2019
by
vipwzw
Committed by
33cn
Jan 07, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix all test
parent
e23d2a79
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1171 additions
and
279 deletions
+1171
-279
1.html
plugin/dapp/js/executor/1.html
+7
-2
account.go
plugin/dapp/js/executor/account.go
+3
-3
const.go
plugin/dapp/js/executor/const.go
+449
-42
const_test.go
plugin/dapp/js/executor/const_test.go
+278
-0
exec_local.go
plugin/dapp/js/executor/exec_local.go
+5
-0
game.js
plugin/dapp/js/executor/game.js
+45
-48
gen.sh
plugin/dapp/js/executor/gen.sh
+16
-0
js.go
plugin/dapp/js/executor/js.go
+22
-19
jsvm_test.go
plugin/dapp/js/executor/jsvm_test.go
+7
-7
query.go
plugin/dapp/js/executor/query.go
+3
-0
rpc_test.go
plugin/dapp/js/executor/rpc_test.go
+98
-47
runtime.js
plugin/dapp/js/executor/runtime.js
+125
-36
table.go
plugin/dapp/js/executor/table.go
+92
-75
testnode.go
vendor/github.com/33cn/chain33/util/testnode/testnode.go
+21
-0
No files found.
plugin/dapp/js/executor/1.html
View file @
17ec8479
<script
src=
"runtime.js"
></script>
<script
src=
"
test
.js"
></script>
<script
src=
"
game
.js"
></script>
<script>
//demo database function
var
statedb
=
{}
...
...
@@ -34,11 +34,15 @@ function getstatedb(key) {
return
statedb
[
key
]
}
function
execname
()
{
return
"user.jsvm.test"
}
function
setstatedb
(
kvs
)
{
for
(
var
i
=
0
;
i
<
kvs
.
length
;
i
++
)
{
statedb
[
kvs
[
i
].
key
]
=
kvs
[
i
].
value
}
}
var
ret
=
callcode
(
"{}"
,
"exec
local_hello
"
,
"{}"
,
[])
var
ret
=
callcode
(
"{}"
,
"exec
_NewGame
"
,
"{}"
,
[])
console
.
log
(
ret
)
</script>
\ No newline at end of file
plugin/dapp/js/executor/account.go
View file @
17ec8479
...
...
@@ -282,7 +282,7 @@ func (u *js) execFrozenFunc(vm *otto.Otto) {
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
receipt
,
err
:=
acc
.
ExecFrozen
(
addr
ess
.
ExecAddress
(
execer
),
addr
,
amount
)
receipt
,
err
:=
acc
.
ExecFrozen
(
addr
,
address
.
ExecAddress
(
execer
)
,
amount
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -311,7 +311,7 @@ func (u *js) execActiveFunc(vm *otto.Otto) {
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
receipt
,
err
:=
acc
.
ExecActive
(
addr
ess
.
ExecAddress
(
execer
),
addr
,
amount
)
receipt
,
err
:=
acc
.
ExecActive
(
addr
,
address
.
ExecAddress
(
execer
)
,
amount
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -340,7 +340,7 @@ func (u *js) execDepositFunc(vm *otto.Otto) {
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
receipt
,
err
:=
acc
.
ExecDeposit
(
addr
ess
.
ExecAddress
(
execer
),
addr
,
amount
)
receipt
,
err
:=
acc
.
ExecDeposit
(
addr
,
address
.
ExecAddress
(
execer
)
,
amount
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
plugin/dapp/js/executor/const.go
View file @
17ec8479
...
...
@@ -3,14 +3,15 @@ package executor
var
callcode
=
`
var tojson = JSON.stringify
//table warp
function
t
able(kvc, config, defaultvalue) {
var ret = table_new(
config, defaultvalue
)
function
T
able(kvc, config, defaultvalue) {
var ret = table_new(
tojson(config), tojson(defaultvalue)
)
if (ret.err) {
throw new Error(ret.err)
}
this.kvc = kvc
this.id = ret.id
this.config = config
this.name = config["#tablename"]
this.defaultvalue = defaultvalue
}
...
...
@@ -18,7 +19,7 @@ function isstring(obj) {
return typeof obj === "string"
}
t
able.prototype.add = function(obj) {
T
able.prototype.add = function(obj) {
if (!isstring(obj)) {
obj = tojson(obj)
}
...
...
@@ -26,7 +27,35 @@ table.prototype.add = function(obj) {
return ret.err
}
table.prototype.replace = function(obj) {
Table.prototype.joinkey = function(left, right) {
return table_joinkey(left, right)
}
Table.prototype.get = function(key, row) {
return table_get(this.id, key, row)
}
Table.prototype.query = function(indexName, prefix, primaryKey, count, direction) {
if (!count) {
count = 20
}
if (!direction) {
direction = 0
}
if (!primaryKey) {
primaryKey = ""
}
if (!prefix) {
prefix = ""
}
if (!indexName) {
indexName = ""
}
var q = table_query(this.id, indexName, prefix, primaryKey, count, direction)
return tojson(q)
}
Table.prototype.replace = function(obj) {
if (!isstring(obj)) {
obj = tojson(obj)
}
...
...
@@ -34,7 +63,7 @@ table.prototype.replace = function(obj) {
return ret.err
}
t
able.prototype.del = function(obj) {
T
able.prototype.del = function(obj) {
if (!isstring(obj)) {
obj = tojson(obj)
}
...
...
@@ -42,7 +71,7 @@ table.prototype.del = function(obj) {
return ret.err
}
t
able.prototype.save = function() {
T
able.prototype.save = function() {
var ret = table_save(this.id)
if (!this.kvc) {
this.kvc.save(ret)
...
...
@@ -50,11 +79,67 @@ table.prototype.save = function() {
return ret
}
table.prototype.close = function() {
Table.prototype.close = function() {
var ret = table_close(this.id)
return ret.err
}
function JoinTable(lefttable, righttable, index) {
this.lefttable = lefttable
this.righttable = righttable
if (this.lefttable.kvc != this.righttable.kvc) {
throw new Error("the kvc of left and right must same")
}
this.index = index
var ret = new_join_table(this.lefttable.id, this.righttable.id, index)
if (ret.err) {
throw new Error(ret.err)
}
this.id = ret.id
this.kvc = this.lefttable.kvc
}
function print(obj) {
if (typeof obj === "string") {
console.log(obj)
return
}
console.log(tojson(obj))
}
JoinTable.prototype.save = function() {
var ret = table_save(this.id)
if (this.kvc) {
this.kvc.save(ret)
}
return ret
}
JoinTable.prototype.close = function() {
table_close(this.lefttable.id)
table_close(this.righttable.id)
var ret = table_close(this.id)
return ret.err
}
JoinTable.prototype.addlogs = function(data) {
var err
for (var i = 0; i < data.length; i++) {
if (data[i].format != "json") {
continue
}
var log = JSON.parse(data[i].log)
if (log.__type__ == this.lefttable.name) {
err = this.lefttable.replace(data[i].log)
throwerr(err)
}
if (log.__type__ == this.righttable.name) {
err = this.righttable.replace(data[i].log)
throwerr(err)
}
}
}
//account warp
function account(kvc, execer, symbol) {
this.execer = execer
...
...
@@ -64,7 +149,7 @@ function account(kvc, execer, symbol) {
account.prototype.genesisInit = function(addr, amount) {
var ret = genesis_init(this, addr, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -72,7 +157,7 @@ account.prototype.genesisInit = function(addr, amount) {
account.prototype.execGenesisInit = function(execer, addr, amount) {
var ret = genesis_init_exec(this, execer, addr, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -89,7 +174,7 @@ account.prototype.execGetBalance = function(execer, addr) {
//本合约转移资产,或者转移到其他合约,或者从其他合约取回资产
account.prototype.transfer = function(from, to, amount) {
var ret = transfer(this, from, to, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -97,7 +182,7 @@ account.prototype.transfer = function(from, to, amount) {
account.prototype.transferToExec = function(execer, from, amount) {
var ret = transfer_to_exec(this, execer, from, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -105,7 +190,7 @@ account.prototype.transferToExec = function(execer, from, amount) {
account.prototype.withdrawFromExec = function(execer, to, amount) {
var ret = withdraw(this, execer, to, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -114,7 +199,7 @@ account.prototype.withdrawFromExec = function(execer, to, amount) {
//管理其他合约的资产转移到这个合约中
account.prototype.execActive = function(execer, addr, amount) {
var ret = exec_active(this, execer, addr, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -122,7 +207,7 @@ account.prototype.execActive = function(execer, addr, amount) {
account.prototype.execFrozen = function(execer, addr, amount) {
var ret = exec_frozen(this, execer, addr, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -130,7 +215,7 @@ account.prototype.execFrozen = function(execer, addr, amount) {
account.prototype.execDeposit = function(execer, addr, amount) {
var ret = exec_deposit(this, execer, addr, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -138,7 +223,7 @@ account.prototype.execDeposit = function(execer, addr, amount) {
account.prototype.execWithdraw = function(execer, addr, amount) {
var ret = exec_withdraw(this, execer, addr, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
...
...
@@ -146,12 +231,47 @@ account.prototype.execWithdraw = function(execer, addr, amount) {
account.prototype.execTransfer = function(execer, from, to, amount) {
var ret = exec_transfer(this, execer, from, to, amount)
if (
!
this.kvc) {
if (this.kvc) {
this.kvc.save(ret)
}
return ret.err
}
//from frozen -> to active
account.prototype.execTransFrozenToActive = function(execer, from, to, amount) {
var err
err = this.execActive(execer, from, amount)
if (err) {
return err
}
return this.execTransfer(execer, from, to, amount)
}
//from frozen -> to frozen
account.prototype.execTransFrozenToFrozen = function(execer, from, to, amount) {
var err
err = this.execActive(execer, from, amount)
if (err) {
return err
}
err = this.execTransfer(execer, from, to, amount)
if (err) {
return err
}
return this.execFrozen(execer, to, amount)
}
account.prototype.execTransActiveToFrozen = function(execer, from, to, amount) {
var err
err = this.execTransfer(execer, from, to, amount)
if (err) {
return err
}
return this.execFrozen(execer, to, amount)
}
COINS = 100000000
function kvcreator(dbtype) {
this.data = {}
this.kvs = []
...
...
@@ -161,11 +281,11 @@ function kvcreator(dbtype) {
this.getloal = getlocaldb
this.list = listdb
if (dbtype == "exec" || dbtype == "init") {
this.get
= this.getstatedb
this.get
db = this.getstate
} else if (dbtype == "local") {
this.get
= this.getlocaldb
this.get
db = this.getlocal
} else if (dbtype == "query") {
this.get
= this.getlocaldb
this.get
db = this.getlocal
} else {
throw new Error("chain33.js: dbtype error")
}
...
...
@@ -184,8 +304,8 @@ kvcreator.prototype.get = function(k, prefix) {
if (this.data[k]) {
v = this.data[k]
} else {
var dbvalue = this.get
(k, !!prefix)
if (dbvalue.err
!= ""
) {
var dbvalue = this.getdb
(k, !!prefix)
if (dbvalue.err) {
return null
}
v = dbvalue.value
...
...
@@ -213,7 +333,7 @@ kvcreator.prototype.save = function(receipt) {
kvcreator.prototype.listvalue = function(prefix, key, count, direction) {
var dbvalues = this.list(prefix, key, count, direction)
if (dbvalues.err
!= ""
) {
if (dbvalues.err) {
return []
}
var values = dbvalues.value
...
...
@@ -247,6 +367,69 @@ kvcreator.prototype.receipt = function() {
return {kvs: this.kvs, logs: this.logs}
}
function GetExecName() {
var exec = execname()
if (exec.err) {
return ""
}
return exec.value
}
function ExecAddress(name) {
var addr = execaddress(name)
if (addr.err) {
return ""
}
console.log(addr.value)
return addr.value
}
function Sha256(data) {
var hash = sha256(data)
if (hash.err) {
return ""
}
return hash.value
}
function Exec(context) {
this.kvc = new kvcreator("exec")
this.context = context
this.name = GetExecName()
if (typeof ExecInit === "function") {
ExecInit.call(this)
}
}
Exec.prototype.txID = function() {
return this.context.height * 100000 + this.context.index
}
function ExecLocal(context, logs) {
this.kvc = new kvcreator("local")
this.context = context
this.logs = logs
this.name = GetExecName()
if (typeof ExecLocalInit === "function") {
ExecLocalInit.call(this)
}
}
function Query(context) {
this.kvc = new kvcreator("query")
this.context = context
this.name = GetExecName()
if (typeof QueryInit === "function") {
QueryInit.call(this)
}
}
function throwerr(err) {
if (err) {
throw new Error(err)
}
}
function callcode(context, f, args, loglist) {
if (f == "init") {
return Init(JSON.parse(context))
...
...
@@ -276,7 +459,7 @@ function callcode(context, f, args, loglist) {
}
var arg = JSON.parse(args)
if (typeof runobj[funcname] != "function") {
throw new Error("chain33.js: invalid function name not found
"
)
throw new Error("chain33.js: invalid function name not found
->" + funcname
)
}
return runobj[funcname](arg)
}
...
...
@@ -285,8 +468,6 @@ function callcode(context, f, args, loglist) {
`
var
jscode
=
`
//数据结构设计
//kvlist [{key:"key1", value:"value1"},{key:"key2", value:"value2"}]
//log 设计 {json data}
function Init(context) {
this.kvc = new kvcreator("init")
this.context = context
...
...
@@ -295,22 +476,6 @@ function Init(context) {
return this.kvc.receipt()
}
function Exec(context) {
this.kvc = new kvcreator("exec")
this.context = context
}
function ExecLocal(context, logs) {
this.kvc = new kvcreator("local")
this.context = context
this.logs = logs
}
function Query(context) {
this.kvc = new kvcreator("query")
this.context = context
}
Exec.prototype.hello = function(args) {
this.kvc.add("args", args)
this.kvc.add("action", "exec")
...
...
@@ -335,3 +500,245 @@ Query.prototype.hello = function(args) {
}
`
var
_
=
jscode
var
gamecode
=
`
//简单的猜数字游戏
//游戏规则: 庄家出一个 0 - 10 的数字 hash(随机数 + 9) (一共的赔偿金额) NewGame()
//用户可以猜这个数字,多个用户都可以猜测。 Guess()
//开奖 CloseGame()
function Init(context) {
this.kvc = new kvcreator("init")
this.context = context
return this.kvc.receipt()
}
var MIN_WAIT_BLOCK = 2
var RAND_MAX = 10
function ExecInit() {
this.acc = new account(this.kvc, "coins", "bty")
}
Exec.prototype.NewGame = function(args) {
var game = {__type__ : "game"}
game.gameid = this.txID()
game.height = this.context.height
game.randhash = args.randhash
game.bet = args.bet
game.hash = this.context.txhash
game.obet = game.bet
game.addr = this.context.from
game.status = 1 //open
//最大值是 9000万,否则js到 int 会溢出
if (game.bet < 10 * COINS || game.bet > 10000000 * COINS) {
throwerr("bet low than 10 or hight than 10000000")
}
if (this.kvc.get(game.randhash)) { //如果randhash 已经被使用了
throwerr("dup rand hash")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
throwerr(err)
this.kvc.add(game.gameid, game)
this.kvc.add(game.randhash, "ok")
this.kvc.addlog(game)
return this.kvc.receipt()
}
Exec.prototype.Guess = function(args) {
var match = {__type__ : "match"}
match.gameid = args.gameid
match.bet = args.bet
match.id = this.txID()
match.addr = this.context.from
match.hash = this.context.txhash
var game = this.kvc.get(match.gameid)
if (!game) {
throwerr("game id not found")
}
if (game.status != 1) {
throwerr("game status not open")
}
if (match.bet < 1 * COINS || match.bet > game.bet / RAND_MAX) {
throwerr("match bet litte than 1 or big than game.bet/10")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
throwerr(err)
this.kvc.add(match.id, match)
this.kvc.addlog(match)
return this.kvc.receipt()
}
Exec.prototype.CloseGame = function(args) {
var local = new MatchLocalTable(this.kvc)
var game = this.kvc.get(args.id)
if (!game) {
throwerr("game id not found")
}
var matches = local.getmath(args.id)
if (!matches) {
matches = []
}
var n = -1
for (var i = 0; i < RAND_MAX; i ++) {
if (sha256(args.randstr + i) == game.randhash) {
n = i
}
}
if (n == -1) {
throwerr("err rand str")
}
//必须可以让用户可以有一个区块的竞猜时间
if (this.context.height - game.height < MIN_WAIT_BLOCK) {
throwerr("close game must wait 2 block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
if (match.num == n) {
//不能随便添加辅助函数,因为可以被外界调用到,所以辅助函数都是传递 this
win(this, game, match)
} else {
fail(this, game, match)
}
}
if (game.bet > 0) {
var err = this.acc.execActive(this.name, game.addr, game.bet)
throwerr(err)
game.bet = 0
}
game.status = 2
this.kvc.add(game.gameid, game)
this.kvc.addlog(game)
return this.kvc.receipt()
}
function win(othis, game, match) {
var amount = (RAND_MAX - 1) * match.bet
if (game.bet - amount < 0) {
amount = game.bet
}
var err
if (amount > 0) {
err = this.acc.execTransFrozenToActive(othis.name, game.addr, match.addr, amount)
throwerr(err)
game.bet -= amount
}
err = othis.acc.execActive(match.addr, match.bet)
throwerr(err)
}
function fail(othis, game, match) {
var amount = match.bet
err = othis.acc.execTransFrozenToFrozen(othis.name, match.addr, game.addr, amount)
throwerr(err)
game.bet += amount
}
Exec.prototype.ForceCloseGame = function(args) {
var local = new MatchLocalTable(this.kvc)
var game = this.kvc.get(args.id)
if (!game) {
throwerr("game id not found")
}
var matches = local.getmath(args.id)
if (!matches) {
matches = []
}
if (this.context.height - game.height < 100) {
throwerr("force close game must wait 100 block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
win(this.kvc, game, match)
}
if (game.bet > 0) {
var err = this.acc.execActive(this.name, game.addr, game.bet)
throwerr(err)
game.bet = 0
}
game.status = 2
this.kvc.add(game.gameid, game)
this.kvc.addlog(game)
return this.kvc.receipt()
}
ExecLocal.prototype.NewGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
ExecLocal.prototype.Guess = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
ExecLocal.prototype.CloseGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
ExecLocal.prototype.ForceCloseGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
Query.prototype.ListGameByAddr = function(args) {
var local = GameLocalTable(this.kvc)
return local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
}
/*
game ->(1 : n) match
game.gameid -> primary
match.gameid -> fk
match.id -> primary
*/
function GameLocalTable(kvc) {
this.config = {
"#tablename" : "game",
"#primary" : "gameid",
"#db" : "localdb",
"gameid" : "%018d",
"status" : "%d",
"hash" : "%s",
"addr" : "%s",
}
this.defaultvalue = {
"gameid" : 0,
"status" : 0,
"hash" : "",
"addr" : "",
}
return new Table(kvc, this.config, this.defaultvalue)
}
function MatchLocalTable(kvc) {
this.config = {
"#tablename" : "match",
"#primary" : "id",
"#db" : "localdb",
"id" : "%018d",
"gameid" : "%018d",
"hash" : "%s",
"addr" : "%s",
}
this.defaultvalue = {
"id" : 0,
"gameid" : 0,
"hash" : "",
"addr" : "",
}
return new Table(kvc, this.config, this.defaultvalue)
}
function MatchGameTable(kvc) {
return new JoinTable(MatchLocalTable(kvc), GameLocalTable(kvc), "addr#status")
}`
var
_
=
gamecode
plugin/dapp/js/executor/const_test.go
0 → 100644
View file @
17ec8479
package
executor_test
var
jscode
=
`
//数据结构设计
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()
}
Exec.prototype.hello = function(args) {
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) {
this.kvc.add("args", args)
this.kvc.add("action", "execlocal")
this.kvc.add("log", this.logs)
this.kvc.add("context", this.context)
return this.kvc.receipt()
}
//return a json string
Query.prototype.hello = function(args) {
var obj = getlocaldb("context")
return tojson(obj)
}
`
var
_
=
jscode
var
gamecode
=
`
//简单的猜数字游戏
//游戏规则: 庄家出一个 0 - 10 的数字 hash(随机数 + 9) (一共的赔偿金额) NewGame()
//用户可以猜这个数字,多个用户都可以猜测。 Guess()
//开奖 CloseGame()
function Init(context) {
this.kvc = new kvcreator("init")
this.context = context
return this.kvc.receipt()
}
var MIN_WAIT_BLOCK = 2
var RAND_MAX = 10
function ExecInit() {
this.acc = new account(this.kvc, "coins", "bty")
}
Exec.prototype.NewGame = function(args) {
var game = {__type__ : "game"}
game.gameid = this.txID()
game.height = this.context.height
game.randhash = args.randhash
game.bet = args.bet
game.hash = this.context.txhash
game.obet = game.bet
game.addr = this.context.from
game.status = 1 //open
//最大值是 9000万,否则js到 int 会溢出
if (game.bet < 10 * COINS || game.bet > 10000000 * COINS) {
throwerr("bet low than 10 or hight than 10000000")
}
if (this.kvc.get(game.randhash)) { //如果randhash 已经被使用了
throwerr("dup rand hash")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
throwerr(err)
this.kvc.add(game.gameid, game)
this.kvc.add(game.randhash, "ok")
this.kvc.addlog(game)
return this.kvc.receipt()
}
Exec.prototype.Guess = function(args) {
var match = {__type__ : "match"}
match.gameid = args.gameid
match.bet = args.bet
match.id = this.txID()
match.addr = this.context.from
match.hash = this.context.txhash
var game = this.kvc.get(match.gameid)
if (!game) {
throwerr("game id not found")
}
if (game.status != 1) {
throwerr("game status not open")
}
if (match.bet < 1 * COINS || match.bet > game.bet / RAND_MAX) {
throwerr("match bet litte than 1 or big than game.bet/10")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
throwerr(err)
this.kvc.add(match.id, match)
this.kvc.addlog(match)
return this.kvc.receipt()
}
Exec.prototype.CloseGame = function(args) {
var local = new MatchLocalTable(this.kvc)
var game = this.kvc.get(args.id)
if (!game) {
throwerr("game id not found")
}
var matches = local.getmath(args.id)
if (!matches) {
matches = []
}
var n = -1
for (var i = 0; i < RAND_MAX; i ++) {
if (sha256(args.randstr + i) == game.randhash) {
n = i
}
}
if (n == -1) {
throwerr("err rand str")
}
//必须可以让用户可以有一个区块的竞猜时间
if (this.context.height - game.height < MIN_WAIT_BLOCK) {
throwerr("close game must wait 2 block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
if (match.num == n) {
//不能随便添加辅助函数,因为可以被外界调用到,所以辅助函数都是传递 this
win(this, game, match)
} else {
fail(this, game, match)
}
}
if (game.bet > 0) {
var err = this.acc.execActive(this.name, game.addr, game.bet)
throwerr(err)
game.bet = 0
}
game.status = 2
this.kvc.add(game.gameid, game)
this.kvc.addlog(game)
return this.kvc.receipt()
}
function win(othis, game, match) {
var amount = (RAND_MAX - 1) * match.bet
if (game.bet - amount < 0) {
amount = game.bet
}
var err
if (amount > 0) {
err = this.acc.execTransFrozenToActive(othis.name, game.addr, match.addr, amount)
throwerr(err)
game.bet -= amount
}
err = othis.acc.execActive(match.addr, match.bet)
throwerr(err)
}
function fail(othis, game, match) {
var amount = match.bet
err = othis.acc.execTransFrozenToFrozen(othis.name, match.addr, game.addr, amount)
throwerr(err)
game.bet += amount
}
Exec.prototype.ForceCloseGame = function(args) {
var local = new MatchLocalTable(this.kvc)
var game = this.kvc.get(args.id)
if (!game) {
throwerr("game id not found")
}
var matches = local.getmath(args.id)
if (!matches) {
matches = []
}
if (this.context.height - game.height < 100) {
throwerr("force close game must wait 100 block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
win(this.kvc, game, match)
}
if (game.bet > 0) {
var err = this.acc.execActive(this.name, game.addr, game.bet)
throwerr(err)
game.bet = 0
}
game.status = 2
this.kvc.add(game.gameid, game)
this.kvc.addlog(game)
return this.kvc.receipt()
}
ExecLocal.prototype.NewGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
ExecLocal.prototype.Guess = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
ExecLocal.prototype.CloseGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
ExecLocal.prototype.ForceCloseGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
}
Query.prototype.ListGameByAddr = function(args) {
var local = GameLocalTable(this.kvc)
return local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
}
/*
game ->(1 : n) match
game.gameid -> primary
match.gameid -> fk
match.id -> primary
*/
function GameLocalTable(kvc) {
this.config = {
"#tablename" : "game",
"#primary" : "gameid",
"#db" : "localdb",
"gameid" : "%018d",
"status" : "%d",
"hash" : "%s",
"addr" : "%s",
}
this.defaultvalue = {
"gameid" : 0,
"status" : 0,
"hash" : "",
"addr" : "",
}
return new Table(kvc, this.config, this.defaultvalue)
}
function MatchLocalTable(kvc) {
this.config = {
"#tablename" : "match",
"#primary" : "id",
"#db" : "localdb",
"id" : "%018d",
"gameid" : "%018d",
"hash" : "%s",
"addr" : "%s",
}
this.defaultvalue = {
"id" : 0,
"gameid" : 0,
"hash" : "",
"addr" : "",
}
return new Table(kvc, this.config, this.defaultvalue)
}
function MatchGameTable(kvc) {
return new JoinTable(MatchLocalTable(kvc), GameLocalTable(kvc), "addr#status")
}`
var
_
=
gamecode
plugin/dapp/js/executor/exec_local.go
View file @
17ec8479
package
executor
import
(
"fmt"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
ptypes
"github.com/33cn/plugin/plugin/dapp/js/types"
...
...
@@ -28,5 +30,8 @@ func (c *js) ExecLocal_Call(payload *jsproto.Call, tx *types.Transaction, receip
kvc
.
AddRollbackKV
()
r
:=
&
types
.
LocalDBSet
{}
r
.
KV
=
kvc
.
KVList
()
for
i
:=
0
;
i
<
len
(
r
.
KV
);
i
++
{
fmt
.
Println
(
string
(
r
.
KV
[
i
]
.
Key
))
}
return
r
,
nil
}
plugin/dapp/js/executor/game.js
View file @
17ec8479
...
...
@@ -11,17 +11,17 @@ function Init(context) {
var
MIN_WAIT_BLOCK
=
2
var
RAND_MAX
=
10
function
ExecInit
(
execthis
)
{
exec
this
.
acc
=
new
account
(
this
.
kvc
,
"coins"
,
"bty"
)
function
ExecInit
()
{
this
.
acc
=
new
account
(
this
.
kvc
,
"coins"
,
"bty"
)
}
Exec
.
prototype
.
NewGame
=
function
(
args
)
{
var
game
=
{
__type__
:
"game"
}
game
.
id
=
this
.
context
.
txhash
game
.
index
=
this
.
txID
()
game
.
gameid
=
this
.
txID
()
game
.
height
=
this
.
context
.
height
game
.
randhash
=
args
.
hash
game
.
randhash
=
args
.
rand
hash
game
.
bet
=
args
.
bet
game
.
hash
=
this
.
context
.
txhash
game
.
obet
=
game
.
bet
game
.
addr
=
this
.
context
.
from
game
.
status
=
1
//open
...
...
@@ -29,9 +29,13 @@ Exec.prototype.NewGame = function(args) {
if
(
game
.
bet
<
10
*
COINS
||
game
.
bet
>
10000000
*
COINS
)
{
throwerr
(
"bet low than 10 or hight than 10000000"
)
}
if
(
this
.
kvc
.
get
(
game
.
randhash
))
{
//如果randhash 已经被使用了
throwerr
(
"dup rand hash"
)
}
var
err
=
this
.
acc
.
execFrozen
(
this
.
name
,
this
.
context
.
from
,
game
.
bet
)
throwerr
(
err
)
this
.
kvc
.
add
(
game
.
id
,
game
)
this
.
kvc
.
add
(
game
.
gameid
,
game
)
this
.
kvc
.
add
(
game
.
randhash
,
"ok"
)
this
.
kvc
.
addlog
(
game
)
return
this
.
kvc
.
receipt
()
}
...
...
@@ -42,6 +46,7 @@ Exec.prototype.Guess = function(args) {
match
.
bet
=
args
.
bet
match
.
id
=
this
.
txID
()
match
.
addr
=
this
.
context
.
from
match
.
hash
=
this
.
context
.
txhash
var
game
=
this
.
kvc
.
get
(
match
.
gameid
)
if
(
!
game
)
{
throwerr
(
"game id not found"
)
...
...
@@ -97,29 +102,29 @@ Exec.prototype.CloseGame = function(args) {
game
.
bet
=
0
}
game
.
status
=
2
this
.
kvc
.
add
(
game
.
id
,
game
)
this
.
kvc
.
add
(
game
.
game
id
,
game
)
this
.
kvc
.
addlog
(
game
)
return
this
.
kvc
.
receipt
()
}
function
win
(
this
,
game
,
match
)
{
function
win
(
o
this
,
game
,
match
)
{
var
amount
=
(
RAND_MAX
-
1
)
*
match
.
bet
if
(
game
.
bet
-
amount
<
0
)
{
amount
=
game
.
bet
}
var
err
if
(
amount
>
0
)
{
err
=
this
.
acc
.
execTransFrozenToActive
(
this
.
name
,
game
.
addr
,
match
.
addr
,
amount
)
err
=
this
.
acc
.
execTransFrozenToActive
(
o
this
.
name
,
game
.
addr
,
match
.
addr
,
amount
)
throwerr
(
err
)
game
.
bet
-=
amount
}
err
=
this
.
acc
.
execActive
(
match
.
addr
,
match
.
bet
)
err
=
o
this
.
acc
.
execActive
(
match
.
addr
,
match
.
bet
)
throwerr
(
err
)
}
function
fail
(
this
,
game
,
match
)
{
function
fail
(
o
this
,
game
,
match
)
{
var
amount
=
match
.
bet
err
=
this
.
acc
.
execTransFrozenToFrozen
(
this
.
name
,
match
.
addr
,
game
.
addr
,
amount
)
err
=
othis
.
acc
.
execTransFrozenToFrozen
(
o
this
.
name
,
match
.
addr
,
game
.
addr
,
amount
)
throwerr
(
err
)
game
.
bet
+=
amount
}
...
...
@@ -147,47 +152,47 @@ Exec.prototype.ForceCloseGame = function(args) {
game
.
bet
=
0
}
game
.
status
=
2
this
.
kvc
.
add
(
game
.
id
,
game
)
this
.
kvc
.
add
(
game
.
game
id
,
game
)
this
.
kvc
.
addlog
(
game
)
return
this
.
kvc
.
receipt
()
}
ExecLocal
.
prototype
.
NewGame
=
function
(
args
)
{
var
local
=
new
MatchGameTable
(
this
.
kvc
)
local
.
add
(
this
.
logs
)
local
.
table
.
save
()
var
local
=
MatchGameTable
(
this
.
kvc
)
local
.
add
logs
(
this
.
logs
)
local
.
save
()
return
this
.
kvc
.
receipt
()
}
ExecLocal
.
prototype
.
Guess
=
function
(
args
)
{
var
local
=
new
MatchGameTable
(
this
.
kvc
)
local
.
add
(
this
.
logs
)
local
.
table
.
save
()
var
local
=
MatchGameTable
(
this
.
kvc
)
local
.
add
logs
(
this
.
logs
)
local
.
save
()
return
this
.
kvc
.
receipt
()
}
ExecLocal
.
prototype
.
CloseGame
=
function
(
args
)
{
var
local
=
new
MatchGameTable
(
this
.
kvc
)
local
.
add
(
this
.
logs
)
local
.
table
.
save
()
var
local
=
MatchGameTable
(
this
.
kvc
)
local
.
add
logs
(
this
.
logs
)
local
.
save
()
return
this
.
kvc
.
receipt
()
}
ExecLocal
.
prototype
.
ForceCloseGame
=
function
(
args
)
{
var
local
=
new
GameLocal
Table
(
this
.
kvc
)
local
.
add
(
this
.
logs
)
local
.
table
.
save
()
var
local
=
MatchGame
Table
(
this
.
kvc
)
local
.
add
logs
(
this
.
logs
)
local
.
save
()
return
this
.
kvc
.
receipt
()
}
Query
.
prototype
.
ListGameByAddr
=
function
(
args
)
{
var
local
=
new
GameLocalTable
(
this
.
kvc
)
return
local
.
query
(
args
)
var
local
=
GameLocalTable
(
this
.
kvc
)
return
local
.
query
(
"addr"
,
args
.
addr
,
args
.
primaryKey
,
args
.
count
,
args
.
direction
)
}
/*
game ->(1 : n) match
game.id -> primary
game.
game
id -> primary
match.gameid -> fk
match.id -> primary
...
...
@@ -195,19 +200,20 @@ match.id -> primary
function
GameLocalTable
(
kvc
)
{
this
.
config
=
{
"#tablename"
:
"game"
,
"#primary"
:
"id"
,
"#primary"
:
"
game
id"
,
"#db"
:
"localdb"
,
"id"
:
"%018d"
,
"
game
id"
:
"%018d"
,
"status"
:
"%d"
,
"hash"
:
"%s"
,
"addr"
:
"%s"
,
}
this
.
defaultvalue
=
{
"
id"
:
"0"
,
"
gameid"
:
0
,
"status"
:
0
,
"hash"
:
""
,
"addr"
:
""
,
}
this
.
kvc
=
kvc
this
.
table
=
new
Table
(
this
.
kvc
,
this
.
config
,
this
.
defaultvalue
)
return
new
Table
(
kvc
,
this
.
config
,
this
.
defaultvalue
)
}
function
MatchLocalTable
(
kvc
)
{
...
...
@@ -216,29 +222,19 @@ function MatchLocalTable(kvc) {
"#primary"
:
"id"
,
"#db"
:
"localdb"
,
"id"
:
"%018d"
,
"gameid"
:
"%s"
,
"gameid"
:
"%018d"
,
"hash"
:
"%s"
,
"addr"
:
"%s"
,
}
this
.
defaultvalue
=
{
"id"
:
0
,
"gameid"
:
0
,
"hash"
:
""
,
"addr"
:
""
,
}
this
.
kvc
=
kvc
this
.
table
=
new
Table
(
this
.
kvc
,
this
.
config
,
this
.
defaultvalue
)
return
new
Table
(
kvc
,
this
.
config
,
this
.
defaultvalue
)
}
function
MatchGameTable
(
kvc
)
{
this
.
left
=
MatchLocalTable
(
kvc
)
this
.
right
=
GameLocalTable
(
kvc
)
this
.
table
=
new
JoinTable
(
left
,
right
,
"addr#status"
)
}
MatchGameTable
.
prototype
.
add
=
function
(
data
)
{
if
(
data
.
__type__
==
"match"
)
{
this
.
left
.
table
.
replace
(
data
)
}
if
(
data
.
__type__
==
"game"
)
{
this
.
right
.
table
.
replace
(
data
)
}
return
new
JoinTable
(
MatchLocalTable
(
kvc
),
GameLocalTable
(
kvc
),
"addr#status"
)
}
\ No newline at end of file
plugin/dapp/js/executor/gen.sh
View file @
17ec8479
...
...
@@ -8,4 +8,19 @@
cat
"test.js"
printf
'`\n'
printf
'var _ = jscode\n'
printf
'var gamecode = `\n'
cat
"game.js"
printf
'`\n'
printf
'var _ = gamecode\n'
}
>
const.go
{
printf
'package executor_test\n\nvar jscode = `\n'
cat
"test.js"
printf
'`\n'
printf
'var _ = jscode\n'
printf
'var gamecode = `\n'
cat
"game.js"
printf
'`\n'
printf
'var _ = gamecode\n'
}
>
const_test.go
\ No newline at end of file
plugin/dapp/js/executor/js.go
View file @
17ec8479
...
...
@@ -3,7 +3,7 @@ package executor
import
(
"bytes"
"encoding/json"
"
fmt
"
"
sync
"
"sync/atomic"
"github.com/33cn/chain33/common"
...
...
@@ -28,7 +28,6 @@ func init() {
panic
(
err
)
}
execaddressFunc
(
basevm
)
registerTableFunc
(
basevm
)
sha256Func
(
basevm
)
}
...
...
@@ -49,7 +48,9 @@ func Init(name string, sub []byte) {
type
js
struct
{
drivers
.
DriverBase
prefix
[]
byte
prefix
[]
byte
globalTableHandle
sync
.
Map
globalHanldeID
int64
}
func
newjs
()
drivers
.
Driver
{
...
...
@@ -224,7 +225,7 @@ func (u *js) localdbFunc(vm *otto.Otto, name string) {
func
(
u
*
js
)
execnameFunc
(
vm
*
otto
.
Otto
,
name
string
)
{
vm
.
Set
(
"execname"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
return
okReturn
(
vm
,
types
.
ExecName
(
"user.
js
."
+
name
))
return
okReturn
(
vm
,
types
.
ExecName
(
"user.
"
+
ptypes
.
JsX
+
"
."
+
name
))
})
}
...
...
@@ -281,7 +282,7 @@ func (u *js) createVM(name string, tx *types.Transaction, index int) (*otto.Otto
u
.
listdbFunc
(
vm
,
name
)
u
.
execnameFunc
(
vm
,
name
)
u
.
registerAccountFunc
(
vm
)
u
.
new
TableFunc
(
vm
,
name
)
u
.
register
TableFunc
(
vm
,
name
)
return
vm
,
nil
}
...
...
@@ -360,26 +361,28 @@ func (u *js) Allow(tx *types.Transaction, index int) error {
return
types
.
ErrNotAllow
}
func
createKVObject
(
vm
*
otto
.
Otto
,
kvs
[]
*
types
.
KeyValue
)
otto
.
Value
{
obj
:=
newObjectString
(
vm
,
"([])"
)
func
createKVObject
(
vm
*
otto
.
Otto
,
kvs
[]
*
types
.
KeyValue
)
[]
interface
{}
{
data
:=
make
([]
interface
{},
len
(
kvs
)
)
for
i
:=
0
;
i
<
len
(
kvs
);
i
++
{
item
:=
newObject
(
vm
)
.
setValue
(
"key"
,
string
(
kvs
[
i
]
.
Key
))
item
.
setValue
(
"value"
,
string
(
kvs
[
i
]
.
Value
))
item
.
setValue
(
"prefix"
,
true
)
obj
.
setValue
(
fmt
.
Sprint
(
i
),
item
)
item
:=
make
(
map
[
string
]
interface
{})
item
[
"key"
]
=
string
(
kvs
[
i
]
.
Key
)
item
[
"value"
]
=
string
(
kvs
[
i
]
.
Value
)
item
[
"prefix"
]
=
true
data
[
i
]
=
item
}
return
obj
.
value
()
return
data
}
func
createLogsObject
(
vm
*
otto
.
Otto
,
logs
[]
*
types
.
ReceiptLog
)
otto
.
Value
{
obj
:=
newObjectString
(
vm
,
"([])"
)
func
createLogsObject
(
vm
*
otto
.
Otto
,
logs
[]
*
types
.
ReceiptLog
)
[]
interface
{}
{
data
:=
make
([]
interface
{},
len
(
logs
)
)
for
i
:=
0
;
i
<
len
(
logs
);
i
++
{
item
:=
newObject
(
vm
)
.
setValue
(
"ty"
,
logs
[
i
]
.
Ty
)
item
.
setValue
(
"log"
,
string
(
logs
[
i
]
.
Log
))
item
.
setValue
(
"format"
,
"proto"
)
obj
.
setValue
(
fmt
.
Sprint
(
i
),
item
)
item
:=
make
(
map
[
string
]
interface
{})
item
[
"ty"
]
=
logs
[
i
]
.
Ty
item
[
"log"
]
=
string
(
logs
[
i
]
.
Log
)
item
[
"format"
]
=
"proto"
data
[
i
]
=
item
}
return
obj
.
value
()
return
data
}
func
accountReturn
(
vm
*
otto
.
Otto
,
acc
*
types
.
Account
)
otto
.
Value
{
...
...
plugin/dapp/js/executor/jsvm_test.go
View file @
17ec8479
...
...
@@ -22,12 +22,12 @@ func init() {
Init
(
ptypes
.
JsX
,
nil
)
}
func
initExec
(
ldb
db
.
DB
,
kvdb
db
.
KVDB
,
t
assert
.
TestingT
)
*
js
{
func
initExec
(
ldb
db
.
DB
,
kvdb
db
.
KVDB
,
code
string
,
t
assert
.
TestingT
)
*
js
{
e
:=
newjs
()
.
(
*
js
)
e
.
SetEnv
(
1
,
time
.
Now
()
.
Unix
(),
1
)
e
.
SetLocalDB
(
kvdb
)
e
.
SetStateDB
(
kvdb
)
c
,
tx
:=
createCodeTx
(
"test"
,
js
code
)
c
,
tx
:=
createCodeTx
(
"test"
,
code
)
receipt
,
err
:=
e
.
Exec_Create
(
c
,
tx
,
0
)
assert
.
Nil
(
t
,
err
)
util
.
SaveKVList
(
ldb
,
receipt
.
KV
)
...
...
@@ -54,7 +54,7 @@ func callCodeTx(name, f, args string) (*jsproto.Call, *types.Transaction) {
func
TestCallcode
(
t
*
testing
.
T
)
{
dir
,
ldb
,
kvdb
:=
util
.
CreateTestDB
()
defer
util
.
CloseTestDB
(
dir
,
ldb
)
e
:=
initExec
(
ldb
,
kvdb
,
t
)
e
:=
initExec
(
ldb
,
kvdb
,
jscode
,
t
)
call
,
tx
:=
callCodeTx
(
"test"
,
"hello"
,
`{"hello":"world"}`
)
receipt
,
err
:=
e
.
Exec_Call
(
call
,
tx
,
0
)
...
...
@@ -107,7 +107,7 @@ func TestCallcode(t *testing.T) {
func
TestCallError
(
t
*
testing
.
T
)
{
dir
,
ldb
,
kvdb
:=
util
.
CreateTestDB
()
defer
util
.
CloseTestDB
(
dir
,
ldb
)
e
:=
initExec
(
ldb
,
kvdb
,
t
)
e
:=
initExec
(
ldb
,
kvdb
,
jscode
,
t
)
//test call error(invalid json input)
call
,
tx
:=
callCodeTx
(
"test"
,
"hello"
,
`{hello":"world"}`
)
_
,
err
:=
e
.
callVM
(
"exec"
,
call
,
tx
,
0
,
nil
)
...
...
@@ -132,7 +132,7 @@ func TestCallError(t *testing.T) {
func
TestBigInt
(
t
*
testing
.
T
)
{
dir
,
ldb
,
kvdb
:=
util
.
CreateTestDB
()
defer
util
.
CloseTestDB
(
dir
,
ldb
)
e
:=
initExec
(
ldb
,
kvdb
,
t
)
e
:=
initExec
(
ldb
,
kvdb
,
jscode
,
t
)
//test call error(invalid json input)
s
:=
fmt
.
Sprintf
(
`{"balance":%d,"balance1":%d,"balance2":%d,"balance3":%d}`
,
math
.
MaxInt64
,
math
.
MinInt64
,
9007199254740990
,
-
9007199254740990
)
call
,
tx
:=
callCodeTx
(
"test"
,
"hello"
,
s
)
...
...
@@ -146,7 +146,7 @@ func TestBigInt(t *testing.T) {
func
BenchmarkBigInt
(
b
*
testing
.
B
)
{
dir
,
ldb
,
kvdb
:=
util
.
CreateTestDB
()
defer
util
.
CloseTestDB
(
dir
,
ldb
)
e
:=
initExec
(
ldb
,
kvdb
,
b
)
e
:=
initExec
(
ldb
,
kvdb
,
jscode
,
b
)
//test call error(invalid json input)
s
:=
fmt
.
Sprintf
(
`{"balance":%d,"balance1":%d,"balance2":%d,"balance3":%d}`
,
math
.
MaxInt64
,
math
.
MinInt64
,
9007199254740990
,
-
9007199254740990
)
call
,
tx
:=
callCodeTx
(
"test"
,
"hello"
,
s
)
...
...
@@ -184,7 +184,7 @@ func TestCalcLocalPrefix(t *testing.T) {
func
TestCacheMemUsage
(
t
*
testing
.
T
)
{
dir
,
ldb
,
kvdb
:=
util
.
CreateTestDB
()
defer
util
.
CloseTestDB
(
dir
,
ldb
)
e
:=
initExec
(
ldb
,
kvdb
,
t
)
e
:=
initExec
(
ldb
,
kvdb
,
jscode
,
t
)
vm
,
err
:=
e
.
createVM
(
"test"
,
nil
,
0
)
assert
.
Nil
(
t
,
err
)
vms
:=
make
([]
*
otto
.
Otto
,
1024
)
...
...
plugin/dapp/js/executor/query.go
View file @
17ec8479
...
...
@@ -4,10 +4,13 @@ import (
"fmt"
"github.com/33cn/chain33/types"
ptypes
"github.com/33cn/plugin/plugin/dapp/js/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
)
func
(
c
*
js
)
Query_Query
(
payload
*
jsproto
.
Call
)
(
types
.
Message
,
error
)
{
execer
:=
types
.
ExecName
(
"user."
+
ptypes
.
JsX
+
"."
+
payload
.
Name
)
c
.
prefix
=
calcLocalPrefix
([]
byte
(
execer
))
jsvalue
,
err
:=
c
.
callVM
(
"query"
,
payload
,
nil
,
0
,
nil
)
if
err
!=
nil
{
fmt
.
Println
(
"query"
,
err
)
...
...
plugin/dapp/js/executor/rpc_test.go
View file @
17ec8479
package
executor_test
import
(
"fmt"
"math/rand"
"testing"
"time"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
rpctypes
"github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/testnode"
...
...
@@ -14,6 +19,10 @@ import (
_
"github.com/33cn/plugin/plugin"
)
func
init
()
{
rand
.
Seed
(
time
.
Now
()
.
UnixNano
())
}
func
TestJsVM
(
t
*
testing
.
T
)
{
mocker
:=
testnode
.
New
(
"--free--"
,
nil
)
defer
mocker
.
Close
()
...
...
@@ -75,53 +84,95 @@ func TestJsVM(t *testing.T) {
t
.
Log
(
queryresult
.
Data
)
}
var
jscode
=
`
//数据结构设计
//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 Exec(context) {
this.kvc = new kvcreator("exec")
this.context = context
}
function ExecLocal(context, logs) {
this.kvc = new kvcreator("local")
this.context = context
this.logs = logs
}
function Query(context) {
this.kvc = new kvcreator("query")
this.context = context
}
Exec.prototype.hello = function(args) {
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()
}
func
TestJsGame
(
t
*
testing
.
T
)
{
contractName
:=
"test1"
mocker
:=
testnode
.
New
(
"--free--"
,
nil
)
defer
mocker
.
Close
()
mocker
.
Listen
()
err
:=
mocker
.
SendHot
()
assert
.
Nil
(
t
,
err
)
//开始部署合约, 测试阶段任何人都可以部署合约
//后期需要加上权限控制
//1. 部署合约
create
:=
&
jsproto
.
Create
{
Code
:
gamecode
,
Name
:
contractName
,
}
req
:=
&
rpctypes
.
CreateTxIn
{
Execer
:
ptypes
.
JsX
,
ActionName
:
"Create"
,
Payload
:
types
.
MustPBToJSON
(
create
),
}
var
txhex
string
err
=
mocker
.
GetJSONC
()
.
Call
(
"Chain33.CreateTransaction"
,
req
,
&
txhex
)
assert
.
Nil
(
t
,
err
)
hash
,
err
:=
mocker
.
SendAndSign
(
mocker
.
GetHotKey
(),
txhex
)
assert
.
Nil
(
t
,
err
)
txinfo
,
err
:=
mocker
.
WaitTx
(
hash
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
txinfo
.
Receipt
.
Ty
,
int32
(
2
))
block
:=
mocker
.
GetLastBlock
()
balance
:=
mocker
.
GetAccount
(
block
.
StateHash
,
mocker
.
GetHotAddress
())
.
Balance
assert
.
Equal
(
t
,
balance
,
10000
*
types
.
Coin
)
//2.1 充值到合约
reqtx
:=
&
rpctypes
.
CreateTx
{
To
:
address
.
ExecAddress
(
"user.jsvm."
+
contractName
),
Amount
:
100
*
types
.
Coin
,
Note
:
"12312"
,
IsWithdraw
:
false
,
IsToken
:
false
,
TokenSymbol
:
""
,
ExecName
:
"user.jsvm."
+
contractName
,
}
err
=
mocker
.
GetJSONC
()
.
Call
(
"Chain33.CreateRawTransaction"
,
reqtx
,
&
txhex
)
assert
.
Nil
(
t
,
err
)
hash
,
err
=
mocker
.
SendAndSign
(
mocker
.
GetHotKey
(),
txhex
)
assert
.
Nil
(
t
,
err
)
txinfo
,
err
=
mocker
.
WaitTx
(
hash
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
txinfo
.
Receipt
.
Ty
,
int32
(
2
))
block
=
mocker
.
GetLastBlock
()
balance
=
mocker
.
GetExecAccount
(
block
.
StateHash
,
"user.jsvm."
+
contractName
,
mocker
.
GetHotAddress
())
.
Balance
assert
.
Equal
(
t
,
100
*
types
.
Coin
,
balance
)
//2.2 调用 hello 函数(随机数,用nonce)
privhash
:=
common
.
Sha256
(
mocker
.
GetHotKey
()
.
Bytes
())
nonce
:=
rand
.
Int63
()
num
:=
rand
.
Int63
()
%
10
realhash
:=
common
.
Sha256
([]
byte
(
string
(
privhash
)
+
":"
+
fmt
.
Sprint
(
nonce
)))
myhash
:=
common
.
ToHex
(
common
.
Sha256
([]
byte
(
string
(
realhash
)
+
fmt
.
Sprint
(
num
))))
ExecLocal.prototype.hello = function(args) {
this.kvc.add("args", args)
this.kvc.add("action", "execlocal")
this.kvc.add("log", this.logs)
this.kvc.add("context", this.context)
return this.kvc.receipt()
}
call
:=
&
jsproto
.
Call
{
Funcname
:
"NewGame"
,
Name
:
contractName
,
Args
:
fmt
.
Sprintf
(
`{"bet": %d, "randhash" : "%s"}`
,
100
*
types
.
Coin
,
myhash
),
}
req
=
&
rpctypes
.
CreateTxIn
{
Execer
:
"user."
+
ptypes
.
JsX
+
"."
+
contractName
,
ActionName
:
"Call"
,
Payload
:
types
.
MustPBToJSON
(
call
),
}
err
=
mocker
.
GetJSONC
()
.
Call
(
"Chain33.CreateTransaction"
,
req
,
&
txhex
)
assert
.
Nil
(
t
,
err
)
t
.
Log
(
mocker
.
GetHotAddress
())
hash
,
err
=
mocker
.
SendAndSignNonce
(
mocker
.
GetHotKey
(),
txhex
,
nonce
)
assert
.
Nil
(
t
,
err
)
txinfo
,
err
=
mocker
.
WaitTx
(
hash
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
txinfo
.
Receipt
.
Ty
,
int32
(
2
))
//return a json string
Query.prototype.hello = function(args) {
return tojson({hello:"wzw"})
//3. query 函数查询
call
=
&
jsproto
.
Call
{
Funcname
:
"ListGameByAddr"
,
Name
:
contractName
,
Args
:
fmt
.
Sprintf
(
`{"addr":"%s", "count" : 20}`
,
txinfo
.
Tx
.
From
),
}
query
:=
&
rpctypes
.
Query4Jrpc
{
Execer
:
"user."
+
ptypes
.
JsX
+
"."
+
contractName
,
FuncName
:
"Query"
,
Payload
:
types
.
MustPBToJSON
(
call
),
}
var
queryresult
jsproto
.
QueryResult
err
=
mocker
.
GetJSONC
()
.
Call
(
"Chain33.Query"
,
query
,
&
queryresult
)
assert
.
Nil
(
t
,
err
)
t
.
Log
(
queryresult
.
Data
)
}
`
plugin/dapp/js/executor/runtime.js
View file @
17ec8479
var
tojson
=
JSON
.
stringify
//table warp
function
t
able
(
kvc
,
config
,
defaultvalue
)
{
var
ret
=
table_new
(
config
,
defaultvalue
)
function
T
able
(
kvc
,
config
,
defaultvalue
)
{
var
ret
=
table_new
(
tojson
(
config
),
tojson
(
defaultvalue
)
)
if
(
ret
.
err
)
{
throw
new
Error
(
ret
.
err
)
}
this
.
kvc
=
kvc
this
.
id
=
ret
.
id
this
.
config
=
config
this
.
name
=
config
[
"#tablename"
]
this
.
defaultvalue
=
defaultvalue
}
...
...
@@ -15,7 +16,7 @@ function isstring(obj) {
return
typeof
obj
===
"string"
}
t
able
.
prototype
.
add
=
function
(
obj
)
{
T
able
.
prototype
.
add
=
function
(
obj
)
{
if
(
!
isstring
(
obj
))
{
obj
=
tojson
(
obj
)
}
...
...
@@ -23,7 +24,35 @@ table.prototype.add = function(obj) {
return
ret
.
err
}
table
.
prototype
.
replace
=
function
(
obj
)
{
Table
.
prototype
.
joinkey
=
function
(
left
,
right
)
{
return
table_joinkey
(
left
,
right
)
}
Table
.
prototype
.
get
=
function
(
key
,
row
)
{
return
table_get
(
this
.
id
,
key
,
row
)
}
Table
.
prototype
.
query
=
function
(
indexName
,
prefix
,
primaryKey
,
count
,
direction
)
{
if
(
!
count
)
{
count
=
20
}
if
(
!
direction
)
{
direction
=
0
}
if
(
!
primaryKey
)
{
primaryKey
=
""
}
if
(
!
prefix
)
{
prefix
=
""
}
if
(
!
indexName
)
{
indexName
=
""
}
var
q
=
table_query
(
this
.
id
,
indexName
,
prefix
,
primaryKey
,
count
,
direction
)
return
tojson
(
q
)
}
Table
.
prototype
.
replace
=
function
(
obj
)
{
if
(
!
isstring
(
obj
))
{
obj
=
tojson
(
obj
)
}
...
...
@@ -31,7 +60,7 @@ table.prototype.replace = function(obj) {
return
ret
.
err
}
t
able
.
prototype
.
del
=
function
(
obj
)
{
T
able
.
prototype
.
del
=
function
(
obj
)
{
if
(
!
isstring
(
obj
))
{
obj
=
tojson
(
obj
)
}
...
...
@@ -39,7 +68,7 @@ table.prototype.del = function(obj) {
return
ret
.
err
}
t
able
.
prototype
.
save
=
function
()
{
T
able
.
prototype
.
save
=
function
()
{
var
ret
=
table_save
(
this
.
id
)
if
(
!
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
...
...
@@ -47,17 +76,17 @@ table.prototype.save = function() {
return
ret
}
t
able
.
prototype
.
close
=
function
()
{
T
able
.
prototype
.
close
=
function
()
{
var
ret
=
table_close
(
this
.
id
)
return
ret
.
err
}
function
JoinTable
(
lefttable
,
righttable
,
index
)
{
this
.
lefttable
=
lefttable
this
.
righttable
=
righttable
if
(
this
.
lefttable
.
kvc
!=
this
.
righttable
.
kvc
)
{
throw
new
Error
(
"the kvc of left and right must same"
)
}
this
.
lefttable
=
lefttable
this
.
righttable
=
righttable
this
.
index
=
index
var
ret
=
new_join_table
(
this
.
lefttable
.
id
,
this
.
righttable
.
id
,
index
)
if
(
ret
.
err
)
{
...
...
@@ -67,9 +96,17 @@ function JoinTable(lefttable, righttable, index) {
this
.
kvc
=
this
.
lefttable
.
kvc
}
JoinTable
.
prototype
.
Save
=
function
()
{
function
print
(
obj
)
{
if
(
typeof
obj
===
"string"
)
{
console
.
log
(
obj
)
return
}
console
.
log
(
tojson
(
obj
))
}
JoinTable
.
prototype
.
save
=
function
()
{
var
ret
=
table_save
(
this
.
id
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
...
...
@@ -82,6 +119,24 @@ JoinTable.prototype.close = function() {
return
ret
.
err
}
JoinTable
.
prototype
.
addlogs
=
function
(
data
)
{
var
err
for
(
var
i
=
0
;
i
<
data
.
length
;
i
++
)
{
if
(
data
[
i
].
format
!=
"json"
)
{
continue
}
var
log
=
JSON
.
parse
(
data
[
i
].
log
)
if
(
log
.
__type__
==
this
.
lefttable
.
name
)
{
err
=
this
.
lefttable
.
replace
(
data
[
i
].
log
)
throwerr
(
err
)
}
if
(
log
.
__type__
==
this
.
righttable
.
name
)
{
err
=
this
.
righttable
.
replace
(
data
[
i
].
log
)
throwerr
(
err
)
}
}
}
//account warp
function
account
(
kvc
,
execer
,
symbol
)
{
this
.
execer
=
execer
...
...
@@ -91,7 +146,7 @@ function account(kvc, execer, symbol) {
account
.
prototype
.
genesisInit
=
function
(
addr
,
amount
)
{
var
ret
=
genesis_init
(
this
,
addr
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -99,7 +154,7 @@ account.prototype.genesisInit = function(addr, amount) {
account
.
prototype
.
execGenesisInit
=
function
(
execer
,
addr
,
amount
)
{
var
ret
=
genesis_init_exec
(
this
,
execer
,
addr
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -116,7 +171,7 @@ account.prototype.execGetBalance = function(execer, addr) {
//本合约转移资产,或者转移到其他合约,或者从其他合约取回资产
account
.
prototype
.
transfer
=
function
(
from
,
to
,
amount
)
{
var
ret
=
transfer
(
this
,
from
,
to
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -124,7 +179,7 @@ account.prototype.transfer = function(from, to, amount) {
account
.
prototype
.
transferToExec
=
function
(
execer
,
from
,
amount
)
{
var
ret
=
transfer_to_exec
(
this
,
execer
,
from
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -132,7 +187,7 @@ account.prototype.transferToExec = function(execer, from, amount) {
account
.
prototype
.
withdrawFromExec
=
function
(
execer
,
to
,
amount
)
{
var
ret
=
withdraw
(
this
,
execer
,
to
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -141,7 +196,7 @@ account.prototype.withdrawFromExec = function(execer, to, amount) {
//管理其他合约的资产转移到这个合约中
account
.
prototype
.
execActive
=
function
(
execer
,
addr
,
amount
)
{
var
ret
=
exec_active
(
this
,
execer
,
addr
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -149,7 +204,7 @@ account.prototype.execActive = function(execer, addr, amount) {
account
.
prototype
.
execFrozen
=
function
(
execer
,
addr
,
amount
)
{
var
ret
=
exec_frozen
(
this
,
execer
,
addr
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -157,7 +212,7 @@ account.prototype.execFrozen = function(execer, addr, amount) {
account
.
prototype
.
execDeposit
=
function
(
execer
,
addr
,
amount
)
{
var
ret
=
exec_deposit
(
this
,
execer
,
addr
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -165,7 +220,7 @@ account.prototype.execDeposit = function(execer, addr, amount) {
account
.
prototype
.
execWithdraw
=
function
(
execer
,
addr
,
amount
)
{
var
ret
=
exec_withdraw
(
this
,
execer
,
addr
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -173,7 +228,7 @@ account.prototype.execWithdraw = function(execer, addr, amount) {
account
.
prototype
.
execTransfer
=
function
(
execer
,
from
,
to
,
amount
)
{
var
ret
=
exec_transfer
(
this
,
execer
,
from
,
to
,
amount
)
if
(
!
this
.
kvc
)
{
if
(
this
.
kvc
)
{
this
.
kvc
.
save
(
ret
)
}
return
ret
.
err
...
...
@@ -203,6 +258,15 @@ account.prototype.execTransFrozenToFrozen = function(execer, from, to, amount) {
return
this
.
execFrozen
(
execer
,
to
,
amount
)
}
account
.
prototype
.
execTransActiveToFrozen
=
function
(
execer
,
from
,
to
,
amount
)
{
var
err
err
=
this
.
execTransfer
(
execer
,
from
,
to
,
amount
)
if
(
err
)
{
return
err
}
return
this
.
execFrozen
(
execer
,
to
,
amount
)
}
COINS
=
100000000
function
kvcreator
(
dbtype
)
{
...
...
@@ -214,11 +278,11 @@ function kvcreator(dbtype) {
this
.
getloal
=
getlocaldb
this
.
list
=
listdb
if
(
dbtype
==
"exec"
||
dbtype
==
"init"
)
{
this
.
get
=
this
.
getstatedb
this
.
get
db
=
this
.
getstate
}
else
if
(
dbtype
==
"local"
)
{
this
.
get
=
this
.
getlocaldb
this
.
get
db
=
this
.
getlocal
}
else
if
(
dbtype
==
"query"
)
{
this
.
get
=
this
.
getlocaldb
this
.
get
db
=
this
.
getlocal
}
else
{
throw
new
Error
(
"chain33.js: dbtype error"
)
}
...
...
@@ -237,7 +301,7 @@ kvcreator.prototype.get = function(k, prefix) {
if
(
this
.
data
[
k
])
{
v
=
this
.
data
[
k
]
}
else
{
var
dbvalue
=
this
.
get
(
k
,
!!
prefix
)
var
dbvalue
=
this
.
getdb
(
k
,
!!
prefix
)
if
(
dbvalue
.
err
)
{
return
null
}
...
...
@@ -300,35 +364,60 @@ kvcreator.prototype.receipt = function() {
return
{
kvs
:
this
.
kvs
,
logs
:
this
.
logs
}
}
function
GetExecName
()
{
var
exec
=
execname
()
if
(
exec
.
err
)
{
return
""
}
return
exec
.
value
}
function
ExecAddress
(
name
)
{
var
addr
=
execaddress
(
name
)
if
(
addr
.
err
)
{
return
""
}
console
.
log
(
addr
.
value
)
return
addr
.
value
}
function
Sha256
(
data
)
{
var
hash
=
sha256
(
data
)
if
(
hash
.
err
)
{
return
""
}
return
hash
.
value
}
function
Exec
(
context
)
{
this
.
kvc
=
new
kvcreator
(
"exec"
)
this
.
context
=
context
this
.
name
=
execn
ame
()
if
(
typeof
ExecInit
==
"function"
)
{
ExecInit
(
this
)
this
.
name
=
GetExecN
ame
()
if
(
typeof
ExecInit
==
=
"function"
)
{
ExecInit
.
call
(
this
)
}
}
Exec
.
prototype
.
txID
=
function
()
{
return
this
.
context
.
height
*
100000
+
this
.
index
return
this
.
context
.
height
*
100000
+
this
.
context
.
index
}
function
ExecLocal
(
context
,
logs
)
{
this
.
kvc
=
new
kvcreator
(
"local"
)
this
.
context
=
context
this
.
logs
=
logs
this
.
name
=
execn
ame
()
if
(
typeof
ExecLocalInit
==
"function"
)
{
ExecLocalInit
(
this
)
this
.
name
=
GetExecN
ame
()
if
(
typeof
ExecLocalInit
==
=
"function"
)
{
ExecLocalInit
.
call
(
this
)
}
}
function
Query
(
context
)
{
this
.
kvc
=
new
kvcreator
(
"query"
)
this
.
context
=
context
this
.
name
=
execn
ame
()
if
(
typeof
QueryInit
==
"function"
)
{
QueryInit
(
this
)
this
.
name
=
GetExecN
ame
()
if
(
typeof
QueryInit
==
=
"function"
)
{
QueryInit
.
call
(
this
)
}
}
...
...
@@ -367,7 +456,7 @@ function callcode(context, f, args, loglist) {
}
var
arg
=
JSON
.
parse
(
args
)
if
(
typeof
runobj
[
funcname
]
!=
"function"
)
{
throw
new
Error
(
"chain33.js: invalid function name not found
"
)
throw
new
Error
(
"chain33.js: invalid function name not found
->"
+
funcname
)
}
return
runobj
[
funcname
](
arg
)
}
...
...
plugin/dapp/js/executor/table.go
View file @
17ec8479
package
executor
import
(
"bytes"
"encoding/json"
"errors"
"fmt"
"regexp"
"strings"
"sync"
"sync/atomic"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/table"
...
...
@@ -35,22 +35,11 @@ import (
"index2" : "",
}
*/
var
globalTableHandle
sync
.
Map
var
globalHanldeID
int64
//NewTable 创建一个新的表格, 返回handle
func
(
u
*
js
)
newTable
(
name
,
config
,
defaultvalue
string
)
(
id
int64
,
err
error
)
{
for
{
id
=
atomic
.
AddInt64
(
&
globalHanldeID
,
1
)
%
maxjsint
if
_
,
ok
:=
globalTableHandle
.
Load
(
id
);
ok
{
continue
}
if
id
<
0
{
atomic
.
StoreInt64
(
&
globalHanldeID
,
0
)
continue
}
break
}
u
.
globalHanldeID
++
id
=
u
.
globalHanldeID
row
,
err
:=
NewJSONRow
(
config
,
defaultvalue
)
if
err
!=
nil
{
return
0
,
err
...
...
@@ -74,7 +63,7 @@ func (u *js) newTable(name, config, defaultvalue string) (id int64, err error) {
indexs
=
append
(
indexs
,
k
)
}
opt
:=
&
table
.
Option
{
Prefix
:
string
(
prefix
),
Prefix
:
string
s
.
Trim
(
string
(
prefix
),
"-"
),
Name
:
row
.
config
[
"#tablename"
],
Primary
:
row
.
config
[
"#primary"
],
Index
:
indexs
,
...
...
@@ -83,7 +72,7 @@ func (u *js) newTable(name, config, defaultvalue string) (id int64, err error) {
if
err
!=
nil
{
return
0
,
err
}
globalTableHandle
.
Store
(
id
,
t
)
u
.
globalTableHandle
.
Store
(
id
,
t
)
return
id
,
nil
}
...
...
@@ -106,42 +95,43 @@ func (u *js) newTableFunc(vm *otto.Otto, name string) {
}
//CloseTable 关闭表格释放内存
func
closeTable
(
id
int64
)
error
{
_
,
ok
:=
globalTableHandle
.
Load
(
id
)
func
(
u
*
js
)
closeTable
(
id
int64
)
error
{
_
,
ok
:=
u
.
globalTableHandle
.
Load
(
id
)
if
!
ok
{
return
types
.
ErrNotFound
}
globalTableHandle
.
Delete
(
id
)
u
.
globalTableHandle
.
Delete
(
id
)
return
nil
}
func
getTable
(
id
int64
)
(
*
table
.
Table
,
error
)
{
if
value
,
ok
:=
globalTableHandle
.
Load
(
id
);
ok
{
func
(
u
*
js
)
getTable
(
id
int64
)
(
*
table
.
Table
,
error
)
{
if
value
,
ok
:=
u
.
globalTableHandle
.
Load
(
id
);
ok
{
return
value
.
(
*
table
.
Table
),
nil
}
return
nil
,
types
.
ErrNotFound
}
func
getTabler
(
id
int64
)
(
tabler
,
error
)
{
if
value
,
ok
:=
globalTableHandle
.
Load
(
id
);
ok
{
func
(
u
*
js
)
getTabler
(
id
int64
)
(
tabler
,
error
)
{
if
value
,
ok
:=
u
.
globalTableHandle
.
Load
(
id
);
ok
{
return
value
.
(
tabler
),
nil
}
return
nil
,
types
.
ErrNotFound
}
func
registerTableFunc
(
vm
*
otto
.
Otto
)
{
tableAddFunc
(
vm
)
tableReplaceFunc
(
vm
)
tableDelFunc
(
vm
)
tableCloseFunc
(
vm
)
tableSave
(
vm
)
tableJoinFunc
(
vm
)
tableQueryFunc
(
vm
)
tableGetFunc
(
vm
)
tableJoinKeyFunc
(
vm
)
func
(
u
*
js
)
registerTableFunc
(
vm
*
otto
.
Otto
,
name
string
)
{
u
.
newTableFunc
(
vm
,
name
)
u
.
tableAddFunc
(
vm
)
u
.
tableReplaceFunc
(
vm
)
u
.
tableDelFunc
(
vm
)
u
.
tableCloseFunc
(
vm
)
u
.
tableSave
(
vm
)
u
.
tableJoinFunc
(
vm
)
u
.
tableQueryFunc
(
vm
)
u
.
tableGetFunc
(
vm
)
u
.
tableJoinKeyFunc
(
vm
)
}
func
tableJoinKeyFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableJoinKeyFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_joinkey"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
left
,
err
:=
call
.
Argument
(
0
)
.
ToString
()
if
err
!=
nil
{
...
...
@@ -156,13 +146,13 @@ func tableJoinKeyFunc(vm *otto.Otto) {
})
}
func
tableAddFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableAddFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_add"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
id
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
tab
,
err
:=
getTable
(
id
)
tab
,
err
:=
u
.
getTable
(
id
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -178,13 +168,13 @@ func tableAddFunc(vm *otto.Otto) {
})
}
func
tableReplaceFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableReplaceFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_replace"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
id
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
tab
,
err
:=
getTable
(
id
)
tab
,
err
:=
u
.
getTable
(
id
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -200,13 +190,13 @@ func tableReplaceFunc(vm *otto.Otto) {
})
}
func
tableDelFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableDelFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_del"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
id
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
tab
,
err
:=
getTable
(
id
)
tab
,
err
:=
u
.
getTable
(
id
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -222,13 +212,13 @@ func tableDelFunc(vm *otto.Otto) {
})
}
func
tableGetFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableGetFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_get"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
id
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
tab
,
err
:=
getTabler
(
id
)
tab
,
err
:=
u
.
getTable
(
id
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -256,13 +246,13 @@ type tabler interface {
Save
()
(
kvs
[]
*
types
.
KeyValue
,
err
error
)
}
func
tableSave
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableSave
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_save"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
id
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
tab
,
err
:=
getTabler
(
id
)
tab
,
err
:=
u
.
getTabler
(
id
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -274,13 +264,13 @@ func tableSave(vm *otto.Otto) {
})
}
func
tableCloseFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableCloseFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_close"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
id
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
err
=
closeTable
(
id
)
err
=
u
.
closeTable
(
id
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -288,13 +278,13 @@ func tableCloseFunc(vm *otto.Otto) {
})
}
func
tableQueryFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableQueryFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"table_query"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
id
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
tab
,
err
:=
getTabler
(
id
)
tab
,
err
:=
u
.
getTabler
(
id
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -333,7 +323,7 @@ func tableQueryFunc(vm *otto.Otto) {
return
errReturn
(
vm
,
err
)
}
_
,
isjoin
:=
tab
.
(
*
table
.
JoinTable
)
querylist
:=
make
([]
*
otto
.
Object
,
len
(
rows
))
querylist
:=
make
([]
interface
{}
,
len
(
rows
))
for
i
:=
0
;
i
<
len
(
rows
);
i
++
{
if
isjoin
{
joindata
,
ok
:=
rows
[
i
]
.
Data
.
(
*
table
.
JoinData
)
...
...
@@ -348,16 +338,18 @@ func tableQueryFunc(vm *otto.Otto) {
if
!
ok
{
return
errReturn
(
vm
,
errors
.
New
(
"rightdata is not jslog"
))
}
obj
:=
newObject
(
vm
)
.
setValue
(
"left"
,
leftdata
.
Data
)
obj
.
setValue
(
"right"
,
rightdata
.
Data
)
querylist
[
i
]
=
obj
.
object
()
obj
:=
make
(
map
[
string
]
interface
{})
obj
[
"left"
]
=
leftdata
.
Data
obj
[
"right"
]
=
rightdata
.
Data
querylist
[
i
]
=
obj
}
else
{
leftdata
,
ok
:=
rows
[
i
]
.
Data
.
(
*
jsproto
.
JsLog
)
if
!
ok
{
return
errReturn
(
vm
,
errors
.
New
(
"data is not JsLog"
))
}
obj
:=
newObject
(
vm
)
.
setValue
(
"left"
,
leftdata
.
Data
)
querylist
[
i
]
=
obj
.
object
()
obj
:=
make
(
map
[
string
]
interface
{})
obj
[
"left"
]
=
leftdata
.
Data
querylist
[
i
]
=
obj
}
}
retvalue
,
err
:=
vm
.
ToValue
(
querylist
)
...
...
@@ -368,13 +360,13 @@ func tableQueryFunc(vm *otto.Otto) {
})
}
func
tableJoinFunc
(
vm
*
otto
.
Otto
)
{
func
(
u
*
js
)
tableJoinFunc
(
vm
*
otto
.
Otto
)
{
vm
.
Set
(
"new_join_table"
,
func
(
call
otto
.
FunctionCall
)
otto
.
Value
{
left
,
err
:=
call
.
Argument
(
0
)
.
ToInteger
()
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
lefttab
,
err
:=
getTable
(
left
)
lefttab
,
err
:=
u
.
getTable
(
left
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -382,7 +374,7 @@ func tableJoinFunc(vm *otto.Otto) {
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
righttab
,
err
:=
getTable
(
right
)
righttab
,
err
:=
u
.
getTable
(
right
)
if
err
!=
nil
{
return
errReturn
(
vm
,
err
)
}
...
...
@@ -395,18 +387,9 @@ func tableJoinFunc(vm *otto.Otto) {
return
errReturn
(
vm
,
err
)
}
var
id
int64
for
{
id
=
atomic
.
AddInt64
(
&
globalHanldeID
,
1
)
%
maxjsint
if
_
,
ok
:=
globalTableHandle
.
Load
(
id
);
ok
{
continue
}
if
id
<
0
{
atomic
.
StoreInt64
(
&
globalHanldeID
,
0
)
continue
}
break
}
globalTableHandle
.
Store
(
id
,
join
)
u
.
globalHanldeID
++
id
=
u
.
globalHanldeID
u
.
globalTableHandle
.
Store
(
id
,
join
)
return
newObject
(
vm
)
.
setValue
(
"id"
,
id
)
.
value
()
})
}
...
...
@@ -428,18 +411,25 @@ handle := new_join_table(left, right, listofjoinindex)
//JSONRow meta
type
JSONRow
struct
{
*
jsproto
.
JsLog
config
map
[
string
]
string
data
map
[
string
]
interface
{}
config
map
[
string
]
string
data
map
[
string
]
interface
{}
lastdata
types
.
Message
isint
*
regexp
.
Regexp
isfloat
*
regexp
.
Regexp
defaultvalue
string
}
//NewJSONRow 创建一个row
func
NewJSONRow
(
config
string
,
defaultvalue
string
)
(
*
JSONRow
,
error
)
{
row
:=
&
JSONRow
{}
row
.
isint
=
regexp
.
MustCompile
(
`%\d*d`
)
row
.
isfloat
=
regexp
.
MustCompile
(
`%[\.\d]*f`
)
row
.
config
=
make
(
map
[
string
]
string
)
err
:=
json
.
Unmarshal
([]
byte
(
config
),
row
.
config
)
err
:=
json
.
Unmarshal
([]
byte
(
config
),
&
row
.
config
)
if
err
!=
nil
{
return
nil
,
err
}
row
.
defaultvalue
=
defaultvalue
row
.
JsLog
=
&
jsproto
.
JsLog
{
Data
:
defaultvalue
}
err
=
row
.
parse
()
if
err
!=
nil
{
...
...
@@ -450,16 +440,25 @@ func NewJSONRow(config string, defaultvalue string) (*JSONRow, error) {
//CreateRow 创建一行
func
(
row
*
JSONRow
)
CreateRow
()
*
table
.
Row
{
return
&
table
.
Row
{
Data
:
&
jsproto
.
JsLog
{}}
return
&
table
.
Row
{
Data
:
&
jsproto
.
JsLog
{
Data
:
row
.
defaultvalue
}}
}
func
(
row
*
JSONRow
)
parse
()
error
{
row
.
data
=
make
(
map
[
string
]
interface
{})
return
json
.
Unmarshal
([]
byte
(
row
.
JsLog
.
Data
),
row
.
data
)
d
:=
json
.
NewDecoder
(
bytes
.
NewBufferString
(
row
.
JsLog
.
Data
))
d
.
UseNumber
()
if
err
:=
d
.
Decode
(
&
row
.
data
);
err
!=
nil
{
return
err
}
return
nil
}
//SetPayload 设置行的内容
func
(
row
*
JSONRow
)
SetPayload
(
data
types
.
Message
)
error
{
if
row
.
lastdata
==
data
{
return
nil
}
row
.
lastdata
=
data
if
rowdata
,
ok
:=
data
.
(
*
jsproto
.
JsLog
);
ok
{
row
.
JsLog
=
rowdata
return
row
.
parse
()
...
...
@@ -471,6 +470,24 @@ func (row *JSONRow) SetPayload(data types.Message) error {
func
(
row
*
JSONRow
)
Get
(
key
string
)
([]
byte
,
error
)
{
if
format
,
ok
:=
row
.
config
[
key
];
ok
{
if
data
,
ok
:=
row
.
data
[
key
];
ok
{
if
n
,
ok
:=
data
.
(
json
.
Number
);
ok
{
if
row
.
isint
.
Match
([]
byte
(
format
))
{
//ini
num
,
err
:=
n
.
Int64
()
if
err
!=
nil
{
return
nil
,
err
}
return
[]
byte
(
fmt
.
Sprintf
(
format
,
num
)),
nil
}
else
if
row
.
isfloat
.
Match
([]
byte
(
format
))
{
num
,
err
:=
n
.
Float64
()
if
err
!=
nil
{
return
nil
,
err
}
return
[]
byte
(
fmt
.
Sprintf
(
format
,
num
)),
nil
}
else
{
s
:=
n
.
String
()
return
[]
byte
(
fmt
.
Sprintf
(
format
,
s
)),
nil
}
}
return
[]
byte
(
fmt
.
Sprintf
(
format
,
data
)),
nil
}
}
...
...
vendor/github.com/33cn/chain33/util/testnode/testnode.go
View file @
17ec8479
...
...
@@ -205,6 +205,27 @@ func (mock *Chain33Mock) SendAndSign(priv crypto.PrivKey, hextx string) ([]byte,
return
reply
.
GetMsg
(),
nil
}
//SendAndSignNonce 用外部传入的nonce 重写nonce
func
(
mock
*
Chain33Mock
)
SendAndSignNonce
(
priv
crypto
.
PrivKey
,
hextx
string
,
nonce
int64
)
([]
byte
,
error
)
{
txbytes
,
err
:=
hex
.
DecodeString
(
hextx
)
if
err
!=
nil
{
return
nil
,
err
}
tx
:=
&
types
.
Transaction
{}
err
=
types
.
Decode
(
txbytes
,
tx
)
if
err
!=
nil
{
return
nil
,
err
}
tx
.
Nonce
=
nonce
tx
.
Fee
=
1e6
tx
.
Sign
(
types
.
SECP256K1
,
priv
)
reply
,
err
:=
mock
.
api
.
SendTx
(
tx
)
if
err
!=
nil
{
return
nil
,
err
}
return
reply
.
GetMsg
(),
nil
}
func
newWalletRealize
(
qAPI
client
.
QueueProtocolAPI
)
{
seed
:=
&
types
.
SaveSeedByPw
{
Seed
:
"subject hamster apple parent vital can adult chapter fork business humor pen tiger void elephant"
,
...
...
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