Commit 6ea8e651 authored by pengjun's avatar pengjun

Merge remote-tracking branch 'upstream/master'

parents c0128c37 e97eda52
......@@ -27,7 +27,7 @@ build/para.sh
build/system-test-rpc.sh
build/ci
build/autotest/*
!build/autotest/build.sh
!build/autotest/run.sh
.DS_Store
logs/
build/wallet
......
......@@ -9,7 +9,6 @@ CLI := build/chain33-cli
SRC_CLI := github.com/33cn/plugin/cli
APP := build/chain33
export CHAIN33_PATH=$(shell go list -f {{.Dir}} github.com/33cn/chain33)
export PLUGIN_PATH=$(shell go list -f {{.Dir}} github.com/33cn/plugin)
BUILD_FLAGS = -ldflags "-X github.com/33cn/chain33/common/version.GitCommit=`git rev-parse --short=8 HEAD`"
LDFLAGS := -ldflags "-w -s"
PKG_LIST_VET := `go list ./... | grep -v "vendor" | grep -v plugin/dapp/evm/executor/vm/common/crypto/bn256`
......@@ -44,23 +43,13 @@ vet:
@go vet ${PKG_LIST_VET}
autotest: ## build autotest binary
@cd build/autotest && bash ./build.sh ${CHAIN33_PATH} && cd ../../
@cd build/autotest && bash ./run.sh build && cd ../../
@if [ -n "$(dapp)" ]; then \
rm -rf build/autotest/local \
&& cp -r $(CHAIN33_PATH)/build/autotest/local $(CHAIN33_PATH)/build/autotest/*.sh build/autotest \
&& cd build/autotest && chmod -R 755 local && chmod 755 *.sh && bash ./copy-autotest.sh local \
&& cd local && bash ./local-autotest.sh $(dapp) \
&& cd ../../../; fi
cd build/autotest && bash ./run.sh local $(dapp) && cd ../../; fi
autotest_ci: autotest ## autotest ci
@rm -rf build/autotest/jerkinsci \
&& cp -r $(CHAIN33_PATH)/build/autotest/jerkinsci $(CHAIN33_PATH)/build/autotest/*.sh build/autotest/ \
cd build/autotest &&chmod -R 755 jerkinsci && chmod 755 *.sh && bash ./copy-autotest.sh jerkinsci/temp$(proj) \
&& cd jerkinsci && bash ./jerkins-ci-autotest.sh $(proj) && cd ../../../
@cd build/autotest && bash ./run.sh jerkinsci $(proj) && cd ../../
autotest_tick: autotest ## run with ticket mining
@rm -rf build/autotest/gitlabci \
&& cp -r $(CHAIN33_PATH)/build/autotest/gitlabci $(CHAIN33_PATH)/build/autotest/*.sh build/autotest/ \
&& cd build/autotest &&chmod -R 755 gitlabci && chmod 755 *.sh && bash ./copy-autotest.sh gitlabci \
&& cd gitlabci && bash ./gitlab-ci-autotest.sh build && cd ../../../
@cd build/autotest && bash ./run.sh gitlabci build && cd ../../
update: ## version 可以是git tag打的具体版本号,也可以是commit hash, 什么都不填的情况下默认从master分支拉取最新版本
@if [ -n "$(version)" ]; then \
......
#!/usr/bin/env bash
set -e
set -o pipefail
#set -o verbose
#set -o xtrace
CHAIN33_PATH=$1
sedfix=""
if [ "$(uname)" == "Darwin" ]; then
sedfix=".bak"
fi
echo "=====chain33_path: ${CHAIN33_PATH} ========"
AutoTestMain="${CHAIN33_PATH}/cmd/autotest/main.go"
ImportPlugin='"github.com/33cn/plugin/plugin"'
function build_auto_test() {
cp "${AutoTestMain}" ./
sed -i $sedfix "/^package/a import _ ${ImportPlugin}" main.go
go build -v -i -o autotest
}
function clean_auto_test() {
rm -f ../autotest/main.go
}
trap "clean_auto_test" INT TERM EXIT
build_auto_test
#!/usr/bin/env bash
set -e
set -o pipefail
#set -o verbose
#set -o xtrace
# os: ubuntu18.04 x64
sedfix=""
if [ "$(uname)" == "Darwin" ]; then
sedfix=".bak"
fi
## get chain33 path
CHAIN33_PATH=$(grep -m1 github.com/33cn/chain33 ../../go.mod | grep -o '[^ ]\+$')
CHAIN33_PATH="${CHAIN33_PATH%/}"
if [[ -d ../../${CHAIN33_PATH} ]]; then
CHAIN33_PATH=../../"$CHAIN33_PATH"
elif [[ ! -d ${CHAIN33_PATH} ]]; then
CHAIN33_PATH="${GOPATH}"/pkg/mod/github.com/33cn/chain33@"$CHAIN33_PATH"
fi
function build_auto_test() {
trap "rm -f ../autotest/main.go" INT TERM EXIT
local AutoTestMain="${CHAIN33_PATH}/cmd/autotest/main.go"
cp "${AutoTestMain}" ./
sed -i $sedfix '/^package/a import _ \"github.com\/33cn\/plugin\/plugin\"' main.go
go build -v -i -o autotest
}
function copyAutoTestConfig() {
declare -a Chain33AutoTestDirs=("${CHAIN33_PATH}/system" "../../plugin")
echo "#copy auto test config to path \"$1\""
local AutoTestConfigFile="$1/autotest.toml"
#pre config auto test
{
echo 'cliCmd="./chain33-cli"'
echo "checkTimeout=60"
} >"${AutoTestConfigFile}"
#copy all the dapp test case config file
for rootDir in "${Chain33AutoTestDirs[@]}"; do
if [[ ! -d ${rootDir} ]]; then
continue
fi
testDirArr=$(find "${rootDir}" -type d -name autotest)
for autotest in ${testDirArr}; do
dapp=$(basename "$(dirname "${autotest}")")
dappConfig=${autotest}/${dapp}.toml
#make sure dapp have auto test config
if [ -e "${dappConfig}" ]; then
cp "${dappConfig}" "$1"/
#add dapp test case config
{
echo "[[TestCaseFile]]"
echo "dapp=\"$dapp\""
echo "filename=\"$dapp.toml\""
} >>"${AutoTestConfigFile}"
fi
done
done
}
function copyChain33() {
echo "# copy chain33 bin to path \"$1\", make sure build chain33"
cp ../chain33 ../chain33-cli ../chain33.toml "$1"
cp "${CHAIN33_PATH}"/cmd/chain33/chain33.test.toml "$1"
}
function copyAll() {
dir="$1"
#check dir exist
if [[ ! -d ${dir} ]]; then
mkdir "${dir}"
fi
cp autotest "${dir}"
copyAutoTestConfig "${dir}"
copyChain33 "${dir}"
echo "# all copy have done!"
}
function main() {
if [[ $1 == "build" ]]; then #build autotest
build_auto_test
else
dir="$1"
echo "$dir"
rm -rf ../autotest/"$dir" && mkdir "$dir"
cp -r "$CHAIN33_PATH"/build/autotest/"$dir"/* ./"$dir"/ && copyAll "$dir"
chmod -R 755 "$dir" && cd "$dir" && ./autotest.sh "${@:2}" && cd ../
fi
}
main "$@"
......@@ -3,6 +3,7 @@
RAW_TX_HASH=""
LAST_BLOCK_HASH=""
CASE_ERR=""
RETURN_RESP=""
#color
RED='\033[1;31m'
......@@ -16,11 +17,32 @@ echo_rst() {
echo -e "${GRE}$1 not support${NOC}"
else
echo -e "${RED}$1 fail${NOC}"
echo -e "${RED}$3 ${NOC}"
CASE_ERR="err"
echo $CASE_ERR
fi
}
chain33_Http() {
# echo "#$4 request: request="$1" MAIN_HTTP="$2" js="$3" FUNCNAME="$4" response="$5""
local body
body=$(curl -ksd "$1" "$2")
RETURN_RESP=$(echo "$body" | jq -r "$5")
echo "#response: $body" "$RETURN_RESP"
ok=$(echo "$body" | jq -r "$3")
[ "$ok" == true ]
rst=$?
echo_rst "$4" "$rst" "$body"
}
chain33_SignAndSendTxWait() {
# txHex="$1" priKey="$2" MAIN_HTTP="$3" FUNCNAME="$4"
req='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$1"'"}]}'
chain33_Http "$req" "$3" '(.result.txs[0].execer != "") and (.result.txs[0].execer != null)' "$4"
chain33_SignAndSendTx "$1" "$2" "$3"
chain33_BlockWait 1 "$3"
}
chain33_BlockWait() {
local MAIN_HTTP=$2
local req='"method":"Chain33.GetLastHeader","params":[]'
......@@ -112,7 +134,7 @@ chain33_ImportPrivkey() {
[ "$ok" == true ]
}
chain33_SignRawTx() {
chain33_SignAndSendTx() {
local txHex="$1"
local priKey="$2"
local MAIN_HTTP=$3
......
......@@ -108,6 +108,8 @@ mainBlockHashForkHeight=209186
mainForkParacrossCommitTx=2270000
#主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度, ycc或其他按实际修改
mainLoopCheckCommitTxDoneForkHeight=4320000
#主链交易验证merkelRoot主链分叉高度,需和主链保持一致,不可修改
mainVerifyMerkleRootForkHeight=-1
#主链每隔几个没有相关平行链交易的区块,平行链上打包空区块,缺省从平行链blockHeight=0开始,依次增长,空块间隔不能为0
[[consensus.sub.para.emptyBlockInterval]]
blockHeight=0
......@@ -210,7 +212,8 @@ ForkBase58AddressCheck=0
ForkEnableParaRegExec=0
ForkCacheDriver=0
ForkTicketFundAddrV1=-1 #fork6.3
#主链和平行链都使用同一个fork高度
ForkRootHash= 4500000
[fork.sub.coins]
Enable=0
......
......@@ -3,7 +3,7 @@ module github.com/33cn/plugin
go 1.12
require (
github.com/33cn/chain33 v0.0.0-20191113065720-35a79536c298
github.com/33cn/chain33 v0.0.0-20191225114001-0e761fbcd8ce
github.com/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac
......
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/33cn/chain33 v0.0.0-20191113065720-35a79536c298 h1:lzR9LMi2nhczH8H6oU9famEl0+glRR52ZTbS9yTOOr8=
github.com/33cn/chain33 v0.0.0-20191113065720-35a79536c298/go.mod h1:4I8n+Zyf3t0UKM5jjpqJY627Tub62oXkLsdzIv4r6rQ=
github.com/33cn/chain33 v0.0.0-20191225114001-0e761fbcd8ce h1:8w3fHBpsupag2ue5iwyIv8cp6va2LtvZuJ/OhvNEEpk=
github.com/33cn/chain33 v0.0.0-20191225114001-0e761fbcd8ce/go.mod h1:4I8n+Zyf3t0UKM5jjpqJY627Tub62oXkLsdzIv4r6rQ=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
......
......@@ -465,9 +465,13 @@ func (client *Client) CreateBlock() {
newblock.ParentHash = lastBlock.Hash(cfg)
newblock.Height = lastBlock.Height + 1
client.AddTxsToBlock(&newblock, txs)
//
newblock.Difficulty = cfg.GetP(0).PowLimitBits
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
//需要首先对交易进行排序然后再计算TxHash
if cfg.IsFork(newblock.Height, "ForkRootHash") {
newblock.Txs = types.TransactionSort(newblock.Txs)
}
newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs)
newblock.BlockTime = client.blockTime
err := client.WriteBlock(lastBlock.StateHash, &newblock)
......
......@@ -58,8 +58,8 @@ type client struct {
commitMsgClient *commitMsgClient
blockSyncClient *blockSyncClient
multiDldCli *multiDldClient
authAccount string
privateKey crypto.PrivKey
jumpDldCli *jumpDldClient
minerPrivateKey crypto.PrivKey
wg sync.WaitGroup
subCfg *subConfig
isClosed int32
......@@ -81,10 +81,10 @@ type subConfig struct {
WaitBlocks4CommitMsg int32 `json:"waitBlocks4CommitMsg,omitempty"`
GenesisAmount int64 `json:"genesisAmount,omitempty"`
MainBlockHashForkHeight int64 `json:"mainBlockHashForkHeight,omitempty"`
MainVrfMerkleRootForkHeight int64 `json:"mainVrfMerkleRootForkHeight,omitempty"`
WaitConsensStopTimes uint32 `json:"waitConsensStopTimes,omitempty"`
MaxCacheCount int64 `json:"maxCacheCount,omitempty"`
MaxSyncErrCount int32 `json:"maxSyncErrCount,omitempty"`
FetchFilterParaTxsClose bool `json:"fetchFilterParaTxsClose,omitempty"`
BatchFetchBlockCount int64 `json:"batchFetchBlockCount,omitempty"`
ParaConsensStartHeight int64 `json:"paraConsensStartHeight,omitempty"`
MultiDownloadOpen bool `json:"multiDownloadOpen,omitempty"`
......@@ -92,6 +92,7 @@ type subConfig struct {
MultiDownJobBuffNum uint32 `json:"multiDownJobBuffNum,omitempty"`
MultiDownServerRspTime uint32 `json:"multiDownServerRspTime,omitempty"`
RmCommitParamMainHeight int64 `json:"rmCommitParamMainHeight,omitempty"`
JumpDownloadOpen bool `json:"jumpDownloadOpen,omitempty"`
}
// New function to init paracross env
......@@ -139,14 +140,14 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
para := &client{
BaseClient: c,
authAccount: subcfg.AuthAccount,
privateKey: priKey,
minerPrivateKey: priKey,
subCfg: &subcfg,
quitCreate: make(chan struct{}),
}
para.commitMsgClient = &commitMsgClient{
paraClient: para,
authAccount: subcfg.AuthAccount,
waitMainBlocks: waitBlocks4CommitMsg,
waitConsensStopTimes: waitConsensStopTimes,
consensHeight: -2,
......@@ -199,6 +200,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
if subcfg.MultiDownServerRspTime > 0 {
para.multiDldCli.serverTimeout = subcfg.MultiDownServerRspTime
}
para.jumpDldCli = &jumpDldClient{paraClient: para}
if subcfg.MainVrfMerkleRootForkHeight <= 0 {
subcfg.MainVrfMerkleRootForkHeight = types.MaxHeight
}
c.SetChild(para)
return para
}
......@@ -298,7 +306,7 @@ func (client *client) InitBlock() {
}
tx := client.CreateGenesisTx()
newblock.Txs = tx
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.GetMainHeight(), newblock.Txs)
err := client.blockSyncClient.createGenesisBlock(newblock)
if err != nil {
panic(fmt.Sprintf("para chain create genesis block,err=%s", err.Error()))
......
......@@ -175,7 +175,7 @@ func TestAddMinerTx(t *testing.T) {
para := &client{BaseClient: &drivers.BaseClient{}}
para.SetAPI(api)
para.subCfg = new(subConfig)
para.privateKey = priKey
para.minerPrivateKey = priKey
para.commitMsgClient = new(commitMsgClient)
para.commitMsgClient.paraClient = para
......
......@@ -13,12 +13,12 @@ import (
"sync/atomic"
"unsafe"
"bytes"
"sync"
"strconv"
"bytes"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/types"
......@@ -31,7 +31,7 @@ const (
consensusInterval = 10 //about 1 new block interval
minerInterval = 10 //5s的主块间隔后分叉概率增加,10s可以消除一些分叉回退
waitBlocks4CommitMsg int32 = 3
waitBlocks4CommitMsg int32 = 5 //commit msg共识发送后等待几个块没确认则重发
waitConsensStopTimes uint32 = 30 //30*10s = 5min
)
......@@ -42,7 +42,7 @@ type paraSelfConsEnable struct {
type commitMsgClient struct {
paraClient *client
waitMainBlocks int32 //等待平行链共识消息在主链上链并成功的块数,超出会重发共识消息,最小是2
waitMainBlocks int32 //等待平行链共识消息在主链上链并成功的块数,超出会重发共识消息
waitConsensStopTimes uint32 //共识高度低于完成高度, reset高度重发等待的次数
resetCh chan interface{}
sendMsgCh chan *types.Transaction
......@@ -53,6 +53,7 @@ type commitMsgClient struct {
consensHeight int64
consensDoneHeight int64
selfConsensError int32 //自共识比主链共识更高的异常场景,需要等待自共识<=主链共识再发送
authAccount string
authAccountIn bool
isRollBack int32
checkTxCommitTimes int32
......@@ -76,7 +77,7 @@ func (client *commitMsgClient) handler() {
client.paraClient.wg.Add(1)
go client.getMainConsensusInfo()
if client.paraClient.authAccount != "" {
if client.authAccount != "" {
client.paraClient.wg.Add(1)
client.sendMsgCh = make(chan *types.Transaction, 1)
go client.sendCommitMsg()
......@@ -129,8 +130,8 @@ func (client *commitMsgClient) resetNotify() {
}
//新的区块产生,检查是否有commitTx正在发送入口
func (client *commitMsgClient) commitTxCheckNotify(txs []*types.TxDetail) {
if client.checkCommitTxSuccess(txs) {
func (client *commitMsgClient) commitTxCheckNotify(block *types.ParaTxDetail) {
if client.checkCommitTxSuccess(block) {
client.sendCommitTx()
}
}
......@@ -199,23 +200,7 @@ func (client *commitMsgClient) sendCommitTx() {
}
func (client *commitMsgClient) verifyTx(curTx *types.Transaction, verifyTxs map[string]bool) bool {
if verifyTxs[string(curTx.Hash())] {
client.setCurrentTx(nil)
return true
}
client.checkTxCommitTimes++
if client.checkTxCommitTimes >= client.waitMainBlocks {
client.checkTxCommitTimes = 0
client.resetSendEnv()
return true
}
return false
}
func (client *commitMsgClient) checkCommitTxSuccess(txs []*types.TxDetail) bool {
func (client *commitMsgClient) checkCommitTxSuccess(block *types.ParaTxDetail) bool {
client.mutex.Lock()
defer client.mutex.Unlock()
......@@ -224,10 +209,13 @@ func (client *commitMsgClient) checkCommitTxSuccess(txs []*types.TxDetail) bool
return false
}
//只处理AddType block,回滚的不处理
if block.Type == types.AddBlock {
//使用map 比每个交易hash byte比较效率应该会高些
txMap := make(map[string]bool)
//committx是平行链交易
if types.IsParaExecName(string(curTx.Execer)) {
for _, tx := range txs {
for _, tx := range block.TxDetails {
if bytes.HasSuffix(tx.Tx.Execer, []byte(pt.ParaX)) && tx.Receipt.Ty == types.ExecOk {
txMap[string(tx.Tx.Hash())] = true
}
......@@ -244,12 +232,33 @@ func (client *commitMsgClient) checkCommitTxSuccess(txs []*types.TxDetail) bool
}
}
//如果没找到且当前正在追赶,则不计数,如果找到了,即便当前在追赶,也立即处理
if !txMap[string(curTx.Hash())] && !client.paraClient.isCaughtUp() {
//验证通过
if txMap[string(curTx.Hash())] {
client.setCurrentTx(nil)
return true
}
}
return client.reSendCommitTx(block.Type)
}
func (client *commitMsgClient) reSendCommitTx(addType int64) bool {
//当前addType是回滚,则不计数,如果有累计则撤销上次累计次数,重新计数
if addType != types.AddBlock {
if client.checkTxCommitTimes > 0 {
client.checkTxCommitTimes--
}
return false
}
client.checkTxCommitTimes++
if client.checkTxCommitTimes < client.waitMainBlocks {
return false
}
return client.verifyTx(curTx, txMap)
client.checkTxCommitTimes = 0
client.resetSendEnv()
return true
}
//如果共识高度一直没有追上发送高度,且当前发送高度已经上链,说明共识一直没达成,安全起见,超过停止次数后,重发
......@@ -275,7 +284,7 @@ func (client *commitMsgClient) checkAuthAccountIn() {
if err != nil {
return
}
authExist := strings.Contains(nodes, client.paraClient.authAccount)
authExist := strings.Contains(nodes, client.authAccount)
//如果授权节点重新加入,需要从当前共识高度重新发送
if !client.authAccountIn && authExist {
......@@ -361,7 +370,7 @@ func (client *commitMsgClient) getSendingTx(startHeight, endHeight int64) (*type
for i, msg := range sendingMsgs {
plog.Debug("paracommitmsg sending", "idx", i, "height", msg.Height, "mainheight", msg.MainBlockHeight,
"blockhash", common.HashHex(msg.BlockHash), "mainHash", common.HashHex(msg.MainBlockHash),
"from", client.paraClient.authAccount)
"from", client.authAccount)
}
return signTx, count
......@@ -678,7 +687,7 @@ out:
isSync = true
}
if client.paraClient.authAccount != "" {
if client.authAccount != "" {
client.GetProperFeeRate()
}
......@@ -836,7 +845,7 @@ func (client *commitMsgClient) getNodeGroupAddrs() (string, error) {
}
func (client *commitMsgClient) onWalletStatus(status *types.WalletStatus) {
if status == nil || client.paraClient.authAccount == "" {
if status == nil || client.authAccount == "" {
return
}
if !status.IsWalletLock && client.privateKey == nil {
......@@ -858,7 +867,7 @@ func (client *commitMsgClient) onWalletStatus(status *types.WalletStatus) {
}
func (client *commitMsgClient) onWalletAccount(acc *types.Account) {
if acc == nil || client.paraClient.authAccount == "" || client.paraClient.authAccount != acc.Addr || client.privateKey != nil {
if acc == nil || client.authAccount == "" || client.authAccount != acc.Addr || client.privateKey != nil {
return
}
err := client.fetchPriKey()
......@@ -872,7 +881,7 @@ func (client *commitMsgClient) onWalletAccount(acc *types.Account) {
}
func (client *commitMsgClient) fetchPriKey() error {
req := &types.ReqString{Data: client.paraClient.authAccount}
req := &types.ReqString{Data: client.authAccount}
msg := client.paraClient.GetQueueClient().NewMessage("wallet", types.EventDumpPrivkey, req)
err := client.paraClient.GetQueueClient().Send(msg, true)
......
......@@ -21,23 +21,11 @@ import (
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
)
func (client *client) addLocalBlock(height int64, block *pt.ParaLocalDbBlock) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleHeightKey(cfg.GetTitle(), height)
kv := &types.KeyValue{Key: key, Value: types.Encode(block)}
set.KV = append(set.KV, kv)
//两个key原子操作
key = calcTitleLastHeightKey(cfg.GetTitle())
kv = &types.KeyValue{Key: key, Value: types.Encode(&types.Int64{Data: height})}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
func (client *client) createLocalGenesisBlock(genesis *types.Block) error {
return client.alignLocalBlock2ChainBlock(genesis)
}
func (client *client) createLocalBlock(lastBlock *pt.ParaLocalDbBlock, txs []*types.Transaction, mainBlock *types.ParaTxDetail) error {
func getNewBlock(lastBlock *pt.ParaLocalDbBlock, txs []*types.Transaction, mainBlock *types.ParaTxDetail) *pt.ParaLocalDbBlock {
var newblock pt.ParaLocalDbBlock
newblock.Height = lastBlock.Height + 1
......@@ -45,88 +33,17 @@ func (client *client) createLocalBlock(lastBlock *pt.ParaLocalDbBlock, txs []*ty
newblock.MainHeight = mainBlock.Header.Height
newblock.ParentMainHash = lastBlock.MainHash
newblock.BlockTime = mainBlock.Header.BlockTime
newblock.Txs = txs
err := client.addLocalBlock(newblock.Height, &newblock)
if err != nil {
return err
}
return err
}
func (client *client) createLocalGenesisBlock(genesis *types.Block) error {
return client.alignLocalBlock2ChainBlock(genesis)
}
func (client *client) delLocalBlock(height int64) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleHeightKey(cfg.GetTitle(), height)
kv := &types.KeyValue{Key: key, Value: nil}
set.KV = append(set.KV, kv)
//两个key原子操作
key = calcTitleLastHeightKey(cfg.GetTitle())
kv = &types.KeyValue{Key: key, Value: types.Encode(&types.Int64{Data: height - 1})}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
}
// localblock 设置到当前高度,当前高度后面block会被新的区块覆盖
func (client *client) removeLocalBlocks(curHeight int64) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleLastHeightKey(cfg.GetTitle())
kv := &types.KeyValue{Key: key, Value: types.Encode(&types.Int64{Data: curHeight})}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
return &newblock
}
func (client *client) getLastLocalHeight() (int64, error) {
cfg := client.GetAPI().GetConfig()
key := calcTitleLastHeightKey(cfg.GetTitle())
set := &types.LocalDBGet{Keys: [][]byte{key}}
value, err := client.getLocalDb(set, len(set.Keys))
if err != nil {
return -1, err
}
if len(value) == 0 || value[0] == nil {
return -1, types.ErrNotFound
}
height := &types.Int64{}
err = types.Decode(value[0], height)
if err != nil {
return -1, err
}
return height.Data, nil
}
func (client *client) getLocalBlockByHeight(height int64) (*pt.ParaLocalDbBlock, error) {
cfg := client.GetAPI().GetConfig()
key := calcTitleHeightKey(cfg.GetTitle(), height)
set := &types.LocalDBGet{Keys: [][]byte{key}}
value, err := client.getLocalDb(set, len(set.Keys))
if err != nil {
return nil, err
}
if len(value) == 0 || value[0] == nil {
return nil, types.ErrNotFound
}
var block pt.ParaLocalDbBlock
err = types.Decode(value[0], &block)
func (client *client) createLocalBlock(lastBlock *pt.ParaLocalDbBlock, txs []*types.Transaction, mainBlock *types.ParaTxDetail) error {
err := client.addLocalBlock(getNewBlock(lastBlock, txs, mainBlock))
if err != nil {
return nil, err
return err
}
return &block, nil
return err
}
func (client *client) getLocalBlockSeq(height int64) (int64, []byte, error) {
......@@ -153,11 +70,12 @@ func (client *client) alignLocalBlock2ChainBlock(chainBlock *types.Block) error
BlockTime: chainBlock.BlockTime,
}
return client.addLocalBlock(localBlock.Height, localBlock)
return client.addLocalBlock(localBlock)
}
//如果localdb里面没有信息,就从chain block返回,至少有创世区块,然后进入循环匹配切换场景
//如果localBlock被删除了,就从chain block获取,如果block能获取到,但远程seq获取不到,则返回当前块主链hash和错误的seq=0,
//然后请求交易校验不过会进入循环匹配切换场景
func (client *client) getLastLocalBlockSeq() (int64, []byte, error) {
height, err := client.getLastLocalHeight()
if err == nil {
......@@ -323,14 +241,14 @@ func (client *client) getBatchSeqCount(currSeq int64) (int64, error) {
} else {
atomic.StoreInt32(&client.caughtUp, 1)
}
if !client.subCfg.FetchFilterParaTxsClose && lastSeq-currSeq > client.subCfg.BatchFetchBlockCount {
return client.subCfg.BatchFetchBlockCount - 1, nil
if lastSeq-currSeq > client.subCfg.BatchFetchBlockCount {
return client.subCfg.BatchFetchBlockCount, nil
}
return 0, nil
return 1, nil
}
if lastSeq == currSeq {
return 0, nil
return 1, nil
}
// lastSeq = currSeq -1
......@@ -423,7 +341,7 @@ func (client *client) requestTxsFromBlock(currSeq int64, preMainBlockHash []byte
func (client *client) requestFilterParaTxs(currSeq int64, count int64, preMainBlockHash []byte) (*types.ParaTxDetails, error) {
cfg := client.GetAPI().GetConfig()
req := &types.ReqParaTxByTitle{IsSeq: true, Start: currSeq, End: currSeq + count, Title: cfg.GetTitle()}
req := &types.ReqParaTxByTitle{IsSeq: true, Start: currSeq, End: currSeq + count - 1, Title: cfg.GetTitle()}
details, err := client.GetParaTxByTitle(req)
if err != nil {
return nil, err
......@@ -432,18 +350,20 @@ func (client *client) requestFilterParaTxs(currSeq int64, count int64, preMainBl
details = validMainBlocks(details)
err = verifyMainBlocks(preMainBlockHash, details)
if err != nil {
plog.Error("requestTxsOnlyPara", "curSeq", currSeq, "count", count, "preMainBlockHash", hex.EncodeToString(preMainBlockHash))
plog.Error("requestFilterParaTxs", "curSeq", currSeq, "count", count, "preMainBlockHash", hex.EncodeToString(preMainBlockHash))
return nil, err
}
//至少应该返回1个
if len(details.Items) == 0 {
plog.Error("requestFilterParaTxs ret nil", "curSeq", currSeq, "count", count, "preMainBlockHash", hex.EncodeToString(preMainBlockHash))
return nil, types.ErrNotFound
}
return details, nil
}
func (client *client) RequestTx(currSeq int64, count int64, preMainBlockHash []byte) (*types.ParaTxDetails, error) {
if !client.subCfg.FetchFilterParaTxsClose {
return client.requestFilterParaTxs(currSeq, count, preMainBlockHash)
}
return client.requestTxsFromBlock(currSeq, preMainBlockHash)
}
func (client *client) processHashNotMatchError(currSeq int64, lastSeqMainHash []byte, err error) (int64, []byte, error) {
......@@ -500,7 +420,6 @@ func (client *client) procLocalBlock(mainBlock *types.ParaTxDetail) (bool, error
plog.Info("Create empty block", "newHeight", lastBlock.Height+1)
}
return true, client.createLocalBlock(lastBlock, txs, mainBlock)
}
func (client *client) procLocalBlocks(mainBlocks *types.ParaTxDetails) error {
......@@ -521,10 +440,70 @@ func (client *client) procLocalBlocks(mainBlocks *types.ParaTxDetails) error {
return nil
}
func (client *client) procLocalAddBlock(mainBlock *types.ParaTxDetail, lastBlock *pt.ParaLocalDbBlock) *pt.ParaLocalDbBlock {
cfg := client.GetAPI().GetConfig()
curMainHeight := mainBlock.Header.Height
emptyInterval := client.getEmptyInterval(lastBlock)
txs := paraexec.FilterTxsForPara(cfg, mainBlock)
plog.Debug("Parachain process block", "lastBlockHeight", lastBlock.Height, "lastBlockMainHeight", lastBlock.MainHeight,
"lastBlockMainHash", common.ToHex(lastBlock.MainHash), "currMainHeight", curMainHeight,
"curMainHash", common.ToHex(mainBlock.Header.Hash), "emptyIntval", emptyInterval, "seqTy", mainBlock.Type)
if mainBlock.Type != types.AddBlock {
panic("para chain quick sync,not addBlock type")
}
//AddAct
if len(txs) == 0 {
if curMainHeight-lastBlock.MainHeight < emptyInterval {
return nil
}
plog.Debug("Create empty block", "newHeight", lastBlock.Height+1)
}
return getNewBlock(lastBlock, txs, mainBlock)
}
//只同步只有AddType的block,比如在当前高度1w高度前的主链blocks,默认没有分叉,只获取addType类型的,如果有分叉,也会在后面常规同步时候纠正过来
func (client *client) procLocalAddBlocks(mainBlocks *types.ParaTxDetails) error {
var blocks []*pt.ParaLocalDbBlock
lastBlock, err := client.getLastLocalBlock()
if err != nil {
plog.Error("procLocalAddBlocks getLastLocalBlock", "err", err)
return err
}
for _, main := range mainBlocks.Items {
b := client.procLocalAddBlock(main, lastBlock)
if b == nil {
continue
}
lastBlock = b
blocks = append(blocks, b)
}
err = client.saveBatchLocalBlocks(blocks)
if err != nil {
plog.Error("procLocalAddBlocks saveBatchLocalBlocks", "err", err)
panic(err)
}
plog.Info("procLocalAddBlocks.saveLocalBlocks", "start", blocks[0].Height, "end", blocks[len(blocks)-1].Height)
client.blockSyncClient.handleLocalChangedMsg()
return nil
}
func (client *client) CreateBlock() {
defer client.wg.Done()
if client.subCfg.JumpDownloadOpen {
client.jumpDldCli.tryJumpDownload()
}
if client.subCfg.MultiDownloadOpen {
client.multiDldCli.tryMultiServerDownload()
}
lastSeq, lastSeqMainHash, err := client.getLastLocalBlockSeq()
if err != nil {
......@@ -560,9 +539,9 @@ out:
plog.Debug("para CreateBlock count not match", "count", count, "items", len(paraTxs.Items))
count = int64(len(paraTxs.Items))
}
//如果超过1个block,则认为当前正在追赶,暂不处理
if client.authAccount != "" && len(paraTxs.Items) == 1 {
client.commitMsgClient.commitTxCheckNotify(paraTxs.Items[0].TxDetails)
//如果当前正在追赶,暂不处理
if client.commitMsgClient.authAccount != "" && client.isCaughtUp() && len(paraTxs.Items) > 0 {
client.commitMsgClient.commitTxCheckNotify(paraTxs.Items[0])
}
err = client.procLocalBlocks(paraTxs)
......
// 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 para
import (
"errors"
"github.com/33cn/chain33/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
)
func (client *client) setLocalDb(set *types.LocalDBSet) error {
//如果追赶上主链了,则落盘
if client.isCaughtUp() {
set.Txid = 1
client.blockSyncClient.handleLocalCaughtUpMsg()
}
msg := client.GetQueueClient().NewMessage("blockchain", types.EventSetValueByKey, set)
err := client.GetQueueClient().Send(msg, true)
if err != nil {
return err
}
resp, err := client.GetQueueClient().Wait(msg)
if err != nil {
return err
}
if resp.GetData().(*types.Reply).IsOk {
return nil
}
return errors.New(string(resp.GetData().(*types.Reply).GetMsg()))
}
func (client *client) getLocalDb(set *types.LocalDBGet, count int) ([][]byte, error) {
msg := client.GetQueueClient().NewMessage("blockchain", types.EventGetValueByKey, set)
err := client.GetQueueClient().Send(msg, true)
if err != nil {
return nil, err
}
resp, err := client.GetQueueClient().Wait(msg)
if err != nil {
return nil, err
}
reply := resp.GetData().(*types.LocalReplyValue)
if len(reply.Values) != count {
plog.Error("Parachain getLocalDb count not match", "expert", count, "real", len(reply.Values))
return nil, types.ErrInvalidParam
}
return reply.Values, nil
}
func (client *client) addLocalBlock(block *pt.ParaLocalDbBlock) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleHeightKey(cfg.GetTitle(), block.Height)
kv := &types.KeyValue{Key: key, Value: types.Encode(block)}
set.KV = append(set.KV, kv)
//两个key原子操作
key = calcTitleLastHeightKey(cfg.GetTitle())
kv = &types.KeyValue{Key: key, Value: types.Encode(&types.Int64{Data: block.Height})}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
}
func (client *client) saveBatchLocalBlocks(blocks []*pt.ParaLocalDbBlock) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
for _, block := range blocks {
key := calcTitleHeightKey(cfg.GetTitle(), block.Height)
kv := &types.KeyValue{Key: key, Value: types.Encode(block)}
set.KV = append(set.KV, kv)
}
//save lastHeight,两个key原子操作
key := calcTitleLastHeightKey(cfg.GetTitle())
kv := &types.KeyValue{Key: key, Value: types.Encode(&types.Int64{Data: blocks[len(blocks)-1].Height})}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
}
func (client *client) delLocalBlock(height int64) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleHeightKey(cfg.GetTitle(), height)
kv := &types.KeyValue{Key: key, Value: nil}
set.KV = append(set.KV, kv)
//两个key原子操作
key = calcTitleLastHeightKey(cfg.GetTitle())
kv = &types.KeyValue{Key: key, Value: types.Encode(&types.Int64{Data: height - 1})}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
}
// localblock 设置到当前高度,当前高度后面block会被新的区块覆盖
func (client *client) removeLocalBlocks(curHeight int64) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleLastHeightKey(cfg.GetTitle())
kv := &types.KeyValue{Key: key, Value: types.Encode(&types.Int64{Data: curHeight})}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
}
func (client *client) getLastLocalHeight() (int64, error) {
cfg := client.GetAPI().GetConfig()
key := calcTitleLastHeightKey(cfg.GetTitle())
set := &types.LocalDBGet{Keys: [][]byte{key}}
value, err := client.getLocalDb(set, len(set.Keys))
if err != nil {
return -1, err
}
if len(value) == 0 || value[0] == nil {
return -1, types.ErrNotFound
}
height := &types.Int64{}
err = types.Decode(value[0], height)
if err != nil {
return -1, err
}
return height.Data, nil
}
func (client *client) getLocalBlockByHeight(height int64) (*pt.ParaLocalDbBlock, error) {
cfg := client.GetAPI().GetConfig()
key := calcTitleHeightKey(cfg.GetTitle(), height)
set := &types.LocalDBGet{Keys: [][]byte{key}}
value, err := client.getLocalDb(set, len(set.Keys))
if err != nil {
return nil, err
}
if len(value) == 0 || value[0] == nil {
return nil, types.ErrNotFound
}
var block pt.ParaLocalDbBlock
err = types.Decode(value[0], &block)
if err != nil {
return nil, err
}
return &block, nil
}
func (client *client) saveMainBlock(height int64, block *types.ParaTxDetail) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleMainHeightKey(cfg.GetTitle(), height)
kv := &types.KeyValue{Key: key, Value: types.Encode(block)}
set.KV = append(set.KV, kv)
return client.setLocalDb(set)
}
func (client *client) saveBatchMainBlocks(txs *types.ParaTxDetails) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
for _, block := range txs.Items {
key := calcTitleMainHeightKey(cfg.GetTitle(), block.Header.Height)
kv := &types.KeyValue{Key: key, Value: types.Encode(block)}
set.KV = append(set.KV, kv)
}
return client.setLocalDb(set)
}
func (client *client) rmvBatchMainBlocks(start, end int64) error {
cfg := client.GetAPI().GetConfig()
set := &types.LocalDBSet{}
for i := start; i < end; i++ {
key := calcTitleMainHeightKey(cfg.GetTitle(), i)
kv := &types.KeyValue{Key: key, Value: nil}
set.KV = append(set.KV, kv)
}
return client.setLocalDb(set)
}
func (client *client) getMainBlockFromDb(height int64) (*types.ParaTxDetail, error) {
cfg := client.GetAPI().GetConfig()
key := calcTitleMainHeightKey(cfg.GetTitle(), height)
set := &types.LocalDBGet{Keys: [][]byte{key}}
value, err := client.getLocalDb(set, len(set.Keys))
if err != nil {
return nil, err
}
if len(value) == 0 || value[0] == nil {
return nil, types.ErrNotFound
}
var tx types.ParaTxDetail
err = types.Decode(value[0], &tx)
if err != nil {
return nil, err
}
return &tx, nil
}
// 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 para
import (
"bytes"
"sync"
"sync/atomic"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/merkle"
"github.com/33cn/chain33/types"
"github.com/pkg/errors"
)
type paraTxBlocksJob struct {
start int64
end int64
paraTxBlocks map[int64]*types.ParaTxDetail //有平行链交易的blocks
headers *types.ParaTxDetails
}
type jumpDldClient struct {
paraClient *client
downFail int32
wg sync.WaitGroup
}
//校验按高度获取的block hash和前一步对应高度的blockhash比对
func verifyBlockHash(heights []*types.BlockInfo, blocks []*types.ParaTxDetail) error {
heightMap := make(map[int64][]byte)
for _, h := range heights {
heightMap[h.Height] = h.Hash
}
for _, b := range blocks {
if !bytes.Equal(heightMap[b.Header.Height], b.Header.Hash) {
plog.Error("jumpDld.verifyBlockHash", "height", b.Header.Height,
"heightsHash", common.ToHex(heightMap[b.Header.Height]), "tx", b.Header.Hash)
return types.ErrBlockHashNoMatch
}
}
return nil
}
func (j *jumpDldClient) getParaHeightList(startHeight, endHeight int64) ([]*types.BlockInfo, error) {
var heightList []*types.BlockInfo
title := j.paraClient.GetAPI().GetConfig().GetTitle()
lastHeight := int64(-1)
for {
req := &types.ReqHeightByTitle{Height: lastHeight, Count: int32(types.MaxBlockCountPerTime), Direction: 1, Title: title}
heights, err := j.paraClient.GetParaHeightsByTitle(req)
if err != nil && err != types.ErrNotFound {
plog.Error("jumpDld.getParaHeightList", "start", lastHeight, "count", req.Count, "title", title, "err", err)
return heightList, err
}
if err == types.ErrNotFound || heights == nil || len(heights.Items) <= 0 {
return heightList, nil
}
//分页查找,只获取范围内的高度
for _, h := range heights.Items {
if h.Height >= startHeight && h.Height <= endHeight {
heightList = append(heightList, h)
}
}
lastHeight = heights.Items[len(heights.Items)-1].Height
if lastHeight >= endHeight {
return heightList, nil
}
if atomic.LoadInt32(&j.downFail) != 0 || j.paraClient.isCancel() {
return nil, errors.New("verify fail or main thread cancel")
}
}
}
//把不连续的平行链区块高度按offset分成二维数组,方便后面处理
func splitHeights2Rows(heights []*types.BlockInfo, offset int) [][]*types.BlockInfo {
var ret [][]*types.BlockInfo
for i := 0; i < len(heights); i += offset {
end := i + offset
if end > len(heights) {
end = len(heights)
}
ret = append(ret, heights[i:end])
}
return ret
}
//按高度每次获取实际1000个有平行链交易的区块,这些区块并不一定连续,为了连续处理有交易和没有交易的区块,需要特殊设置起始结束高度,
//但每次处理的起始高度和结束高度都包含了有交易的1000个平行链高度
func getHeaderStartEndRange(startHeight, endHeight int64, arr [][]*types.BlockInfo, i int) (int64, int64) {
single := arr[i]
s := startHeight
e := single[len(single)-1].Height
if i > 0 {
s = arr[i-1][len(arr[i-1])-1].Height + 1
}
if i == len(arr)-1 {
e = endHeight
}
return s, e
}
func (j *jumpDldClient) verifyTxMerkleRoot(tx *types.ParaTxDetail, headMap map[int64]*types.ParaTxDetail) error {
var verifyTxs []*types.Transaction
for _, t := range tx.TxDetails {
verifyTxs = append(verifyTxs, t.Tx)
}
verifyTxRoot := merkle.CalcMerkleRoot(j.paraClient.GetAPI().GetConfig(), tx.Header.Height, verifyTxs)
if !bytes.Equal(verifyTxRoot, tx.ChildHash) {
plog.Error("jumpDldClient.verifyTxMerkelHash", "height", tx.Header.Height,
"calcHash", common.ToHex(verifyTxRoot), "rcvHash", common.ToHex(tx.ChildHash))
return types.ErrCheckTxHash
}
txRootHash := merkle.GetMerkleRootFromBranch(tx.Proofs, tx.ChildHash, tx.Index)
if !bytes.Equal(txRootHash, headMap[tx.Header.Height].Header.TxHash) {
plog.Error("jumpDldClient.verifyRootHash", "height", tx.Header.Height,
"txHash", common.ToHex(txRootHash), "headerHash", common.ToHex(headMap[tx.Header.Height].Header.TxHash))
return types.ErrCheckTxHash
}
return nil
}
func (j *jumpDldClient) process(job *paraTxBlocksJob) {
if atomic.LoadInt32(&j.downFail) != 0 || j.paraClient.isCancel() {
return
}
headMap := make(map[int64]*types.ParaTxDetail)
for _, h := range job.headers.Items {
headMap[h.Header.Height] = h
}
//收集header头尾区间有没有paraTxBlocks
txBlocks := &types.ParaTxDetails{}
for i := job.start; i <= job.end; i++ {
if job.paraTxBlocks[i] != nil {
txBlocks.Items = append(txBlocks.Items, job.paraTxBlocks[i])
}
}
if len(txBlocks.Items) > 0 {
for _, tx := range txBlocks.Items {
// 1. 校验平行链交易的区块头hash 和之前读取的主链头对应高度的块hash
if !bytes.Equal(tx.Header.Hash, headMap[tx.Header.Height].Header.Hash) {
plog.Error("jumpDldClient.process verifyhash", "height", tx.Header.Height,
"txHash", common.ToHex(tx.Header.Hash), "headerHash", common.ToHex(headMap[tx.Header.Height].Header.Hash))
atomic.StoreInt32(&j.downFail, 1)
return
}
// 2. 校验交易merkle根和之前读的主链头的交易rootHash
if tx.Header.Height >= j.paraClient.subCfg.MainVrfMerkleRootForkHeight {
err := j.verifyTxMerkleRoot(tx, headMap)
if err != nil {
atomic.StoreInt32(&j.downFail, 1)
return
}
}
// verify ok, attach tx block to header
headMap[tx.Header.Height].TxDetails = tx.TxDetails
}
}
err := j.paraClient.procLocalAddBlocks(job.headers)
if err != nil {
atomic.StoreInt32(&j.downFail, 1)
plog.Error("jumpDldClient.process procLocalAddBlocks", "start", job.start, "end", job.end, "err", err)
}
}
func (j *jumpDldClient) processTxJobs(ch chan *paraTxBlocksJob) {
defer j.wg.Done()
for job := range ch {
j.process(job)
}
}
//按高度list请求平行链区块,服务器有可能返回少于请求高度,少于时候需要继续请求
func (j *jumpDldClient) fetchHeightListBlocks(hlist []int64, title string) (*types.ParaTxDetails, error) {
index := 0
retBlocks := &types.ParaTxDetails{}
for {
list := hlist[index:]
req := &types.ReqParaTxByHeight{Items: list, Title: title}
blocks, err := j.paraClient.GetParaTxByHeight(req)
if err != nil {
plog.Error("jumpDld.getParaTxs fetchHeightListBlocks", "start", list[0], "end", list[len(list)-1], "title", title)
return nil, err
}
retBlocks.Items = append(retBlocks.Items, blocks.Items...)
index += len(blocks.Items)
if index == len(hlist) {
return retBlocks, nil
}
//从逻辑上应该不会有大于场景出现
if index > len(hlist) {
plog.Error("jumpDld.getParaTxs fetchHeightListBlocks len", "index", index, "len", len(hlist), "start", list[0], "end", list[len(list)-1], "title", title)
return nil, err
}
}
}
func (j *jumpDldClient) getParaTxsBlocks(blocksList []*types.BlockInfo, title string) (map[int64]*types.ParaTxDetail, error) {
var hlist []int64
for _, h := range blocksList {
hlist = append(hlist, h.Height)
}
blocks, err := j.fetchHeightListBlocks(hlist, title)
if err != nil {
plog.Error("jumpDld.getParaTxsBlocks", "start", hlist[0], "end", hlist[len(hlist)-1], "title", title)
return nil, err
}
err = verifyBlockHash(blocksList, blocks.Items)
if err != nil {
plog.Error("jumpDld.getParaTxsBlocks verifyTx", "start", hlist[0], "end", hlist[len(hlist)-1], "title", title)
return nil, err
}
blocksMap := make(map[int64]*types.ParaTxDetail)
for _, b := range blocks.Items {
blocksMap[b.Header.Height] = b
}
return blocksMap, nil
}
func (j *jumpDldClient) getHeaders(start, end int64) (*types.ParaTxDetails, error) {
blocks := &types.ReqBlocks{Start: start, End: end}
headers, err := j.paraClient.GetBlockHeaders(blocks)
if err != nil {
plog.Error("jumpDld.getHeaders", "start", start, "end", end, "error", err)
return nil, err
}
plog.Debug("jumpDld.getHeaders", "start", start, "end", end)
paraTxHeaders := &types.ParaTxDetails{}
for _, header := range headers.Items {
paraTxHeaders.Items = append(paraTxHeaders.Items, &types.ParaTxDetail{Type: types.AddBlock, Header: header})
}
return paraTxHeaders, nil
}
func (j *jumpDldClient) procParaTxHeaders(startHeight, endHeight int64, paraBlocks map[int64]*types.ParaTxDetail, jobCh chan *paraTxBlocksJob) error {
for s := startHeight; s <= endHeight; s += types.MaxBlockCountPerTime {
end := s + types.MaxBlockCountPerTime - 1
if end > endHeight {
end = endHeight
}
headers, err := j.getHeaders(s, end)
if err != nil {
plog.Error("jumpDld.procParaTxHeaders", "start", startHeight, "end", endHeight, "err", err)
return err
}
//每1000个header同步一次,这样可以更快更小粒度的使同步层获取区块执行
job := &paraTxBlocksJob{start: s, end: end, paraTxBlocks: paraBlocks, headers: headers}
jobCh <- job
if atomic.LoadInt32(&j.downFail) != 0 || j.paraClient.isCancel() {
return errors.New("verify fail or main thread cancel")
}
}
return nil
}
//每1000header执行一次比全部获取出来更有效率,可以和同步层更好并行处理,节约时间,1000paraTxBlocks花时间很少,相比headers获取,串行获取时间可以忽略
func (j *jumpDldClient) getParaTxs(startHeight, endHeight int64, heights []*types.BlockInfo, jobCh chan *paraTxBlocksJob) error {
title := j.paraClient.GetAPI().GetConfig().GetTitle()
heightsRows := splitHeights2Rows(heights, int(types.MaxBlockCountPerTime))
for i, row := range heightsRows {
//获取每一排1000个paraTxBlocks
paraBlocks, err := j.getParaTxsBlocks(row, title)
if err != nil {
return err
}
//根据1000个paraTxBlocks的头尾高度获取header的头尾高度,header的高度要包含paraTxBlocks高度
headerStart, headerEnd := getHeaderStartEndRange(startHeight, endHeight, heightsRows, i)
plog.Debug("jumpDld.getParaTxs", "headerStart", headerStart, "headerEnd", headerEnd, "i", i)
err = j.procParaTxHeaders(headerStart, headerEnd, paraBlocks, jobCh)
if err != nil {
return err
}
if atomic.LoadInt32(&j.downFail) != 0 || j.paraClient.isCancel() {
return errors.New("verify fail or main thread cancel")
}
}
return nil
}
//Jump Download 是选择有平行链交易的区块跳跃下载的功能,分为三个步骤:
//0. 只获取当前主链高度1w高度前的区块,默认没有分叉,都是addType block
//1. 获取所有平行链交易的高度列表,大概5s以内
//2. 按高度列表获取含平行链交易的主链区块每次获取一段1000高度,并获取相关范围的主链headers,一起执行,单独获取headers和同步处理不能并行
func (j *jumpDldClient) tryJumpDownload() {
curMainHeight, err := j.paraClient.GetLastHeightOnMainChain()
if err != nil {
plog.Error("tryJumpDownload getMain height", "err", err.Error())
return
}
//如果切换不成功,则不进行多服务下载
_, localBlock, err := j.paraClient.switchLocalHashMatchedBlock()
if err != nil {
plog.Error("tryJumpDownload switch local height", "err", err.Error())
return
}
startHeight := localBlock.MainHeight + 1
endHeight := curMainHeight - maxRollbackHeight
if !(endHeight > startHeight && endHeight-startHeight > maxRollbackHeight) {
plog.Info("tryJumpDownload.quit", "start", startHeight, "end", endHeight)
return
}
plog.Info("tryJumpDownload", "start", startHeight, "end", endHeight)
//1. 获取有平行链交易的块高度列表
t1 := types.Now()
heights, err := j.getParaHeightList(startHeight, endHeight)
if err != nil {
plog.Error("JumpDld.getParaHeightList", "err", err)
}
if len(heights) == 0 {
plog.Error("JumpDld.getParaHeightList no height found")
return
}
plog.Info("tryJumpDownload.getParaHeightList", "time", types.Since(t1))
//2. 按有平行链交易的高度列表获取平行链块
jobsCh := make(chan *paraTxBlocksJob, defaultJobBufferNum)
j.wg.Add(1)
go j.processTxJobs(jobsCh)
t1 = types.Now()
err = j.getParaTxs(startHeight, endHeight, heights, jobsCh)
if err != nil {
//需要close processTxJobs 后再返回
plog.Error("tryJumpDownload.getParaTxs", "err", err)
}
close(jobsCh)
j.wg.Wait()
plog.Info("tryJumpDownload.getParaTxs done", "time", types.Since(t1))
}
# 平行链有选择的下载包含平行链交易的主链区块方案
## 说明
1. 新平行链节点从头开始同步主链区块需要两个信息,一个是所有主链区块头部信息,一个是含有平行链交易的主链区块
1. 获取所有主链区块头部一是为了产生空块,另一个是为了校验,平行链交易的区块对交易做merkel root计算需要和header tx root一致
## 分段下载方案实现
1. 本地区块和主链区块同步对齐确定下载开始高度,然后根据主链当前高度减1w高度确定下载结束高度,结束高度之前认为不存在回滚问题
1. 下载所有包含平行链交易的主链区块高度列表,用时3s
1. 把高度列表按1000高度分为多个段,每次获取一段含平行链交易的主链区块,同时根据这一段的头尾高度确定主链头的区间,然后区间内每次获取1000个区块头
  然后结合之前下载的1000个平行链交易的区块产生准区块,同步层可以立即同步执行
1. 比如1~2w高度,含平行链交易的块为 100,105,...1500, 1610...2700, ...15300,17200...19100, 第一个段就是100~1500,获取区块头区间为1~1500,
下一个区块头区间为1501~2700,最后一个区块头区间为15301~20000
##几种方案比较:
1. 每次请求1000个区块,依次下载,不区分是否有平行链交易区块,这种场景服务端读取数据库需要读头部或平行链交易的区块body,缓存没有很好利用
在当前测试环境下实际测试500w个主链区块用时33分钟
1. 多主链服务节点下载,在主链节点ip确定的情况下可以很大的提高下载速度,但是由于当前是云节点代理的方式,测试结果没有理论效果明显
1. 先下载所有主链头,在下载含平行链交易区块,由于串行化,用时40多分钟
1. 先下载平行链交易,再依次下载相关主链头区间,并行执行,可以提高到30分钟,由于有可能主链头区间有几十万,同步执行会等待,可以继续优化
1. 先分段下载平行链交易,再分段下载相关的主链头区间,每次1000区块,可以缩小同步层的等待时间,整体下载过程时间基本就是下载主链头部的时间
1. 下载所有平行链交易用时大概1分多钟,相比所有头部时间很小
1. 测试用时21分钟
1. 本方案也采用的最后一种方案
\ No newline at end of file
// 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 para
import (
"testing"
"github.com/33cn/chain33/types"
typesmocks "github.com/33cn/chain33/types/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestGetHeightsArry(t *testing.T) {
h0 := &types.BlockInfo{Height: 1}
h1 := &types.BlockInfo{Height: 3}
h2 := &types.BlockInfo{Height: 5}
h3 := &types.BlockInfo{Height: 6}
h4 := &types.BlockInfo{Height: 9}
h5 := &types.BlockInfo{Height: 15}
h6 := &types.BlockInfo{Height: 21}
h7 := &types.BlockInfo{Height: 25}
h8 := &types.BlockInfo{Height: 31}
h9 := &types.BlockInfo{Height: 41}
heights := []*types.BlockInfo{h0, h1, h2, h3, h4, h5, h6, h7, h8, h9}
hh := splitHeights2Rows(heights, 3)
h11 := []*types.BlockInfo{h0, h1, h2}
h12 := []*types.BlockInfo{h3, h4, h5}
h13 := []*types.BlockInfo{h6, h7, h8}
h14 := []*types.BlockInfo{h9}
expect := [][]*types.BlockInfo{h11, h12, h13, h14}
assert.Equal(t, expect, hh)
s, e := getHeaderStartEndRange(0, 100, hh, 0)
assert.Equal(t, int64(0), s)
assert.Equal(t, h2.Height, e)
s, e = getHeaderStartEndRange(0, 100, hh, 1)
assert.Equal(t, h2.Height+1, s)
assert.Equal(t, h5.Height, e)
s, e = getHeaderStartEndRange(0, 100, hh, 2)
assert.Equal(t, h5.Height+1, s)
assert.Equal(t, h8.Height, e)
s, e = getHeaderStartEndRange(0, 100, hh, 3)
assert.Equal(t, h8.Height+1, s)
assert.Equal(t, int64(100), e)
}
func TestFetchHeightListBlocks(t *testing.T) {
para := &client{}
grpcClient := &typesmocks.Chain33Client{}
para.grpcClient = grpcClient
jump := &jumpDldClient{paraClient: para}
b1 := &types.ParaTxDetail{Header: &types.Header{Height: 1}}
b2 := &types.ParaTxDetail{Header: &types.Header{Height: 2}}
b3 := &types.ParaTxDetail{Header: &types.Header{Height: 3}}
b4 := &types.ParaTxDetail{Header: &types.Header{Height: 4}}
b5 := &types.ParaTxDetail{Header: &types.Header{Height: 5}}
b6 := &types.ParaTxDetail{Header: &types.Header{Height: 6}}
b7 := &types.ParaTxDetail{Header: &types.Header{Height: 7}}
b8 := &types.ParaTxDetail{Header: &types.Header{Height: 8}}
b9 := &types.ParaTxDetail{Header: &types.Header{Height: 9}}
blocks1 := &types.ParaTxDetails{Items: []*types.ParaTxDetail{b1, b2, b3}}
blocks2 := &types.ParaTxDetails{Items: []*types.ParaTxDetail{b4, b5, b6, b7}}
blocks3 := &types.ParaTxDetails{Items: []*types.ParaTxDetail{b8, b9}}
grpcClient.On("GetParaTxByHeight", mock.Anything, mock.Anything).Return(blocks1, nil).Once()
grpcClient.On("GetParaTxByHeight", mock.Anything, mock.Anything).Return(blocks2, nil).Once()
grpcClient.On("GetParaTxByHeight", mock.Anything, mock.Anything).Return(blocks3, nil).Once()
allBlocks := &types.ParaTxDetails{}
allBlocks.Items = append(allBlocks.Items, blocks1.Items...)
allBlocks.Items = append(allBlocks.Items, blocks2.Items...)
allBlocks.Items = append(allBlocks.Items, blocks3.Items...)
hlist := []int64{1, 2, 3, 4, 5, 6, 7, 8, 9}
blocks, err := jump.fetchHeightListBlocks(hlist, "title")
assert.NoError(t, err)
assert.Equal(t, allBlocks.Items, blocks.Items)
}
......@@ -159,10 +159,6 @@ func (m *multiDldClient) getConns(inv *inventory) error {
//缺省不打开,因为有些节点下载时间不稳定,容易超时出错,后面看怎么优化
func (m *multiDldClient) tryMultiServerDownload() {
if !m.paraClient.subCfg.MultiDownloadOpen {
return
}
curMainHeight, err := m.paraClient.GetLastHeightOnMainChain()
if err != nil {
plog.Error("tryMultiServerDownload getMain height", "err", err.Error())
......@@ -224,7 +220,7 @@ func (m *multiDldClient) tryMultiServerDownload() {
func (i *inventory) getFirstBlock(d *downloadJob) *types.ParaTxDetail {
if i.isSaveDb {
block, err := d.getBlockFromDb(i.start)
block, err := d.mDldCli.paraClient.getMainBlockFromDb(i.start)
if err != nil {
panic(err)
}
......@@ -238,7 +234,7 @@ func (i *inventory) getLastBlock(d *downloadJob) *types.ParaTxDetail {
return nil
}
if i.isSaveDb {
block, err := d.getBlockFromDb(i.end)
block, err := d.mDldCli.paraClient.getMainBlockFromDb(i.end)
if err != nil {
panic(err)
}
......@@ -257,7 +253,7 @@ func (m *multiDldClient) processDoneJobs(ch chan *downloadJob) {
func (d *downloadJob) resetInv(i *inventory) {
if i.isSaveDb {
d.rmvBatchMainBlocks(i)
d.mDldCli.paraClient.rmvBatchMainBlocks(i.start, i.curHeight)
}
i.curHeight = i.start
i.txs.Items = nil
......@@ -268,7 +264,7 @@ func (d *downloadJob) process() {
for _, inv := range d.invs {
if inv.isSaveDb {
for i := inv.start; i <= inv.end; i++ {
block, err := d.getBlockFromDb(i)
block, err := d.mDldCli.paraClient.getMainBlockFromDb(i)
if err != nil {
panic(err)
}
......@@ -280,7 +276,7 @@ func (d *downloadJob) process() {
d.mDldCli.paraClient.blockSyncClient.handleLocalChangedMsg()
} else {
//block需要严格顺序执行,数据库错误,panic 重新来过
err := d.mDldCli.paraClient.procLocalBlocks(inv.txs)
err := d.mDldCli.paraClient.procLocalAddBlocks(inv.txs)
if err != nil {
panic(err)
}
......@@ -292,7 +288,7 @@ func (d *downloadJob) process() {
func (d *downloadJob) getPreVerifyBlock(inv *inventory) (*types.ParaTxDetail, error) {
if inv.isSaveDb {
lastBlock, err := d.getBlockFromDb(inv.curHeight - 1)
lastBlock, err := d.mDldCli.paraClient.getMainBlockFromDb(inv.curHeight - 1)
if err != nil {
return nil, err
}
......@@ -328,64 +324,6 @@ func (d *downloadJob) verifyDownloadBlock(inv *inventory, blocks *types.ParaTxDe
return nil
}
func (d *downloadJob) saveMainBlock(height int64, block *types.ParaTxDetail) error {
cfg := d.mDldCli.paraClient.GetAPI().GetConfig()
set := &types.LocalDBSet{}
key := calcTitleMainHeightKey(cfg.GetTitle(), height)
kv := &types.KeyValue{Key: key, Value: types.Encode(block)}
set.KV = append(set.KV, kv)
return d.mDldCli.paraClient.setLocalDb(set)
}
func (d *downloadJob) saveBatchMainBlocks(txs *types.ParaTxDetails) error {
cfg := d.mDldCli.paraClient.GetAPI().GetConfig()
set := &types.LocalDBSet{}
for _, block := range txs.Items {
key := calcTitleMainHeightKey(cfg.GetTitle(), block.Header.Height)
kv := &types.KeyValue{Key: key, Value: types.Encode(block)}
set.KV = append(set.KV, kv)
}
return d.mDldCli.paraClient.setLocalDb(set)
}
func (d *downloadJob) rmvBatchMainBlocks(inv *inventory) error {
cfg := d.mDldCli.paraClient.GetAPI().GetConfig()
set := &types.LocalDBSet{}
for i := inv.start; i < inv.curHeight; i++ {
key := calcTitleMainHeightKey(cfg.GetTitle(), i)
kv := &types.KeyValue{Key: key, Value: nil}
set.KV = append(set.KV, kv)
}
return d.mDldCli.paraClient.setLocalDb(set)
}
func (d *downloadJob) getBlockFromDb(height int64) (*types.ParaTxDetail, error) {
cfg := d.mDldCli.paraClient.GetAPI().GetConfig()
key := calcTitleMainHeightKey(cfg.GetTitle(), height)
set := &types.LocalDBGet{Keys: [][]byte{key}}
value, err := d.mDldCli.paraClient.getLocalDb(set, len(set.Keys))
if err != nil {
return nil, err
}
if len(value) == 0 || value[0] == nil {
return nil, types.ErrNotFound
}
var tx types.ParaTxDetail
err = types.Decode(value[0], &tx)
if err != nil {
return nil, err
}
return &tx, nil
}
func (d *downloadJob) checkInv(lastRetry, pre *types.ParaTxDetail, inv *inventory) error {
if !inv.isDone {
return types.ErrNotFound
......@@ -515,7 +453,7 @@ func (d *downloadJob) getInvBlocks(inv *inventory, connPool chan *connectCli) {
//save 之前save到db,后面区块全部save到db
if inv.isSaveDb {
d.saveBatchMainBlocks(txs)
d.mDldCli.paraClient.saveBatchMainBlocks(txs)
} else {
inv.txs.Items = append(inv.txs.Items, txs.Items...)
}
......@@ -528,7 +466,7 @@ func (d *downloadJob) getInvBlocks(inv *inventory, connPool chan *connectCli) {
return
}
if !inv.isSaveDb && types.Size(inv.txs) > maxBlockSize {
d.saveBatchMainBlocks(inv.txs)
d.mDldCli.paraClient.saveBatchMainBlocks(inv.txs)
inv.txs.Items = nil
inv.isSaveDb = true
}
......
......@@ -8,66 +8,40 @@ import (
"bytes"
"context"
"encoding/hex"
"errors"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
)
func (client *client) setLocalDb(set *types.LocalDBSet) error {
//如果追赶上主链了,则落盘
if client.isCaughtUp() {
set.Txid = 1
client.blockSyncClient.handleLocalCaughtUpMsg()
}
msg := client.GetQueueClient().NewMessage("blockchain", types.EventSetValueByKey, set)
err := client.GetQueueClient().Send(msg, true)
if err != nil {
return err
}
resp, err := client.GetQueueClient().Wait(msg)
if err != nil {
return err
}
if resp.GetData().(*types.Reply).IsOk {
return nil
}
return errors.New(string(resp.GetData().(*types.Reply).GetMsg()))
}
func (client *client) getLocalDb(set *types.LocalDBGet, count int) ([][]byte, error) {
msg := client.GetQueueClient().NewMessage("blockchain", types.EventGetValueByKey, set)
err := client.GetQueueClient().Send(msg, true)
if err != nil {
return nil, err
}
resp, err := client.GetQueueClient().Wait(msg)
func (client *client) GetBlockByHeight(height int64) (*types.Block, error) {
//from blockchain db
blockDetails, err := client.GetAPI().GetBlocks(&types.ReqBlocks{Start: height, End: height})
if err != nil {
plog.Error("GetBlockByHeight fail", "err", err)
return nil, err
}
reply := resp.GetData().(*types.LocalReplyValue)
if len(reply.Values) != count {
plog.Error("Parachain getLocalDb count not match", "expert", count, "real", len(reply.Values))
if 1 != int64(len(blockDetails.Items)) {
plog.Error("GetBlockByHeight count fail", "len", len(blockDetails.Items))
return nil, types.ErrInvalidParam
}
return reply.Values, nil
return blockDetails.Items[0].Block, nil
}
func (client *client) GetBlockByHeight(height int64) (*types.Block, error) {
func (client *client) GetBlockHeaders(req *types.ReqBlocks) (*types.Headers, error) {
//from blockchain db
blockDetails, err := client.GetAPI().GetBlocks(&types.ReqBlocks{Start: height, End: height})
headers, err := client.grpcClient.GetHeaders(context.Background(), req)
if err != nil {
plog.Error("paracommitmsg get node status block count fail")
plog.Error("GetBlockHeaders fail", "err", err)
return nil, err
}
if 1 != int64(len(blockDetails.Items)) {
plog.Error("paracommitmsg get node status block count fail")
return nil, types.ErrInvalidParam
count := req.End - req.Start + 1
if int64(len(headers.Items)) != count {
plog.Error("GetBlockHeaders", "start", req.Start, "end", req.End, "reals", headers.Items[0].Height, "reale", headers.Items[len(headers.Items)-1].Height,
"len", len(headers.Items), "count", count)
return nil, types.ErrBlockHeightNoMatch
}
return blockDetails.Items[0].Block, nil
return headers, nil
}
// 获取当前平行链block对应主链seq,hash信息
......@@ -88,7 +62,7 @@ func (client *client) getLastBlockMainInfo() (int64, *types.Block, error) {
func (client *client) getLastBlockInfo() (*types.Block, error) {
lastBlock, err := client.RequestLastBlock()
if err != nil {
plog.Error("Parachain RequestLastBlock fail", "err", err)
plog.Error("Parachain getLastBlockInfo fail", "err", err)
return nil, err
}
......@@ -169,3 +143,30 @@ func (client *client) QueryTxOnMainByHash(hash []byte) (*types.TransactionDetail
return detail, nil
}
func (client *client) GetParaHeightsByTitle(req *types.ReqHeightByTitle) (*types.ReplyHeightByTitle, error) {
//from blockchain db
heights, err := client.grpcClient.LoadParaTxByTitle(context.Background(), req)
if err != nil {
plog.Error("GetParaHeightsByTitle fail", "err", err)
return nil, err
}
return heights, nil
}
func (client *client) GetParaTxByHeight(req *types.ReqParaTxByHeight) (*types.ParaTxDetails, error) {
//from blockchain db
blocks, err := client.grpcClient.GetParaTxByHeight(context.Background(), req)
if err != nil {
plog.Error("GetParaTxByHeight get node status block count fail")
return nil, err
}
//可以小于等于,不能大于
if len(blocks.Items) > len(req.Items) {
plog.Error("GetParaTxByHeight get blocks more than req")
return nil, types.ErrInvalidParam
}
return blocks, nil
}
......@@ -39,6 +39,8 @@ type blockSyncClient struct {
isSyncCaughtUpAtom int32
//isDownloadCaughtUpAtom 下载是否已经追赶上
isDownloadCaughtUpAtom int32
//isSyncFirstCaughtUp 系统启动后download 层和sync层第一次都追赶上的设置,后面如果因为回滚或节点切换不同步,则不考虑
isSyncFirstCaughtUp bool
}
//nextActionType 定义每一轮可执行操作
......@@ -231,7 +233,7 @@ func (client *blockSyncClient) syncBlocksIfNeed() (bool, error) {
if err == nil {
isSyncCaughtUp := lastBlock.Height+1 == lastLocalHeight
client.setSyncCaughtUp(isSyncCaughtUp)
if client.paraClient.authAccount != "" {
if client.paraClient.commitMsgClient.authAccount != "" {
client.printDebugInfo("Para sync - add block commit", "isSyncCaughtUp", isSyncCaughtUp)
client.paraClient.commitMsgClient.updateChainHeightNotify(lastBlock.Height+1, false)
}
......@@ -250,7 +252,7 @@ func (client *blockSyncClient) syncBlocksIfNeed() (bool, error) {
//通知发送层
if err == nil {
client.setSyncCaughtUp(false)
if client.paraClient.authAccount != "" {
if client.paraClient.commitMsgClient.authAccount != "" {
client.printDebugInfo("Para sync - rollback block commit", "isSyncCaughtUp", false)
client.paraClient.commitMsgClient.updateChainHeightNotify(lastBlock.Height-1, true)
}
......@@ -384,7 +386,7 @@ func (client *blockSyncClient) addMinerTx(preStateHash []byte, block *types.Bloc
return err
}
tx.Sign(types.SECP256K1, client.paraClient.privateKey)
tx.Sign(types.SECP256K1, client.paraClient.minerPrivateKey)
block.Txs = append([]*types.Transaction{tx}, block.Txs...)
return nil
......@@ -403,7 +405,12 @@ func (client *blockSyncClient) addBlock(lastBlock *types.Block, localBlock *pt.P
}
//挖矿固定难度
newBlock.Difficulty = cfg.GetP(0).PowLimitBits
newBlock.TxHash = merkle.CalcMerkleRoot(newBlock.Txs)
//需要首先对交易进行排序然后再计算TxHash
if cfg.IsFork(newBlock.GetMainHeight(), "ForkRootHash") {
newBlock.Txs = types.TransactionSort(newBlock.Txs)
}
newBlock.TxHash = merkle.CalcMerkleRoot(cfg, newBlock.GetMainHeight(), newBlock.Txs)
newBlock.BlockTime = localBlock.BlockTime
newBlock.MainHash = localBlock.MainHash
newBlock.MainHeight = localBlock.MainHeight
......@@ -466,7 +473,13 @@ func (client *blockSyncClient) rollbackBlock(block *types.Block) error {
func (client *blockSyncClient) writeBlock(prev []byte, paraBlock *types.Block) error {
//共识模块不执行block,统一由blockchain模块执行block并做去重的处理,返回执行后的blockdetail
blockDetail := &types.BlockDetail{Block: paraBlock}
paraBlockDetail := &types.ParaChainBlockDetail{Blockdetail: blockDetail, IsSync: client.downloadHasCaughtUp()}
//database刷盘设置,默认不刷盘,提高执行速度,系统启动后download 层和sync层第一次都追赶上设置为刷盘,后面如果有回滚或节点切换不同步,则不再改变,减少数据库损坏风险
if !client.isSyncFirstCaughtUp && client.downloadHasCaughtUp() && client.syncHasCaughtUp() {
client.isSyncFirstCaughtUp = true
plog.Info("Para sync - SyncFirstCaughtUp", "Height", paraBlock.Height)
}
paraBlockDetail := &types.ParaChainBlockDetail{Blockdetail: blockDetail, IsSync: client.isSyncFirstCaughtUp}
msg := client.paraClient.GetQueueClient().NewMessage("blockchain", types.EventAddParaChainBlockDetail, paraBlockDetail)
err := client.paraClient.GetQueueClient().Send(msg, true)
if err != nil {
......
......@@ -66,7 +66,7 @@ func createParaTestInstance(t *testing.T, q queue.Queue) *client {
assert.Nil(t, err)
priKey, err := secp.PrivKeyFromBytes(pk)
assert.Nil(t, err)
para.privateKey = priKey
para.minerPrivateKey = priKey
//实例化BlockSyncClient
para.blockSyncClient = &blockSyncClient{
......
......@@ -92,7 +92,11 @@ func (client *Client) CreateBlock() {
newblock.ParentHash = lastBlock.Hash(cfg)
newblock.Height = lastBlock.Height + 1
newblock.Txs = txs
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
//需要首先对交易进行排序
if cfg.IsFork(newblock.Height, "ForkRootHash") {
newblock.Txs = types.TransactionSort(newblock.Txs)
}
newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs)
newblock.BlockTime = types.Now().Unix()
if lastBlock.BlockTime >= newblock.BlockTime {
newblock.BlockTime = lastBlock.BlockTime + 1
......
......@@ -184,7 +184,11 @@ func (client *Client) CreateBlock() {
newblock.ParentHash = lastBlock.Hash(cfg)
newblock.Height = lastBlock.Height + 1
client.AddTxsToBlock(&newblock, txs)
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
//需要首先对交易进行排序然后再计算TxHash
if cfg.IsFork(newblock.Height, "ForkRootHash") {
newblock.Txs = types.TransactionSort(newblock.Txs)
}
newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs)
newblock.BlockTime = types.Now().Unix()
if lastBlock.BlockTime >= newblock.BlockTime {
newblock.BlockTime = lastBlock.BlockTime + 1
......
......@@ -747,8 +747,15 @@ func (cs *ConsensusState) createProposalBlock() (block *ttypes.TendermintBlock)
tendermintlog.Error("createProposalBlock createBaseTx fail")
return nil
}
cfg := cs.client.GetQueueClient().GetConfig()
block.Data.Txs[0] = baseTx
block.Data.TxHash = merkle.CalcMerkleRoot(block.Data.Txs)
//需要首先对交易进行排序然后再计算TxHash
if cfg.IsFork(block.Data.Height, "ForkRootHash") {
block.Data.Txs = types.TransactionSort(block.Data.Txs)
}
block.Data.TxHash = merkle.CalcMerkleRoot(cfg, block.Data.Height, block.Data.Txs)
pblockNew := cs.client.PreExecBlock(block.Data, false)
if pblockNew == nil {
tendermintlog.Error("createProposalBlock PreExecBlock fail")
......
......@@ -22,7 +22,6 @@ import (
"github.com/33cn/chain33/common/log"
"github.com/33cn/chain33/executor"
"github.com/33cn/chain33/mempool"
"github.com/33cn/chain33/p2p"
"github.com/33cn/chain33/queue"
"github.com/33cn/chain33/rpc"
"github.com/33cn/chain33/store"
......@@ -60,14 +59,13 @@ func TestTendermintPerf(t *testing.T) {
}
func TendermintPerf(t *testing.T) {
q, chain, s, mem, exec, cs, p2p := initEnvTendermint()
q, chain, s, mem, exec, cs := initEnvTendermint()
defer chain.Close()
defer mem.Close()
defer exec.Close()
defer s.Close()
defer q.Close()
defer cs.Close()
defer p2p.Close()
err := createConn()
for err != nil {
err = createConn()
......@@ -86,7 +84,7 @@ func TendermintPerf(t *testing.T) {
time.Sleep(2 * time.Second)
}
func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, queue.Module, *executor.Executor, queue.Module, queue.Module) {
func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, queue.Module, *executor.Executor, queue.Module) {
flag.Parse()
chain33Cfg := types.NewChain33Config(types.ReadFile("chain33.test.toml"))
var q = queue.New("channel")
......@@ -108,14 +106,11 @@ func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, que
mem := mempool.New(chain33Cfg)
mem.SetQueueClient(q.Client())
network := p2p.New(chain33Cfg)
network.SetQueueClient(q.Client())
rpc.InitCfg(cfg.RPC)
gapi := rpc.NewGRpcServer(q.Client(), nil)
go gapi.Listen()
return q, chain, s, mem, exec, cs, network
return q, chain, s, mem, exec, cs
}
func createConn() error {
......
......@@ -604,6 +604,12 @@ func (client *Client) Miner(parent, block *types.Block) error {
if err != nil {
return err
}
//需要首先对交易进行排序
cfg := client.GetAPI().GetConfig()
if cfg.IsFork(block.Height, "ForkRootHash") {
block.Txs = types.TransactionSort(block.Txs)
}
err = client.WriteBlock(parent.StateHash, block)
if err != nil {
return err
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
#txhash=""
function run_testcases() {
echo "run_testcases"
}
function debug_function() {
set -x
eval "$@"
set +x
}
function rpc_test() {
chain33_RpcTestBegin autonomy
......@@ -30,4 +22,4 @@ function rpc_test() {
}
debug_function rpc_test "$1"
chain33_debug_function rpc_test "$1"
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set +e
set -o pipefail
MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
gID=""
......@@ -31,49 +30,35 @@ init() {
chain33_NewAccount() {
label=$1
result=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.NewAccount","params":[{"label":"'"$label"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result.acc.addr")
[ "$result" != "" ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
glAddr=$result
echo "$glAddr"
req='{"method":"Chain33.NewAccount","params":[{"label":"'"$label"'"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.acc.addr|length > 0)' "$FUNCNAME" ".result.acc.addr"
glAddr=$RETURN_RESP
}
chain33_SendTransaction() {
rawTx=$1
addr=$2
#签名交易
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.SignRawTx","params":[{"addr":"'"$addr"'","txHex":"'"$rawTx"'","expire":"120s","fee":10000000,"index":0}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
signTx=$(echo "${resp}" | jq -r ".result")
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.SendTransaction","params":[{"data":"'"$signTx"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.SignRawTx","params":[{"addr":"'"$addr"'","txHex":"'"$rawTx"'","expire":"120s","fee":10000000,"index":0}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "Chain33.SignRawTx" ".result"
signTx=$RETURN_RESP
req='{"method":"Chain33.SendTransaction","params":[{"data":"'"$signTx"'"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
gResp=$RETURN_RESP
#返回交易
gResp=$(jq -r ".result" <<<"$resp")
echo "tx hash is $gResp"
chain33_QueryTx "$gResp" "${MAIN_HTTP}"
chain33_QueryTx "$RETURN_RESP" "${MAIN_HTTP}"
}
blackwhite_BlackwhiteCreateTx() {
#创建交易
addr=$1
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"blackwhite.BlackwhiteCreateTx","params":[{"PlayAmount":100000000,"PlayerCount":3,"GameName":"hello","Timeout":600,"Fee":1000000}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"blackwhite.BlackwhiteCreateTx","params":[{"PlayAmount":100000000,"PlayerCount":3,"GameName":"hello","Timeout":600,"Fee":1000000}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SendTransaction "${rawTx}" "${addr}"
chain33_SendTransaction "$RETURN_RESP" "${addr}"
gID="${gResp}"
echo "gameID $gID"
}
blackwhite_BlackwhitePlayTx() {
......@@ -81,83 +66,54 @@ blackwhite_BlackwhitePlayTx() {
round1=$2
round2=$3
round3=$4
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"blackwhite.BlackwhitePlayTx","params":[{"gameID":"'"$gID"'","amount":100000000,"Fee":1000000,"hashValues":["'"$round1"'","'"$round2"'","'"$round3"'"]}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"blackwhite.BlackwhitePlayTx","params":[{"gameID":"'"$gID"'","amount":100000000,"Fee":1000000,"hashValues":["'"$round1"'","'"$round2"'","'"$round3"'"]}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SendTransaction "${rawTx}" "${addr}"
chain33_SendTransaction "$RETURN_RESP" "${addr}"
}
blackwhite_BlackwhiteShowTx() {
addr=$1
sec=$2
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"blackwhite.BlackwhiteShowTx","params":[{"gameID":"'"$gID"'","secret":"'"$sec"'","Fee":1000000}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SendTransaction "${rawTx}" "${addr}"
req='{"method":"blackwhite.BlackwhiteShowTx","params":[{"gameID":"'"$gID"'","secret":"'"$sec"'","Fee":1000000}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
chain33_SendTransaction "$RETURN_RESP" "${addr}"
}
blackwhite_BlackwhiteTimeoutDoneTx() {
gameID=$1
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"blackwhite.BlackwhiteTimeoutDoneTx","params":[{"gameID":"'"$gameID"'","Fee":1000000}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"blackwhite.BlackwhiteTimeoutDoneTx","params":[{"gameID":"'"$gameID"'","Fee":1000000}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME"
}
blackwhite_GetBlackwhiteRoundInfo() {
gameID=$1
execer="blackwhite"
funcName="GetBlackwhiteRoundInfo"
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"gameID":"'"$gameID"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.round | [has("gameID", "status", "playAmount", "playerCount", "curPlayerCount", "loop", "curShowCount", "timeout"),true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"blackwhite","funcName":"GetBlackwhiteRoundInfo","payload":{"gameID":"'"$gameID"'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.round | [has("gameID", "status", "playAmount", "playerCount", "curPlayerCount", "loop", "curShowCount", "timeout"),true] | unique | length == 1)' "$FUNCNAME"
}
blackwhite_GetBlackwhiteByStatusAndAddr() {
gameID=$1
addr=$2
execer="blackwhite"
funcName="GetBlackwhiteByStatusAndAddr"
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"status":5,"address":"'"$addr"'","count":1,"direction":0,"index":-1}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.round[0].createAddr == "'"$addr"'") and (.result.round[0].status == 5) and (.result.round[0] | [has("gameID", "status", "playAmount", "playerCount", "curPlayerCount", "loop", "curShowCount", "timeout", "winner"),true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
addr=$1
req='{"method":"Chain33.Query","params":[{"execer":"blackwhite","funcName":"GetBlackwhiteByStatusAndAddr","payload":{"status":5,"address":"'"$addr"'","count":1,"direction":0,"index":-1}}]}'
resok='(.error|not) and (.result.round[0].createAddr == "'"$addr"'") and (.result.round[0].status == 5) and (.result.round[0] | [has("gameID", "status", "playAmount", "playerCount", "curPlayerCount", "loop", "curShowCount", "timeout", "winner"),true] | unique | length == 1)'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
blackwhite_GetBlackwhiteloopResult() {
gameID=$1
execer="blackwhite"
funcName="GetBlackwhiteloopResult"
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"gameID":"'"$gameID"'","loopSeq":0}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.gameID == "'"$gameID"'") and (.result.results|length >= 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"blackwhite","funcName":"GetBlackwhiteloopResult","payload":{"gameID":"'"$gameID"'","loopSeq":0}}]}'
resok='(.error|not) and (.result.gameID == "'"$gameID"'") and (.result.results|length >= 1)'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
function run_testcases() {
#密钥
sect1="123"
#结果base64.StdEncoding.EncodeToString(common.Sha256([]byte("0"+secret+black)))
# black == "1" white := "0"
#black0="O3LD8NyaeeSCc8xDfvBoacTrQlrY91FHT9ceEOXgs18="
black1="6vm6gJ2wvEIxC8Yc6r/N6lIU5OZk633YMnIfwcZBD0o="
black2="6FXx5aeDSCaq1UrhLO8u0H31Hl8TpvzxuHrgGo9WeFk="
white0="DrNPzA68XiGimZE/igx70kTPJxnIJnVf8NCGnb7XoYU="
white1="SB5Pnf6Umf2Wba0dqyNOezq5FEqTd22WPVYAhSA6Lxs="
#white2="OiexKDzIlS1CKr3KBNWEY1k5uXzDI/ou6Dd+x0ByQCM="
#先创建账户地址
chain33_NewAccount "label188"
......@@ -201,9 +157,8 @@ function run_testcases() {
blackwhite_BlackwhiteTimeoutDoneTx "$gID"
#查询部分
blackwhite_GetBlackwhiteRoundInfo "$gID"
blackwhite_GetBlackwhiteByStatusAndAddr "$gID" "${gameAddr1}"
blackwhite_GetBlackwhiteByStatusAndAddr "${gameAddr1}"
blackwhite_GetBlackwhiteloopResult "$gID"
}
function main() {
......@@ -212,17 +167,8 @@ function main() {
echo "main_ip=$MAIN_HTTP"
init
run_testcases
chain33_RpcTestRst blackwhite "$CASE_ERR"
}
function debug_function() {
set -x
eval "$@"
set +x
}
debug_function main "$1"
chain33_debug_function main "$1"
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
CASE_ERR=""
#eventId=""
#txhash=""
init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
......@@ -30,8 +25,7 @@ function main() {
init
run_test
chain33_RpcTestRst dposvote "$CASE_ERR"
}
main "$1"
chain33_debug_function main "$1"
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
CASE_ERR=""
evm_createContract_unsignedTx="0a0365766d129407228405608060405234801561001057600080fd5b50610264806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063b8e010de1461003b578063cc80f6f314610045575b600080fd5b6100436100c2565b005b61004d610109565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561008757818101518382015260200161006f565b50505050905090810190601f1680156100b45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051808201909152600d8082527f5468697320697320746573742e000000000000000000000000000000000000006020909201918252610106916000916101a0565b50565b60008054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156101955780601f1061016a57610100808354040283529160200191610195565b820191906000526020600020905b81548152906001019060200180831161017857829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101e157805160ff191683800117855561020e565b8280016001018555821561020e579182015b8281111561020e5782518255916020019190600101906101f3565b5061021a92915061021e565b5090565b61019d91905b8082111561021a576000815560010161022456fea165627a7a72305820fec5dd5ca2cb47523ba08c04749bc5c14c435afee039f3047c2b7ea2faca737800293a8a025b7b22636f6e7374616e74223a66616c73652c22696e70757473223a5b5d2c226e616d65223a22736574222c226f757470757473223a5b5d2c2270617961626c65223a66616c73652c2273746174654d75746162696c697479223a226e6f6e70617961626c65222c2274797065223a2266756e6374696f6e227d2c7b22636f6e7374616e74223a747275652c22696e70757473223a5b5d2c226e616d65223a2273686f77222c226f757470757473223a5b7b226e616d65223a22222c2274797065223a22737472696e67227d5d2c2270617961626c65223a66616c73652c2273746174654d75746162696c697479223a2276696577222c2274797065223a2266756e6374696f6e227d5d20c0c7ee04309aedc4bcfba5beca5f3a223139746a5335316b6a7772436f535153313355336f7765376759424c6653666f466d"
evm_createContract_para_unsignedTx="0a0f757365722e702e706172612e65766d129407228405608060405234801561001057600080fd5b50610264806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063b8e010de1461003b578063cc80f6f314610045575b600080fd5b6100436100c2565b005b61004d610109565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561008757818101518382015260200161006f565b50505050905090810190601f1680156100b45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051808201909152600d8082527f5468697320697320746573742e000000000000000000000000000000000000006020909201918252610106916000916101a0565b50565b60008054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156101955780601f1061016a57610100808354040283529160200191610195565b820191906000526020600020905b81548152906001019060200180831161017857829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101e157805160ff191683800117855561020e565b8280016001018555821561020e579182015b8281111561020e5782518255916020019190600101906101f3565b5061021a92915061021e565b5090565b61019d91905b8082111561021a576000815560010161022456fea165627a7a7230582080ff1004de2195e6c08d0d0a65484b3d393c99c280e305cb383dbc89343cdd6a00293a8a025b7b22636f6e7374616e74223a66616c73652c22696e70757473223a5b5d2c226e616d65223a22736574222c226f757470757473223a5b5d2c2270617961626c65223a66616c73652c2273746174654d75746162696c697479223a226e6f6e70617961626c65222c2274797065223a2266756e6374696f6e227d2c7b22636f6e7374616e74223a747275652c22696e70757473223a5b5d2c226e616d65223a2273686f77222c226f757470757473223a5b7b226e616d65223a22222c2274797065223a22737472696e67227d5d2c2270617961626c65223a66616c73652c2273746174654d75746162696c697479223a2276696577222c2274797065223a2266756e6374696f6e227d5d20c0c7ee0430e1c7facdc1f199956c3a2231483969326a67464a594e5167573350695468694337796b7a5663653570764b7478"
evm_creatorAddr="1PTXh2EZ8aRUzpuoDRASV19K86Kx3qQiPt"
......@@ -14,29 +12,14 @@ evm_contractAddr=""
evm_addr=""
txHash=""
#color
RED='\033[1;31m'
GRE='\033[1;32m'
NOC='\033[0m'
# $2=0 means true, other false
function echo_rst() {
if [ "$2" -eq 0 ]; then
echo -e "${GRE}$1 ok${NOC}"
else
echo -e "${RED}$1 fail${NOC}"
CASE_ERR="FAIL"
fi
}
function evm_createContract() {
validator=$1
expectRes=$2
if [ "$ispara" == "true" ]; then
paraName="user.p.para."
chain33_SignRawTx "${evm_createContract_para_unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
chain33_SignAndSendTx "${evm_createContract_para_unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
else
chain33_SignRawTx "${evm_createContract_unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
chain33_SignAndSendTx "${evm_createContract_unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
fi
txHash=$RAW_TX_HASH
queryTransaction "${validator}" "${expectRes}"
......@@ -47,16 +30,9 @@ function evm_createContract() {
}
function evm_addressCheck() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"evm","funcName":"CheckAddrExists","payload":{"addr":"'${evm_contractAddr}'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
bContract=$(echo "${res}" | jq -r ".result.contract")
contractAddr=$(echo "${res}" | jq -r ".result.contractAddr")
if [ "${bContract}" == "true" ] && [ "${contractAddr}" == "${evm_contractAddr}" ]; then
echo_rst "evm address check" 0
else
echo_rst "evm address check" 1
fi
return
req='{"method":"Chain33.Query","params":[{"execer":"evm","funcName":"CheckAddrExists","payload":{"addr":"'${evm_contractAddr}'"}}]}'
resok='(.result.contract == true ) and (.result.contractAddr == "'"${evm_contractAddr}"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
function evm_callContract() {
op=$1
......@@ -72,7 +48,7 @@ function evm_callContract() {
return
fi
chain33_SignRawTx "${unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
chain33_SignAndSendTx "${unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
txHash=$RAW_TX_HASH
queryTransaction "${validator}" "${expectRes}"
echo "CallContract queryExecRes end"
......@@ -81,14 +57,8 @@ function evm_callContract() {
}
function evm_abiGet() {
abiInfo=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"evm","funcName":"QueryABI","payload":{"address":"'${evm_contractAddr}'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
res=$(echo "${abiInfo}" | jq -r ".result" | jq -r 'has("abi")')
if [ "${res}" == "true" ]; then
echo_rst "CallContract queryExecRes" 0
else
echo_rst "CallContract queryExecRes" 1
fi
return
req='{"method":"Chain33.Query","params":[{"execer":"evm","funcName":"QueryABI","payload":{"address":"'${evm_contractAddr}'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} "(.result.abi != null)" "$FUNCNAME"
}
function evm_transfer() {
......@@ -101,7 +71,7 @@ function evm_transfer() {
return
fi
chain33_SignRawTx "${unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
chain33_SignAndSendTx "${unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
txHash=$RAW_TX_HASH
queryTransaction "${validator}" "${expectRes}"
echo "evm transfer queryExecRes end"
......@@ -111,16 +81,9 @@ function evm_transfer() {
function evm_getBalance() {
expectBalance=$1
echo "This is evm get balance test."
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetBalance","params":[{"addresses":["'${evm_creatorAddr}'"],"execer":"'${evm_addr}'", "paraName": "'${paraName}'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
balance=$(echo "${res}" | jq -r ".result[0].balance")
addr=$(echo "${res}" | jq -r ".result[0].addr")
if [ "${balance}" == "${expectBalance}" ] && [ "${addr}" == "${evm_creatorAddr}" ]; then
echo_rst "evm getBalance" 0
else
echo_rst "evm getBalance" 1
fi
req='{"method":"Chain33.GetBalance","params":[{"addresses":["'${evm_creatorAddr}'"],"execer":"'${evm_addr}'", "paraName": "'${paraName}'"}]}'
resok='(.result[0].balance == '$expectBalance') and (.result[0].addr == "'"$evm_creatorAddr"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
function evm_withDraw() {
......@@ -133,7 +96,7 @@ function evm_withDraw() {
return
fi
chain33_SignRawTx "${unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
chain33_SignAndSendTx "${unsignedTx}" "${evm_creatorAddr_key}" "$MAIN_HTTP"
txHash=$RAW_TX_HASH
queryTransaction "${validator}" "${expectRes}"
echo "evm withdraw queryExecRes end"
......@@ -185,8 +148,6 @@ function init() {
echo "ipara=$ispara"
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#1PTXh2EZ8aRUzpuoDRASV19K86Kx3qQiPt
chain33_ImportPrivkey "0x4947ce3c4b845cfed59be2edf47320546116a3ff3af5715a7df094d116039b89" "1PTXh2EZ8aRUzpuoDRASV19K86Kx3qQiPt" "evm" "${main_ip}"
local from="1PTXh2EZ8aRUzpuoDRASV19K86Kx3qQiPt"
......@@ -195,12 +156,10 @@ function init() {
chain33_applyCoins "$from" 12000000000 "${main_ip}"
chain33_QueryBalance "${from}" "$main_ip"
else
# tx fee
chain33_applyCoins "$from" 1000000000 "${main_ip}"
chain33_QueryBalance "${from}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0x4947ce3c4b845cfed59be2edf47320546116a3ff3af5715a7df094d116039b89" "1PTXh2EZ8aRUzpuoDRASV19K86Kx3qQiPt" "evm" "$para_ip"
chain33_applyCoins "$from" 12000000000 "${para_ip}"
......@@ -243,14 +202,12 @@ function run_test() {
function main() {
chain33_RpcTestBegin evm
local ip=$1
MAIN_HTTP=$ip
echo "main_ip=$MAIN_HTTP"
init
run_test "$MAIN_HTTP"
chain33_RpcTestRst evm "$CASE_ERR"
}
......
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
#!/bin/sh
# 官方ci集成脚本
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
/*Package commands implement dapp client commands*/
package commands
import (
"github.com/spf13/cobra"
)
/*
* 实现合约对应客户端
*/
// Cmd exchange client command
func Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "exchange",
Short: "exchange command",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
//add sub command
)
return cmd
}
# exchange合约
## 前言
这是一个基于chain33开发的去中心化交易所合约,不收任何手续费,用于满足一小部分人群或者其他特定业务场景中,虚拟资产之间得交换。
## 使用
合约提供了类似中心化交易所健全的查询接口,所有得接口设计都基于用户的角度去出发
合约接口,在线构造交易和查询接口分别复用了框架中的CreateTransaction和Query接口,详情请参考
[CreateTransaction接口](https://github.com/33cn/chain33/blob/master/rpc/jrpchandler.go#L1101)[Query接口](https://github.com/33cn/chain33/blob/master/rpc/jrpchandler.go#L838)
查询方法名称|功能
-----|----
QueryMarketDepth|获取指定交易资产的市场深度
QueryHistoryOrderList|实时获取指定交易对已经成交的订单信息
QueryOrder|根据orderID订单号查询具体的订单信息
QueryOrderList|根据用户地址和订单状态(ordered,completed,revoked),实时地获取相应相应的订单详情
可参照exchange_test.go中得相关测试用例,构建limitOrder或者revokeOrder交易进行相关测试
## 注意事项
合约撮合规则如下:
序号|规则
---|----
1|买家获利得原则
2|买单高于市场价,按价格由低往高撮合
3|卖单低于市场价,按价格由高往低进行撮合
4|价格相同按先进先出的原则进行撮合
5|出于系统安全考虑,最大撮合深度为100单,单笔挂单最小为1e8,就是一个bty
**表结构说明**
表名|主键|索引|用途|说明
---|---|---|---|---
depth|price|nil|动态记录市场深度|主键price是复合主键由{leftAsset}:{rightAsset}:{op}:{price}构成
order|orderID|market_order,addr_status|实时动态维护更新市场上的挂单|market_order是复合索引由{leftAsset}:{rightAsset}:{op}:{price}:{orderID},addr_status是复合索引由{addr}:{status},当订单成交或者撤回时,该条订单记录和索引会从order表中自动删除
history|index|name,addr_status|实时记录某资产交易对下面最新完成的订单信息(revoked状态的交易也会记录)|name是复合索引由{leftAsset}:{rightAsset}构成, addr_status是复合索引由{addr}:{status}
**表中相关参数说明**
参数名|说明
----|----
leftAsset|交易对左边资产名称
rightAsset|交易对右边资产名称
op|买卖操作 1为买,2为卖
status|挂单状态,0 ordered, 1 completed,2 revoked
price|挂单价格,占位16 %016d,为了兼容不同架构的系统,这里设计为整型,由原有浮点型乘以1e8。 比如某交易对在中心化交易所上面是0.25,这里就变成25000000,price取值范围为1<=price<=1e16的整数
orderID|单号,由系统自动生成,整型,占位22 %022d
index|系统自动生成的index,占位22 %022d
package executor
import (
log "github.com/33cn/chain33/common/log/log15"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
exchangetypes "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 执行器相关定义
* 重载基类相关接口
*/
var (
//日志
elog = log.New("module", "exchange.executor")
)
var driverName = exchangetypes.ExchangeX
// Init register dapp
func Init(name string, cfg *types.Chain33Config, sub []byte) {
drivers.Register(cfg, GetName(), newExchange, cfg.GetDappFork(driverName, "Enable"))
InitExecType()
}
// InitExecType Init Exec Type
func InitExecType() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&exchange{}))
}
type exchange struct {
drivers.DriverBase
}
func newExchange() drivers.Driver {
t := &exchange{}
t.SetChild(t)
t.SetExecutorType(types.LoadExecutorType(driverName))
return t
}
// GetName get driver name
func GetName() string {
return newExchange().GetName()
}
func (e *exchange) GetDriverName() string {
return driverName
}
// CheckTx 实现自定义检验交易接口,供框架调用
func (e *exchange) CheckTx(tx *types.Transaction, index int) error {
//发送交易的时候就检查payload,做严格的参数检查
var exchange exchangetypes.ExchangeAction
types.Decode(tx.GetPayload(), &exchange)
if exchange.Ty == exchangetypes.TyLimitOrderAction {
limitOrder := exchange.GetLimitOrder()
left := limitOrder.GetLeftAsset()
right := limitOrder.GetRightAsset()
price := limitOrder.GetPrice()
amount := limitOrder.GetAmount()
op := limitOrder.GetOp()
if !CheckExchangeAsset(left, right) {
return exchangetypes.ErrAsset
}
if !CheckPrice(price) {
return exchangetypes.ErrAssetPrice
}
if !CheckAmount(amount) {
return exchangetypes.ErrAssetAmount
}
if !CheckOp(op) {
return exchangetypes.ErrAssetOp
}
}
if exchange.Ty == exchangetypes.TyMarketOrderAction {
return types.ErrActionNotSupport
}
return nil
}
//ExecutorOrder Exec 的时候 同时执行 ExecLocal
func (e *exchange) ExecutorOrder() int64 {
return drivers.ExecLocalSameTime
}
// GetPayloadValue get payload value
func (e *exchange) GetPayloadValue() types.Message {
return &exchangetypes.ExchangeAction{}
}
package executor
import (
"testing"
"github.com/33cn/chain33/common/db"
"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/client"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/queue"
et "github.com/33cn/plugin/plugin/dapp/exchange/types"
"github.com/stretchr/testify/assert"
)
type execEnv struct {
blockTime int64
blockHeight int64
difficulty uint64
}
var (
PrivKeyA = "0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" // 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4
PrivKeyB = "0x19c069234f9d3e61135fefbeb7791b149cdf6af536f26bebb310d4cd22c3fee4" // 1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR
PrivKeyC = "0x7a80a1f75d7360c6123c32a78ecf978c1ac55636f87892df38d8b85a9aeff115" // 1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k
PrivKeyD = "0xcacb1f5d51700aea07fca2246ab43b0917d70405c65edea9b5063d72eb5c6b71" // 1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs
Nodes = []string{
"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4",
"1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR",
"1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k",
"1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs",
}
)
func TestExchange(t *testing.T) {
//环境准备
cfg := types.NewChain33Config(types.GetDefaultCfgstring())
cfg.SetTitleOnlyForTest("chain33")
Init(et.ExchangeX, cfg, nil)
total := 100 * types.Coin
accountA := types.Account{
Balance: total,
Frozen: 0,
Addr: Nodes[0],
}
accountB := types.Account{
Balance: total,
Frozen: 0,
Addr: Nodes[1],
}
accountC := types.Account{
Balance: total,
Frozen: 0,
Addr: Nodes[2],
}
accountD := types.Account{
Balance: total,
Frozen: 0,
Addr: Nodes[3],
}
dir, stateDB, kvdb := util.CreateTestDB()
//defer util.CloseTestDB(dir, stateDB)
execAddr := address.ExecAddress(et.ExchangeX)
accA, _ := account.NewAccountDB(cfg, "coins", "bty", stateDB)
accA.SaveExecAccount(execAddr, &accountA)
accB, _ := account.NewAccountDB(cfg, "coins", "bty", stateDB)
accB.SaveExecAccount(execAddr, &accountB)
accC, _ := account.NewAccountDB(cfg, "coins", "bty", stateDB)
accC.SaveExecAccount(execAddr, &accountC)
accD, _ := account.NewAccountDB(cfg, "coins", "bty", stateDB)
accD.SaveExecAccount(execAddr, &accountD)
accA1, _ := account.NewAccountDB(cfg, "token", "CCNY", stateDB)
accA1.SaveExecAccount(execAddr, &accountA)
accB1, _ := account.NewAccountDB(cfg, "paracross", "coins.bty", stateDB)
accB1.SaveExecAccount(execAddr, &accountB)
accC1, _ := account.NewAccountDB(cfg, "paracross", "token.CCNY", stateDB)
accC1.SaveExecAccount(execAddr, &accountC)
accD1, _ := account.NewAccountDB(cfg, "token", "CCNY", stateDB)
accD1.SaveExecAccount(execAddr, &accountD)
env := &execEnv{
10,
1,
1539918074,
}
/*
买卖单价格相同,测试正常撮合流程,查询功能是否可用
用例说明:
1.先挂数量是10的买单。
2.然后再挂数量是5的吃单
3.最后撤销未成交部分的买单
*/
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 4, Amount: 10 * types.Coin, Op: et.OpBuy}, PrivKeyA, stateDB, kvdb, env)
//根据地址状态查看订单,最新得订单号永远是在list[0],第一位
orderList, err := Exec_QueryOrderList(et.Ordered, Nodes[0], "", stateDB, kvdb)
assert.Equal(t, nil, err)
orderID1 := orderList.List[0].OrderID
//根据订单号,查询订单详情
order, err := Exec_QueryOrder(orderID1, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Ordered), order.Status)
assert.Equal(t, 10*types.Coin, order.GetBalance())
//根据op查询市场深度
marketDepthList, err := Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Op: et.OpBuy}, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, 10*types.Coin, marketDepthList.List[0].GetAmount())
// 吃半单
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 4, Amount: 5 * types.Coin, Op: et.OpSell}, PrivKeyB, stateDB, kvdb, env)
//根据地址状态查看订单,最新得订单号永远是在list[0],第一位
orderList, err = Exec_QueryOrderList(et.Completed, Nodes[1], "", stateDB, kvdb)
assert.Equal(t, nil, err)
orderID2 := orderList.List[0].OrderID
//查询订单1详情
order, err = Exec_QueryOrder(orderID1, stateDB, kvdb)
assert.Equal(t, nil, err)
//订单1的状态应该还是ordered
assert.Equal(t, int32(et.Ordered), order.Status)
assert.Equal(t, 5*types.Coin, order.Balance)
//order2状态是completed
order, err = Exec_QueryOrder(orderID2, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Completed), order.Status)
//根据op查询市场深度
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Op: et.OpBuy}, stateDB, kvdb)
assert.Equal(t, nil, err)
//市场深度应该改变
assert.Equal(t, 5*types.Coin, marketDepthList.List[0].GetAmount())
//QueryHistoryOrderList
orderList, err = Exec_QueryHistoryOrder(&et.QueryHistoryOrderList{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}}, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, orderID2, orderList.List[0].OrderID)
//撤回未完成的订单
Exec_RevokeOrder(t, orderID1, PrivKeyA, stateDB, kvdb, env)
//根据订单号,查询订单详情
order, err = Exec_QueryOrder(orderID1, stateDB, kvdb)
assert.Equal(t, nil, err)
//订单1的状态应该Revoked
assert.Equal(t, int32(et.Revoked), order.Status)
assert.Equal(t, 5*types.Coin, order.Balance)
//根据op查询市场深度
//查看bty,CCNY买市场深度,查不到买单深度
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Op: et.OpBuy}, stateDB, kvdb)
assert.NotEqual(t, nil, err)
//根据原有状态去查看买单是否被改变
//原有ordered状态的数据应该被删除
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[0], "", stateDB, kvdb)
assert.Equal(t, types.ErrNotFound, err)
/*
买卖单价格相同,测试正常撮合流程,查询功能是否可用
反向测试
用例说明:
1.先挂数量是10的卖单。
2.然后再挂数量是10的卖单
3.再挂数量是5的买单
4.再挂数量是15的买单
*/
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 50000000, Amount: 10 * types.Coin, Op: et.OpSell}, PrivKeyA, stateDB, kvdb, env)
//根据地址状态查看订单
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[0], "", stateDB, kvdb)
orderID3 := orderList.List[0].OrderID
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 50000000, Amount: 10 * types.Coin, Op: et.OpSell}, PrivKeyA, stateDB, kvdb, env)
//根据地址状态查看订单
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[0], "", stateDB, kvdb)
orderID4 := orderList.List[0].OrderID
//根据op查询市场深度
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Op: et.OpSell}, stateDB, kvdb)
assert.Equal(t, nil, err)
//市场深度应该改变
assert.Equal(t, 20*types.Coin, marketDepthList.List[0].GetAmount())
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 50000000, Amount: 5 * types.Coin, Op: et.OpBuy}, PrivKeyB, stateDB, kvdb, env)
//根据地址状态查看订单
orderList, err = Exec_QueryOrderList(et.Completed, Nodes[1], "", stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Completed), orderList.List[1].Status)
//同价格按先进先出得原则吃单
//查询订单3详情
order, err = Exec_QueryOrder(orderID3, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Ordered), order.Status)
//订单余额
assert.Equal(t, 5*types.Coin, order.Balance)
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 50000000, Amount: 15 * types.Coin, Op: et.OpBuy}, PrivKeyB, stateDB, kvdb, env)
//order3,order4挂单全部被吃完
order, err = Exec_QueryOrder(orderID3, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Completed), order.Status)
order, err = Exec_QueryOrder(orderID4, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Completed), order.Status)
//根据op查询市场深度,这时候应该查不到
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Op: et.OpSell}, stateDB, kvdb)
assert.Equal(t, types.ErrNotFound, err)
/*
低于市场价的卖单测试 /高于市场价格的买单测试
用例说明:
1.先挂数量是5,价格为4的买单
2.再挂数量是10,价格为3的卖单
3.再挂数量是5,价格为4的卖单
4.再挂数量是5,价格为5的卖单
5.挂数量是15,价格为4.5的买单
6.挂单数量是2,价格为1的卖单
7.挂单数量是8,价格为1的卖单
8.撤回未成交的卖单
*/
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 400000000, Amount: 5 * types.Coin, Op: et.OpBuy}, PrivKeyD, stateDB, kvdb, env)
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[3], "", stateDB, kvdb)
orderID6 := orderList.List[0].OrderID
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 300000000, Amount: 10 * types.Coin, Op: et.OpSell}, PrivKeyC, stateDB, kvdb, env)
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[2], "", stateDB, kvdb)
orderID7 := orderList.List[0].OrderID
//此时订单6应该被吃掉
order, err = Exec_QueryOrder(orderID6, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Completed), order.Status)
order, err = Exec_QueryOrder(orderID7, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Ordered), order.Status)
//查看账户余额,按卖方价格成交
acc := accD1.LoadExecAccount(Nodes[3], execAddr)
assert.Equal(t, 85*types.Coin, acc.Balance)
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 400000000, Amount: 5 * types.Coin, Op: et.OpSell}, PrivKeyC, stateDB, kvdb, env)
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[2], "", stateDB, kvdb)
orderID8 := orderList.List[0].OrderID
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 500000000, Amount: 5 * types.Coin, Op: et.OpSell}, PrivKeyC, stateDB, kvdb, env)
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[2], "", stateDB, kvdb)
orderID9 := orderList.List[0].OrderID
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 450000000, Amount: 15 * types.Coin, Op: et.OpBuy}, PrivKeyD, stateDB, kvdb, env)
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[3], "", stateDB, kvdb)
//orderID10 := orderList.List[0].OrderID
assert.Equal(t, 5*types.Coin, orderList.List[0].Balance)
//order7和order8价格在吃单范围内
order, err = Exec_QueryOrder(orderID7, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Completed), order.Status)
order, err = Exec_QueryOrder(orderID8, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Completed), order.Status)
order, err = Exec_QueryOrder(orderID9, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, int32(et.Ordered), order.Status)
assert.Equal(t, 5*types.Coin, order.Balance)
//余额检查
acc = accD1.LoadExecAccount(Nodes[3], execAddr)
// 100-3*10-5*4-4.5*5 = 27.5
assert.Equal(t, int64(2750000000), acc.Balance)
acc = accC.LoadExecAccount(Nodes[2], execAddr)
assert.Equal(t, 80*types.Coin, acc.Balance)
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 100000000, Amount: 2 * types.Coin, Op: et.OpSell}, PrivKeyC, stateDB, kvdb, env)
orderList, err = Exec_QueryOrderList(et.Completed, Nodes[2], "", stateDB, kvdb)
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 100000000, Amount: 8 * types.Coin, Op: et.OpSell}, PrivKeyC, stateDB, kvdb, env)
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[2], "", stateDB, kvdb)
orderID10 := orderList.List[0].OrderID
assert.Equal(t, int32(et.Ordered), orderList.List[0].Status)
assert.Equal(t, 5*types.Coin, orderList.List[0].Balance)
//余额检查
acc = accD1.LoadExecAccount(Nodes[3], execAddr)
// 100-3*10-5*4-1*5 = 45
assert.Equal(t, 45*types.Coin, acc.Balance)
acc = accC.LoadExecAccount(Nodes[2], execAddr)
assert.Equal(t, 70*types.Coin, acc.Balance)
//orderID9和order10未成交
Exec_RevokeOrder(t, orderID9, PrivKeyC, stateDB, kvdb, env)
Exec_RevokeOrder(t, orderID10, PrivKeyC, stateDB, kvdb, env)
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Op: et.OpSell}, stateDB, kvdb)
assert.NotEqual(t, nil, err)
acc = accC.LoadExecAccount(Nodes[2], execAddr)
assert.Equal(t, 80*types.Coin, acc.Balance)
//清理环境,重建数据库
util.CloseTestDB(dir, stateDB)
total = 1000 * types.Coin
accountA = types.Account{
Balance: total,
Frozen: 0,
Addr: Nodes[0],
}
accountB = types.Account{
Balance: total,
Frozen: 0,
Addr: Nodes[1],
}
dir, stateDB, kvdb = util.CreateTestDB()
defer util.CloseTestDB(dir, stateDB)
//execAddr := address.ExecAddress(et.ExchangeX)
accA, _ = account.NewAccountDB(cfg, "coins", "bty", stateDB)
accA.SaveExecAccount(execAddr, &accountA)
accB, _ = account.NewAccountDB(cfg, "coins", "bty", stateDB)
accB.SaveExecAccount(execAddr, &accountB)
accA1, _ = account.NewAccountDB(cfg, "token", "CCNY", stateDB)
accA1.SaveExecAccount(execAddr, &accountA)
accB1, _ = account.NewAccountDB(cfg, "token", "CCNY", stateDB)
accB1.SaveExecAccount(execAddr, &accountB)
env = &execEnv{
10,
1,
1539918074,
}
/*
撮合深度测试:
用例说明:
1.先挂200单,价格为1数量为1的买单
2.然后再挂价格为1,数量为200的卖单
3.相同得地址不能交易,不会撮合
4.不同的地址没有权限进行订单撤销
*/
for i := 0; i < 200; i++ {
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 100000000, Amount: 1 * types.Coin, Op: et.OpBuy}, PrivKeyA, stateDB, kvdb, env)
}
Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 100000000, Amount: 200 * types.Coin, Op: et.OpSell}, PrivKeyB, stateDB, kvdb, env)
if et.MaxMatchCount > 200 {
return
}
orderList, err = Exec_QueryOrderList(et.Ordered, Nodes[1], "", stateDB, kvdb)
orderID := orderList.List[0].OrderID
assert.Equal(t, nil, err)
assert.Equal(t, (200-et.MaxMatchCount)*types.Coin, orderList.List[0].Balance)
//根据op查询市场深度
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Op: et.OpBuy}, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, (200-et.MaxMatchCount)*types.Coin, marketDepthList.List[0].GetAmount())
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Op: et.OpSell}, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, (200-et.MaxMatchCount)*types.Coin, marketDepthList.List[0].GetAmount())
//根据状态地址查询订单信息
//分页查询
var count int
var primaryKey string
for {
orderList, err := Exec_QueryOrderList(et.Completed, Nodes[0], primaryKey, stateDB, kvdb)
if err != nil {
break
}
count = count + len(orderList.List)
if orderList.PrimaryKey == "" {
break
}
primaryKey = orderList.PrimaryKey
}
assert.Equal(t, et.MaxMatchCount, count)
//分页查询查看历史订单
//根据状态地址查询订单信息
count = 0
primaryKey = ""
for {
query := &et.QueryHistoryOrderList{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, PrimaryKey: primaryKey}
orderList, err := Exec_QueryHistoryOrder(query, stateDB, kvdb)
if err != nil {
break
}
count = count + len(orderList.List)
if orderList.PrimaryKey == "" {
break
}
primaryKey = orderList.PrimaryKey
}
assert.Equal(t, et.MaxMatchCount, count)
//相同得地址不能交易,不会撮合
err = Exec_LimitOrder(t, &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 100000000, Amount: 100 * types.Coin, Op: et.OpSell}, PrivKeyA, stateDB, kvdb, env)
assert.Equal(t, nil, err)
marketDepthList, err = Exec_QueryMarketDepth(&et.QueryMarketDepth{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Op: et.OpSell}, stateDB, kvdb)
assert.Equal(t, nil, err)
assert.Equal(t, (200-et.MaxMatchCount+100)*types.Coin, marketDepthList.List[0].GetAmount())
//不同的地址没有权限进行订单撤销
err = Exec_RevokeOrder(t, orderID, PrivKeyA, stateDB, kvdb, env)
assert.NotEqual(t, nil, err)
err = Exec_RevokeOrder(t, orderID, PrivKeyB, stateDB, kvdb, env)
assert.Equal(t, nil, err)
}
func Exec_LimitOrder(t *testing.T, limitOrder *et.LimitOrder, privKey string, stateDB db.DB, kvdb db.KVDB, env *execEnv) error {
ety := types.LoadExecutorType(et.ExchangeX)
tx, err := ety.Create("LimitOrder", limitOrder)
if err != nil {
return err
}
cfg := types.NewChain33Config(types.GetDefaultCfgstring())
cfg.SetTitleOnlyForTest("chain33")
tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
if err != nil {
return err
}
tx, err = signTx(tx, privKey)
if err != nil {
return err
}
exec := newExchange()
e := exec.(*exchange)
err = e.CheckTx(tx, 1)
if err != nil {
return err
}
q := queue.New("channel")
q.SetConfig(cfg)
api, _ := client.New(q.Client(), nil)
exec.SetAPI(api)
exec.SetStateDB(stateDB)
exec.SetLocalDB(kvdb)
env.blockHeight = env.blockHeight + 1
env.blockTime = env.blockTime + 20
env.difficulty = env.difficulty + 1
exec.SetEnv(env.blockHeight, env.blockTime, env.difficulty)
receipt, err := exec.Exec(tx, int(1))
if err != nil {
return err
}
for _, kv := range receipt.KV {
stateDB.Set(kv.Key, kv.Value)
}
receiptData := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err := exec.ExecLocal(tx, receiptData, int(1))
if err != nil {
return err
}
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
//save to database
util.SaveKVList(stateDB, set.KV)
assert.Equal(t, types.ExecOk, int(receipt.Ty))
return nil
}
func Exec_RevokeOrder(t *testing.T, orderID int64, privKey string, stateDB db.DB, kvdb db.KVDB, env *execEnv) error {
ety := types.LoadExecutorType(et.ExchangeX)
tx, err := ety.Create("RevokeOrder", &et.RevokeOrder{OrderID: orderID})
if err != nil {
return err
}
cfg := types.NewChain33Config(types.GetDefaultCfgstring())
cfg.SetTitleOnlyForTest("chain33")
tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
if err != nil {
return err
}
tx, err = signTx(tx, privKey)
if err != nil {
return err
}
exec := newExchange()
e := exec.(*exchange)
err = e.CheckTx(tx, 1)
assert.Nil(t, err)
q := queue.New("channel")
q.SetConfig(cfg)
api, _ := client.New(q.Client(), nil)
exec.SetAPI(api)
exec.SetStateDB(stateDB)
exec.SetLocalDB(kvdb)
env.blockHeight = env.blockHeight + 1
env.blockTime = env.blockTime + 20
env.difficulty = env.difficulty + 1
exec.SetEnv(env.blockHeight, env.blockTime, env.difficulty)
receipt, err := exec.Exec(tx, int(1))
if err != nil {
return err
}
for _, kv := range receipt.KV {
stateDB.Set(kv.Key, kv.Value)
}
receiptData := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err := exec.ExecLocal(tx, receiptData, int(1))
if err != nil {
return err
}
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
//save to database
util.SaveKVList(stateDB, set.KV)
assert.Equal(t, types.ExecOk, int(receipt.Ty))
return nil
}
func Exec_QueryOrderList(status int32, addr string, primaryKey string, stateDB db.KV, kvdb db.KVDB) (*et.OrderList, error) {
cfg := types.NewChain33Config(types.GetDefaultCfgstring())
cfg.SetTitleOnlyForTest("chain33")
exec := newExchange()
q := queue.New("channel")
q.SetConfig(cfg)
api, _ := client.New(q.Client(), nil)
exec.SetAPI(api)
exec.SetStateDB(stateDB)
exec.SetLocalDB(kvdb)
//根据地址状态查看订单
msg, err := exec.Query(et.FuncNameQueryOrderList, types.Encode(&et.QueryOrderList{Status: status, Address: addr, PrimaryKey: primaryKey}))
if err != nil {
return nil, err
}
return msg.(*et.OrderList), nil
}
func Exec_QueryOrder(orderID int64, stateDB db.KV, kvdb db.KVDB) (*et.Order, error) {
cfg := types.NewChain33Config(types.GetDefaultCfgstring())
cfg.SetTitleOnlyForTest("chain33")
exec := newExchange()
q := queue.New("channel")
q.SetConfig(cfg)
api, _ := client.New(q.Client(), nil)
exec.SetAPI(api)
exec.SetStateDB(stateDB)
exec.SetLocalDB(kvdb)
//根据orderID查看订单信息
msg, err := exec.Query(et.FuncNameQueryOrder, types.Encode(&et.QueryOrder{OrderID: orderID}))
if err != nil {
return nil, err
}
return msg.(*et.Order), err
}
func Exec_QueryMarketDepth(query *et.QueryMarketDepth, stateDB db.KV, kvdb db.KVDB) (*et.MarketDepthList, error) {
cfg := types.NewChain33Config(types.GetDefaultCfgstring())
cfg.SetTitleOnlyForTest("chain33")
exec := newExchange()
q := queue.New("channel")
q.SetConfig(cfg)
api, _ := client.New(q.Client(), nil)
exec.SetAPI(api)
exec.SetStateDB(stateDB)
exec.SetLocalDB(kvdb)
//根据QueryMarketDepth查看市场深度
msg, err := exec.Query(et.FuncNameQueryMarketDepth, types.Encode(query))
if err != nil {
return nil, err
}
return msg.(*et.MarketDepthList), err
}
func Exec_QueryHistoryOrder(query *et.QueryHistoryOrderList, stateDB db.KV, kvdb db.KVDB) (*et.OrderList, error) {
cfg := types.NewChain33Config(types.GetDefaultCfgstring())
cfg.SetTitleOnlyForTest("chain33")
exec := newExchange()
q := queue.New("channel")
q.SetConfig(cfg)
api, _ := client.New(q.Client(), nil)
exec.SetAPI(api)
exec.SetStateDB(stateDB)
exec.SetLocalDB(kvdb)
//根据QueryMarketDepth查看市场深度
msg, err := exec.Query(et.FuncNameQueryHistoryOrderList, types.Encode(query))
return msg.(*et.OrderList), err
}
func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) {
signType := types.SECP256K1
c, err := crypto.New(types.GetSignName("", 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
}
func TestCheckPrice(t *testing.T) {
t.Log(CheckPrice(1e8))
t.Log(CheckPrice(-1))
t.Log(CheckPrice(1e17))
t.Log(CheckPrice(0))
}
func TestRawMeta(t *testing.T) {
HistoryOrderRow := NewHistoryOrderRow()
t.Log(HistoryOrderRow.Get("index"))
MarketDepthRow := NewMarketDepthRow()
t.Log(MarketDepthRow.Get("price"))
marketOrderRow := NewOrderRow()
t.Log(marketOrderRow.Get("orderID"))
}
func TestKV(t *testing.T) {
a := &types.KeyValue{Key: []byte("1111111"), Value: nil}
t.Log(a.Key, a.Value)
}
func TestSafeMul(t *testing.T) {
t.Log(SafeMul(1e8, 1e7))
t.Log(SafeMul(1e10, 1e16))
t.Log(SafeMul(1e7, 1e6))
}
package executor
import (
"fmt"
"math/big"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client"
dbm "github.com/33cn/chain33/common/db"
tab "github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
et "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
// Action action struct
type Action struct {
statedb dbm.KV
txhash []byte
fromaddr string
blocktime int64
height int64
execaddr string
localDB dbm.KVDB
index int
api client.QueueProtocolAPI
}
func NewAction(e *exchange, tx *types.Transaction, index int) *Action {
hash := tx.Hash()
fromaddr := tx.From()
return &Action{e.GetStateDB(), hash, fromaddr,
e.GetBlockTime(), e.GetHeight(), dapp.ExecAddress(string(tx.Execer)), e.GetLocalDB(), index, e.GetAPI()}
}
//GetIndex get index
func (a *Action) GetIndex() int64 {
//扩容4个0,用于匹配多个matchorder索引时使用
return (a.height*types.MaxTxsPerBlock + int64(a.index)) * 1e4
}
//GetKVSet get kv set
func (a *Action) GetKVSet(order *et.Order) (kvset []*types.KeyValue) {
kvset = append(kvset, &types.KeyValue{Key: calcOrderKey(order.OrderID), Value: types.Encode(order)})
return kvset
}
//缓存
func (a *Action) updateStateDBCache(order *et.Order) {
a.statedb.Set(calcOrderKey(order.OrderID), types.Encode(order))
}
//反转
func (a *Action) OpSwap(op int32) int32 {
if op == et.OpBuy {
return et.OpSell
}
return et.OpBuy
}
//计算实际花费
func (a *Action) calcActualCost(op int32, amount int64, price int64) int64 {
if op == et.OpBuy {
return SafeMul(amount, price)
}
return amount
}
//price 精度允许范围 1<=price<=1e16 整数
func CheckPrice(price int64) bool {
if price > 1e16 || price < 1 {
return false
}
return true
}
func CheckOp(op int32) bool {
if op == et.OpBuy || op == et.OpSell {
return true
}
return false
}
func CheckCount(count int32) bool {
return count <= 20 && count >= 0
}
//最小交易1e8
func CheckAmount(amount int64) bool {
if amount < types.Coin || amount >= types.MaxCoin {
return false
}
return true
}
func CheckDirection(direction int32) bool {
if direction == et.ListASC || direction == et.ListDESC {
return true
}
return false
}
func CheckStatus(status int32) bool {
if status == et.Ordered || status == et.Completed || status == et.Revoked {
return true
}
return false
}
//检查交易得资产是否合法
func CheckExchangeAsset(left, right *et.Asset) bool {
if left.Execer == "" || left.Symbol == "" || right.Execer == "" || right.Symbol == "" {
return false
}
if (left.Execer == "coins" && right.Execer == "coins") || (left.Symbol == right.Symbol) {
return false
}
return true
}
func (a *Action) LimitOrder(payload *et.LimitOrder) (*types.Receipt, error) {
leftAsset := payload.GetLeftAsset()
rightAsset := payload.GetRightAsset()
//TODO 参数要合法,必须有严格的校验,后面统一加入到checkTx里面
//coins执行器下面只有bty
if !CheckExchangeAsset(leftAsset, rightAsset) {
return nil, et.ErrAsset
}
if !CheckAmount(payload.GetAmount()) {
return nil, et.ErrAssetAmount
}
if !CheckPrice(payload.GetPrice()) {
return nil, et.ErrAssetPrice
}
if !CheckOp(payload.GetOp()) {
return nil, et.ErrAssetOp
}
//TODO 这里symbol
cfg := a.api.GetConfig()
leftAssetDB, err := account.NewAccountDB(cfg, leftAsset.GetExecer(), leftAsset.GetSymbol(), a.statedb)
if err != nil {
return nil, err
}
rightAssetDB, err := account.NewAccountDB(cfg, rightAsset.GetExecer(), rightAsset.GetSymbol(), a.statedb)
if err != nil {
return nil, err
}
//先检查账户余额
if payload.GetOp() == et.OpBuy {
amount := SafeMul(payload.GetAmount(), payload.GetPrice())
rightAccount := rightAssetDB.LoadExecAccount(a.fromaddr, a.execaddr)
if rightAccount.Balance < amount {
elog.Error("LimitOrder.BalanceCheck", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", amount, "err", et.ErrAssetBalance.Error())
return nil, et.ErrAssetBalance
}
return a.matchLimitOrder(payload, leftAssetDB, rightAssetDB)
}
if payload.GetOp() == et.OpSell {
amount := payload.GetAmount()
leftAccount := leftAssetDB.LoadExecAccount(a.fromaddr, a.execaddr)
if leftAccount.Balance < amount {
elog.Error("LimitOrder.BalanceCheck", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", amount, "err", et.ErrAssetBalance.Error())
return nil, et.ErrAssetBalance
}
return a.matchLimitOrder(payload, leftAssetDB, rightAssetDB)
}
return nil, fmt.Errorf("unknow op")
}
func (a *Action) RevokeOrder(payload *et.RevokeOrder) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kvs []*types.KeyValue
order, err := findOrderByOrderID(a.statedb, a.localDB, payload.GetOrderID())
if err != nil {
return nil, err
}
if order.Addr != a.fromaddr {
elog.Error("RevokeOrder.OrderCheck", "addr", a.fromaddr, "order.addr", order.Addr, "order.status", order.Status, "err", et.ErrAddr.Error())
return nil, et.ErrAddr
}
if order.Status == et.Completed || order.Status == et.Revoked {
elog.Error("RevokeOrder.OrderCheck", "addr", a.fromaddr, "order.addr", order.Addr, "order.status", order.Status, "err", et.ErrOrderSatus.Error())
return nil, et.ErrOrderSatus
}
leftAsset := order.GetLimitOrder().GetLeftAsset()
rightAsset := order.GetLimitOrder().GetRightAsset()
price := order.GetLimitOrder().GetPrice()
balance := order.GetBalance()
cfg := a.api.GetConfig()
if order.GetLimitOrder().GetOp() == et.OpBuy {
rightAssetDB, err := account.NewAccountDB(cfg, rightAsset.GetExecer(), rightAsset.GetSymbol(), a.statedb)
if err != nil {
return nil, err
}
amount := a.calcActualCost(et.OpBuy, balance, price)
rightAccount := rightAssetDB.LoadExecAccount(a.fromaddr, a.execaddr)
if rightAccount.Frozen < amount {
elog.Error("RevokeOrder.BalanceCheck", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", amount, "err", et.ErrAssetBalance.Error())
return nil, et.ErrAssetBalance
}
receipt, err := rightAssetDB.ExecActive(a.fromaddr, a.execaddr, amount)
if err != nil {
elog.Error("RevokeOrder.ExecActive", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", amount, "err", err.Error())
return nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
}
if order.GetLimitOrder().GetOp() == et.OpSell {
leftAssetDB, err := account.NewAccountDB(cfg, leftAsset.GetExecer(), leftAsset.GetSymbol(), a.statedb)
if err != nil {
return nil, err
}
amount := a.calcActualCost(et.OpSell, balance, price)
leftAccount := leftAssetDB.LoadExecAccount(a.fromaddr, a.execaddr)
if leftAccount.Frozen < amount {
elog.Error("RevokeOrder.BalanceCheck", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", amount, "err", et.ErrAssetBalance.Error())
return nil, et.ErrAssetBalance
}
receipt, err := leftAssetDB.ExecActive(a.fromaddr, a.execaddr, amount)
if err != nil {
elog.Error("RevokeOrder.ExecActive", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", amount, "err", err.Error())
return nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
}
//更新order状态
order.Status = et.Revoked
order.UpdateTime = a.blocktime
kvs = append(kvs, a.GetKVSet(order)...)
re := &et.ReceiptExchange{
Order: order,
Index: a.GetIndex(),
}
receiptlog := &types.ReceiptLog{Ty: et.TyRevokeOrderLog, Log: types.Encode(re)}
logs = append(logs, receiptlog)
receipts := &types.Receipt{Ty: types.ExecOk, KV: kvs, Logs: logs}
return receipts, nil
}
//撮合交易逻辑方法
// 规则:
//1.买单高于市场价,按价格由低往高撮合。
//2.卖单低于市场价,按价格由高往低进行撮合。
//3.价格相同按先进先出的原则进行撮合
//4.买家获利得原则
func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAccountDB *account.DB) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kvs []*types.KeyValue
var orderKey string
var priceKey string
var count int
or := &et.Order{
OrderID: a.GetIndex(),
Value: &et.Order_LimitOrder{LimitOrder: payload},
Ty: et.TyLimitOrderAction,
Executed: 0,
AVGPrice: 0,
Balance: payload.GetAmount(),
Status: et.Ordered,
Addr: a.fromaddr,
UpdateTime: a.blocktime,
Index: a.GetIndex(),
}
re := &et.ReceiptExchange{
Order: or,
Index: a.GetIndex(),
}
//单笔交易最多撮合100笔历史订单,最大可撮合得深度,系统得自我防护
//迭代已有挂单价格
for {
//当撮合深度大于最大深度时跳出
if count >= et.MaxMatchCount {
break
}
//获取现有市场挂单价格信息
marketDepthList, err := QueryMarketDepth(a.localDB, payload.GetLeftAsset(), payload.GetRightAsset(), a.OpSwap(payload.Op), priceKey, et.Count)
if err == types.ErrNotFound {
break
}
for _, marketDepth := range marketDepthList.List {
if count >= et.MaxMatchCount {
break
}
// 卖单价大于买单价
if payload.Op == et.OpBuy && marketDepth.Price > payload.GetPrice() {
continue
}
// 买单价小于卖单价
if payload.Op == et.OpSell && marketDepth.Price < payload.GetPrice() {
continue
}
//根据价格进行迭代
for {
//当撮合深度大于等于最大深度时跳出
if count >= et.MaxMatchCount {
break
}
orderList, err := findOrderIDListByPrice(a.localDB, payload.GetLeftAsset(), payload.GetRightAsset(), marketDepth.Price, a.OpSwap(payload.Op), et.ListASC, orderKey)
if err == types.ErrNotFound {
break
}
for _, matchorder := range orderList.List {
//当撮合深度大于最大深度时跳出
if count >= et.MaxMatchCount {
break
}
//同地址不能交易
if matchorder.Addr == a.fromaddr {
continue
}
//撮合,指针传递
log, kv, err := a.matchModel(leftAccountDB, rightAccountDB, payload, matchorder, or, re)
if err != nil {
return nil, err
}
logs = append(logs, log...)
kvs = append(kvs, kv...)
//订单完成,直接返回,如果没有完成,则继续撮合,直到count等于
if or.Status == et.Completed {
receiptlog := &types.ReceiptLog{Ty: et.TyLimitOrderLog, Log: types.Encode(re)}
logs = append(logs, receiptlog)
receipts := &types.Receipt{Ty: types.ExecOk, KV: kvs, Logs: logs}
return receipts, nil
}
//TODO 这里得逻辑是否需要调整?当匹配的单数过多,会导致receipt日志数量激增,理论上存在日志存储攻击,需要加下最大匹配深度,防止这种攻击发生
//撮合深度计数
count = count + 1
}
//查询数据不满足10条说明没有了,跳出循环
if orderList.PrimaryKey == "" {
break
}
orderKey = orderList.PrimaryKey
}
}
//查询的数据如果没有primaryKey说明没有后续数据了,跳出循环
if marketDepthList.PrimaryKey == "" {
break
}
priceKey = marketDepthList.PrimaryKey
}
//未完成的订单需要冻结剩余未成交的资金
if payload.Op == et.OpBuy {
receipt, err := rightAccountDB.ExecFrozen(a.fromaddr, a.execaddr, a.calcActualCost(et.OpBuy, or.Balance, payload.Price))
if err != nil {
elog.Error("LimitOrder.ExecFrozen", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", a.calcActualCost(et.OpBuy, or.Balance, payload.Price), "err", err.Error())
return nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
}
if payload.Op == et.OpSell {
receipt, err := leftAccountDB.ExecFrozen(a.fromaddr, a.execaddr, a.calcActualCost(et.OpSell, or.Balance, payload.Price))
if err != nil {
elog.Error("LimitOrder.ExecFrozen", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", a.calcActualCost(et.OpSell, or.Balance, payload.Price), "err", err.Error())
return nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
}
//更新order状态
kvs = append(kvs, a.GetKVSet(or)...)
receiptlog := &types.ReceiptLog{Ty: et.TyLimitOrderLog, Log: types.Encode(re)}
logs = append(logs, receiptlog)
receipts := &types.Receipt{Ty: types.ExecOk, KV: kvs, Logs: logs}
return receipts, nil
}
//交易撮合模型
func (a *Action) matchModel(leftAccountDB, rightAccountDB *account.DB, payload *et.LimitOrder, matchorder *et.Order, or *et.Order, re *et.ReceiptExchange) ([]*types.ReceiptLog, []*types.KeyValue, error) {
var logs []*types.ReceiptLog
var kvs []*types.KeyValue
//TODO 这里得逻辑是否需要调整?当匹配的单数过多,会导致receipt日志数量激增,理论上存在日志存储攻击,需要加下最大匹配深度,防止这种攻击发生
//先判断挂单得额度够不够,只有两种状态,大于等于,或者小于
if matchorder.GetBalance() >= or.GetBalance() {
if payload.Op == et.OpSell {
//转移冻结资产
receipt, err := rightAccountDB.ExecTransferFrozen(matchorder.Addr, a.fromaddr, a.execaddr, a.calcActualCost(matchorder.GetLimitOrder().Op, or.GetBalance(), payload.Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransferFrozen", "addr", matchorder.Addr, "execaddr", a.execaddr, "amount", a.calcActualCost(matchorder.GetLimitOrder().Op, or.GetBalance(), payload.Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//解冻多余资金
if payload.Price < matchorder.GetLimitOrder().Price {
receipt, err := rightAccountDB.ExecActive(matchorder.Addr, a.execaddr, a.calcActualCost(matchorder.GetLimitOrder().Op, or.GetBalance(), matchorder.GetLimitOrder().Price-payload.Price))
if err != nil {
elog.Error("matchLimitOrder.ExecActive", "addr", matchorder.Addr, "execaddr", a.execaddr, "amount", a.calcActualCost(matchorder.GetLimitOrder().Op, or.GetBalance(), matchorder.GetLimitOrder().Price-payload.Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
}
//将达成交易的相应资产结算
receipt, err = leftAccountDB.ExecTransfer(a.fromaddr, matchorder.Addr, a.execaddr, a.calcActualCost(payload.Op, or.GetBalance(), payload.Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransfer", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", a.calcActualCost(payload.Op, or.GetBalance(), payload.Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//卖单成交得平均价格始终与自身挂单价格相同
or.AVGPrice = payload.Price
//计算matchOrder平均成交价格
matchorder.AVGPrice = caclAVGPrice(matchorder, payload.Price, payload.Amount)
}
if payload.Op == et.OpBuy {
//转移冻结资产
receipt, err := leftAccountDB.ExecTransferFrozen(matchorder.Addr, a.fromaddr, a.execaddr, a.calcActualCost(matchorder.GetLimitOrder().Op, or.GetBalance(), matchorder.GetLimitOrder().Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransferFrozen", "addr", matchorder.Addr, "execaddr", a.execaddr, "amount", a.calcActualCost(matchorder.GetLimitOrder().Op, or.GetBalance(), matchorder.GetLimitOrder().Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//将达成交易的相应资产结算
receipt, err = rightAccountDB.ExecTransfer(a.fromaddr, matchorder.Addr, a.execaddr, a.calcActualCost(payload.Op, or.GetBalance(), matchorder.GetLimitOrder().Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransfer", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", a.calcActualCost(payload.Op, or.GetBalance(), matchorder.GetLimitOrder().Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//买单得话,价格选取卖单的价格
or.AVGPrice = matchorder.GetLimitOrder().Price
//计算matchOrder平均成交价格
matchorder.AVGPrice = caclAVGPrice(matchorder, matchorder.GetLimitOrder().Price, payload.Amount)
}
// match receiptorder,涉及赋值先手顺序,代码顺序不可变
matchorder.Status = func(a, b int64) int32 {
if a > b {
return et.Ordered
}
return et.Completed
}(matchorder.GetBalance(), or.GetBalance())
matchorder.Balance = matchorder.GetBalance() - or.GetBalance()
//记录本次成交得量
matchorder.Executed = or.GetBalance()
a.updateStateDBCache(matchorder)
kvs = append(kvs, a.GetKVSet(matchorder)...)
or.Executed = or.Executed + or.GetBalance()
or.Status = et.Completed
or.Balance = 0
//update receipt order
re.Order = or
re.MatchOrders = append(re.MatchOrders, matchorder)
a.updateStateDBCache(or)
kvs = append(kvs, a.GetKVSet(or)...)
return logs, kvs, nil
}
if payload.Op == et.OpSell {
//转移冻结资产
receipt, err := rightAccountDB.ExecTransferFrozen(matchorder.Addr, a.fromaddr, a.execaddr, a.calcActualCost(matchorder.GetLimitOrder().Op, matchorder.GetBalance(), payload.Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransferFrozen", "addr", matchorder.Addr, "execaddr", a.execaddr, "amount", a.calcActualCost(matchorder.GetLimitOrder().Op, matchorder.GetBalance(), payload.Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//解冻成交部分 多余资金
if payload.Price < matchorder.GetLimitOrder().Price {
receipt, err := rightAccountDB.ExecActive(matchorder.Addr, a.execaddr, a.calcActualCost(matchorder.GetLimitOrder().Op, matchorder.GetBalance(), matchorder.GetLimitOrder().Price-payload.Price))
if err != nil {
elog.Error("matchLimitOrder.ExecActive", "addr", matchorder.Addr, "execaddr", a.execaddr, "amount", a.calcActualCost(matchorder.GetLimitOrder().Op, or.GetBalance(), matchorder.GetLimitOrder().Price-payload.Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
}
//将达成交易的相应资产结算
receipt, err = leftAccountDB.ExecTransfer(a.fromaddr, matchorder.Addr, a.execaddr, a.calcActualCost(payload.Op, matchorder.GetBalance(), payload.Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransfer", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", a.calcActualCost(payload.Op, matchorder.GetBalance(), payload.Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//买单得话,价格选取卖单的价格
or.AVGPrice = payload.Price
//计算matchOrder平均成交价格
matchorder.AVGPrice = caclAVGPrice(matchorder, payload.Price, matchorder.GetBalance())
}
if payload.Op == et.OpBuy {
//转移冻结资产
receipt, err := leftAccountDB.ExecTransferFrozen(matchorder.Addr, a.fromaddr, a.execaddr, a.calcActualCost(matchorder.GetLimitOrder().Op, matchorder.GetBalance(), matchorder.GetLimitOrder().Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransferFrozen", "addr", matchorder.Addr, "execaddr", a.execaddr, "amount", a.calcActualCost(matchorder.GetLimitOrder().Op, matchorder.GetBalance(), matchorder.GetLimitOrder().Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//将达成交易的相应资产结算
receipt, err = rightAccountDB.ExecTransfer(a.fromaddr, matchorder.Addr, a.execaddr, a.calcActualCost(payload.Op, matchorder.GetBalance(), matchorder.GetLimitOrder().Price))
if err != nil {
elog.Error("matchLimitOrder.ExecTransfer", "addr", a.fromaddr, "execaddr", a.execaddr, "amount", a.calcActualCost(payload.Op, matchorder.GetBalance(), matchorder.GetLimitOrder().Price), "err", err.Error())
return nil, nil, err
}
logs = append(logs, receipt.Logs...)
kvs = append(kvs, receipt.KV...)
//买单得话,价格选取卖单的价格
or.AVGPrice = matchorder.GetLimitOrder().Price
//计算matchOrder平均成交价格
matchorder.AVGPrice = caclAVGPrice(matchorder, matchorder.GetLimitOrder().Price, matchorder.GetBalance())
}
//涉及赋值先后顺序,不可颠倒
or.Balance = or.Balance - matchorder.Balance
or.Executed = or.Executed + matchorder.Balance
or.Status = et.Ordered
a.updateStateDBCache(or)
// match receiptorder
matchorder.Executed = matchorder.Balance
matchorder.Status = et.Completed
matchorder.Balance = 0
a.updateStateDBCache(matchorder)
kvs = append(kvs, a.GetKVSet(matchorder)...)
re.Order = or
re.MatchOrders = append(re.MatchOrders, matchorder)
return logs, kvs, nil
}
//根据订单号查询,分为两步,优先去localdb中查询,如没有则再去状态数据库中查询
// 1.挂单中得订单信会根据orderID在localdb中存储
// 2.订单撤销,或者成交后,根据orderID在localdb中存储得数据会被删除,这时只能到状态数据库中查询
func findOrderByOrderID(statedb dbm.KV, localdb dbm.KV, orderID int64) (*et.Order, error) {
table := NewMarketOrderTable(localdb)
primaryKey := []byte(fmt.Sprintf("%022d", orderID))
row, err := table.GetData(primaryKey)
if err != nil {
data, err := statedb.Get(calcOrderKey(orderID))
if err != nil {
elog.Error("findOrderByOrderID.Get", "orderID", orderID, "err", err.Error())
return nil, err
}
var order et.Order
err = types.Decode(data, &order)
if err != nil {
elog.Error("findOrderByOrderID.Decode", "orderID", orderID, "err", err.Error())
return nil, err
}
return &order, nil
}
return row.Data.(*et.Order), nil
}
func findOrderIDListByPrice(localdb dbm.KV, left, right *et.Asset, price int64, op, direction int32, primaryKey string) (*et.OrderList, error) {
table := NewMarketOrderTable(localdb)
prefix := []byte(fmt.Sprintf("%s:%s:%d:%016d", left.GetSymbol(), right.GetSymbol(), op, price))
var rows []*tab.Row
var err error
if primaryKey == "" { //第一次查询,默认展示最新得成交记录
rows, err = table.ListIndex("market_order", prefix, nil, et.Count, direction)
} else {
rows, err = table.ListIndex("market_order", prefix, []byte(primaryKey), et.Count, direction)
}
if err != nil {
elog.Error("findOrderIDListByPrice.", "left", left, "right", right, "price", price, "err", err.Error())
return nil, err
}
var orderList et.OrderList
for _, row := range rows {
order := row.Data.(*et.Order)
//替换已经成交得量
order.Executed = order.GetLimitOrder().Amount - order.Balance
orderList.List = append(orderList.List, order)
}
//设置主键索引
if len(rows) == int(et.Count) {
orderList.PrimaryKey = string(rows[len(rows)-1].Primary)
}
return &orderList, nil
}
//买单深度是按价格倒序,由高到低
func Direction(op int32) int32 {
if op == et.OpBuy {
return et.ListDESC
}
return et.ListASC
}
//这里primaryKey当作主键索引来用,首次查询不需要填值,买单按价格由高往低,卖单按价格由低往高查询
func QueryMarketDepth(localdb dbm.KV, left, right *et.Asset, op int32, primaryKey string, count int32) (*et.MarketDepthList, error) {
table := NewMarketDepthTable(localdb)
prefix := []byte(fmt.Sprintf("%s:%s:%d", left.GetSymbol(), right.GetSymbol(), op))
if count == 0 {
count = et.Count
}
var rows []*tab.Row
var err error
if primaryKey == "" { //第一次查询,默认展示最新得成交记录
rows, err = table.ListIndex("price", prefix, nil, count, Direction(op))
} else {
rows, err = table.ListIndex("price", prefix, []byte(primaryKey), count, Direction(op))
}
if err != nil {
elog.Error("QueryMarketDepth.", "left", left, "right", right, "err", err.Error())
return nil, err
}
var list et.MarketDepthList
for _, row := range rows {
list.List = append(list.List, row.Data.(*et.MarketDepth))
}
//设置主键索引
if len(rows) == int(count) {
list.PrimaryKey = string(rows[len(rows)-1].Primary)
}
return &list, nil
}
//QueryHistoryOrderList 只返回成交的订单信息
func QueryHistoryOrderList(localdb dbm.KV, left, right *et.Asset, primaryKey string, count, direction int32) (types.Message, error) {
table := NewHistoryOrderTable(localdb)
prefix := []byte(fmt.Sprintf("%s:%s", left.Symbol, right.Symbol))
indexName := "name"
if count == 0 {
count = et.Count
}
var rows []*tab.Row
var err error
var orderList et.OrderList
HERE:
if primaryKey == "" { //第一次查询,默认展示最新得成交记录
rows, err = table.ListIndex(indexName, prefix, nil, count, direction)
} else {
rows, err = table.ListIndex(indexName, prefix, []byte(primaryKey), count, direction)
}
if err != nil && err != types.ErrNotFound {
elog.Error("QueryCompletedOrderList.", "left", left, "right", right, "err", err.Error())
return nil, err
}
if err == types.ErrNotFound {
return &orderList, nil
}
for _, row := range rows {
order := row.Data.(*et.Order)
//因为这张表里面记录了 completed,revoked 两种状态的订单,所以需要过滤
if order.Status == et.Revoked {
continue
}
//替换已经成交得量
order.Executed = order.GetLimitOrder().Amount - order.Balance
orderList.List = append(orderList.List, order)
if len(orderList.List) == int(count) {
//设置主键索引
orderList.PrimaryKey = string(row.Primary)
return &orderList, nil
}
}
if len(orderList.List) != int(count) && len(rows) == int(count) {
primaryKey = string(rows[len(rows)-1].Primary)
goto HERE
}
return &orderList, nil
}
//QueryOrderList,默认展示最新的
func QueryOrderList(localdb dbm.KV, addr string, status, count, direction int32, primaryKey string) (types.Message, error) {
var table *tab.Table
if status == et.Completed || status == et.Revoked {
table = NewHistoryOrderTable(localdb)
} else {
table = NewMarketOrderTable(localdb)
}
prefix := []byte(fmt.Sprintf("%s:%d", addr, status))
indexName := "addr_status"
if count == 0 {
count = et.Count
}
var rows []*tab.Row
var err error
if primaryKey == "" { //第一次查询,默认展示最新得成交记录
rows, err = table.ListIndex(indexName, prefix, nil, count, direction)
} else {
rows, err = table.ListIndex(indexName, prefix, []byte(primaryKey), count, direction)
}
if err != nil {
elog.Error("QueryOrderList.", "addr", addr, "err", err.Error())
return nil, err
}
var orderList et.OrderList
for _, row := range rows {
order := row.Data.(*et.Order)
//替换已经成交得量
order.Executed = order.GetLimitOrder().Amount - order.Balance
orderList.List = append(orderList.List, order)
}
//设置主键索引
if len(rows) == int(count) {
orderList.PrimaryKey = string(rows[len(rows)-1].Primary)
}
return &orderList, nil
}
func queryMarketDepth(localdb dbm.KV, left, right *et.Asset, op int32, price int64) (*et.MarketDepth, error) {
table := NewMarketDepthTable(localdb)
primaryKey := []byte(fmt.Sprintf("%s:%s:%d:%016d", left.GetSymbol(), right.GetSymbol(), op, price))
row, err := table.GetData(primaryKey)
if err != nil {
return nil, err
}
return row.Data.(*et.MarketDepth), nil
}
//math库中的安全大数乘法,防溢出
func SafeMul(x, y int64) int64 {
res := big.NewInt(0).Mul(big.NewInt(x), big.NewInt(y))
res = big.NewInt(0).Div(res, big.NewInt(types.Coin))
return res.Int64()
}
//计算平均成交价格
func caclAVGPrice(order *et.Order, price int64, amount int64) int64 {
x := big.NewInt(0).Mul(big.NewInt(order.AVGPrice), big.NewInt(order.GetLimitOrder().Amount-order.GetBalance()))
y := big.NewInt(0).Mul(big.NewInt(price), big.NewInt(amount))
total := big.NewInt(0).Add(x, y)
div := big.NewInt(0).Add(big.NewInt(order.GetLimitOrder().Amount-order.GetBalance()), big.NewInt(amount))
avg := big.NewInt(0).Div(total, div)
return avg.Int64()
}
package executor
import (
"github.com/33cn/chain33/types"
exchangetypes "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 实现交易的链上执行接口
* 关键数据上链(statedb)并生成交易回执(log)
*/
func (e *exchange) Exec_LimitOrder(payload *exchangetypes.LimitOrder, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(e, tx, index)
return action.LimitOrder(payload)
}
func (e *exchange) Exec_MarketOrder(payload *exchangetypes.MarketOrder, tx *types.Transaction, index int) (*types.Receipt, error) {
//TODO marketOrder
return nil, types.ErrActionNotSupport
}
func (e *exchange) Exec_RevokeOrder(payload *exchangetypes.RevokeOrder, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(e, tx, index)
return action.RevokeOrder(payload)
}
package executor
import (
"github.com/33cn/chain33/types"
)
/*
* 实现区块回退时本地执行的数据清除
*/
// ExecDelLocal 回退自动删除,重写基类
func (e *exchange) ExecDelLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
kvs, err := e.DelRollbackKV(tx, tx.Execer)
if err != nil {
return nil, err
}
dbSet := &types.LocalDBSet{}
dbSet.KV = append(dbSet.KV, kvs...)
return dbSet, nil
}
package executor
import (
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
ety "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 实现交易相关数据本地执行,数据不上链
* 非关键数据,本地存储(localDB), 用于辅助查询,效率高
*/
func (e *exchange) ExecLocal_LimitOrder(payload *ety.LimitOrder, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receiptData.Ty == types.ExecOk {
for _, log := range receiptData.Logs {
switch log.Ty {
case ety.TyLimitOrderLog:
receipt := &ety.ReceiptExchange{}
if err := types.Decode(log.Log, receipt); err != nil {
return nil, err
}
kv := e.updateIndex(receipt)
dbSet.KV = append(dbSet.KV, kv...)
}
}
}
return e.addAutoRollBack(tx, dbSet.KV), nil
}
func (e *exchange) ExecLocal_MarketOrder(payload *ety.MarketOrder, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receiptData.Ty == types.ExecOk {
for _, log := range receiptData.Logs {
switch log.Ty {
case ety.TyMarketOrderLog:
receipt := &ety.ReceiptExchange{}
if err := types.Decode(log.Log, receipt); err != nil {
return nil, err
}
kv := e.updateIndex(receipt)
dbSet.KV = append(dbSet.KV, kv...)
}
}
}
return e.addAutoRollBack(tx, dbSet.KV), nil
}
func (e *exchange) ExecLocal_RevokeOrder(payload *ety.RevokeOrder, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receiptData.Ty == types.ExecOk {
for _, log := range receiptData.Logs {
switch log.Ty {
case ety.TyRevokeOrderLog:
receipt := &ety.ReceiptExchange{}
if err := types.Decode(log.Log, receipt); err != nil {
return nil, err
}
kv := e.updateIndex(receipt)
dbSet.KV = append(dbSet.KV, kv...)
}
}
}
return e.addAutoRollBack(tx, dbSet.KV), nil
}
//设置自动回滚
func (e *exchange) addAutoRollBack(tx *types.Transaction, kv []*types.KeyValue) *types.LocalDBSet {
dbSet := &types.LocalDBSet{}
dbSet.KV = e.AddRollbackKV(tx, tx.Execer, kv)
return dbSet
}
func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyValue) {
historyTable := NewHistoryOrderTable(e.GetLocalDB())
marketTable := NewMarketDepthTable(e.GetLocalDB())
orderTable := NewMarketOrderTable(e.GetLocalDB())
switch receipt.Order.Status {
case ety.Ordered:
err := e.updateOrder(marketTable, orderTable, historyTable, receipt.GetOrder(), receipt.GetIndex())
if err != nil {
return nil
}
err = e.updateMatchOrders(marketTable, orderTable, historyTable, receipt.GetOrder(), receipt.GetMatchOrders(), receipt.GetIndex())
if err != nil {
return nil
}
case ety.Completed:
err := e.updateOrder(marketTable, orderTable, historyTable, receipt.GetOrder(), receipt.GetIndex())
if err != nil {
return nil
}
err = e.updateMatchOrders(marketTable, orderTable, historyTable, receipt.GetOrder(), receipt.GetMatchOrders(), receipt.GetIndex())
if err != nil {
return nil
}
case ety.Revoked:
err := e.updateOrder(marketTable, orderTable, historyTable, receipt.GetOrder(), receipt.GetIndex())
if err != nil {
return nil
}
}
//刷新KV
kv, err := marketTable.Save()
if err != nil {
elog.Error("updateIndex", "marketTable.Save", err.Error())
return nil
}
kvs = append(kvs, kv...)
kv, err = orderTable.Save()
if err != nil {
elog.Error("updateIndex", "orderTable.Save", err.Error())
return nil
}
kvs = append(kvs, kv...)
kv, err = historyTable.Save()
if err != nil {
elog.Error("updateIndex", "historyTable.Save", err.Error())
return nil
}
kvs = append(kvs, kv...)
return
}
func (e *exchange) updateOrder(marketTable, orderTable, historyTable *table.Table, order *ety.Order, index int64) error {
left := order.GetLimitOrder().GetLeftAsset()
right := order.GetLimitOrder().GetRightAsset()
op := order.GetLimitOrder().GetOp()
price := order.GetLimitOrder().GetPrice()
switch order.Status {
case ety.Ordered:
var markDepth ety.MarketDepth
depth, err := queryMarketDepth(e.GetLocalDB(), left, right, op, price)
if err == types.ErrNotFound {
markDepth.Price = price
markDepth.LeftAsset = left
markDepth.RightAsset = right
markDepth.Op = op
markDepth.Amount = order.Balance
} else {
markDepth.Price = price
markDepth.LeftAsset = left
markDepth.RightAsset = right
markDepth.Op = op
markDepth.Amount = depth.Amount + order.Balance
}
//marketDepth
err = marketTable.Replace(&markDepth)
if err != nil {
elog.Error("updateIndex", "marketTable.Replace", err.Error())
return err
}
err = orderTable.Replace(order)
if err != nil {
elog.Error("updateIndex", "orderTable.Replace", err.Error())
return err
}
case ety.Completed:
err := historyTable.Replace(order)
if err != nil {
elog.Error("updateIndex", "historyTable.Replace", err.Error())
return err
}
case ety.Revoked:
//只有状态时ordered状态的订单才能被撤回
var marketDepth ety.MarketDepth
depth, err := queryMarketDepth(e.GetLocalDB(), left, right, op, price)
if err == nil {
//marketDepth
marketDepth.Price = price
marketDepth.LeftAsset = left
marketDepth.RightAsset = right
marketDepth.Op = op
marketDepth.Amount = depth.Amount - order.Balance
err = marketTable.Replace(&marketDepth)
if err != nil {
elog.Error("updateIndex", "marketTable.Replace", err.Error())
return err
}
}
if marketDepth.Amount <= 0 {
//删除
err = marketTable.DelRow(&marketDepth)
if err != nil {
elog.Error("updateIndex", "marketTable.DelRow", err.Error())
return err
}
}
//删除原有状态orderID
order.Status = ety.Ordered
err = orderTable.DelRow(order)
if err != nil {
elog.Error("updateIndex", "orderTable.DelRow", err.Error())
return err
}
order.Status = ety.Revoked
order.Index = index
//添加撤销的订单
err = historyTable.Replace(order)
if err != nil {
elog.Error("updateIndex", "historyTable.Replace", err.Error())
return err
}
}
return nil
}
func (e *exchange) updateMatchOrders(marketTable, orderTable, historyTable *table.Table, order *ety.Order, matchOrders []*ety.Order, index int64) error {
left := order.GetLimitOrder().GetLeftAsset()
right := order.GetLimitOrder().GetRightAsset()
op := order.GetLimitOrder().GetOp()
if len(matchOrders) > 0 {
//撮合交易更新
cache := make(map[int64]int64)
for i, matchOrder := range matchOrders {
if matchOrder.Status == ety.Completed {
// 删除原有状态orderID
matchOrder.Status = ety.Ordered
err := orderTable.DelRow(matchOrder)
if err != nil {
elog.Error("updateIndex", "orderTable.DelRow", err.Error())
return err
}
//索引index,改为当前的index
matchOrder.Status = ety.Completed
matchOrder.Index = index + int64(i+1)
err = historyTable.Replace(matchOrder)
if err != nil {
elog.Error("updateIndex", "historyTable.Replace", err.Error())
return err
}
}
if matchOrder.Status == ety.Ordered {
//更新数据
err := orderTable.Replace(matchOrder)
if err != nil {
elog.Error("updateIndex", "orderTable.Replace", err.Error())
return err
}
}
executed := cache[matchOrder.GetLimitOrder().Price]
executed = executed + matchOrder.Executed
cache[matchOrder.GetLimitOrder().Price] = executed
}
//更改匹配市场深度
for pr, executed := range cache {
var matchDepth ety.MarketDepth
depth, err := queryMarketDepth(e.GetLocalDB(), left, right, OpSwap(op), pr)
if err == types.ErrNotFound {
continue
} else {
matchDepth.Price = pr
matchDepth.LeftAsset = left
matchDepth.RightAsset = right
matchDepth.Op = OpSwap(op)
matchDepth.Amount = depth.Amount - executed
}
//marketDepth
err = marketTable.Replace(&matchDepth)
if err != nil {
elog.Error("updateIndex", "marketTable.Replace", err.Error())
return err
}
if matchDepth.Amount <= 0 {
//删除
err = marketTable.DelRow(&matchDepth)
if err != nil {
elog.Error("updateIndex", "marketTable.DelRow", err.Error())
return err
}
}
}
}
return nil
}
func OpSwap(op int32) int32 {
if op == ety.OpBuy {
return ety.OpSell
}
return ety.OpBuy
}
package executor
import (
"github.com/33cn/chain33/types"
et "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
//查询市场深度
func (s *exchange) Query_QueryMarketDepth(in *et.QueryMarketDepth) (types.Message, error) {
if !CheckCount(in.Count) {
return nil, et.ErrCount
}
if !CheckExchangeAsset(in.LeftAsset, in.RightAsset) {
return nil, et.ErrAsset
}
if !CheckOp(in.Op) {
return nil, et.ErrAssetOp
}
return QueryMarketDepth(s.GetLocalDB(), in.LeftAsset, in.RightAsset, in.Op, in.PrimaryKey, in.Count)
}
//查询已经完成得订单
func (s *exchange) Query_QueryHistoryOrderList(in *et.QueryHistoryOrderList) (types.Message, error) {
if !CheckExchangeAsset(in.LeftAsset, in.RightAsset) {
return nil, et.ErrAsset
}
if !CheckCount(in.Count) {
return nil, et.ErrCount
}
if !CheckDirection(in.Direction) {
return nil, et.ErrDirection
}
return QueryHistoryOrderList(s.GetLocalDB(), in.LeftAsset, in.RightAsset, in.PrimaryKey, in.Count, in.Direction)
}
//根据orderID查询订单信息
func (s *exchange) Query_QueryOrder(in *et.QueryOrder) (types.Message, error) {
if in.OrderID == 0 {
return nil, et.ErrOrderID
}
return findOrderByOrderID(s.GetStateDB(), s.GetLocalDB(), in.OrderID)
}
//根据订单状态,查询订单信息(这里面包含所有交易对)
func (s *exchange) Query_QueryOrderList(in *et.QueryOrderList) (types.Message, error) {
if !CheckStatus(in.Status) {
return nil, et.ErrStatus
}
if !CheckCount(in.Count) {
return nil, et.ErrCount
}
if !CheckDirection(in.Direction) {
return nil, et.ErrDirection
}
if in.Address == "" {
return nil, et.ErrAddr
}
return QueryOrderList(s.GetLocalDB(), in.Address, in.Status, in.Count, in.Direction, in.PrimaryKey)
}
package executor
import (
"fmt"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
ety "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 用户合约存取kv数据时,key值前缀需要满足一定规范
* 即key = keyPrefix + userKey
* 需要字段前缀查询时,使用’-‘作为分割符号
*/
const (
//KeyPrefixStateDB state db key必须前缀
KeyPrefixStateDB = "mavl-exchange-"
//KeyPrefixLocalDB local db的key必须前缀
KeyPrefixLocalDB = "LODB-exchange"
)
//状态数据库中存储具体挂单信息
func calcOrderKey(orderID int64) []byte {
key := fmt.Sprintf("%s"+"orderID:%022d", KeyPrefixStateDB, orderID)
return []byte(key)
}
var opt_exchange_depth = &table.Option{
Prefix: KeyPrefixLocalDB,
Name: "depth",
Primary: "price",
Index: nil,
}
//重新设计表,list查询全部在订单信息localdb查询中
var opt_exchange_order = &table.Option{
Prefix: KeyPrefixLocalDB,
Name: "order",
Primary: "orderID",
Index: []string{"market_order", "addr_status"},
}
var opt_exchange_history = &table.Option{
Prefix: KeyPrefixLocalDB,
Name: "history",
Primary: "index",
Index: []string{"name", "addr_status"},
}
//NewTable 新建表
func NewMarketDepthTable(kvdb db.KV) *table.Table {
rowmeta := NewMarketDepthRow()
table, err := table.NewTable(rowmeta, kvdb, opt_exchange_depth)
if err != nil {
panic(err)
}
return table
}
func NewMarketOrderTable(kvdb db.KV) *table.Table {
rowmeta := NewOrderRow()
table, err := table.NewTable(rowmeta, kvdb, opt_exchange_order)
if err != nil {
panic(err)
}
return table
}
func NewHistoryOrderTable(kvdb db.KV) *table.Table {
rowmeta := NewHistoryOrderRow()
table, err := table.NewTable(rowmeta, kvdb, opt_exchange_history)
if err != nil {
panic(err)
}
return table
}
//OrderRow table meta 结构
type OrderRow struct {
*ety.Order
}
//NewOrderRow 新建一个meta 结构
func NewOrderRow() *OrderRow {
return &OrderRow{Order: &ety.Order{}}
}
//CreateRow
func (r *OrderRow) CreateRow() *table.Row {
return &table.Row{Data: &ety.Order{}}
}
//SetPayload 设置数据
func (r *OrderRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*ety.Order); ok {
r.Order = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (r *OrderRow) Get(key string) ([]byte, error) {
if key == "orderID" {
return []byte(fmt.Sprintf("%022d", r.OrderID)), nil
} else if key == "market_order" {
return []byte(fmt.Sprintf("%s:%s:%d:%016d", r.GetLimitOrder().LeftAsset.GetSymbol(), r.GetLimitOrder().RightAsset.GetSymbol(), r.GetLimitOrder().Op, r.GetLimitOrder().Price)), nil
} else if key == "addr_status" {
return []byte(fmt.Sprintf("%s:%d", r.Addr, r.Status)), nil
}
return nil, types.ErrNotFound
}
//HistoryOrderRow table meta 结构
type HistoryOrderRow struct {
*ety.Order
}
func NewHistoryOrderRow() *HistoryOrderRow {
return &HistoryOrderRow{Order: &ety.Order{Value: &ety.Order_LimitOrder{LimitOrder: &ety.LimitOrder{}}}}
}
func (m *HistoryOrderRow) CreateRow() *table.Row {
return &table.Row{Data: &ety.Order{Value: &ety.Order_LimitOrder{LimitOrder: &ety.LimitOrder{}}}}
}
//SetPayload 设置数据
func (m *HistoryOrderRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*ety.Order); ok {
m.Order = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (m *HistoryOrderRow) Get(key string) ([]byte, error) {
if key == "index" {
return []byte(fmt.Sprintf("%022d", m.Index)), nil
} else if key == "name" {
return []byte(fmt.Sprintf("%s:%s", m.GetLimitOrder().LeftAsset.GetSymbol(), m.GetLimitOrder().RightAsset.GetSymbol())), nil
} else if key == "addr_status" {
return []byte(fmt.Sprintf("%s:%d", m.Addr, m.Status)), nil
}
return nil, types.ErrNotFound
}
//marketDepthRow table meta 结构
type MarketDepthRow struct {
*ety.MarketDepth
}
//NewOracleRow 新建一个meta 结构
func NewMarketDepthRow() *MarketDepthRow {
return &MarketDepthRow{MarketDepth: &ety.MarketDepth{}}
}
//CreateRow 新建数据行(注意index 数据一定也要保存到数据中,不能就保存eventid)
func (m *MarketDepthRow) CreateRow() *table.Row {
return &table.Row{Data: &ety.MarketDepth{}}
}
//SetPayload 设置数据
func (m *MarketDepthRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*ety.MarketDepth); ok {
m.MarketDepth = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (m *MarketDepthRow) Get(key string) ([]byte, error) {
if key == "price" {
return []byte(fmt.Sprintf("%s:%s:%d:%016d", m.LeftAsset.GetSymbol(), m.RightAsset.GetSymbol(), m.Op, m.Price)), nil
}
return nil, types.ErrNotFound
}
package types
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/exchange/commands"
"github.com/33cn/plugin/plugin/dapp/exchange/executor"
"github.com/33cn/plugin/plugin/dapp/exchange/rpc"
exchangetypes "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 初始化dapp相关的组件
*/
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: exchangetypes.ExchangeX,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.Cmd,
RPC: rpc.Init,
})
}
all:
./create_protobuf.sh
#!/bin/sh
# proto生成命令,将pb.go文件生成到types/目录下, chain33_path支持引用chain33框架的proto文件
chain33_path=$(go list -f '{{.Dir}}' "github.com/33cn/chain33")
protoc --go_out=plugins=grpc:../types ./*.proto --proto_path=. --proto_path="${chain33_path}/types/proto/"
syntax = "proto3";
package types;
message Exchange {
}
message ExchangeAction {
oneof value {
LimitOrder limitOrder = 1;
MarketOrder marketOrder = 2;
RevokeOrder revokeOrder = 3;
}
int32 ty = 6;
}
//限价订单
message LimitOrder {
//交易对
asset leftAsset = 1;
//交易对
asset rightAsset = 2;
//价格
int64 price = 3;
//总量
int64 amount = 4;
//操作, 1为买,2为卖
int32 op = 5;
}
//市价委托
message MarketOrder {
//资产1
asset leftAsset = 1;
//资产2
asset rightAsset = 2;
//总量
int64 amount = 3;
//操作, 1为买,2为卖
int32 op = 4;
}
//撤回订单
message RevokeOrder {
//订单号
int64 orderID = 1;
}
//资产类型
message asset {
string execer = 1;
string symbol = 2;
}
//订单信息
message Order {
int64 orderID = 1;
oneof value {
LimitOrder limitOrder = 2;
MarketOrder marketOrder = 3;
}
//挂单类型
int32 ty = 4;
//已经成交的数量
int64 executed = 5;
//成交均价
int64 AVG_price = 6;
//余额
int64 balance = 7;
//状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
int32 status = 8;
//用户地址
string addr = 9;
//更新时间
int64 updateTime = 10;
//索引
int64 index = 11;
}
//查询接口
message QueryMarketDepth {
//资产1
asset leftAsset = 1;
//资产2
asset rightAsset = 2;
//操作, 1为买,2为卖
int32 op = 3;
// 这里用价格作为索引值
string primaryKey = 4;
//单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
int32 count = 5;
}
//市场深度
message MarketDepth {
//资产1
asset leftAsset = 1;
//资产2
asset rightAsset = 2;
//价格
int64 price = 3;
//总量
int64 amount = 4;
//操作, 1为买,2为卖
int32 op = 5;
}
//查询接口返回的市场深度列表
message MarketDepthList {
repeated MarketDepth list = 1;
string primaryKey = 2;
}
//查询最新得成交信息,外部接口
message QueryHistoryOrderList {
//资产1
asset leftAsset = 1;
//资产2
asset rightAsset = 2;
// 索引值
string primaryKey = 3;
//单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
int32 count = 4;
// 0降序,1升序,默认降序
int32 direction = 5;
}
//根据orderID去查询订单信息
message QueryOrder {
int64 orderID = 1;
}
//根据地址,状态查询用户自己的挂单信息
message QueryOrderList {
//挂单状态必填(默认是0,只查询ordered挂单中的)
int32 status = 1;
//用户地址信息,必填
string address = 2;
// 主键索引
string primaryKey = 3;
//单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
int32 count = 4;
// 0降序,1升序,默认降序
int32 direction = 5;
}
//订单列表
message OrderList {
repeated Order list = 1;
string primaryKey = 2;
}
//exchange执行票据日志
message ReceiptExchange {
Order order = 1;
repeated Order matchOrders = 2;
int64 index = 3;
}
service exchange {
}
package rpc
/*
* 实现json rpc和grpc service接口
* json rpc用Jrpc结构作为接收实例
* grpc使用channelClient结构作为接收实例
*/
package rpc
import (
rpctypes "github.com/33cn/chain33/rpc/types"
exchangetypes "github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* rpc相关结构定义和初始化
*/
// 实现grpc的service接口
type channelClient struct {
rpctypes.ChannelClient
}
// Jrpc 实现json rpc调用实例
type Jrpc struct {
cli *channelClient
}
// Grpc grpc
type Grpc struct {
*channelClient
}
// Init init rpc
func Init(name string, s rpctypes.RPCServer) {
cli := &channelClient{}
grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc)
//存在grpc service时注册grpc server,需要生成对应的pb.go文件
exchangetypes.RegisterExchangeServer(s.GRPC(), grpc)
}
package types
import "fmt"
// some errors definition
var (
ErrAssetAmount = fmt.Errorf("%s", "The asset amount is not valid!")
ErrAssetPrice = fmt.Errorf("%s", "The asset price is not valid!")
ErrAssetOp = fmt.Errorf("%s", "The asset op is not define!")
ErrAssetBalance = fmt.Errorf("%s", "Insufficient balance!")
ErrOrderSatus = fmt.Errorf("%s", "The order status is reovked or completed!")
ErrAddr = fmt.Errorf("%s", "Wrong Addr!")
ErrAsset = fmt.Errorf("%s", "The asset's execer or symbol can't be nil,The same assets cannot be exchanged!")
ErrCount = fmt.Errorf("%s", "The param count can't large 20")
ErrDirection = fmt.Errorf("%s", "The direction only 0 or 1!")
ErrStatus = fmt.Errorf("%s", "The status only in 0 , 1, 2!")
ErrOrderID = fmt.Errorf("%s", "Wrong OrderID!")
)
package types
import (
"reflect"
"github.com/33cn/chain33/types"
)
/*
* 交易相关类型定义
* 交易action通常有对应的log结构,用于交易回执日志记录
* 每一种action和log需要用id数值和name名称加以区分
*/
// action类型id和name,这些常量可以自定义修改
const (
TyUnknowAction = iota + 200
TyLimitOrderAction
TyMarketOrderAction
TyRevokeOrderAction
NameLimitOrderAction = "LimitOrder"
NameMarketOrderAction = "MarketOrder"
NameRevokeOrderAction = "RevokeOrder"
FuncNameQueryMarketDepth = "QueryMarketDepth"
FuncNameQueryHistoryOrderList = "QueryHistoryOrderList"
FuncNameQueryOrder = "QueryOrder"
FuncNameQueryOrderList = "QueryOrderList"
)
// log类型id值
const (
TyUnknownLog = iota + 200
TyLimitOrderLog
TyMarketOrderLog
TyRevokeOrderLog
)
// OP
const (
OpBuy = iota + 1
OpSell
)
//order status
const (
Ordered = iota
Completed
Revoked
)
//const
const (
ListDESC = int32(0)
ListASC = int32(1)
ListSeek = int32(2)
)
const (
//单次list还回条数
Count = int32(10)
//系统最大撮合深度
MaxMatchCount = 100
)
var (
//ExchangeX 执行器名称定义
ExchangeX = "exchange"
//定义actionMap
actionMap = map[string]int32{
NameLimitOrderAction: TyLimitOrderAction,
NameMarketOrderAction: TyMarketOrderAction,
NameRevokeOrderAction: TyRevokeOrderAction,
}
//定义log的id和具体log类型及名称,填入具体自定义log类型
logMap = map[int64]*types.LogInfo{
TyLimitOrderLog: {Ty: reflect.TypeOf(ReceiptExchange{}), Name: "TyLimitOrderLog"},
TyMarketOrderLog: {Ty: reflect.TypeOf(ReceiptExchange{}), Name: "TyMarketOrderLog"},
TyRevokeOrderLog: {Ty: reflect.TypeOf(ReceiptExchange{}), Name: "TyRevokeOrderLog"},
}
//tlog = log.New("module", "exchange.types")
)
// init defines a register function
func init() {
types.AllowUserExec = append(types.AllowUserExec, []byte(ExchangeX))
//注册合约启用高度
types.RegFork(ExchangeX, InitFork)
types.RegExec(ExchangeX, InitExecutor)
}
// InitFork defines register fork
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(ExchangeX, "Enable", 0)
}
// InitExecutor defines register executor
func InitExecutor(cfg *types.Chain33Config) {
types.RegistorExecutor(ExchangeX, NewType(cfg))
}
type ExchangeType struct {
types.ExecTypeBase
}
func NewType(cfg *types.Chain33Config) *ExchangeType {
c := &ExchangeType{}
c.SetChild(c)
c.SetConfig(cfg)
return c
}
// GetPayload 获取合约action结构
func (e *ExchangeType) GetPayload() types.Message {
return &ExchangeAction{}
}
// GeTypeMap 获取合约action的id和name信息
func (e *ExchangeType) GetTypeMap() map[string]int32 {
return actionMap
}
// GetLogMap 获取合约log相关信息
func (e *ExchangeType) GetLogMap() map[int64]*types.LogInfo {
return logMap
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: exchange.proto
/*
Package types is a generated protocol buffer package.
It is generated from these files:
exchange.proto
It has these top-level messages:
Exchange
ExchangeAction
LimitOrder
MarketOrder
RevokeOrder
Asset
Order
QueryMarketDepth
MarketDepth
MarketDepthList
QueryHistoryOrderList
QueryOrder
QueryOrderList
OrderList
ReceiptExchange
*/
package types
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Exchange struct {
}
func (m *Exchange) Reset() { *m = Exchange{} }
func (m *Exchange) String() string { return proto.CompactTextString(m) }
func (*Exchange) ProtoMessage() {}
func (*Exchange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type ExchangeAction struct {
// Types that are valid to be assigned to Value:
// *ExchangeAction_LimitOrder
// *ExchangeAction_MarketOrder
// *ExchangeAction_RevokeOrder
Value isExchangeAction_Value `protobuf_oneof:"value"`
Ty int32 `protobuf:"varint,6,opt,name=ty" json:"ty,omitempty"`
}
func (m *ExchangeAction) Reset() { *m = ExchangeAction{} }
func (m *ExchangeAction) String() string { return proto.CompactTextString(m) }
func (*ExchangeAction) ProtoMessage() {}
func (*ExchangeAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
type isExchangeAction_Value interface {
isExchangeAction_Value()
}
type ExchangeAction_LimitOrder struct {
LimitOrder *LimitOrder `protobuf:"bytes,1,opt,name=limitOrder,oneof"`
}
type ExchangeAction_MarketOrder struct {
MarketOrder *MarketOrder `protobuf:"bytes,2,opt,name=marketOrder,oneof"`
}
type ExchangeAction_RevokeOrder struct {
RevokeOrder *RevokeOrder `protobuf:"bytes,3,opt,name=revokeOrder,oneof"`
}
func (*ExchangeAction_LimitOrder) isExchangeAction_Value() {}
func (*ExchangeAction_MarketOrder) isExchangeAction_Value() {}
func (*ExchangeAction_RevokeOrder) isExchangeAction_Value() {}
func (m *ExchangeAction) GetValue() isExchangeAction_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *ExchangeAction) GetLimitOrder() *LimitOrder {
if x, ok := m.GetValue().(*ExchangeAction_LimitOrder); ok {
return x.LimitOrder
}
return nil
}
func (m *ExchangeAction) GetMarketOrder() *MarketOrder {
if x, ok := m.GetValue().(*ExchangeAction_MarketOrder); ok {
return x.MarketOrder
}
return nil
}
func (m *ExchangeAction) GetRevokeOrder() *RevokeOrder {
if x, ok := m.GetValue().(*ExchangeAction_RevokeOrder); ok {
return x.RevokeOrder
}
return nil
}
func (m *ExchangeAction) GetTy() int32 {
if m != nil {
return m.Ty
}
return 0
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*ExchangeAction) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _ExchangeAction_OneofMarshaler, _ExchangeAction_OneofUnmarshaler, _ExchangeAction_OneofSizer, []interface{}{
(*ExchangeAction_LimitOrder)(nil),
(*ExchangeAction_MarketOrder)(nil),
(*ExchangeAction_RevokeOrder)(nil),
}
}
func _ExchangeAction_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*ExchangeAction)
// value
switch x := m.Value.(type) {
case *ExchangeAction_LimitOrder:
b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.LimitOrder); err != nil {
return err
}
case *ExchangeAction_MarketOrder:
b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.MarketOrder); err != nil {
return err
}
case *ExchangeAction_RevokeOrder:
b.EncodeVarint(3<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.RevokeOrder); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("ExchangeAction.Value has unexpected type %T", x)
}
return nil
}
func _ExchangeAction_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*ExchangeAction)
switch tag {
case 1: // value.limitOrder
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(LimitOrder)
err := b.DecodeMessage(msg)
m.Value = &ExchangeAction_LimitOrder{msg}
return true, err
case 2: // value.marketOrder
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(MarketOrder)
err := b.DecodeMessage(msg)
m.Value = &ExchangeAction_MarketOrder{msg}
return true, err
case 3: // value.revokeOrder
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(RevokeOrder)
err := b.DecodeMessage(msg)
m.Value = &ExchangeAction_RevokeOrder{msg}
return true, err
default:
return false, nil
}
}
func _ExchangeAction_OneofSizer(msg proto.Message) (n int) {
m := msg.(*ExchangeAction)
// value
switch x := m.Value.(type) {
case *ExchangeAction_LimitOrder:
s := proto.Size(x.LimitOrder)
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *ExchangeAction_MarketOrder:
s := proto.Size(x.MarketOrder)
n += proto.SizeVarint(2<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *ExchangeAction_RevokeOrder:
s := proto.Size(x.RevokeOrder)
n += proto.SizeVarint(3<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
// 限价订单
type LimitOrder struct {
// 交易对
LeftAsset *Asset `protobuf:"bytes,1,opt,name=leftAsset" json:"leftAsset,omitempty"`
// 交易对
RightAsset *Asset `protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
// 价格
Price int64 `protobuf:"varint,3,opt,name=price" json:"price,omitempty"`
// 总量
Amount int64 `protobuf:"varint,4,opt,name=amount" json:"amount,omitempty"`
// 操作, 1为买,2为卖
Op int32 `protobuf:"varint,5,opt,name=op" json:"op,omitempty"`
}
func (m *LimitOrder) Reset() { *m = LimitOrder{} }
func (m *LimitOrder) String() string { return proto.CompactTextString(m) }
func (*LimitOrder) ProtoMessage() {}
func (*LimitOrder) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *LimitOrder) GetLeftAsset() *Asset {
if m != nil {
return m.LeftAsset
}
return nil
}
func (m *LimitOrder) GetRightAsset() *Asset {
if m != nil {
return m.RightAsset
}
return nil
}
func (m *LimitOrder) GetPrice() int64 {
if m != nil {
return m.Price
}
return 0
}
func (m *LimitOrder) GetAmount() int64 {
if m != nil {
return m.Amount
}
return 0
}
func (m *LimitOrder) GetOp() int32 {
if m != nil {
return m.Op
}
return 0
}
// 市价委托
type MarketOrder struct {
// 资产1
LeftAsset *Asset `protobuf:"bytes,1,opt,name=leftAsset" json:"leftAsset,omitempty"`
// 资产2
RightAsset *Asset `protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
// 总量
Amount int64 `protobuf:"varint,3,opt,name=amount" json:"amount,omitempty"`
// 操作, 1为买,2为卖
Op int32 `protobuf:"varint,4,opt,name=op" json:"op,omitempty"`
}
func (m *MarketOrder) Reset() { *m = MarketOrder{} }
func (m *MarketOrder) String() string { return proto.CompactTextString(m) }
func (*MarketOrder) ProtoMessage() {}
func (*MarketOrder) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *MarketOrder) GetLeftAsset() *Asset {
if m != nil {
return m.LeftAsset
}
return nil
}
func (m *MarketOrder) GetRightAsset() *Asset {
if m != nil {
return m.RightAsset
}
return nil
}
func (m *MarketOrder) GetAmount() int64 {
if m != nil {
return m.Amount
}
return 0
}
func (m *MarketOrder) GetOp() int32 {
if m != nil {
return m.Op
}
return 0
}
// 撤回订单
type RevokeOrder struct {
// 订单号
OrderID int64 `protobuf:"varint,1,opt,name=orderID" json:"orderID,omitempty"`
}
func (m *RevokeOrder) Reset() { *m = RevokeOrder{} }
func (m *RevokeOrder) String() string { return proto.CompactTextString(m) }
func (*RevokeOrder) ProtoMessage() {}
func (*RevokeOrder) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *RevokeOrder) GetOrderID() int64 {
if m != nil {
return m.OrderID
}
return 0
}
// 资产类型
type Asset struct {
Execer string `protobuf:"bytes,1,opt,name=execer" json:"execer,omitempty"`
Symbol string `protobuf:"bytes,2,opt,name=symbol" json:"symbol,omitempty"`
}
func (m *Asset) Reset() { *m = Asset{} }
func (m *Asset) String() string { return proto.CompactTextString(m) }
func (*Asset) ProtoMessage() {}
func (*Asset) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *Asset) GetExecer() string {
if m != nil {
return m.Execer
}
return ""
}
func (m *Asset) GetSymbol() string {
if m != nil {
return m.Symbol
}
return ""
}
// 订单信息
type Order struct {
OrderID int64 `protobuf:"varint,1,opt,name=orderID" json:"orderID,omitempty"`
// Types that are valid to be assigned to Value:
// *Order_LimitOrder
// *Order_MarketOrder
Value isOrder_Value `protobuf_oneof:"value"`
// 挂单类型
Ty int32 `protobuf:"varint,4,opt,name=ty" json:"ty,omitempty"`
// 已经成交的数量
Executed int64 `protobuf:"varint,5,opt,name=executed" json:"executed,omitempty"`
// 成交均价
AVGPrice int64 `protobuf:"varint,6,opt,name=AVG_price,json=AVGPrice" json:"AVG_price,omitempty"`
// 余额
Balance int64 `protobuf:"varint,7,opt,name=balance" json:"balance,omitempty"`
// 状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
Status int32 `protobuf:"varint,8,opt,name=status" json:"status,omitempty"`
// 用户地址
Addr string `protobuf:"bytes,9,opt,name=addr" json:"addr,omitempty"`
// 更新时间
UpdateTime int64 `protobuf:"varint,10,opt,name=updateTime" json:"updateTime,omitempty"`
// 索引
Index int64 `protobuf:"varint,11,opt,name=index" json:"index,omitempty"`
}
func (m *Order) Reset() { *m = Order{} }
func (m *Order) String() string { return proto.CompactTextString(m) }
func (*Order) ProtoMessage() {}
func (*Order) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
type isOrder_Value interface {
isOrder_Value()
}
type Order_LimitOrder struct {
LimitOrder *LimitOrder `protobuf:"bytes,2,opt,name=limitOrder,oneof"`
}
type Order_MarketOrder struct {
MarketOrder *MarketOrder `protobuf:"bytes,3,opt,name=marketOrder,oneof"`
}
func (*Order_LimitOrder) isOrder_Value() {}
func (*Order_MarketOrder) isOrder_Value() {}
func (m *Order) GetValue() isOrder_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *Order) GetOrderID() int64 {
if m != nil {
return m.OrderID
}
return 0
}
func (m *Order) GetLimitOrder() *LimitOrder {
if x, ok := m.GetValue().(*Order_LimitOrder); ok {
return x.LimitOrder
}
return nil
}
func (m *Order) GetMarketOrder() *MarketOrder {
if x, ok := m.GetValue().(*Order_MarketOrder); ok {
return x.MarketOrder
}
return nil
}
func (m *Order) GetTy() int32 {
if m != nil {
return m.Ty
}
return 0
}
func (m *Order) GetExecuted() int64 {
if m != nil {
return m.Executed
}
return 0
}
func (m *Order) GetAVGPrice() int64 {
if m != nil {
return m.AVGPrice
}
return 0
}
func (m *Order) GetBalance() int64 {
if m != nil {
return m.Balance
}
return 0
}
func (m *Order) GetStatus() int32 {
if m != nil {
return m.Status
}
return 0
}
func (m *Order) GetAddr() string {
if m != nil {
return m.Addr
}
return ""
}
func (m *Order) GetUpdateTime() int64 {
if m != nil {
return m.UpdateTime
}
return 0
}
func (m *Order) GetIndex() int64 {
if m != nil {
return m.Index
}
return 0
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*Order) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _Order_OneofMarshaler, _Order_OneofUnmarshaler, _Order_OneofSizer, []interface{}{
(*Order_LimitOrder)(nil),
(*Order_MarketOrder)(nil),
}
}
func _Order_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*Order)
// value
switch x := m.Value.(type) {
case *Order_LimitOrder:
b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.LimitOrder); err != nil {
return err
}
case *Order_MarketOrder:
b.EncodeVarint(3<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.MarketOrder); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("Order.Value has unexpected type %T", x)
}
return nil
}
func _Order_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*Order)
switch tag {
case 2: // value.limitOrder
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(LimitOrder)
err := b.DecodeMessage(msg)
m.Value = &Order_LimitOrder{msg}
return true, err
case 3: // value.marketOrder
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(MarketOrder)
err := b.DecodeMessage(msg)
m.Value = &Order_MarketOrder{msg}
return true, err
default:
return false, nil
}
}
func _Order_OneofSizer(msg proto.Message) (n int) {
m := msg.(*Order)
// value
switch x := m.Value.(type) {
case *Order_LimitOrder:
s := proto.Size(x.LimitOrder)
n += proto.SizeVarint(2<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *Order_MarketOrder:
s := proto.Size(x.MarketOrder)
n += proto.SizeVarint(3<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
// 查询接口
type QueryMarketDepth struct {
// 资产1
LeftAsset *Asset `protobuf:"bytes,1,opt,name=leftAsset" json:"leftAsset,omitempty"`
// 资产2
RightAsset *Asset `protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
// 操作, 1为买,2为卖
Op int32 `protobuf:"varint,3,opt,name=op" json:"op,omitempty"`
// 这里用价格作为索引值
PrimaryKey string `protobuf:"bytes,4,opt,name=primaryKey" json:"primaryKey,omitempty"`
// 单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
Count int32 `protobuf:"varint,5,opt,name=count" json:"count,omitempty"`
}
func (m *QueryMarketDepth) Reset() { *m = QueryMarketDepth{} }
func (m *QueryMarketDepth) String() string { return proto.CompactTextString(m) }
func (*QueryMarketDepth) ProtoMessage() {}
func (*QueryMarketDepth) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (m *QueryMarketDepth) GetLeftAsset() *Asset {
if m != nil {
return m.LeftAsset
}
return nil
}
func (m *QueryMarketDepth) GetRightAsset() *Asset {
if m != nil {
return m.RightAsset
}
return nil
}
func (m *QueryMarketDepth) GetOp() int32 {
if m != nil {
return m.Op
}
return 0
}
func (m *QueryMarketDepth) GetPrimaryKey() string {
if m != nil {
return m.PrimaryKey
}
return ""
}
func (m *QueryMarketDepth) GetCount() int32 {
if m != nil {
return m.Count
}
return 0
}
// 市场深度
type MarketDepth struct {
// 资产1
LeftAsset *Asset `protobuf:"bytes,1,opt,name=leftAsset" json:"leftAsset,omitempty"`
// 资产2
RightAsset *Asset `protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
// 价格
Price int64 `protobuf:"varint,3,opt,name=price" json:"price,omitempty"`
// 总量
Amount int64 `protobuf:"varint,4,opt,name=amount" json:"amount,omitempty"`
// 操作, 1为买,2为卖
Op int32 `protobuf:"varint,5,opt,name=op" json:"op,omitempty"`
}
func (m *MarketDepth) Reset() { *m = MarketDepth{} }
func (m *MarketDepth) String() string { return proto.CompactTextString(m) }
func (*MarketDepth) ProtoMessage() {}
func (*MarketDepth) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
func (m *MarketDepth) GetLeftAsset() *Asset {
if m != nil {
return m.LeftAsset
}
return nil
}
func (m *MarketDepth) GetRightAsset() *Asset {
if m != nil {
return m.RightAsset
}
return nil
}
func (m *MarketDepth) GetPrice() int64 {
if m != nil {
return m.Price
}
return 0
}
func (m *MarketDepth) GetAmount() int64 {
if m != nil {
return m.Amount
}
return 0
}
func (m *MarketDepth) GetOp() int32 {
if m != nil {
return m.Op
}
return 0
}
// 查询接口返回的市场深度列表
type MarketDepthList struct {
List []*MarketDepth `protobuf:"bytes,1,rep,name=list" json:"list,omitempty"`
PrimaryKey string `protobuf:"bytes,2,opt,name=primaryKey" json:"primaryKey,omitempty"`
}
func (m *MarketDepthList) Reset() { *m = MarketDepthList{} }
func (m *MarketDepthList) String() string { return proto.CompactTextString(m) }
func (*MarketDepthList) ProtoMessage() {}
func (*MarketDepthList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *MarketDepthList) GetList() []*MarketDepth {
if m != nil {
return m.List
}
return nil
}
func (m *MarketDepthList) GetPrimaryKey() string {
if m != nil {
return m.PrimaryKey
}
return ""
}
// 查询最新得成交信息,外部接口
type QueryHistoryOrderList struct {
// 资产1
LeftAsset *Asset `protobuf:"bytes,1,opt,name=leftAsset" json:"leftAsset,omitempty"`
// 资产2
RightAsset *Asset `protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
// 索引值
PrimaryKey string `protobuf:"bytes,3,opt,name=primaryKey" json:"primaryKey,omitempty"`
// 单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
Count int32 `protobuf:"varint,4,opt,name=count" json:"count,omitempty"`
// 0降序,1升序,默认降序
Direction int32 `protobuf:"varint,5,opt,name=direction" json:"direction,omitempty"`
}
func (m *QueryHistoryOrderList) Reset() { *m = QueryHistoryOrderList{} }
func (m *QueryHistoryOrderList) String() string { return proto.CompactTextString(m) }
func (*QueryHistoryOrderList) ProtoMessage() {}
func (*QueryHistoryOrderList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
func (m *QueryHistoryOrderList) GetLeftAsset() *Asset {
if m != nil {
return m.LeftAsset
}
return nil
}
func (m *QueryHistoryOrderList) GetRightAsset() *Asset {
if m != nil {
return m.RightAsset
}
return nil
}
func (m *QueryHistoryOrderList) GetPrimaryKey() string {
if m != nil {
return m.PrimaryKey
}
return ""
}
func (m *QueryHistoryOrderList) GetCount() int32 {
if m != nil {
return m.Count
}
return 0
}
func (m *QueryHistoryOrderList) GetDirection() int32 {
if m != nil {
return m.Direction
}
return 0
}
// 根据orderID去查询订单信息
type QueryOrder struct {
OrderID int64 `protobuf:"varint,1,opt,name=orderID" json:"orderID,omitempty"`
}
func (m *QueryOrder) Reset() { *m = QueryOrder{} }
func (m *QueryOrder) String() string { return proto.CompactTextString(m) }
func (*QueryOrder) ProtoMessage() {}
func (*QueryOrder) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
func (m *QueryOrder) GetOrderID() int64 {
if m != nil {
return m.OrderID
}
return 0
}
// 根据地址,状态查询用户自己的挂单信息
type QueryOrderList struct {
// 挂单状态必填(默认是0,只查询ordered挂单中的)
Status int32 `protobuf:"varint,1,opt,name=status" json:"status,omitempty"`
// 用户地址信息,必填
Address string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"`
// 主键索引
PrimaryKey string `protobuf:"bytes,3,opt,name=primaryKey" json:"primaryKey,omitempty"`
// 单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
Count int32 `protobuf:"varint,4,opt,name=count" json:"count,omitempty"`
// 0降序,1升序,默认降序
Direction int32 `protobuf:"varint,5,opt,name=direction" json:"direction,omitempty"`
}
func (m *QueryOrderList) Reset() { *m = QueryOrderList{} }
func (m *QueryOrderList) String() string { return proto.CompactTextString(m) }
func (*QueryOrderList) ProtoMessage() {}
func (*QueryOrderList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
func (m *QueryOrderList) GetStatus() int32 {
if m != nil {
return m.Status
}
return 0
}
func (m *QueryOrderList) GetAddress() string {
if m != nil {
return m.Address
}
return ""
}
func (m *QueryOrderList) GetPrimaryKey() string {
if m != nil {
return m.PrimaryKey
}
return ""
}
func (m *QueryOrderList) GetCount() int32 {
if m != nil {
return m.Count
}
return 0
}
func (m *QueryOrderList) GetDirection() int32 {
if m != nil {
return m.Direction
}
return 0
}
// 订单列表
type OrderList struct {
List []*Order `protobuf:"bytes,1,rep,name=list" json:"list,omitempty"`
PrimaryKey string `protobuf:"bytes,2,opt,name=primaryKey" json:"primaryKey,omitempty"`
}
func (m *OrderList) Reset() { *m = OrderList{} }
func (m *OrderList) String() string { return proto.CompactTextString(m) }
func (*OrderList) ProtoMessage() {}
func (*OrderList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
func (m *OrderList) GetList() []*Order {
if m != nil {
return m.List
}
return nil
}
func (m *OrderList) GetPrimaryKey() string {
if m != nil {
return m.PrimaryKey
}
return ""
}
// exchange执行票据日志
type ReceiptExchange struct {
Order *Order `protobuf:"bytes,1,opt,name=order" json:"order,omitempty"`
MatchOrders []*Order `protobuf:"bytes,2,rep,name=matchOrders" json:"matchOrders,omitempty"`
Index int64 `protobuf:"varint,3,opt,name=index" json:"index,omitempty"`
}
func (m *ReceiptExchange) Reset() { *m = ReceiptExchange{} }
func (m *ReceiptExchange) String() string { return proto.CompactTextString(m) }
func (*ReceiptExchange) ProtoMessage() {}
func (*ReceiptExchange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
func (m *ReceiptExchange) GetOrder() *Order {
if m != nil {
return m.Order
}
return nil
}
func (m *ReceiptExchange) GetMatchOrders() []*Order {
if m != nil {
return m.MatchOrders
}
return nil
}
func (m *ReceiptExchange) GetIndex() int64 {
if m != nil {
return m.Index
}
return 0
}
func init() {
proto.RegisterType((*Exchange)(nil), "types.Exchange")
proto.RegisterType((*ExchangeAction)(nil), "types.ExchangeAction")
proto.RegisterType((*LimitOrder)(nil), "types.LimitOrder")
proto.RegisterType((*MarketOrder)(nil), "types.MarketOrder")
proto.RegisterType((*RevokeOrder)(nil), "types.RevokeOrder")
proto.RegisterType((*Asset)(nil), "types.asset")
proto.RegisterType((*Order)(nil), "types.Order")
proto.RegisterType((*QueryMarketDepth)(nil), "types.QueryMarketDepth")
proto.RegisterType((*MarketDepth)(nil), "types.MarketDepth")
proto.RegisterType((*MarketDepthList)(nil), "types.MarketDepthList")
proto.RegisterType((*QueryHistoryOrderList)(nil), "types.QueryHistoryOrderList")
proto.RegisterType((*QueryOrder)(nil), "types.QueryOrder")
proto.RegisterType((*QueryOrderList)(nil), "types.QueryOrderList")
proto.RegisterType((*OrderList)(nil), "types.OrderList")
proto.RegisterType((*ReceiptExchange)(nil), "types.ReceiptExchange")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// Client API for Exchange service
type ExchangeClient interface {
}
type exchangeClient struct {
cc *grpc.ClientConn
}
func NewExchangeClient(cc *grpc.ClientConn) ExchangeClient {
return &exchangeClient{cc}
}
// Server API for Exchange service
type ExchangeServer interface {
}
func RegisterExchangeServer(s *grpc.Server, srv ExchangeServer) {
s.RegisterService(&_Exchange_serviceDesc, srv)
}
var _Exchange_serviceDesc = grpc.ServiceDesc{
ServiceName: "types.exchange",
HandlerType: (*ExchangeServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{},
Metadata: "exchange.proto",
}
func init() { proto.RegisterFile("exchange.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 667 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdd, 0x6e, 0xd3, 0x4a,
0x10, 0xae, 0xed, 0x38, 0xa9, 0x27, 0x47, 0xe9, 0x39, 0xab, 0x73, 0x8e, 0x2c, 0x40, 0xa8, 0xf2,
0x45, 0xa9, 0x10, 0xca, 0x45, 0x2b, 0xc1, 0x75, 0x50, 0x51, 0x8b, 0x68, 0x05, 0xac, 0x50, 0x25,
0xae, 0x90, 0x6b, 0x0f, 0xcd, 0xaa, 0x49, 0x6c, 0xad, 0x37, 0x55, 0x2d, 0x1e, 0x82, 0x3b, 0x9e,
0x00, 0x5e, 0x80, 0x77, 0xe0, 0x96, 0x27, 0xe0, 0x61, 0xd0, 0xce, 0xae, 0xe3, 0x4d, 0x5b, 0xd4,
0x0a, 0x94, 0x3b, 0x7f, 0xf3, 0xb3, 0xfe, 0x66, 0xe6, 0x9b, 0x5d, 0x18, 0xe0, 0x45, 0x36, 0x4e,
0x67, 0xa7, 0x38, 0x2c, 0x65, 0xa1, 0x0a, 0x16, 0xaa, 0xba, 0xc4, 0x2a, 0x01, 0x58, 0x7f, 0x66,
0x1d, 0xc9, 0x77, 0x0f, 0x06, 0x0d, 0x18, 0x65, 0x4a, 0x14, 0x33, 0xb6, 0x0b, 0x30, 0x11, 0x53,
0xa1, 0x5e, 0xca, 0x1c, 0x65, 0xec, 0x6d, 0x7a, 0xdb, 0xfd, 0x9d, 0x7f, 0x86, 0x94, 0x3a, 0x3c,
0x5c, 0x38, 0x0e, 0xd6, 0xb8, 0x13, 0xc6, 0x1e, 0x43, 0x7f, 0x9a, 0xca, 0x33, 0xb4, 0x59, 0x3e,
0x65, 0x31, 0x9b, 0x75, 0xd4, 0x7a, 0x0e, 0xd6, 0xb8, 0x1b, 0xa8, 0xf3, 0x24, 0x9e, 0x17, 0x67,
0x68, 0xf2, 0x82, 0xa5, 0x3c, 0xde, 0x7a, 0x74, 0x9e, 0x13, 0xc8, 0x06, 0xe0, 0xab, 0x3a, 0xee,
0x6e, 0x7a, 0xdb, 0x21, 0xf7, 0x55, 0xfd, 0xb4, 0x07, 0xe1, 0x79, 0x3a, 0x99, 0x63, 0xf2, 0xd9,
0x03, 0x68, 0x59, 0xb2, 0x87, 0x10, 0x4d, 0xf0, 0xbd, 0x1a, 0x55, 0x15, 0x2a, 0x5b, 0xcb, 0x5f,
0xf6, 0xf4, 0x54, 0xdb, 0x78, 0xeb, 0x66, 0x8f, 0x00, 0xa4, 0x38, 0x1d, 0xdb, 0x60, 0xff, 0x9a,
0x60, 0xc7, 0xcf, 0xfe, 0x85, 0xb0, 0x94, 0x22, 0x43, 0xe2, 0x1c, 0x70, 0x03, 0xd8, 0xff, 0xd0,
0x4d, 0xa7, 0xc5, 0x7c, 0xa6, 0xe2, 0x0e, 0x99, 0x2d, 0xd2, 0x7c, 0x8b, 0x32, 0x0e, 0x0d, 0xdf,
0xa2, 0x4c, 0x3e, 0x7a, 0xd0, 0x77, 0xda, 0xb2, 0x42, 0x9e, 0x2d, 0xa3, 0xe0, 0x1a, 0x46, 0x9d,
0x05, 0xa3, 0x07, 0xd0, 0x77, 0xfa, 0xcd, 0x62, 0xe8, 0x15, 0xfa, 0xe3, 0xf9, 0x1e, 0xd1, 0x09,
0x78, 0x03, 0x93, 0x27, 0x10, 0xa6, 0xcd, 0xc9, 0x78, 0x81, 0x99, 0x15, 0x49, 0xc4, 0x2d, 0xd2,
0xf6, 0xaa, 0x9e, 0x9e, 0x14, 0x13, 0xe2, 0x16, 0x71, 0x8b, 0x92, 0x1f, 0x3e, 0x84, 0x37, 0x1c,
0x7e, 0x49, 0x7c, 0xfe, 0x6f, 0x89, 0x2f, 0xb8, 0xad, 0xf8, 0x8c, 0x88, 0x3a, 0x8d, 0x88, 0xd8,
0x1d, 0x58, 0xd7, 0x25, 0xcc, 0x15, 0xe6, 0x34, 0xaa, 0x80, 0x2f, 0x30, 0xbb, 0x0b, 0xd1, 0xe8,
0x78, 0xff, 0x9d, 0x19, 0x79, 0xd7, 0x38, 0x47, 0xc7, 0xfb, 0xaf, 0x68, 0xea, 0x31, 0xf4, 0x4e,
0xd2, 0x49, 0x3a, 0xcb, 0x30, 0xee, 0x99, 0x7a, 0x2c, 0xa4, 0x5e, 0xa8, 0x54, 0xcd, 0xab, 0x78,
0x9d, 0x7e, 0x63, 0x11, 0x63, 0xd0, 0x49, 0xf3, 0x5c, 0xc6, 0x11, 0x75, 0x88, 0xbe, 0xd9, 0x7d,
0x80, 0x79, 0x99, 0xa7, 0x0a, 0xdf, 0x88, 0x29, 0xc6, 0x40, 0x07, 0x39, 0x16, 0xad, 0x38, 0x31,
0xcb, 0xf1, 0x22, 0xee, 0x1b, 0xc5, 0x11, 0x68, 0x95, 0xff, 0xd5, 0x83, 0xbf, 0x5f, 0xcf, 0x51,
0xd6, 0xa6, 0xe2, 0x3d, 0x2c, 0xd5, 0x78, 0x85, 0xba, 0x32, 0xfa, 0x09, 0x1a, 0xfd, 0x68, 0xf6,
0xa5, 0x14, 0xd3, 0x54, 0xd6, 0x2f, 0xd0, 0x34, 0x35, 0xe2, 0x8e, 0x45, 0xb3, 0xcf, 0x48, 0x86,
0x66, 0x09, 0x0c, 0x48, 0xbe, 0x2c, 0xf6, 0x60, 0xd5, 0x7c, 0xff, 0x6c, 0x5f, 0xdf, 0xc2, 0x86,
0x43, 0xf3, 0x50, 0x54, 0x8a, 0x6d, 0x41, 0x67, 0x22, 0x2a, 0xcd, 0x32, 0xb8, 0x22, 0x37, 0x8a,
0xe2, 0xe4, 0xbf, 0xd4, 0x18, 0xff, 0x72, 0x63, 0x92, 0x6f, 0x1e, 0xfc, 0x47, 0x73, 0x3b, 0x10,
0x95, 0x2a, 0x64, 0x4d, 0xda, 0xa4, 0x3f, 0xac, 0xae, 0x19, 0xcb, 0x9c, 0x82, 0x5f, 0x0f, 0xab,
0xe3, 0x0c, 0x8b, 0xdd, 0x83, 0x28, 0x17, 0x12, 0xe9, 0x99, 0xb0, 0xbd, 0x69, 0x0d, 0xc9, 0x16,
0x00, 0x95, 0x71, 0xd3, 0xfd, 0xf1, 0xc9, 0x83, 0x41, 0x1b, 0x48, 0x85, 0xb6, 0x5b, 0xe2, 0x2d,
0x6d, 0x49, 0x0c, 0x3d, 0xbd, 0x19, 0x58, 0x55, 0xb6, 0x6f, 0x0d, 0x5c, 0x49, 0x01, 0x47, 0x10,
0xb5, 0x94, 0x36, 0x97, 0xa6, 0xdb, 0x74, 0x92, 0xfc, 0xb7, 0x9c, 0xeb, 0x07, 0xd8, 0xe0, 0x98,
0xa1, 0x28, 0x55, 0xf3, 0xc0, 0xb2, 0x04, 0xc2, 0xc2, 0x79, 0x55, 0x97, 0x4f, 0x35, 0x2e, 0x36,
0xd4, 0x97, 0x99, 0xca, 0xc6, 0x64, 0xd4, 0x75, 0x5f, 0xfd, 0xbf, 0x1b, 0xd0, 0xde, 0x0a, 0x81,
0x73, 0x2b, 0xec, 0x80, 0xbe, 0xca, 0xcc, 0x5f, 0x4f, 0xba, 0xf4, 0xfa, 0xef, 0xfe, 0x0c, 0x00,
0x00, 0xff, 0xff, 0xf2, 0x3c, 0xac, 0xed, 0x0f, 0x08, 0x00, 0x00,
}
#!/usr/bin/env bash
# shellcheck disable=SC2128
set -e
# shellcheck source=/dev/null
set -o pipefail
MAIN_HTTP=""
......@@ -8,36 +8,24 @@ GAME_ID=""
PASSWD="ABCD"
HASH_VALUE=$(echo -n "ABCD1" | sha256sum | awk '{print $1}')
EXECTOR=""
PRIVA_A="0xfa21dc33a6144c546537580d28d894355d1e9af7292be175808b0f5737c30849"
PRIVA_B="0x213286d352b01fd740b6eaeb78a4fd316d743dd51d2f12c6789977430a41e0c7"
# shellcheck source=/dev/null
EXECTOR=""
source ../dapp-test-common.sh
function chain33_GetExecAddr() {
#获取GAME合约地址
local exector=$1
local req='"method":"Chain33.ConvertExectoAddr","params":[{"execname":"'"${exector}"'"}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
# GAME_ADDR=$(echo "${res}" | jq -r ".result")
echo_rst "$FUNCNAME" "$?"
req='{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"'"$1"'"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME"
}
function CreateGameTx() {
local amount=$1
local hash_value=$2
local req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"createGame", "payload":{"amount": '"${amount}"',"hashType":"sha256","hashValue":"'"${hash_value}"'"}}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
rawTx=$(echo "${resp}" | jq -r ".result")
if [ "$rawTx" == "null" ]; then
echo_rst "CreateGame createRawTx" 1
fi
chain33_SignRawTx "${rawTx}" "${PRIVA_A}" "${MAIN_HTTP}"
local req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"createGame", "payload":{"amount": '"${amount}"',"hashType":"sha256","hashValue":"'"${hash_value}"'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "${RETURN_RESP}" "${PRIVA_A}" "${MAIN_HTTP}"
GAME_ID=$RAW_TX_HASH
echo_rst "CreateGame query_tx" "$?"
......@@ -45,81 +33,43 @@ function CreateGameTx() {
function MatchGameTx() {
local gameId=$1
local req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"matchGame", "payload":{"gameId": "'"${gameId}"'","guess":2}}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
rawTx=$(echo "${resp}" | jq -r ".result")
if [ "$rawTx" == "null" ]; then
echo_rst "MatchGame createRawTx" 1
fi
chain33_SignRawTx "${rawTx}" "${PRIVA_B}" "${MAIN_HTTP}"
local req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"matchGame", "payload":{"gameId": "'"${gameId}"'","guess":2}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "MatchGame createRawTx" ".result"
chain33_SignAndSendTx "${RETURN_RESP}" "${PRIVA_B}" "${MAIN_HTTP}"
echo_rst "MatchGame query_tx" "$?"
}
function CloseGameTx() {
local gameId=$1
local secret=$2
local req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"closeGame", "payload":{"gameId": "'"${gameId}"'","secret":"'"${secret}"'","result":1}}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
rawTx=$(echo "${resp}" | jq -r ".result")
if [ "$rawTx" == "null" ]; then
echo_rst "CloseGame createRawTx" 1
fi
local req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"closeGame", "payload":{"gameId": "'"${gameId}"'","secret":"'"${secret}"'","result":1}}]}'
chain33_SignRawTx "${rawTx}" "${PRIVA_A}" "${MAIN_HTTP}"
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "CloseGame createRawTx" ".result"
chain33_SignAndSendTx "${RETURN_RESP}" "${PRIVA_A}" "${MAIN_HTTP}"
echo_rst "CloseGame query_tx" "$?"
}
function CancleGameTx() {
local gameId=$1
local req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"cancelGame", "payload":{"gameId": "'"${gameId}"'"}}]'
local req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"cancelGame", "payload":{"gameId": "'"${gameId}"'"}}]}'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
rawTx=$(echo "${resp}" | jq -r ".result")
if [ "$rawTx" == "null" ]; then
echo_rst "CancleGame createRawTx" 1
fi
chain33_SignRawTx "${rawTx}" "${PRIVA_A}" "${MAIN_HTTP}"
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "CancleGame createRawTx" ".result"
chain33_SignAndSendTx "${RETURN_RESP}" "${PRIVA_A}" "${MAIN_HTTP}"
echo_rst "CancleGame query_tx" "$?"
}
function QueryGameByStatus() {
local status=$1
local req='"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameListByStatusAndAddr","payload":{"status":'"${status}"',"address":""}}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
GAMES=$(echo "${resp}" | jq -r ".result.games")
echo "${GAMES}"
echo_rst "$FUNCNAME" "$?"
local req='{"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameListByStatusAndAddr","payload":{"status":'"${status}"',"address":""}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result.games"
}
function QueryGameByGameId() {
local gameId=$1
local status=$2
local req='"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameById","payload":{"gameId":"'"${gameId}"'"}}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
STATUS=$(echo "${resp}" | jq -r ".result.game.status")
if [ "${STATUS}" -ne "${status}" ]; then
echo "status is not equal"
echo_rst "QueryGameByGameId" 1
return 0
fi
echo_rst "QueryGameByGameId" 0
local req='{"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameById","payload":{"gameId":"'"${gameId}"'"}}]}'
resok='(.error|not) and (.result.game.status = "'"${status}"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
function init() {
......@@ -138,10 +88,8 @@ function init() {
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f
chain33_ImportPrivkey "0xfa21dc33a6144c546537580d28d894355d1e9af7292be175808b0f5737c30849" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "${main_ip}"
#16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc
chain33_ImportPrivkey "0x213286d352b01fd740b6eaeb78a4fd316d743dd51d2f12c6789977430a41e0c7" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$main_ip"
chain33_ImportPrivkey "$PRIVA_A" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "${main_ip}"
chain33_ImportPrivkey "$PRIVA_B" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$main_ip"
local ACCOUNT_A="16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f"
local ACCOUNT_B="16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc"
......@@ -153,16 +101,14 @@ function init() {
chain33_applyCoins "$ACCOUNT_B" 12000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_B}" "$main_ip"
else
# tx fee
chain33_applyCoins "$ACCOUNT_A" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$main_ip"
chain33_applyCoins "$ACCOUNT_B" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_B}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0xfa21dc33a6144c546537580d28d894355d1e9af7292be175808b0f5737c30849" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "$para_ip"
chain33_ImportPrivkey "0x213286d352b01fd740b6eaeb78a4fd316d743dd51d2f12c6789977430a41e0c7" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$para_ip"
chain33_ImportPrivkey "$PRIVA_A" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "$para_ip"
chain33_ImportPrivkey "$PRIVA_B" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$para_ip"
chain33_applyCoins "$ACCOUNT_A" 12000000000 "${para_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$para_ip"
......@@ -181,43 +127,28 @@ function init() {
function run_test() {
local ip=$1
CreateGameTx 1000000000 "${HASH_VALUE}"
QueryGameByGameId "${GAME_ID}" 1
QueryGameByStatus 1
MatchGameTx "${GAME_ID}"
QueryGameByGameId "${GAME_ID}" 2
QueryGameByStatus 2
CloseGameTx "${GAME_ID}" "${PASSWD}"
QueryGameByGameId "${GAME_ID}" 4
QueryGameByStatus 4
CreateGameTx 500000000 "${HASH_VALUE}"
QueryGameByGameId "${GAME_ID}" 1
CancleGameTx "${GAME_ID}"
QueryGameByGameId "${GAME_ID}" 3
QueryGameByStatus 3
}
function main() {
chain33_RpcTestBegin game
local ip=$1
MAIN_HTTP=$ip
chain33_RpcTestBegin game
echo "main_ip=$MAIN_HTTP"
init
run_test "$MAIN_HTTP"
chain33_RpcTestRst game "$CASE_ERR"
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
CASE_ERR=""
guess_admin_addr=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
guess_user1_addr=1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM
guess_user2_addr=17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN
......@@ -20,103 +18,38 @@ eventId=""
txhash=""
guess_game_start() {
echo "========== # guess start tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"Start", "payload":{"topic":"WorldCup Final","options":"A:France;B:Claodia","category":"football","maxBetsOneTime":10000000000,"maxBetsNumber":100000000000,"devFeeFactor":5,"devFeeAddr":"1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7","platFeeFactor":5,"platFeeAddr":"1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX"}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
eventId="${txhash}"
echo "eventId $eventId"
echo "========== # guess start tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
}
guess_game_bet() {
local priv=$1
local opt=$2
echo "========== # guess bet tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"Bet", "payload":{"gameID":"'"${eventId}"'","option":"'"${opt}"'", "betsNum":500000000}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "${priv}" ${MAIN_HTTP}
echo "========== # guess bet tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "${priv}" ${MAIN_HTTP} "$FUNCNAME"
}
guess_game_stop() {
echo "========== # guess stop tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"StopBet", "payload":{"gameID":"'"${eventId}"'"}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP}
echo "========== # guess stop tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
}
guess_game_publish() {
echo "========== # guess publish tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"Publish", "payload":{"gameID":"'"${eventId}"'","result":"A"}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP}
echo "========== # guess publish tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
}
guess_game_abort() {
echo "========== # guess abort tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"Abort", "payload":{"gameID":"'"${eventId}"'"}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP}
echo "========== # guess abort tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
}
guess_QueryGameByID() {
local event_id=$1
local status=$2
echo "========== # guess QueryGameByID begin =========="
local req='"method":"Chain33.Query", "params":[{"execer":"guess","funcName":"QueryGameByID","payload":{"gameID":"'"$event_id"'"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.result|has("game")) and (.result.game.status == '"$status"')' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
echo "========== # guess QueryGameByID end =========="
local req='{"method":"Chain33.Query", "params":[{"execer":"guess","funcName":"QueryGameByID","payload":{"gameID":"'"$event_id"'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.result|has("game")) and (.result.game.status == '"$status"')' "$FUNCNAME"
}
init() {
......@@ -132,10 +65,7 @@ init() {
echo "guess_addr=$guess_addr"
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM
chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "guess11" "${main_ip}"
#17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN
chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "guess22" "$main_ip"
local guess1="1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM"
......@@ -148,14 +78,12 @@ init() {
chain33_applyCoins "$guess2" 12000000000 "${main_ip}"
chain33_QueryBalance "${guess2}" "$main_ip"
else
# tx fee
chain33_applyCoins "$guess1" 1000000000 "${main_ip}"
chain33_QueryBalance "${guess1}" "$main_ip"
chain33_applyCoins "$guess2" 1000000000 "${main_ip}"
chain33_QueryBalance "${guess2}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "guess11" "$para_ip"
chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "guess22" "$para_ip"
......@@ -174,7 +102,6 @@ init() {
}
function run_test() {
#导入地址私钥
chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "user1" "$MAIN_HTTP"
chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "user2" "$MAIN_HTTP"
......@@ -320,7 +247,6 @@ function main() {
init
run_test
chain33_RpcTestRst guess "$CASE_ERR"
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
......@@ -7,67 +8,24 @@ MAIN_HTTP=""
addr_A=19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3
addr_B=1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD
# shellcheck source=/dev/null
source ../dapp-test-common.sh
hashlock_lock() {
local secret=$1
echo "========== # hashlock lock tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"hashlock","actionName":"HashlockLock", "payload":{"secret":"'"${secret}"'","amount":1000000000, "time":75,"toAddr":"'"${addr_B}"'", "returnAddr":"'"${addr_A}"'","fee":100000000}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" ${MAIN_HTTP}
#echo "txHash ${txhash}"
echo "========== # hashlock lock tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" ${MAIN_HTTP} "$FUNCNAME"
}
hashlock_send() {
local secret=$1
echo "========== # hashlock send tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"hashlock","actionName":"HashlockSend", "payload":{"secret":"'"${secret}"'","fee":100000000}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0xb76a398c3901dfe5c7335525da88fda4df24c11ad11af4332f00c0953cc2910f" ${MAIN_HTTP}
#echo "txHash ${txhash}"
echo "========== # hashlock send tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "0xb76a398c3901dfe5c7335525da88fda4df24c11ad11af4332f00c0953cc2910f" ${MAIN_HTTP} "$FUNCNAME"
}
hashlock_unlock() {
local secret=$1
echo "========== # hashlock unlock tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"hashlock","actionName":"HashlockUnlock", "payload":{"secret":"'"${secret}"'","fee":100000000}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" ${MAIN_HTTP}
#echo "txHash ${txhash}"
echo "========== # hashlock unlock tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" ${MAIN_HTTP} "$FUNCNAME"
}
init() {
......@@ -80,10 +38,7 @@ init() {
fi
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3
chain33_ImportPrivkey "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" "19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3" "hashlock1" "${main_ip}"
#1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD
chain33_ImportPrivkey "0xb76a398c3901dfe5c7335525da88fda4df24c11ad11af4332f00c0953cc2910f" "1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD" "hashlock2" "$main_ip"
local hashlock1="19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3"
......@@ -129,10 +84,8 @@ function run_test() {
hashlock_send "abc"
chain33_QueryBalance "$addr_B" "${MAIN_HTTP}"
hashlock_unlock "abc"
hashlock_lock "aef"
chain33_QueryBalance "$addr_A" "${MAIN_HTTP}"
sleep 5
hashlock_unlock "aef"
chain33_BlockWait 1 ${MAIN_HTTP}
......@@ -140,13 +93,12 @@ function run_test() {
}
function main() {
MAIN_HTTP="$1"
chain33_RpcTestBegin hashlock
MAIN_HTTP="$1"
echo "ip=$MAIN_HTTP"
init
run_test
chain33_RpcTestRst hashlock "$CASE_ERR"
}
......
......@@ -8,6 +8,7 @@ import (
_ "github.com/33cn/plugin/plugin/dapp/dposvote" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/echo" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/evm" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/exchange" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/game" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/guess" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/hashlock" //auto gen
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source ../dapp-test-common.sh
......@@ -12,11 +11,6 @@ function init() {
beneficiary_key=0xf146df80206194c81e0b3171db6aa40c7ad6182a24560698d4871d4dc75223ce
beneficiary=1DwHQp8S7RS9krQTyrqePxRyvaLcuoQGks
chain33_applyCoins "${beneficiary}" 10000000000 "${MAIN_HTTP}"
#paracross_get_money 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
#//beneficiary=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
#beneficiary_key=0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01
#owner=14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
#owner_key=CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944
echo "ipara=$ispara"
manager_name="manage"
exec_name="jsvm"
......@@ -40,55 +34,30 @@ function init() {
}
function configJSCreator() {
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${manager_name}'","actionName":"Modify","payload":{"key":"js-creator","op":"add", "value" : "'${beneficiary}'"}}]}'
echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${super_manager}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'${manager_name}'","actionName":"Modify","payload":{"key":"js-creator","op":"add","value":"'${beneficiary}'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${super_manager}" "${MAIN_HTTP}"
}
function createJSContract() {
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${exec_name}'","actionName":"Create","payload":{"name":"'${game}'","code":"'${jsCode}'"}}]}'
echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${beneficiary_key}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'${exec_name}'","actionName":"Create","payload":{"name":"'${game}'","code":"'${jsCode}'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${beneficiary_key}" "${MAIN_HTTP}"
}
function callJS() {
#the_exec=
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${user_game}'","actionName":"Call","payload":{"name":"'${game}'","funcname":"hello", "args" : "{}"}}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${beneficiary_key}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'${user_game}'","actionName":"Call","payload":{"name":"'${game}'","funcname":"hello","args":"{}"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${beneficiary_key}" "${MAIN_HTTP}"
}
function queryJS() {
req='{"jsonrpc": "2.0", "method" : "Chain33.Query" , "params":[{"execer":"'${user_game}'","funcName":"Query","payload":{"name":"'${game}'","funcname":"hello", "args" : "{}"}}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"Chain33.Query","params":[{"execer":"'${user_game}'","funcName":"Query","payload":{"name":"'${game}'","funcname":"hello","args":"{}"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME"
}
function run_testcases() {
configJSCreator
createJSContract
callJS
queryJS
......@@ -96,13 +65,11 @@ function run_testcases() {
function rpc_test() {
chain33_RpcTestBegin js
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
init
run_testcases
chain33_RpcTestRst js "$CASE_ERR"
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
lottery_addCreator_unsignedTx="0a066d616e616765123c0a3a0a0f6c6f74746572792d63726561746f721222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a0361646420a08d0630c788b8f7ccbadbc0703a223151344e687572654a784b4e4266373164323642394a336642516f5163666d657a32"
......@@ -29,18 +28,15 @@ init() {
if [[ $ispara == true ]]; then
lottExecAddr=$(curl -ksd '{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"user.p.para.lottery"}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "${lottery_addCreator_unsignedTx_para}" "${lottery_creator_priv}" ${MAIN_HTTP}
chain33_SignAndSendTx "${lottery_addCreator_unsignedTx_para}" "${lottery_creator_priv}" ${MAIN_HTTP}
else
lottExecAddr=$(curl -ksd '{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"lottery"}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "${lottery_addCreator_unsignedTx}" "${lottery_creator_priv}" ${MAIN_HTTP}
chain33_SignAndSendTx "${lottery_addCreator_unsignedTx}" "${lottery_creator_priv}" ${MAIN_HTTP}
fi
echo "lottExecAddr=$lottExecAddr"
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#1FLh9wBS2rat1mUS4G95hRpJt6yHYy5nHF
chain33_ImportPrivkey "0x8223b757a5d0f91b12e7af3b9666ca33be47fe63e1502987b0537089aaf90bc1" "1FLh9wBS2rat1mUS4G95hRpJt6yHYy5nHF" "lottery1" "${main_ip}"
#1UWE6NfXPR7eNAjYgT4HMERp7cMMi486E
chain33_ImportPrivkey "0xbfccb96690e0a1f89748b321f85b03e14bda0cb3d5d19f255ff0b9b0ffb624b3" "1UWE6NfXPR7eNAjYgT4HMERp7cMMi486E" "lottery2" "$main_ip"
local ACCOUNT_A="1FLh9wBS2rat1mUS4G95hRpJt6yHYy5nHF"
......@@ -53,14 +49,12 @@ init() {
chain33_applyCoins "$ACCOUNT_B" 12000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_B}" "$main_ip"
else
# tx fee
chain33_applyCoins "$ACCOUNT_A" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$main_ip"
chain33_applyCoins "$ACCOUNT_B" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_B}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0x8223b757a5d0f91b12e7af3b9666ca33be47fe63e1502987b0537089aaf90bc1" "1FLh9wBS2rat1mUS4G95hRpJt6yHYy5nHF" "lottery1" "$para_ip"
chain33_ImportPrivkey "0xbfccb96690e0a1f89748b321f85b03e14bda0cb3d5d19f255ff0b9b0ffb624b3" "1UWE6NfXPR7eNAjYgT4HMERp7cMMi486E" "lottery2" "$para_ip"
......@@ -74,15 +68,11 @@ init() {
lottery_LotteryCreate() {
#创建交易
priv=$1
resp=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryCreate",
"payload":{"purBlockNum":'"$purNum"',"drawBlockNum":'"$drawNum"', "opRewardRatio":'"$opRatio"',"devRewardRatio":'"$devRatio"',"fee":1000000}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[[ $ok == null ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryCreate","payload":{"purBlockNum":'"$purNum"',"drawBlockNum":'"$drawNum"', "opRewardRatio":'"$opRatio"',"devRewardRatio":'"$devRatio"',"fee":1000000}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SignRawTx "${rawTx}" "${priv}" ${MAIN_HTTP}
chain33_SignAndSendTx "${RETURN_RESP}" "${priv}" ${MAIN_HTTP}
gID="${RAW_TX_HASH}"
echo "gameID $gID"
......@@ -94,111 +84,78 @@ lottery_LotteryBuy() {
amount=$2
number=$3
way=$4
resp=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryBuy",
"payload":{"lotteryId":"'"$gID"'","amount":'"$amount"',"number":'"$number"',"way":'"$way"',"fee":1000000}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[[ $ok == null ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryBuy","payload":{"lotteryId":"'"$gID"'","amount":'"$amount"',"number":'"$number"',"way":'"$way"',"fee":1000000}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SignRawTx "${rawTx}" "${priv}" ${MAIN_HTTP}
chain33_SignAndSendTx "${RETURN_RESP}" "${priv}" ${MAIN_HTTP}
}
lottery_LotteryDraw() {
#创建交易
priv=$1
resp=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryDraw",
"payload":{"lotteryId":"'"$gID"'","fee":1000000}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[[ $ok == null ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryDraw","payload":{"lotteryId":"'"$gID"'","fee":1000000}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SignRawTx "${rawTx}" "${priv}" ${MAIN_HTTP}
chain33_SignAndSendTx "${RETURN_RESP}" "${priv}" ${MAIN_HTTP}
}
lottery_LotteryClose() {
#创建交易
priv=$1
resp=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryClose",
"payload":{"lotteryId":"'"$gID"'","fee":1000000}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[[ $ok == null ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"lottery","actionName":"LotteryClose","payload":{"lotteryId":"'"$gID"'","fee":1000000}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SignRawTx "${rawTx}" "${priv}" ${MAIN_HTTP}
chain33_SignAndSendTx "${RETURN_RESP}" "${priv}" ${MAIN_HTTP}
}
lottery_GetLotteryNormalInfo() {
gameID=$1
addr=$2
execer="lottery"
funcName="GetLotteryNormalInfo"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.purBlockNum == "'"$purNum"'") and (.result.drawBlockNum == "'"$drawNum"'") and (.result.createAddr == "'"$addr"'") and (.result.opRewardRatio == "'"$opRatio"'") and (.result.devRewardRatio == "'"$devRatio"'") and (.result | [has("createHeight"), true] | unique | length == 1)' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryNormalInfo","payload":{"lotteryId":"'"$gameID"'"}}]}'
resok='(.error|not) and (.result.purBlockNum == "'"$purNum"'") and (.result.drawBlockNum == "'"$drawNum"'") and (.result.createAddr == "'"$addr"'") and (.result.opRewardRatio == "'"$opRatio"'") and (.result.devRewardRatio == "'"$devRatio"'") and (.result | [has("createHeight"), true] | unique | length == 1)'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
lottery_GetLotteryCurrentInfo() {
gameID=$1
status=$2
amount=$3
execer="lottery"
funcName="GetLotteryCurrentInfo"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.status == '"$status"') and (.result.buyAmount == "'"$amount"'") and (.result | [has("lastTransToPurState", "lastTransToDrawState", "totalPurchasedTxNum", "round", "luckyNumber", "lastTransToPurStateOnMain", "lastTransToDrawStateOnMain", "purBlockNum", "drawBlockNum", "missingRecords", "totalAddrNum"), true] | unique | length == 1)' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryCurrentInfo","payload":{"lotteryId":"'"$gameID"'"}}]}'
resok='(.error|not) and (.result.status == '"$status"') and (.result.buyAmount == "'"$amount"'") and (.result | [has("lastTransToPurState", "lastTransToDrawState", "totalPurchasedTxNum", "round", "luckyNumber", "lastTransToPurStateOnMain", "lastTransToDrawStateOnMain", "purBlockNum", "drawBlockNum", "missingRecords", "totalAddrNum"), true] | unique | length == 1)'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME" ".result.luckyNumber"
if [[ $status == 3 ]]; then
luckyNumber=$(echo "${resp}" | jq -r ".result.luckyNumber")
luckyNumber=$RETURN_RESP
echo -e "######\\n luckyNumber is $luckyNumber \\n######"
fi
echo "end"
}
lottery_GetLotteryPurchaseAddr() {
gameID=$1
count=$2
execer="lottery"
funcName="GetLotteryPurchaseAddr"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.address | length == '"$count"')' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryPurchaseAddr","payload":{"lotteryId":"'"$gameID"'"}}]}'
resok='(.error|not) and (.result.address | length == '"$count"')'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
lottery_GetLotteryHistoryLuckyNumber() {
gameID=$1
count=$2
lucky=$3
execer="lottery"
funcName="GetLotteryHistoryLuckyNumber"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].number == "'"$lucky"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryHistoryLuckyNumber","payload":{"lotteryId":"'"$gameID"'"}}]}'
resok='(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].number == "'"$lucky"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
lottery_GetLotteryRoundLuckyNumber() {
gameID=$1
round=$2
lucky=$3
execer="lottery"
funcName="GetLotteryRoundLuckyNumber"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'", "round":['"$round"']}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.records | length == 1) and (.result.records[0].number == "'"$lucky"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryRoundLuckyNumber","payload":{"lotteryId":"'"$gameID"'", "round":['"$round"']}}]}'
resok='(.error|not) and (.result.records | length == 1) and (.result.records[0].number == "'"$lucky"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
lottery_GetLotteryHistoryBuyInfo() {
......@@ -206,13 +163,9 @@ lottery_GetLotteryHistoryBuyInfo() {
addr=$2
count=$3
number=$4
execer="lottery"
funcName="GetLotteryHistoryBuyInfo"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].number == "'"$number"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryHistoryBuyInfo","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'"}}]}'
resok='(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].number == "'"$number"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
lottery_GetLotteryBuyRoundInfo() {
......@@ -221,13 +174,9 @@ lottery_GetLotteryBuyRoundInfo() {
round=$3
count=$4
number=$5
execer="lottery"
funcName="GetLotteryBuyRoundInfo"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'", "round":'"$round"'}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].number == "'"$number"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryBuyRoundInfo","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'", "round":'"$round"'}}]}'
resok='(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].number == "'"$number"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
lottery_GetLotteryHistoryGainInfo() {
......@@ -235,13 +184,9 @@ lottery_GetLotteryHistoryGainInfo() {
addr=$2
count=$3
amount=$4
execer="lottery"
funcName="GetLotteryHistoryGainInfo"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].addr == "'"$addr"'") and (.result.records[0].buyAmount == "'"$amount"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryHistoryGainInfo","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'"}}]}'
resok='(.error|not) and (.result.records | length == '"$count"') and (.result.records[0].addr == "'"$addr"'") and (.result.records[0].buyAmount == "'"$amount"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
lottery_GetLotteryRoundGainInfo() {
......@@ -249,13 +194,9 @@ lottery_GetLotteryRoundGainInfo() {
addr=$2
round=$3
amount=$4
execer="lottery"
funcName="GetLotteryRoundGainInfo"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'", "round":'"$round"'}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.addr == "'"$addr"'") and (.result.round == "'"$round"'") and (.result.buyAmount == "'"$amount"'") and (.result | [has("fundAmount"), true] | unique | length == 1)' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"lottery","funcName":"GetLotteryRoundGainInfo","payload":{"lotteryId":"'"$gameID"'", "addr":"'"$addr"'", "round":'"$round"'}}]}'
resok='(.error|not) and (.result.addr == "'"$addr"'") and (.result.round == "'"$round"'") and (.result.buyAmount == "'"$amount"'") and (.result | [has("fundAmount"), true] | unique | length == 1)'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
function run_testcases() {
......@@ -312,13 +253,12 @@ function run_testcases() {
}
function main() {
chain33_RpcTestBegin lottery
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
chain33_RpcTestBegin lottery
init
run_testcases
chain33_RpcTestRst lottery "$CASE_ERR"
}
......
......@@ -10,18 +10,9 @@ source ../dapp-test-common.sh
Symbol="BTY"
Asset="coins"
#PrivKeyA="0x06c0fa653c719275d1baa365c7bc0b9306447287499a715b541b930482eaa504"
#PrivKeyB="0x4c8663cded61093af20339ae038b3c6bfa58a33e65874a655022f82eaf3f2fa0"
#PrivKeyC="0x9abcf378b397682109c174b37a45bfc8a459c9514dd2ef719e22a9815373047d"
#PrivKeyD="0xbf8f865a03fec64f30d2243847807e88d2dbc8104e77925e4fc11c4d4380f3da"
#PrivKeyE="0x5b8ca316cf073aa94f1056a9e3f6e0b9a9ec11ae45862d58c7a09640b4d55302"
#PrivKeyGen="CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944"
AddrA="1C5xK2ytuoFqxmVGMcyz9XFKFWcDA8T3rK"
AddrB="1LDGrokrZjo1HtSmSnw8ef3oy5Vm1nctbj"
#AddrC="1DkrXbz2bK6XMpY4v9z2YUnhwWTXT6V5jd"
#AddrD="166po3ghRbRu53hu8jBBQzddp7kUJ9Ynyf"
AddrE="1KHwX7ZadNeQDjBGpnweb4k2dqj2CWtAYo"
#GenAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
GenAddr="15wcitPEu1X1TBfrGfwN8GTkNTJoCmGc75"
PrivKeyGen="0x295710fa409bd0b0bf928efa0994645edfe80a247d89c1e1637f90dc5e303f5e"
......@@ -29,8 +20,7 @@ PrivKeyGen="0x295710fa409bd0b0bf928efa0994645edfe80a247d89c1e1637f90dc5e303f5e"
multisigExecAddr=""
multisigAccAddr=""
execName=""
#execCoins=""
#symbolCoins=""
function init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ipara=$ispara"
......@@ -70,169 +60,115 @@ function init() {
function multisig_AccCreateTx() {
echo "========== # multisig_AccCreateTx begin =========="
txHex=$(curl -ksd '{"method":"multisig.MultiSigAccCreateTx","params":[{"owners":[{"ownerAddr":"'$AddrA'","weight":20},{"ownerAddr":"'$AddrB'","weight":10},{"ownerAddr":"'$GenAddr'","weight":30}],"requiredWeight":15,"dailyLimit":{"symbol":"'$Symbol'","execer":"'$Asset'","dailyLimit":1000000000}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#查看创建的多重签名地址是否ok
data=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccCount","payload":{}}]}' ${MAIN_HTTP} | jq -r ".result.data")
echo "$data"
#获取创建的多重签名地址
multisigAccAddr=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccounts","payload":{"start":"0","end":"0"}}]}' ${MAIN_HTTP} | jq -r ".result.address[0]")
echo "multisigAccAddr=$multisigAccAddr"
#多重签名地址查询具体信息
result1=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccountInfo","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}' ${MAIN_HTTP})
ok1=$(jq '(.result.createAddr == "'$GenAddr'")' <<<"$result1")
[ "$ok1" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
result=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAllAddress","payload":{"multiSigAccAddr":"'$GenAddr'"}}]}' ${MAIN_HTTP})
ok=$(jq '(.result.address[0] == "'"$multisigAccAddr"'")' <<<"$result")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
#多重签名地址查询具体信息
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccountInfo","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}'
resok='(.result.createAddr == "'$GenAddr'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAllAddress","payload":{"multiSigAccAddr":"'$GenAddr'"}}]}'
resok='(.result.address[0] == "'"$multisigAccAddr"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
echo "========== # multisig_AccCreateTx ok =========="
}
#多重签名地址转入操作
function multisig_TransferInTx() {
echo "========== # multisig_TransferInTx begin =========="
#首先转账到multisig合约中
txHex=$(curl -ksd '{"method":"Chain33.CreateRawTransaction","params":[{"to":"'"$multisigExecAddr"'","amount":5000000000,"fee":1,"note":"12312","execName":"'"$execName"'"}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#转账到multisigAccAddr地址中
txHex=$(curl -ksd '{"method":"multisig.MultiSigAccTransferInTx","params":[{"symbol":"'$Symbol'","amount":4000000000,"note":"test ","execname":"'$Asset'","to":"'"$multisigAccAddr"'"}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#查询multisigAccAddr地址资产信息
accountasset=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAssets","payload":{"multiSigAddr":"'"$multisigAccAddr"'","assets":{"execer":"'$Asset'","symbol":"'$Symbol'"},"isAll":false}}]}' ${MAIN_HTTP} | jq -r ".result.accAssets[0]")
echo "multisig_TransferInTx:=${accountasset}"
ok=$(jq '(.assets.execer == "'$Asset'") and (.assets.symbol == "'$Symbol'") and (.account.frozen == "4000000000")' <<<"$accountasset")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAssets","payload":{"multiSigAddr":"'"$multisigAccAddr"'","assets":{"execer":"'$Asset'","symbol":"'$Symbol'"},"isAll":false}}]}'
resok='(.result.accAssets[0].assets.execer == "'$Asset'") and (.result.accAssets[0].assets.symbol == "'$Symbol'") and (.result.accAssets[0].account.frozen == "4000000000")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
echo "========== # multisig_TransferInTx end =========="
}
function multisig_TransferOutTx() {
echo "========== # multisig_TransferOutTx begin =========="
#由GenAddr账户签名从multisigAccAddr账户转出2000000000到AddrB
txHex=$(curl -ksd '{"method":"multisig.MultiSigAccTransferOutTx","params":[{"symbol":"'$Symbol'","amount":2000000000,"note":"test ","execname":"coins","to":"'$AddrB'","from":"'"$multisigAccAddr"'"}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#查询AddrB账户在multisig合约下有2000000000
accountasset=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAssets","payload":{"multiSigAddr":"1LDGrokrZjo1HtSmSnw8ef3oy5Vm1nctbj","assets":{"execer":"coins","symbol":"'$Symbol'"},"isAll":false}}]}' ${MAIN_HTTP} | jq -r ".result.accAssets[0]")
echo "multisig_TransferOutTx:=${accountasset}"
ok=$(jq '(.assets.execer == "'$Asset'") and (.assets.symbol == "'$Symbol'") and (.account.balance == "2000000000")' <<<"$accountasset")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAssets","payload":{"multiSigAddr":"1LDGrokrZjo1HtSmSnw8ef3oy5Vm1nctbj","assets":{"execer":"coins","symbol":"'$Symbol'"},"isAll":false}}]}'
resok='(.result.accAssets[0].assets.execer == "'$Asset'") and (.result.accAssets[0].assets.symbol == "'$Symbol'") and (.result.accAssets[0].account.balance == "2000000000")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
#查询multisigAccAddr地址资产信息,减少了2000000000
accountasset=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAssets","payload":{"multiSigAddr":"'"$multisigAccAddr"'","assets":{"execer":"'$Asset'","symbol":"'$Symbol'"},"isAll":false}}]}' ${MAIN_HTTP} | jq -r ".result.accAssets[0]")
ok=$(jq '(.assets.execer == "'$Asset'") and (.assets.symbol == "'$Symbol'") and (.account.frozen == "2000000000")' <<<"$accountasset")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccAssets","payload":{"multiSigAddr":"'"$multisigAccAddr"'","assets":{"execer":"'$Asset'","symbol":"'$Symbol'"},"isAll":false}}]}'
resok='(.result.accAssets[0].assets.execer == "'$Asset'") and (.result.accAssets[0].assets.symbol == "'$Symbol'") and (.result.accAssets[0].account.frozen == "2000000000")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
echo "========== # multisig_TransferOutTx end =========="
}
function multisig_OwnerOperateTx() {
echo "========== # multisig_OwnerOperateTx begin =========="
#通过GenAddr账户添加AddrE到多重签名账户的owner
txHex=$(curl -ksd '{"method":"multisig.MultiSigOwnerOperateTx","params":[{"multiSigAccAddr":"'"$multisigAccAddr"'","newOwner":"'$AddrE'","newWeight":8,"operateFlag":1}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
#查询多重签名账户的信息中有AddrE
owner=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccountInfo","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}' ${MAIN_HTTP} | jq -r ".result.owners[3]")
ok=$(jq '(.ownerAddr == "'$AddrE'")' <<<"$owner")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
#查询多重签名账户的信息中有AddrEmultisig_TransferInTx
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccountInfo","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}'
resok='(.result.owners[3].ownerAddr == "'$AddrE'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
#删除多重签名账户的信息中owner AddrE
txHex=$(curl -ksd '{"method":"multisig.MultiSigOwnerOperateTx","params":[{"multiSigAccAddr":"'"$multisigAccAddr"'","oldOwner":"'$AddrE'","operateFlag":2}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#修改多重签名账户中owner AddrA的weight为30
txHex=$(curl -ksd '{"method":"multisig.MultiSigOwnerOperateTx","params":[{"multiSigAccAddr":"'"$multisigAccAddr"'","oldOwner":"'$AddrA'","newWeight":30,"operateFlag":3}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#将多重签名账户中owner AddrA的地址替换成AddrE
txHex=$(curl -ksd '{"method":"multisig.MultiSigOwnerOperateTx","params":[{"multiSigAccAddr":"'"$multisigAccAddr"'","oldOwner":"'$AddrA'","newOwner":"'$AddrE'","operateFlag":4}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#查询多重签名账户的信息中有AddrE并且weight为30
owner=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccountInfo","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}' ${MAIN_HTTP} | jq -r ".result.owners[0]")
ok=$(jq '(.ownerAddr == "'$AddrE'") and (.weight == "30")' <<<"$owner")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccountInfo","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}'
resok='(.result.owners[0].ownerAddr == "'$AddrE'") and (.result.owners[0].weight == "30")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
echo "========== # multisig_OwnerOperateTx end =========="
}
function multisig_AccOperateTx() {
echo "========== # multisig_AccOperateTx begin =========="
#修改每日限额的值为 Symbol:Asset dailyLimit=1200000000
txHex=$(curl -ksd '{"method":"multisig.MultiSigAccOperateTx","params":[{"multiSigAccAddr":"'"$multisigAccAddr"'","dailyLimit":{"symbol":"'$Symbol'","execer":"'$Asset'","dailyLimit":1200000000}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#增加资产的配置 HYB:token dailyLimit=1000000000
txHex=$(curl -ksd '{"method":"multisig.MultiSigAccOperateTx","params":[{"multiSigAccAddr":"'"$multisigAccAddr"'","dailyLimit":{"symbol":"HYB","execer":"token","dailyLimit":1000000000}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#修改RequiredWeight=16
txHex=$(curl -ksd '{"method":"multisig.MultiSigAccOperateTx","params":[{"multiSigAccAddr":"'"$multisigAccAddr"'","newRequiredWeight":16,"operateFlag":true}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignRawTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTx "$txHex" "$PrivKeyGen" ${MAIN_HTTP}
#获取本多重签名账户上的交易数,已经对应的交易信息
data=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccTxCount","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}' ${MAIN_HTTP} | jq -r ".result")
ok=$(jq '(.data != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
#获取本多重签名账户上的交易数,通过交易交易id获取交易信息
data=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccTxCount","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}' ${MAIN_HTTP} | jq -r ".result")
ok=$(jq '(.data != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigAccTxCount","payload":{"multiSigAccAddr":"'"$multisigAccAddr"'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.result.data != null)' "$FUNCNAME"
#查询多重签名账户信息中
data=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigTxInfo","payload":{"multiSigAddr":"'"$multisigAccAddr"'","txId":"7"}}]}' ${MAIN_HTTP} | jq -r ".result")
ok=$(jq '(.txid == "7") and (.executed == true) and (.multiSigAddr == "'"$multisigAccAddr"'") ' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"Chain33.Query","params":[{"execer":"multisig","funcName":"MultiSigTxInfo","payload":{"multiSigAddr":"'"$multisigAccAddr"'","txId":"7"}}]}'
resok='(.result.txid == "7") and (.result.executed == true) and (.result.multiSigAddr == "'"$multisigAccAddr"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
echo "========== # multisig_AccOperateTx end =========="
}
function run_test() {
......@@ -241,7 +177,6 @@ function run_test() {
multisig_TransferOutTx
multisig_OwnerOperateTx
multisig_AccOperateTx
}
function main() {
......@@ -251,8 +186,7 @@ function main() {
init
run_test
chain33_RpcTestRst multisi "$CASE_ERR"
}
main "$1"
chain33_debug_function main "$1"
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
MAIN_HTTP=""
oracle_addPublisher_unsignedTx="0a066d616e61676512410a3f0a146f7261636c652d7075626c6973682d6576656e741222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a0361646420a08d0630e6b685d696ee9394163a223151344e687572654a784b4e4266373164323642394a336642516f5163666d657a32"
......@@ -8,7 +9,6 @@ oracle_publisher_key="4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C72
eventId=""
txhash=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
oracle_AddPublisher() {
......@@ -16,88 +16,52 @@ oracle_AddPublisher() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ispara=$ispara"
if [ "$ispara" == true ]; then
chain33_SignRawTx "${oracle_addPublisher_unsignedTx_para}" "${oracle_publisher_key}" "${MAIN_HTTP}"
chain33_SignAndSendTx "${oracle_addPublisher_unsignedTx_para}" "${oracle_publisher_key}" "${MAIN_HTTP}"
else
chain33_SignRawTx "${oracle_addPublisher_unsignedTx}" "${oracle_publisher_key}" "${MAIN_HTTP}"
chain33_SignAndSendTx "${oracle_addPublisher_unsignedTx}" "${oracle_publisher_key}" "${MAIN_HTTP}"
fi
}
oracle_publish_transaction() {
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventPublish","payload":{"type":"football", "subType":"Premier League","time":1747814996,"content":"test","introduction":"test"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${oracle_publisher_key}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventPublish","payload":{"type":"football", "subType":"Premier League","time":1747814996,"content":"test","introduction":"test"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${MAIN_HTTP}"
eventId="${txhash}"
echo "eventId $eventId"
}
oracle_prePublishResult_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPrePublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"0:1"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${oracle_publisher_key}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPrePublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"0:1"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${MAIN_HTTP}"
}
oracle_eventAbort_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventAbort","payload":{"eventID":"'"$event_id"'"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${oracle_publisher_key}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventAbort","payload":{"eventID":"'"$event_id"'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${MAIN_HTTP}"
}
oracle_resultAbort_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultAbort","payload":{"eventID":"'"$event_id"'"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${oracle_publisher_key}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultAbort","payload":{"eventID":"'"$event_id"'"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${MAIN_HTTP}"
}
oracle_publishResult_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"1:1"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${oracle_publisher_key}" "${MAIN_HTTP}"
req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"1:1"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${MAIN_HTTP}"
}
oracle_QueryOraclesByID() {
event_id=$1
local req='"method":"Chain33.Query", "params":[{"execer":"oracle","funcName":"QueryOraclesByIDs","payload":{"eventID":["'"$event_id"'"]}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.status[0] | [has("eventID", "status", "type", "subType", "source"),true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query", "params":[{"execer":"oracle","funcName":"QueryOraclesByIDs","payload":{"eventID":["'"$event_id"'"]}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.status[0] | [has("eventID", "status", "type", "subType", "source"),true] | unique | length == 1)' "$FUNCNAME"
}
function run_test() {
......@@ -134,14 +98,12 @@ function run_test() {
}
function main() {
chain33_RpcTestBegin oracle
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
chain33_RpcTestBegin oracle
run_test
chain33_RpcTestRst oracle "$CASE_ERR"
}
main "$1"
chain33_debug_function main "$1"
......@@ -33,7 +33,7 @@ checkItem = ["balance"]
#send para asset bty
[[TransferCase]]
id = "btyParaTrans"
command = "send para asset_transfer --ptitle user.p.test. -a 0.1 -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
command = "send para asset_transfer --paraName user.p.test. -a 0.1 -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
from = "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
#复用coins的transfer用例,此处to地址比较特殊,为平行链paracross合约的地址
to = "16zsMh7mvNDKPG6E9NVrPhw6zL93gWsTpR"
......@@ -55,7 +55,7 @@ dep = ["tokenFinish"]
#send para asset token PT
[[TransferCase]]
id = "tokenParaTrans"
command = "send para asset_transfer --ptitle user.p.test. -s PT -a 1 -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
command = "send para asset_transfer --paraName user.p.test. -s PT -a 1 -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
from = "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
#复用coins的transfer用例,此处to地址比较特殊,为平行链paracross合约的地址
to = "16zsMh7mvNDKPG6E9NVrPhw6zL93gWsTpR"
......
......@@ -336,11 +336,11 @@ function para_cross_transfer_withdraw() {
echo "${hash}"
query_tx "${CLI}" "${hash}"
hash=$(${CLI} send para asset_transfer --ptitle user.p.para. -a 1.4 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01)
hash=$(${CLI} send para asset_transfer --paraName user.p.para. -a 1.4 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01)
echo "${hash}"
query_tx "${PARA_CLI}" "${hash}"
hash2=$(${CLI} send para asset_withdraw --ptitle user.p.para. -a 0.7 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01)
hash2=$(${CLI} send para asset_withdraw --paraName user.p.para. -a 0.7 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01)
local times=200
while true; do
......@@ -361,6 +361,23 @@ function para_cross_transfer_withdraw() {
break
fi
done
echo "check asset transfer tx=$hash"
res=$(${CLI} para asset_txinfo -s "${hash}")
echo "$res"
succ=$(jq -r ".success" <<<"$res")
if [ "${succ}" != "true" ]; then
echo "para asset transfer tx report fail"
exit 1
fi
echo "check asset withdraw tx=$hash2"
res=$(${CLI} para asset_txinfo -s "${hash2}")
echo "$res"
succ=$(jq -r ".success" <<<"$res")
if [ "${succ}" != "true" ]; then
echo "para asset withdraw tx report fail"
exit 1
fi
}
function token_create_on_mainChain() {
......@@ -426,12 +443,12 @@ function para_cross_transfer_withdraw_for_token() {
query_tx "${MAIN_CLI}" "${hash}"
echo "=========== # 2.transfer asset to para chain ============="
hash=$(${CLI} send para asset_transfer --ptitle user.p.para. -s FZM -a 220 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
hash=$(${CLI} send para asset_transfer --paraName user.p.para. -s FZM -a 220 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
echo "${hash}"
query_tx "${MAIN_CLI}" "${hash}"
echo "=========== # 3.asset_withdraw from parachain ============="
${CLI} send para asset_withdraw --ptitle user.p.para. -a 111 -s FZM -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
${CLI} send para asset_withdraw --paraName user.p.para. -a 111 -s FZM -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
local times=100
while true; do
......
......@@ -14,3 +14,4 @@ help: ## Display this help screen
@printf "[command]\n"
@printf "[nodegroup]: create super node group if not create \n"
@printf "[wallet]: set node wallet private key if not set \n"
@printf "[miner]: unlock wallet to miner \n"
\ No newline at end of file
# 平行链授权节点一键式部署
## 需求
平行链申请超级节点步骤比较多,需要设置的地方也比较多,容易遗漏
## 使用
1. 把编译好的chain33,chain33-cli,chain33.toml,和chain33.para.toml和本脚本目录放到一起
1. 修改config文件配置项,每个配置项都有说明
1. make docker-compose 缺省启动
1. make docker-compose op=nodegroup 配置超级账户组
1. make docker-compose op=wallet 配置钱包开启共识
1. 系统缺省会把区块链数据从docker重映射到本地storage目录,以后默认启动历史数据不会丢失
1. make docker-compose down 停止当前平行链
## 系统重启
1. 系统重启使用 make docker-compose即可, 起来后 make docker-compose op=miner开启挖矿
\ No newline at end of file
paraName="test"
#genesisAccount=""
#genesisAmount=100000000
#mainStartHeight=4800000
#authAccount=()
#authPrikey=()
##docker8901端口暴露到宿主机的端口
#authPort=("18901" "18902" "18903" "18904")
#
##需要和chain33 主链保持一致
#superManager="['1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP']"
#
##nodegroup create
##申请超级账户需要在主链冻结币数量
#authFrozenCoins=0
#nodeGroupApplier=""
#applierPrikey=""
#superManagerPrikey=""
#平行链名字,这里不需要加user.p.前缀
paraName="test"
#### 测试链配置,主链配置需要把如下测试链配置屏蔽 ##########
#### 测试链配置四个节点例子,主链配置需要把如下测试链配置屏蔽 ##########
#创世账户
genesisAccount="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
#创世数量
genesisAmount=100000000
#从主链哪个高度开始同步区块
mainStartHeight=4000000
#平行链授权账户,这里的数量要和下面的authPrikey和authPort保持一致
authAccount=( "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4" "1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR" "1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k" "1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs")
#授权账户的私钥,为了导入钱包,自动开启共识挖矿
authPrikey=("0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" "0x19c069234f9d3e61135fefbeb7791b149cdf6af536f26bebb310d4cd22c3fee4" "0x7a80a1f75d7360c6123c32a78ecf978c1ac55636f87892df38d8b85a9aeff115" "0xcacb1f5d51700aea07fca2246ab43b0917d70405c65edea9b5063d72eb5c6b71")
#授权节点的宿主机端口
authPort=("18901" "18902" "18903" "18904")
#需要和chain33 主链保持一致
......@@ -32,8 +22,12 @@ superManager="['12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv']"
tokenApprs="['12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv']"
#nodegroup create
#超级账户创建
#授权账户申请需要在主链上冻结的BTY数量,申请之前需要chain33项目方沟通,需要chain33超级管理员审批通过
authFrozenCoins=0
#超级账户组申请者,需要事先在paracross合约转移必须的BTY,数量=申请的授权账户数量*authFrozenCoins
nodeGroupApplier="1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"
#超级账户组申请者私钥 签名交易使用
applierPrikey="0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b"
#超级管理员私钥,在主链上申请不需要填
superManagerPrikey="4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01"
......@@ -87,6 +87,13 @@ function para_import_wallet() {
./$CHAIN33_CLI --rpc_laddr "http://localhost:$port" wallet status
}
function para_unlock_wallet() {
for ((i = 0; i < ${#authPort[@]}; i++)); do
echo "=========== # para unlock wallet ${authPort[$i]}============="
./$CHAIN33_CLI --rpc_laddr "http://localhost:${authPort[$i]}" wallet unlock -p 1314fuzamei -t 0
done
}
function start() {
echo "=========== # docker-compose ps ============="
docker-compose ps
......@@ -175,6 +182,7 @@ EOF
volumes:
- "../storage/parachain$i/paradatadir:/root/paradatadir"
- "../storage/parachain$i/logs:/root/logs"
- "../storage/parachain$i/parawallet:/root/parawallet"
EOF
done
......@@ -260,6 +268,10 @@ function main() {
para_set_wallet
fi
if [ "$1" == "miner" ]; then
para_unlock_wallet
fi
echo "===============================parachain startup end========================================================="
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
CASE_ERR=""
UNIT_HTTP=""
IS_PARA=false
# shellcheck source=/dev/null
source ../dapp-test-common.sh
paracross_GetBlock2MainInfo() {
local height
height=$(curl -ksd '{"method":"paracross.GetBlock2MainInfo","params":[{"start":1,"end":3}]}' ${UNIT_HTTP} | jq -r ".result.items[1].height")
[ "$height" -eq 2 ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
}
function paracross_SignAndSend() {
local signedTx
local sendedTx
signedTx=$(curl -ksd '{"method":"Chain33.SignRawTx","params":[{"expire":"120s","fee":'"$1"',"privkey":"'"$2"'","txHex":"'"$3"'"}]}' ${UNIT_HTTP} | jq -r ".result")
#echo "signedTx:$signedTx"
sendedTx=$(curl -ksd '{"method":"Chain33.SendTransaction","params":[{"data":"'"$signedTx"'"}]}' ${UNIT_HTTP} | jq -r ".result")
echo "sendedTx:$sendedTx"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName": "GetBlock2MainInfo", "payload" : {"start":1,"end":3}}]}' ${UNIT_HTTP} '(.result.items[1].height == "2")' "$FUNCNAME"
}
function paracross_QueryParaBalance() {
......@@ -63,7 +47,6 @@ function paracross_QueryMainBalance() {
}
function paracross_Transfer_Withdraw_Inner() {
# 计数器,资产转移操作和取钱操作都成功才算成功,也就是 counter == 2
local count=0
#fromAddr 跨链资产转移地址
......@@ -80,8 +63,6 @@ function paracross_Transfer_Withdraw_Inner() {
local amount_should=27000
#withdraw_should 应取款金额
local withdraw_should=13000
#fee 交易费
#local fee=1000000
#平行链转移前余额
local para_balance_before
#平行链转移后余额
......@@ -108,9 +89,7 @@ function paracross_Transfer_Withdraw_Inner() {
#2 存钱到合约地址
tx_hash=$(curl -ksd '{"method":"Chain33.CreateRawTransaction","params":[{"to":"'"$paracross_addr"'","amount":'$amount_save'}]}' ${UNIT_HTTP} | jq -r ".result")
##echo "tx:$tx"
chain33_SignRawTx "$tx_hash" "$privkey" ${UNIT_HTTP}
#paracross_SignAndSend $fee "$privkey" "$tx_hash"
chain33_SignAndSendTx "$tx_hash" "$privkey" ${UNIT_HTTP}
#1. 查询资产转移前余额状态
para_balance_before=$(paracross_QueryParaBalance "$from_addr" "paracross")
......@@ -120,9 +99,7 @@ function paracross_Transfer_Withdraw_Inner() {
#3 资产从主链转移到平行链
tx_hash=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"'"$execer_name"'","actionName":"ParacrossAssetTransfer","payload":{"execName":"'"$execer_name"'","to":"'"$from_addr"'","amount":'$amount_should'}}]}' ${UNIT_HTTP} | jq -r ".result")
#echo "rawTx:$rawTx"
chain33_SignRawTx "$tx_hash" "$privkey" ${UNIT_HTTP}
#paracross_SignAndSend $fee "$privkey" "$tx_hash"
chain33_SignAndSendTx "$tx_hash" "$privkey" ${UNIT_HTTP}
#4 查询转移后余额状态
local times=100
......@@ -143,7 +120,6 @@ function paracross_Transfer_Withdraw_Inner() {
exit 1
fi
else
#echo "para_cross_transfer_withdraw success"
count=$((count + 1))
break
fi
......@@ -151,9 +127,7 @@ function paracross_Transfer_Withdraw_Inner() {
#5 取钱
tx_hash=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"'"$execer_name"'","actionName":"ParacrossAssetWithdraw","payload":{"IsWithdraw":true,"execName":"'"$execer_name"'","to":"'"$from_addr"'","amount":'$withdraw_should'}}]}' ${UNIT_HTTP} | jq -r ".result")
#echo "rawTx:$rawTx"
chain33_SignRawTx "$tx_hash" "$privkey" ${UNIT_HTTP}
#paracross_SignAndSend $fee "$privkey" "$tx_hash"
chain33_SignAndSendTx "$tx_hash" "$privkey" ${UNIT_HTTP}
#6 查询取钱后余额状态
local times=100
......@@ -165,7 +139,6 @@ function paracross_Transfer_Withdraw_Inner() {
#实际取钱金额
para_withdraw_real=$((para_balance_after - para_balance_withdraw_after))
main_withdraw_real=$((main_balance_withdraw_after - main_balance_after))
#echo $withdraw_real
if [ "$withdraw_should" != "$para_withdraw_real" ] || [ "$withdraw_should" != "$main_withdraw_real" ]; then
chain33_BlockWait 2 ${UNIT_HTTP}
times=$((times - 1))
......@@ -174,7 +147,6 @@ function paracross_Transfer_Withdraw_Inner() {
exit 1
fi
else
#echo "para_cross_transfer_withdraw success"
count=$((count + 1))
break
fi
......@@ -197,99 +169,44 @@ function paracross_Transfer_Withdraw() {
local execer_name="user.p.para.paracross"
paracross_Transfer_Withdraw_Inner "$from_addr" "$privkey" "$paracross_addr" "$execer_name"
}
function paracross_IsSync() {
local ok
if [ "$IS_PARA" == "true" ]; then
ok=$(curl -ksd '{"method":"paracross.IsSync","params":[]}' ${UNIT_HTTP} | jq -r ".result")
req='{"method":"paracross.IsSync","params":[]}'
else
ok=$(curl -ksd '{"method":"Chain33.IsSync","params":[]}' ${UNIT_HTTP} | jq -r ".result")
req='{"method":"Chain33.IsSync","params":[]}'
fi
[ "$ok" == true ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http "$req" ${UNIT_HTTP} '(.error|not)' "$FUNCNAME"
}
function paracross_ListTitles() {
local resp
local ok
local main_ip=${UNIT_HTTP//8901/8801}
resp=$(curl -ksd '{"method":"paracross.ListTitles","params":[]}' ${main_ip})
echo "$resp"
ok=$(jq '(.error|not) and (.result| [has("titles"),true])' <<<"$resp")
[ "$ok" == true ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName": "ListTitles", "payload" : {}}]}' ${main_ip} '(.error|not) and (.result| [has("titles"),true])' "$FUNCNAME"
}
function paracross_GetHeight() {
local resp
local ok
if [ "$IS_PARA" == "true" ]; then
resp=$(curl -ksd '{"method":"paracross.GetHeight","params":[]}' ${UNIT_HTTP})
#echo $resp
ok=$(jq '(.error|not) and (.result| [has("consensHeight"),true])' <<<"$resp")
[ "$ok" == true ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName": "GetHeight", "payload" : {}}]}' ${UNIT_HTTP} '(.error|not) and (.result| [has("consensHeight"),true])' "$FUNCNAME"
fi
}
function paracross_GetNodeGroupAddrs() {
local resp
local ok
resp=$(curl -ksd '{"method":"paracross.GetNodeGroupAddrs","params":[{"title":"user.p.para."}]}' ${UNIT_HTTP})
#echo $resp
ok=$(jq '(.error|not) and (.result| [has("key","value"),true])' <<<"$resp")
[ "$ok" == true ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeGroupAddrs","payload":{"title":"user.p.para."}}]}' ${UNIT_HTTP} '(.error|not) and (.result| [has("key","value"),true])' "$FUNCNAME"
}
function paracross_GetNodeGroupStatus() {
local resp
local ok
resp=$(curl -ksd '{"method":"paracross.GetNodeGroupStatus","params":[{"title":"user.p.para."}]}' ${UNIT_HTTP})
#echo $resp
ok=$(jq '(.error|not) and (.result| [has("status"),true])' <<<"$resp")
[ "$ok" == true ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeGroupStatus","payload":{"title":"user.p.para."}}]}' ${UNIT_HTTP} '(.error|not) and (.result| [has("status"),true])' "$FUNCNAME"
}
function paracross_ListNodeGroupStatus() {
local resp
local ok
resp=$(curl -ksd '{"method":"paracross.ListNodeGroupStatus","params":[{"title":"user.p.para.","status":2}]}' ${UNIT_HTTP})
#echo $resp
ok=$(jq '(.error|not) and (.result| [has("status"),true])' <<<"$resp")
[ "$ok" == true ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"ListNodeGroupStatus","payload":{"title":"user.p.para.","status":2}}]}' ${UNIT_HTTP} '(.error|not) and (.result| [has("status"),true])' "$FUNCNAME"
}
function paracross_ListNodeStatus() {
local resp
local ok
resp=$(curl -ksd '{"method":"paracross.ListNodeStatus","params":[{"title":"user.p.para.","status":4}]}' ${UNIT_HTTP})
#echo $resp
ok=$(jq '(.error|not) and (.result| [has("status"),true])' <<<"$resp")
[ "$ok" == true ]
local rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"ListNodeStatusInfo","payload":{"title":"user.p.para.","status":4}}]}' ${UNIT_HTTP} '(.error|not) and (.result| [has("status"),true])' "$FUNCNAME"
}
#main chain import pri key
para_test_addr="1MAuE8QSbbech3bVKK2JPJJxYxNtT95oSU"
para_test_prikey="0x24d1fad138be98eebee31440f144aa38c404533f40862995282162bc538e91c8"
......@@ -312,7 +229,6 @@ function paracross_txgroupex() {
exit 1
fi
tx_hash_asset=$(jq -r ".result" <<<"$resp")
# tx_hash_asset=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"'"${paracross_execer_name}"'","actionName":"ParacrossAssetTransfer","payload":{"execName":"'"${paracross_execer_name}"'","to":"'"$para_test_addr"'","amount":'${amount_transfer}'}}]}' "${para_ip}" | jq -r ".result")
# 资产从平行链转移到平行链合约
req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${paracross_execer_name}"'","actionName":"TransferToExec","payload":{"execName":"'"${paracross_execer_name}"'","to":"'"${trade_exec_addr}"'","amount":'${amount_trade}', "cointoken":"coins.bty"}}]'
......@@ -343,10 +259,9 @@ function paracross_txgroupex() {
#send
chain33_SendTx "${tx_sign2}" "${para_ip}"
}
//测试平行链交易组跨链失败,主链自动恢复原值
#测试平行链交易组跨链失败,主链自动恢复原值
function paracross_testTxGroupFail() {
local para_ip=$1
......@@ -359,9 +274,8 @@ function paracross_testTxGroupFail() {
echo "paracross_addr=$paracross_addr"
#execer
local trade_exec_addr="12bihjzbaYWjcpDiiy9SuAWeqNksQdiN13"
//测试跨链过去1个,交易组转账8个失败的场景,主链应该还保持原来的
#测试跨链过去1个,交易组转账8个失败的场景,主链应该还保持原来的
local amount_trade=800000000
local amount_transfer=100000000
local amount_left=500000000
......@@ -458,7 +372,7 @@ function paracross_testTxGroup() {
paracross_testSelfConsensStages() {
local para_ip=$1
req='"method":"paracross.GetHeight","params":[]'
req='"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName": "GetHeight", "payload" : {}}]'
resp=$(curl -ksd "{$req}" "${para_ip}")
err=$(jq '(.error)' <<<"$resp")
if [ "$err" != null ]; then
......@@ -471,10 +385,10 @@ paracross_testSelfConsensStages() {
req='"method":"Chain33.CreateTransaction","params":[{"execer" : "user.p.para.paracross","actionName" : "selfConsStageConfig","payload" : {"title":"user.p.para.","op" : "1", "stage" : {"startHeight":'"$newHeight"',"enable":2} }}]'
resp=$(curl -ksd "{$req}" "${para_ip}")
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "$para_test_prikey" "${para_ip}"
chain33_SignAndSendTx "$rawtx" "$para_test_prikey" "${para_ip}"
echo "get stage apply id"
req='"method":"paracross.ListSelfStages","params":[{"status":1,"count":1}]'
req='"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"ListSelfStages","payload":{"status":1,"count":1}}]'
resp=$(curl -ksd "{$req}" "${para_ip}")
echo "$resp"
id=$(jq -r ".result.stageInfo[0].id" <<<"$resp")
......@@ -492,29 +406,29 @@ paracross_testSelfConsensStages() {
resp=$(curl -ksd "{$req}" "${para_ip}")
rawtx=$(jq -r ".result" <<<"$resp")
echo "send vote 1"
chain33_SignRawTx "$rawtx" "$KS_PRI" "${para_ip}"
chain33_SignAndSendTx "$rawtx" "$KS_PRI" "${para_ip}"
echo "send vote 2"
chain33_SignRawTx "$rawtx" "$JR_PRI" "${para_ip}" "110s"
chain33_SignAndSendTx "$rawtx" "$JR_PRI" "${para_ip}" "130s"
echo "send vote 3"
chain33_SignRawTx "$rawtx" "$NL_PRI" "${para_ip}" "111s"
chain33_SignAndSendTx "$rawtx" "$NL_PRI" "${para_ip}" "140s"
echo "query status"
req='"method":"paracross.ListSelfStages","params":[{"status":3,"count":1}]'
req='"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"ListSelfStages","payload":{"status":3,"count":1}}]'
resp=$(curl -ksd "{$req}" "${para_ip}")
echo "$resp"
ok1=$(jq '(.error|not) and (.result| [has("id"),true])' <<<"$resp")
req='"method":"paracross.GetSelfConsStages","params":[]'
req='"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetSelfConsStages","payload":{}}]'
resp=$(curl -ksd "{$req}" "${para_ip}")
echo "$resp"
ok2=$(jq '(.error|not) and (.result| [has("startHeight"),true])' <<<"$resp")
req='"method":"paracross.GetSelfConsOneStage","params":[{"data":1000}]'
req='"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetSelfConsOneStage","payload":{"data":1000}}]'
resp=$(curl -ksd "{$req}" "${para_ip}")
echo "$resp"
ok3=$(jq '(.error|not) and (.result.enable==1)' <<<"$resp")
req='"method":"paracross.GetSelfConsOneStage","params":[{"data":'"$newHeight"'}]'
req='"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetSelfConsOneStage","payload":{"data":'"$newHeight"'}}]'
resp=$(curl -ksd "{$req}" "${para_ip}")
echo "$resp"
ok4=$(jq '(.error|not) and (.result.enable==2)' <<<"$resp")
......
......@@ -42,6 +42,7 @@ func ParcCmd() *cobra.Command {
GetHeightCmd(),
GetBlockInfoCmd(),
GetLocalBlockInfoCmd(),
GetConsensDoneInfoCmd(),
)
return cmd
}
......@@ -66,9 +67,6 @@ func addCreateAssetTransferFlags(cmd *cobra.Command) {
cmd.Flags().StringP("note", "n", "", "transaction note info")
cmd.Flags().StringP("ptitle", "", "", "the title of para chain, like `user.p.guodun.`")
cmd.MarkFlagRequired("ptitle")
cmd.Flags().StringP("symbol", "s", "", "default for bty, symbol for token")
}
......@@ -98,9 +96,6 @@ func addCreateAssetWithdrawFlags(cmd *cobra.Command) {
cmd.Flags().StringP("note", "n", "", "transaction note info")
cmd.Flags().StringP("ptitle", "", "", "the title of para chain, like `user.p.guodun.`")
cmd.MarkFlagRequired("ptitle")
cmd.Flags().StringP("to", "t", "", "receiver account address")
cmd.MarkFlagRequired("to")
......@@ -118,6 +113,7 @@ func createAssetWithdraw(cmd *cobra.Command, args []string) {
func createAssetTx(cmd *cobra.Command, isWithdraw bool) (string, error) {
title, _ := cmd.Flags().GetString("title")
//这里cfg除了里面FormatTx需要外,没其他作用,平行链执行器需要的参数已经填好了,这里title就是默认空就可以,支持主链构建平行链交易
cfg := types.GetCliSysParam(title)
amount, _ := cmd.Flags().GetFloat64("amount")
......@@ -130,12 +126,12 @@ func createAssetTx(cmd *cobra.Command, isWithdraw bool) (string, error) {
note, _ := cmd.Flags().GetString("note")
symbol, _ := cmd.Flags().GetString("symbol")
ptitle, _ := cmd.Flags().GetString("ptitle")
if !strings.HasPrefix(ptitle, "user.p") {
fmt.Fprintln(os.Stderr, "ptitle is not right, title format like `user.p.guodun.`")
paraName, _ := cmd.Flags().GetString("paraName")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "title is not right, title format like `user.p.guodun.`")
return "", types.ErrInvalidParam
}
execName := ptitle + pt.ParaX
execName := paraName + pt.ParaX
param := types.CreateTx{
To: toAddr,
......@@ -269,7 +265,10 @@ func createNodeJoinTx(cmd *cobra.Command, args []string) {
opAddr, _ := cmd.Flags().GetString("addr")
coins, _ := cmd.Flags().GetFloat64("coins")
paraName, _ := cmd.Flags().GetString("paraName")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeAddrConfig{Title: paraName, Op: 1, Addr: opAddr, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -304,7 +303,10 @@ func createNodeVoteTx(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
id, _ := cmd.Flags().GetString("id")
val, _ := cmd.Flags().GetUint32("value")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeAddrConfig{Title: paraName, Op: 2, Id: id, Value: val}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -337,7 +339,10 @@ func addNodeQuitFlags(cmd *cobra.Command) {
func createNodeQuitTx(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
opAddr, _ := cmd.Flags().GetString("addr")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeAddrConfig{Title: paraName, Op: 3, Addr: opAddr}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -370,7 +375,10 @@ func addNodeCancelFlags(cmd *cobra.Command) {
func createNodeCancelTx(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
id, _ := cmd.Flags().GetString("id")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeAddrConfig{Title: paraName, Op: 4, Id: id}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -416,12 +424,17 @@ func nodeInfo(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
addr, _ := cmd.Flags().GetString("addr")
params := pt.ReqParacrossNodeInfo{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetNodeAddrInfo"
req := pt.ReqParacrossNodeInfo{
Title: paraName,
Addr: addr,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.ParaNodeAddrIdStatus
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeAddrStatus", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -447,12 +460,17 @@ func nodeIDInfo(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
id, _ := cmd.Flags().GetString("id")
params := pt.ReqParacrossNodeInfo{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetNodeIDInfo"
req := pt.ReqParacrossNodeInfo{
Title: paraName,
Id: id,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.ParaNodeIdStatus
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeIDStatus", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -478,12 +496,17 @@ func nodeList(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
status, _ := cmd.Flags().GetInt32("status")
params := pt.ReqParacrossNodeInfo{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "ListNodeStatusInfo"
req := pt.ReqParacrossNodeInfo{
Title: paraName,
Status: status,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.RespParacrossNodeAddrs
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.ListNodeStatus", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -655,6 +678,11 @@ func nodeGroupApply(cmd *cobra.Command, args []string) {
addrs, _ := cmd.Flags().GetString("addrs")
coins, _ := cmd.Flags().GetFloat64("coins")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeGroupConfig{Title: paraName, Op: 1, Addrs: addrs, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -691,6 +719,11 @@ func nodeGroupApprove(cmd *cobra.Command, args []string) {
id, _ := cmd.Flags().GetString("id")
coins, _ := cmd.Flags().GetFloat64("coins")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeGroupConfig{Title: paraName, Op: 2, Id: id, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -722,7 +755,10 @@ func addNodeGroupQuitCmdFlags(cmd *cobra.Command) {
func nodeGroupQuit(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
id, _ := cmd.Flags().GetString("id")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeGroupConfig{Title: paraName, Op: 3, Id: id}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -754,7 +790,10 @@ func addNodeGroupModifyCmdFlags(cmd *cobra.Command) {
func nodeGroupModify(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
coins, _ := cmd.Flags().GetFloat64("coins")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeGroupConfig{Title: paraName, Op: 4, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
......@@ -798,8 +837,14 @@ func consusHeight(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
paraName, _ := cmd.Flags().GetString("paraName")
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetHeight"
req := types.ReqString{Data: paraName}
params.Payload = types.MustPBToJSON(&req)
var res pt.ParacrossConsensusStatus
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetHeight", &types.ReqString{Data: paraName}, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -826,14 +871,18 @@ func blockInfo(cmd *cobra.Command, args []string) {
startH, _ := cmd.Flags().GetInt64("start")
endH, _ := cmd.Flags().GetInt64("end")
params := types.ReqBlocks{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetBlock2MainInfo"
req := types.ReqBlocks{
Start: startH,
End: endH,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.ParaBlock2MainInfo
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetBlock2MainInfo", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
// GetBlockInfoCmd get blocks hash with main chain hash map
......@@ -888,12 +937,17 @@ func paraInfo(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
height, _ := cmd.Flags().GetInt64("height")
params := pt.ReqParacrossTitleHeight{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetTitleHeight"
req := pt.ReqParacrossTitleHeight{
Title: paraName,
Height: height,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.ParacrossHeightStatusRsp
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetTitleHeight", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -901,7 +955,7 @@ func paraInfo(cmd *cobra.Command, args []string) {
func GetParaInfoCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "consens_status",
Short: "Get para chain current consensus status",
Short: "Get para chain heights' consensus status",
Run: paraInfo,
}
addParaBodyCmdFlags(cmd)
......@@ -922,8 +976,14 @@ func GetParaListCmd() *cobra.Command {
func paraList(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "ListTitles"
req := types.ReqNil{}
params.Payload = types.MustPBToJSON(&req)
var res pt.RespParacrossTitles
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.ListTitles", types.ReqNil{}, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -947,18 +1007,23 @@ func paraAssetTransfer(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
hash, _ := cmd.Flags().GetString("hash")
params := types.ReqString{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetAssetTxResult"
req := types.ReqString{
Data: hash,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.ParacrossAssetRsp
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetAssetTxResult", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
// GetParaAssetTransCmd get para chain asset transfer info
func GetParaAssetTransCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "asset_tranfer",
Use: "asset_txinfo",
Short: "Get para chain cross asset transfer info",
Run: paraAssetTransfer,
}
......@@ -970,8 +1035,14 @@ func nodeGroup(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
paraName, _ := cmd.Flags().GetString("paraName")
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetNodeGroupAddrs"
req := pt.ReqParacrossNodeInfo{Title: paraName}
params.Payload = types.MustPBToJSON(&req)
var res types.ReplyConfig
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeGroupAddrs", pt.ReqParacrossNodeInfo{Title: paraName}, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -989,12 +1060,16 @@ func nodeGroupStatus(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
paraName, _ := cmd.Flags().GetString("paraName")
params := pt.ReqParacrossNodeInfo{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetNodeGroupStatus"
req := pt.ReqParacrossNodeInfo{
Title: paraName,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.ParaNodeGroupStatus
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeGroupStatus", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -1018,20 +1093,30 @@ func nodeGroupList(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
status, _ := cmd.Flags().GetInt32("status")
params := pt.ReqParacrossNodeInfo{
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "ListNodeGroupStatus"
req := pt.ReqParacrossNodeInfo{
Status: status,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.RespParacrossNodeGroups
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.ListNodeGroupStatus", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
func stagesInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetSelfConsStages"
req := types.ReqNil{}
params.Payload = types.MustPBToJSON(&req)
var res pt.SelfConsensStages
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetSelfConsStages", nil, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -1050,9 +1135,14 @@ func stageOneInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
height, _ := cmd.Flags().GetInt64("height")
params := types.Int64{Data: height}
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetSelfConsOneStage"
req := types.Int64{Data: height}
params.Payload = types.MustPBToJSON(&req)
var res pt.SelfConsensStage
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetSelfConsOneStage", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
......@@ -1081,7 +1171,7 @@ func QuerySelfStagesCmd() *cobra.Command {
func addShowSelfStagesflags(cmd *cobra.Command) {
cmd.Flags().StringP("id", "q", "", "stage apply ID")
cmd.Flags().Uint32P("status", "s", 0, "status")
cmd.Flags().Uint32P("status", "s", 0, "status:1:applying,3:closed,4:canceled,5:voting")
cmd.Flags().Int32P("count", "c", 1, "count, default is 1")
cmd.Flags().Int32P("direction", "d", 0, "direction, default is reserve")
cmd.Flags().Int64P("height", "t", -1, "height, default is -1")
......@@ -1097,7 +1187,15 @@ func showSelfStages(cmd *cobra.Command, args []string) {
height, _ := cmd.Flags().GetInt64("height")
index, _ := cmd.Flags().GetInt32("index")
params := pt.ReqQuerySelfStages{
if id == "" && status == 0 {
fmt.Fprintln(os.Stderr, "should fill id or status in")
return
}
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "ListSelfStages"
req := pt.ReqQuerySelfStages{
Status: status,
Id: id,
Count: count,
......@@ -1105,8 +1203,45 @@ func showSelfStages(cmd *cobra.Command, args []string) {
Height: height,
Index: index,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.ReplyQuerySelfStages
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.ListSelfStages", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
func addConsensDoneCmdFlags(cmd *cobra.Command) {
cmd.Flags().Int64P("height", "g", 0, "height to para chain")
cmd.MarkFlagRequired("height")
}
func consensDoneInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
paraName, _ := cmd.Flags().GetString("paraName")
height, _ := cmd.Flags().GetInt64("height")
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetDoneTitleHeight"
req := pt.ReqParacrossTitleHeight{
Title: paraName,
Height: height,
}
params.Payload = types.MustPBToJSON(&req)
var res pt.RespParacrossDone
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
// GetConsensDoneInfoCmd get para chain done height consens info
func GetConsensDoneInfoCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "consens_done",
Short: "Get para chain done height consensus info",
Run: consensDoneInfo,
}
addConsensDoneCmdFlags(cmd)
return cmd
}
......@@ -181,7 +181,7 @@ func makeRecordReceipt(addr string, commit *pt.ParacrossCommitAction) *types.Rec
}
}
func makeDoneReceipt(cfg *types.Chain33Config, execMainHeight int64, commit *pt.ParacrossNodeStatus,
func makeDoneReceipt(cfg *types.Chain33Config, execMainHeight, execHeight int64, commit *pt.ParacrossNodeStatus,
most, commitCount, totalCount int32) *types.Receipt {
log := &pt.ReceiptParacrossDone{
......@@ -194,6 +194,7 @@ func makeDoneReceipt(cfg *types.Chain33Config, execMainHeight int64, commit *pt.
TxResult: commit.TxResult,
MainBlockHeight: commit.MainBlockHeight,
MainBlockHash: commit.MainBlockHash,
ChainExecHeight: execHeight,
}
key := calcTitleKey(commit.Title)
status := &pt.ParacrossStatus{
......@@ -511,7 +512,7 @@ func (a *action) commitTxDone(nodeStatus *pt.ParacrossNodeStatus, stat *pt.Parac
}
//add commit done receipt
receiptDone := makeDoneReceipt(cfg, a.exec.GetMainHeight(), nodeStatus, int32(most), int32(commitCount), int32(len(nodes)))
receiptDone := makeDoneReceipt(cfg, a.exec.GetMainHeight(), a.height, nodeStatus, int32(most), int32(commitCount), int32(len(nodes)))
receipt = mergeReceipt(receipt, receiptDone)
r, err := a.commitTxDoneStep2(nodeStatus, stat, titleStatus)
......@@ -696,7 +697,7 @@ func (a *action) commitTxDoneByStat(stat *pt.ParacrossHeightStatus, titleStatus
//add commit done receipt
cfg := a.api.GetConfig()
receiptDone := makeDoneReceipt(cfg, a.exec.GetMainHeight(), mostStatus, int32(most), int32(commitCount), int32(len(nodes)))
receiptDone := makeDoneReceipt(cfg, a.exec.GetMainHeight(), a.height, mostStatus, int32(most), int32(commitCount), int32(len(nodes)))
receipt = mergeReceipt(receipt, receiptDone)
r, err := a.commitTxDoneStep2(mostStatus, stat, titleStatus)
......
......@@ -28,6 +28,10 @@ func (p *Paracross) Query_GetTitleHeight(in *pt.ReqParacrossTitleHeight) (types.
if in == nil {
return nil, types.ErrInvalidParam
}
cfg := p.GetAPI().GetConfig()
if cfg.IsPara() {
in.Title = cfg.GetTitle()
}
stat, err := p.paracrossGetStateTitleHeight(in.Title, in.Height)
if err != nil {
clog.Error("paracross.GetTitleHeight", "title", title, "height", in.Height, "err", err.Error())
......@@ -63,13 +67,20 @@ func (p *Paracross) Query_GetTitleByHash(in *pt.ReqParacrossTitleHash) (types.Me
//Query_GetNodeGroupAddrs get node group addrs
func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
if in == nil || in.GetTitle() == "" {
if in == nil {
return nil, types.ErrInvalidParam
}
cfg := p.GetAPI().GetConfig()
if cfg.IsPara() {
in.Title = cfg.GetTitle()
} else if in.Title == "" {
return nil, errors.Wrap(types.ErrInvalidParam, "title is null")
}
ret, key, err := getConfigNodes(p.GetStateDB(), in.GetTitle())
if err != nil {
return nil, errors.Cause(err)
return nil, err
}
var nodes []string
for k := range ret {
......@@ -83,9 +94,16 @@ func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types.
//Query_GetNodeAddrInfo get specific node addr info
func (p *Paracross) Query_GetNodeAddrInfo(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
if in == nil || in.Title == "" || in.Addr == "" {
if in == nil || in.Addr == "" {
return nil, types.ErrInvalidParam
}
cfg := p.GetAPI().GetConfig()
if cfg.IsPara() {
in.Title = cfg.GetTitle()
} else if in.Title == "" {
return nil, types.ErrInvalidParam
}
stat, err := getNodeAddr(p.GetStateDB(), in.Title, in.Addr)
if err != nil {
return nil, err
......@@ -94,7 +112,7 @@ func (p *Paracross) Query_GetNodeAddrInfo(in *pt.ReqParacrossNodeInfo) (types.Me
if err != nil {
return nil, err
}
cfg := p.GetAPI().GetConfig()
if pt.IsParaForkHeight(cfg, mainHeight, pt.ForkLoopCheckCommitTxDone) {
stat.QuitId = getParaNodeIDSuffix(stat.QuitId)
stat.ProposalId = getParaNodeIDSuffix(stat.ProposalId)
......@@ -117,14 +135,21 @@ func (p *Paracross) getMainHeight() (int64, error) {
//Query_GetNodeIDInfo get specific node addr info
func (p *Paracross) Query_GetNodeIDInfo(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
if in == nil || in.Title == "" || in.Id == "" {
if in == nil || in.Id == "" {
return nil, types.ErrInvalidParam
}
cfg := p.GetAPI().GetConfig()
if cfg.IsPara() {
in.Title = cfg.GetTitle()
} else if in.Title == "" {
return nil, errors.Wrap(types.ErrInvalidParam, "title is null")
}
mainHeight, err := p.getMainHeight()
if err != nil {
return nil, err
}
cfg := p.GetAPI().GetConfig()
stat, err := getNodeIDWithFork(cfg, p.GetStateDB(), in.Title, mainHeight, in.Id)
if err != nil {
return nil, err
......@@ -214,6 +239,10 @@ func (p *Paracross) Query_GetDoneTitleHeight(in *pt.ReqParacrossTitleHeight) (ty
if in == nil {
return nil, types.ErrInvalidParam
}
cfg := p.GetAPI().GetConfig()
if cfg.IsPara() {
in.Title = cfg.GetTitle()
}
return p.paracrossGetTitleHeight(in.Title, in.Height)
}
......@@ -300,6 +329,7 @@ func listLocalTitles(db dbm.KVDB) (types.Message, error) {
MostSameCommit: st.MostSameCommit,
Title: st.Title,
Height: st.Height,
ChainExecHeight: st.ChainExecHeight,
TxResult: string(st.TxResult),
}
......@@ -385,6 +415,7 @@ func loadLocalTitle(db dbm.KV, title string, height int64) (types.Message, error
MostSameCommit: st.MostSameCommit,
Title: st.Title,
Height: st.Height,
ChainExecHeight: st.ChainExecHeight,
TxResult: hex.EncodeToString(st.TxResult),
}, nil
}
......@@ -457,3 +488,60 @@ func (p *Paracross) Query_GetSelfConsOneStage(in *types.Int64) (types.Message, e
func (p *Paracross) Query_ListSelfStages(in *pt.ReqQuerySelfStages) (types.Message, error) {
return p.listSelfStages(in)
}
func (p *Paracross) Query_GetBlock2MainInfo(req *types.ReqBlocks) (*pt.ParaBlock2MainInfo, error) {
ret := &pt.ParaBlock2MainInfo{}
details, err := p.GetAPI().GetBlocks(req)
if err != nil {
return nil, err
}
cfg := p.GetAPI().GetConfig()
for _, item := range details.Items {
data := &pt.ParaBlock2MainMap{
Height: item.Block.Height,
BlockHash: common.ToHex(item.Block.Hash(cfg)),
MainHeight: item.Block.MainHeight,
MainHash: common.ToHex(item.Block.MainHash),
}
ret.Items = append(ret.Items, data)
}
return ret, nil
}
func (p *Paracross) Query_GetHeight(req *types.ReqString) (*pt.ParacrossConsensusStatus, error) {
cfg := p.GetAPI().GetConfig()
if req == nil || req.Data == "" {
if !cfg.IsPara() {
return nil, errors.Wrap(types.ErrInvalidParam, "req invalid")
}
}
reqTitle := req.Data
if cfg.IsPara() {
reqTitle = cfg.GetTitle()
}
res, err := p.paracrossGetHeight(reqTitle)
if err != nil {
return nil, errors.Wrapf(err, "title:%s", reqTitle)
}
header, err := p.GetAPI().GetLastHeader()
if err != nil {
return nil, errors.Wrap(err, "GetLastHeader")
}
chainHeight := header.Height
if resp, ok := res.(*pt.ParacrossStatus); ok {
// 如果主链上查询平行链的高度,chain height应该是平行链的高度而不是主链高度, 平行链的真实高度需要在平行链侧查询
if !cfg.IsPara() {
chainHeight = resp.Height
}
return &pt.ParacrossConsensusStatus{
Title: resp.Title,
ChainHeight: chainHeight,
ConsensHeight: resp.Height,
ConsensBlockHash: common.ToHex(resp.BlockHash),
}, nil
}
return nil, types.ErrDecode
}
......@@ -328,6 +328,7 @@ message ReceiptParacrossDone {
repeated bytes crossTxHashs = 12;
bytes mainBlockHash = 13;
int64 mainBlockHeight = 14;
int64 chainExecHeight = 15;
}
message ReceiptParacrossRecord {
......@@ -356,6 +357,8 @@ message RespParacrossDone {
string stateHash = 6;
uint32 txCounts = 7;
string txResult = 8;
//commitDone chainHeight
int64 chainExecHeight= 9;
}
message RespParacrossTitles {
......@@ -421,10 +424,5 @@ message ParaLocalDbBlockInfo {
}
service paracross {
rpc GetTitle(ReqString) returns (ParacrossConsensusStatus) {}
rpc ListTitles(ReqNil) returns (RespParacrossTitles) {}
rpc GetDoneTitleHeight(ReqParacrossTitleHeight) returns (RespParacrossDone) {}
rpc GetTitleHeight(ReqParacrossTitleHeight) returns (ParacrossHeightStatusRsp) {}
rpc GetAssetTxResult(ReqString) returns (ParacrossAssetRsp) {}
rpc IsSync(ReqNil) returns (IsCaughtUp) {}
}
\ No newline at end of file
......@@ -7,142 +7,10 @@ package rpc
import (
"context"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
)
func (c *channelClient) GetTitle(ctx context.Context, req *types.ReqString) (*pt.ParacrossConsensusStatus, error) {
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetTitle", req)
if err != nil {
return nil, err
}
header, err := c.GetLastHeader()
if err != nil {
return nil, err
}
chainHeight := header.Height
if resp, ok := data.(*pt.ParacrossStatus); ok {
// 如果主链上查询平行链的高度,chain height应该是平行链的高度而不是主链高度, 平行链的真实高度需要在平行链侧查询
if !cfg.IsPara() {
chainHeight = resp.Height
}
return &pt.ParacrossConsensusStatus{
Title: resp.Title,
ChainHeight: chainHeight,
ConsensHeight: resp.Height,
ConsensBlockHash: common.ToHex(resp.BlockHash),
}, nil
}
return nil, types.ErrDecode
}
// GetHeight jrpc get consensus height
func (c *Jrpc) GetHeight(req *types.ReqString, result *interface{}) error {
cfg := c.cli.GetConfig()
if req == nil || req.Data == "" {
if cfg.IsPara() {
req = &types.ReqString{Data: cfg.GetTitle()}
} else {
return types.ErrInvalidParam
}
}
data, err := c.cli.GetTitle(context.Background(), req)
if err != nil {
return err
}
*result = *data
return err
}
func (c *channelClient) ListTitles(ctx context.Context, req *types.ReqNil) (*pt.RespParacrossTitles, error) {
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "ListTitles", req)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.RespParacrossTitles); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// ListTitles get paracross consensus titles list
func (c *Jrpc) ListTitles(req *types.ReqNil, result *interface{}) error {
data, err := c.cli.ListTitles(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
func (c *channelClient) GetTitleHeight(ctx context.Context, req *pt.ReqParacrossTitleHeight) (*pt.ParacrossHeightStatusRsp, error) {
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetTitleHeight", req)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParacrossHeightStatusRsp); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetTitleHeight get consensus title height
func (c *Jrpc) GetTitleHeight(req *pt.ReqParacrossTitleHeight, result *interface{}) error {
if req == nil {
return types.ErrInvalidParam
}
data, err := c.cli.GetTitleHeight(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
func (c *channelClient) GetDoneTitleHeight(ctx context.Context, req *pt.ReqParacrossTitleHeight) (*pt.RespParacrossDone, error) {
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetDoneTitleHeight", req)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.RespParacrossDone); ok {
return resp, nil
}
return nil, types.ErrDecode
}
func (c *channelClient) GetAssetTxResult(ctx context.Context, req *types.ReqString) (*pt.ParacrossAssetRsp, error) {
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetAssetTxResult", req)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParacrossAssetRsp); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetAssetTxResult get asset tx result
func (c *Jrpc) GetAssetTxResult(req *types.ReqString, result *interface{}) error {
if req == nil {
return types.ErrInvalidParam
}
data, err := c.cli.GetAssetTxResult(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
// IsSync query is sync
func (c *channelClient) IsSync(ctx context.Context, in *types.ReqNil) (*types.IsCaughtUp, error) {
data, err := c.QueryConsensusFunc("para", "IsCaughtUp", &types.ReqNil{})
......@@ -166,7 +34,7 @@ func (c *Jrpc) IsSync(in *types.ReqNil, result *interface{}) error {
return nil
}
// GetParaLocalBlockInfo query para local height
// GetParaLocalBlockInfo query para chain the download layer's local height
func (c *channelClient) GetParaLocalBlockInfo(ctx context.Context, in *types.ReqInt) (*pt.ParaLocalDbBlockInfo, error) {
data, err := c.QueryConsensusFunc("para", "LocalBlockInfo", in)
if err != nil {
......@@ -184,260 +52,3 @@ func (c *Jrpc) GetParaLocalBlockInfo(in *types.ReqInt, result *interface{}) erro
*result = data
return nil
}
func (c *channelClient) GetBlock2MainInfo(ctx context.Context, req *types.ReqBlocks) (*pt.ParaBlock2MainInfo, error) {
ret := &pt.ParaBlock2MainInfo{}
details, err := c.GetBlocks(req)
if err != nil {
return nil, err
}
cfg := c.GetConfig()
for _, item := range details.Items {
data := &pt.ParaBlock2MainMap{
Height: item.Block.Height,
BlockHash: common.ToHex(item.Block.Hash(cfg)),
MainHeight: item.Block.MainHeight,
MainHash: common.ToHex(item.Block.MainHash),
}
ret.Items = append(ret.Items, data)
}
return ret, nil
}
// GetBlock2MainInfo jrpc get para block info with main chain map
func (c *Jrpc) GetBlock2MainInfo(req *types.ReqBlocks, result *interface{}) error {
if req == nil {
return types.ErrInvalidParam
}
ret, err := c.cli.GetBlock2MainInfo(context.Background(), req)
if err != nil {
return err
}
*result = *ret
return nil
}
// GetNodeAddrStatus get super node status
func (c *channelClient) GetNodeAddrStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeAddrIdStatus, error) {
r := *req
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetNodeAddrInfo", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParaNodeAddrIdStatus); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeIDStatus get super node status
func (c *channelClient) GetNodeIDStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeIdStatus, error) {
r := *req
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetNodeIDInfo", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParaNodeIdStatus); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeAddrStatus get super node status
func (c *Jrpc) GetNodeAddrStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
if req == nil || req.Addr == "" {
return types.ErrInvalidParam
}
data, err := c.cli.GetNodeAddrStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
// GetNodeIDStatus get super node status
func (c *Jrpc) GetNodeIDStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
if req == nil || req.Id == "" {
return types.ErrInvalidParam
}
data, err := c.cli.GetNodeIDStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
//ListNodeStatus list super node by status
func (c *channelClient) ListNodeStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.RespParacrossNodeAddrs, error) {
r := *req
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "ListNodeStatusInfo", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.RespParacrossNodeAddrs); ok {
return resp, nil
}
return nil, types.ErrDecode
}
//ListNodeStatus list super node by status
func (c *Jrpc) ListNodeStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.ListNodeStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
// GetNodeGroupAddrs get super node group addrs
func (c *channelClient) GetNodeGroupAddrs(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*types.ReplyConfig, error) {
r := *req
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetNodeGroupAddrs", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*types.ReplyConfig); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeGroupAddrs get super node group addrs
func (c *Jrpc) GetNodeGroupAddrs(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.GetNodeGroupAddrs(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
// GetNodeGroupStatus get super node group status
func (c *channelClient) GetNodeGroupStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeGroupStatus, error) {
r := *req
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "GetNodeGroupStatus", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParaNodeGroupStatus); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeGroupStatus get super node group status
func (c *Jrpc) GetNodeGroupStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.GetNodeGroupStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
//ListNodeGroupStatus list super node group by status
func (c *channelClient) ListNodeGroupStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.RespParacrossNodeGroups, error) {
r := *req
cfg := c.GetConfig()
data, err := c.Query(pt.GetExecName(cfg), "ListNodeGroupStatus", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.RespParacrossNodeGroups); ok {
return resp, nil
}
return nil, types.ErrDecode
}
//ListNodeGroupStatus list super node group by status
func (c *Jrpc) ListNodeGroupStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.ListNodeGroupStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
// GetNodeGroupAddrs get super node group addrs
func (c *channelClient) GetSelfConsStages(ctx context.Context, req *types.ReqNil) (*pt.SelfConsensStages, error) {
cfg := c.GetConfig()
r := *req
data, err := c.Query(pt.GetExecName(cfg), "GetSelfConsStages", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.SelfConsensStages); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeGroupAddrs get super node group addrs
func (c *Jrpc) GetSelfConsStages(req *types.ReqNil, result *interface{}) error {
data, err := c.cli.GetSelfConsStages(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
// GetNodeGroupAddrs get super node group addrs
func (c *channelClient) GetSelfConsOneStage(ctx context.Context, req *types.Int64) (*pt.SelfConsensStage, error) {
cfg := c.GetConfig()
r := *req
data, err := c.Query(pt.GetExecName(cfg), "GetSelfConsOneStage", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.SelfConsensStage); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeGroupAddrs get super node group addrs
func (c *Jrpc) GetSelfConsOneStage(req *types.Int64, result *interface{}) error {
data, err := c.cli.GetSelfConsOneStage(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
func (c *channelClient) ListSelfStages(ctx context.Context, req *pt.ReqQuerySelfStages) (*pt.ReplyQuerySelfStages, error) {
cfg := c.GetConfig()
r := *req
data, err := c.Query(pt.GetExecName(cfg), "ListSelfStages", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ReplyQuerySelfStages); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// ListSelfStages get paracross self consensus stage list
func (c *Jrpc) ListSelfStages(req *pt.ReqQuerySelfStages, result *interface{}) error {
data, err := c.cli.ListSelfStages(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -15,7 +15,6 @@ import (
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
ptestNode "github.com/33cn/plugin/plugin/dapp/paracross/testnode"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"golang.org/x/net/context"
......@@ -31,117 +30,6 @@ func newJrpc(api client.QueueProtocolAPI) *Jrpc {
return &Jrpc{cli: newGrpc(api)}
}
func TestChannelClient_GetTitle(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
client := newGrpc(api)
client.Init("paracross", nil, nil, nil)
req := &types.ReqString{Data: "xxxxxxxxxxx"}
api.On("Query", pt.GetExecName(cfg), "GetTitle", req).Return(&pt.ParacrossStatus{}, nil)
api.On("GetLastHeader", mock.Anything).Return(&types.Header{}, nil).Once()
_, err := client.GetTitle(context.Background(), req)
assert.Nil(t, err)
}
func TestJrpc_GetTitle(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
j := newJrpc(api)
req := &types.ReqString{Data: "xxxxxxxxxxx"}
var result interface{}
api.On("Query", pt.GetExecName(cfg), "GetTitle", req).Return(&pt.ParacrossStatus{
Title: "user.p.para", Height: int64(64), BlockHash: []byte{177, 17, 9, 106, 247, 117, 90, 242, 221, 160, 157, 31, 33, 51, 10, 99, 77, 47, 245, 223, 59, 64, 121, 121, 215, 167, 152, 17, 223, 218, 173, 83}}, nil)
api.On("GetLastHeader", mock.Anything).Return(&types.Header{}, nil).Once()
err := j.GetHeight(req, &result)
assert.Nil(t, err)
}
func TestChannelClient_ListTitles(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
client := newGrpc(api)
client.Init("paracross", nil, nil, nil)
req := &types.ReqNil{}
api.On("Query", pt.GetExecName(cfg), "ListTitles", req).Return(&pt.RespParacrossTitles{}, nil)
_, err := client.ListTitles(context.Background(), req)
assert.Nil(t, err)
}
func TestJrpc_ListTitles(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
j := newJrpc(api)
req := &types.ReqNil{}
var result interface{}
api.On("Query", pt.GetExecName(cfg), "ListTitles", req).Return(&pt.RespParacrossTitles{}, nil)
err := j.ListTitles(req, &result)
assert.Nil(t, err)
}
func TestChannelClient_GetTitleHeight(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
client := newGrpc(api)
client.Init("paracross", nil, nil, nil)
req := &pt.ReqParacrossTitleHeight{}
api.On("Query", pt.GetExecName(cfg), "GetTitleHeight", req).Return(&pt.ParacrossHeightStatusRsp{}, nil)
_, err := client.GetTitleHeight(context.Background(), req)
assert.Nil(t, err)
}
func TestChannelClient_GetTitleDoneHeight(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
client := newGrpc(api)
client.Init("paracross", nil, nil, nil)
req := &pt.ReqParacrossTitleHeight{}
api.On("Query", pt.GetExecName(cfg), "GetDoneTitleHeight", req).Return(&pt.RespParacrossDone{}, nil)
_, err := client.GetDoneTitleHeight(context.Background(), req)
assert.Nil(t, err)
}
func TestJrpc_GetTitleHeight(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
j := newJrpc(api)
req := &pt.ReqParacrossTitleHeight{}
var result interface{}
api.On("Query", pt.GetExecName(cfg), "GetTitleHeight", req).Return(&pt.ParacrossHeightStatusRsp{}, nil)
err := j.GetTitleHeight(req, &result)
assert.Nil(t, err)
}
func TestChannelClient_GetAssetTxResult(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
client := newGrpc(api)
client.Init("paracross", nil, nil, nil)
req := &types.ReqString{}
api.On("Query", pt.GetExecName(cfg), "GetAssetTxResult", req).Return(&pt.ParacrossAssetRsp{}, nil)
_, err := client.GetAssetTxResult(context.Background(), req)
assert.Nil(t, err)
}
func TestJrpc_GetAssetTxResult(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
j := newJrpc(api)
req := &types.ReqString{}
var result interface{}
api.On("Query", pt.GetExecName(cfg), "GetAssetTxResult", req).Return(&pt.ParacrossAssetRsp{}, nil)
err := j.GetAssetTxResult(req, &result)
assert.Nil(t, err)
}
func TestChannelClient_IsSync(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI)
......
......@@ -6,7 +6,10 @@ import (
"github.com/33cn/chain33/util"
_ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/types"
_ "github.com/33cn/plugin/plugin"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/stretchr/testify/assert"
)
func TestParaNode(t *testing.T) {
......@@ -20,4 +23,8 @@ func TestParaNode(t *testing.T) {
tx = util.CreateTxWithExecer(paraCfg, para.Para.GetGenesisKey(), "user.p.test.none")
para.Para.SendTxRPC(tx)
para.Para.WaitHeight(2)
res, err := para.Para.GetAPI().Query(pt.ParaX, "GetTitle", &types.ReqString{Data: "user.p.test."})
assert.Nil(t, err)
assert.Equal(t, int64(-1), res.(*pt.ParacrossStatus).Height)
}
......@@ -41,7 +41,7 @@ func (m *ParacrossStatusDetails) Reset() { *m = ParacrossStatusDetails{}
func (m *ParacrossStatusDetails) String() string { return proto.CompactTextString(m) }
func (*ParacrossStatusDetails) ProtoMessage() {}
func (*ParacrossStatusDetails) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{0}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{0}
}
func (m *ParacrossStatusDetails) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossStatusDetails.Unmarshal(m, b)
......@@ -88,7 +88,7 @@ func (m *ParacrossStatusBlockDetails) Reset() { *m = ParacrossStatusBloc
func (m *ParacrossStatusBlockDetails) String() string { return proto.CompactTextString(m) }
func (*ParacrossStatusBlockDetails) ProtoMessage() {}
func (*ParacrossStatusBlockDetails) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{1}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{1}
}
func (m *ParacrossStatusBlockDetails) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossStatusBlockDetails.Unmarshal(m, b)
......@@ -140,7 +140,7 @@ func (m *ParacrossHeightStatus) Reset() { *m = ParacrossHeightStatus{} }
func (m *ParacrossHeightStatus) String() string { return proto.CompactTextString(m) }
func (*ParacrossHeightStatus) ProtoMessage() {}
func (*ParacrossHeightStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{2}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{2}
}
func (m *ParacrossHeightStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossHeightStatus.Unmarshal(m, b)
......@@ -226,7 +226,7 @@ func (m *ParacrossHeightStatusRsp) Reset() { *m = ParacrossHeightStatusR
func (m *ParacrossHeightStatusRsp) String() string { return proto.CompactTextString(m) }
func (*ParacrossHeightStatusRsp) ProtoMessage() {}
func (*ParacrossHeightStatusRsp) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{3}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{3}
}
func (m *ParacrossHeightStatusRsp) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossHeightStatusRsp.Unmarshal(m, b)
......@@ -310,7 +310,7 @@ func (m *ParacrossStatus) Reset() { *m = ParacrossStatus{} }
func (m *ParacrossStatus) String() string { return proto.CompactTextString(m) }
func (*ParacrossStatus) ProtoMessage() {}
func (*ParacrossStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{4}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{4}
}
func (m *ParacrossStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossStatus.Unmarshal(m, b)
......@@ -379,7 +379,7 @@ func (m *ParacrossConsensusStatus) Reset() { *m = ParacrossConsensusStat
func (m *ParacrossConsensusStatus) String() string { return proto.CompactTextString(m) }
func (*ParacrossConsensusStatus) ProtoMessage() {}
func (*ParacrossConsensusStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{5}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{5}
}
func (m *ParacrossConsensusStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossConsensusStatus.Unmarshal(m, b)
......@@ -443,7 +443,7 @@ func (m *ParaNodeAddrConfig) Reset() { *m = ParaNodeAddrConfig{} }
func (m *ParaNodeAddrConfig) String() string { return proto.CompactTextString(m) }
func (*ParaNodeAddrConfig) ProtoMessage() {}
func (*ParaNodeAddrConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{6}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{6}
}
func (m *ParaNodeAddrConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaNodeAddrConfig.Unmarshal(m, b)
......@@ -517,7 +517,7 @@ func (m *ParaNodeVoteDetail) Reset() { *m = ParaNodeVoteDetail{} }
func (m *ParaNodeVoteDetail) String() string { return proto.CompactTextString(m) }
func (*ParaNodeVoteDetail) ProtoMessage() {}
func (*ParaNodeVoteDetail) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{7}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{7}
}
func (m *ParaNodeVoteDetail) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaNodeVoteDetail.Unmarshal(m, b)
......@@ -566,7 +566,7 @@ func (m *ParaNodeAddrIdStatus) Reset() { *m = ParaNodeAddrIdStatus{} }
func (m *ParaNodeAddrIdStatus) String() string { return proto.CompactTextString(m) }
func (*ParaNodeAddrIdStatus) ProtoMessage() {}
func (*ParaNodeAddrIdStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{8}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{8}
}
func (m *ParaNodeAddrIdStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaNodeAddrIdStatus.Unmarshal(m, b)
......@@ -639,7 +639,7 @@ func (m *ParaNodeIdStatus) Reset() { *m = ParaNodeIdStatus{} }
func (m *ParaNodeIdStatus) String() string { return proto.CompactTextString(m) }
func (*ParaNodeIdStatus) ProtoMessage() {}
func (*ParaNodeIdStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{9}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{9}
}
func (m *ParaNodeIdStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaNodeIdStatus.Unmarshal(m, b)
......@@ -729,7 +729,7 @@ func (m *ReceiptParaNodeConfig) Reset() { *m = ReceiptParaNodeConfig{} }
func (m *ReceiptParaNodeConfig) String() string { return proto.CompactTextString(m) }
func (*ReceiptParaNodeConfig) ProtoMessage() {}
func (*ReceiptParaNodeConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{10}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{10}
}
func (m *ReceiptParaNodeConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParaNodeConfig.Unmarshal(m, b)
......@@ -790,7 +790,7 @@ func (m *ReceiptParaNodeAddrStatUpdate) Reset() { *m = ReceiptParaNodeAd
func (m *ReceiptParaNodeAddrStatUpdate) String() string { return proto.CompactTextString(m) }
func (*ReceiptParaNodeAddrStatUpdate) ProtoMessage() {}
func (*ReceiptParaNodeAddrStatUpdate) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{11}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{11}
}
func (m *ReceiptParaNodeAddrStatUpdate) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParaNodeAddrStatUpdate.Unmarshal(m, b)
......@@ -849,7 +849,7 @@ func (m *ReceiptParaNodeVoteDone) Reset() { *m = ReceiptParaNodeVoteDone
func (m *ReceiptParaNodeVoteDone) String() string { return proto.CompactTextString(m) }
func (*ReceiptParaNodeVoteDone) ProtoMessage() {}
func (*ReceiptParaNodeVoteDone) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{12}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{12}
}
func (m *ReceiptParaNodeVoteDone) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParaNodeVoteDone.Unmarshal(m, b)
......@@ -940,7 +940,7 @@ func (m *ParaNodeGroupConfig) Reset() { *m = ParaNodeGroupConfig{} }
func (m *ParaNodeGroupConfig) String() string { return proto.CompactTextString(m) }
func (*ParaNodeGroupConfig) ProtoMessage() {}
func (*ParaNodeGroupConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{13}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{13}
}
func (m *ParaNodeGroupConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaNodeGroupConfig.Unmarshal(m, b)
......@@ -1012,7 +1012,7 @@ func (m *ParaNodeGroupStatus) Reset() { *m = ParaNodeGroupStatus{} }
func (m *ParaNodeGroupStatus) String() string { return proto.CompactTextString(m) }
func (*ParaNodeGroupStatus) ProtoMessage() {}
func (*ParaNodeGroupStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{14}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{14}
}
func (m *ParaNodeGroupStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaNodeGroupStatus.Unmarshal(m, b)
......@@ -1095,7 +1095,7 @@ func (m *ReceiptParaNodeGroupConfig) Reset() { *m = ReceiptParaNodeGroup
func (m *ReceiptParaNodeGroupConfig) String() string { return proto.CompactTextString(m) }
func (*ReceiptParaNodeGroupConfig) ProtoMessage() {}
func (*ReceiptParaNodeGroupConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{15}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{15}
}
func (m *ReceiptParaNodeGroupConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParaNodeGroupConfig.Unmarshal(m, b)
......@@ -1158,7 +1158,7 @@ func (m *ReqParacrossNodeInfo) Reset() { *m = ReqParacrossNodeInfo{} }
func (m *ReqParacrossNodeInfo) String() string { return proto.CompactTextString(m) }
func (*ReqParacrossNodeInfo) ProtoMessage() {}
func (*ReqParacrossNodeInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{16}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{16}
}
func (m *ReqParacrossNodeInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReqParacrossNodeInfo.Unmarshal(m, b)
......@@ -1217,7 +1217,7 @@ func (m *RespParacrossNodeAddrs) Reset() { *m = RespParacrossNodeAddrs{}
func (m *RespParacrossNodeAddrs) String() string { return proto.CompactTextString(m) }
func (*RespParacrossNodeAddrs) ProtoMessage() {}
func (*RespParacrossNodeAddrs) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{17}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{17}
}
func (m *RespParacrossNodeAddrs) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RespParacrossNodeAddrs.Unmarshal(m, b)
......@@ -1255,7 +1255,7 @@ func (m *RespParacrossNodeGroups) Reset() { *m = RespParacrossNodeGroups
func (m *RespParacrossNodeGroups) String() string { return proto.CompactTextString(m) }
func (*RespParacrossNodeGroups) ProtoMessage() {}
func (*RespParacrossNodeGroups) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{18}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{18}
}
func (m *RespParacrossNodeGroups) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RespParacrossNodeGroups.Unmarshal(m, b)
......@@ -1296,7 +1296,7 @@ func (m *ParaBlock2MainMap) Reset() { *m = ParaBlock2MainMap{} }
func (m *ParaBlock2MainMap) String() string { return proto.CompactTextString(m) }
func (*ParaBlock2MainMap) ProtoMessage() {}
func (*ParaBlock2MainMap) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{19}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{19}
}
func (m *ParaBlock2MainMap) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaBlock2MainMap.Unmarshal(m, b)
......@@ -1355,7 +1355,7 @@ func (m *ParaBlock2MainInfo) Reset() { *m = ParaBlock2MainInfo{} }
func (m *ParaBlock2MainInfo) String() string { return proto.CompactTextString(m) }
func (*ParaBlock2MainInfo) ProtoMessage() {}
func (*ParaBlock2MainInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{20}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{20}
}
func (m *ParaBlock2MainInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaBlock2MainInfo.Unmarshal(m, b)
......@@ -1407,7 +1407,7 @@ func (m *ParacrossNodeStatus) Reset() { *m = ParacrossNodeStatus{} }
func (m *ParacrossNodeStatus) String() string { return proto.CompactTextString(m) }
func (*ParacrossNodeStatus) ProtoMessage() {}
func (*ParacrossNodeStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{21}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{21}
}
func (m *ParacrossNodeStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossNodeStatus.Unmarshal(m, b)
......@@ -1536,7 +1536,7 @@ func (m *SelfConsensStages) Reset() { *m = SelfConsensStages{} }
func (m *SelfConsensStages) String() string { return proto.CompactTextString(m) }
func (*SelfConsensStages) ProtoMessage() {}
func (*SelfConsensStages) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{22}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{22}
}
func (m *SelfConsensStages) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SelfConsensStages.Unmarshal(m, b)
......@@ -1575,7 +1575,7 @@ func (m *SelfConsensStage) Reset() { *m = SelfConsensStage{} }
func (m *SelfConsensStage) String() string { return proto.CompactTextString(m) }
func (*SelfConsensStage) ProtoMessage() {}
func (*SelfConsensStage) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{23}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{23}
}
func (m *SelfConsensStage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SelfConsensStage.Unmarshal(m, b)
......@@ -1625,7 +1625,7 @@ func (m *SelfConsensStageInfo) Reset() { *m = SelfConsensStageInfo{} }
func (m *SelfConsensStageInfo) String() string { return proto.CompactTextString(m) }
func (*SelfConsensStageInfo) ProtoMessage() {}
func (*SelfConsensStageInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{24}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{24}
}
func (m *SelfConsensStageInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SelfConsensStageInfo.Unmarshal(m, b)
......@@ -1699,7 +1699,7 @@ func (m *LocalSelfConsStageInfo) Reset() { *m = LocalSelfConsStageInfo{}
func (m *LocalSelfConsStageInfo) String() string { return proto.CompactTextString(m) }
func (*LocalSelfConsStageInfo) ProtoMessage() {}
func (*LocalSelfConsStageInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{25}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{25}
}
func (m *LocalSelfConsStageInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LocalSelfConsStageInfo.Unmarshal(m, b)
......@@ -1746,7 +1746,7 @@ func (m *ConfigVoteInfo) Reset() { *m = ConfigVoteInfo{} }
func (m *ConfigVoteInfo) String() string { return proto.CompactTextString(m) }
func (*ConfigVoteInfo) ProtoMessage() {}
func (*ConfigVoteInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{26}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{26}
}
func (m *ConfigVoteInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ConfigVoteInfo.Unmarshal(m, b)
......@@ -1791,7 +1791,7 @@ func (m *ConfigCancelInfo) Reset() { *m = ConfigCancelInfo{} }
func (m *ConfigCancelInfo) String() string { return proto.CompactTextString(m) }
func (*ConfigCancelInfo) ProtoMessage() {}
func (*ConfigCancelInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{27}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{27}
}
func (m *ConfigCancelInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ConfigCancelInfo.Unmarshal(m, b)
......@@ -1837,7 +1837,7 @@ func (m *ParaStageConfig) Reset() { *m = ParaStageConfig{} }
func (m *ParaStageConfig) String() string { return proto.CompactTextString(m) }
func (*ParaStageConfig) ProtoMessage() {}
func (*ParaStageConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{28}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{28}
}
func (m *ParaStageConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaStageConfig.Unmarshal(m, b)
......@@ -2026,7 +2026,7 @@ func (m *ReceiptSelfConsStageConfig) Reset() { *m = ReceiptSelfConsStage
func (m *ReceiptSelfConsStageConfig) String() string { return proto.CompactTextString(m) }
func (*ReceiptSelfConsStageConfig) ProtoMessage() {}
func (*ReceiptSelfConsStageConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{29}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{29}
}
func (m *ReceiptSelfConsStageConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptSelfConsStageConfig.Unmarshal(m, b)
......@@ -2076,7 +2076,7 @@ func (m *ReceiptSelfConsStageVoteDone) Reset() { *m = ReceiptSelfConsSta
func (m *ReceiptSelfConsStageVoteDone) String() string { return proto.CompactTextString(m) }
func (*ReceiptSelfConsStageVoteDone) ProtoMessage() {}
func (*ReceiptSelfConsStageVoteDone) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{30}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{30}
}
func (m *ReceiptSelfConsStageVoteDone) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptSelfConsStageVoteDone.Unmarshal(m, b)
......@@ -2150,7 +2150,7 @@ func (m *ReceiptSelfConsStagesUpdate) Reset() { *m = ReceiptSelfConsStag
func (m *ReceiptSelfConsStagesUpdate) String() string { return proto.CompactTextString(m) }
func (*ReceiptSelfConsStagesUpdate) ProtoMessage() {}
func (*ReceiptSelfConsStagesUpdate) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{31}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{31}
}
func (m *ReceiptSelfConsStagesUpdate) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptSelfConsStagesUpdate.Unmarshal(m, b)
......@@ -2201,7 +2201,7 @@ func (m *ReqQuerySelfStages) Reset() { *m = ReqQuerySelfStages{} }
func (m *ReqQuerySelfStages) String() string { return proto.CompactTextString(m) }
func (*ReqQuerySelfStages) ProtoMessage() {}
func (*ReqQuerySelfStages) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{32}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{32}
}
func (m *ReqQuerySelfStages) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReqQuerySelfStages.Unmarshal(m, b)
......@@ -2274,7 +2274,7 @@ func (m *ReplyQuerySelfStages) Reset() { *m = ReplyQuerySelfStages{} }
func (m *ReplyQuerySelfStages) String() string { return proto.CompactTextString(m) }
func (*ReplyQuerySelfStages) ProtoMessage() {}
func (*ReplyQuerySelfStages) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{33}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{33}
}
func (m *ReplyQuerySelfStages) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReplyQuerySelfStages.Unmarshal(m, b)
......@@ -2312,7 +2312,7 @@ func (m *ParacrossCommitAction) Reset() { *m = ParacrossCommitAction{} }
func (m *ParacrossCommitAction) String() string { return proto.CompactTextString(m) }
func (*ParacrossCommitAction) ProtoMessage() {}
func (*ParacrossCommitAction) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{34}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{34}
}
func (m *ParacrossCommitAction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossCommitAction.Unmarshal(m, b)
......@@ -2351,7 +2351,7 @@ func (m *ParacrossMinerAction) Reset() { *m = ParacrossMinerAction{} }
func (m *ParacrossMinerAction) String() string { return proto.CompactTextString(m) }
func (*ParacrossMinerAction) ProtoMessage() {}
func (*ParacrossMinerAction) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{35}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{35}
}
func (m *ParacrossMinerAction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossMinerAction.Unmarshal(m, b)
......@@ -2408,7 +2408,7 @@ func (m *ParacrossAction) Reset() { *m = ParacrossAction{} }
func (m *ParacrossAction) String() string { return proto.CompactTextString(m) }
func (*ParacrossAction) ProtoMessage() {}
func (*ParacrossAction) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{36}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{36}
}
func (m *ParacrossAction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossAction.Unmarshal(m, b)
......@@ -2817,7 +2817,7 @@ func (m *ReceiptParacrossCommit) Reset() { *m = ReceiptParacrossCommit{}
func (m *ReceiptParacrossCommit) String() string { return proto.CompactTextString(m) }
func (*ReceiptParacrossCommit) ProtoMessage() {}
func (*ReceiptParacrossCommit) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{37}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{37}
}
func (m *ReceiptParacrossCommit) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParacrossCommit.Unmarshal(m, b)
......@@ -2876,7 +2876,7 @@ func (m *ReceiptParacrossMiner) Reset() { *m = ReceiptParacrossMiner{} }
func (m *ReceiptParacrossMiner) String() string { return proto.CompactTextString(m) }
func (*ReceiptParacrossMiner) ProtoMessage() {}
func (*ReceiptParacrossMiner) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{38}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{38}
}
func (m *ReceiptParacrossMiner) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParacrossMiner.Unmarshal(m, b)
......@@ -2918,6 +2918,7 @@ type ReceiptParacrossDone struct {
CrossTxHashs [][]byte `protobuf:"bytes,12,rep,name=crossTxHashs,proto3" json:"crossTxHashs,omitempty"`
MainBlockHash []byte `protobuf:"bytes,13,opt,name=mainBlockHash,proto3" json:"mainBlockHash,omitempty"`
MainBlockHeight int64 `protobuf:"varint,14,opt,name=mainBlockHeight,proto3" json:"mainBlockHeight,omitempty"`
ChainExecHeight int64 `protobuf:"varint,15,opt,name=chainExecHeight,proto3" json:"chainExecHeight,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -2927,7 +2928,7 @@ func (m *ReceiptParacrossDone) Reset() { *m = ReceiptParacrossDone{} }
func (m *ReceiptParacrossDone) String() string { return proto.CompactTextString(m) }
func (*ReceiptParacrossDone) ProtoMessage() {}
func (*ReceiptParacrossDone) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{39}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{39}
}
func (m *ReceiptParacrossDone) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParacrossDone.Unmarshal(m, b)
......@@ -3045,6 +3046,13 @@ func (m *ReceiptParacrossDone) GetMainBlockHeight() int64 {
return 0
}
func (m *ReceiptParacrossDone) GetChainExecHeight() int64 {
if m != nil {
return m.ChainExecHeight
}
return 0
}
type ReceiptParacrossRecord struct {
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
Status *ParacrossNodeStatus `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
......@@ -3057,7 +3065,7 @@ func (m *ReceiptParacrossRecord) Reset() { *m = ReceiptParacrossRecord{}
func (m *ReceiptParacrossRecord) String() string { return proto.CompactTextString(m) }
func (*ReceiptParacrossRecord) ProtoMessage() {}
func (*ReceiptParacrossRecord) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{40}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{40}
}
func (m *ReceiptParacrossRecord) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptParacrossRecord.Unmarshal(m, b)
......@@ -3104,7 +3112,7 @@ func (m *ParacrossTx) Reset() { *m = ParacrossTx{} }
func (m *ParacrossTx) String() string { return proto.CompactTextString(m) }
func (*ParacrossTx) ProtoMessage() {}
func (*ParacrossTx) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{41}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{41}
}
func (m *ParacrossTx) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossTx.Unmarshal(m, b)
......@@ -3144,7 +3152,7 @@ func (m *ReqParacrossTitleHeight) Reset() { *m = ReqParacrossTitleHeight
func (m *ReqParacrossTitleHeight) String() string { return proto.CompactTextString(m) }
func (*ReqParacrossTitleHeight) ProtoMessage() {}
func (*ReqParacrossTitleHeight) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{42}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{42}
}
func (m *ReqParacrossTitleHeight) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReqParacrossTitleHeight.Unmarshal(m, b)
......@@ -3187,6 +3195,8 @@ type RespParacrossDone struct {
StateHash string `protobuf:"bytes,6,opt,name=stateHash,proto3" json:"stateHash,omitempty"`
TxCounts uint32 `protobuf:"varint,7,opt,name=txCounts,proto3" json:"txCounts,omitempty"`
TxResult string `protobuf:"bytes,8,opt,name=txResult,proto3" json:"txResult,omitempty"`
// commitDone chainHeight
ChainExecHeight int64 `protobuf:"varint,9,opt,name=chainExecHeight,proto3" json:"chainExecHeight,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -3196,7 +3206,7 @@ func (m *RespParacrossDone) Reset() { *m = RespParacrossDone{} }
func (m *RespParacrossDone) String() string { return proto.CompactTextString(m) }
func (*RespParacrossDone) ProtoMessage() {}
func (*RespParacrossDone) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{43}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{43}
}
func (m *RespParacrossDone) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RespParacrossDone.Unmarshal(m, b)
......@@ -3272,6 +3282,13 @@ func (m *RespParacrossDone) GetTxResult() string {
return ""
}
func (m *RespParacrossDone) GetChainExecHeight() int64 {
if m != nil {
return m.ChainExecHeight
}
return 0
}
type RespParacrossTitles struct {
Titles []*RespParacrossDone `protobuf:"bytes,1,rep,name=titles,proto3" json:"titles,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
......@@ -3283,7 +3300,7 @@ func (m *RespParacrossTitles) Reset() { *m = RespParacrossTitles{} }
func (m *RespParacrossTitles) String() string { return proto.CompactTextString(m) }
func (*RespParacrossTitles) ProtoMessage() {}
func (*RespParacrossTitles) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{44}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{44}
}
func (m *RespParacrossTitles) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RespParacrossTitles.Unmarshal(m, b)
......@@ -3322,7 +3339,7 @@ func (m *ReqParacrossTitleHash) Reset() { *m = ReqParacrossTitleHash{} }
func (m *ReqParacrossTitleHash) String() string { return proto.CompactTextString(m) }
func (*ReqParacrossTitleHash) ProtoMessage() {}
func (*ReqParacrossTitleHash) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{45}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{45}
}
func (m *ReqParacrossTitleHash) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReqParacrossTitleHash.Unmarshal(m, b)
......@@ -3381,7 +3398,7 @@ func (m *ParacrossAsset) Reset() { *m = ParacrossAsset{} }
func (m *ParacrossAsset) String() string { return proto.CompactTextString(m) }
func (*ParacrossAsset) ProtoMessage() {}
func (*ParacrossAsset) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{46}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{46}
}
func (m *ParacrossAsset) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossAsset.Unmarshal(m, b)
......@@ -3502,7 +3519,7 @@ func (m *ParacrossAssetRsp) Reset() { *m = ParacrossAssetRsp{} }
func (m *ParacrossAssetRsp) String() string { return proto.CompactTextString(m) }
func (*ParacrossAssetRsp) ProtoMessage() {}
func (*ParacrossAssetRsp) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{47}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{47}
}
func (m *ParacrossAssetRsp) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParacrossAssetRsp.Unmarshal(m, b)
......@@ -3615,7 +3632,7 @@ func (m *ParaLocalDbBlock) Reset() { *m = ParaLocalDbBlock{} }
func (m *ParaLocalDbBlock) String() string { return proto.CompactTextString(m) }
func (*ParaLocalDbBlock) ProtoMessage() {}
func (*ParaLocalDbBlock) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{48}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{48}
}
func (m *ParaLocalDbBlock) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaLocalDbBlock.Unmarshal(m, b)
......@@ -3693,7 +3710,7 @@ func (m *ParaLocalDbBlockInfo) Reset() { *m = ParaLocalDbBlockInfo{} }
func (m *ParaLocalDbBlockInfo) String() string { return proto.CompactTextString(m) }
func (*ParaLocalDbBlockInfo) ProtoMessage() {}
func (*ParaLocalDbBlockInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_paracross_313193799a5638f5, []int{49}
return fileDescriptor_paracross_86d4df6243fac7f6, []int{49}
}
func (m *ParaLocalDbBlockInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ParaLocalDbBlockInfo.Unmarshal(m, b)
......@@ -3820,11 +3837,6 @@ const _ = grpc.SupportPackageIsVersion4
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ParacrossClient interface {
GetTitle(ctx context.Context, in *types.ReqString, opts ...grpc.CallOption) (*ParacrossConsensusStatus, error)
ListTitles(ctx context.Context, in *types.ReqNil, opts ...grpc.CallOption) (*RespParacrossTitles, error)
GetDoneTitleHeight(ctx context.Context, in *ReqParacrossTitleHeight, opts ...grpc.CallOption) (*RespParacrossDone, error)
GetTitleHeight(ctx context.Context, in *ReqParacrossTitleHeight, opts ...grpc.CallOption) (*ParacrossHeightStatusRsp, error)
GetAssetTxResult(ctx context.Context, in *types.ReqString, opts ...grpc.CallOption) (*ParacrossAssetRsp, error)
IsSync(ctx context.Context, in *types.ReqNil, opts ...grpc.CallOption) (*types.IsCaughtUp, error)
}
......@@ -3836,51 +3848,6 @@ func NewParacrossClient(cc *grpc.ClientConn) ParacrossClient {
return &paracrossClient{cc}
}
func (c *paracrossClient) GetTitle(ctx context.Context, in *types.ReqString, opts ...grpc.CallOption) (*ParacrossConsensusStatus, error) {
out := new(ParacrossConsensusStatus)
err := c.cc.Invoke(ctx, "/types.paracross/GetTitle", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *paracrossClient) ListTitles(ctx context.Context, in *types.ReqNil, opts ...grpc.CallOption) (*RespParacrossTitles, error) {
out := new(RespParacrossTitles)
err := c.cc.Invoke(ctx, "/types.paracross/ListTitles", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *paracrossClient) GetDoneTitleHeight(ctx context.Context, in *ReqParacrossTitleHeight, opts ...grpc.CallOption) (*RespParacrossDone, error) {
out := new(RespParacrossDone)
err := c.cc.Invoke(ctx, "/types.paracross/GetDoneTitleHeight", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *paracrossClient) GetTitleHeight(ctx context.Context, in *ReqParacrossTitleHeight, opts ...grpc.CallOption) (*ParacrossHeightStatusRsp, error) {
out := new(ParacrossHeightStatusRsp)
err := c.cc.Invoke(ctx, "/types.paracross/GetTitleHeight", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *paracrossClient) GetAssetTxResult(ctx context.Context, in *types.ReqString, opts ...grpc.CallOption) (*ParacrossAssetRsp, error) {
out := new(ParacrossAssetRsp)
err := c.cc.Invoke(ctx, "/types.paracross/GetAssetTxResult", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *paracrossClient) IsSync(ctx context.Context, in *types.ReqNil, opts ...grpc.CallOption) (*types.IsCaughtUp, error) {
out := new(types.IsCaughtUp)
err := c.cc.Invoke(ctx, "/types.paracross/IsSync", in, out, opts...)
......@@ -3892,11 +3859,6 @@ func (c *paracrossClient) IsSync(ctx context.Context, in *types.ReqNil, opts ...
// ParacrossServer is the server API for Paracross service.
type ParacrossServer interface {
GetTitle(context.Context, *types.ReqString) (*ParacrossConsensusStatus, error)
ListTitles(context.Context, *types.ReqNil) (*RespParacrossTitles, error)
GetDoneTitleHeight(context.Context, *ReqParacrossTitleHeight) (*RespParacrossDone, error)
GetTitleHeight(context.Context, *ReqParacrossTitleHeight) (*ParacrossHeightStatusRsp, error)
GetAssetTxResult(context.Context, *types.ReqString) (*ParacrossAssetRsp, error)
IsSync(context.Context, *types.ReqNil) (*types.IsCaughtUp, error)
}
......@@ -3904,96 +3866,6 @@ func RegisterParacrossServer(s *grpc.Server, srv ParacrossServer) {
s.RegisterService(&_Paracross_serviceDesc, srv)
}
func _Paracross_GetTitle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types.ReqString)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ParacrossServer).GetTitle(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.paracross/GetTitle",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ParacrossServer).GetTitle(ctx, req.(*types.ReqString))
}
return interceptor(ctx, in, info, handler)
}
func _Paracross_ListTitles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types.ReqNil)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ParacrossServer).ListTitles(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.paracross/ListTitles",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ParacrossServer).ListTitles(ctx, req.(*types.ReqNil))
}
return interceptor(ctx, in, info, handler)
}
func _Paracross_GetDoneTitleHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReqParacrossTitleHeight)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ParacrossServer).GetDoneTitleHeight(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.paracross/GetDoneTitleHeight",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ParacrossServer).GetDoneTitleHeight(ctx, req.(*ReqParacrossTitleHeight))
}
return interceptor(ctx, in, info, handler)
}
func _Paracross_GetTitleHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReqParacrossTitleHeight)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ParacrossServer).GetTitleHeight(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.paracross/GetTitleHeight",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ParacrossServer).GetTitleHeight(ctx, req.(*ReqParacrossTitleHeight))
}
return interceptor(ctx, in, info, handler)
}
func _Paracross_GetAssetTxResult_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types.ReqString)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ParacrossServer).GetAssetTxResult(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.paracross/GetAssetTxResult",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ParacrossServer).GetAssetTxResult(ctx, req.(*types.ReqString))
}
return interceptor(ctx, in, info, handler)
}
func _Paracross_IsSync_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types.ReqNil)
if err := dec(in); err != nil {
......@@ -4017,26 +3889,6 @@ var _Paracross_serviceDesc = grpc.ServiceDesc{
HandlerType: (*ParacrossServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetTitle",
Handler: _Paracross_GetTitle_Handler,
},
{
MethodName: "ListTitles",
Handler: _Paracross_ListTitles_Handler,
},
{
MethodName: "GetDoneTitleHeight",
Handler: _Paracross_GetDoneTitleHeight_Handler,
},
{
MethodName: "GetTitleHeight",
Handler: _Paracross_GetTitleHeight_Handler,
},
{
MethodName: "GetAssetTxResult",
Handler: _Paracross_GetAssetTxResult_Handler,
},
{
MethodName: "IsSync",
Handler: _Paracross_IsSync_Handler,
},
......@@ -4045,158 +3897,153 @@ var _Paracross_serviceDesc = grpc.ServiceDesc{
Metadata: "paracross.proto",
}
func init() { proto.RegisterFile("paracross.proto", fileDescriptor_paracross_313193799a5638f5) }
var fileDescriptor_paracross_313193799a5638f5 = []byte{
// 2397 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0xcd, 0x73, 0x1c, 0x47,
0x15, 0xdf, 0xd9, 0x2f, 0x69, 0x9f, 0x3e, 0x2c, 0x4d, 0x64, 0x79, 0x91, 0x1d, 0x47, 0xd5, 0x65,
0x52, 0x82, 0x38, 0x36, 0x96, 0xc1, 0x54, 0x8a, 0xa2, 0x88, 0x2d, 0xc7, 0x5a, 0x55, 0xec, 0x54,
0x32, 0x52, 0xe0, 0xc0, 0x85, 0xd1, 0x6e, 0x5b, 0x9a, 0x62, 0x77, 0x66, 0x3c, 0xdd, 0x9b, 0x48,
0x5c, 0x28, 0x0a, 0x38, 0xc3, 0x89, 0x2a, 0x38, 0xe4, 0x02, 0x67, 0xaa, 0xf8, 0x07, 0x38, 0x70,
0x0c, 0xa7, 0x70, 0xe0, 0xc0, 0x8d, 0x1b, 0x77, 0x0e, 0x5c, 0xa9, 0x7e, 0xdd, 0x3d, 0xfd, 0xb1,
0xb3, 0x63, 0xd9, 0xf1, 0x25, 0xb7, 0xed, 0xd7, 0xaf, 0x5f, 0xbf, 0xf7, 0xeb, 0xf7, 0x5e, 0xbf,
0xd7, 0xb3, 0x70, 0x29, 0x8f, 0x8b, 0x78, 0x58, 0x64, 0x8c, 0xdd, 0xca, 0x8b, 0x8c, 0x67, 0x61,
0x87, 0x9f, 0xe7, 0x94, 0x6d, 0xad, 0xf3, 0x22, 0x4e, 0x59, 0x3c, 0xe4, 0x49, 0x96, 0xca, 0x99,
0xad, 0xe5, 0x61, 0x36, 0x99, 0x94, 0xa3, 0xb5, 0xe3, 0x71, 0x36, 0xfc, 0xe9, 0xf0, 0x34, 0x4e,
0x14, 0x85, 0x3c, 0x86, 0xcd, 0x0f, 0xb5, 0xb0, 0x43, 0x1e, 0xf3, 0x29, 0x7b, 0x48, 0x79, 0x9c,
0x8c, 0x59, 0xb8, 0x01, 0x9d, 0x78, 0x34, 0x2a, 0x58, 0x3f, 0xd8, 0x6e, 0xed, 0xf4, 0x22, 0x39,
0x08, 0xaf, 0x41, 0x0f, 0x65, 0x0c, 0x62, 0x76, 0xda, 0x6f, 0x6e, 0xb7, 0x76, 0x96, 0x23, 0x43,
0x20, 0x3f, 0x86, 0xab, 0x9e, 0xb4, 0x07, 0x62, 0x4e, 0x8b, 0xbc, 0x0e, 0x50, 0xf2, 0x4a, 0xb9,
0xcb, 0x91, 0x45, 0x11, 0xc2, 0xf9, 0x59, 0x44, 0xd9, 0x74, 0xcc, 0x99, 0x16, 0x5e, 0x12, 0xc8,
0x1f, 0x9a, 0x70, 0xb9, 0x94, 0x3e, 0xa0, 0xc9, 0xc9, 0x29, 0x97, 0x7b, 0x84, 0x9b, 0xd0, 0x65,
0xf8, 0xab, 0x1f, 0x6c, 0x07, 0x3b, 0x9d, 0x48, 0x8d, 0x84, 0x09, 0x3c, 0xe1, 0x63, 0xda, 0x6f,
0x6e, 0x07, 0xc2, 0x04, 0x1c, 0x08, 0xee, 0x53, 0x5c, 0xdd, 0x6f, 0x6d, 0x07, 0x3b, 0xad, 0x48,
0x8d, 0xc2, 0xef, 0xc2, 0xc2, 0x48, 0x2a, 0xda, 0x6f, 0x6f, 0x07, 0x3b, 0x4b, 0xbb, 0xaf, 0xdf,
0x42, 0x58, 0x6f, 0x55, 0x03, 0x14, 0x69, 0x6e, 0x61, 0xd6, 0x24, 0x4e, 0x52, 0xa9, 0x52, 0xbf,
0x83, 0x42, 0x2d, 0x4a, 0xb8, 0x05, 0x8b, 0x38, 0x12, 0x90, 0x75, 0xb7, 0x83, 0x9d, 0xe5, 0xa8,
0x1c, 0x87, 0x8f, 0x60, 0xf9, 0xd8, 0x82, 0xa8, 0xbf, 0x80, 0x3b, 0x93, 0xea, 0x9d, 0x6d, 0x30,
0x23, 0x67, 0x1d, 0xf9, 0x4f, 0x00, 0xfd, 0x4a, 0x70, 0x22, 0x96, 0xbf, 0x22, 0x7c, 0x5c, 0x33,
0xdb, 0xb5, 0x66, 0x76, 0x50, 0xa0, 0x31, 0x73, 0x1b, 0x96, 0x84, 0x23, 0x26, 0xfc, 0x3e, 0xba,
0x54, 0x17, 0x5d, 0xca, 0x26, 0x85, 0x3b, 0x70, 0x49, 0x0e, 0x1f, 0x94, 0xee, 0xb5, 0x80, 0x5c,
0x3e, 0x99, 0xfc, 0x3e, 0x80, 0x4b, 0x1e, 0x30, 0xc6, 0x92, 0xa0, 0xda, 0x92, 0xa6, 0x63, 0x89,
0xe3, 0xc4, 0x2d, 0x3c, 0x11, 0x43, 0x78, 0x61, 0x3b, 0xad, 0xe3, 0x24, 0x7f, 0xb2, 0x8f, 0x61,
0x2f, 0x4b, 0x19, 0x4d, 0xd9, 0xb4, 0x5e, 0x49, 0x01, 0xcd, 0xa9, 0xd9, 0x4f, 0x6a, 0x6a, 0x93,
0xc2, 0x1b, 0xb0, 0x32, 0x94, 0xa2, 0x06, 0xf6, 0xb9, 0xb8, 0xc4, 0xf0, 0x9b, 0xb0, 0xa6, 0x08,
0x06, 0xc1, 0x36, 0x6e, 0x34, 0x43, 0x27, 0xbf, 0x0b, 0x20, 0x14, 0x6a, 0x7e, 0x90, 0x8d, 0xa8,
0x80, 0x7f, 0x2f, 0x4b, 0x9f, 0x26, 0x27, 0x73, 0x14, 0x5c, 0x85, 0x66, 0x96, 0xa3, 0x5e, 0x2b,
0x51, 0x33, 0xcb, 0xc5, 0x38, 0x19, 0xa1, 0x0e, 0xbd, 0xa8, 0x99, 0x8c, 0xc2, 0x10, 0xda, 0x22,
0x37, 0xa8, 0xcd, 0xf0, 0xb7, 0x90, 0xf4, 0x49, 0x3c, 0x9e, 0x52, 0x04, 0x68, 0x25, 0x92, 0x03,
0xe9, 0x05, 0x49, 0xca, 0x1e, 0x15, 0xd9, 0xcf, 0x68, 0x8a, 0xb1, 0x20, 0x4c, 0x35, 0x24, 0xf2,
0xae, 0xd1, 0xeb, 0x87, 0x19, 0xa7, 0xd2, 0xbb, 0xe7, 0xa4, 0x22, 0xb1, 0x47, 0xc6, 0xa9, 0xcc,
0x14, 0xbd, 0x48, 0x0e, 0xc8, 0x6f, 0x03, 0xd8, 0xb0, 0x4d, 0x3b, 0x18, 0x29, 0xf4, 0xb5, 0x9a,
0x81, 0xa5, 0xe6, 0x75, 0x80, 0xbc, 0xc8, 0xf2, 0x8c, 0xc5, 0xe3, 0x83, 0x91, 0x8a, 0x02, 0x8b,
0x22, 0x1c, 0xe8, 0xd9, 0x34, 0xe1, 0x07, 0xda, 0x5c, 0x35, 0xb2, 0x02, 0xaa, 0x5d, 0x1d, 0x50,
0x1d, 0x0b, 0x40, 0xf2, 0xbf, 0x00, 0xd6, 0xb4, 0x4a, 0xa5, 0x3a, 0x12, 0xc5, 0xa0, 0x44, 0xd1,
0x88, 0x6c, 0x56, 0x8b, 0x6c, 0xd9, 0x67, 0x72, 0x1d, 0x80, 0xc7, 0xc5, 0x09, 0xc5, 0xe0, 0x51,
0xc8, 0x5b, 0x14, 0x1f, 0xe9, 0xce, 0x0c, 0xd2, 0xe1, 0x6d, 0x8d, 0x5e, 0x17, 0x33, 0xce, 0xd7,
0xac, 0x8c, 0xe3, 0xa2, 0xaf, 0x80, 0x15, 0x6e, 0xff, 0xb4, 0xc8, 0x26, 0xb8, 0xe1, 0x82, 0x0c,
0x6f, 0x3d, 0xb6, 0x02, 0x6d, 0xd1, 0x0e, 0x34, 0xf2, 0xd7, 0x00, 0x2e, 0x47, 0x74, 0x48, 0x93,
0x9c, 0x6b, 0xc1, 0xca, 0xd5, 0xaa, 0x4e, 0xe3, 0x0e, 0x74, 0x87, 0x38, 0x8b, 0x10, 0xcc, 0xea,
0x64, 0x3c, 0x35, 0x52, 0x8c, 0xe1, 0x5b, 0xd0, 0xce, 0x0b, 0xfa, 0x09, 0x82, 0xb3, 0xb4, 0x7b,
0xc5, 0x5b, 0xa0, 0xc1, 0x8e, 0x90, 0x29, 0xbc, 0x03, 0x0b, 0xc3, 0x69, 0x51, 0xd0, 0x94, 0xab,
0x04, 0x3f, 0x97, 0x5f, 0xf3, 0x91, 0x3f, 0x06, 0xf0, 0xba, 0x67, 0x80, 0xd0, 0x42, 0xb0, 0x7d,
0x9c, 0x8f, 0x62, 0x4e, 0x1d, 0x58, 0x02, 0x0f, 0x96, 0xdb, 0x4a, 0x3b, 0x69, 0xce, 0xd5, 0x0a,
0x73, 0x3c, 0x0d, 0xbf, 0x63, 0x34, 0x6c, 0x3d, 0x7f, 0x4d, 0xa9, 0xe5, 0x7f, 0x03, 0xb8, 0xe2,
0x69, 0x89, 0xe7, 0x97, 0xa5, 0x74, 0xc6, 0xcf, 0xaa, 0x73, 0xbe, 0xeb, 0x4f, 0xad, 0x19, 0x7f,
0x12, 0xf3, 0x19, 0x8f, 0xc7, 0x42, 0xb4, 0x76, 0x7a, 0x8b, 0x82, 0x37, 0xb7, 0x18, 0x89, 0x6d,
0xd1, 0xdb, 0x3a, 0x91, 0x21, 0x60, 0xc6, 0xcc, 0x18, 0xc7, 0xc9, 0x2e, 0x4e, 0x96, 0xe3, 0xb0,
0x0f, 0x0b, 0xc2, 0xbf, 0x22, 0xc6, 0x95, 0x57, 0xe9, 0xa1, 0xd8, 0x73, 0x94, 0xa5, 0x54, 0x1a,
0x8b, 0x8e, 0xd5, 0x89, 0x2c, 0x0a, 0xf9, 0x65, 0x00, 0xaf, 0x69, 0x73, 0xf7, 0x8b, 0x6c, 0x9a,
0x7f, 0xa9, 0x2c, 0x56, 0xe6, 0x18, 0x19, 0x4c, 0x2a, 0xc7, 0x3c, 0x37, 0x8e, 0xc8, 0xdf, 0x7d,
0x2d, 0x5e, 0x49, 0x7c, 0x6f, 0xc3, 0x92, 0x41, 0x5f, 0xeb, 0x64, 0x93, 0x2e, 0x10, 0xe1, 0xb6,
0x67, 0x76, 0xe7, 0x06, 0xec, 0x82, 0x13, 0xb0, 0x9f, 0x07, 0xb0, 0xe5, 0x79, 0x92, 0x0d, 0x6d,
0x55, 0xd4, 0xee, 0x7a, 0x51, 0xbb, 0xe5, 0xb9, 0xac, 0xb5, 0xbe, 0x0c, 0xdb, 0x5b, 0x4e, 0xd8,
0x56, 0xae, 0x70, 0xe2, 0xe2, 0xdb, 0x7e, 0xe4, 0xd6, 0x2d, 0x29, 0xc3, 0xe2, 0x14, 0x36, 0x22,
0xfa, 0xac, 0xbc, 0x8e, 0x31, 0xc2, 0xd3, 0xa7, 0xd9, 0x7c, 0x07, 0x49, 0xf4, 0x1d, 0x60, 0x5f,
0x6b, 0x2d, 0xcb, 0xd6, 0x39, 0x79, 0x9f, 0xec, 0xc1, 0x66, 0x44, 0x59, 0xee, 0x6c, 0x25, 0x8f,
0xe9, 0x1b, 0xd0, 0x4a, 0x46, 0xf2, 0xe2, 0xaa, 0xc9, 0x37, 0x82, 0x87, 0xec, 0x8b, 0x20, 0xf6,
0x84, 0xa0, 0x5d, 0x2c, 0xbc, 0x69, 0x4b, 0xa9, 0xb3, 0x1d, 0x05, 0xfd, 0x3a, 0x80, 0x75, 0x31,
0x89, 0xf7, 0xfd, 0xee, 0x93, 0x38, 0x49, 0x9f, 0xc4, 0xb9, 0x75, 0xe4, 0xc1, 0xfc, 0x62, 0x48,
0x9a, 0x3f, 0xb7, 0x18, 0x6a, 0xd5, 0x16, 0x43, 0x6d, 0xb7, 0xe8, 0x23, 0x0f, 0xe5, 0x65, 0x6e,
0xd4, 0x40, 0xf4, 0x6f, 0x41, 0x27, 0xe1, 0x74, 0xa2, 0xad, 0xe9, 0x5b, 0xd6, 0x38, 0x0a, 0x47,
0x92, 0x8d, 0xfc, 0xbb, 0x25, 0x03, 0xac, 0xc4, 0x44, 0x05, 0xd8, 0x0d, 0x58, 0x11, 0x3b, 0x99,
0x62, 0x27, 0xc0, 0x5a, 0xcc, 0x25, 0x8a, 0xb2, 0xd2, 0x10, 0xec, 0x0a, 0xcb, 0x27, 0xcf, 0x09,
0x44, 0x83, 0x5a, 0xdb, 0x41, 0x8d, 0xc0, 0x72, 0x5e, 0x50, 0xb3, 0xb9, 0x2c, 0x04, 0x1d, 0x9a,
0x8b, 0x6c, 0xd7, 0x2f, 0x33, 0xa5, 0x04, 0x61, 0x0c, 0x55, 0xd5, 0xae, 0x96, 0x50, 0xd2, 0x84,
0x04, 0x56, 0x32, 0x2c, 0x4a, 0x09, 0x25, 0x41, 0x60, 0xcf, 0xcf, 0xf6, 0xb2, 0x69, 0xca, 0x59,
0xbf, 0x87, 0x89, 0xad, 0x1c, 0xcb, 0x39, 0xd9, 0x39, 0xf5, 0x41, 0x16, 0xa9, 0x7a, 0x2c, 0x52,
0x2e, 0x3f, 0x93, 0x3d, 0xd8, 0x12, 0x36, 0x59, 0x7a, 0x88, 0x95, 0xa6, 0x80, 0xf9, 0x48, 0x2f,
0x5d, 0x96, 0x98, 0x3a, 0x44, 0xa1, 0xb9, 0x22, 0x48, 0x21, 0x2b, 0x28, 0xc4, 0xa1, 0x85, 0x37,
0x61, 0x3d, 0xcd, 0xd2, 0x3d, 0x2c, 0xdd, 0x8f, 0xb4, 0x92, 0xab, 0xa8, 0xe4, 0xec, 0x04, 0x79,
0x00, 0xeb, 0x87, 0x74, 0xfc, 0x54, 0x15, 0xcc, 0x87, 0x3c, 0x3e, 0xa1, 0x2c, 0x7c, 0xdb, 0x75,
0x14, 0x1d, 0x3c, 0x3e, 0xa3, 0xf6, 0x93, 0xc7, 0xb0, 0xe6, 0x4f, 0x89, 0x24, 0xc9, 0x78, 0x5c,
0xf0, 0x81, 0xed, 0xf8, 0x36, 0x49, 0x9c, 0x2f, 0x4d, 0xe3, 0x63, 0x75, 0x1f, 0xae, 0x44, 0x6a,
0x44, 0xfe, 0x15, 0xc0, 0x86, 0x2f, 0x0e, 0xdd, 0xb7, 0x3e, 0xaf, 0xaf, 0x94, 0x79, 0xfd, 0x6d,
0xe8, 0x30, 0xb1, 0xc8, 0x2b, 0x4d, 0x66, 0xb5, 0x47, 0x2e, 0x27, 0x59, 0xb7, 0xbd, 0x64, 0x7d,
0x1d, 0x80, 0x9e, 0xd1, 0xa1, 0xdb, 0x5f, 0x1a, 0xca, 0x0b, 0x97, 0x72, 0x84, 0xc2, 0xe6, 0xe3,
0x6c, 0x18, 0x8f, 0xb5, 0x32, 0xc6, 0xba, 0x3b, 0x5a, 0xeb, 0xc0, 0x29, 0x3f, 0xaa, 0x90, 0xd0,
0x9a, 0xa3, 0x37, 0x1d, 0xa4, 0x23, 0x7a, 0xa6, 0xb2, 0x87, 0x1e, 0x92, 0x7b, 0xb0, 0x2a, 0xf3,
0xbe, 0xd0, 0xa0, 0x12, 0xbc, 0xb2, 0x4d, 0x68, 0x5a, 0x6d, 0x02, 0x21, 0xb0, 0x26, 0xd7, 0xed,
0xc5, 0xe9, 0x90, 0x8e, 0xab, 0x56, 0x92, 0x2f, 0x54, 0x13, 0x88, 0xea, 0xbc, 0xd0, 0xc5, 0x7f,
0x5b, 0x9b, 0x08, 0xb5, 0x07, 0x33, 0x68, 0x68, 0x03, 0xdf, 0x82, 0xb6, 0x80, 0xad, 0xbf, 0x84,
0xfc, 0x97, 0x15, 0xbf, 0x6b, 0xd9, 0xa0, 0x11, 0x21, 0x13, 0xd6, 0xb0, 0xa8, 0x35, 0x86, 0x8e,
0x11, 0xef, 0x1b, 0x34, 0x68, 0x44, 0x8a, 0xf1, 0xc1, 0x82, 0x02, 0x81, 0xfc, 0xca, 0x5c, 0xbe,
0xce, 0xc9, 0x28, 0xf3, 0x74, 0x35, 0x79, 0x81, 0xa3, 0x99, 0xa9, 0x26, 0x9b, 0xcf, 0x5f, 0x53,
0x5e, 0x9b, 0x5f, 0x04, 0x70, 0xad, 0x4a, 0x8d, 0xb9, 0x25, 0x65, 0xe9, 0xea, 0xcd, 0x0b, 0xb9,
0xba, 0x5b, 0x4b, 0xb6, 0xea, 0x6b, 0xc9, 0x76, 0x5d, 0x2d, 0xd9, 0x99, 0x5f, 0x4b, 0x76, 0x9d,
0x5a, 0x92, 0xfc, 0x1c, 0xae, 0x56, 0x99, 0xc4, 0x54, 0x11, 0x7f, 0xd3, 0x81, 0xb6, 0x3f, 0xc7,
0x00, 0x5d, 0x8d, 0xec, 0xfa, 0xb8, 0xce, 0x5f, 0x50, 0x82, 0xfa, 0x59, 0x00, 0x61, 0x44, 0x9f,
0x7d, 0x34, 0xa5, 0xc5, 0xb9, 0x60, 0x53, 0x39, 0xce, 0x7d, 0x99, 0x31, 0xd9, 0xc3, 0x2f, 0x46,
0x36, 0xa0, 0x33, 0x14, 0xa9, 0x52, 0xc1, 0x25, 0x07, 0x02, 0xa9, 0x51, 0x52, 0x50, 0x7c, 0xef,
0xd3, 0x48, 0x95, 0x04, 0xeb, 0xea, 0xea, 0x38, 0x57, 0xd7, 0x06, 0x74, 0x12, 0x0c, 0x57, 0x59,
0x8a, 0xcb, 0x01, 0xf9, 0x48, 0x14, 0x4b, 0xf9, 0xf8, 0xdc, 0xd7, 0xf0, 0x1d, 0xbc, 0x82, 0xa4,
0x8f, 0xa8, 0x4c, 0x5c, 0xeb, 0x46, 0x86, 0x9b, 0xbc, 0x6f, 0xbd, 0xd7, 0xc9, 0x84, 0x7f, 0x5f,
0x6a, 0xb6, 0xeb, 0x58, 0xed, 0x56, 0x34, 0xde, 0x35, 0x5f, 0x96, 0x58, 0x5c, 0xb6, 0xf5, 0x38,
0xfd, 0x24, 0x49, 0x69, 0xf1, 0xf2, 0xb2, 0x44, 0x51, 0x90, 0x30, 0x4b, 0x7b, 0x95, 0xbc, 0x17,
0x23, 0x9f, 0x4c, 0x7e, 0xd3, 0xb1, 0xde, 0x9a, 0xd4, 0x8e, 0xf7, 0x44, 0xc1, 0x2b, 0xac, 0x51,
0x3b, 0x5e, 0xf3, 0x77, 0xb4, 0x6d, 0xc5, 0x38, 0xc7, 0x71, 0x78, 0x17, 0x3a, 0x13, 0xa1, 0x78,
0x45, 0x6b, 0xe7, 0x5b, 0x25, 0x92, 0x0f, 0xf2, 0x86, 0xdf, 0x87, 0x95, 0x98, 0x31, 0xca, 0x8f,
0x8a, 0x38, 0x65, 0x4f, 0x69, 0xa1, 0xea, 0x5f, 0x9d, 0x85, 0xee, 0x8b, 0x39, 0xa6, 0x27, 0x07,
0x8d, 0xc8, 0xe5, 0x2e, 0x97, 0xff, 0x28, 0xe1, 0xa7, 0xa3, 0x22, 0xfe, 0x14, 0x5d, 0xc1, 0x5f,
0xae, 0x27, 0xcb, 0xe5, 0x9a, 0x10, 0xde, 0x85, 0x45, 0xae, 0x37, 0xee, 0xd6, 0x6f, 0x5c, 0x32,
0x8a, 0x45, 0x9f, 0xea, 0xed, 0x16, 0xea, 0xb7, 0x2b, 0x19, 0xc3, 0xf7, 0x60, 0x55, 0x0b, 0x38,
0xca, 0xde, 0x3b, 0xa3, 0x43, 0x2c, 0x77, 0x0c, 0x4a, 0xee, 0x7e, 0x92, 0x65, 0xd0, 0x88, 0xbc,
0x45, 0xe1, 0xf7, 0x00, 0xd2, 0xf2, 0x91, 0x01, 0x8b, 0xa2, 0xba, 0x67, 0x84, 0x41, 0x23, 0xb2,
0xd8, 0xc3, 0x47, 0x70, 0x29, 0x75, 0x1b, 0x16, 0x75, 0x47, 0xd4, 0xb4, 0x34, 0x83, 0x46, 0xe4,
0x2f, 0x0a, 0x1f, 0xc0, 0x25, 0xa6, 0x03, 0x48, 0xc9, 0x91, 0x77, 0xc7, 0xa6, 0x25, 0xc7, 0x9a,
0x15, 0x32, 0xbc, 0x05, 0x22, 0x01, 0xf0, 0x73, 0xd5, 0x2a, 0x36, 0xf9, 0xb9, 0xb9, 0x24, 0x3e,
0x0f, 0x44, 0xaf, 0x51, 0x76, 0x68, 0x96, 0xc3, 0xcd, 0xeb, 0xce, 0xac, 0xf2, 0xe4, 0x62, 0xe1,
0xf1, 0x2d, 0xa7, 0x3b, 0x9b, 0x71, 0x6f, 0xe7, 0x75, 0x59, 0x66, 0xc4, 0x7b, 0x7e, 0x7f, 0x56,
0xbf, 0xa8, 0xcc, 0x8a, 0xef, 0x3b, 0xcf, 0x43, 0x26, 0x0a, 0x5e, 0x2a, 0x43, 0xfc, 0xb3, 0x25,
0x52, 0x98, 0x2b, 0x0d, 0xef, 0x2b, 0xf7, 0xc2, 0x09, 0x66, 0x2e, 0x1c, 0xd1, 0x6c, 0x8b, 0x91,
0x84, 0x51, 0x81, 0x6e, 0x93, 0xc2, 0x37, 0x61, 0x55, 0x5c, 0x32, 0x87, 0xf1, 0x84, 0x2a, 0x26,
0x99, 0x87, 0x3d, 0xaa, 0xa9, 0x40, 0xda, 0xd5, 0x3d, 0x44, 0xc7, 0xef, 0xbc, 0x4c, 0x75, 0xdf,
0xad, 0xab, 0xee, 0x17, 0x6a, 0xaa, 0xfb, 0x45, 0xaf, 0xba, 0x77, 0xba, 0x8e, 0x9e, 0xdf, 0x75,
0x58, 0xb5, 0x3f, 0x3c, 0xa7, 0xf6, 0x5f, 0xba, 0x48, 0xed, 0xbf, 0x5c, 0x51, 0xfb, 0xcf, 0x74,
0x66, 0x2b, 0x17, 0xec, 0xcc, 0x56, 0x2b, 0x3b, 0x33, 0xf2, 0x93, 0x59, 0x8f, 0x8f, 0xe8, 0x30,
0x2b, 0x46, 0xaf, 0xca, 0xe3, 0xc9, 0xd7, 0x61, 0xa9, 0x9c, 0x3e, 0x3a, 0x13, 0x07, 0x26, 0x51,
0x51, 0x82, 0xd5, 0x48, 0x76, 0xe8, 0xe6, 0x41, 0xe1, 0x48, 0x9c, 0xae, 0xdf, 0x3d, 0x5e, 0xe4,
0x03, 0x04, 0xf9, 0x45, 0x13, 0xd6, 0x9d, 0x5e, 0xff, 0xab, 0xe5, 0xa7, 0xbd, 0x97, 0xf5, 0xd3,
0x9e, 0xf1, 0x53, 0xb2, 0x0f, 0xaf, 0x39, 0x10, 0x20, 0x9a, 0x22, 0xf9, 0x74, 0x51, 0x1b, 0xff,
0x7d, 0x60, 0x06, 0xae, 0x48, 0xf1, 0xc9, 0x24, 0xe2, 0x9f, 0x8a, 0xd0, 0xac, 0xfa, 0x4c, 0x66,
0xde, 0x3b, 0x9c, 0x2f, 0x98, 0x7f, 0x6e, 0xc2, 0xaa, 0xb9, 0xf0, 0xc5, 0xa5, 0x23, 0x9c, 0x4c,
0xb4, 0x62, 0xda, 0xc9, 0xc4, 0x6f, 0x4c, 0xcf, 0x99, 0xae, 0xcf, 0x78, 0x26, 0x8e, 0x2e, 0x29,
0x2f, 0x36, 0x04, 0x7d, 0x31, 0xb2, 0x28, 0x96, 0x47, 0xb5, 0x71, 0x47, 0x35, 0x12, 0xf4, 0x78,
0x82, 0x85, 0x9d, 0x82, 0x5c, 0x8e, 0xc4, 0x9e, 0xa2, 0xc1, 0x53, 0x68, 0xe3, 0x6f, 0xac, 0x15,
0xcf, 0x27, 0xc7, 0xd9, 0x58, 0x3d, 0x94, 0xaa, 0x91, 0x75, 0x6c, 0xe0, 0x1c, 0x1b, 0x7e, 0x10,
0x12, 0xc7, 0x2d, 0xd0, 0x52, 0x11, 0x76, 0x19, 0x39, 0x66, 0xe8, 0xf8, 0x21, 0x24, 0x2e, 0x62,
0xc5, 0xb5, 0x29, 0x5b, 0x4c, 0x43, 0x11, 0x69, 0x83, 0x4d, 0x87, 0x43, 0xca, 0x58, 0xff, 0x0a,
0x1a, 0xa7, 0x87, 0xe4, 0x2f, 0x4d, 0xf9, 0xd8, 0x64, 0x00, 0x8b, 0x58, 0xfe, 0x92, 0x98, 0xf5,
0x6a, 0x30, 0xeb, 0x7d, 0xd5, 0x31, 0xeb, 0x19, 0xcc, 0xfe, 0xa1, 0x3e, 0x08, 0x61, 0x13, 0xfe,
0xf0, 0x18, 0x73, 0xdd, 0xdc, 0xf7, 0x39, 0xfb, 0x85, 0xad, 0xe9, 0x7d, 0x3d, 0x7e, 0xde, 0xeb,
0xdc, 0x9b, 0xb0, 0x9a, 0xc7, 0xe2, 0xa6, 0x7d, 0x62, 0xbf, 0xd1, 0x2d, 0x47, 0x1e, 0xb5, 0x8c,
0x89, 0xa3, 0x64, 0x42, 0x15, 0xaa, 0x86, 0x10, 0xde, 0x80, 0x16, 0x3f, 0x93, 0x1f, 0x6d, 0x97,
0x76, 0x43, 0x15, 0x8f, 0x47, 0xe6, 0xaf, 0x06, 0x91, 0x98, 0x26, 0x7f, 0x53, 0x1f, 0xde, 0x6c,
0xa3, 0xb0, 0x75, 0xbf, 0xa8, 0x61, 0xbd, 0x2f, 0x6d, 0x58, 0xef, 0x05, 0x0d, 0x5b, 0x33, 0x86,
0xf5, 0xd0, 0x88, 0xdd, 0xcf, 0x5a, 0xd0, 0x2b, 0xff, 0x5c, 0x11, 0xfe, 0x00, 0x16, 0xf7, 0x29,
0xc7, 0x84, 0x12, 0xae, 0x95, 0x79, 0xe8, 0xd9, 0x21, 0x2f, 0x92, 0xf4, 0x64, 0xeb, 0x8d, 0xd9,
0xba, 0xdf, 0xf9, 0xde, 0x4b, 0x1a, 0xe1, 0x3b, 0x00, 0x8f, 0x13, 0xc6, 0x55, 0x6a, 0x5b, 0x31,
0x22, 0x3e, 0x48, 0xc6, 0x5b, 0x5b, 0x55, 0x99, 0x4d, 0xb2, 0x92, 0x46, 0xf8, 0x21, 0x84, 0xfb,
0x14, 0xdd, 0xcd, 0xbe, 0x66, 0xae, 0x1b, 0x11, 0x55, 0xd7, 0xd0, 0xd6, 0xdc, 0x6c, 0x49, 0x1a,
0xe1, 0x21, 0xac, 0x6a, 0x6b, 0x2e, 0x28, 0xed, 0x8d, 0xda, 0x2a, 0x8e, 0xe5, 0xa4, 0x11, 0xbe,
0x0b, 0x6b, 0xfb, 0x94, 0x63, 0xdc, 0x97, 0x35, 0xc2, 0x2c, 0x54, 0x7d, 0x5f, 0x90, 0x4e, 0x14,
0xa4, 0x11, 0xde, 0x84, 0xee, 0x01, 0x3b, 0x3c, 0x4f, 0x87, 0x3e, 0x3e, 0xeb, 0x6a, 0x78, 0xc0,
0xf6, 0xe2, 0xe9, 0xc9, 0x29, 0xff, 0x38, 0x27, 0x8d, 0xe3, 0x2e, 0xfe, 0x6d, 0xe5, 0xee, 0xff,
0x03, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x35, 0x92, 0x17, 0x03, 0x23, 0x00, 0x00,
func init() { proto.RegisterFile("paracross.proto", fileDescriptor_paracross_86d4df6243fac7f6) }
var fileDescriptor_paracross_86d4df6243fac7f6 = []byte{
// 2317 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0xcd, 0x6f, 0x1c, 0x49,
0x15, 0x77, 0xcf, 0xa7, 0xe7, 0xd9, 0xe3, 0x8f, 0x5e, 0xc7, 0x19, 0x9c, 0x6c, 0x64, 0xb5, 0xc2,
0xca, 0xb0, 0xd9, 0x84, 0x38, 0x10, 0xb4, 0x42, 0x48, 0xc4, 0xce, 0xc7, 0x58, 0x9b, 0xac, 0xd8,
0xb6, 0x17, 0x0e, 0x5c, 0x68, 0xcf, 0x94, 0xed, 0x16, 0x33, 0xdd, 0x93, 0xee, 0x9a, 0x5d, 0x9b,
0x0b, 0x48, 0xc0, 0x19, 0x4e, 0x48, 0x70, 0xe0, 0x02, 0x37, 0x24, 0x24, 0xfe, 0x01, 0x0e, 0x1c,
0x97, 0xd3, 0x72, 0xe4, 0xc6, 0x8d, 0x3b, 0x07, 0xae, 0xe8, 0xbd, 0xaa, 0xea, 0xfa, 0x98, 0x9e,
0xb6, 0x93, 0xcd, 0x65, 0x6f, 0x53, 0xaf, 0x5e, 0xbd, 0x7a, 0xef, 0x57, 0xef, 0xbd, 0x7a, 0xaf,
0x7a, 0x60, 0x75, 0x12, 0x65, 0xd1, 0x20, 0x4b, 0xf3, 0xfc, 0xee, 0x24, 0x4b, 0x79, 0xea, 0x37,
0xf9, 0xc5, 0x84, 0xe5, 0x5b, 0xeb, 0x3c, 0x8b, 0x92, 0x3c, 0x1a, 0xf0, 0x38, 0x4d, 0xc4, 0xcc,
0xd6, 0xf2, 0x20, 0x1d, 0x8f, 0x8b, 0xd1, 0xda, 0xf1, 0x28, 0x1d, 0xfc, 0x64, 0x70, 0x16, 0xc5,
0x92, 0x12, 0x3c, 0x87, 0xcd, 0xef, 0x2b, 0x61, 0x87, 0x3c, 0xe2, 0xd3, 0xfc, 0x31, 0xe3, 0x51,
0x3c, 0xca, 0xfd, 0x0d, 0x68, 0x46, 0xc3, 0x61, 0x96, 0xf7, 0xbc, 0xed, 0xfa, 0x4e, 0x27, 0x14,
0x03, 0xff, 0x26, 0x74, 0x48, 0x46, 0x3f, 0xca, 0xcf, 0x7a, 0xb5, 0xed, 0xfa, 0xce, 0x72, 0xa8,
0x09, 0xc1, 0x8f, 0xe0, 0x86, 0x23, 0x6d, 0x0f, 0xe7, 0x94, 0xc8, 0x5b, 0x00, 0x05, 0xaf, 0x90,
0xbb, 0x1c, 0x1a, 0x14, 0x14, 0xce, 0xcf, 0x43, 0x96, 0x4f, 0x47, 0x3c, 0x57, 0xc2, 0x0b, 0x42,
0xf0, 0xfb, 0x1a, 0x5c, 0x2b, 0xa4, 0xf7, 0x59, 0x7c, 0x7a, 0xc6, 0xc5, 0x1e, 0xfe, 0x26, 0xb4,
0x72, 0xfa, 0xd5, 0xf3, 0xb6, 0xbd, 0x9d, 0x66, 0x28, 0x47, 0x68, 0x02, 0x8f, 0xf9, 0x88, 0xf5,
0x6a, 0xdb, 0x1e, 0x9a, 0x40, 0x03, 0xe4, 0x3e, 0xa3, 0xd5, 0xbd, 0xfa, 0xb6, 0xb7, 0x53, 0x0f,
0xe5, 0xc8, 0xff, 0x36, 0xb4, 0x87, 0x42, 0xd1, 0x5e, 0x63, 0xdb, 0xdb, 0x59, 0xda, 0x7d, 0xfb,
0x2e, 0xc1, 0x7a, 0xb7, 0x1c, 0xa0, 0x50, 0x71, 0xa3, 0x59, 0xe3, 0x28, 0x4e, 0x84, 0x4a, 0xbd,
0x26, 0x09, 0x35, 0x28, 0xfe, 0x16, 0x2c, 0xd2, 0x08, 0x21, 0x6b, 0x6d, 0x7b, 0x3b, 0xcb, 0x61,
0x31, 0xf6, 0x9f, 0xc2, 0xf2, 0xb1, 0x01, 0x51, 0xaf, 0x4d, 0x3b, 0x07, 0xe5, 0x3b, 0x9b, 0x60,
0x86, 0xd6, 0xba, 0xe0, 0x3f, 0x1e, 0xf4, 0x4a, 0xc1, 0x09, 0xf3, 0xc9, 0x1b, 0xc2, 0xc7, 0x36,
0xb3, 0x51, 0x69, 0x66, 0x93, 0x04, 0x6a, 0x33, 0xb7, 0x61, 0x09, 0x1d, 0x31, 0xe6, 0x8f, 0xc8,
0xa5, 0x5a, 0xe4, 0x52, 0x26, 0xc9, 0xdf, 0x81, 0x55, 0x31, 0xdc, 0x2b, 0xdc, 0xab, 0x4d, 0x5c,
0x2e, 0x39, 0xf8, 0x9d, 0x07, 0xab, 0x0e, 0x30, 0xda, 0x12, 0xaf, 0xdc, 0x92, 0x9a, 0x65, 0x89,
0xe5, 0xc4, 0x75, 0x3a, 0x11, 0x4d, 0x78, 0x65, 0x3b, 0x8d, 0xe3, 0x0c, 0xfe, 0x64, 0x1e, 0xc3,
0x7e, 0x9a, 0xe4, 0x2c, 0xc9, 0xa7, 0xd5, 0x4a, 0x22, 0x34, 0x67, 0x7a, 0x3f, 0xa1, 0xa9, 0x49,
0xf2, 0x6f, 0x43, 0x77, 0x20, 0x44, 0xf5, 0xcd, 0x73, 0xb1, 0x89, 0xfe, 0xd7, 0x61, 0x4d, 0x12,
0x34, 0x82, 0x0d, 0xda, 0x68, 0x86, 0x1e, 0xfc, 0xd6, 0x03, 0x1f, 0xd5, 0xfc, 0x30, 0x1d, 0x32,
0x84, 0x7f, 0x3f, 0x4d, 0x4e, 0xe2, 0xd3, 0x39, 0x0a, 0xae, 0x40, 0x2d, 0x9d, 0x90, 0x5e, 0xdd,
0xb0, 0x96, 0x4e, 0x70, 0x1c, 0x0f, 0x49, 0x87, 0x4e, 0x58, 0x8b, 0x87, 0xbe, 0x0f, 0x0d, 0xcc,
0x0d, 0x72, 0x33, 0xfa, 0x8d, 0x92, 0x3e, 0x89, 0x46, 0x53, 0x46, 0x00, 0x75, 0x43, 0x31, 0x10,
0x5e, 0x10, 0x27, 0xf9, 0xd3, 0x2c, 0xfd, 0x29, 0x4b, 0x28, 0x16, 0xd0, 0x54, 0x4d, 0x0a, 0xbe,
0xa7, 0xf5, 0xfa, 0x41, 0xca, 0x99, 0xf0, 0xee, 0x39, 0xa9, 0x08, 0xf7, 0x48, 0x39, 0x13, 0x99,
0xa2, 0x13, 0x8a, 0x41, 0xf0, 0x1b, 0x0f, 0x36, 0x4c, 0xd3, 0x0e, 0x86, 0x12, 0x7d, 0xa5, 0xa6,
0x67, 0xa8, 0x79, 0x0b, 0x60, 0x92, 0xa5, 0x93, 0x34, 0x8f, 0x46, 0x07, 0x43, 0x19, 0x05, 0x06,
0x05, 0x1d, 0xe8, 0xe5, 0x34, 0xe6, 0x07, 0xca, 0x5c, 0x39, 0x32, 0x02, 0xaa, 0x51, 0x1e, 0x50,
0x4d, 0x03, 0xc0, 0xe0, 0x7f, 0x1e, 0xac, 0x29, 0x95, 0x0a, 0x75, 0x04, 0x8a, 0x5e, 0x81, 0xa2,
0x16, 0x59, 0x2b, 0x17, 0x59, 0x37, 0xcf, 0xe4, 0x16, 0x00, 0x8f, 0xb2, 0x53, 0x46, 0xc1, 0x23,
0x91, 0x37, 0x28, 0x2e, 0xd2, 0xcd, 0x19, 0xa4, 0xfd, 0x7b, 0x0a, 0xbd, 0x16, 0x65, 0x9c, 0xaf,
0x18, 0x19, 0xc7, 0x46, 0x5f, 0x02, 0x8b, 0x6e, 0x7f, 0x92, 0xa5, 0x63, 0xda, 0xb0, 0x2d, 0xc2,
0x5b, 0x8d, 0x8d, 0x40, 0x5b, 0x34, 0x03, 0x2d, 0xf8, 0x9b, 0x07, 0xd7, 0x42, 0x36, 0x60, 0xf1,
0x84, 0x2b, 0xc1, 0xd2, 0xd5, 0xca, 0x4e, 0xe3, 0x3e, 0xb4, 0x06, 0x34, 0x4b, 0x10, 0xcc, 0xea,
0xa4, 0x3d, 0x35, 0x94, 0x8c, 0xfe, 0xbb, 0xd0, 0x98, 0x64, 0xec, 0x13, 0x02, 0x67, 0x69, 0xf7,
0xba, 0xb3, 0x40, 0x81, 0x1d, 0x12, 0x93, 0x7f, 0x1f, 0xda, 0x83, 0x69, 0x96, 0xb1, 0x84, 0xcb,
0x04, 0x3f, 0x97, 0x5f, 0xf1, 0x05, 0x7f, 0xf4, 0xe0, 0x6d, 0xc7, 0x00, 0xd4, 0x02, 0xd9, 0x3e,
0x9e, 0x0c, 0x23, 0xce, 0x2c, 0x58, 0x3c, 0x07, 0x96, 0x7b, 0x52, 0x3b, 0x61, 0xce, 0x8d, 0x12,
0x73, 0x1c, 0x0d, 0xbf, 0xa5, 0x35, 0xac, 0x5f, 0xbe, 0xa6, 0xd0, 0xf2, 0xbf, 0x1e, 0x5c, 0x77,
0xb4, 0xa4, 0xf3, 0x4b, 0x13, 0x36, 0xe3, 0x67, 0xe5, 0x39, 0xdf, 0xf6, 0xa7, 0xfa, 0x8c, 0x3f,
0xe1, 0x7c, 0xca, 0xa3, 0x11, 0x8a, 0x56, 0x4e, 0x6f, 0x50, 0xe8, 0xe6, 0xc6, 0x11, 0x6e, 0x4b,
0xde, 0xd6, 0x0c, 0x35, 0x81, 0x32, 0x66, 0x9a, 0x73, 0x9a, 0x6c, 0xd1, 0x64, 0x31, 0xf6, 0x7b,
0xd0, 0x46, 0xff, 0x0a, 0x73, 0x2e, 0xbd, 0x4a, 0x0d, 0x71, 0xcf, 0x61, 0x9a, 0x30, 0x61, 0x2c,
0x39, 0x56, 0x33, 0x34, 0x28, 0xc1, 0x2f, 0x3c, 0x78, 0x4b, 0x99, 0xfb, 0x2c, 0x4b, 0xa7, 0x93,
0x2f, 0x94, 0xc5, 0x8a, 0x1c, 0x23, 0x82, 0x49, 0xe6, 0x98, 0x4b, 0xe3, 0x28, 0xf8, 0x87, 0xab,
0xc5, 0x1b, 0x89, 0xef, 0x6d, 0x58, 0xd2, 0xe8, 0x2b, 0x9d, 0x4c, 0xd2, 0x15, 0x22, 0xdc, 0xf4,
0xcc, 0xd6, 0xdc, 0x80, 0x6d, 0x5b, 0x01, 0xfb, 0x99, 0x07, 0x5b, 0x8e, 0x27, 0x99, 0xd0, 0x96,
0x45, 0xed, 0xae, 0x13, 0xb5, 0x5b, 0x8e, 0xcb, 0x1a, 0xeb, 0x8b, 0xb0, 0xbd, 0x6b, 0x85, 0x6d,
0xe9, 0x0a, 0x2b, 0x2e, 0xbe, 0xe9, 0x46, 0x6e, 0xd5, 0x92, 0x22, 0x2c, 0xce, 0x60, 0x23, 0x64,
0x2f, 0x8b, 0xeb, 0x98, 0x22, 0x3c, 0x39, 0x49, 0xe7, 0x3b, 0x48, 0xac, 0xee, 0x00, 0xf3, 0x5a,
0xab, 0x1b, 0xb6, 0xce, 0xc9, 0xfb, 0xc1, 0x3e, 0x6c, 0x86, 0x2c, 0x9f, 0x58, 0x5b, 0x89, 0x63,
0xfa, 0x1a, 0xd4, 0xe3, 0xa1, 0xb8, 0xb8, 0x2a, 0xf2, 0x0d, 0xf2, 0x04, 0xcf, 0x30, 0x88, 0x1d,
0x21, 0x64, 0x57, 0xee, 0xdf, 0x31, 0xa5, 0x54, 0xd9, 0x4e, 0x82, 0x7e, 0xe5, 0xc1, 0x3a, 0x4e,
0xd2, 0x7d, 0xbf, 0xfb, 0x22, 0x8a, 0x93, 0x17, 0xd1, 0xc4, 0x38, 0x72, 0x6f, 0x7e, 0x31, 0x24,
0xcc, 0x9f, 0x5b, 0x0c, 0xd5, 0x2b, 0x8b, 0xa1, 0x86, 0x5d, 0xf4, 0x05, 0x8f, 0xc5, 0x65, 0xae,
0xd5, 0x20, 0xf4, 0xef, 0x42, 0x33, 0xe6, 0x6c, 0xac, 0xac, 0xe9, 0x19, 0xd6, 0x58, 0x0a, 0x87,
0x82, 0x2d, 0xf8, 0x77, 0x5d, 0x04, 0x58, 0x81, 0x89, 0x0c, 0xb0, 0xdb, 0xd0, 0xc5, 0x9d, 0x74,
0xb1, 0xe3, 0x51, 0x2d, 0x66, 0x13, 0xb1, 0xac, 0xd4, 0x04, 0xb3, 0xc2, 0x72, 0xc9, 0x73, 0x02,
0x51, 0xa3, 0xd6, 0xb0, 0x50, 0x0b, 0x60, 0x79, 0x92, 0x31, 0xbd, 0xb9, 0x28, 0x04, 0x2d, 0x9a,
0x8d, 0x6c, 0xcb, 0x2d, 0x33, 0x85, 0x04, 0x34, 0x86, 0xc9, 0x6a, 0x57, 0x49, 0x28, 0x68, 0x28,
0x21, 0x2f, 0x18, 0x16, 0x85, 0x84, 0x82, 0x80, 0xd8, 0xf3, 0xf3, 0xfd, 0x74, 0x9a, 0xf0, 0xbc,
0xd7, 0xa1, 0xc4, 0x56, 0x8c, 0xc5, 0x9c, 0xe8, 0x9c, 0x7a, 0x20, 0x8a, 0x54, 0x35, 0xc6, 0x94,
0xcb, 0xcf, 0x45, 0x0f, 0xb6, 0x44, 0x4d, 0x96, 0x1a, 0x52, 0xa5, 0x89, 0x30, 0x1f, 0xa9, 0xa5,
0xcb, 0x02, 0x53, 0x8b, 0x88, 0x9a, 0x4b, 0x82, 0x10, 0xd2, 0x25, 0x21, 0x16, 0xcd, 0xbf, 0x03,
0xeb, 0x49, 0x9a, 0xec, 0x53, 0xe9, 0x7e, 0xa4, 0x94, 0x5c, 0x21, 0x25, 0x67, 0x27, 0x82, 0x3d,
0x58, 0x3f, 0x64, 0xa3, 0x13, 0x59, 0x30, 0x1f, 0xf2, 0xe8, 0x94, 0xe5, 0xfe, 0x7b, 0xb6, 0xa3,
0xa8, 0xe0, 0x71, 0x19, 0x95, 0x9f, 0x3c, 0x87, 0x35, 0x77, 0x0a, 0x93, 0x64, 0xce, 0xa3, 0x8c,
0xf7, 0x4d, 0xc7, 0x37, 0x49, 0x78, 0xbe, 0x2c, 0x89, 0x8e, 0xe5, 0x7d, 0xd8, 0x0d, 0xe5, 0x28,
0xf8, 0x97, 0x07, 0x1b, 0xae, 0x38, 0x72, 0xdf, 0xea, 0xbc, 0xde, 0x2d, 0xf2, 0xfa, 0x7b, 0xd0,
0xcc, 0x71, 0x91, 0x53, 0x9a, 0xcc, 0x6a, 0x4f, 0x5c, 0x56, 0xb2, 0x6e, 0x38, 0xc9, 0xfa, 0x16,
0x00, 0x3b, 0x67, 0x03, 0xbb, 0xbf, 0xd4, 0x94, 0x57, 0x2e, 0xe5, 0x02, 0x06, 0x9b, 0xcf, 0xd3,
0x41, 0x34, 0x52, 0xca, 0x68, 0xeb, 0xee, 0x2b, 0xad, 0x3d, 0xab, 0xfc, 0x28, 0x43, 0x42, 0x69,
0x4e, 0xde, 0x74, 0x90, 0x0c, 0xd9, 0xb9, 0xcc, 0x1e, 0x6a, 0x18, 0x3c, 0x84, 0x15, 0x91, 0xf7,
0x51, 0x83, 0x52, 0xf0, 0x8a, 0x36, 0xa1, 0x66, 0xb4, 0x09, 0x41, 0x00, 0x6b, 0x62, 0xdd, 0x7e,
0x94, 0x0c, 0xd8, 0xa8, 0x6c, 0x65, 0xf0, 0xb9, 0x6c, 0x02, 0x49, 0x9d, 0x57, 0xba, 0xf8, 0xef,
0x29, 0x13, 0xa1, 0xf2, 0x60, 0xfa, 0x0b, 0xca, 0xc0, 0x77, 0xa1, 0x81, 0xb0, 0xf5, 0x96, 0x88,
0xff, 0x9a, 0xe4, 0xb7, 0x2d, 0xeb, 0x2f, 0x84, 0xc4, 0x44, 0x35, 0x2c, 0x69, 0x4d, 0xa1, 0xa3,
0xc5, 0xbb, 0x06, 0xf5, 0x17, 0x42, 0xc9, 0xb8, 0xd7, 0x96, 0x20, 0x04, 0xbf, 0xd4, 0x97, 0xaf,
0x75, 0x32, 0xd2, 0x3c, 0x55, 0x4d, 0x5e, 0xe1, 0x68, 0x66, 0xaa, 0xc9, 0xda, 0xe5, 0x6b, 0x8a,
0x6b, 0xf3, 0x73, 0x0f, 0x6e, 0x96, 0xa9, 0x31, 0xb7, 0xa4, 0x2c, 0x5c, 0xbd, 0x76, 0x25, 0x57,
0xb7, 0x6b, 0xc9, 0x7a, 0x75, 0x2d, 0xd9, 0xa8, 0xaa, 0x25, 0x9b, 0xf3, 0x6b, 0xc9, 0x96, 0x55,
0x4b, 0x06, 0x3f, 0x83, 0x1b, 0x65, 0x26, 0xe5, 0xb2, 0x88, 0xbf, 0x63, 0x41, 0xdb, 0x9b, 0x63,
0x80, 0xaa, 0x46, 0x76, 0x5d, 0x5c, 0xe7, 0x2f, 0x28, 0x40, 0xfd, 0x83, 0x07, 0x7e, 0xc8, 0x5e,
0x7e, 0x34, 0x65, 0xd9, 0x05, 0xb2, 0xc9, 0x1c, 0x67, 0xbf, 0xcc, 0xe8, 0xec, 0xe1, 0x16, 0x23,
0x1b, 0xd0, 0x1c, 0x60, 0xaa, 0x94, 0x70, 0x89, 0x01, 0x22, 0x35, 0x8c, 0x33, 0x46, 0xef, 0x7d,
0x0a, 0xa9, 0x82, 0x60, 0x5c, 0x5d, 0x4d, 0xeb, 0xea, 0xda, 0x80, 0x66, 0x4c, 0xe1, 0x2a, 0x4a,
0x71, 0x31, 0x08, 0x3e, 0xc2, 0x62, 0x69, 0x32, 0xba, 0x70, 0x35, 0x7c, 0x9f, 0xae, 0x20, 0xe1,
0x23, 0x32, 0x13, 0x57, 0xba, 0x91, 0xe6, 0x0e, 0x3e, 0x30, 0xde, 0xeb, 0x44, 0xc2, 0x7f, 0x24,
0x34, 0xdb, 0xb5, 0xac, 0xb6, 0x2b, 0x1a, 0xe7, 0x9a, 0x2f, 0x4a, 0x2c, 0x2e, 0xda, 0x7a, 0x9a,
0x7e, 0x11, 0x27, 0x2c, 0x7b, 0x7d, 0x59, 0x58, 0x14, 0xc4, 0xb9, 0xa1, 0xbd, 0x4c, 0xde, 0x8b,
0xa1, 0x4b, 0x0e, 0x7e, 0xdd, 0x34, 0xde, 0x9a, 0xe4, 0x8e, 0x0f, 0xb1, 0xe0, 0x45, 0x6b, 0xe4,
0x8e, 0x37, 0xdd, 0x1d, 0x4d, 0x5b, 0x29, 0xce, 0x69, 0xec, 0x3f, 0x80, 0xe6, 0x18, 0x15, 0x2f,
0x69, 0xed, 0x5c, 0xab, 0x30, 0xf9, 0x10, 0xaf, 0xff, 0x5d, 0xe8, 0x46, 0x79, 0xce, 0xf8, 0x51,
0x16, 0x25, 0xf9, 0x09, 0xcb, 0x64, 0xfd, 0xab, 0xb2, 0xd0, 0x23, 0x9c, 0xcb, 0xd5, 0x64, 0x7f,
0x21, 0xb4, 0xb9, 0x8b, 0xe5, 0x3f, 0x8c, 0xf9, 0xd9, 0x30, 0x8b, 0x3e, 0x25, 0x57, 0x70, 0x97,
0xab, 0xc9, 0x62, 0xb9, 0x22, 0xf8, 0x0f, 0x60, 0x91, 0xab, 0x8d, 0x5b, 0xd5, 0x1b, 0x17, 0x8c,
0xb8, 0xe8, 0x53, 0xb5, 0x5d, 0xbb, 0x7a, 0xbb, 0x82, 0xd1, 0x7f, 0x02, 0x2b, 0x4a, 0xc0, 0x51,
0xfa, 0xe4, 0x9c, 0x0d, 0xa8, 0xdc, 0xd1, 0x28, 0xd9, 0xfb, 0x09, 0x96, 0xfe, 0x42, 0xe8, 0x2c,
0xf2, 0xbf, 0x03, 0x90, 0x14, 0x8f, 0x0c, 0x54, 0x14, 0x55, 0x3d, 0x23, 0xf4, 0x17, 0x42, 0x83,
0xdd, 0x7f, 0x0a, 0xab, 0x89, 0xdd, 0xb0, 0xc8, 0x3b, 0xa2, 0xa2, 0xa5, 0xe9, 0x2f, 0x84, 0xee,
0x22, 0x7f, 0x0f, 0x56, 0x73, 0x15, 0x40, 0x52, 0x8e, 0xb8, 0x3b, 0x36, 0x0d, 0x39, 0xc6, 0x2c,
0xca, 0x70, 0x16, 0x60, 0x02, 0xe0, 0x17, 0xb2, 0x55, 0xac, 0xf1, 0x0b, 0x7d, 0x49, 0x7c, 0xe6,
0x61, 0xaf, 0x51, 0x74, 0x68, 0x86, 0xc3, 0xcd, 0xeb, 0xce, 0x8c, 0xf2, 0xe4, 0x6a, 0xe1, 0xf1,
0x0d, 0xab, 0x3b, 0x9b, 0x71, 0x6f, 0xeb, 0x75, 0x59, 0x64, 0xc4, 0x87, 0x6e, 0x7f, 0x56, 0xbd,
0xa8, 0xc8, 0x8a, 0x1f, 0x58, 0xcf, 0x43, 0x3a, 0x0a, 0x5e, 0x2b, 0x43, 0xfc, 0xbc, 0x81, 0x29,
0xcc, 0x96, 0x46, 0xf7, 0x95, 0x7d, 0xe1, 0x78, 0x33, 0x17, 0x0e, 0x36, 0xdb, 0x38, 0x12, 0x30,
0x4a, 0xd0, 0x4d, 0x92, 0xff, 0x0e, 0xac, 0xe0, 0x25, 0x73, 0x18, 0x8d, 0x99, 0x64, 0x12, 0x79,
0xd8, 0xa1, 0xea, 0x0a, 0xa4, 0x51, 0xde, 0x43, 0x34, 0xdd, 0xce, 0x4b, 0x57, 0xf7, 0xad, 0xaa,
0xea, 0xbe, 0x5d, 0x51, 0xdd, 0x2f, 0x3a, 0xd5, 0xbd, 0xd5, 0x75, 0x74, 0xdc, 0xae, 0xc3, 0xa8,
0xfd, 0xe1, 0x92, 0xda, 0x7f, 0xe9, 0x2a, 0xb5, 0xff, 0x72, 0x49, 0xed, 0x3f, 0xd3, 0x99, 0x75,
0xaf, 0xd8, 0x99, 0xad, 0x94, 0x77, 0x66, 0x3b, 0xb0, 0x4a, 0xcf, 0xe1, 0x4f, 0x74, 0x11, 0xbc,
0x2a, 0x38, 0x1d, 0x72, 0xf0, 0xe3, 0xd9, 0xd8, 0x08, 0xd9, 0x20, 0xcd, 0x86, 0x6f, 0x2a, 0x36,
0x82, 0xaf, 0xc2, 0x52, 0x31, 0x7d, 0x74, 0x8e, 0x47, 0x2b, 0xf0, 0x93, 0x82, 0xe5, 0x48, 0xf4,
0xf2, 0xfa, 0xe9, 0xe1, 0x08, 0xfd, 0xc0, 0xed, 0x33, 0xaf, 0xf2, 0xa9, 0x22, 0xf8, 0x73, 0x0d,
0xd6, 0xad, 0x57, 0x81, 0x2f, 0x97, 0x47, 0x77, 0x5e, 0xd7, 0xa3, 0x3b, 0x86, 0x47, 0x97, 0x9c,
0x7f, 0xa7, 0xfc, 0xfc, 0x9f, 0xc1, 0x5b, 0x16, 0x58, 0x84, 0x3b, 0x26, 0xb4, 0x16, 0xe9, 0xed,
0xbe, 0x39, 0xcc, 0x00, 0x1b, 0x4a, 0x3e, 0x91, 0x98, 0xdc, 0xf3, 0x43, 0x1b, 0xca, 0x4f, 0x6f,
0xe6, 0x0d, 0xc5, 0xfa, 0x2a, 0xfa, 0x97, 0x1a, 0xac, 0xe8, 0x22, 0x02, 0x2f, 0x32, 0x74, 0x47,
0x6c, 0xef, 0x94, 0x3b, 0xe2, 0x6f, 0x4a, 0xf9, 0xa9, 0xaa, 0xf9, 0x78, 0x8a, 0x87, 0x1c, 0x17,
0x97, 0x25, 0x1d, 0xcf, 0x62, 0x68, 0x50, 0x0c, 0xdf, 0x6b, 0xd0, 0x8e, 0x72, 0x84, 0xf4, 0x68,
0x4c, 0xc5, 0xa2, 0x3c, 0x1c, 0x31, 0xc2, 0x3d, 0xb1, 0x69, 0x94, 0xe7, 0x42, 0xbf, 0xa9, 0xfe,
0xbc, 0x18, 0x1f, 0xa7, 0x23, 0xf9, 0xf8, 0x2a, 0x47, 0xc6, 0x01, 0x83, 0x75, 0xc0, 0xf4, 0x91,
0x09, 0x1d, 0x03, 0xd1, 0x92, 0x67, 0x71, 0x8d, 0x38, 0x66, 0xe8, 0xf4, 0x71, 0x25, 0xca, 0x22,
0xc9, 0xb5, 0x29, 0xda, 0x56, 0x4d, 0xc1, 0x54, 0x94, 0x4f, 0x07, 0x03, 0x96, 0xe7, 0xbd, 0xeb,
0x64, 0x9c, 0x1a, 0x06, 0x7f, 0xad, 0x89, 0x07, 0x2c, 0x0d, 0x58, 0x98, 0x4f, 0x5e, 0x13, 0xb3,
0x4e, 0x05, 0x66, 0x9d, 0x2f, 0x3b, 0x66, 0x1d, 0x8d, 0xd9, 0x3f, 0xe5, 0x47, 0x26, 0x6a, 0xec,
0x1f, 0x1f, 0x53, 0xfe, 0x9c, 0xfb, 0xe6, 0x67, 0xbe, 0xda, 0xd5, 0x9c, 0x2f, 0xd2, 0x97, 0xbd,
0xf8, 0xbd, 0x03, 0x2b, 0x93, 0x08, 0x6f, 0xef, 0x17, 0xe6, 0xbb, 0xdf, 0x72, 0xe8, 0x50, 0x8b,
0x98, 0x38, 0x8a, 0xc7, 0x4c, 0xa2, 0xaa, 0x09, 0xfe, 0x6d, 0xa8, 0xf3, 0x73, 0xf1, 0x21, 0x78,
0x69, 0xd7, 0x97, 0xf1, 0x78, 0xa4, 0xff, 0xbe, 0x10, 0xe2, 0x74, 0xf0, 0x77, 0xf9, 0x31, 0xcf,
0x34, 0x8a, 0x9e, 0x03, 0xae, 0x6a, 0x58, 0xe7, 0x0b, 0x1b, 0xd6, 0x79, 0x45, 0xc3, 0xd6, 0xb4,
0x61, 0x1d, 0x32, 0x62, 0xf7, 0x7d, 0xe8, 0x14, 0xff, 0xd7, 0xf0, 0xef, 0x40, 0xeb, 0x20, 0x3f,
0xbc, 0x48, 0x06, 0x7e, 0xb7, 0x48, 0x42, 0x2f, 0x3f, 0x8c, 0x47, 0x5b, 0xeb, 0x72, 0x78, 0x90,
0xef, 0x47, 0xd3, 0xd3, 0x33, 0xfe, 0xf1, 0x24, 0x58, 0x38, 0x6e, 0xd1, 0x9f, 0x34, 0x1e, 0xfc,
0x3f, 0x00, 0x00, 0xff, 0xff, 0x64, 0x92, 0x6c, 0xee, 0xf1, 0x21, 0x00, 0x00,
}
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
MAIN_HTTP=""
GAME_ID=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
pokerbull_PlayRawTx() {
echo "========== # pokerbull play tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Play","payload":{"gameId":"pokerbull-abc", "value":"1000000000", "round":1}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP}
echo "========== # pokerbull play tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
chain33_SignAndSendTxWait "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP} "$FUNCNAME"
}
pokerbull_QuitRawTx() {
echo "========== # pokerbull quit tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Quit","payload":{"gameId":"'$GAME_ID'"}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP}
echo "========== # pokerbull quit tx end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
chain33_SignAndSendTxWait "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP} "$FUNCNAME"
}
pokerbull_ContinueRawTx() {
echo "========== # pokerbull continue tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Continue","payload":{"gameId":"'$GAME_ID'"}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" ${MAIN_HTTP}
echo "========== # pokerbull continue tx end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
chain33_SignAndSendTxWait "$tx" "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" ${MAIN_HTTP} "$FUNCNAME"
}
pokerbull_StartRawTx() {
echo "========== # pokerbull start tx begin =========="
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Start","payload":{"value":"1000000000", "playerNum":"2"}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP}
req='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.result.txs[0].execer != null)' "$FUNCNAME"
chain33_SignAndSendTx "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP}
GAME_ID=$RAW_TX_HASH
echo "========== # pokerbull start tx end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
}
pokerbull_QueryResult() {
echo "========== # pokerbull query result begin =========="
local req='"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByID","payload":{"gameId":"'$GAME_ID'"}}]'
data=$(curl -ksd "{$req}" ${MAIN_HTTP} | jq -r ".result")
ok=$(jq '(.game.gameId == "'"$GAME_ID"'")' <<<"$data")
req='{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByID","payload":{"gameId":"'$GAME_ID'"}}]}'
resok='(.result.game.gameId == "'"$GAME_ID"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByAddr","payload":{"addr":"14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.result != null)' "$FUNCNAME"
data=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByAddr","payload":{"addr":"14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4"}}]}' ${MAIN_HTTP} | jq -r ".result")
[ "$data" != null ]
echo_rst "$FUNCNAME" "$?"
data=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByStatus","payload":{"status":"3"}}]}' ${MAIN_HTTP} | jq -r ".result")
[ "$data" != null ]
echo_rst "$FUNCNAME" "$?"
echo "========== # pokerbull query result end =========="
req='{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByStatus","payload":{"status":"3"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.result != null)' "$FUNCNAME"
}
init() {
......@@ -104,10 +55,7 @@ init() {
fi
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4
chain33_ImportPrivkey "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" "14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4" "pokerbull1" "${main_ip}"
#1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1
chain33_ImportPrivkey "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" "1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1" "pokerbull2" "$main_ip"
local pokerbull1="14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4"
......@@ -120,14 +68,12 @@ init() {
chain33_applyCoins "$pokerbull2" 12000000000 "${main_ip}"
chain33_QueryBalance "${pokerbull2}" "$main_ip"
else
# tx fee
chain33_applyCoins "$pokerbull1" 1000000000 "${main_ip}"
chain33_QueryBalance "${pokerbull1}" "$main_ip"
chain33_applyCoins "$pokerbull2" 1000000000 "${main_ip}"
chain33_QueryBalance "${pokerbull2}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" "14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4" "pokerbull1" "$para_ip"
chain33_ImportPrivkey "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" "1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1" "pokerbull2" "$para_ip"
......@@ -155,7 +101,6 @@ function run_test() {
pokerbull_PlayRawTx
pokerbull_QueryResult
}
function main() {
......@@ -165,7 +110,6 @@ function main() {
init
run_test
chain33_RpcTestRst pokerbull "$CASE_ERR"
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
privacy_CreateRawTransaction() {
local ip=$1
req='"method":"privacy.CreateRawTransaction","params":[{"pubkeypair":"0a9d212b2505aefaa8da370319088bbccfac097b007f52ed71d8133456c8185823c8eac43c5e937953d7b6c8e68b0db1f4f03df4946a29f524875118960a35fb", "assetExec":"coins", "tokenname":"BTY", "type":1, "amount":100000000}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$ip")
echo "#response: $resp"
ok=$(jq '.error|not' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"privacy.CreateRawTransaction","params":[{"pubkeypair":"0a9d212b2505aefaa8da370319088bbccfac097b007f52ed71d8133456c8185823c8eac43c5e937953d7b6c8e68b0db1f4f03df4946a29f524875118960a35fb", "assetExec":"coins", "tokenname":"BTY", "type":1, "amount":100000000}]}'
chain33_Http "$req" ${MAIN_HTTP} '.error|not' "$FUNCNAME"
}
privacy_GetPrivacyTxByAddr() {
local ip=$1
req='"method":"privacy.GetPrivacyTxByAddr","params":[{"tokenname":"BTY","sendRecvFlag":0,"from":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "direction":1, "count":1}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$ip")
echo "#response: $resp"
ok=$(jq '.error|not' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_Http '{"method":"privacy.GetPrivacyTxByAddr","params":[{"tokenname":"BTY","sendRecvFlag":0,"from":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "direction":1, "count":1}]}' ${MAIN_HTTP} '.error|not' "$FUNCNAME"
}
privacy_ShowPrivacyKey() {
local ip=$1
req='"method":"privacy.ShowPrivacyKey", "params":[{"data":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$ip")
echo "#response: $resp"
ok=$(jq '(.error|not) and .result.showSuccessful and (.result.pubkeypair=="0a9d212b2505aefaa8da370319088bbccfac097b007f52ed71d8133456c8185823c8eac43c5e937953d7b6c8e68b0db1f4f03df4946a29f524875118960a35fb")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"privacy.ShowPrivacyKey", "params":[{"data":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"}]}'
resok='(.error|not) and .result.showSuccessful and (.result.pubkeypair=="0a9d212b2505aefaa8da370319088bbccfac097b007f52ed71d8133456c8185823c8eac43c5e937953d7b6c8e68b0db1f4f03df4946a29f524875118960a35fb")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
privacy_ShowPrivacyAccountInfo() {
local ip=$1
req='"method":"privacy.ShowPrivacyAccountInfo", "params":[{"addr":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "token":"BTY", "displaymode":1}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$ip")
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result|[has("utxos", "ftxos", "displaymode"), true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
req='{"method":"privacy.ShowPrivacyAccountInfo", "params":[{"addr":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "token":"BTY", "displaymode":1}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result|[has("utxos", "ftxos", "displaymode"), true] | unique | length == 1)' "$FUNCNAME"
}
privacy_ShowPrivacyAccountSpend() {
local ip=$1
req='"method":"privacy.ShowPrivacyAccountSpend", "params":[{"addr":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "token":"BTY"}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$ip")
echo "#response: $resp"
ok=$(jq '(.error|not) and .result.utxoHaveTxHashs' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_Http '{"method":"privacy.ShowPrivacyAccountSpend", "params":[{"addr":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "token":"BTY"}]}' ${MAIN_HTTP} '(.error|not) and .result.utxoHaveTxHashs' "$FUNCNAME"
}
privacy_RescanUtxos() {
local ip=$1
req='"method":"privacy.RescanUtxos", "params":[{"addrs":["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"], "flag":0}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$ip")
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result|[has("flag", "repRescanResults"), true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_Http '{"method":"privacy.RescanUtxos", "params":[{"addrs":["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"], "flag":0}]}' ${MAIN_HTTP} '(.error|not) and (.result|[has("flag", "repRescanResults"), true] | unique | length == 1)' "$FUNCNAME"
}
privacy_EnablePrivacy() {
local ip=$1
req='"method":"privacy.EnablePrivacy", "params":[{"addrs":["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"]}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$ip")
echo "#response: $resp"
ok=$(jq '(.error|not) and .result.results[0].IsOK' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_Http '{"method":"privacy.EnablePrivacy", "params":[{"addrs":["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"]}]}' ${MAIN_HTTP} '(.error|not) and .result.results[0].IsOK' "$FUNCNAME"
}
function run_test() {
local ip=$1
privacy_EnablePrivacy "$ip"
privacy_ShowPrivacyKey "$ip"
privacy_CreateRawTransaction "$ip"
privacy_ShowPrivacyAccountInfo "$ip"
privacy_ShowPrivacyAccountSpend "$ip"
privacy_RescanUtxos "$ip"
privacy_GetPrivacyTxByAddr "$ip"
privacy_EnablePrivacy
privacy_ShowPrivacyKey
privacy_CreateRawTransaction
privacy_ShowPrivacyAccountInfo
privacy_ShowPrivacyAccountSpend
privacy_RescanUtxos
privacy_GetPrivacyTxByAddr
}
function main() {
MAIN_HTTP="$1"
chain33_RpcTestBegin privacy
MAIN_HTTP="$1"
echo "ip=$MAIN_HTTP"
run_test "$MAIN_HTTP"
run_test
chain33_RpcTestRst privacy "$CASE_ERR"
}
main "$1"
chain33_debug_function main "$1"
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
relay_CreateRawRelaySaveBTCHeadTx() {
local req='"method":"relay.CreateRawRelaySaveBTCHeadTx","params":[{"hash":"5e7d9c599cd040ec2ba53f4dee28028710be8c135e779f65c56feadaae34c3f2","height":10,"version":536870912,"merkleRoot":"ab91cd4160e1379c337eee6b7a4bdbb7399d70268d86045aba150743c00c90b6","time":1530862108,"nonce":0,"bits":545259519,"previousHash":"604efe53975ab06cad8748fd703ad5bc960e8b752b2aae98f0f871a4a05abfc7","isReset":true}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
local req='{"method":"relay.CreateRawRelaySaveBTCHeadTx","params":[{"hash":"5e7d9c599cd040ec2ba53f4dee28028710be8c135e779f65c56feadaae34c3f2","height":10,"version":536870912,"merkleRoot":"ab91cd4160e1379c337eee6b7a4bdbb7399d70268d86045aba150743c00c90b6","time":1530862108,"nonce":0,"bits":545259519,"previousHash":"604efe53975ab06cad8748fd703ad5bc960e8b752b2aae98f0f871a4a05abfc7","isReset":true}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
}
relay_CreateRawRelaySaveBTCHeadTx_11() {
local req='"method":"relay.CreateRawRelaySaveBTCHeadTx","params":[{"hash":"7b7a4a9b49db5a1162be515d380cd186e98c2bf0bb90f1145485d7c43343fc7c","height":11,"version":536870912,"merkleRoot":"cfa9b66696aea63b7266ffaa1cb4b96c8dd6959eaabf2eb14173f4adaa551f6f","time":1530862108,"nonce":1,"bits":545259519,"previousHash":"5e7d9c599cd040ec2ba53f4dee28028710be8c135e779f65c56feadaae34c3f2","isReset":false}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
local req='{"method":"relay.CreateRawRelaySaveBTCHeadTx","params":[{"hash":"7b7a4a9b49db5a1162be515d380cd186e98c2bf0bb90f1145485d7c43343fc7c","height":11,"version":536870912,"merkleRoot":"cfa9b66696aea63b7266ffaa1cb4b96c8dd6959eaabf2eb14173f4adaa551f6f","time":1530862108,"nonce":1,"bits":545259519,"previousHash":"5e7d9c599cd040ec2ba53f4dee28028710be8c135e779f65c56feadaae34c3f2","isReset":false}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
}
relay_CreateRawRelayOrderTx() {
local req='"method":"relay.CreateRawRelayOrderTx","params":[{"operation":0,"coin":"BTC","amount":299000000,"addr":"1Am9UTGfdnxabvcywYG2hvzr6qK8T3oUZT","btyAmount":1000000000,"coinWaits":6}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
local req='{"method":"relay.CreateRawRelayOrderTx","params":[{"operation":0,"coin":"BTC","amount":299000000,"addr":"1Am9UTGfdnxabvcywYG2hvzr6qK8T3oUZT","btyAmount":1000000000,"coinWaits":6}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
}
relay_CreateRawRelayAcceptTx() {
......@@ -54,16 +33,9 @@ relay_CreateRawRelayAcceptTx() {
exit 1
fi
local req='"method":"relay.CreateRawRelayAcceptTx","params":[{"orderId":"'"$id"'","coinAddr":"1Am9UTGfdnxabvcywYG2hvzr6qK8T3oUZT"}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "0xec9162ea5fc2f473ab8240619a0a0f495ba9e9e5d4d9c434b8794a68280236c4" "${MAIN_HTTP}"
local req='{"method":"relay.CreateRawRelayAcceptTx","params":[{"orderId":"'"$id"'","coinAddr":"1Am9UTGfdnxabvcywYG2hvzr6qK8T3oUZT"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "0xec9162ea5fc2f473ab8240619a0a0f495ba9e9e5d4d9c434b8794a68280236c4" "${MAIN_HTTP}"
}
relay_CreateRawRelayRevokeTx() {
......@@ -76,16 +48,9 @@ relay_CreateRawRelayRevokeTx() {
exit 1
fi
local req='"method":"relay.CreateRawRelayRevokeTx","params":[{"orderId":"'"$id"'","target":0,"action":1}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
local req='{"method":"relay.CreateRawRelayRevokeTx","params":[{"orderId":"'"$id"'","target":0,"action":1}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "0x22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "${MAIN_HTTP}"
}
relay_CreateRawRelayConfirmTx() {
......@@ -98,71 +63,36 @@ relay_CreateRawRelayConfirmTx() {
exit 1
fi
local req='"method":"relay.CreateRawRelayConfirmTx","params":[{"orderId":"'"$id"'","rawTx":"6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4"}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "0xec9162ea5fc2f473ab8240619a0a0f495ba9e9e5d4d9c434b8794a68280236c4" "${MAIN_HTTP}"
local req='{"method":"relay.CreateRawRelayConfirmTx","params":[{"orderId":"'"$id"'","rawTx":"6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "0xec9162ea5fc2f473ab8240619a0a0f495ba9e9e5d4d9c434b8794a68280236c4" "${MAIN_HTTP}"
}
query_GetRelayOrderByStatus() {
status="$1"
local req='"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetRelayOrderByStatus","payload":{"addr":"","status":"'"$status"'","coins":["BTC"],"pageNumber":0,"pageSize":0}}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.relayorders[0].id != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
local req='{"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetRelayOrderByStatus","payload":{"addr":"","status":"'"$status"'","coins":["BTC"],"pageNumber":0,"pageSize":0}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.relayorders[0].id != null)' "$FUNCNAME"
}
query_GetSellRelayOrder() {
local req='"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetSellRelayOrder","payload":{"addr":"1G5Cjy8LuQex2fuYv3gzb7B8MxAnxLEqt3","status":"pending","coins":["BTC"],"pageNumber":0,"pageSize":0}}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.relayorders[0].status == "pending") and (.result.relayorders[0].coinOperation == 0) and (.result.relayorders[0].id != "") ' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
local req='{"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetSellRelayOrder","payload":{"addr":"1G5Cjy8LuQex2fuYv3gzb7B8MxAnxLEqt3","status":"pending","coins":["BTC"],"pageNumber":0,"pageSize":0}}]}'
resok='(.error|not) and (.result.relayorders[0].status == "pending") and (.result.relayorders[0].coinOperation == 0) and (.result.relayorders[0].id != null)'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
query_GetBuyRelayOrder() {
local req='"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetBuyRelayOrder","payload":{"addr":"1EZKahMRfoMiKp1BewjWrQWoaJ9kmC4hum","status":"locking","coins":["BTC"],"pageNumber":0,"pageSize":0}}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.relayorders[0].status == "locking")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
local req='{"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetBuyRelayOrder","payload":{"addr":"1EZKahMRfoMiKp1BewjWrQWoaJ9kmC4hum","status":"locking","coins":["BTC"],"pageNumber":0,"pageSize":0}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.relayorders[0].status == "locking")' "$FUNCNAME"
}
query_GetBTCHeaderList() {
local req='"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetBTCHeaderList","payload":{"reqHeight":"10","counts":10,"direction":0}}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.heights|length == 2)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
local req='{"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetBTCHeaderList","payload":{"reqHeight":"10","counts":10,"direction":0}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.heights|length == 2)' "$FUNCNAME"
}
query_GetBTCHeaderCurHeight() {
local req='"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetBTCHeaderCurHeight","payload":{"baseHeight":"0"}}]'
# echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.baseHeight == "10") and (.result.curHeight == "10")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
local req='{"method":"Chain33.Query", "params":[{"execer":"relay","funcName":"GetBTCHeaderCurHeight","payload":{"baseHeight":"0"}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.baseHeight == "10") and (.result.curHeight == "10")' "$FUNCNAME"
}
init() {
......@@ -178,10 +108,7 @@ init() {
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#1G5Cjy8LuQex2fuYv3gzb7B8MxAnxLEqt3
chain33_ImportPrivkey "22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "1G5Cjy8LuQex2fuYv3gzb7B8MxAnxLEqt3" "relay_sell" "${main_ip}"
#1EZKahMRfoMiKp1BewjWrQWoaJ9kmC4hum
chain33_ImportPrivkey "ec9162ea5fc2f473ab8240619a0a0f495ba9e9e5d4d9c434b8794a68280236c4" "1EZKahMRfoMiKp1BewjWrQWoaJ9kmC4hum" "relay_acc" "$main_ip"
local sellAddr="1G5Cjy8LuQex2fuYv3gzb7B8MxAnxLEqt3"
......@@ -194,14 +121,12 @@ init() {
chain33_applyCoins "$accepAddr" 12000000000 "${main_ip}"
chain33_QueryBalance "${accepAddr}" "$main_ip"
else
# tx fee
chain33_applyCoins "$sellAddr" 1000000000 "${main_ip}"
chain33_QueryBalance "${sellAddr}" "$main_ip"
chain33_applyCoins "$accepAddr" 1000000000 "${main_ip}"
chain33_QueryBalance "${accepAddr}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "22968d29c6de695381a8719ef7bf00e2edb6cce500bb59a4fc73c41887610962" "1G5Cjy8LuQex2fuYv3gzb7B8MxAnxLEqt3" "relay_sell" "$para_ip"
chain33_ImportPrivkey "ec9162ea5fc2f473ab8240619a0a0f495ba9e9e5d4d9c434b8794a68280236c4" "1EZKahMRfoMiKp1BewjWrQWoaJ9kmC4hum" "relay_acc" "$para_ip"
......@@ -238,7 +163,6 @@ function run_testcases() {
relay_CreateRawRelaySaveBTCHeadTx_11
query_GetBTCHeaderList
}
function rpc_test() {
......@@ -248,7 +172,6 @@ function rpc_test() {
init
run_testcases
chain33_RpcTestRst Relay "$CASE_ERR"
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
# TODO
......@@ -19,7 +19,7 @@ function updateConfig() {
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
chain33_SignAndSendTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
}
function token_preCreate() {
......@@ -29,7 +29,7 @@ function token_preCreate() {
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
chain33_SignAndSendTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
}
function token_finish() {
......@@ -39,7 +39,7 @@ function token_finish() {
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
chain33_SignAndSendTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
}
function token_sendExec() {
......@@ -49,7 +49,7 @@ function token_sendExec() {
return
fi
chain33_SignRawTx "${unsignedTx}" "$3" "${MAIN_HTTP}"
chain33_SignAndSendTx "${unsignedTx}" "$3" "${MAIN_HTTP}"
}
function createToken() {
......@@ -61,126 +61,45 @@ function createToken() {
}
retrieve_Backup() {
echo "========== # retrieve backup begin =========="
local req='{"method":"retrieve.CreateRawRetrieveBackupTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'","delayPeriod": 61}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
local reqDecode='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}'
data=$(curl -ksd "$reqDecode" ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "$retrieve2_key" ${MAIN_HTTP}
echo "========== # retrieve backup end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
chain33_SignAndSendTxWait "$tx" "$retrieve2_key" ${MAIN_HTTP} "$FUNCNAME"
}
retrieve_Prepare() {
echo "========== # retrieve prepare begin =========="
local req='{"method":"retrieve.CreateRawRetrievePrepareTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
local reqDecode='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}'
data=$(curl -ksd "$reqDecode" ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "$retrieve1_key" ${MAIN_HTTP}
echo "========== # retrieve prepare end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
chain33_SignAndSendTxWait "$tx" "$retrieve1_key" ${MAIN_HTTP} "$FUNCNAME"
}
retrieve_Perform() {
echo "========== # retrieve perform begin =========="
local req='{"method":"retrieve.CreateRawRetrievePerformTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
local reqDecode='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}'
data=$(curl -ksd "$reqDecode" ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "$retrieve1_key" ${MAIN_HTTP}
echo "========== # retrieve perform end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
chain33_SignAndSendTxWait "$tx" "$retrieve1_key" ${MAIN_HTTP} "$FUNCNAME"
}
retrieve_Perform_Token() {
echo "========== # retrieve perform begin =========="
local req='{"method":"retrieve.CreateRawRetrievePerformTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'","assets": [{"exec":"token","symbol":"'"$symbol"'"}] }]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
local reqDecode='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}'
data=$(curl -ksd "$reqDecode" ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "$retrieve1_key" ${MAIN_HTTP}
echo "========== # retrieve perform end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
chain33_SignAndSendTxWait "$tx" "$retrieve1_key" ${MAIN_HTTP} "$FUNCNAME"
}
retrieve_Cancel() {
echo "========== # retrieve cancel begin =========="
local req='{"method":"retrieve.CreateRawRetrieveCancelTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
local reqDecode='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}'
data=$(curl -ksd "$reqDecode" ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer != "")' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "$retrieve2_key" ${MAIN_HTTP}
echo "========== # retrieve cancel end =========="
chain33_BlockWait 1 "${MAIN_HTTP}"
chain33_SignAndSendTxWait "$tx" "$retrieve2_key" ${MAIN_HTTP} "$FUNCNAME"
}
retrieve_QueryResult() {
echo "========== # retrieve query result begin =========="
local status=$1
local req='{"method":"Chain33.Query","params":[{"execer":"retrieve","funcName":"GetRetrieveInfo","payload":{"backupAddress":"'$retrieve1'", "defaultAddress":"'$retrieve2'"}}]}'
data=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
ok=$(jq '(.status == '"$status"')' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
echo "========== # retrieve query result end =========="
chain33_Http "$req" ${MAIN_HTTP} '(.result.status == '"$status"')' "$FUNCNAME"
}
retrieve_QueryAssetResult() {
echo "========== # retrieve query result begin =========="
local status=$1
local req='{"method":"Chain33.Query","params":[{"execer":"retrieve","funcName":"GetRetrieveInfo","payload":{"backupAddress":"'$retrieve1'", "defaultAddress":"'$retrieve2'","assetExec":"token", "assetSymbol":"'"$symbol"'"}}]}'
data=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
ok=$(jq '(.status == '"$status"')' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
echo "========== # retrieve query result end =========="
chain33_Http "$req" ${MAIN_HTTP} '(.result.status == '"$status"')' "$FUNCNAME"
}
init() {
......@@ -207,7 +126,6 @@ init() {
chain33_applyCoins "${retrieve2}" 10000000000 "${MAIN_HTTP}"
if [ "$ispara" == true ]; then
# for fee
local main_ip=${MAIN_HTTP//8901/8801}
chain33_applyCoins "${retrieve1}" 1000000000 "${main_ip}"
chain33_applyCoins "${retrieve2}" 1000000000 "${main_ip}"
......@@ -244,15 +162,13 @@ function run_test() {
}
function main() {
MAIN_HTTP="$1"
chain33_RpcTestBegin retrieve
MAIN_HTTP="$1"
echo "ip=$MAIN_HTTP"
init
run_test
chain33_RpcTestRst retrieve "$CASE_ERR"
}
set -x
chain33_debug_function main "$1"
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e
set -o pipefail
MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh
ticketId=""
......@@ -17,107 +17,71 @@ ticket_CreateBindMiner() {
returnAddr=$2
returnPriv=$3
amount=$4
resp=$(curl -ksd '{"method":"ticket.CreateBindMiner","params":[{"bindAddr":"'"$minerAddr"'", "originAddr":"'"$returnAddr"'", "amount":'"$amount"', "checkBalance":true}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[[ $ok == null ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result.txHex")
chain33_SignRawTx "${rawTx}" "${returnPriv}" ${MAIN_HTTP}
req='{"method":"ticket.CreateBindMiner","params":[{"bindAddr":"'"$minerAddr"'", "originAddr":"'"$returnAddr"'", "amount":'"$amount"', "checkBalance":true}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result.txHex"
chain33_SignAndSendTx "$RETURN_RESP" "${returnPriv}" ${MAIN_HTTP}
}
ticket_SetAutoMining() {
flag=$1
resp=$(curl -ksd '{"method":"ticket.SetAutoMining","params":[{"flag":'"$flag"'}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.isOK == true)' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"ticket.SetAutoMining","params":[{"flag":'"$flag"'}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.isOK == true)' "$FUNCNAME"
}
ticket_GetTicketCount() {
resp=$(curl -ksd '{"method":"ticket.GetTicketCount","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result > 0)' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
chain33_Http '{"method":"ticket.GetTicketCount","params":[{}]}' ${MAIN_HTTP} '(.error|not) and (.result > 0)' "$FUNCNAME"
}
ticket_CloseTickets() {
addr=$1
resp=$(curl -ksd '{"method":"ticket.CloseTickets","params":[{"minerAddress":"'"$addr"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not)' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"ticket.CloseTickets","params":[{"minerAddress":"'"$addr"'"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME"
}
ticket_TicketInfos() {
tid=$1
minerAddr=$2
returnAddr=$3
execer="ticket"
funcName="TicketInfos"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"ticketIds":["'"$tid"'"]}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.tickets | length > 0) and (.result.tickets[0].minerAddress == "'"$minerAddr"'") and (.result.tickets[0].returnAddress == "'"$returnAddr"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"ticket","funcName":"TicketInfos","payload":{"ticketIds":["'"$tid"'"]}}]}'
resok='(.error|not) and (.result.tickets | length > 0) and (.result.tickets[0].minerAddress == "'"$minerAddr"'") and (.result.tickets[0].returnAddress == "'"$returnAddr"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
ticket_TicketList() {
minerAddr=$1
returnAddr=$2
status=$3
execer="ticket"
funcName="TicketList"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"addr":"'"$minerAddr"'", "status":'"$status"'}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.tickets | length > 0) and (.result.tickets[0].minerAddress == "'"$minerAddr"'") and (.result.tickets[0].returnAddress == "'"$returnAddr"'") and (.result.tickets[0].status == '"$status"')' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
ticket0=$(echo "${resp}" | jq -r ".result.tickets[0]")
req='{"method":"Chain33.Query","params":[{"execer":"ticket","funcName":"TicketList","payload":{"addr":"'"$minerAddr"'", "status":'"$status"'}}]}'
resok='(.error|not) and (.result.tickets | length > 0) and (.result.tickets[0].minerAddress == "'"$minerAddr"'") and (.result.tickets[0].returnAddress == "'"$returnAddr"'") and (.result.tickets[0].status == '"$status"')'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
ticket0=$(echo "${RETURN_RESP}" | jq -r ".result.tickets[0]")
echo -e "######\\n ticket[0] is $ticket0) \\n######"
ticketId=$(echo "${resp}" | jq -r ".result.tickets[0].ticketId")
ticketId=$(echo "${RETURN_RESP}" | jq -r ".result.tickets[0].ticketId")
echo -e "######\\n ticketId is $ticketId \\n######"
}
ticket_MinerAddress() {
returnAddr=$1
minerAddr=$2
execer="ticket"
funcName="MinerAddress"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"data":"'"$returnAddr"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.data == "'"$minerAddr"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"ticket","funcName":"MinerAddress","payload":{"data":"'"$returnAddr"'"}}]}'
resok='(.error|not) and (.result.data == "'"$minerAddr"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
ticket_MinerSourceList() {
minerAddr=$1
returnAddr=$2
execer="ticket"
funcName="MinerSourceList"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"data":"'"$minerAddr"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.datas | length > 0) and (.result.datas[0] == "'"$returnAddr"'")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"ticket","funcName":"MinerSourceList","payload":{"data":"'"$minerAddr"'"}}]}'
resok='(.error|not) and (.result.datas | length > 0) and (.result.datas[0] == "'"$returnAddr"'")'
chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
}
ticket_RandNumHash() {
hash=$1
blockNum=$2
execer="ticket"
funcName="RandNumHash"
resp=$(curl -ksd '{"method":"Chain33.Query","params":[{"execer":"'"$execer"'","funcName":"'"$funcName"'","payload":{"hash":"'"$hash"'", "blockNum":'"$blockNum"'}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.hash != "")' <<<"$resp")
[[ $ok == true ]]
rst=$?
echo_rst "$FUNCNAME" "$rst"
req='{"method":"Chain33.Query","params":[{"execer":"ticket","funcName":"RandNumHash","payload":{"hash":"'"$hash"'", "blockNum":'"$blockNum"'}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.hash != null)' "$FUNCNAME"
}
function run_testcases() {
......
......@@ -29,6 +29,7 @@ func TicketCmd() *cobra.Command {
CountTicketCmd(),
CloseTicketCmd(),
GetColdAddrByMinerCmd(),
listTicketCmd(),
)
return cmd
......@@ -97,6 +98,41 @@ func countTicket(cmd *cobra.Command, args []string) {
ctx.Run()
}
// listTicketCmd get ticket count
func listTicketCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "Get ticket id list",
Run: listTicket,
}
cmd.Flags().StringP("miner_acct", "m", "", "miner address (optional)")
cmd.Flags().Int32P("status", "s", 1, "ticket status (default 1:opened tickets)")
return cmd
}
func listTicket(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
minerAddr, _ := cmd.Flags().GetString("miner_acct")
status, _ := cmd.Flags().GetInt32("status")
if minerAddr != "" {
var params rpctypes.Query4Jrpc
params.Execer = ty.TicketX
params.FuncName = "TicketList"
req := ty.TicketList{Addr: minerAddr, Status: status}
params.Payload = types.MustPBToJSON(&req)
var res ty.ReplyTicketList
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
return
}
var res []ty.Ticket
ctx := jsonclient.NewRPCCtx(rpcLaddr, "ticket.GetTicketList", nil, &res)
ctx.Run()
}
// CloseTicketCmd close all accessible tickets
func CloseTicketCmd() *cobra.Command {
cmd := &cobra.Command{
......
......@@ -222,6 +222,7 @@ ForkBase58AddressCheck=-1 #fork6.2
ForkEnableParaRegExec=0
ForkCacheDriver=0
ForkTicketFundAddrV1=-1 #fork6.3
ForkRootHash =1
[fork.sub.coins]
Enable=0
[fork.sub.ticket]
......
......@@ -51,7 +51,7 @@ func NewDB(cfg *types.Chain33Config, id, minerAddress, returnWallet string, bloc
t.MinerAddress = minerAddress
t.ReturnAddress = returnWallet
t.CreateTime = blocktime
t.Status = 1
t.Status = ty.TicketOpened
t.IsGenesis = isGenesis
t.prevstatus = 0
//height == 0 的情况下,不去改变 genesis block
......@@ -73,11 +73,11 @@ func NewDB(cfg *types.Chain33Config, id, minerAddress, returnWallet string, bloc
// GetReceiptLog get receipt
func (t *DB) GetReceiptLog() *types.ReceiptLog {
log := &types.ReceiptLog{}
if t.Status == 1 {
if t.Status == ty.TicketOpened {
log.Ty = ty.TyLogNewTicket
} else if t.Status == 2 {
} else if t.Status == ty.TicketMined {
log.Ty = ty.TyLogMinerTicket
} else if t.Status == 3 {
} else if t.Status == ty.TicketClosed {
log.Ty = ty.TyLogCloseTicket
}
r := &ty.ReceiptTicket{}
......@@ -305,7 +305,7 @@ func (action *Action) TicketMiner(miner *ty.TicketMiner, index int) (*types.Rece
if err != nil {
return nil, err
}
if ticket.Status != 1 {
if ticket.Status != ty.TicketOpened {
return nil, types.ErrCoinBaseTicketStatus
}
cfg := ty.GetTicketMinerParam(chain33Cfg, action.height)
......@@ -330,7 +330,7 @@ func (action *Action) TicketMiner(miner *ty.TicketMiner, index int) (*types.Rece
}
}
prevstatus := ticket.Status
ticket.Status = 2
ticket.Status = ty.TicketMined
ticket.MinerValue = miner.Reward
if chain33Cfg.IsFork(action.height, "ForkMinerTime") {
ticket.MinerTime = action.blocktime
......@@ -383,20 +383,20 @@ func (action *Action) TicketClose(tclose *ty.TicketClose) (*types.Receipt, error
return nil, err
}
//ticket 的生成时间超过 2天,可提款
if ticket.Status != 2 && ticket.Status != 1 {
if ticket.Status != ty.TicketMined && ticket.Status != ty.TicketOpened {
tlog.Error("ticket", "id", ticket.GetTicketId(), "status", ticket.GetStatus())
return nil, ty.ErrTicketClosed
}
if !ticket.IsGenesis {
//分成两种情况
if ticket.Status == 1 && action.blocktime-ticket.GetCreateTime() < cfg.TicketWithdrawTime {
if ticket.Status == ty.TicketOpened && action.blocktime-ticket.GetCreateTime() < cfg.TicketWithdrawTime {
return nil, ty.ErrTime
}
//已经挖矿成功了
if ticket.Status == 2 && action.blocktime-ticket.GetCreateTime() < cfg.TicketWithdrawTime {
if ticket.Status == ty.TicketMined && action.blocktime-ticket.GetCreateTime() < cfg.TicketWithdrawTime {
return nil, ty.ErrTime
}
if ticket.Status == 2 && action.blocktime-ticket.GetMinerTime() < cfg.TicketMinerWaitTime {
if ticket.Status == ty.TicketMined && action.blocktime-ticket.GetMinerTime() < cfg.TicketMinerWaitTime {
return nil, ty.ErrTime
}
}
......@@ -405,7 +405,7 @@ func (action *Action) TicketClose(tclose *ty.TicketClose) (*types.Receipt, error
return nil, types.ErrFromAddr
}
prevstatus := ticket.Status
ticket.Status = 3
ticket.Status = ty.TicketClosed
tickets[i] = &DB{*ticket, prevstatus}
}
var logs []*types.ReceiptLog
......
......@@ -143,3 +143,25 @@ func (c *Jrpc) SetAutoMining(in *ty.MinerFlag, result *rpctypes.Reply) error {
*result = reply
return nil
}
// GetTicketList get ticket list info
func (g *channelClient) GetTicketList(ctx context.Context, in *types.ReqNil) ([]*ty.Ticket, error) {
inn := *in
data, err := g.ExecWalletFunc(ty.TicketX, "WalletGetTickets", &inn)
if err != nil {
return nil, err
}
return data.(*ty.ReplyWalletTickets).Tickets, nil
}
// GetTicketList get ticket list info
func (c *Jrpc) GetTicketList(in *types.ReqNil, result *interface{}) error {
resp, err := c.cli.GetTicketList(context.Background(), &types.ReqNil{})
if err != nil {
return err
}
*result = resp
return nil
}
......@@ -273,6 +273,7 @@ ForkBase58AddressCheck=1800000
ForkEnableParaRegExec=0
ForkCacheDriver=0
ForkTicketFundAddrV1=-1
ForkRootHash=1
[fork.sub.coins]
Enable=0
......
......@@ -13,6 +13,18 @@ import (
"github.com/33cn/chain33/types"
)
// 0 -> 未成熟 1 -> 可挖矿 2 -> 已挖成功 3-> 已关闭
const (
//TicketInit ticket init status
TicketInit = iota
//TicketOpened ticket opened status
TicketOpened
//TicketMined ticket mined status
TicketMined
//TicketClosed ticket closed status
TicketClosed
)
const (
//log for ticket
......
......@@ -406,13 +406,13 @@ func (policy *ticketPolicy) forceCloseTicketList(height int64, priv crypto.PrivK
cfg := ty.GetTicketMinerParam(chain33Cfg, height)
for _, t := range tlist {
if !t.IsGenesis {
if t.Status == 1 && now-t.GetCreateTime() < cfg.TicketWithdrawTime {
if t.Status == ty.TicketOpened && now-t.GetCreateTime() < cfg.TicketWithdrawTime {
continue
}
if t.Status == 2 && now-t.GetCreateTime() < cfg.TicketWithdrawTime {
if t.Status == ty.TicketMined && now-t.GetCreateTime() < cfg.TicketWithdrawTime {
continue
}
if t.Status == 2 && now-t.GetMinerTime() < cfg.TicketMinerWaitTime {
if t.Status == ty.TicketMined && now-t.GetMinerTime() < cfg.TicketMinerWaitTime {
continue
}
}
......
......@@ -40,10 +40,16 @@ func TestForceCloseTicketList(t *testing.T) {
wallet.api = qapi
ticket.walletOperate = wallet
t1 := &ty.Ticket{Status: 1, IsGenesis: false}
t2 := &ty.Ticket{Status: 2, IsGenesis: false}
t3 := &ty.Ticket{Status: 3, IsGenesis: false}
tlist := []*ty.Ticket{t1, t2, t3}
t1 := &ty.Ticket{Status: ty.TicketOpened, IsGenesis: false}
t2 := &ty.Ticket{Status: ty.TicketMined, IsGenesis: false}
t3 := &ty.Ticket{Status: ty.TicketClosed, IsGenesis: false}
now := types.Now().Unix()
t4 := &ty.Ticket{Status: ty.TicketOpened, IsGenesis: false, CreateTime: now}
t5 := &ty.Ticket{Status: ty.TicketMined, IsGenesis: false, CreateTime: now}
t6 := &ty.Ticket{Status: ty.TicketMined, IsGenesis: false, MinerTime: now}
tlist := []*ty.Ticket{t1, t2, t3, t4, t5, t6}
r1, r2 := ticket.forceCloseTicketList(0, nil, tlist)
assert.Equal(t, []byte(sendhash), r1)
......@@ -69,9 +75,9 @@ func TestCloseTicketsByAddr(t *testing.T) {
wallet.api = qapi
ticket.walletOperate = wallet
t1 := &ty.Ticket{Status: 1, IsGenesis: false}
t2 := &ty.Ticket{Status: 2, IsGenesis: false}
t3 := &ty.Ticket{Status: 3, IsGenesis: false}
t1 := &ty.Ticket{Status: ty.TicketOpened, IsGenesis: false}
t2 := &ty.Ticket{Status: ty.TicketMined, IsGenesis: false}
t3 := &ty.Ticket{Status: ty.TicketClosed, IsGenesis: false}
tlist := &ty.ReplyTicketList{Tickets: []*ty.Ticket{t1, t2, t3}}
qapi.On("Query", ty.TicketX, "TicketList", mock.Anything).Return(tlist, nil)
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
CASE_ERR=""
tokenAddr="1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK"
recvAddr="1CLrYLNhHfCfMUV7mtdqhbMSF6vGmtTvzq"
superManager="0xc34b5d9d44ac7b754806f761d3d4d2c4fe5214f6b074c19f069c4f5c2a29c8cc"
tokenSymbol="ABCDE"
token_addr=""
execName="token"
txHash=""
#color
RED='\033[1;31m'
GRE='\033[1;32m'
NOC='\033[0m'
# $2=0 means true, other false
function echo_rst() {
if [ "$2" -eq 0 ]; then
echo -e "${GRE}$1 ok${NOC}"
else
echo -e "${RED}$1 fail${NOC}"
CASE_ERR="FAIL"
fi
}
# 查询交易的执行结果
# 根据传入的规则,校验查询的结果 (参数1: 校验规则 参数2: 预期匹配结果)
function queryTransaction() {
validator=$1
expectRes=$2
echo "txhash=${txHash}"
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.QueryTransaction","params":[{"hash":"'"${txHash}"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r "${validator}")
# echo "txhash=${RAW_TX_HASH}"
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.QueryTransaction","params":[{"hash":"'"${RAW_TX_HASH}"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r "${validator}")
if [ "${res}" != "${expectRes}" ]; then
return 1
else
......@@ -43,14 +25,18 @@ function queryTransaction() {
fi
}
function signRawTxAndQuery() {
chain33_SignAndSendTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "$1 queryExecRes" "$?"
}
function init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ipara=$ispara"
chain33_ImportPrivkey "${superManager}" "${tokenAddr}" "tokenAddr" "${MAIN_HTTP}"
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#1CLrYLNhHfCfMUV7mtdqhbMSF6vGmtTvzq
chain33_ImportPrivkey "0x882c963ce2afbedc2353cb417492aa9e889becd878a10f2529fc9e6c3b756128" "1CLrYLNhHfCfMUV7mtdqhbMSF6vGmtTvzq" "token1" "${main_ip}"
local ACCOUNT_A="1CLrYLNhHfCfMUV7mtdqhbMSF6vGmtTvzq"
......@@ -59,12 +45,10 @@ function init() {
chain33_applyCoins "$ACCOUNT_A" 12000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$main_ip"
else
# tx fee
chain33_applyCoins "$ACCOUNT_A" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0x882c963ce2afbedc2353cb417492aa9e889becd878a10f2529fc9e6c3b756128" "1CLrYLNhHfCfMUV7mtdqhbMSF6vGmtTvzq" "token1" "$para_ip"
chain33_applyCoins "$ACCOUNT_A" 12000000000 "${para_ip}"
......@@ -96,25 +80,16 @@ function updateConfig() {
echo_rst "update config create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "update config queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function token_preCreate() {
unsignedTx=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"token.CreateRawTokenPreCreateTx","params":[{"name": "yinhebib", "symbol": "'"${tokenSymbol}"'", "total": 100000000000, "price": 100, "category": 1,"owner":"'${tokenAddr}'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result")
if [ "${unsignedTx}" == "" ]; then
echo_rst "token preCreate create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "token preCreate queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function token_getPreCreated() {
......@@ -132,21 +107,12 @@ function token_finish() {
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "token finish queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function token_getFinishCreated() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${execName}"'","funcName":"GetTokens","payload":{"queryAll":true,"status":1,"tokens":[],"symbolOnly":false}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result.tokens" | grep "symbol")
if [ "${res}" != "" ]; then
echo_rst "token get finishCreated create tx" 0
else
echo_rst "token get finishCreated create tx" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${execName}"'","funcName":"GetTokens","payload":{"queryAll":true,"status":1,"tokens":[],"symbolOnly":false}}]}'
chain33_Http "$req" ${MAIN_HTTP} "(.result.tokens[0].symbol != null)" "$FUNCNAME"
}
function token_assets() {
......@@ -166,8 +132,8 @@ function token_assets() {
else
echo_rst "token get assets tx" 1
fi
}
function token_balance() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"token.GetTokenBalance","params":[{"addresses": ["'${tokenAddr}'"],"tokenSymbol":"'"${tokenSymbol}"'","execer": "'"${execName}"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
......@@ -192,12 +158,7 @@ function token_burn() {
echo_rst "token burn create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "token burn queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function token_mint() {
......@@ -206,12 +167,7 @@ function token_mint() {
echo_rst "token mint create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "token mint queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function token_transfer() {
unsignedTx=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.CreateTransaction","params":[{"execer": "'"${execName}"'","actionName":"Transfer","payload": {"cointoken":"'"${tokenSymbol}"'", "amount": "1000000000", "note": "", "to": "'"${recvAddr}"'"}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result")
......@@ -219,12 +175,7 @@ function token_transfer() {
echo_rst "token transfer create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "token transfer queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function token_sendExec() {
......@@ -233,12 +184,7 @@ function token_sendExec() {
echo_rst "token sendExec create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "token sendExec queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function token_withdraw() {
......@@ -247,17 +193,11 @@ function token_withdraw() {
echo_rst "token withdraw create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${superManager}" "${MAIN_HTTP}"
txHash=$RAW_TX_HASH
queryTransaction ".error | not" "true"
echo_rst "token withdraw queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME"
}
function run_test() {
local ip=$1
set -x
token_preCreate
token_getPreCreated
......@@ -271,19 +211,16 @@ function run_test() {
token_sendExec
token_assets
token_withdraw
set +x
}
function main() {
local ip=$1
chain33_RpcTestBegin token
local ip=$1
MAIN_HTTP=$ip
echo "main_ip=$MAIN_HTTP"
init
run_test "$ip"
chain33_RpcTestRst token "$CASE_ERR"
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source ../dapp-test-common.sh
MAIN_HTTP=""
CASE_ERR=""
trade_addr=""
tradeAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
tradeBuyerAddr="1CvLe1qNaC7tCf5xmfAqJ9UJkMhtmhUKNg"
......@@ -17,11 +15,7 @@ function updateConfig() {
echo_rst "update config create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "update config queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
}
function token_preCreate() {
......@@ -30,11 +24,7 @@ function token_preCreate() {
echo_rst "token preCreate create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "token preCreate queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
}
function token_finish() {
......@@ -43,29 +33,12 @@ function token_finish() {
echo_rst "token finish create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "token finish queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
}
function token_balance() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"token.GetTokenBalance","params":[{"addresses": ["'"${tradeAddr}"'"],"tokenSymbol":"'"${tokenSymbol}"'","execer": "'"${tokenExecName}"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
if [ "${res}" == "" ]; then
echo_rst "token get balance tx" 1
return
fi
addr=$(echo "${res}" | jq -r ".result[0].addr")
balance=$(echo "${res}" | jq -r ".result[0].balance")
if [ "${addr}" == "${tradeAddr}" ] && [ "${balance}" -eq 1000000000000 ]; then
echo_rst "token get balance tx" 0
else
echo_rst "token get balance tx" 1
fi
req='{"method":"token.GetTokenBalance","params":[{"addresses": ["'"${tradeAddr}"'"],"tokenSymbol":"'"${tokenSymbol}"'","execer": "'"${tokenExecName}"'"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not) and (.result[0].addr == "'"${tradeAddr}"'") and (.result[0].balance == 1000000000000)' "$FUNCNAME"
}
function token_transfer() {
......@@ -75,11 +48,7 @@ function token_transfer() {
echo_rst "token transfer create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "token transfer queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
}
function token_sendExec() {
......@@ -89,11 +58,7 @@ function token_sendExec() {
echo_rst "token sendExec create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${addr}" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "token sendExec queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "${addr}"
}
function trade_createSellTx() {
......@@ -102,22 +67,13 @@ function trade_createSellTx() {
echo_rst "trade createSellTx create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "trade createSellTx queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
}
function trade_getSellOrder() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesSellOrder","payload":{"addr": "'"${tradeAddr}"'","token":["'"${tokenSymbol}"'"]}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
result=$(echo "${res}" | jq -r ".error | not")
if [ "${result}" == true ]; then
sellID=$(echo "${res}" | jq -r ".result.orders[0].sellID" | awk -F '-' '{print $4}')
echo_rst "trade getSellOrder" 0
else
echo_rst "trade getSellOrder" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesSellOrder","payload":{"addr": "'"${tradeAddr}"'","token":["'"${tokenSymbol}"'"]}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not)' "$FUNCNAME"
sellID=$(echo "${RETURN_RESP}" | jq -r ".result.orders[0].sellID" | awk -F '-' '{print $4}')
}
function trade_createBuyTx() {
......@@ -126,66 +82,37 @@ function trade_createBuyTx() {
echo_rst "trade createBuyTx create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0xaeef1ad76d43a2056d0dcb57d5bf1ba96471550614ab9e7f611ef9c5ca403f42" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "trade createBuyTx queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0xaeef1ad76d43a2056d0dcb57d5bf1ba96471550614ab9e7f611ef9c5ca403f42"
}
function trade_getBuyOrder() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesBuyOrder","payload":{"addr": "'"${tradeBuyerAddr}"'","token":["'"${tokenSymbol}"'"]}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".error | not")
if [ "${res}" == true ]; then
echo_rst "trade getBuyOrder" 0
else
echo_rst "trade getBuyOrder" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesBuyOrder","payload":{"addr": "'"${tradeBuyerAddr}"'","token":["'"${tokenSymbol}"'"]}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not)' "$FUNCNAME"
}
function trade_statusBuyOrder() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesBuyOrderWithStatus","payload":{"addr": "'"${tradeBuyerAddr}"'","status":6}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".error | not")
if [ "${res}" == true ]; then
echo_rst "trade getStatusBuyOrder" 0
else
echo_rst "trade getStatusBuyOrder" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesBuyOrderWithStatus","payload":{"addr": "'"${tradeBuyerAddr}"'","status":6}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not)' "$FUNCNAME"
}
function trade_statusOrder() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesOrderWithStatus","payload":{"addr": "'"${tradeAddr}"'","status":1}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".error | not")
if [ "${res}" == true ]; then
echo_rst "trade getStatusOrder" 0
else
echo_rst "trade getStatusOrder" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesOrderWithStatus","payload":{"addr": "'"${tradeAddr}"'","status":1}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not)' "$FUNCNAME"
}
function trade_statusSellOrder() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesSellOrderWithStatus","payload":{"addr": "'"${tradeAddr}"'", "status":1}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".error | not")
if [ "${res}" == true ]; then
echo_rst "trade getStatusSellOrder" 0
else
echo_rst "trade getStatusSellOrder" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetOnesSellOrderWithStatus","payload":{"addr": "'"${tradeAddr}"'", "status":1}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not)' "$FUNCNAME"
}
function trade_statusTokenBuyOrder() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetTokenBuyOrderByStatus","payload":{"tokenSymbol": "'"${tokenSymbol}"'", "count" :1 , "direction": 1,"status":6}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".error | not")
if [ "${res}" == true ]; then
echo_rst "trade getTokenBuyOrder" 0
else
echo_rst "trade getTokenBuyOrder" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetTokenBuyOrderByStatus","payload":{"tokenSymbol": "'"${tokenSymbol}"'", "count" :1 , "direction": 1,"status":6}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not)' "$FUNCNAME"
}
function trade_statusTokenSellOrder() {
res=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetTokenSellOrderByStatus","payload":{"tokenSymbol": "'"${tokenSymbol}"'", "count" :1 , "direction": 1,"status":1}}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".error | not")
if [ "${res}" == true ]; then
echo_rst "trade getTokenSellOrder" 0
else
echo_rst "trade getTokenSellOrder" 1
fi
req='{"method":"Chain33.Query","params":[{"execer":"'"${tradeExecName}"'","funcName":"GetTokenSellOrderByStatus","payload":{"tokenSymbol": "'"${tokenSymbol}"'", "count" :1 , "direction": 1,"status":1}}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error | not)' "$FUNCNAME"
}
function trade_buyLimit() {
......@@ -194,11 +121,7 @@ function trade_buyLimit() {
echo_rst "trade buyLimit create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0xaeef1ad76d43a2056d0dcb57d5bf1ba96471550614ab9e7f611ef9c5ca403f42" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "trade buyLimit queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0xaeef1ad76d43a2056d0dcb57d5bf1ba96471550614ab9e7f611ef9c5ca403f42"
buyID=$(curl -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.QueryTransaction","params":[{"hash":"'"${RAW_TX_HASH}"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result.receipt.logs[1].log.base.buyID" | awk -F '-' '{print $4}')
}
......@@ -208,11 +131,7 @@ function trade_sellMarket() {
echo_rst "trade sellMarket create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "${tradeAddr}" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "trade sellMarket queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "${tradeAddr}"
}
function trade_revokeBuy() {
......@@ -221,11 +140,7 @@ function trade_revokeBuy() {
echo_rst "trade revokeBuy create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "trade revokeBuy queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
}
function trade_revoke() {
......@@ -234,11 +149,7 @@ function trade_revoke() {
echo_rst "trade revoke create tx" 1
return
fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "trade revoke queryExecRes" "$?"
signRawTxAndQuery "$FUNCNAME" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
}
# 查询交易的执行结果
......@@ -255,6 +166,12 @@ function queryTransaction() {
fi
}
function signRawTxAndQuery() {
chain33_SignAndSendTx "${unsignedTx}" "$2" "${MAIN_HTTP}"
queryTransaction ".error | not" "true"
echo_rst "$1 queryExecRes" "$?"
}
function init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ipara=$ispara"
......@@ -274,8 +191,6 @@ function init() {
fi
local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#1CvLe1qNaC7tCf5xmfAqJ9UJkMhtmhUKNg
chain33_ImportPrivkey "0xaeef1ad76d43a2056d0dcb57d5bf1ba96471550614ab9e7f611ef9c5ca403f42" "1CvLe1qNaC7tCf5xmfAqJ9UJkMhtmhUKNg" "trade1" "${main_ip}"
local ACCOUNT_A="1CvLe1qNaC7tCf5xmfAqJ9UJkMhtmhUKNg"
......@@ -284,12 +199,10 @@ function init() {
chain33_applyCoins "$ACCOUNT_A" 12000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$main_ip"
else
# tx fee
chain33_applyCoins "$ACCOUNT_A" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$main_ip"
local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0xaeef1ad76d43a2056d0dcb57d5bf1ba96471550614ab9e7f611ef9c5ca403f42" "1CvLe1qNaC7tCf5xmfAqJ9UJkMhtmhUKNg" "trade1" "$para_ip"
chain33_applyCoins "$ACCOUNT_A" 12000000000 "${para_ip}"
......@@ -333,14 +246,13 @@ function run_test() {
}
function main() {
local ip=$1
chain33_RpcTestBegin trade
local ip=$1
MAIN_HTTP=$ip
echo "main_ip=$MAIN_HTTP"
init
run_test "$MAIN_HTTP"
chain33_RpcTestRst trade "$CASE_ERR"
}
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source ../dapp-test-common.sh
......@@ -10,28 +9,26 @@ txhash=""
function query_unfreezeID() {
chain33_BlockWait 1 "$MAIN_HTTP"
# echo "req=$req"
local times=10
while true; do
req='{"method":"Chain33.QueryTransaction","params":[{"hash":"'"$txhash"'"}]}'
ret=$(curl -ksd "$req" ${MAIN_HTTP})
tx=$(jq -r ".result.tx.hash" <<<"$ret")
echo "====query tx= ${txhash}, return=$ret "
# echo "====query tx= ${txhash}, return=$ret "
if [ "${tx}" != "${txhash}" ]; then
chain33_BlockWait 1 "${MAIN_HTTP}"
times=$((times - 1))
if [ $times -le 0 ]; then
echo "====query tx=$txhash failed"
echo -e "${RED}====query tx=$txhash failed${NOC}"
echo "req=$req"
curl -ksd "$req" ${MAIN_HTTP}
exit 1
fi
else
unfreeze_id=$(jq '(.result.receipt.logs['"$uid_index"'].log.current.unfreezeID)' <<<"$ret")
#echo "${unfreeze_id}"
unfreeze_id2=${unfreeze_id#\"mavl-unfreeze-}
uid=${unfreeze_id2%\"}
echo "====query tx=$txhash success"
echo -e "${GRE}====query tx=$txhash success${NOC}"
break
fi
done
......@@ -75,89 +72,51 @@ function init() {
function CreateRawUnfreezeCreate() {
req='{"jsonrpc": "2.0", "method" : "unfreeze.CreateRawUnfreezeCreate" , "params":[{"startTime":10000,"assetExec":"coins","assetSymbol":"'$symbol'","totalCount":400000000,"beneficiary":"'$beneficiary'","means":"FixAmount","fixAmount": {"period":10,"amount":1000000}}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "$owner_key" "${MAIN_HTTP}"
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "$owner_key" "${MAIN_HTTP}"
query_unfreezeID
}
function CreateRawUnfreezeWithdraw() {
sleep 10
req='{"method":"unfreeze.CreateRawUnfreezeWithdraw","params":[{"unfreezeID":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "${beneficiary_key}" "${MAIN_HTTP}"
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "${beneficiary_key}" "${MAIN_HTTP}"
}
function CreateRawUnfreezeTerminate() {
req='{"method":"unfreeze.CreateRawUnfreezeTerminate","params":[{"unfreezeID":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
chain33_SignRawTx "$rawtx" "$owner_key" "${MAIN_HTTP}"
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "$RETURN_RESP" "$owner_key" "${MAIN_HTTP}"
chain33_BlockWait 2 "${MAIN_HTTP}"
}
function GetUnfreeze() {
req='{"method":"unfreeze.GetUnfreeze","params":[{"data":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME"
}
function GetUnfreezeWithdraw() {
req='{"method":"unfreeze.GetUnfreezeWithdraw","params":[{"data":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME"
}
function run_testcases() {
CreateRawUnfreezeCreate
CreateRawUnfreezeWithdraw
GetUnfreeze
GetUnfreezeWithdraw
CreateRawUnfreezeTerminate
}
function debug_function() {
set -x
eval "$@"
set +x
}
function rpc_test() {
chain33_RpcTestBegin unfreeze
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
init
run_testcases
chain33_RpcTestRst unfreeze "$CASE_ERR"
}
debug_function rpc_test "$1"
chain33_debug_function rpc_test "$1"
......@@ -36,6 +36,7 @@ var (
quit bool
isPrunedMavl bool // 是否是被裁剪过的 mavl
delPrunedMavlState int32 = delPrunedMavlStart // Upgrade时候删除pruned mavl的状态
isCompactDelMavl bool // 是否对删除mavl后压缩
)
const (
......@@ -149,6 +150,11 @@ func New(cfg *types.Store, sub []byte, chain33cfg *types.Chain33Config) queue.Mo
if err == nil {
isDelMavlData = true
}
// 查询是否已经压缩过
_, err = bs.GetDB().Get(genCompactDelMavlKey(mvccPrefix))
if err == nil {
isCompactDelMavl = true
}
// 查询是否是删除裁剪版mavl
isPrunedMavl = isPrunedMavlDB(bs.GetDB())
// 读取fork高度
......@@ -205,11 +211,6 @@ func (kvmMavls *KVmMavlStore) Set(datas *types.StoreSet, sync bool) ([]byte, err
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
}
......@@ -273,6 +274,24 @@ func (kvmMavls *KVmMavlStore) MemSet(datas *types.StoreSet, sync bool) ([]byte,
wg.Add(1)
go DelMavl(kvmMavls.GetDB())
}
// 对删除的mavl进行压缩
if isDelMavlData && !isCompactDelMavl && !isDelMavling() {
go CompactDelMavl(kvmMavls.GetDB())
if datas.Height > delMavlDataHeight && datas.Height < delMavlDataHeight*2 {
// 出于对区块链安全的角度阻塞执行区块压缩之发生在固定高度区间内
count := 0
for {
if quit || isCompactDelMavl {
break
}
if count%100 == 0 {
kmlog.Info("block compact db", "count time s", count)
}
count++
time.Sleep(time.Second)
}
}
}
return hash, err
}
......@@ -509,6 +528,24 @@ func setDelMavl(state int32) {
atomic.StoreInt32(&delMavlDataState, state)
}
func CompactDelMavl(db dbm.DB) {
setDelMavl(delMavlStateStart)
defer setDelMavl(delMavlStateEnd)
// 开始进行压缩处理
kmlog.Info("start compact db")
err := db.CompactRange(nil, nil)
if err == nil {
db.Set(genCompactDelMavlKey(mvccPrefix), []byte(""))
isCompactDelMavl = true
}
kmlog.Info("end compact db", "error", err)
}
func genCompactDelMavlKey(prefix []byte) []byte {
key := "--compactDelMavl--"
return []byte(fmt.Sprintf("%s%s", string(prefix), key))
}
func isNeedDelPrunedMavl() bool {
return atomic.LoadInt32(&delPrunedMavlState) == 0
}
......
......@@ -601,6 +601,24 @@ func TestDelMavlData(t *testing.T) {
require.NoError(t, err)
}
func TestCompactDelMavl(t *testing.T) {
dir, err := ioutil.TempDir("", "example")
assert.Nil(t, err)
defer os.RemoveAll(dir) // clean up
os.RemoveAll(dir) //删除已存在目录
storeCfg := newStoreCfg(dir)
store := New(storeCfg, nil, nil).(*KVmMavlStore)
assert.NotNil(t, store)
db := store.GetDB()
for i := 0; i < 100; i++ {
db.Set([]byte(GetRandomString(MaxKeylenth)), []byte(fmt.Sprintf("v%d", i)))
}
CompactDelMavl(db)
_, err = db.Get(genCompactDelMavlKey(mvccPrefix))
assert.NoError(t, err)
}
func TestPruning(t *testing.T) {
dir, err := ioutil.TempDir("", "example")
assert.Nil(t, err)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment