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
112b9f75
Commit
112b9f75
authored
Mar 18, 2019
by
lilinleeli1234
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/lynAzrael/plugin
parents
5bace73a
b7699804
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
57 changed files
with
2339 additions
and
126 deletions
+2339
-126
Makefile
plugin/dapp/js/cmd/Makefile
+0
-4
build.sh
plugin/dapp/js/cmd/build.sh
+0
-11
js.go
plugin/dapp/js/command/js.go
+1
-1
plugin.go
plugin/dapp/js/plugin.go
+2
-2
lottery.go
plugin/dapp/lottery/executor/lottery.go
+21
-14
action.go
plugin/dapp/multisig/executor/action.go
+1
-1
asset-transfer.md
plugin/dapp/paracross/executor/asset-transfer.md
+0
-2
privacy_test.go
plugin/dapp/privacy/crypto/privacy_test.go
+8
-2
build.sh
plugin/dapp/relay/cmd/build.sh
+12
-11
testcase.sh
plugin/dapp/relay/cmd/build/testcase.sh
+1
-0
token.go
plugin/dapp/token/autotest/token.go
+2
-0
token.toml
plugin/dapp/token/autotest/token.toml
+14
-1
tokenCase.go
plugin/dapp/token/autotest/tokenCase.go
+108
-0
token.go
plugin/dapp/token/commands/token.go
+118
-0
exec.go
plugin/dapp/token/executor/exec.go
+10
-0
exec_del_local.go
plugin/dapp/token/executor/exec_del_local.go
+64
-0
exec_local.go
plugin/dapp/token/executor/exec_local.go
+86
-0
logs.go
plugin/dapp/token/executor/logs.go
+100
-0
query.go
plugin/dapp/token/executor/query.go
+22
-0
token_new_test.go
plugin/dapp/token/executor/token_new_test.go
+73
-0
token_test.go
plugin/dapp/token/executor/token_test.go
+243
-0
tokendb.go
plugin/dapp/token/executor/tokendb.go
+130
-1
transwithdraw.go
plugin/dapp/token/executor/transwithdraw.go
+4
-1
token.proto
plugin/dapp/token/proto/token.proto
+28
-0
rpc.go
plugin/dapp/token/rpc/rpc.go
+26
-0
const.go
plugin/dapp/token/types/const.go
+13
-0
token.pb.go
plugin/dapp/token/types/token.pb.go
+0
-0
types.go
plugin/dapp/token/types/types.go
+4
-0
init.go
plugin/store/init/init.go
+4
-3
kvmvcc_mavl.go
plugin/store/kvmvccmavl/kvmvcc_mavl.go
+315
-0
kvmvcc_mavl_test.go
plugin/store/kvmvccmavl/kvmvcc_mavl_test.go
+0
-0
kvmvccdb.go
plugin/store/kvmvccmavl/kvmvccdb.go
+0
-0
mavl.go
plugin/store/kvmvccmavl/mavl.go
+160
-0
.travis.yml
vendor/github.com/33cn/chain33/.travis.yml
+1
-1
account.go
vendor/github.com/33cn/chain33/account/account.go
+37
-0
account_test.go
vendor/github.com/33cn/chain33/account/account_test.go
+10
-0
bityuan.toml
vendor/github.com/33cn/chain33/cmd/chain33/bityuan.toml
+4
-0
chain33.test.toml
vendor/github.com/33cn/chain33/cmd/chain33/chain33.test.toml
+4
-0
chain33.toml
vendor/github.com/33cn/chain33/cmd/chain33/chain33.toml
+4
-0
execenv.go
vendor/github.com/33cn/chain33/executor/execenv.go
+14
-1
executor_real_test.go
...or/github.com/33cn/chain33/executor/executor_real_test.go
+9
-3
executor_test.go
vendor/github.com/33cn/chain33/executor/executor_test.go
+2
-0
localdb.go
vendor/github.com/33cn/chain33/executor/localdb.go
+40
-9
localdb_test.go
vendor/github.com/33cn/chain33/executor/localdb_test.go
+28
-0
types.go
...github.com/33cn/chain33/system/dapp/manage/types/types.go
+1
-1
memmavl.go
...r/github.com/33cn/chain33/system/store/mavl/db/memmavl.go
+204
-0
node.go
vendor/github.com/33cn/chain33/system/store/mavl/db/node.go
+4
-0
tree.go
vendor/github.com/33cn/chain33/system/store/mavl/db/tree.go
+144
-4
tree_test.go
...github.com/33cn/chain33/system/store/mavl/db/tree_test.go
+146
-0
mavl.go
vendor/github.com/33cn/chain33/system/store/mavl/mavl.go
+12
-1
account.pb.go
vendor/github.com/33cn/chain33/types/account.pb.go
+82
-33
const.go
vendor/github.com/33cn/chain33/types/const.go
+3
-0
error.go
vendor/github.com/33cn/chain33/types/error.go
+3
-0
account.proto
vendor/github.com/33cn/chain33/types/proto/account.proto
+5
-0
exec.go
vendor/github.com/33cn/chain33/util/exec.go
+8
-16
util.go
vendor/github.com/33cn/chain33/util/util.go
+2
-2
util_test.go
vendor/github.com/33cn/chain33/util/util_test.go
+2
-1
No files found.
plugin/dapp/js/cmd/Makefile
deleted
100644 → 0
View file @
5bace73a
all
:
chmod
+x ./build.sh
./build.sh
$(OUT)
$(FLAG)
\ No newline at end of file
plugin/dapp/js/cmd/build.sh
deleted
100755 → 0
View file @
5bace73a
#!/bin/sh
strpwd
=
$(
pwd
)
strcmd
=
${
strpwd
##*dapp/
}
strapp
=
${
strcmd
%/cmd*
}
OUT_DIR
=
"
${
1
}
/
$strapp
"
#FLAG=$2
mkdir
-p
"
${
OUT_DIR
}
"
cp
./build/
*
"
${
OUT_DIR
}
"
plugin/dapp/js/c
m
d/js.go
→
plugin/dapp/js/c
omman
d/js.go
View file @
112b9f75
...
...
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
c
m
d
package
c
omman
d
import
(
"fmt"
...
...
plugin/dapp/js/plugin.go
View file @
112b9f75
...
...
@@ -2,12 +2,12 @@ package js
import
(
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/js/cmd"
"github.com/33cn/plugin/plugin/dapp/js/executor"
ptypes
"github.com/33cn/plugin/plugin/dapp/js/types"
// init auto test
_
"github.com/33cn/plugin/plugin/dapp/js/autotest"
"github.com/33cn/plugin/plugin/dapp/js/command"
)
func
init
()
{
...
...
@@ -15,7 +15,7 @@ func init() {
Name
:
ptypes
.
JsX
,
ExecName
:
executor
.
GetName
(),
Exec
:
executor
.
Init
,
Cmd
:
c
m
d
.
JavaScriptCmd
,
Cmd
:
c
omman
d
.
JavaScriptCmd
,
RPC
:
nil
,
})
}
plugin/dapp/lottery/executor/lottery.go
View file @
112b9f75
...
...
@@ -5,6 +5,7 @@
package
executor
import
(
"fmt"
"sort"
log
"github.com/33cn/chain33/common/log/log15"
...
...
@@ -61,25 +62,31 @@ func (lott *Lottery) GetDriverName() string {
return
pty
.
LotteryX
}
func
(
lott
*
Lottery
)
findLotteryBuyRecords
(
key
[]
byte
)
(
*
pty
.
LotteryBuyRecords
,
error
)
{
count
:=
lott
.
GetLocalDB
()
.
PrefixCount
(
key
)
llog
.
Error
(
"findLotteryBuyRecords"
,
"count"
,
count
)
values
,
err
:=
lott
.
GetLocalDB
()
.
List
(
key
,
nil
,
int32
(
count
),
0
)
if
err
!=
nil
{
return
nil
,
err
}
func
(
lott
*
Lottery
)
findLotteryBuyRecords
(
prefix
[]
byte
)
(
*
pty
.
LotteryBuyRecords
,
error
)
{
count
:=
0
var
key
[]
byte
var
records
pty
.
LotteryBuyRecords
for
_
,
value
:=
range
values
{
var
record
pty
.
LotteryBuyRecord
err
:=
types
.
Decode
(
value
,
&
record
)
for
{
values
,
err
:=
lott
.
GetLocalDB
()
.
List
(
prefix
,
key
,
DefultCount
,
0
)
if
err
!=
nil
{
continue
return
nil
,
err
}
for
_
,
value
:=
range
values
{
var
record
pty
.
LotteryBuyRecord
err
:=
types
.
Decode
(
value
,
&
record
)
if
err
!=
nil
{
continue
}
records
.
Records
=
append
(
records
.
Records
,
&
record
)
}
count
+=
len
(
values
)
if
len
(
values
)
<
int
(
DefultCount
)
{
break
}
records
.
Records
=
append
(
records
.
Records
,
&
record
)
key
=
[]
byte
(
fmt
.
Sprintf
(
"%s:%18d"
,
prefix
,
records
.
Records
[
count
-
1
]
.
Index
)
)
}
llog
.
Info
(
"findLotteryBuyRecords"
,
"count"
,
count
)
return
&
records
,
nil
}
...
...
plugin/dapp/multisig/executor/action.go
View file @
112b9f75
...
...
@@ -94,7 +94,7 @@ func (a *action) MultiSigAccCreate(accountCreate *mty.MultiSigAccCreate) (*types
//通过创建交易的txhash生成一个唯一的多重签名合约 NewAddrFromString
addr
:=
address
.
MultiSignAddress
(
a
.
txhash
)
//账户去重校验
multiSig
,
err
:=
getMultiSigAcc
ount
(
a
.
local
db
,
addr
)
multiSig
,
err
:=
getMultiSigAcc
FromDb
(
a
.
db
,
addr
)
if
err
==
nil
&&
multiSig
!=
nil
{
return
nil
,
mty
.
ErrAccountHasExist
}
...
...
plugin/dapp/paracross/executor/asset-transfer.md
View file @
112b9f75
...
...
@@ -36,13 +36,11 @@ asset-transfer 分两种, 主链转出, 主链转入
1.
用户主链paracross合约帐号, balance -
1.
某平行链paracross合约帐号, balance +
*
平行链(如果上面步骤失败,, 平行链会过滤掉这个交易)
1.
平行链中paracross合约帐号 balance +
1.
平行链中 用户paracross合约帐号 balance +
主链转入 withdraw
*
平行链
1.
平行链中 用户paracross合约帐号 balance -
1.
平行链中paracross合约帐号 balance -
*
主链(上面步骤失败, 不进行操作)
1.
commit 交易共识时执行
1.
某平行链paracross合约帐号, balance -
...
...
plugin/dapp/privacy/crypto/privacy_test.go
View file @
112b9f75
...
...
@@ -51,11 +51,17 @@ func (*signatureMock) Equals(crypto.Signature) bool {
return
true
}
func
formatByte32
(
b
[]
byte
)
[]
byte
{
var
b32
[
32
]
byte
copy
(
b32
[
:
],
b
)
return
b32
[
:
]
}
type
privKeyMock
struct
{
}
func
(
mock
*
privKeyMock
)
Bytes
()
[]
byte
{
return
[]
byte
(
"1234"
)
return
formatByte32
([]
byte
(
"1234"
)
)
}
func
(
mock
*
privKeyMock
)
Sign
(
msg
[]
byte
)
crypto
.
Signature
{
...
...
@@ -82,7 +88,7 @@ func TestNewPrivacy(t *testing.T) {
}
func
test_RecoverOnetimePriKey
(
t
*
testing
.
T
)
{
R
:=
[]
byte
(
"1234"
)
R
:=
formatByte32
([]
byte
(
"1234"
)
)
pkm
:=
privKeyMock
{}
privKey
,
err
:=
RecoverOnetimePriKey
(
R
,
&
pkm
,
&
pkm
,
0
)
assert
.
Nil
(
t
,
err
)
...
...
plugin/dapp/relay/cmd/build.sh
View file @
112b9f75
#!/usr/bin/env bash
strpwd
=
$(
pwd
)
strcmd
=
${
strpwd
##*dapp/
}
strapp
=
${
strcmd
%/cmd*
}
#strpwd=$(pwd)
#strcmd=${strpwd##*dapp/}
#strapp=${strcmd%/cmd*}
#
#OUT_DIR="${1}/$strapp"
#SRC_RELAYD=github.com/33cn/plugin/plugin/dapp/relay/cmd/relayd
#FLAG=$2
OUT_DIR
=
"
${
1
}
/
$strapp
"
SRC_RELAYD
=
github.com/33cn/plugin/plugin/dapp/relay/cmd/relayd
FLAG
=
$2
# shellcheck disable=SC2086
go build
-i
${
FLAG
}
-v
-o
"
${
OUT_DIR
}
/relayd"
"
${
SRC_RELAYD
}
"
cp
./relayd/relayd.toml
"
${
OUT_DIR
}
/relayd.toml"
cp
./build/
*
"
${
OUT_DIR
}
"
# shellcheck disable=SC2086,1072
#go build -i ${FLAG} -v -o "${OUT_DIR}/relayd" "${SRC_RELAYD}"
#cp ./relayd/relayd.toml "${OUT_DIR}/relayd.toml"
#cp ./build/* "${OUT_DIR}"
echo
"ignore"
plugin/dapp/relay/cmd/build/testcase.sh
View file @
112b9f75
...
...
@@ -170,6 +170,7 @@ function relay_test() {
coinaddr
=
$(${
1
}
tx query
-s
"
${
buy_hash
}
"
| jq
-r
".receipt.logs[2].log.coinAddr"
)
if
[
"
${
coinaddr
}
"
!=
"1Am9UTGfdnxabvcywYG2hvzr6qK8T3oUZT"
]
;
then
${
1
}
tx query
-s
"
${
buy_hash
}
"
echo
"wrong create order to coinaddr"
exit
1
fi
...
...
plugin/dapp/token/autotest/token.go
View file @
112b9f75
...
...
@@ -18,6 +18,8 @@ type tokenAutoTest struct {
TransferCaseArr
[]
autotest
.
TransferCase
`toml:"TransferCase,omitempty"`
WithdrawCaseArr
[]
autotest
.
WithdrawCase
`toml:"WithdrawCase,omitempty"`
TokenRevokeCaseArr
[]
TokenRevokeCase
`toml:"TokenRevokeCase,omitempty"`
TokenMintCaseArr
[]
TokenMintCase
`toml:"TokenMintCase,omitempty"`
TokenBurnCaseArr
[]
TokenBurnCase
`toml:"TokenBurnCase,omitempty"`
}
func
init
()
{
...
...
plugin/dapp/token/autotest/token.toml
View file @
112b9f75
...
...
@@ -7,7 +7,7 @@ command = "account import_key -k 0xc21d38be90493512a5c2417d565269a8b23ce8152010e
[[TokenPreCreateCase]]
id
=
"tokenPre"
command
=
"send token precreate -f 0.01 -i testToken -n testToken -s TC -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t 100000 -p 1 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
command
=
"send token precreate -
c 1 -
f 0.01 -i testToken -n testToken -s TC -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t 100000 -p 1 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
dep
=
[
"transForPrecreate"
,
"import1"
]
[[TokenPreCreateCase]]
...
...
@@ -21,6 +21,19 @@ id = "tokenFinish"
command
=
"send token finish -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -f 0.01 -s TC -k 0xc34b5d9d44ac7b754806f761d3d4d2c4fe5214f6b074c19f069c4f5c2a29c8cc"
dep
=
["tokenPre"]
[[TokenMintCase]]
id
=
"tokenMint"
command
=
"send token mint -a 100 -s TC -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
dep
=
["tokenFinish"]
amount
=
"100"
checkItem
=
["balance"]
[[TokenBurnCase]]
id
=
"tokenBurn"
command
=
"send token burn -a 50 -s TC -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
dep
=
["tokenMint"]
amount
=
"50"
checkItem
=
["balance"]
#send to token for precreate
[[TransferCase]]
...
...
plugin/dapp/token/autotest/tokenCase.go
View file @
112b9f75
...
...
@@ -6,6 +6,8 @@ package autotest
import
(
"github.com/33cn/chain33/cmd/autotest/types"
"strconv"
)
// TokenPreCreateCase token precreatecase command
...
...
@@ -59,3 +61,109 @@ func (testCase *TokenFinishCreateCase) SendCommand(packID string) (types.PackFun
return
types
.
DefaultSend
(
testCase
,
&
TokenFinishCreatePack
{},
packID
)
}
// TokenMintCase token mint case
type
TokenMintCase
struct
{
types
.
BaseCase
Amount
string
`toml:"amount"`
}
// TokenMintPack token mint pack command
type
TokenMintPack
struct
{
types
.
BaseCasePack
}
// SendCommand send command function of tokenfinishcreatecase
func
(
testCase
*
TokenMintCase
)
SendCommand
(
packID
string
)
(
types
.
PackFunc
,
error
)
{
return
types
.
DefaultSend
(
testCase
,
&
TokenMintPack
{},
packID
)
}
// GetCheckHandlerMap get check handle for map
func
(
pack
*
TokenMintPack
)
GetCheckHandlerMap
()
interface
{}
{
funcMap
:=
make
(
types
.
CheckHandlerMapDiscard
,
2
)
funcMap
[
"balance"
]
=
pack
.
checkBalance
return
funcMap
}
func
(
pack
*
TokenMintPack
)
checkBalance
(
txInfo
map
[
string
]
interface
{})
bool
{
logArr
:=
txInfo
[
"receipt"
]
.
(
map
[
string
]
interface
{})[
"logs"
]
.
([]
interface
{})
logTokenBurn
:=
logArr
[
1
]
.
(
map
[
string
]
interface
{})[
"log"
]
.
(
map
[
string
]
interface
{})
logAccBurn
:=
logArr
[
2
]
.
(
map
[
string
]
interface
{})[
"log"
]
.
(
map
[
string
]
interface
{})
interCase
:=
pack
.
TCase
.
(
*
TokenMintCase
)
amount1
,
_
:=
strconv
.
ParseInt
(
interCase
.
Amount
,
10
,
64
)
amount
:=
amount1
*
1e8
pack
.
FLog
.
Info
(
"MintDetails"
,
"TestID"
,
pack
.
PackID
,
"TokenPrev"
,
logTokenBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"total"
]
.
(
string
),
"TokenCurr"
,
logTokenBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"total"
]
.
(
string
),
"AccPrev"
,
logAccBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"balance"
]
.
(
string
),
"AccCurr"
,
logAccBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"balance"
]
.
(
string
),
"amount"
,
amount1
)
totalCurrent
:=
parseInt64
(
logTokenBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"total"
])
totalPrev
:=
parseInt64
(
logTokenBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"total"
])
accCurrent
:=
parseInt64
(
logAccBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"balance"
])
accPrev
:=
parseInt64
(
logAccBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"balance"
])
return
totalCurrent
-
amount
==
totalPrev
&&
accCurrent
-
amount
==
accPrev
}
// TokenBurnCase token mint case
type
TokenBurnCase
struct
{
types
.
BaseCase
Amount
string
`toml:"amount"`
}
// TokenBurnPack token mint pack command
type
TokenBurnPack
struct
{
types
.
BaseCasePack
}
// SendCommand send command function
func
(
testCase
*
TokenBurnCase
)
SendCommand
(
packID
string
)
(
types
.
PackFunc
,
error
)
{
return
types
.
DefaultSend
(
testCase
,
&
TokenBurnPack
{},
packID
)
}
// GetCheckHandlerMap get check handle for map
func
(
pack
*
TokenBurnPack
)
GetCheckHandlerMap
()
interface
{}
{
funcMap
:=
make
(
types
.
CheckHandlerMapDiscard
,
2
)
funcMap
[
"balance"
]
=
pack
.
checkBalance
return
funcMap
}
func
(
pack
*
TokenBurnPack
)
checkBalance
(
txInfo
map
[
string
]
interface
{})
bool
{
logArr
:=
txInfo
[
"receipt"
]
.
(
map
[
string
]
interface
{})[
"logs"
]
.
([]
interface
{})
logTokenBurn
:=
logArr
[
1
]
.
(
map
[
string
]
interface
{})[
"log"
]
.
(
map
[
string
]
interface
{})
logAccBurn
:=
logArr
[
2
]
.
(
map
[
string
]
interface
{})[
"log"
]
.
(
map
[
string
]
interface
{})
interCase
:=
pack
.
TCase
.
(
*
TokenBurnCase
)
amount1
,
_
:=
strconv
.
ParseInt
(
interCase
.
Amount
,
10
,
64
)
amount
:=
amount1
*
1e8
pack
.
FLog
.
Info
(
"BurnDetails"
,
"TestID"
,
pack
.
PackID
,
"TokenPrev"
,
logTokenBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"total"
]
.
(
string
),
"TokenCurr"
,
logTokenBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"total"
]
.
(
string
),
"AccPrev"
,
logAccBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"balance"
]
.
(
string
),
"AccCurr"
,
logAccBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"balance"
]
.
(
string
),
"amount"
,
amount1
)
totalCurrent
:=
parseInt64
(
logTokenBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"total"
])
totalPrev
:=
parseInt64
(
logTokenBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"total"
])
accCurrent
:=
parseInt64
(
logAccBurn
[
"current"
]
.
(
map
[
string
]
interface
{})[
"balance"
])
accPrev
:=
parseInt64
(
logAccBurn
[
"prev"
]
.
(
map
[
string
]
interface
{})[
"balance"
])
return
totalCurrent
+
amount
==
totalPrev
&&
accCurrent
+
amount
==
accPrev
}
func
parseInt64
(
s
interface
{})
int64
{
i
,
_
:=
strconv
.
ParseInt
(
s
.
(
string
),
10
,
64
)
return
i
}
plugin/dapp/token/commands/token.go
View file @
112b9f75
...
...
@@ -42,6 +42,9 @@ func TokenCmd() *cobra.Command {
CreateRawTokenFinishTxCmd
(),
CreateRawTokenRevokeTxCmd
(),
CreateTokenTransferExecCmd
(),
CreateRawTokenMintTxCmd
(),
CreateRawTokenBurnTxCmd
(),
GetTokenLogsCmd
(),
)
return
cmd
...
...
@@ -465,3 +468,118 @@ func tokenRevoke(cmd *cobra.Command, args []string) {
ctx
:=
jsonclient
.
NewRPCCtx
(
rpcLaddr
,
"token.CreateRawTokenRevokeTx"
,
params
,
nil
)
ctx
.
RunWithoutMarshal
()
}
// CreateRawTokenMintTxCmd create raw token mintage transaction
func
CreateRawTokenMintTxCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"mint"
,
Short
:
"Create a mint token transaction"
,
Run
:
tokenMint
,
}
addTokenMintFlags
(
cmd
)
return
cmd
}
func
addTokenMintFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"symbol"
,
"s"
,
""
,
"token symbol"
)
cmd
.
MarkFlagRequired
(
"symbol"
)
cmd
.
Flags
()
.
Float64P
(
"amount"
,
"a"
,
0
,
"amount of mintage"
)
cmd
.
MarkFlagRequired
(
"amount"
)
cmd
.
Flags
()
.
Float64P
(
"fee"
,
"f"
,
0
,
"token transaction fee"
)
}
func
tokenMint
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
symbol
,
_
:=
cmd
.
Flags
()
.
GetString
(
"symbol"
)
amount
,
_
:=
cmd
.
Flags
()
.
GetFloat64
(
"amount"
)
params
:=
&
tokenty
.
TokenMint
{
Symbol
:
symbol
,
Amount
:
int64
((
amount
+
0.000001
)
*
1e4
)
*
1e4
,
}
ctx
:=
jsonclient
.
NewRPCCtx
(
rpcLaddr
,
"token.CreateRawTokenMintTx"
,
params
,
nil
)
ctx
.
RunWithoutMarshal
()
}
// CreateRawTokenBurnTxCmd create raw token burn transaction
func
CreateRawTokenBurnTxCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"burn"
,
Short
:
"Create a burn token transaction"
,
Run
:
tokenBurn
,
}
addTokenBurnFlags
(
cmd
)
return
cmd
}
func
addTokenBurnFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"symbol"
,
"s"
,
""
,
"token symbol"
)
cmd
.
MarkFlagRequired
(
"symbol"
)
cmd
.
Flags
()
.
Float64P
(
"amount"
,
"a"
,
0
,
"amount of burn"
)
cmd
.
MarkFlagRequired
(
"amount"
)
cmd
.
Flags
()
.
Float64P
(
"fee"
,
"f"
,
0
,
"token transaction fee"
)
}
func
tokenBurn
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
symbol
,
_
:=
cmd
.
Flags
()
.
GetString
(
"symbol"
)
amount
,
_
:=
cmd
.
Flags
()
.
GetFloat64
(
"amount"
)
params
:=
&
tokenty
.
TokenBurn
{
Symbol
:
symbol
,
Amount
:
int64
((
amount
+
0.000001
)
*
1e4
)
*
1e4
,
}
ctx
:=
jsonclient
.
NewRPCCtx
(
rpcLaddr
,
"token.CreateRawTokenBurnTx"
,
params
,
nil
)
ctx
.
RunWithoutMarshal
()
}
// GetTokenLogsCmd get logs of token
func
GetTokenLogsCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"get_token_logs"
,
Short
:
"Get logs of token"
,
Run
:
getTokenLogs
,
}
getTokenLogsFlags
(
cmd
)
return
cmd
}
func
getTokenLogs
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
paraName
,
_
:=
cmd
.
Flags
()
.
GetString
(
"paraName"
)
symbol
,
_
:=
cmd
.
Flags
()
.
GetString
(
"symbol"
)
var
params
rpctypes
.
Query4Jrpc
params
.
Execer
=
getRealExecName
(
paraName
,
"token"
)
params
.
FuncName
=
"GetTokenHistory"
params
.
Payload
=
types
.
MustPBToJSON
(
&
types
.
ReqString
{
Data
:
symbol
})
rpc
,
err
:=
jsonclient
.
NewJSONClient
(
rpcLaddr
)
if
err
!=
nil
{
fmt
.
Fprintln
(
os
.
Stderr
,
err
)
return
}
var
res
tokenty
.
ReplyTokenLogs
err
=
rpc
.
Call
(
"Chain33.Query"
,
params
,
&
res
)
if
err
!=
nil
{
fmt
.
Fprintln
(
os
.
Stderr
,
err
)
return
}
data
,
err
:=
json
.
MarshalIndent
(
res
,
""
,
" "
)
if
err
!=
nil
{
fmt
.
Fprintln
(
os
.
Stderr
,
err
)
return
}
fmt
.
Println
(
string
(
data
))
}
func
getTokenLogsFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"symbol"
,
"s"
,
""
,
"token symbol"
)
cmd
.
MarkFlagRequired
(
"symbol"
)
}
plugin/dapp/token/executor/exec.go
View file @
112b9f75
...
...
@@ -69,3 +69,13 @@ func (t *token) Exec_TransferToExec(payload *types.AssetsTransferToExec, tx *typ
}
return
t
.
ExecTransWithdraw
(
db
,
tx
,
&
tokenAction
,
index
)
}
func
(
t
*
token
)
Exec_TokenMint
(
payload
*
tokenty
.
TokenMint
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
action
:=
newTokenAction
(
t
,
""
,
tx
)
return
action
.
mint
(
payload
)
}
func
(
t
*
token
)
Exec_TokenBurn
(
payload
*
tokenty
.
TokenBurn
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
action
:=
newTokenAction
(
t
,
""
,
tx
)
return
action
.
burn
(
payload
)
}
plugin/dapp/token/executor/exec_del_local.go
View file @
112b9f75
...
...
@@ -5,6 +5,7 @@
package
executor
import
(
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
tokenty
"github.com/33cn/plugin/plugin/dapp/token/types"
)
...
...
@@ -107,6 +108,19 @@ func (t *token) ExecDelLocal_TokenFinishCreate(payload *tokenty.TokenFinishCreat
var
set
[]
*
types
.
KeyValue
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
prepareKey
,
Value
:
types
.
Encode
(
localToken
)})
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
nil
})
table
:=
NewLogsTable
(
t
.
GetLocalDB
())
txIndex
:=
dapp
.
HeightIndexStr
(
t
.
GetHeight
(),
int64
(
index
))
err
=
table
.
Del
([]
byte
(
txIndex
))
if
err
!=
nil
{
return
nil
,
err
}
kv
,
err
:=
table
.
Save
()
if
err
!=
nil
{
return
nil
,
err
}
set
=
append
(
set
,
kv
...
)
return
&
types
.
LocalDBSet
{
KV
:
set
},
nil
}
...
...
@@ -123,3 +137,53 @@ func (t *token) ExecDelLocal_TokenRevokeCreate(payload *tokenty.TokenRevokeCreat
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
prepareKey
,
Value
:
types
.
Encode
(
localToken
)})
return
&
types
.
LocalDBSet
{
KV
:
set
},
nil
}
func
(
t
*
token
)
ExecDelLocal_TokenMint
(
payload
*
tokenty
.
TokenMint
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
localToken
,
err
:=
loadLocalToken
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
,
t
.
GetLocalDB
())
if
err
!=
nil
{
return
nil
,
err
}
localToken
=
resetMint
(
localToken
,
t
.
GetHeight
(),
t
.
GetBlockTime
(),
payload
.
Amount
)
key
:=
calcTokenStatusKeyLocal
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
)
var
set
[]
*
types
.
KeyValue
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
types
.
Encode
(
localToken
)})
table
:=
NewLogsTable
(
t
.
GetLocalDB
())
txIndex
:=
dapp
.
HeightIndexStr
(
t
.
GetHeight
(),
int64
(
index
))
err
=
table
.
Del
([]
byte
(
txIndex
))
if
err
!=
nil
{
return
nil
,
err
}
kv
,
err
:=
table
.
Save
()
if
err
!=
nil
{
return
nil
,
err
}
set
=
append
(
set
,
kv
...
)
return
&
types
.
LocalDBSet
{
KV
:
set
},
nil
}
func
(
t
*
token
)
ExecDelLocal_TokenBurn
(
payload
*
tokenty
.
TokenBurn
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
localToken
,
err
:=
loadLocalToken
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
,
t
.
GetLocalDB
())
if
err
!=
nil
{
return
nil
,
err
}
localToken
=
resetBurn
(
localToken
,
t
.
GetHeight
(),
t
.
GetBlockTime
(),
payload
.
Amount
)
key
:=
calcTokenStatusKeyLocal
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
)
var
set
[]
*
types
.
KeyValue
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
types
.
Encode
(
localToken
)})
table
:=
NewLogsTable
(
t
.
GetLocalDB
())
txIndex
:=
dapp
.
HeightIndexStr
(
t
.
GetHeight
(),
int64
(
index
))
err
=
table
.
Del
([]
byte
(
txIndex
))
if
err
!=
nil
{
return
nil
,
err
}
kv
,
err
:=
table
.
Save
()
if
err
!=
nil
{
return
nil
,
err
}
set
=
append
(
set
,
kv
...
)
return
&
types
.
LocalDBSet
{
KV
:
set
},
nil
}
plugin/dapp/token/executor/exec_local.go
View file @
112b9f75
...
...
@@ -5,7 +5,10 @@
package
executor
import
(
"encoding/hex"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
tokenty
"github.com/33cn/plugin/plugin/dapp/token/types"
)
...
...
@@ -107,6 +110,19 @@ func (t *token) ExecLocal_TokenFinishCreate(payload *tokenty.TokenFinishCreate,
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
types
.
Encode
(
localToken
)})
kv
:=
AddTokenToAssets
(
payload
.
Owner
,
t
.
GetLocalDB
(),
payload
.
Symbol
)
set
=
append
(
set
,
kv
...
)
table
:=
NewLogsTable
(
t
.
GetLocalDB
())
txIndex
:=
dapp
.
HeightIndexStr
(
t
.
GetHeight
(),
int64
(
index
))
err
=
table
.
Add
(
&
tokenty
.
LocalLogs
{
Symbol
:
payload
.
Symbol
,
TxIndex
:
txIndex
,
ActionType
:
tokenty
.
TokenActionFinishCreate
,
TxHash
:
hex
.
EncodeToString
(
tx
.
Hash
())})
if
err
!=
nil
{
return
nil
,
err
}
kv
,
err
=
table
.
Save
()
if
err
!=
nil
{
return
nil
,
err
}
set
=
append
(
set
,
kv
...
)
return
&
types
.
LocalDBSet
{
KV
:
set
},
nil
}
...
...
@@ -182,6 +198,16 @@ func setRevoked(t *tokenty.LocalToken, height, time int64) *tokenty.LocalToken {
return
t
}
func
setMint
(
t
*
tokenty
.
LocalToken
,
height
,
time
,
amount
int64
)
*
tokenty
.
LocalToken
{
t
.
Total
=
t
.
Total
+
amount
return
t
}
func
setBurn
(
t
*
tokenty
.
LocalToken
,
height
,
time
,
amount
int64
)
*
tokenty
.
LocalToken
{
t
.
Total
=
t
.
Total
-
amount
return
t
}
func
resetCreated
(
t
*
tokenty
.
LocalToken
)
*
tokenty
.
LocalToken
{
t
.
CreatedTime
=
0
t
.
CreatedHeight
=
0
...
...
@@ -195,3 +221,63 @@ func resetRevoked(t *tokenty.LocalToken) *tokenty.LocalToken {
t
.
Status
=
tokenty
.
TokenStatusPreCreated
return
t
}
func
resetMint
(
t
*
tokenty
.
LocalToken
,
height
,
time
,
amount
int64
)
*
tokenty
.
LocalToken
{
t
.
Total
=
t
.
Total
-
amount
return
t
}
func
resetBurn
(
t
*
tokenty
.
LocalToken
,
height
,
time
,
amount
int64
)
*
tokenty
.
LocalToken
{
t
.
Total
=
t
.
Total
+
amount
return
t
}
func
(
t
*
token
)
ExecLocal_TokenMint
(
payload
*
tokenty
.
TokenMint
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
localToken
,
err
:=
loadLocalToken
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
,
t
.
GetLocalDB
())
if
err
!=
nil
{
return
nil
,
err
}
localToken
=
setMint
(
localToken
,
t
.
GetHeight
(),
t
.
GetBlockTime
(),
payload
.
Amount
)
var
set
[]
*
types
.
KeyValue
key
:=
calcTokenStatusKeyLocal
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
)
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
types
.
Encode
(
localToken
)})
table
:=
NewLogsTable
(
t
.
GetLocalDB
())
txIndex
:=
dapp
.
HeightIndexStr
(
t
.
GetHeight
(),
int64
(
index
))
err
=
table
.
Add
(
&
tokenty
.
LocalLogs
{
Symbol
:
payload
.
Symbol
,
TxIndex
:
txIndex
,
ActionType
:
tokenty
.
TokenActionMint
,
TxHash
:
"0x"
+
hex
.
EncodeToString
(
tx
.
Hash
())})
if
err
!=
nil
{
return
nil
,
err
}
kv
,
err
:=
table
.
Save
()
if
err
!=
nil
{
return
nil
,
err
}
set
=
append
(
set
,
kv
...
)
return
&
types
.
LocalDBSet
{
KV
:
set
},
nil
}
func
(
t
*
token
)
ExecLocal_TokenBurn
(
payload
*
tokenty
.
TokenBurn
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
localToken
,
err
:=
loadLocalToken
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
,
t
.
GetLocalDB
())
if
err
!=
nil
{
return
nil
,
err
}
localToken
=
setBurn
(
localToken
,
t
.
GetHeight
(),
t
.
GetBlockTime
(),
payload
.
Amount
)
var
set
[]
*
types
.
KeyValue
key
:=
calcTokenStatusKeyLocal
(
payload
.
Symbol
,
tx
.
From
(),
tokenty
.
TokenStatusCreated
)
set
=
append
(
set
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
types
.
Encode
(
localToken
)})
table
:=
NewLogsTable
(
t
.
GetLocalDB
())
txIndex
:=
dapp
.
HeightIndexStr
(
t
.
GetHeight
(),
int64
(
index
))
err
=
table
.
Add
(
&
tokenty
.
LocalLogs
{
Symbol
:
payload
.
Symbol
,
TxIndex
:
txIndex
,
ActionType
:
tokenty
.
TokenActionBurn
,
TxHash
:
"0x"
+
hex
.
EncodeToString
(
tx
.
Hash
())})
if
err
!=
nil
{
return
nil
,
err
}
kv
,
err
:=
table
.
Save
()
if
err
!=
nil
{
return
nil
,
err
}
set
=
append
(
set
,
kv
...
)
return
&
types
.
LocalDBSet
{
KV
:
set
},
nil
}
plugin/dapp/token/executor/logs.go
0 → 100644
View file @
112b9f75
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
executor
// 记录token 的更改记录,
// 包含创建完成, 铸币, 以后可能包含燃烧等
import
(
dbm
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
pty
"github.com/33cn/plugin/plugin/dapp/token/types"
)
var
opt_logs_table
=
&
table
.
Option
{
Prefix
:
"LODB-token"
,
Name
:
"logs"
,
Primary
:
"txIndex"
,
Index
:
[]
string
{
"symbol"
,
},
}
// LogsRow row
type
LogsRow
struct
{
*
pty
.
LocalLogs
}
// NewOrderRow create row
func
NewOrderRow
()
*
LogsRow
{
return
&
LogsRow
{
LocalLogs
:
nil
}
}
// CreateRow create row
func
(
r
*
LogsRow
)
CreateRow
()
*
table
.
Row
{
return
&
table
.
Row
{
Data
:
&
pty
.
LocalLogs
{}}
}
// SetPayload set payload
func
(
r
*
LogsRow
)
SetPayload
(
data
types
.
Message
)
error
{
if
d
,
ok
:=
data
.
(
*
pty
.
LocalLogs
);
ok
{
r
.
LocalLogs
=
d
return
nil
}
return
types
.
ErrTypeAsset
}
// Get get index key
func
(
r
*
LogsRow
)
Get
(
key
string
)
([]
byte
,
error
)
{
switch
key
{
case
"txIndex"
:
return
[]
byte
(
r
.
TxIndex
),
nil
case
"symbol"
:
return
[]
byte
(
r
.
Symbol
),
nil
default
:
return
nil
,
types
.
ErrNotFound
}
}
// NewLogsTable create table
func
NewLogsTable
(
kvdb
dbm
.
KV
)
*
table
.
Table
{
rowMeta
:=
NewOrderRow
()
err
:=
rowMeta
.
SetPayload
(
&
pty
.
LocalLogs
{})
if
err
!=
nil
{
panic
(
err
)
}
t
,
err
:=
table
.
NewTable
(
rowMeta
,
kvdb
,
opt_logs_table
)
if
err
!=
nil
{
panic
(
err
)
}
return
t
}
func
list
(
db
dbm
.
KVDB
,
indexName
string
,
data
*
pty
.
LocalLogs
,
count
,
direction
int32
)
([]
*
table
.
Row
,
error
)
{
query
:=
NewLogsTable
(
db
)
.
GetQuery
(
db
)
var
primary
[]
byte
if
len
(
data
.
TxIndex
)
>
0
{
primary
=
[]
byte
(
data
.
TxIndex
)
}
cur
:=
&
LogsRow
{
LocalLogs
:
data
}
index
,
err
:=
cur
.
Get
(
indexName
)
if
err
!=
nil
{
tokenlog
.
Error
(
"query List failed"
,
"key"
,
string
(
primary
),
"param"
,
data
,
"err"
,
err
)
return
nil
,
err
}
tokenlog
.
Debug
(
"query List dbg"
,
"indexName"
,
indexName
,
"index"
,
string
(
index
),
"primary"
,
primary
,
"count"
,
count
,
"direction"
,
direction
)
rows
,
err
:=
query
.
ListIndex
(
indexName
,
index
,
primary
,
count
,
direction
)
if
err
!=
nil
{
tokenlog
.
Error
(
"query List failed"
,
"key"
,
string
(
primary
),
"param"
,
data
,
"err"
,
err
)
return
nil
,
err
}
if
len
(
rows
)
==
0
{
return
nil
,
types
.
ErrNotFound
}
return
rows
,
nil
}
plugin/dapp/token/executor/query.go
View file @
112b9f75
...
...
@@ -69,3 +69,25 @@ func (t *token) Query_GetTxByToken(in *tokenty.ReqTokenTx) (types.Message, error
}
return
t
.
getTxByToken
(
in
)
}
// Query_GetTokenHistory 获取token 的变更历史
func
(
t
*
token
)
Query_GetTokenHistory
(
in
*
types
.
ReqString
)
(
types
.
Message
,
error
)
{
if
in
==
nil
{
return
nil
,
types
.
ErrInvalidParam
}
rows
,
err
:=
list
(
t
.
GetLocalDB
(),
"symbol"
,
&
tokenty
.
LocalLogs
{
Symbol
:
in
.
Data
},
-
1
,
0
)
if
err
!=
nil
{
tokenlog
.
Error
(
"Query_GetTokenHistory"
,
"err"
,
err
)
return
nil
,
err
}
var
replys
tokenty
.
ReplyTokenLogs
for
_
,
row
:=
range
rows
{
o
,
ok
:=
row
.
Data
.
(
*
tokenty
.
LocalLogs
)
if
!
ok
{
tokenlog
.
Error
(
"Query_GetTokenHistory"
,
"err"
,
"bad row type"
)
return
nil
,
types
.
ErrTypeAsset
}
replys
.
Logs
=
append
(
replys
.
Logs
,
o
)
}
return
&
replys
,
nil
}
plugin/dapp/token/executor/token_new_test.go
View file @
112b9f75
...
...
@@ -157,6 +157,7 @@ func TestPrecreate(t *testing.T) {
Total
:
tokenAmount
,
Price
:
tokenPrice
,
Owner
:
addr
,
Category
:
pty
.
CategoryMintBurnSupport
,
}
precreate
:=
&
pty
.
TokenAction
{
Ty
:
pty
.
TokenActionPreCreate
,
...
...
@@ -312,6 +313,78 @@ func TestQueryAsset(t *testing.T) {
}
func
TestTokenMint
(
t
*
testing
.
T
)
{
if
!
isMainNetTest
{
return
}
fmt
.
Println
(
"TestTokenMint start"
)
defer
fmt
.
Println
(
"TestTokenMint end"
)
v
:=
&
pty
.
TokenAction_TokenMint
{
TokenMint
:
&
pty
.
TokenMint
{
Symbol
:
tokenSym
,
Amount
:
transAmount
}}
transfer
:=
&
pty
.
TokenAction
{
Value
:
v
,
Ty
:
pty
.
ActionTransfer
}
tx
:=
&
types
.
Transaction
{
Execer
:
[]
byte
(
execName
),
Payload
:
types
.
Encode
(
transfer
),
Fee
:
fee
,
To
:
addrexec
}
tx
.
Nonce
=
r
.
Int63
()
tx
.
Sign
(
types
.
SECP256K1
,
privkey
)
reply
,
err
:=
mainClient
.
SendTransaction
(
context
.
Background
(),
tx
)
if
err
!=
nil
{
fmt
.
Println
(
"err"
,
err
)
t
.
Error
(
err
)
return
}
if
!
reply
.
IsOk
{
fmt
.
Println
(
"err = "
,
reply
.
GetMsg
())
t
.
Error
(
ErrTest
)
return
}
if
!
waitTx
(
tx
.
Hash
())
{
t
.
Error
(
ErrTest
)
return
}
}
func
TestQueryTokenLogs
(
t
*
testing
.
T
)
{
if
!
isParaNetTest
{
return
}
fmt
.
Println
(
"TestQueryTokenLogs start"
)
defer
fmt
.
Println
(
"TestQueryTokenLogs end"
)
var
req
types
.
ChainExecutor
req
.
Driver
=
execName
req
.
FuncName
=
"GetTokenHistory"
req
.
Param
=
types
.
Encode
(
&
types
.
ReqString
{
Data
:
tokenSym
})
reply
,
err
:=
paraClient
.
QueryChain
(
context
.
Background
(),
&
req
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
t
.
Error
(
err
)
return
}
if
!
reply
.
IsOk
{
fmt
.
Println
(
"Query reply err"
)
t
.
Error
(
ErrTest
)
return
}
var
res
pty
.
ReplyTokenLogs
err
=
types
.
Decode
(
reply
.
Msg
,
&
res
)
if
err
!=
nil
{
t
.
Error
(
err
)
return
}
assert
.
Equal
(
t
,
2
,
len
(
res
.
Logs
))
for
_
,
l
:=
range
res
.
Logs
{
fmt
.
Println
(
l
.
Symbol
)
fmt
.
Println
(
l
.
TxHash
)
fmt
.
Println
(
l
.
TxIndex
)
fmt
.
Println
(
l
.
ActionType
)
}
}
//***************************************************
//**************common actions for Test**************
//***************************************************
...
...
plugin/dapp/token/executor/token_test.go
0 → 100644
View file @
112b9f75
package
executor
import
(
"testing"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/crypto"
dbm
"github.com/33cn/chain33/common/db"
pty
"github.com/33cn/plugin/plugin/dapp/token/types"
"github.com/stretchr/testify/assert"
//"github.com/33cn/chain33/types/jsonpb"
)
type
execEnv
struct
{
blockTime
int64
blockHeight
int64
difficulty
uint64
}
var
(
Symbol
=
"TEST"
AssetExecToken
=
"token"
AssetExecPara
=
"paracross"
PrivKeyA
=
"0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b"
// 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4
PrivKeyB
=
"0x19c069234f9d3e61135fefbeb7791b149cdf6af536f26bebb310d4cd22c3fee4"
// 1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR
PrivKeyC
=
"0x7a80a1f75d7360c6123c32a78ecf978c1ac55636f87892df38d8b85a9aeff115"
// 1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k
PrivKeyD
=
"0xcacb1f5d51700aea07fca2246ab43b0917d70405c65edea9b5063d72eb5c6b71"
// 1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs
Nodes
=
[][]
byte
{
[]
byte
(
"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"
),
[]
byte
(
"1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR"
),
[]
byte
(
"1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k"
),
[]
byte
(
"1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs"
),
}
)
func
TestToken
(
t
*
testing
.
T
)
{
types
.
SetTitleOnlyForTest
(
"chain33"
)
tokenTotal
:=
int64
(
10000
*
1e8
)
tokenBurn
:=
int64
(
10
*
1e8
)
tokenMint
:=
int64
(
20
*
1e8
)
total
:=
int64
(
100000
)
accountA
:=
types
.
Account
{
Balance
:
total
,
Frozen
:
0
,
Addr
:
string
(
Nodes
[
0
]),
}
accountB
:=
types
.
Account
{
Balance
:
total
,
Frozen
:
0
,
Addr
:
string
(
Nodes
[
1
]),
}
execAddr
:=
address
.
ExecAddress
(
pty
.
TokenX
)
stateDB
,
_
:=
dbm
.
NewGoMemDB
(
"1"
,
"2"
,
100
)
_
,
_
,
kvdb
:=
util
.
CreateTestDB
()
accA
,
_
:=
account
.
NewAccountDB
(
AssetExecPara
,
Symbol
,
stateDB
)
accA
.
SaveExecAccount
(
execAddr
,
&
accountA
)
accB
,
_
:=
account
.
NewAccountDB
(
AssetExecPara
,
Symbol
,
stateDB
)
accB
.
SaveExecAccount
(
execAddr
,
&
accountB
)
env
:=
execEnv
{
10
,
types
.
GetDappFork
(
pty
.
TokenX
,
pty
.
ForkTokenSymbolWithNumberX
),
1539918074
,
}
// set config key
item
:=
&
types
.
ConfigItem
{
Key
:
"mavl-manage-token-blacklist"
,
Value
:
&
types
.
ConfigItem_Arr
{
Arr
:
&
types
.
ArrayConfig
{
Value
:
[]
string
{
"bty"
}},
},
}
stateDB
.
Set
([]
byte
(
item
.
Key
),
types
.
Encode
(
item
))
item2
:=
&
types
.
ConfigItem
{
Key
:
"mavl-manage-token-finisher"
,
Value
:
&
types
.
ConfigItem_Arr
{
Arr
:
&
types
.
ArrayConfig
{
Value
:
[]
string
{
string
(
Nodes
[
0
])}},
},
}
stateDB
.
Set
([]
byte
(
item2
.
Key
),
types
.
Encode
(
item2
))
// create token
// 创建
//ty := pty.TokenType{}
p1
:=
&
pty
.
TokenPreCreate
{
Name
:
Symbol
,
Symbol
:
Symbol
,
Introduction
:
Symbol
,
Total
:
tokenTotal
,
Price
:
0
,
Owner
:
string
(
Nodes
[
0
]),
Category
:
pty
.
CategoryMintBurnSupport
,
}
//v, _ := types.PBToJSON(p1)
createTx
,
err
:=
types
.
CallCreateTransaction
(
pty
.
TokenX
,
"TokenPreCreate"
,
p1
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process"
,
"err"
,
err
)
}
createTx
,
err
=
signTx
(
createTx
,
PrivKeyA
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process sign"
,
"err"
,
err
)
}
exec
:=
newToken
()
exec
.
SetStateDB
(
stateDB
)
exec
.
SetLocalDB
(
kvdb
)
exec
.
SetEnv
(
env
.
blockHeight
,
env
.
blockTime
,
env
.
difficulty
)
receipt
,
err
:=
exec
.
Exec
(
createTx
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
receipt
)
t
.
Log
(
receipt
)
for
_
,
kv
:=
range
receipt
.
KV
{
stateDB
.
Set
(
kv
.
Key
,
kv
.
Value
)
}
receiptDate
:=
&
types
.
ReceiptData
{
Ty
:
receipt
.
Ty
,
Logs
:
receipt
.
Logs
}
set
,
err
:=
exec
.
ExecLocal
(
createTx
,
receiptDate
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
set
)
p2
:=
&
pty
.
TokenFinishCreate
{
Symbol
:
Symbol
,
Owner
:
string
(
Nodes
[
0
]),
}
//v, _ := types.PBToJSON(p1)
createTx2
,
err
:=
types
.
CallCreateTransaction
(
pty
.
TokenX
,
"TokenFinishCreate"
,
p2
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process"
,
"err"
,
err
)
}
createTx2
,
err
=
signTx
(
createTx2
,
PrivKeyA
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process sign"
,
"err"
,
err
)
}
exec
.
SetEnv
(
env
.
blockHeight
+
1
,
env
.
blockTime
+
1
,
env
.
difficulty
)
receipt
,
err
=
exec
.
Exec
(
createTx2
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
receipt
)
//t.Log(receipt)
for
_
,
kv
:=
range
receipt
.
KV
{
stateDB
.
Set
(
kv
.
Key
,
kv
.
Value
)
}
accDB
,
_
:=
account
.
NewAccountDB
(
pty
.
TokenX
,
Symbol
,
stateDB
)
accChcek
:=
accDB
.
LoadAccount
(
string
(
Nodes
[
0
]))
assert
.
Equal
(
t
,
tokenTotal
,
accChcek
.
Balance
)
receiptDate
=
&
types
.
ReceiptData
{
Ty
:
receipt
.
Ty
,
Logs
:
receipt
.
Logs
}
set
,
err
=
exec
.
ExecLocal
(
createTx2
,
receiptDate
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
set
)
// mint burn
p3
:=
&
pty
.
TokenMint
{
Symbol
:
Symbol
,
Amount
:
tokenMint
,
}
//v, _ := types.PBToJSON(p1)
createTx3
,
err
:=
types
.
CallCreateTransaction
(
pty
.
TokenX
,
"TokenMint"
,
p3
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process"
,
"err"
,
err
)
}
createTx3
,
err
=
signTx
(
createTx3
,
PrivKeyA
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process sign"
,
"err"
,
err
)
}
exec
.
SetEnv
(
env
.
blockHeight
+
2
,
env
.
blockTime
+
2
,
env
.
difficulty
)
receipt
,
err
=
exec
.
Exec
(
createTx3
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
receipt
)
//t.Log(receipt)
for
_
,
kv
:=
range
receipt
.
KV
{
stateDB
.
Set
(
kv
.
Key
,
kv
.
Value
)
}
accChcek
=
accDB
.
LoadAccount
(
string
(
Nodes
[
0
]))
assert
.
Equal
(
t
,
tokenTotal
+
tokenMint
,
accChcek
.
Balance
)
receiptDate
=
&
types
.
ReceiptData
{
Ty
:
receipt
.
Ty
,
Logs
:
receipt
.
Logs
}
set
,
err
=
exec
.
ExecLocal
(
createTx3
,
receiptDate
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
set
)
p4
:=
&
pty
.
TokenBurn
{
Symbol
:
Symbol
,
Amount
:
tokenBurn
,
}
//v, _ := types.PBToJSON(p1)
createTx4
,
err
:=
types
.
CallCreateTransaction
(
pty
.
TokenX
,
"TokenBurn"
,
p4
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process"
,
"err"
,
err
)
}
createTx4
,
err
=
signTx
(
createTx4
,
PrivKeyA
)
if
err
!=
nil
{
t
.
Error
(
"RPC_Default_Process sign"
,
"err"
,
err
)
}
exec
.
SetEnv
(
env
.
blockHeight
+
1
,
env
.
blockTime
+
1
,
env
.
difficulty
)
receipt
,
err
=
exec
.
Exec
(
createTx4
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
receipt
)
//t.Log(receipt)
for
_
,
kv
:=
range
receipt
.
KV
{
stateDB
.
Set
(
kv
.
Key
,
kv
.
Value
)
}
accChcek
=
accDB
.
LoadAccount
(
string
(
Nodes
[
0
]))
assert
.
Equal
(
t
,
tokenTotal
+
tokenMint
-
tokenBurn
,
accChcek
.
Balance
)
receiptDate
=
&
types
.
ReceiptData
{
Ty
:
receipt
.
Ty
,
Logs
:
receipt
.
Logs
}
set
,
err
=
exec
.
ExecLocal
(
createTx4
,
receiptDate
,
int
(
1
))
assert
.
Nil
(
t
,
err
)
assert
.
NotNil
(
t
,
set
)
}
func
signTx
(
tx
*
types
.
Transaction
,
hexPrivKey
string
)
(
*
types
.
Transaction
,
error
)
{
signType
:=
types
.
SECP256K1
c
,
err
:=
crypto
.
New
(
types
.
GetSignName
(
pty
.
TokenX
,
signType
))
if
err
!=
nil
{
return
tx
,
err
}
bytes
,
err
:=
common
.
FromHex
(
hexPrivKey
[
:
])
if
err
!=
nil
{
return
tx
,
err
}
privKey
,
err
:=
c
.
PrivKeyFromBytes
(
bytes
)
if
err
!=
nil
{
return
tx
,
err
}
tx
.
Sign
(
int32
(
signType
),
privKey
)
return
tx
,
nil
}
plugin/dapp/token/executor/tokendb.go
View file @
112b9f75
...
...
@@ -40,7 +40,10 @@ func newTokenDB(preCreate *pty.TokenPreCreate, creator string, height int64) *to
func
(
t
*
tokenDB
)
save
(
db
dbm
.
KV
,
key
[]
byte
)
{
set
:=
t
.
getKVSet
(
key
)
for
i
:=
0
;
i
<
len
(
set
);
i
++
{
db
.
Set
(
set
[
i
]
.
GetKey
(),
set
[
i
]
.
Value
)
err
:=
db
.
Set
(
set
[
i
]
.
GetKey
(),
set
[
i
]
.
Value
)
if
err
!=
nil
{
panic
(
err
)
}
}
}
...
...
@@ -59,6 +62,48 @@ func (t *tokenDB) getKVSet(key []byte) (kvset []*types.KeyValue) {
return
kvset
}
func
loadTokenDB
(
db
dbm
.
KV
,
symbol
string
)
(
*
tokenDB
,
error
)
{
token
,
err
:=
db
.
Get
(
calcTokenKey
(
symbol
))
if
err
!=
nil
{
tokenlog
.
Error
(
"tokendb load "
,
"Can't get token form db for token"
,
symbol
)
return
nil
,
pty
.
ErrTokenNotExist
}
var
t
pty
.
Token
err
=
types
.
Decode
(
token
,
&
t
)
if
err
!=
nil
{
tokenlog
.
Error
(
"tokendb load"
,
"Can't decode token info"
,
symbol
)
return
nil
,
err
}
return
&
tokenDB
{
t
},
nil
}
func
(
t
*
tokenDB
)
mint
(
db
dbm
.
KV
,
addr
string
,
amount
int64
)
([]
*
types
.
KeyValue
,
[]
*
types
.
ReceiptLog
,
error
)
{
if
t
.
token
.
Owner
!=
addr
{
return
nil
,
nil
,
types
.
ErrNotAllow
}
if
t
.
token
.
Total
+
amount
>
types
.
MaxTokenBalance
{
return
nil
,
nil
,
types
.
ErrAmount
}
prevToken
:=
t
.
token
t
.
token
.
Total
+=
amount
kvs
:=
append
(
t
.
getKVSet
(
calcTokenKey
(
t
.
token
.
Symbol
)),
t
.
getKVSet
(
calcTokenAddrNewKeyS
(
t
.
token
.
Symbol
,
t
.
token
.
Owner
))
...
)
logs
:=
[]
*
types
.
ReceiptLog
{{
Ty
:
pty
.
TyLogTokenMint
,
Log
:
types
.
Encode
(
&
pty
.
ReceiptTokenAmount
{
Prev
:
&
prevToken
,
Current
:
&
t
.
token
})}}
return
kvs
,
logs
,
nil
}
func
(
t
*
tokenDB
)
burn
(
db
dbm
.
KV
,
amount
int64
)
([]
*
types
.
KeyValue
,
[]
*
types
.
ReceiptLog
,
error
)
{
if
t
.
token
.
Total
<
amount
{
return
nil
,
nil
,
types
.
ErrNoBalance
}
prevToken
:=
t
.
token
t
.
token
.
Total
-=
amount
kvs
:=
append
(
t
.
getKVSet
(
calcTokenKey
(
t
.
token
.
Symbol
)),
t
.
getKVSet
(
calcTokenAddrNewKeyS
(
t
.
token
.
Symbol
,
t
.
token
.
Owner
))
...
)
logs
:=
[]
*
types
.
ReceiptLog
{{
Ty
:
pty
.
TyLogTokenBurn
,
Log
:
types
.
Encode
(
&
pty
.
ReceiptTokenAmount
{
Prev
:
&
prevToken
,
Current
:
&
t
.
token
})}}
return
kvs
,
logs
,
nil
}
func
getTokenFromDB
(
db
dbm
.
KV
,
symbol
string
,
owner
string
)
(
*
pty
.
Token
,
error
)
{
key
:=
calcTokenAddrKeyS
(
symbol
,
owner
)
value
,
err
:=
db
.
Get
(
key
)
...
...
@@ -468,3 +513,87 @@ func validSymbolWithHeight(cs []byte, height int64) bool {
}
return
validSymbolOriginal
(
cs
)
}
// 铸币不可控, 也是麻烦。 2选1
// 1. 谁可以发起
// 2. 是否需要审核 这个会增加管理的成本
// 现在实现选择 1
func
(
action
*
tokenAction
)
mint
(
mint
*
pty
.
TokenMint
)
(
*
types
.
Receipt
,
error
)
{
if
mint
==
nil
{
return
nil
,
types
.
ErrInvalidParam
}
if
mint
.
GetAmount
()
<
0
||
mint
.
GetAmount
()
>
types
.
MaxTokenBalance
||
mint
.
GetSymbol
()
==
""
{
return
nil
,
types
.
ErrInvalidParam
}
tokendb
,
err
:=
loadTokenDB
(
action
.
db
,
mint
.
GetSymbol
())
if
err
!=
nil
{
return
nil
,
err
}
if
tokendb
.
token
.
Category
&
pty
.
CategoryMintBurnSupport
==
0
{
tokenlog
.
Error
(
"Can't mint category"
,
"category"
,
tokendb
.
token
.
Category
,
"support"
,
pty
.
CategoryMintBurnSupport
)
return
nil
,
types
.
ErrNotSupport
}
kvs
,
logs
,
err
:=
tokendb
.
mint
(
action
.
db
,
action
.
fromaddr
,
mint
.
Amount
)
if
err
!=
nil
{
tokenlog
.
Error
(
"token mint "
,
"symbol"
,
mint
.
GetSymbol
(),
"error"
,
err
,
"from"
,
action
.
fromaddr
,
"owner"
,
tokendb
.
token
.
Owner
)
return
nil
,
err
}
tokenAccount
,
err
:=
account
.
NewAccountDB
(
"token"
,
mint
.
GetSymbol
(),
action
.
db
)
if
err
!=
nil
{
return
nil
,
err
}
tokenlog
.
Debug
(
"mint"
,
"token.Owner"
,
mint
.
Symbol
,
"token.GetTotal()"
,
mint
.
Amount
)
receipt
,
err
:=
tokenAccount
.
Mint
(
action
.
fromaddr
,
mint
.
Amount
)
if
err
!=
nil
{
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
return
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kvs
,
Logs
:
logs
},
nil
}
func
(
action
*
tokenAction
)
burn
(
burn
*
pty
.
TokenBurn
)
(
*
types
.
Receipt
,
error
)
{
if
burn
==
nil
{
return
nil
,
types
.
ErrInvalidParam
}
if
burn
.
GetAmount
()
<
0
||
burn
.
GetAmount
()
>
types
.
MaxTokenBalance
||
burn
.
GetSymbol
()
==
""
{
return
nil
,
types
.
ErrInvalidParam
}
tokendb
,
err
:=
loadTokenDB
(
action
.
db
,
burn
.
GetSymbol
())
if
err
!=
nil
{
return
nil
,
err
}
if
tokendb
.
token
.
Category
&
pty
.
CategoryMintBurnSupport
==
0
{
tokenlog
.
Error
(
"Can't burn category"
,
"category"
,
tokendb
.
token
.
Category
,
"support"
,
pty
.
CategoryMintBurnSupport
)
return
nil
,
types
.
ErrNotSupport
}
kvs
,
logs
,
err
:=
tokendb
.
burn
(
action
.
db
,
burn
.
Amount
)
if
err
!=
nil
{
tokenlog
.
Error
(
"token burn "
,
"symbol"
,
burn
.
GetSymbol
(),
"error"
,
err
,
"from"
,
action
.
fromaddr
,
"owner"
,
tokendb
.
token
.
Owner
)
return
nil
,
err
}
tokenAccount
,
err
:=
account
.
NewAccountDB
(
"token"
,
burn
.
GetSymbol
(),
action
.
db
)
if
err
!=
nil
{
return
nil
,
err
}
tokenlog
.
Debug
(
"burn"
,
"token.Owner"
,
burn
.
Symbol
,
"token.GetTotal()"
,
burn
.
Amount
)
receipt
,
err
:=
tokenAccount
.
Burn
(
action
.
fromaddr
,
burn
.
Amount
)
if
err
!=
nil
{
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
return
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kvs
,
Logs
:
logs
},
nil
}
plugin/dapp/token/executor/transwithdraw.go
View file @
112b9f75
...
...
@@ -172,7 +172,10 @@ func updateAddrReciver(cachedb dbm.KVDB, token string, addr string, amount int64
}
else
{
recv
-=
amount
}
setAddrReciver
(
cachedb
,
token
,
addr
,
recv
)
err
=
setAddrReciver
(
cachedb
,
token
,
addr
,
recv
)
if
err
!=
nil
{
return
nil
,
err
}
//keyvalue
return
getAddrReciverKV
(
token
,
addr
,
recv
),
nil
}
plugin/dapp/token/proto/token.proto
View file @
112b9f75
...
...
@@ -15,6 +15,8 @@ message TokenAction {
AssetsWithdraw
withdraw
=
5
;
AssetsGenesis
genesis
=
6
;
AssetsTransferToExec
transferToExec
=
8
;
TokenMint
tokenMint
=
9
;
TokenBurn
tokenBurn
=
10
;
}
int32
Ty
=
7
;
}
...
...
@@ -40,6 +42,16 @@ message TokenRevokeCreate {
string
owner
=
2
;
}
message
TokenMint
{
string
symbol
=
1
;
int64
amount
=
2
;
}
message
TokenBurn
{
string
symbol
=
1
;
int64
amount
=
2
;
}
// state db
message
Token
{
string
name
=
1
;
...
...
@@ -60,6 +72,11 @@ message ReceiptToken {
int32
status
=
3
;
}
message
ReceiptTokenAmount
{
Token
prev
=
1
;
Token
current
=
2
;
}
// local
message
LocalToken
{
string
name
=
1
;
...
...
@@ -82,6 +99,13 @@ message LocalToken {
int32
category
=
17
;
}
message
LocalLogs
{
string
symbol
=
1
;
string
txIndex
=
2
;
int32
actionType
=
3
;
string
txHash
=
4
;
}
// query
message
ReqTokens
{
bool
queryAll
=
1
;
...
...
@@ -142,6 +166,10 @@ message ReqTokenTx {
string
addr
=
7
;
}
message
ReplyTokenLogs
{
repeated
LocalLogs
logs
=
1
;
}
service
token
{
// token 对外提供服务的接口
//区块链接口
...
...
plugin/dapp/token/rpc/rpc.go
View file @
112b9f75
...
...
@@ -121,3 +121,29 @@ func (c *Jrpc) CreateRawTokenRevokeTx(param *tokenty.TokenRevokeCreate, result *
*
result
=
hex
.
EncodeToString
(
data
)
return
nil
}
// CreateRawTokenMintTx 创建未签名的mint Token交易
func
(
c
*
Jrpc
)
CreateRawTokenMintTx
(
param
*
tokenty
.
TokenMint
,
result
*
interface
{})
error
{
if
param
==
nil
||
param
.
Symbol
==
""
||
param
.
Amount
<=
0
{
return
types
.
ErrInvalidParam
}
data
,
err
:=
types
.
CallCreateTx
(
types
.
ExecName
(
tokenty
.
TokenX
),
"TokenMint"
,
param
)
if
err
!=
nil
{
return
err
}
*
result
=
hex
.
EncodeToString
(
data
)
return
nil
}
// CreateRawTokenBurnTx 创建未签名的 burn Token交易
func
(
c
*
Jrpc
)
CreateRawTokenBurnTx
(
param
*
tokenty
.
TokenBurn
,
result
*
interface
{})
error
{
if
param
==
nil
||
param
.
Symbol
==
""
||
param
.
Amount
<=
0
{
return
types
.
ErrInvalidParam
}
data
,
err
:=
types
.
CallCreateTx
(
types
.
ExecName
(
tokenty
.
TokenX
),
"TokenBurn"
,
param
)
if
err
!=
nil
{
return
err
}
*
result
=
hex
.
EncodeToString
(
data
)
return
nil
}
plugin/dapp/token/types/const.go
View file @
112b9f75
...
...
@@ -19,6 +19,10 @@ const (
TokenActionRevokeCreate
=
9
// TokenActionTransferToExec for token transfer to exec
TokenActionTransferToExec
=
11
// TokenActionMint for token mint
TokenActionMint
=
12
// TokenActionBurn for token burn
TokenActionBurn
=
13
)
// token status
...
...
@@ -72,6 +76,10 @@ const (
TyLogTokenGenesisTransfer
=
321
// TyLogTokenGenesisDeposit log for token genesis deposit
TyLogTokenGenesisDeposit
=
322
// TyLogTokenMint log for token mint
TyLogTokenMint
=
323
// TyLogTokenBurn log for token burn
TyLogTokenBurn
=
324
)
const
(
...
...
@@ -82,3 +90,8 @@ const (
// TokenIntroLenLimit token introduction length limit
TokenIntroLenLimit
=
1024
)
const
(
// CategoryMintBurnSupport support mint & burn
CategoryMintBurnSupport
=
1
<<
iota
)
plugin/dapp/token/types/token.pb.go
View file @
112b9f75
This diff is collapsed.
Click to expand it.
plugin/dapp/token/types/types.go
View file @
112b9f75
...
...
@@ -57,6 +57,8 @@ func (t *TokenType) GetTypeMap() map[string]int32 {
"TokenFinishCreate"
:
TokenActionFinishCreate
,
"TokenRevokeCreate"
:
TokenActionRevokeCreate
,
"TransferToExec"
:
TokenActionTransferToExec
,
"TokenMint"
:
TokenActionMint
,
"TokenBurn"
:
TokenActionBurn
,
}
}
...
...
@@ -75,6 +77,8 @@ func (t *TokenType) GetLogMap() map[int64]*types.LogInfo {
TyLogPreCreateToken
:
{
Ty
:
reflect
.
TypeOf
(
ReceiptToken
{}),
Name
:
"LogPreCreateToken"
},
TyLogFinishCreateToken
:
{
Ty
:
reflect
.
TypeOf
(
ReceiptToken
{}),
Name
:
"LogFinishCreateToken"
},
TyLogRevokeCreateToken
:
{
Ty
:
reflect
.
TypeOf
(
ReceiptToken
{}),
Name
:
"LogRevokeCreateToken"
},
TyLogTokenMint
:
{
Ty
:
reflect
.
TypeOf
(
ReceiptTokenAmount
{}),
Name
:
"LogMintToken"
},
TyLogTokenBurn
:
{
Ty
:
reflect
.
TypeOf
(
ReceiptTokenAmount
{}),
Name
:
"LogBurnToken"
},
}
}
...
...
plugin/store/init/init.go
View file @
112b9f75
package
init
import
(
_
"github.com/33cn/plugin/plugin/store/kvdb"
//auto gen
_
"github.com/33cn/plugin/plugin/store/kvmvcc"
//auto gen
_
"github.com/33cn/plugin/plugin/store/mpt"
//auto gen
_
"github.com/33cn/plugin/plugin/store/kvdb"
//auto gen
_
"github.com/33cn/plugin/plugin/store/kvmvcc"
//auto gen
_
"github.com/33cn/plugin/plugin/store/kvmvccmavl"
//auto gen
_
"github.com/33cn/plugin/plugin/store/mpt"
//auto gen
)
plugin/store/kvmvccmavl/kvmvcc_mavl.go
0 → 100644
View file @
112b9f75
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package kvmvccmavl kvmvcc+mavl接口
package
kvmvccmavl
import
(
"bytes"
"errors"
"fmt"
"sync"
"sync/atomic"
"time"
dbm
"github.com/33cn/chain33/common/db"
clog
"github.com/33cn/chain33/common/log"
log
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/queue"
drivers
"github.com/33cn/chain33/system/store"
"github.com/33cn/chain33/types"
"github.com/hashicorp/golang-lru"
)
var
(
kmlog
=
log
.
New
(
"module"
,
"kvmvccMavl"
)
// ErrStateHashLost ...
ErrStateHashLost
=
errors
.
New
(
"ErrStateHashLost"
)
kvmvccMavlFork
int64
=
200
*
10000
isDelMavlData
=
false
delMavlDataHeight
=
kvmvccMavlFork
+
10000
delMavlDataState
int32
wg
sync
.
WaitGroup
quit
bool
)
const
(
cacheSize
=
2048
//可以缓存2048个roothash, height对
batchDataSize
=
1024
*
1024
*
1
delMavlStateStart
=
1
delMavlStateEnd
=
0
)
// SetLogLevel set log level
func
SetLogLevel
(
level
string
)
{
clog
.
SetLogLevel
(
level
)
}
// DisableLog disable log output
func
DisableLog
()
{
kmlog
.
SetHandler
(
log
.
DiscardHandler
())
}
func
init
()
{
drivers
.
Reg
(
"kvmvccmavl"
,
New
)
}
// KVmMavlStore provide kvmvcc and mavl store interface implementation
type
KVmMavlStore
struct
{
*
drivers
.
BaseStore
*
KVMVCCStore
*
MavlStore
cache
*
lru
.
Cache
}
type
subKVMVCCConfig
struct
{
EnableMVCCIter
bool
`json:"enableMVCCIter"`
EnableMavlPrune
bool
`json:"enableMavlPrune"`
PruneHeight
int32
`json:"pruneHeight"`
}
type
subMavlConfig
struct
{
EnableMavlPrefix
bool
`json:"enableMavlPrefix"`
EnableMVCC
bool
`json:"enableMVCC"`
EnableMavlPrune
bool
`json:"enableMavlPrune"`
PruneHeight
int32
`json:"pruneHeight"`
}
type
subConfig
struct
{
EnableMVCCIter
bool
`json:"enableMVCCIter"`
EnableMavlPrefix
bool
`json:"enableMavlPrefix"`
EnableMVCC
bool
`json:"enableMVCC"`
EnableMavlPrune
bool
`json:"enableMavlPrune"`
PruneHeight
int32
`json:"pruneHeight"`
}
// New construct KVMVCCStore module
func
New
(
cfg
*
types
.
Store
,
sub
[]
byte
)
queue
.
Module
{
bs
:=
drivers
.
NewBaseStore
(
cfg
)
var
kvms
*
KVmMavlStore
var
subcfg
subConfig
var
subKVMVCCcfg
subKVMVCCConfig
var
subMavlcfg
subMavlConfig
if
sub
!=
nil
{
types
.
MustDecode
(
sub
,
&
subcfg
)
subKVMVCCcfg
.
EnableMVCCIter
=
subcfg
.
EnableMVCCIter
subKVMVCCcfg
.
EnableMavlPrune
=
subcfg
.
EnableMavlPrune
subKVMVCCcfg
.
PruneHeight
=
subcfg
.
PruneHeight
subMavlcfg
.
EnableMavlPrefix
=
subcfg
.
EnableMavlPrefix
subMavlcfg
.
EnableMVCC
=
subcfg
.
EnableMVCC
subMavlcfg
.
EnableMavlPrune
=
subcfg
.
EnableMavlPrune
subMavlcfg
.
PruneHeight
=
subcfg
.
PruneHeight
}
cache
,
err
:=
lru
.
New
(
cacheSize
)
if
err
!=
nil
{
panic
(
"new KVmMavlStore fail"
)
}
kvms
=
&
KVmMavlStore
{
bs
,
NewKVMVCC
(
&
subKVMVCCcfg
,
bs
.
GetDB
()),
NewMavl
(
&
subMavlcfg
,
bs
.
GetDB
()),
cache
}
// 查询是否已经删除mavl
_
,
err
=
bs
.
GetDB
()
.
Get
(
genDelMavlKey
(
mvccPrefix
))
if
err
==
nil
{
isDelMavlData
=
true
}
bs
.
SetChild
(
kvms
)
return
kvms
}
// Close the KVmMavlStore module
func
(
kvmMavls
*
KVmMavlStore
)
Close
()
{
quit
=
true
wg
.
Wait
()
kvmMavls
.
KVMVCCStore
.
Close
()
kvmMavls
.
MavlStore
.
Close
()
kvmMavls
.
BaseStore
.
Close
()
kmlog
.
Info
(
"store kvmMavls closed"
)
}
// Set kvs with statehash to KVmMavlStore
func
(
kvmMavls
*
KVmMavlStore
)
Set
(
datas
*
types
.
StoreSet
,
sync
bool
)
([]
byte
,
error
)
{
if
datas
.
Height
<
kvmvccMavlFork
{
hash
,
err
:=
kvmMavls
.
MavlStore
.
Set
(
datas
,
sync
)
if
err
!=
nil
{
return
hash
,
err
}
_
,
err
=
kvmMavls
.
KVMVCCStore
.
Set
(
datas
,
hash
,
sync
)
if
err
!=
nil
{
return
hash
,
err
}
if
err
==
nil
{
kvmMavls
.
cache
.
Add
(
string
(
hash
),
datas
.
Height
)
}
return
hash
,
err
}
// 仅仅做kvmvcc
hash
,
err
:=
kvmMavls
.
KVMVCCStore
.
Set
(
datas
,
nil
,
sync
)
if
err
==
nil
{
kvmMavls
.
cache
.
Add
(
string
(
hash
),
datas
.
Height
)
}
// 删除Mavl数据
if
datas
.
Height
>
delMavlDataHeight
&&
!
isDelMavlData
&&
!
isDelMavling
()
{
wg
.
Add
(
1
)
go
DelMavl
(
kvmMavls
.
GetDB
())
}
return
hash
,
err
}
// Get kvs with statehash from KVmMavlStore
func
(
kvmMavls
*
KVmMavlStore
)
Get
(
datas
*
types
.
StoreGet
)
[][]
byte
{
return
kvmMavls
.
KVMVCCStore
.
Get
(
datas
)
}
// MemSet set kvs to the mem of KVmMavlStore module and return the StateHash
func
(
kvmMavls
*
KVmMavlStore
)
MemSet
(
datas
*
types
.
StoreSet
,
sync
bool
)
([]
byte
,
error
)
{
if
datas
.
Height
<
kvmvccMavlFork
{
hash
,
err
:=
kvmMavls
.
MavlStore
.
MemSet
(
datas
,
sync
)
if
err
!=
nil
{
return
hash
,
err
}
_
,
err
=
kvmMavls
.
KVMVCCStore
.
MemSet
(
datas
,
hash
,
sync
)
if
err
!=
nil
{
return
hash
,
err
}
if
err
==
nil
{
kvmMavls
.
cache
.
Add
(
string
(
hash
),
datas
.
Height
)
}
return
hash
,
err
}
// 仅仅做kvmvcc
hash
,
err
:=
kvmMavls
.
KVMVCCStore
.
MemSet
(
datas
,
nil
,
sync
)
if
err
==
nil
{
kvmMavls
.
cache
.
Add
(
string
(
hash
),
datas
.
Height
)
}
// 删除Mavl数据
if
datas
.
Height
>
delMavlDataHeight
&&
!
isDelMavlData
&&
!
isDelMavling
()
{
wg
.
Add
(
1
)
go
DelMavl
(
kvmMavls
.
GetDB
())
}
return
hash
,
err
}
// Commit kvs in the mem of KVmMavlStore module to state db and return the StateHash
func
(
kvmMavls
*
KVmMavlStore
)
Commit
(
req
*
types
.
ReqHash
)
([]
byte
,
error
)
{
if
value
,
ok
:=
kvmMavls
.
cache
.
Get
(
string
(
req
.
Hash
));
ok
{
if
value
.
(
int64
)
<
kvmvccMavlFork
{
hash
,
err
:=
kvmMavls
.
MavlStore
.
Commit
(
req
)
if
err
!=
nil
{
return
hash
,
err
}
_
,
err
=
kvmMavls
.
KVMVCCStore
.
Commit
(
req
)
return
hash
,
err
}
return
kvmMavls
.
KVMVCCStore
.
Commit
(
req
)
}
return
kvmMavls
.
KVMVCCStore
.
Commit
(
req
)
}
// Rollback kvs in the mem of KVmMavlStore module and return the StateHash
func
(
kvmMavls
*
KVmMavlStore
)
Rollback
(
req
*
types
.
ReqHash
)
([]
byte
,
error
)
{
if
value
,
ok
:=
kvmMavls
.
cache
.
Get
(
string
(
req
.
Hash
));
ok
{
if
value
.
(
int64
)
<
kvmvccMavlFork
{
hash
,
err
:=
kvmMavls
.
MavlStore
.
Rollback
(
req
)
if
err
!=
nil
{
return
hash
,
err
}
_
,
err
=
kvmMavls
.
KVMVCCStore
.
Rollback
(
req
)
return
hash
,
err
}
return
kvmMavls
.
KVMVCCStore
.
Rollback
(
req
)
}
return
kvmMavls
.
KVMVCCStore
.
Rollback
(
req
)
}
// IterateRangeByStateHash travel with Prefix by StateHash to get the latest version kvs.
func
(
kvmMavls
*
KVmMavlStore
)
IterateRangeByStateHash
(
statehash
[]
byte
,
start
[]
byte
,
end
[]
byte
,
ascending
bool
,
fn
func
(
key
,
value
[]
byte
)
bool
)
{
if
value
,
ok
:=
kvmMavls
.
cache
.
Get
(
string
(
statehash
));
ok
{
if
value
.
(
int64
)
<
kvmvccMavlFork
{
kvmMavls
.
MavlStore
.
IterateRangeByStateHash
(
statehash
,
start
,
end
,
ascending
,
fn
)
return
}
kvmMavls
.
KVMVCCStore
.
IterateRangeByStateHash
(
statehash
,
start
,
end
,
ascending
,
fn
)
return
}
kvmMavls
.
KVMVCCStore
.
IterateRangeByStateHash
(
statehash
,
start
,
end
,
ascending
,
fn
)
}
// ProcEvent handles supported events
func
(
kvmMavls
*
KVmMavlStore
)
ProcEvent
(
msg
*
queue
.
Message
)
{
msg
.
ReplyErr
(
"KVmMavlStore"
,
types
.
ErrActionNotSupport
)
}
// Del set kvs to nil with StateHash
func
(
kvmMavls
*
KVmMavlStore
)
Del
(
req
*
types
.
StoreDel
)
([]
byte
,
error
)
{
if
req
.
Height
<
kvmvccMavlFork
{
hash
,
err
:=
kvmMavls
.
MavlStore
.
Del
(
req
)
if
err
!=
nil
{
return
hash
,
err
}
_
,
err
=
kvmMavls
.
KVMVCCStore
.
Del
(
req
)
if
err
!=
nil
{
return
hash
,
err
}
if
err
==
nil
{
kvmMavls
.
cache
.
Remove
(
string
(
req
.
StateHash
))
}
return
hash
,
err
}
// 仅仅做kvmvcc
hash
,
err
:=
kvmMavls
.
KVMVCCStore
.
Del
(
req
)
if
err
==
nil
{
kvmMavls
.
cache
.
Remove
(
string
(
req
.
StateHash
))
}
return
hash
,
err
}
// DelMavl 数据库中mavl数据清除
// 达到kvmvccMavlFork + 100000 后触发清除
func
DelMavl
(
db
dbm
.
DB
)
{
defer
wg
.
Done
()
setDelMavl
(
delMavlStateStart
)
defer
setDelMavl
(
delMavlStateEnd
)
isDel
:=
delMavlData
(
db
)
if
isDel
{
isDelMavlData
=
true
kmlog
.
Info
(
"DelMavl success"
)
}
}
func
delMavlData
(
db
dbm
.
DB
)
bool
{
it
:=
db
.
Iterator
(
nil
,
nil
,
true
)
defer
it
.
Close
()
batch
:=
db
.
NewBatch
(
true
)
for
it
.
Rewind
();
it
.
Valid
();
it
.
Next
()
{
if
quit
{
return
false
}
if
!
bytes
.
HasPrefix
(
it
.
Key
(),
mvccPrefix
)
{
// 将非mvcc的mavl数据全部删除
batch
.
Delete
(
it
.
Key
())
if
batch
.
ValueSize
()
>
batchDataSize
{
batch
.
Write
()
batch
.
Reset
()
time
.
Sleep
(
time
.
Millisecond
*
100
)
}
}
}
batch
.
Set
(
genDelMavlKey
(
mvccPrefix
),
[]
byte
(
""
))
batch
.
Write
()
return
true
}
func
genDelMavlKey
(
prefix
[]
byte
)
[]
byte
{
delMavl
:=
"--delMavlData--"
return
[]
byte
(
fmt
.
Sprintf
(
"%s%s"
,
string
(
prefix
),
delMavl
))
}
func
isDelMavling
()
bool
{
return
atomic
.
LoadInt32
(
&
delMavlDataState
)
==
1
}
func
setDelMavl
(
state
int32
)
{
atomic
.
StoreInt32
(
&
delMavlDataState
,
state
)
}
plugin/store/kvmvccmavl/kvmvcc_mavl_test.go
0 → 100644
View file @
112b9f75
This diff is collapsed.
Click to expand it.
plugin/store/kvmvccmavl/kvmvccdb.go
0 → 100644
View file @
112b9f75
This diff is collapsed.
Click to expand it.
plugin/store/kvmvccmavl/mavl.go
0 → 100644
View file @
112b9f75
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
kvmvccmavl
import
(
"sync"
"github.com/33cn/chain33/common"
dbm
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/queue"
"github.com/33cn/chain33/system/store/mavl/db"
"github.com/33cn/chain33/types"
)
// MavlStore mavl store struct
type
MavlStore
struct
{
db
dbm
.
DB
trees
*
sync
.
Map
enableMavlPrefix
bool
enableMVCC
bool
enableMavlPrune
bool
pruneHeight
int32
}
// NewMavl new mavl store module
func
NewMavl
(
sub
*
subMavlConfig
,
db
dbm
.
DB
)
*
MavlStore
{
var
subcfg
subMavlConfig
if
sub
!=
nil
{
subcfg
.
EnableMavlPrefix
=
sub
.
EnableMavlPrefix
subcfg
.
EnableMVCC
=
sub
.
EnableMVCC
subcfg
.
EnableMavlPrune
=
sub
.
EnableMavlPrune
subcfg
.
PruneHeight
=
sub
.
PruneHeight
}
mavls
:=
&
MavlStore
{
db
,
&
sync
.
Map
{},
subcfg
.
EnableMavlPrefix
,
subcfg
.
EnableMVCC
,
subcfg
.
EnableMavlPrune
,
subcfg
.
PruneHeight
}
mavl
.
EnableMavlPrefix
(
subcfg
.
EnableMavlPrefix
)
mavl
.
EnableMVCC
(
subcfg
.
EnableMVCC
)
mavl
.
EnablePrune
(
subcfg
.
EnableMavlPrune
)
mavl
.
SetPruneHeight
(
int
(
subcfg
.
PruneHeight
))
return
mavls
}
// Close close mavl store
func
(
mavls
*
MavlStore
)
Close
()
{
mavl
.
ClosePrune
()
kmlog
.
Info
(
"store mavl closed"
)
}
// Set set k v to mavl store db; sync is true represent write sync
func
(
mavls
*
MavlStore
)
Set
(
datas
*
types
.
StoreSet
,
sync
bool
)
([]
byte
,
error
)
{
return
mavl
.
SetKVPair
(
mavls
.
db
,
datas
,
sync
)
}
// Get get values by keys
func
(
mavls
*
MavlStore
)
Get
(
datas
*
types
.
StoreGet
)
[][]
byte
{
var
tree
*
mavl
.
Tree
var
err
error
values
:=
make
([][]
byte
,
len
(
datas
.
Keys
))
search
:=
string
(
datas
.
StateHash
)
if
data
,
ok
:=
mavls
.
trees
.
Load
(
search
);
ok
{
tree
=
data
.
(
*
mavl
.
Tree
)
}
else
{
tree
=
mavl
.
NewTree
(
mavls
.
db
,
true
)
//get接口也应该传入高度
//tree.SetBlockHeight(datas.Height)
err
=
tree
.
Load
(
datas
.
StateHash
)
kmlog
.
Debug
(
"store mavl get tree"
,
"err"
,
err
,
"StateHash"
,
common
.
ToHex
(
datas
.
StateHash
))
}
if
err
==
nil
{
for
i
:=
0
;
i
<
len
(
datas
.
Keys
);
i
++
{
_
,
value
,
exit
:=
tree
.
Get
(
datas
.
Keys
[
i
])
if
exit
{
values
[
i
]
=
value
}
}
}
return
values
}
// MemSet set keys values to memcory mavl, return root hash and error
func
(
mavls
*
MavlStore
)
MemSet
(
datas
*
types
.
StoreSet
,
sync
bool
)
([]
byte
,
error
)
{
beg
:=
types
.
Now
()
defer
func
()
{
kmlog
.
Info
(
"MemSet"
,
"cost"
,
types
.
Since
(
beg
))
}()
if
len
(
datas
.
KV
)
==
0
{
kmlog
.
Info
(
"store mavl memset,use preStateHash as stateHash for kvset is null"
)
mavls
.
trees
.
Store
(
string
(
datas
.
StateHash
),
nil
)
return
datas
.
StateHash
,
nil
}
tree
:=
mavl
.
NewTree
(
mavls
.
db
,
sync
)
tree
.
SetBlockHeight
(
datas
.
Height
)
err
:=
tree
.
Load
(
datas
.
StateHash
)
if
err
!=
nil
{
return
nil
,
err
}
for
i
:=
0
;
i
<
len
(
datas
.
KV
);
i
++
{
tree
.
Set
(
datas
.
KV
[
i
]
.
Key
,
datas
.
KV
[
i
]
.
Value
)
}
hash
:=
tree
.
Hash
()
mavls
.
trees
.
Store
(
string
(
hash
),
tree
)
return
hash
,
nil
}
// Commit convert memcory mavl to storage db
func
(
mavls
*
MavlStore
)
Commit
(
req
*
types
.
ReqHash
)
([]
byte
,
error
)
{
beg
:=
types
.
Now
()
defer
func
()
{
kmlog
.
Info
(
"Commit"
,
"cost"
,
types
.
Since
(
beg
))
}()
tree
,
ok
:=
mavls
.
trees
.
Load
(
string
(
req
.
Hash
))
if
!
ok
{
kmlog
.
Error
(
"store mavl commit"
,
"err"
,
types
.
ErrHashNotFound
)
return
nil
,
types
.
ErrHashNotFound
}
if
tree
==
nil
{
kmlog
.
Info
(
"store mavl commit,do nothing for kvset is null"
)
mavls
.
trees
.
Delete
(
string
(
req
.
Hash
))
return
req
.
Hash
,
nil
}
hash
:=
tree
.
(
*
mavl
.
Tree
)
.
Save
()
if
hash
==
nil
{
kmlog
.
Error
(
"store mavl commit"
,
"err"
,
types
.
ErrHashNotFound
)
return
nil
,
types
.
ErrDataBaseDamage
}
mavls
.
trees
.
Delete
(
string
(
req
.
Hash
))
return
req
.
Hash
,
nil
}
// Rollback 回退将缓存的mavl树删除掉
func
(
mavls
*
MavlStore
)
Rollback
(
req
*
types
.
ReqHash
)
([]
byte
,
error
)
{
beg
:=
types
.
Now
()
defer
func
()
{
kmlog
.
Info
(
"Rollback"
,
"cost"
,
types
.
Since
(
beg
))
}()
_
,
ok
:=
mavls
.
trees
.
Load
(
string
(
req
.
Hash
))
if
!
ok
{
kmlog
.
Error
(
"store mavl rollback"
,
"err"
,
types
.
ErrHashNotFound
)
return
nil
,
types
.
ErrHashNotFound
}
mavls
.
trees
.
Delete
(
string
(
req
.
Hash
))
return
req
.
Hash
,
nil
}
// IterateRangeByStateHash 迭代实现功能; statehash:当前状态hash, start:开始查找的key, end: 结束的key, ascending:升序,降序, fn 迭代回调函数
func
(
mavls
*
MavlStore
)
IterateRangeByStateHash
(
statehash
[]
byte
,
start
[]
byte
,
end
[]
byte
,
ascending
bool
,
fn
func
(
key
,
value
[]
byte
)
bool
)
{
mavl
.
IterateRangeByStateHash
(
mavls
.
db
,
statehash
,
start
,
end
,
ascending
,
fn
)
}
// ProcEvent not support message
func
(
mavls
*
MavlStore
)
ProcEvent
(
msg
queue
.
Message
)
{
msg
.
ReplyErr
(
"Store"
,
types
.
ErrActionNotSupport
)
}
// Del ...
func
(
mavls
*
MavlStore
)
Del
(
req
*
types
.
StoreDel
)
([]
byte
,
error
)
{
//not support
return
nil
,
nil
}
vendor/github.com/33cn/chain33/.travis.yml
View file @
112b9f75
...
...
@@ -11,7 +11,7 @@ matrix:
-
name
:
check_fmt
sudo
:
require
go
:
-
"
1.
9
"
-
"
1.
11.x
"
-
master
install
:
-
go get -u golang.org/x/tools/cmd/goimports
...
...
vendor/github.com/33cn/chain33/account/account.go
View file @
112b9f75
...
...
@@ -472,3 +472,40 @@ func (acc *DB) mintReceipt(kv []*types.KeyValue, receipt proto.Message) *types.R
Logs
:
[]
*
types
.
ReceiptLog
{
log1
},
}
}
// Burn 然收
func
(
acc
*
DB
)
Burn
(
addr
string
,
amount
int64
)
(
*
types
.
Receipt
,
error
)
{
if
!
types
.
CheckAmount
(
amount
)
{
return
nil
,
types
.
ErrAmount
}
accTo
:=
acc
.
LoadAccount
(
addr
)
if
accTo
.
Balance
<
amount
{
return
nil
,
types
.
ErrNoBalance
}
copyAcc
:=
*
accTo
accTo
.
Balance
=
accTo
.
Balance
-
amount
receipt
:=
&
types
.
ReceiptAccountBurn
{
Prev
:
&
copyAcc
,
Current
:
accTo
,
}
kv
:=
acc
.
GetKVSet
(
accTo
)
acc
.
SaveKVSet
(
kv
)
return
acc
.
burnReceipt
(
kv
,
receipt
),
nil
}
func
(
acc
*
DB
)
burnReceipt
(
kv
[]
*
types
.
KeyValue
,
receipt
proto
.
Message
)
*
types
.
Receipt
{
ty
:=
int32
(
types
.
TyLogBurn
)
log1
:=
&
types
.
ReceiptLog
{
Ty
:
ty
,
Log
:
types
.
Encode
(
receipt
),
}
return
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kv
,
Logs
:
[]
*
types
.
ReceiptLog
{
log1
},
}
}
vendor/github.com/33cn/chain33/account/account_test.go
View file @
112b9f75
...
...
@@ -591,3 +591,13 @@ func TestDB_Mint(t *testing.T) {
t
.
Logf
(
"Token mint addr balance [%d]"
,
tokenCoin
.
LoadAccount
(
addr1
)
.
Balance
)
require
.
Equal
(
t
,
int64
(
1000
*
1e8
+
10
*
1e8
),
tokenCoin
.
LoadAccount
(
addr1
)
.
Balance
)
}
func
TestDB_Burn
(
t
*
testing
.
T
)
{
_
,
tokenCoin
:=
GenerAccDb
()
tokenCoin
.
GenerAccData
()
_
,
err
:=
tokenCoin
.
Burn
(
addr1
,
10
*
1e8
)
require
.
NoError
(
t
,
err
)
t
.
Logf
(
"Token mint addr balance [%d]"
,
tokenCoin
.
LoadAccount
(
addr1
)
.
Balance
)
require
.
Equal
(
t
,
int64
(
1000
*
1e8
-
10
*
1e8
),
tokenCoin
.
LoadAccount
(
addr1
)
.
Balance
)
}
vendor/github.com/33cn/chain33/cmd/chain33/bityuan.toml
View file @
112b9f75
...
...
@@ -90,6 +90,10 @@ enableMVCC=false
enableMavlPrune
=
false
# 裁剪高度间隔
pruneHeight
=
10000
# 是否使能mavl数据载入内存
enableMemTree
=
false
# 是否使能mavl叶子节点数据载入内存
enableMemVal
=
false
[wallet]
# walletdb路径
...
...
vendor/github.com/33cn/chain33/cmd/chain33/chain33.test.toml
View file @
112b9f75
...
...
@@ -144,6 +144,10 @@ enableMavlPrefix=false
enableMVCC
=
false
enableMavlPrune
=
false
pruneHeight
=
10000
# 是否使能mavl数据载入内存
enableMemTree
=
false
# 是否使能mavl叶子节点数据载入内存
enableMemVal
=
false
[wallet]
minFee
=
1000000
...
...
vendor/github.com/33cn/chain33/cmd/chain33/chain33.toml
View file @
112b9f75
...
...
@@ -210,6 +210,10 @@ enableMVCC=false
enableMavlPrune
=
false
# 裁剪高度间隔
pruneHeight
=
10000
# 是否使能mavl数据载入内存
enableMemTree
=
false
# 是否使能mavl叶子节点数据载入内存
enableMemVal
=
false
[wallet]
# 交易发送最低手续费,单位0.00000001BTY(1e-8),默认100000,即0.001BTY
...
...
vendor/github.com/33cn/chain33/executor/execenv.go
View file @
112b9f75
...
...
@@ -203,11 +203,24 @@ func (e *executor) Exec(tx *types.Transaction, index int) (*types.Receipt, error
if
err
:=
drivers
.
CheckAddress
(
tx
.
GetRealToAddr
(),
e
.
height
);
err
!=
nil
{
return
nil
,
err
}
if
e
.
localDB
!=
nil
{
e
.
localDB
.
(
*
LocalDB
)
.
DisableWrite
()
if
exec
.
ExecutorOrder
()
!=
drivers
.
ExecLocalSameTime
{
e
.
localDB
.
(
*
LocalDB
)
.
DisableRead
()
}
defer
func
()
{
e
.
localDB
.
(
*
LocalDB
)
.
EnableWrite
()
if
exec
.
ExecutorOrder
()
!=
drivers
.
ExecLocalSameTime
{
e
.
localDB
.
(
*
LocalDB
)
.
EnableRead
()
}
}()
}
//第一步先检查 CheckTx
if
err
:=
exec
.
CheckTx
(
tx
,
index
);
err
!=
nil
{
return
nil
,
err
}
return
exec
.
Exec
(
tx
,
index
)
r
,
err
:=
exec
.
Exec
(
tx
,
index
)
return
r
,
err
}
func
(
e
*
executor
)
execLocal
(
tx
*
types
.
Transaction
,
r
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
...
...
vendor/github.com/33cn/chain33/executor/executor_real_test.go
View file @
112b9f75
...
...
@@ -312,7 +312,10 @@ func (demo *demoApp) Exec(tx *types.Transaction, index int) (receipt *types.Rece
}
if
seterrkey
{
println
(
"set err key value"
)
demo
.
GetLocalDB
()
.
Set
([]
byte
(
"key1"
),
[]
byte
(
"value1"
))
err
=
demo
.
GetLocalDB
()
.
Set
([]
byte
(
"key1"
),
[]
byte
(
"value1"
))
if
err
!=
nil
{
return
nil
,
err
}
}
receipt
=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
}
receipt
.
KV
=
append
(
receipt
.
KV
,
&
types
.
KeyValue
{
...
...
@@ -401,11 +404,14 @@ func TestExecLocalSameTime0(t *testing.T) {
return
}
for
i
,
receipt
:=
range
detail
.
Receipts
{
assert
.
Equal
(
t
,
receipt
.
GetTy
(),
int32
(
2
),
fmt
.
Sprint
(
i
))
if
i
==
0
{
assert
.
Equal
(
t
,
receipt
.
GetTy
(),
int32
(
2
),
fmt
.
Sprint
(
i
))
}
if
i
>=
1
{
assert
.
Equal
(
t
,
receipt
.
GetTy
(),
int32
(
1
),
fmt
.
Sprint
(
i
))
fmt
.
Println
(
receipt
)
assert
.
Equal
(
t
,
len
(
receipt
.
Logs
),
2
)
assert
.
Equal
(
t
,
receipt
.
Logs
[
1
]
.
Ty
,
int32
(
0
))
assert
.
Equal
(
t
,
receipt
.
Logs
[
1
]
.
Ty
,
int32
(
1
))
}
}
}
...
...
vendor/github.com/33cn/chain33/executor/executor_test.go
View file @
112b9f75
...
...
@@ -5,6 +5,7 @@
package
executor
import
(
"fmt"
"testing"
"time"
...
...
@@ -198,5 +199,6 @@ func TestExecutorErrAPIEnv(t *testing.T) {
msg
:=
queue
.
NewMessage
(
0
,
""
,
1
,
txlist
)
exec
.
procExecTxList
(
msg
)
_
,
err
:=
exec
.
client
.
WaitTimeout
(
msg
,
100
*
time
.
Second
)
fmt
.
Println
(
err
)
assert
.
Equal
(
t
,
true
,
api
.
IsAPIEnvError
(
err
))
}
vendor/github.com/33cn/chain33/executor/localdb.go
View file @
112b9f75
...
...
@@ -12,15 +12,17 @@ import (
//数据的get set 主要经过 cache
//如果需要进行list, 那么把get set 的内容加入到 后端数据库
type
LocalDB
struct
{
cache
map
[
string
][]
byte
txcache
map
[
string
][]
byte
keys
[]
string
intx
bool
hasbegin
bool
kvs
[]
*
types
.
KeyValue
txid
*
types
.
Int64
client
queue
.
Client
api
client
.
QueueProtocolAPI
cache
map
[
string
][]
byte
txcache
map
[
string
][]
byte
keys
[]
string
intx
bool
hasbegin
bool
kvs
[]
*
types
.
KeyValue
txid
*
types
.
Int64
client
queue
.
Client
api
client
.
QueueProtocolAPI
disableread
bool
disablewrite
bool
}
//NewLocalDB 创建一个新的LocalDB
...
...
@@ -41,6 +43,26 @@ func NewLocalDB(cli queue.Client) db.KVDB {
}
}
//DisableRead 禁止读取LocalDB数据库
func
(
l
*
LocalDB
)
DisableRead
()
{
l
.
disableread
=
true
}
//DisableWrite 禁止写LocalDB数据库
func
(
l
*
LocalDB
)
DisableWrite
()
{
l
.
disablewrite
=
true
}
//EnableRead 启动读取LocalDB数据库
func
(
l
*
LocalDB
)
EnableRead
()
{
l
.
disableread
=
false
}
//EnableWrite 启动写LocalDB数据库
func
(
l
*
LocalDB
)
EnableWrite
()
{
l
.
disablewrite
=
false
}
func
(
l
*
LocalDB
)
resetTx
()
{
l
.
intx
=
false
l
.
txcache
=
nil
...
...
@@ -128,6 +150,9 @@ func (l *LocalDB) Rollback() {
//Get 获取key
func
(
l
*
LocalDB
)
Get
(
key
[]
byte
)
([]
byte
,
error
)
{
if
l
.
disableread
{
return
nil
,
types
.
ErrDisableRead
}
skey
:=
string
(
key
)
if
l
.
intx
&&
l
.
txcache
!=
nil
{
if
value
,
ok
:=
l
.
txcache
[
skey
];
ok
{
...
...
@@ -160,6 +185,9 @@ func (l *LocalDB) Get(key []byte) ([]byte, error) {
//Set 获取key
func
(
l
*
LocalDB
)
Set
(
key
[]
byte
,
value
[]
byte
)
error
{
if
l
.
disablewrite
{
return
types
.
ErrDisableWrite
}
skey
:=
string
(
key
)
if
l
.
intx
{
if
l
.
txcache
==
nil
{
...
...
@@ -176,6 +204,9 @@ func (l *LocalDB) Set(key []byte, value []byte) error {
// List 从数据库中查询数据列表
func
(
l
*
LocalDB
)
List
(
prefix
,
key
[]
byte
,
count
,
direction
int32
)
([][]
byte
,
error
)
{
if
l
.
disableread
{
return
nil
,
types
.
ErrDisableRead
}
err
:=
l
.
save
()
if
err
!=
nil
{
return
nil
,
err
...
...
vendor/github.com/33cn/chain33/executor/localdb_test.go
View file @
112b9f75
...
...
@@ -18,6 +18,34 @@ func TestLocalDBGet(t *testing.T) {
testDBGet
(
t
,
db
)
}
func
TestLocalDBEnable
(
t
*
testing
.
T
)
{
mock33
:=
testnode
.
New
(
""
,
nil
)
defer
mock33
.
Close
()
db
:=
executor
.
NewLocalDB
(
mock33
.
GetClient
())
ldb
:=
db
.
(
*
executor
.
LocalDB
)
defer
ldb
.
Close
()
_
,
err
:=
ldb
.
Get
([]
byte
(
"hello"
))
assert
.
Equal
(
t
,
err
,
types
.
ErrNotFound
)
ldb
.
DisableRead
()
_
,
err
=
ldb
.
Get
([]
byte
(
"hello"
))
assert
.
Equal
(
t
,
err
,
types
.
ErrDisableRead
)
_
,
err
=
ldb
.
List
(
nil
,
nil
,
0
,
0
)
assert
.
Equal
(
t
,
err
,
types
.
ErrDisableRead
)
ldb
.
EnableRead
()
_
,
err
=
ldb
.
Get
([]
byte
(
"hello"
))
assert
.
Equal
(
t
,
err
,
types
.
ErrNotFound
)
_
,
err
=
ldb
.
List
(
nil
,
nil
,
0
,
0
)
assert
.
Equal
(
t
,
err
,
nil
)
ldb
.
DisableWrite
()
err
=
ldb
.
Set
([]
byte
(
"hello"
),
nil
)
assert
.
Equal
(
t
,
err
,
types
.
ErrDisableWrite
)
ldb
.
EnableWrite
()
err
=
ldb
.
Set
([]
byte
(
"hello"
),
nil
)
assert
.
Equal
(
t
,
err
,
nil
)
}
func
BenchmarkLocalDBGet
(
b
*
testing
.
B
)
{
mock33
:=
testnode
.
New
(
""
,
nil
)
defer
mock33
.
Close
()
...
...
vendor/github.com/33cn/chain33/system/dapp/manage/types/types.go
View file @
112b9f75
...
...
@@ -20,7 +20,7 @@ var (
}
logmap
=
map
[
int64
]
*
types
.
LogInfo
{
// 这里reflect.TypeOf类型必须是proto.Message类型,且是交易的回持结构
TyLogModifyConfig
:
{
reflect
.
TypeOf
(
types
.
ReceiptConfig
{}),
"LogModifyConfig"
},
TyLogModifyConfig
:
{
Ty
:
reflect
.
TypeOf
(
types
.
ReceiptConfig
{}),
Name
:
"LogModifyConfig"
},
}
)
...
...
vendor/github.com/33cn/chain33/system/store/mavl/db/memmavl.go
0 → 100644
View file @
112b9f75
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
mavl
import
(
"fmt"
"time"
"github.com/33cn/chain33/common"
dbm
"github.com/33cn/chain33/common/db"
farm
"github.com/dgryski/go-farm"
"github.com/hashicorp/golang-lru"
)
// MemTreeOpera memtree操作接口
type
MemTreeOpera
interface
{
Add
(
key
,
value
interface
{})
Get
(
key
interface
{})
(
value
interface
{},
ok
bool
)
Delete
(
key
interface
{})
Contains
(
key
interface
{})
bool
Len
()
int
}
// TreeMap map形式memtree
type
TreeMap
struct
{
mpCache
map
[
interface
{}]
interface
{}
}
// NewTreeMap new mem tree
func
NewTreeMap
(
size
int
)
*
TreeMap
{
mp
:=
&
TreeMap
{}
mp
.
mpCache
=
make
(
map
[
interface
{}]
interface
{},
size
)
return
mp
}
// Add 添加元素
func
(
tm
*
TreeMap
)
Add
(
key
,
value
interface
{})
{
if
_
,
ok
:=
tm
.
mpCache
[
key
];
ok
{
delete
(
tm
.
mpCache
,
key
)
return
}
tm
.
mpCache
[
key
]
=
value
}
// Get 获取元素
func
(
tm
*
TreeMap
)
Get
(
key
interface
{})
(
value
interface
{},
ok
bool
)
{
if
value
,
ok
:=
tm
.
mpCache
[
key
];
ok
{
return
value
,
ok
}
return
nil
,
false
}
// Delete 删除元素
func
(
tm
*
TreeMap
)
Delete
(
key
interface
{})
{
if
_
,
ok
:=
tm
.
mpCache
[
key
];
ok
{
delete
(
tm
.
mpCache
,
key
)
}
}
// Contains 查看是否包含元素
func
(
tm
*
TreeMap
)
Contains
(
key
interface
{})
bool
{
if
_
,
ok
:=
tm
.
mpCache
[
key
];
ok
{
return
true
}
return
false
}
// Len 元素长度
func
(
tm
*
TreeMap
)
Len
()
int
{
return
len
(
tm
.
mpCache
)
}
// TreeARC lru的mem tree
type
TreeARC
struct
{
arcCache
*
lru
.
ARCCache
}
// NewTreeARC new lru mem tree
func
NewTreeARC
(
size
int
)
*
TreeARC
{
ma
:=
&
TreeARC
{}
ma
.
arcCache
,
_
=
lru
.
NewARC
(
size
)
return
ma
}
// Add 添加元素
func
(
ta
*
TreeARC
)
Add
(
key
,
value
interface
{})
{
if
ta
.
arcCache
.
Contains
(
key
)
{
ta
.
arcCache
.
Remove
(
key
)
return
}
ta
.
arcCache
.
Add
(
key
,
value
)
}
// Get 获取元素
func
(
ta
*
TreeARC
)
Get
(
key
interface
{})
(
value
interface
{},
ok
bool
)
{
return
ta
.
arcCache
.
Get
(
key
)
}
// Delete 删除元素
func
(
ta
*
TreeARC
)
Delete
(
key
interface
{})
{
ta
.
arcCache
.
Remove
(
key
)
}
// Contains 查看是否包含元素
func
(
ta
*
TreeARC
)
Contains
(
key
interface
{})
bool
{
return
ta
.
arcCache
.
Contains
(
key
)
}
// Len 元素长度
func
(
ta
*
TreeARC
)
Len
()
int
{
return
ta
.
arcCache
.
Len
()
}
// LoadTree2MemDb 从数据库中载入mem tree
func
LoadTree2MemDb
(
db
dbm
.
DB
,
hash
[]
byte
,
mp
map
[
uint64
]
struct
{})
{
nDb
:=
newNodeDB
(
db
,
true
)
node
,
err
:=
nDb
.
getLightNode
(
nil
,
hash
)
if
err
!=
nil
{
fmt
.
Println
(
"err"
,
err
)
return
}
pri
:=
""
if
len
(
node
.
hash
)
>
32
{
pri
=
string
(
node
.
hash
[
:
16
])
}
treelog
.
Info
(
"hash node"
,
"hash pri"
,
pri
,
"hash"
,
common
.
ToHex
(
node
.
hash
),
"height"
,
node
.
height
)
start
:=
time
.
Now
()
leftHash
:=
make
([]
byte
,
len
(
node
.
leftHash
))
copy
(
leftHash
,
node
.
leftHash
)
rightHash
:=
make
([]
byte
,
len
(
node
.
rightHash
))
copy
(
rightHash
,
node
.
rightHash
)
mp
[
farm
.
Hash64
(
node
.
hash
)]
=
struct
{}{}
node
.
loadNodeInfo
(
nDb
,
mp
)
end
:=
time
.
Now
()
treelog
.
Info
(
"hash node"
,
"cost time"
,
end
.
Sub
(
start
),
"node count"
,
len
(
mp
))
PrintMemStats
(
1
)
}
func
(
node
*
Node
)
loadNodeInfo
(
db
*
nodeDB
,
mp
map
[
uint64
]
struct
{})
{
if
node
.
height
==
0
{
//trMem.Add(Hash64(node.hash), &hashNode{leftHash: node.leftHash, rightHash: node.rightHash})
leftHash
:=
make
([]
byte
,
len
(
node
.
leftHash
))
copy
(
leftHash
,
node
.
leftHash
)
rightHash
:=
make
([]
byte
,
len
(
node
.
rightHash
))
copy
(
rightHash
,
node
.
rightHash
)
mp
[
farm
.
Hash64
(
node
.
hash
)]
=
struct
{}{}
return
}
if
node
.
leftHash
!=
nil
{
left
,
err
:=
db
.
getLightNode
(
nil
,
node
.
leftHash
)
if
err
!=
nil
{
return
}
//trMem.Add(Hash64(left.hash), &hashNode{leftHash: left.leftHash, rightHash: left.rightHash})
leftHash
:=
make
([]
byte
,
len
(
left
.
leftHash
))
copy
(
leftHash
,
left
.
leftHash
)
rightHash
:=
make
([]
byte
,
len
(
left
.
rightHash
))
copy
(
rightHash
,
left
.
rightHash
)
mp
[
farm
.
Hash64
(
left
.
hash
)]
=
struct
{}{}
left
.
loadNodeInfo
(
db
,
mp
)
}
if
node
.
rightHash
!=
nil
{
right
,
err
:=
db
.
getLightNode
(
nil
,
node
.
rightHash
)
if
err
!=
nil
{
return
}
//trMem.Add(Hash64(right.hash), &hashNode{leftHash: right.leftHash, rightHash: right.rightHash})
leftHash
:=
make
([]
byte
,
len
(
right
.
leftHash
))
copy
(
leftHash
,
right
.
leftHash
)
rightHash
:=
make
([]
byte
,
len
(
right
.
rightHash
))
copy
(
rightHash
,
right
.
rightHash
)
mp
[
farm
.
Hash64
(
right
.
hash
)]
=
struct
{}{}
right
.
loadNodeInfo
(
db
,
mp
)
}
}
func
(
ndb
*
nodeDB
)
getLightNode
(
t
*
Tree
,
hash
[]
byte
)
(
*
Node
,
error
)
{
// Doesn't exist, load from db.
var
buf
[]
byte
buf
,
err
:=
ndb
.
db
.
Get
(
hash
)
if
len
(
buf
)
==
0
||
err
!=
nil
{
return
nil
,
ErrNodeNotExist
}
node
,
err
:=
MakeNode
(
buf
,
t
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"Error reading IAVLNode. bytes: %X error: %v"
,
buf
,
err
))
}
node
.
hash
=
hash
node
.
key
=
nil
node
.
value
=
nil
return
node
,
nil
}
func
copyBytes
(
b
[]
byte
)
(
copiedBytes
[]
byte
)
{
if
b
==
nil
{
return
nil
}
copiedBytes
=
make
([]
byte
,
len
(
b
))
copy
(
copiedBytes
,
b
)
return
copiedBytes
}
vendor/github.com/33cn/chain33/system/store/mavl/db/node.go
View file @
112b9f75
...
...
@@ -11,6 +11,7 @@ import (
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
farm
"github.com/dgryski/go-farm"
"github.com/golang/protobuf/proto"
)
...
...
@@ -499,6 +500,9 @@ func removeOrphan(t *Tree, node *Node) {
if
t
.
ndb
==
nil
{
return
}
if
enableMemTree
&&
t
!=
nil
{
t
.
obsoleteNode
[
uintkey
(
farm
.
Hash64
(
node
.
hash
))]
=
struct
{}{}
}
t
.
ndb
.
RemoveNode
(
t
,
node
)
}
...
...
vendor/github.com/33cn/chain33/system/store/mavl/db/tree.go
View file @
112b9f75
...
...
@@ -15,6 +15,7 @@ import (
dbm
"github.com/33cn/chain33/common/db"
log
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
farm
"github.com/dgryski/go-farm"
"github.com/golang/protobuf/proto"
"github.com/hashicorp/golang-lru"
)
...
...
@@ -37,6 +38,10 @@ var (
// 当前树的最大高度
maxBlockHeight
int64
heightMtx
sync
.
Mutex
//
enableMemTree
bool
memTree
MemTreeOpera
enableMemVal
bool
)
// EnableMavlPrefix 使能mavl加前缀
...
...
@@ -49,23 +54,53 @@ func EnableMVCC(enable bool) {
enableMvcc
=
enable
}
// EnableMemTree 使能mavl数据载入内存
func
EnableMemTree
(
enable
bool
)
{
enableMemTree
=
enable
}
// EnableMemVal 使能mavl叶子节点数据载入内存
func
EnableMemVal
(
enable
bool
)
{
enableMemVal
=
enable
}
type
memNode
struct
{
data
[][]
byte
//顺序为lefthash, righthash, key, value
Height
int32
Size
int32
}
type
uintkey
uint64
// Tree merkle avl tree
type
Tree
struct
{
root
*
Node
ndb
*
nodeDB
blockHeight
int64
// 树更新之后,废弃的节点(更新缓存中节点先对旧节点进行删除然后再更新)
obsoleteNode
map
[
uintkey
]
struct
{}
updateNode
map
[
uintkey
]
*
memNode
}
// NewTree 新建一个merkle avl 树
func
NewTree
(
db
dbm
.
DB
,
sync
bool
)
*
Tree
{
if
db
==
nil
{
// In-memory IAVLTree
return
&
Tree
{}
return
&
Tree
{
obsoleteNode
:
make
(
map
[
uintkey
]
struct
{}),
updateNode
:
make
(
map
[
uintkey
]
*
memNode
),
}
}
// Persistent IAVLTree
ndb
:=
newNodeDB
(
db
,
sync
)
// 使能情况下非空创建当前整tree的缓存
if
enableMemTree
&&
memTree
==
nil
{
memTree
=
NewTreeMap
(
50
*
10000
)
}
return
&
Tree
{
ndb
:
ndb
,
ndb
:
ndb
,
obsoleteNode
:
make
(
map
[
uintkey
]
struct
{}),
updateNode
:
make
(
map
[
uintkey
]
*
memNode
),
}
}
...
...
@@ -116,13 +151,17 @@ func (t *Tree) Has(key []byte) bool {
func
(
t
*
Tree
)
Set
(
key
[]
byte
,
value
[]
byte
)
(
updated
bool
)
{
//treelog.Info("IAVLTree.Set", "key", key, "value",value)
if
t
.
root
==
nil
{
t
.
root
=
NewNode
(
key
,
value
)
t
.
root
=
NewNode
(
copyBytes
(
key
),
copyBytes
(
value
)
)
return
false
}
t
.
root
,
updated
=
t
.
root
.
set
(
t
,
key
,
value
)
t
.
root
,
updated
=
t
.
root
.
set
(
t
,
copyBytes
(
key
),
copyBytes
(
value
)
)
return
updated
}
func
(
t
*
Tree
)
getObsoleteNode
()
map
[
uintkey
]
struct
{}
{
return
t
.
obsoleteNode
}
// Hash 计算tree 的roothash
func
(
t
*
Tree
)
Hash
()
[]
byte
{
if
t
.
root
==
nil
{
...
...
@@ -148,6 +187,17 @@ func (t *Tree) Save() []byte {
if
enablePrune
{
t
.
root
.
saveRootHash
(
t
)
}
// 更新memTree
if
enableMemTree
&&
memTree
!=
nil
{
for
k
:=
range
t
.
obsoleteNode
{
memTree
.
Delete
(
k
)
}
for
k
,
v
:=
range
t
.
updateNode
{
memTree
.
Add
(
k
,
v
)
}
treelog
.
Debug
(
"Tree.Save"
,
"memTree len"
,
memTree
.
Len
(),
"tree height"
,
t
.
blockHeight
)
}
beg
:=
types
.
Now
()
err
:=
t
.
ndb
.
Commit
()
treelog
.
Info
(
"tree.commit"
,
"cost"
,
types
.
Since
(
beg
))
...
...
@@ -395,6 +445,13 @@ func (ndb *nodeDB) GetNode(t *Tree, hash []byte) (*Node, error) {
return
elem
.
(
*
Node
),
nil
}
}
//从memtree中获取
if
enableMemTree
{
node
,
err
:=
getNode4MemTree
(
hash
)
if
err
==
nil
{
return
node
,
nil
}
}
// Doesn't exist, load from db.
var
buf
[]
byte
buf
,
err
:=
ndb
.
db
.
Get
(
hash
)
...
...
@@ -409,6 +466,10 @@ func (ndb *nodeDB) GetNode(t *Tree, hash []byte) (*Node, error) {
node
.
hash
=
hash
node
.
persisted
=
true
ndb
.
cacheNode
(
node
)
// Save node hashInt64 to memTree
if
enableMemTree
{
updateGlobalMemTree
(
node
)
}
return
node
,
nil
}
...
...
@@ -459,6 +520,85 @@ func (ndb *nodeDB) SaveNode(t *Tree, node *Node) {
ndb
.
cacheNode
(
node
)
delete
(
ndb
.
orphans
,
string
(
node
.
hash
))
//treelog.Debug("SaveNode", "hash", node.hash, "height", node.height, "value", node.value)
// Save node hashInt64 to localmem
if
enableMemTree
{
updateLocalMemTree
(
t
,
node
)
}
}
func
getNode4MemTree
(
hash
[]
byte
)
(
*
Node
,
error
)
{
if
memTree
==
nil
{
return
nil
,
ErrNodeNotExist
}
elem
,
ok
:=
memTree
.
Get
(
uintkey
(
farm
.
Hash64
(
hash
)))
if
ok
{
sn
:=
elem
.
(
*
memNode
)
node
:=
&
Node
{
height
:
sn
.
Height
,
size
:
sn
.
Size
,
hash
:
hash
,
persisted
:
true
,
}
node
.
leftHash
=
sn
.
data
[
0
]
node
.
rightHash
=
sn
.
data
[
1
]
node
.
key
=
sn
.
data
[
2
]
if
len
(
sn
.
data
)
==
4
{
node
.
value
=
sn
.
data
[
3
]
}
return
node
,
nil
}
return
nil
,
ErrNodeNotExist
}
// Save node hashInt64 to memTree
func
updateGlobalMemTree
(
node
*
Node
)
{
if
node
==
nil
||
memTree
==
nil
{
return
}
if
!
enableMemVal
&&
node
.
height
==
0
{
return
}
memN
:=
&
memNode
{
Height
:
node
.
height
,
Size
:
node
.
size
,
}
if
node
.
height
==
0
{
memN
.
data
=
make
([][]
byte
,
4
)
memN
.
data
[
3
]
=
node
.
value
}
else
{
memN
.
data
=
make
([][]
byte
,
3
)
}
memN
.
data
[
0
]
=
node
.
leftHash
memN
.
data
[
1
]
=
node
.
rightHash
memN
.
data
[
2
]
=
node
.
key
memTree
.
Add
(
uintkey
(
farm
.
Hash64
(
node
.
hash
)),
memN
)
}
// Save node hashInt64 to localmem
func
updateLocalMemTree
(
t
*
Tree
,
node
*
Node
)
{
if
t
==
nil
||
node
==
nil
{
return
}
if
!
enableMemVal
&&
node
.
height
==
0
{
return
}
if
t
.
updateNode
!=
nil
{
memN
:=
&
memNode
{
Height
:
node
.
height
,
Size
:
node
.
size
,
}
if
node
.
height
==
0
{
memN
.
data
=
make
([][]
byte
,
4
)
memN
.
data
[
3
]
=
node
.
value
}
else
{
memN
.
data
=
make
([][]
byte
,
3
)
}
memN
.
data
[
0
]
=
node
.
leftHash
memN
.
data
[
1
]
=
node
.
rightHash
memN
.
data
[
2
]
=
node
.
key
t
.
updateNode
[
uintkey
(
farm
.
Hash64
(
node
.
hash
))]
=
memN
//treelog.Debug("Tree.SaveNode", "store struct size", unsafe.Sizeof(store), "byte size", len(storenode), "height", node.height)
}
}
//cache缓存节点
...
...
vendor/github.com/33cn/chain33/system/store/mavl/db/tree_test.go
View file @
112b9f75
...
...
@@ -15,6 +15,8 @@ import (
"sync"
"testing"
"unsafe"
.
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/log"
...
...
@@ -1255,6 +1257,89 @@ func TestDelLeafCountKV(t *testing.T) {
}
}
func
TestGetObsoleteNode
(
t
*
testing
.
T
)
{
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"datastore"
)
require
.
NoError
(
t
,
err
)
t
.
Log
(
dir
)
defer
os
.
Remove
(
dir
)
EnableMemTree
(
true
)
EnableMemVal
(
true
)
defer
EnableMemTree
(
false
)
defer
EnableMemVal
(
false
)
db
:=
db
.
NewDB
(
"mavltree"
,
"leveldb"
,
dir
,
100
)
tree
:=
NewTree
(
db
,
true
)
type
record
struct
{
key
string
value
string
}
records
:=
[]
record
{
{
"abc"
,
"abc"
},
{
"low"
,
"low"
},
{
"fan"
,
"fan"
},
}
for
_
,
r
:=
range
records
{
updated
:=
tree
.
Set
([]
byte
(
r
.
key
),
[]
byte
(
r
.
value
))
if
updated
{
t
.
Error
(
"should have not been updated"
)
}
}
hash
:=
tree
.
Save
()
obs
:=
tree
.
getObsoleteNode
()
require
.
Equal
(
t
,
0
,
len
(
obs
))
mp
:=
make
(
map
[
uint64
]
struct
{})
LoadTree2MemDb
(
db
,
hash
,
mp
)
tree1
:=
NewTree
(
db
,
true
)
tree1
.
Load
(
hash
)
records1
:=
[]
record
{
{
"abc"
,
"abc1"
},
{
"low"
,
"low1"
},
{
"fan"
,
"fan1"
},
}
for
_
,
r
:=
range
records1
{
tree1
.
Set
([]
byte
(
r
.
key
),
[]
byte
(
r
.
value
))
}
hash1
:=
tree1
.
Save
()
obs
=
tree1
.
getObsoleteNode
()
mp1
:=
make
(
map
[
uint64
]
struct
{})
LoadTree2MemDb
(
db
,
hash1
,
mp1
)
require
.
Equal
(
t
,
len
(
mp
),
len
(
obs
))
//做了全部更新,因此旧节点全部删除
for
ob
:=
range
obs
{
_
,
ok
:=
mp
[
uint64
(
ob
)]
if
!
ok
{
require
.
Error
(
t
,
fmt
.
Errorf
(
"should exist"
))
}
}
tree2
:=
NewTree
(
db
,
true
)
tree2
.
Load
(
hash
)
records2
:=
[]
record
{
{
"fan"
,
"fan1"
},
{
"foo"
,
"foo"
},
{
"foobaz"
,
"foobaz"
},
{
"good"
,
"good"
},
}
for
_
,
r
:=
range
records2
{
tree2
.
Set
([]
byte
(
r
.
key
),
[]
byte
(
r
.
value
))
}
hash2
:=
tree2
.
Save
()
obs
=
tree2
.
getObsoleteNode
()
mp2
:=
make
(
map
[
uint64
]
struct
{})
LoadTree2MemDb
(
db
,
hash2
,
mp2
)
//require.Equal(t, 0, len(obs))
for
ob
:=
range
obs
{
_
,
ok
:=
mp
[
uint64
(
ob
)]
if
!
ok
{
require
.
Error
(
t
,
fmt
.
Errorf
(
"should exist"
))
}
}
}
func
TestPruningFirstLevelNode
(
t
*
testing
.
T
)
{
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"datastore"
)
require
.
NoError
(
t
,
err
)
...
...
@@ -1899,3 +1984,64 @@ func saveBlock(dbm db.DB, height int64, hash []byte, txN int64, mvcc bool) (newH
}
return
newHash
,
nil
}
func
TestSize1
(
t
*
testing
.
T
)
{
type
storeNode
struct
{
Key
[]
byte
Value
[]
byte
LeftHash
[]
byte
RightHash
[]
byte
Height
int32
Size
int32
}
type
storeNode1
struct
{
Key
[][]
byte
Height
int32
Size
int32
}
a
:=
types
.
StoreNode
{}
b
:=
storeNode
{}
var
c
[]
byte
d
:=
storeNode1
{}
//arcmp := NewTreeMap(350 * 10000)
//if arcmp == nil {
// return
//}
//for i := 0; i < 300*10000; i++ {
// data := &storeNode{
// Key: []byte("12345678901234567890123456789012"),
// Value: []byte("12345678901234567890123456789012"),
// LeftHash: []byte("12345678901234567890123456789012"),
// RightHash: []byte("12345678901234567890123456789012"),
// //Key: copyBytes([]byte("12345678901234567890123456789012")),
// //Value: copyBytes([]byte("12345678901234567890123456789012")),
// //LeftHash: copyBytes([]byte("12345678901234567890123456789012")),
// //RightHash: copyBytes([]byte("12345678901234567890123456789012")),
// Height: 123,
// Size: 123,
// }
// arcmp.Add(int64(i), data)
//}
//for i := 0; i < 100*10000; i++ {
// data := &storeNode1{}
// data.Height = 123
// data.Size = 123
// d.Key = make([][]byte, 4)
// //d.Key[0] = []byte("12345678901234567890123456789012")
// //d.Key[1] = []byte("12345678901234567890123456789012")
// //d.Key[2] = []byte("12345678901234567890123456789012")
// //d.Key[3] = []byte("12345678901234567890123456789012")
//
// d.Key[0] = copyBytes([]byte("12345678901234567890123456789012"))
// d.Key[1] = copyBytes([]byte("12345678901234567890123456789012"))
// d.Key[2] = copyBytes([]byte("12345678901234567890123456789012"))
// d.Key[3] = copyBytes([]byte("12345678901234567890123456789012"))
// arcmp.Add(int64(i), data)
//}
PrintMemStats
(
1
)
fmt
.
Println
(
unsafe
.
Sizeof
(
a
),
unsafe
.
Sizeof
(
b
),
unsafe
.
Sizeof
(
c
),
unsafe
.
Sizeof
(
d
),
len
(
d
.
Key
),
cap
(
d
.
Key
))
}
vendor/github.com/33cn/chain33/system/store/mavl/mavl.go
View file @
112b9f75
...
...
@@ -37,6 +37,8 @@ type Store struct {
enableMVCC
bool
enableMavlPrune
bool
pruneHeight
int32
enableMemTree
bool
enableMemVal
bool
}
func
init
()
{
...
...
@@ -51,6 +53,10 @@ type subConfig struct {
EnableMavlPrune
bool
`json:"enableMavlPrune"`
// 裁剪高度间隔
PruneHeight
int32
`json:"pruneHeight"`
// 是否使能内存树
EnableMemTree
bool
`json:"enableMemTree"`
// 是否使能内存树中叶子节点
EnableMemVal
bool
`json:"enableMemVal"`
}
// New new mavl store module
...
...
@@ -60,15 +66,20 @@ func New(cfg *types.Store, sub []byte) queue.Module {
if
sub
!=
nil
{
types
.
MustDecode
(
sub
,
&
subcfg
)
}
mavls
:=
&
Store
{
bs
,
&
sync
.
Map
{},
subcfg
.
EnableMavlPrefix
,
subcfg
.
EnableMVCC
,
subcfg
.
EnableMavlPrune
,
subcfg
.
PruneHeight
}
mavls
:=
&
Store
{
bs
,
&
sync
.
Map
{},
subcfg
.
EnableMavlPrefix
,
subcfg
.
EnableMVCC
,
subcfg
.
EnableMavlPrune
,
subcfg
.
PruneHeight
,
subcfg
.
EnableMemTree
,
subcfg
.
EnableMemVal
}
mavls
.
enableMavlPrefix
=
subcfg
.
EnableMavlPrefix
mavls
.
enableMVCC
=
subcfg
.
EnableMVCC
mavls
.
enableMavlPrune
=
subcfg
.
EnableMavlPrune
mavls
.
pruneHeight
=
subcfg
.
PruneHeight
mavls
.
enableMemTree
=
subcfg
.
EnableMemTree
mavls
.
enableMemVal
=
subcfg
.
EnableMemVal
mavl
.
EnableMavlPrefix
(
mavls
.
enableMavlPrefix
)
mavl
.
EnableMVCC
(
mavls
.
enableMVCC
)
mavl
.
EnablePrune
(
mavls
.
enableMavlPrune
)
mavl
.
SetPruneHeight
(
int
(
mavls
.
pruneHeight
))
mavl
.
EnableMemTree
(
mavls
.
enableMemTree
)
mavl
.
EnableMemVal
(
mavls
.
enableMemVal
)
bs
.
SetChild
(
mavls
)
return
mavls
}
...
...
vendor/github.com/33cn/chain33/types/account.pb.go
View file @
112b9f75
...
...
@@ -248,6 +248,53 @@ func (m *ReceiptAccountMint) GetCurrent() *Account {
return
nil
}
type
ReceiptAccountBurn
struct
{
Prev
*
Account
`protobuf:"bytes,1,opt,name=prev,proto3" json:"prev,omitempty"`
Current
*
Account
`protobuf:"bytes,2,opt,name=current,proto3" json:"current,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
}
func
(
m
*
ReceiptAccountBurn
)
Reset
()
{
*
m
=
ReceiptAccountBurn
{}
}
func
(
m
*
ReceiptAccountBurn
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
ReceiptAccountBurn
)
ProtoMessage
()
{}
func
(
*
ReceiptAccountBurn
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
4
}
}
func
(
m
*
ReceiptAccountBurn
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
return
xxx_messageInfo_ReceiptAccountBurn
.
Unmarshal
(
m
,
b
)
}
func
(
m
*
ReceiptAccountBurn
)
XXX_Marshal
(
b
[]
byte
,
deterministic
bool
)
([]
byte
,
error
)
{
return
xxx_messageInfo_ReceiptAccountBurn
.
Marshal
(
b
,
m
,
deterministic
)
}
func
(
m
*
ReceiptAccountBurn
)
XXX_Merge
(
src
proto
.
Message
)
{
xxx_messageInfo_ReceiptAccountBurn
.
Merge
(
m
,
src
)
}
func
(
m
*
ReceiptAccountBurn
)
XXX_Size
()
int
{
return
xxx_messageInfo_ReceiptAccountBurn
.
Size
(
m
)
}
func
(
m
*
ReceiptAccountBurn
)
XXX_DiscardUnknown
()
{
xxx_messageInfo_ReceiptAccountBurn
.
DiscardUnknown
(
m
)
}
var
xxx_messageInfo_ReceiptAccountBurn
proto
.
InternalMessageInfo
func
(
m
*
ReceiptAccountBurn
)
GetPrev
()
*
Account
{
if
m
!=
nil
{
return
m
.
Prev
}
return
nil
}
func
(
m
*
ReceiptAccountBurn
)
GetCurrent
()
*
Account
{
if
m
!=
nil
{
return
m
.
Current
}
return
nil
}
//查询一个地址列表在某个执行器中余额
type
ReqBalance
struct
{
//地址列表
...
...
@@ -266,7 +313,7 @@ func (m *ReqBalance) Reset() { *m = ReqBalance{} }
func
(
m
*
ReqBalance
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
ReqBalance
)
ProtoMessage
()
{}
func
(
*
ReqBalance
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
4
}
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
5
}
}
func
(
m
*
ReqBalance
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
...
...
@@ -334,7 +381,7 @@ func (m *Accounts) Reset() { *m = Accounts{} }
func
(
m
*
Accounts
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
Accounts
)
ProtoMessage
()
{}
func
(
*
Accounts
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
5
}
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
6
}
}
func
(
m
*
Accounts
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
...
...
@@ -374,7 +421,7 @@ func (m *ExecAccount) Reset() { *m = ExecAccount{} }
func
(
m
*
ExecAccount
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
ExecAccount
)
ProtoMessage
()
{}
func
(
*
ExecAccount
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
6
}
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
7
}
}
func
(
m
*
ExecAccount
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
...
...
@@ -421,7 +468,7 @@ func (m *AllExecBalance) Reset() { *m = AllExecBalance{} }
func
(
m
*
AllExecBalance
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
AllExecBalance
)
ProtoMessage
()
{}
func
(
*
AllExecBalance
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
7
}
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
8
}
}
func
(
m
*
AllExecBalance
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
...
...
@@ -473,7 +520,7 @@ func (m *ReqAllExecBalance) Reset() { *m = ReqAllExecBalance{} }
func
(
m
*
ReqAllExecBalance
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
ReqAllExecBalance
)
ProtoMessage
()
{}
func
(
*
ReqAllExecBalance
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
8
}
return
fileDescriptor_8e28828dcb8d24f0
,
[]
int
{
9
}
}
func
(
m
*
ReqAllExecBalance
)
XXX_Unmarshal
(
b
[]
byte
)
error
{
...
...
@@ -534,6 +581,7 @@ func init() {
proto
.
RegisterType
((
*
ReceiptExecAccountTransfer
)(
nil
),
"types.ReceiptExecAccountTransfer"
)
proto
.
RegisterType
((
*
ReceiptAccountTransfer
)(
nil
),
"types.ReceiptAccountTransfer"
)
proto
.
RegisterType
((
*
ReceiptAccountMint
)(
nil
),
"types.ReceiptAccountMint"
)
proto
.
RegisterType
((
*
ReceiptAccountBurn
)(
nil
),
"types.ReceiptAccountBurn"
)
proto
.
RegisterType
((
*
ReqBalance
)(
nil
),
"types.ReqBalance"
)
proto
.
RegisterType
((
*
Accounts
)(
nil
),
"types.Accounts"
)
proto
.
RegisterType
((
*
ExecAccount
)(
nil
),
"types.ExecAccount"
)
...
...
@@ -544,32 +592,33 @@ func init() {
func
init
()
{
proto
.
RegisterFile
(
"account.proto"
,
fileDescriptor_8e28828dcb8d24f0
)
}
var
fileDescriptor_8e28828dcb8d24f0
=
[]
byte
{
// 427 bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0xc4
,
0x54
,
0xcd
,
0x6a
,
0x14
,
0x41
,
0x10
,
0xa6
,
0xf7
,
0x27
,
0x9b
,
0xa9
,
0xd5
,
0x80
,
0x7d
,
0x08
,
0x4d
,
0x30
,
0x38
,
0xf6
,
0x69
,
0x0e
,
0xb2
,
0x0b
,
0x8e
,
0x2f
,
0x90
,
0x80
,
0xe0
,
0x45
,
0x84
,
0xd6
,
0x53
,
0x2e
,
0xd2
,
0xd3
,
0xa9
,
0x75
,
0x07
,
0x27
,
0x3d
,
0x93
,
0xee
,
0x5e
,
0x71
,
0x7d
,
0x00
,
0x5f
,
0x43
,
0xf0
,
0x49
,
0xa5
,
0x6b
,
0x7b
,
0xb2
,
0xb3
,
0x06
,
0x25
,
0x07
,
0xc1
,
0xdb
,
0xd4
,
0xf7
,
0x55
,
0xd5
,
0xf7
,
0x75
,
0x55
,
0x31
,
0xf0
,
0x58
,
0x1b
,
0xd3
,
0x6e
,
0x6c
,
0x58
,
0x74
,
0xae
,
0x0d
,
0x2d
,
0x9f
,
0x86
,
0x6d
,
0x87
,
0x5e
,
0x7e
,
0x86
,
0xd9
,
0xc5
,
0x0e
,
0xe7
,
0x67
,
0x70
,
0x6c
,
0x36
,
0xce
,
0xa1
,
0x35
,
0x5b
,
0xc1
,
0x72
,
0x56
,
0x4c
,
0xd5
,
0x5d
,
0xcc
,
0x05
,
0xcc
,
0x2a
,
0xdd
,
0x68
,
0x6b
,
0x50
,
0x8c
,
0x72
,
0x56
,
0x8c
,
0x55
,
0x1f
,
0xf2
,
0x53
,
0x38
,
0x5a
,
0xb9
,
0xf6
,
0x1b
,
0x5a
,
0x31
,
0x26
,
0x22
,
0x45
,
0x9c
,
0xc3
,
0x44
,
0x5f
,
0x5f
,
0x3b
,
0x31
,
0xc9
,
0x59
,
0x91
,
0x29
,
0xfa
,
0x96
,
0xdf
,
0x19
,
0x9c
,
0x29
,
0x34
,
0x58
,
0x77
,
0xe1
,
0xf5
,
0x57
,
0x34
,
0x49
,
0xf8
,
0x83
,
0xd3
,
0xd6
,
0xaf
,
0xd0
,
0x45
,
0x03
,
0x18
,
0xe1
,
0x58
,
0xc6
,
0xa8
,
0xec
,
0x2e
,
0xe6
,
0x12
,
0x26
,
0x9d
,
0xc3
,
0x2f
,
0xa4
,
0x3e
,
0x7f
,
0x79
,
0xb2
,
0x20
,
0xf7
,
0x8b
,
0xd4
,
0x41
,
0x11
,
0xc7
,
0x0b
,
0x98
,
0xed
,
0x0c
,
0x07
,
0xf2
,
0x72
,
0x3f
,
0xad
,
0xa7
,
0xe5
,
0x0a
,
0x4e
,
0x93
,
0x8f
,
0xdf
,
0x3d
,
0xf4
,
0x3a
,
0xec
,
0x61
,
0x3a
,
0xa3
,
0xbf
,
0xeb
,
0x54
,
0xc0
,
0x0f
,
0x75
,
0xde
,
0xd6
,
0x36
,
0xfc
,
0x63
,
0x8d
,
0x9f
,
0x0c
,
0x40
,
0xe1
,
0xed
,
0x65
,
0xda
,
0xc7
,
0x53
,
0xc8
,
0xe2
,
0xac
,
0xd1
,
0x7b
,
0xf4
,
0x82
,
0xe5
,
0xe3
,
0x22
,
0x53
,
0x7b
,
0x20
,
0x6e
,
0x2b
,
0x8e
,
0x14
,
0x1d
,
0x75
,
0xcd
,
0x54
,
0x8a
,
0x62
,
0x95
,
0x0f
,
0x3a
,
0xe0
,
0x1b
,
0xed
,
0xd7
,
0x34
,
0xbc
,
0x4c
,
0xed
,
0x01
,
0x7e
,
0x0e
,
0xa0
,
0xbd
,
0xc7
,
0xf0
,
0x31
,
0x66
,
0xa7
,
0x8d
,
0x66
,
0x84
,
0xc4
,
0x35
,
0xf2
,
0xe7
,
0xf0
,
0x68
,
0x47
,
0xfb
,
0xed
,
0x4d
,
0xd5
,
0x36
,
0x62
,
0x4a
,
0x09
,
0x73
,
0xc2
,
0xde
,
0x13
,
0x24
,
0x5f
,
0xc0
,
0x71
,
0x32
,
0xee
,
0x79
,
0x0e
,
0x63
,
0x6d
,
0x0c
,
0x79
,
0xbb
,
0xff
,
0xac
,
0x48
,
0xc9
,
0x77
,
0x30
,
0x1f
,
0xdc
,
0xc7
,
0xc0
,
0x34
,
0x3b
,
0x30
,
0x5d
,
0xc0
,
0x2c
,
0xdd
,
0xf4
,
0x9f
,
0x66
,
0x94
,
0x68
,
0x79
,
0x05
,
0x27
,
0x17
,
0x4d
,
0x13
,
0x7b
,
0xf6
,
0x63
,
0xea
,
0xcf
,
0x93
,
0xed
,
0xcf
,
0x93
,
0xbf
,
0x3a
,
0x90
,
0x15
,
0x23
,
0x32
,
0xc8
,
0x53
,
0xcf
,
0x01
,
0xa3
,
0x86
,
0x69
,
0xf2
,
0x07
,
0x83
,
0x27
,
0x0a
,
0x6f
,
0x1f
,
0xd0
,
0xff
,
0x3f
,
0x0d
,
0xff
,
0xf2
,
0xd9
,
0xd5
,
0xf9
,
0xa7
,
0x3a
,
0xac
,
0x37
,
0xd5
,
0xc2
,
0xb4
,
0x37
,
0xcb
,
0xb2
,
0x34
,
0x76
,
0x69
,
0xd6
,
0xba
,
0xb6
,
0x65
,
0xb9
,
0xa4
,
0xb7
,
0x55
,
0x47
,
0xf4
,
0x4b
,
0x28
,
0x7f
,
0x05
,
0x00
,
0x00
,
0xff
,
0xff
,
0x1b
,
0xce
,
0xc2
,
0x14
,
0x23
,
0x04
,
0x00
,
0x00
,
// 434 bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0xc4
,
0x54
,
0xcd
,
0x6e
,
0x13
,
0x31
,
0x10
,
0x96
,
0xf3
,
0xd3
,
0x74
,
0x27
,
0x50
,
0x09
,
0x1f
,
0x2a
,
0xab
,
0xa2
,
0x62
,
0xf1
,
0x69
,
0x0f
,
0x28
,
0x91
,
0x58
,
0x5e
,
0xa0
,
0x91
,
0x90
,
0xb8
,
0x20
,
0x24
,
0xc3
,
0xa9
,
0x17
,
0xe4
,
0x75
,
0x27
,
0x24
,
0x22
,
0xf5
,
0x6e
,
0x6d
,
0x2f
,
0x22
,
0x3c
,
0x00
,
0xaf
,
0x81
,
0xc4
,
0x93
,
0x22
,
0x4f
,
0xbc
,
0xcd
,
0x86
,
0x0a
,
0xd4
,
0x03
,
0xa8
,
0xb7
,
0x9d
,
0xef
,
0x1b
,
0xcf
,
0xf7
,
0xd9
,
0x33
,
0xb3
,
0xf0
,
0x58
,
0x1b
,
0x53
,
0xb7
,
0x36
,
0xcc
,
0x1a
,
0x57
,
0x87
,
0x9a
,
0x8f
,
0xc3
,
0xb6
,
0x41
,
0x2f
,
0x3f
,
0xc3
,
0xe4
,
0x62
,
0x87
,
0xf3
,
0x33
,
0x38
,
0x36
,
0xad
,
0x73
,
0x68
,
0xcd
,
0x56
,
0xb0
,
0x9c
,
0x15
,
0x63
,
0x75
,
0x1b
,
0x73
,
0x01
,
0x93
,
0x4a
,
0x6f
,
0xb4
,
0x35
,
0x28
,
0x06
,
0x39
,
0x2b
,
0x86
,
0xaa
,
0x0b
,
0xf9
,
0x29
,
0x1c
,
0x2d
,
0x5d
,
0xfd
,
0x0d
,
0xad
,
0x18
,
0x12
,
0x91
,
0x22
,
0xce
,
0x61
,
0xa4
,
0xaf
,
0xae
,
0x9c
,
0x18
,
0xe5
,
0xac
,
0xc8
,
0x14
,
0x7d
,
0xcb
,
0xef
,
0x0c
,
0xce
,
0x14
,
0x1a
,
0x5c
,
0x37
,
0xe1
,
0xf5
,
0x57
,
0x34
,
0x49
,
0xf8
,
0x83
,
0xd3
,
0xd6
,
0x2f
,
0xd1
,
0x45
,
0x03
,
0x18
,
0xe1
,
0x78
,
0x8c
,
0xd1
,
0xb1
,
0xdb
,
0x98
,
0x4b
,
0x18
,
0x35
,
0x0e
,
0xbf
,
0x90
,
0xfa
,
0xf4
,
0xe5
,
0xc9
,
0x8c
,
0xdc
,
0xcf
,
0x52
,
0x05
,
0x45
,
0x1c
,
0x2f
,
0x60
,
0xb2
,
0x33
,
0x1c
,
0xc8
,
0xcb
,
0xdd
,
0xb4
,
0x8e
,
0x96
,
0x4b
,
0x38
,
0x4d
,
0x3e
,
0x7e
,
0xf7
,
0xd0
,
0xe9
,
0xb0
,
0xfb
,
0xe9
,
0x0c
,
0xfe
,
0xae
,
0x53
,
0x01
,
0x3f
,
0xd4
,
0x79
,
0xbb
,
0xb6
,
0xe1
,
0x7f
,
0x6b
,
0x2c
,
0x5a
,
0x67
,
0xff
,
0xb1
,
0xc6
,
0x4f
,
0x06
,
0xa0
,
0xf0
,
0x66
,
0x91
,
0x7a
,
0xfe
,
0x14
,
0xb2
,
0xd8
,
0x4f
,
0xf4
,
0x1e
,
0xbd
,
0x60
,
0xf9
,
0xb0
,
0xc8
,
0xd4
,
0x1e
,
0x88
,
0x13
,
0x11
,
0xdb
,
0x86
,
0x8e
,
0xaa
,
0x66
,
0x2a
,
0x45
,
0xf1
,
0x94
,
0x0f
,
0x3a
,
0xe0
,
0x1b
,
0xed
,
0x57
,
0xd4
,
0xa0
,
0x4c
,
0xed
,
0x01
,
0x7e
,
0x0e
,
0xa0
,
0xbd
,
0xc7
,
0xf0
,
0x31
,
0x66
,
0xa7
,
0xa9
,
0xc9
,
0x08
,
0x89
,
0xa3
,
0xc2
,
0x9f
,
0xc3
,
0xa3
,
0x1d
,
0xed
,
0xb7
,
0xd7
,
0x55
,
0xbd
,
0x11
,
0x63
,
0x4a
,
0x98
,
0x12
,
0xf6
,
0x9e
,
0x20
,
0xf9
,
0x02
,
0x8e
,
0x93
,
0x71
,
0xcf
,
0x73
,
0x18
,
0x6a
,
0x63
,
0xc8
,
0xdb
,
0xdd
,
0x6b
,
0x45
,
0x4a
,
0xbe
,
0x83
,
0x69
,
0x6f
,
0x06
,
0x7b
,
0xa6
,
0xd9
,
0x81
,
0xe9
,
0x02
,
0x26
,
0x69
,
0x6f
,
0xfe
,
0xf4
,
0x46
,
0x89
,
0x96
,
0x97
,
0x70
,
0x72
,
0xb1
,
0xd9
,
0xc4
,
0x9a
,
0xdd
,
0x33
,
0x75
,
0x2b
,
0xc0
,
0xf6
,
0x2b
,
0xc0
,
0x5f
,
0x1d
,
0xc8
,
0x8a
,
0x01
,
0x19
,
0xe4
,
0xa9
,
0x66
,
0x8f
,
0x51
,
0xfd
,
0x34
,
0xf9
,
0x83
,
0xc1
,
0x13
,
0x85
,
0x37
,
0xf7
,
0xa8
,
0xff
,
0x40
,
0x8f
,
0xbf
,
0x78
,
0x76
,
0x79
,
0xfe
,
0x69
,
0x1d
,
0x56
,
0x6d
,
0x35
,
0x33
,
0xf5
,
0xf5
,
0xbc
,
0x2c
,
0x8d
,
0x9d
,
0x9b
,
0x95
,
0x5e
,
0xdb
,
0xb2
,
0x9c
,
0xd3
,
0xdd
,
0xaa
,
0x23
,
0xfa
,
0xed
,
0x94
,
0xbf
,
0x02
,
0x00
,
0x00
,
0xff
,
0xff
,
0x57
,
0xdf
,
0x86
,
0xd3
,
0x87
,
0x04
,
0x00
,
0x00
,
}
vendor/github.com/33cn/chain33/types/const.go
View file @
112b9f75
...
...
@@ -104,6 +104,7 @@ const (
TyLogGenesisDeposit
=
12
TyLogRollback
=
13
TyLogMint
=
14
TyLogBurn
=
15
)
//SystemLog 系统log日志
...
...
@@ -121,6 +122,8 @@ var SystemLog = map[int64]*LogInfo{
TyLogGenesisTransfer
:
{
reflect
.
TypeOf
(
ReceiptAccountTransfer
{}),
"LogGenesisTransfer"
},
TyLogGenesisDeposit
:
{
reflect
.
TypeOf
(
ReceiptAccountTransfer
{}),
"LogGenesisDeposit"
},
TyLogRollback
:
{
reflect
.
TypeOf
(
LocalDBSet
{}),
"LogRollback"
},
TyLogMint
:
{
reflect
.
TypeOf
(
ReceiptAccountMint
{}),
"LogMint"
},
TyLogBurn
:
{
reflect
.
TypeOf
(
ReceiptAccountBurn
{}),
"LogBurn"
},
}
//exec type
...
...
vendor/github.com/33cn/chain33/types/error.go
View file @
112b9f75
...
...
@@ -181,4 +181,7 @@ var (
ErrHeightOverflow
=
errors
.
New
(
"ErrHeightOverflow"
)
ErrRecordBlockSequence
=
errors
.
New
(
"ErrRecordBlockSequence"
)
ErrExecPanic
=
errors
.
New
(
"ErrExecPanic"
)
ErrDisableWrite
=
errors
.
New
(
"ErrDisableWrite"
)
ErrDisableRead
=
errors
.
New
(
"ErrDisableRead"
)
)
vendor/github.com/33cn/chain33/types/proto/account.proto
View file @
112b9f75
...
...
@@ -41,6 +41,11 @@ message ReceiptAccountMint {
Account
current
=
2
;
}
message
ReceiptAccountBurn
{
Account
prev
=
1
;
Account
current
=
2
;
}
//查询一个地址列表在某个执行器中余额
message
ReqBalance
{
//地址列表
...
...
vendor/github.com/33cn/chain33/util/exec.go
View file @
112b9f75
...
...
@@ -205,25 +205,17 @@ func ReportErrEventToFront(logger log.Logger, client queue.Client, frommodule st
//DelDupKey 删除重复的key
func
DelDupKey
(
kvs
[]
*
types
.
KeyValue
)
[]
*
types
.
KeyValue
{
dupindex
:=
make
(
map
[
string
]
int
)
hasdup
:=
false
for
i
,
kv
:=
range
kvs
{
n
:=
0
for
_
,
kv
:=
range
kvs
{
skey
:=
string
(
kv
.
Key
)
if
index
,
ok
:=
dupindex
[
skey
];
ok
{
hasdup
=
true
kvs
[
index
]
=
nil
}
dupindex
[
skey
]
=
i
}
//没有重复的情况下,不需要重新处理
if
!
hasdup
{
return
kvs
}
index
:=
0
for
_
,
kv
:=
range
kvs
{
if
kv
!=
nil
{
//重复的key 替换老的key
kvs
[
index
]
=
kv
index
++
}
else
{
dupindex
[
skey
]
=
n
kvs
[
n
]
=
kv
n
++
}
}
return
kvs
[
0
:
index
]
return
kvs
[
0
:
n
]
}
vendor/github.com/33cn/chain33/util/util.go
View file @
112b9f75
...
...
@@ -225,8 +225,9 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er
//通过consensus module 再次检查
ulog
.
Debug
(
"ExecBlock"
,
"height------->"
,
block
.
Height
,
"ntx"
,
len
(
block
.
Txs
))
beg
:=
types
.
Now
()
beg2
:=
beg
defer
func
()
{
ulog
.
Info
(
"ExecBlock"
,
"height"
,
block
.
Height
,
"ntx"
,
len
(
block
.
Txs
),
"writebatchsync"
,
sync
,
"cost"
,
types
.
Since
(
beg
))
ulog
.
Info
(
"ExecBlock"
,
"height"
,
block
.
Height
,
"ntx"
,
len
(
block
.
Txs
),
"writebatchsync"
,
sync
,
"cost"
,
types
.
Since
(
beg
2
))
}()
if
errReturn
&&
block
.
Height
>
0
&&
!
block
.
CheckSign
()
{
...
...
@@ -330,7 +331,6 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er
}
}
ulog
.
Info
(
"ExecBlock"
,
"CheckBlock"
,
types
.
Since
(
beg
))
beg
=
types
.
Now
()
// 写数据库失败时需要及时返回错误,防止错误数据被写入localdb中CHAIN33-567
err
=
ExecKVSetCommit
(
client
,
block
.
StateHash
)
if
err
!=
nil
{
...
...
vendor/github.com/33cn/chain33/util/util_test.go
View file @
112b9f75
...
...
@@ -144,8 +144,8 @@ func TestDelDupKey(t *testing.T) {
{
Key
:
[]
byte
(
"hello"
),
Value
:
[]
byte
(
"world2"
)},
}
result
:=
[]
*
types
.
KeyValue
{
{
Key
:
[]
byte
(
"hello1"
),
Value
:
[]
byte
(
"world"
)},
{
Key
:
[]
byte
(
"hello"
),
Value
:
[]
byte
(
"world2"
)},
{
Key
:
[]
byte
(
"hello1"
),
Value
:
[]
byte
(
"world"
)},
}
kvs
=
DelDupKey
(
kvs
)
assert
.
Equal
(
t
,
kvs
,
result
)
...
...
@@ -173,6 +173,7 @@ func BenchmarkDelDupKey(b *testing.B) {
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
key
,
Value
:
value
})
}
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
testkv
:=
make
([]
*
types
.
KeyValue
,
len
(
kvs
))
copy
(
testkv
,
kvs
)
...
...
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