Commit 6ea8e651 authored by pengjun's avatar pengjun

Merge remote-tracking branch 'upstream/master'

parents c0128c37 e97eda52
...@@ -27,7 +27,7 @@ build/para.sh ...@@ -27,7 +27,7 @@ build/para.sh
build/system-test-rpc.sh build/system-test-rpc.sh
build/ci build/ci
build/autotest/* build/autotest/*
!build/autotest/build.sh !build/autotest/run.sh
.DS_Store .DS_Store
logs/ logs/
build/wallet build/wallet
......
...@@ -9,7 +9,6 @@ CLI := build/chain33-cli ...@@ -9,7 +9,6 @@ CLI := build/chain33-cli
SRC_CLI := github.com/33cn/plugin/cli SRC_CLI := github.com/33cn/plugin/cli
APP := build/chain33 APP := build/chain33
export CHAIN33_PATH=$(shell go list -f {{.Dir}} github.com/33cn/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`" BUILD_FLAGS = -ldflags "-X github.com/33cn/chain33/common/version.GitCommit=`git rev-parse --short=8 HEAD`"
LDFLAGS := -ldflags "-w -s" LDFLAGS := -ldflags "-w -s"
PKG_LIST_VET := `go list ./... | grep -v "vendor" | grep -v plugin/dapp/evm/executor/vm/common/crypto/bn256` PKG_LIST_VET := `go list ./... | grep -v "vendor" | grep -v plugin/dapp/evm/executor/vm/common/crypto/bn256`
...@@ -44,23 +43,13 @@ vet: ...@@ -44,23 +43,13 @@ vet:
@go vet ${PKG_LIST_VET} @go vet ${PKG_LIST_VET}
autotest: ## build autotest binary 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 \ @if [ -n "$(dapp)" ]; then \
rm -rf build/autotest/local \ cd build/autotest && bash ./run.sh local $(dapp) && cd ../../; fi
&& 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
autotest_ci: autotest ## autotest ci autotest_ci: autotest ## autotest ci
@rm -rf build/autotest/jerkinsci \ @cd build/autotest && bash ./run.sh jerkinsci $(proj) && cd ../../
&& 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 ../../../
autotest_tick: autotest ## run with ticket mining autotest_tick: autotest ## run with ticket mining
@rm -rf build/autotest/gitlabci \ @cd build/autotest && bash ./run.sh gitlabci build && cd ../../
&& 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 ../../../
update: ## version 可以是git tag打的具体版本号,也可以是commit hash, 什么都不填的情况下默认从master分支拉取最新版本 update: ## version 可以是git tag打的具体版本号,也可以是commit hash, 什么都不填的情况下默认从master分支拉取最新版本
@if [ -n "$(version)" ]; then \ @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 @@ ...@@ -3,6 +3,7 @@
RAW_TX_HASH="" RAW_TX_HASH=""
LAST_BLOCK_HASH="" LAST_BLOCK_HASH=""
CASE_ERR="" CASE_ERR=""
RETURN_RESP=""
#color #color
RED='\033[1;31m' RED='\033[1;31m'
...@@ -16,11 +17,32 @@ echo_rst() { ...@@ -16,11 +17,32 @@ echo_rst() {
echo -e "${GRE}$1 not support${NOC}" echo -e "${GRE}$1 not support${NOC}"
else else
echo -e "${RED}$1 fail${NOC}" echo -e "${RED}$1 fail${NOC}"
echo -e "${RED}$3 ${NOC}"
CASE_ERR="err" CASE_ERR="err"
echo $CASE_ERR echo $CASE_ERR
fi 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() { chain33_BlockWait() {
local MAIN_HTTP=$2 local MAIN_HTTP=$2
local req='"method":"Chain33.GetLastHeader","params":[]' local req='"method":"Chain33.GetLastHeader","params":[]'
...@@ -112,7 +134,7 @@ chain33_ImportPrivkey() { ...@@ -112,7 +134,7 @@ chain33_ImportPrivkey() {
[ "$ok" == true ] [ "$ok" == true ]
} }
chain33_SignRawTx() { chain33_SignAndSendTx() {
local txHex="$1" local txHex="$1"
local priKey="$2" local priKey="$2"
local MAIN_HTTP=$3 local MAIN_HTTP=$3
......
...@@ -108,6 +108,8 @@ mainBlockHashForkHeight=209186 ...@@ -108,6 +108,8 @@ mainBlockHashForkHeight=209186
mainForkParacrossCommitTx=2270000 mainForkParacrossCommitTx=2270000
#主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度, ycc或其他按实际修改 #主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度, ycc或其他按实际修改
mainLoopCheckCommitTxDoneForkHeight=4320000 mainLoopCheckCommitTxDoneForkHeight=4320000
#主链交易验证merkelRoot主链分叉高度,需和主链保持一致,不可修改
mainVerifyMerkleRootForkHeight=-1
#主链每隔几个没有相关平行链交易的区块,平行链上打包空区块,缺省从平行链blockHeight=0开始,依次增长,空块间隔不能为0 #主链每隔几个没有相关平行链交易的区块,平行链上打包空区块,缺省从平行链blockHeight=0开始,依次增长,空块间隔不能为0
[[consensus.sub.para.emptyBlockInterval]] [[consensus.sub.para.emptyBlockInterval]]
blockHeight=0 blockHeight=0
...@@ -210,7 +212,8 @@ ForkBase58AddressCheck=0 ...@@ -210,7 +212,8 @@ ForkBase58AddressCheck=0
ForkEnableParaRegExec=0 ForkEnableParaRegExec=0
ForkCacheDriver=0 ForkCacheDriver=0
ForkTicketFundAddrV1=-1 #fork6.3 ForkTicketFundAddrV1=-1 #fork6.3
#主链和平行链都使用同一个fork高度
ForkRootHash= 4500000
[fork.sub.coins] [fork.sub.coins]
Enable=0 Enable=0
......
...@@ -3,7 +3,7 @@ module github.com/33cn/plugin ...@@ -3,7 +3,7 @@ module github.com/33cn/plugin
go 1.12 go 1.12
require ( 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/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7 github.com/NebulousLabs/Sia v1.3.7
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac
......
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 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-20191225114001-0e761fbcd8ce h1:8w3fHBpsupag2ue5iwyIv8cp6va2LtvZuJ/OhvNEEpk=
github.com/33cn/chain33 v0.0.0-20191113065720-35a79536c298/go.mod h1:4I8n+Zyf3t0UKM5jjpqJY627Tub62oXkLsdzIv4r6rQ= 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 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
......
...@@ -465,9 +465,13 @@ func (client *Client) CreateBlock() { ...@@ -465,9 +465,13 @@ func (client *Client) CreateBlock() {
newblock.ParentHash = lastBlock.Hash(cfg) newblock.ParentHash = lastBlock.Hash(cfg)
newblock.Height = lastBlock.Height + 1 newblock.Height = lastBlock.Height + 1
client.AddTxsToBlock(&newblock, txs) client.AddTxsToBlock(&newblock, txs)
//
newblock.Difficulty = cfg.GetP(0).PowLimitBits 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 newblock.BlockTime = client.blockTime
err := client.WriteBlock(lastBlock.StateHash, &newblock) err := client.WriteBlock(lastBlock.StateHash, &newblock)
......
...@@ -58,8 +58,8 @@ type client struct { ...@@ -58,8 +58,8 @@ type client struct {
commitMsgClient *commitMsgClient commitMsgClient *commitMsgClient
blockSyncClient *blockSyncClient blockSyncClient *blockSyncClient
multiDldCli *multiDldClient multiDldCli *multiDldClient
authAccount string jumpDldCli *jumpDldClient
privateKey crypto.PrivKey minerPrivateKey crypto.PrivKey
wg sync.WaitGroup wg sync.WaitGroup
subCfg *subConfig subCfg *subConfig
isClosed int32 isClosed int32
...@@ -81,10 +81,10 @@ type subConfig struct { ...@@ -81,10 +81,10 @@ type subConfig struct {
WaitBlocks4CommitMsg int32 `json:"waitBlocks4CommitMsg,omitempty"` WaitBlocks4CommitMsg int32 `json:"waitBlocks4CommitMsg,omitempty"`
GenesisAmount int64 `json:"genesisAmount,omitempty"` GenesisAmount int64 `json:"genesisAmount,omitempty"`
MainBlockHashForkHeight int64 `json:"mainBlockHashForkHeight,omitempty"` MainBlockHashForkHeight int64 `json:"mainBlockHashForkHeight,omitempty"`
MainVrfMerkleRootForkHeight int64 `json:"mainVrfMerkleRootForkHeight,omitempty"`
WaitConsensStopTimes uint32 `json:"waitConsensStopTimes,omitempty"` WaitConsensStopTimes uint32 `json:"waitConsensStopTimes,omitempty"`
MaxCacheCount int64 `json:"maxCacheCount,omitempty"` MaxCacheCount int64 `json:"maxCacheCount,omitempty"`
MaxSyncErrCount int32 `json:"maxSyncErrCount,omitempty"` MaxSyncErrCount int32 `json:"maxSyncErrCount,omitempty"`
FetchFilterParaTxsClose bool `json:"fetchFilterParaTxsClose,omitempty"`
BatchFetchBlockCount int64 `json:"batchFetchBlockCount,omitempty"` BatchFetchBlockCount int64 `json:"batchFetchBlockCount,omitempty"`
ParaConsensStartHeight int64 `json:"paraConsensStartHeight,omitempty"` ParaConsensStartHeight int64 `json:"paraConsensStartHeight,omitempty"`
MultiDownloadOpen bool `json:"multiDownloadOpen,omitempty"` MultiDownloadOpen bool `json:"multiDownloadOpen,omitempty"`
...@@ -92,6 +92,7 @@ type subConfig struct { ...@@ -92,6 +92,7 @@ type subConfig struct {
MultiDownJobBuffNum uint32 `json:"multiDownJobBuffNum,omitempty"` MultiDownJobBuffNum uint32 `json:"multiDownJobBuffNum,omitempty"`
MultiDownServerRspTime uint32 `json:"multiDownServerRspTime,omitempty"` MultiDownServerRspTime uint32 `json:"multiDownServerRspTime,omitempty"`
RmCommitParamMainHeight int64 `json:"rmCommitParamMainHeight,omitempty"` RmCommitParamMainHeight int64 `json:"rmCommitParamMainHeight,omitempty"`
JumpDownloadOpen bool `json:"jumpDownloadOpen,omitempty"`
} }
// New function to init paracross env // New function to init paracross env
...@@ -139,14 +140,14 @@ func New(cfg *types.Consensus, sub []byte) queue.Module { ...@@ -139,14 +140,14 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
para := &client{ para := &client{
BaseClient: c, BaseClient: c,
authAccount: subcfg.AuthAccount, minerPrivateKey: priKey,
privateKey: priKey,
subCfg: &subcfg, subCfg: &subcfg,
quitCreate: make(chan struct{}), quitCreate: make(chan struct{}),
} }
para.commitMsgClient = &commitMsgClient{ para.commitMsgClient = &commitMsgClient{
paraClient: para, paraClient: para,
authAccount: subcfg.AuthAccount,
waitMainBlocks: waitBlocks4CommitMsg, waitMainBlocks: waitBlocks4CommitMsg,
waitConsensStopTimes: waitConsensStopTimes, waitConsensStopTimes: waitConsensStopTimes,
consensHeight: -2, consensHeight: -2,
...@@ -199,6 +200,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module { ...@@ -199,6 +200,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
if subcfg.MultiDownServerRspTime > 0 { if subcfg.MultiDownServerRspTime > 0 {
para.multiDldCli.serverTimeout = subcfg.MultiDownServerRspTime para.multiDldCli.serverTimeout = subcfg.MultiDownServerRspTime
} }
para.jumpDldCli = &jumpDldClient{paraClient: para}
if subcfg.MainVrfMerkleRootForkHeight <= 0 {
subcfg.MainVrfMerkleRootForkHeight = types.MaxHeight
}
c.SetChild(para) c.SetChild(para)
return para return para
} }
...@@ -298,7 +306,7 @@ func (client *client) InitBlock() { ...@@ -298,7 +306,7 @@ func (client *client) InitBlock() {
} }
tx := client.CreateGenesisTx() tx := client.CreateGenesisTx()
newblock.Txs = tx newblock.Txs = tx
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs) newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.GetMainHeight(), newblock.Txs)
err := client.blockSyncClient.createGenesisBlock(newblock) err := client.blockSyncClient.createGenesisBlock(newblock)
if err != nil { if err != nil {
panic(fmt.Sprintf("para chain create genesis block,err=%s", err.Error())) panic(fmt.Sprintf("para chain create genesis block,err=%s", err.Error()))
......
...@@ -175,7 +175,7 @@ func TestAddMinerTx(t *testing.T) { ...@@ -175,7 +175,7 @@ func TestAddMinerTx(t *testing.T) {
para := &client{BaseClient: &drivers.BaseClient{}} para := &client{BaseClient: &drivers.BaseClient{}}
para.SetAPI(api) para.SetAPI(api)
para.subCfg = new(subConfig) para.subCfg = new(subConfig)
para.privateKey = priKey para.minerPrivateKey = priKey
para.commitMsgClient = new(commitMsgClient) para.commitMsgClient = new(commitMsgClient)
para.commitMsgClient.paraClient = para para.commitMsgClient.paraClient = para
......
...@@ -13,12 +13,12 @@ import ( ...@@ -13,12 +13,12 @@ import (
"sync/atomic" "sync/atomic"
"unsafe" "unsafe"
"bytes"
"sync" "sync"
"strconv" "strconv"
"bytes"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -31,7 +31,7 @@ const ( ...@@ -31,7 +31,7 @@ const (
consensusInterval = 10 //about 1 new block interval consensusInterval = 10 //about 1 new block interval
minerInterval = 10 //5s的主块间隔后分叉概率增加,10s可以消除一些分叉回退 minerInterval = 10 //5s的主块间隔后分叉概率增加,10s可以消除一些分叉回退
waitBlocks4CommitMsg int32 = 3 waitBlocks4CommitMsg int32 = 5 //commit msg共识发送后等待几个块没确认则重发
waitConsensStopTimes uint32 = 30 //30*10s = 5min waitConsensStopTimes uint32 = 30 //30*10s = 5min
) )
...@@ -42,7 +42,7 @@ type paraSelfConsEnable struct { ...@@ -42,7 +42,7 @@ type paraSelfConsEnable struct {
type commitMsgClient struct { type commitMsgClient struct {
paraClient *client paraClient *client
waitMainBlocks int32 //等待平行链共识消息在主链上链并成功的块数,超出会重发共识消息,最小是2 waitMainBlocks int32 //等待平行链共识消息在主链上链并成功的块数,超出会重发共识消息
waitConsensStopTimes uint32 //共识高度低于完成高度, reset高度重发等待的次数 waitConsensStopTimes uint32 //共识高度低于完成高度, reset高度重发等待的次数
resetCh chan interface{} resetCh chan interface{}
sendMsgCh chan *types.Transaction sendMsgCh chan *types.Transaction
...@@ -53,6 +53,7 @@ type commitMsgClient struct { ...@@ -53,6 +53,7 @@ type commitMsgClient struct {
consensHeight int64 consensHeight int64
consensDoneHeight int64 consensDoneHeight int64
selfConsensError int32 //自共识比主链共识更高的异常场景,需要等待自共识<=主链共识再发送 selfConsensError int32 //自共识比主链共识更高的异常场景,需要等待自共识<=主链共识再发送
authAccount string
authAccountIn bool authAccountIn bool
isRollBack int32 isRollBack int32
checkTxCommitTimes int32 checkTxCommitTimes int32
...@@ -76,7 +77,7 @@ func (client *commitMsgClient) handler() { ...@@ -76,7 +77,7 @@ func (client *commitMsgClient) handler() {
client.paraClient.wg.Add(1) client.paraClient.wg.Add(1)
go client.getMainConsensusInfo() go client.getMainConsensusInfo()
if client.paraClient.authAccount != "" { if client.authAccount != "" {
client.paraClient.wg.Add(1) client.paraClient.wg.Add(1)
client.sendMsgCh = make(chan *types.Transaction, 1) client.sendMsgCh = make(chan *types.Transaction, 1)
go client.sendCommitMsg() go client.sendCommitMsg()
...@@ -129,8 +130,8 @@ func (client *commitMsgClient) resetNotify() { ...@@ -129,8 +130,8 @@ func (client *commitMsgClient) resetNotify() {
} }
//新的区块产生,检查是否有commitTx正在发送入口 //新的区块产生,检查是否有commitTx正在发送入口
func (client *commitMsgClient) commitTxCheckNotify(txs []*types.TxDetail) { func (client *commitMsgClient) commitTxCheckNotify(block *types.ParaTxDetail) {
if client.checkCommitTxSuccess(txs) { if client.checkCommitTxSuccess(block) {
client.sendCommitTx() client.sendCommitTx()
} }
} }
...@@ -199,23 +200,7 @@ func (client *commitMsgClient) sendCommitTx() { ...@@ -199,23 +200,7 @@ func (client *commitMsgClient) sendCommitTx() {
} }
func (client *commitMsgClient) verifyTx(curTx *types.Transaction, verifyTxs map[string]bool) bool { func (client *commitMsgClient) checkCommitTxSuccess(block *types.ParaTxDetail) 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 {
client.mutex.Lock() client.mutex.Lock()
defer client.mutex.Unlock() defer client.mutex.Unlock()
...@@ -224,10 +209,13 @@ func (client *commitMsgClient) checkCommitTxSuccess(txs []*types.TxDetail) bool ...@@ -224,10 +209,13 @@ func (client *commitMsgClient) checkCommitTxSuccess(txs []*types.TxDetail) bool
return false return false
} }
//只处理AddType block,回滚的不处理
if block.Type == types.AddBlock {
//使用map 比每个交易hash byte比较效率应该会高些
txMap := make(map[string]bool) txMap := make(map[string]bool)
//committx是平行链交易 //committx是平行链交易
if types.IsParaExecName(string(curTx.Execer)) { 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 { if bytes.HasSuffix(tx.Tx.Execer, []byte(pt.ParaX)) && tx.Receipt.Ty == types.ExecOk {
txMap[string(tx.Tx.Hash())] = true txMap[string(tx.Tx.Hash())] = true
} }
...@@ -244,12 +232,33 @@ func (client *commitMsgClient) checkCommitTxSuccess(txs []*types.TxDetail) bool ...@@ -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 false
} }
return client.verifyTx(curTx, txMap) client.checkTxCommitTimes = 0
client.resetSendEnv()
return true
} }
//如果共识高度一直没有追上发送高度,且当前发送高度已经上链,说明共识一直没达成,安全起见,超过停止次数后,重发 //如果共识高度一直没有追上发送高度,且当前发送高度已经上链,说明共识一直没达成,安全起见,超过停止次数后,重发
...@@ -275,7 +284,7 @@ func (client *commitMsgClient) checkAuthAccountIn() { ...@@ -275,7 +284,7 @@ func (client *commitMsgClient) checkAuthAccountIn() {
if err != nil { if err != nil {
return return
} }
authExist := strings.Contains(nodes, client.paraClient.authAccount) authExist := strings.Contains(nodes, client.authAccount)
//如果授权节点重新加入,需要从当前共识高度重新发送 //如果授权节点重新加入,需要从当前共识高度重新发送
if !client.authAccountIn && authExist { if !client.authAccountIn && authExist {
...@@ -361,7 +370,7 @@ func (client *commitMsgClient) getSendingTx(startHeight, endHeight int64) (*type ...@@ -361,7 +370,7 @@ func (client *commitMsgClient) getSendingTx(startHeight, endHeight int64) (*type
for i, msg := range sendingMsgs { for i, msg := range sendingMsgs {
plog.Debug("paracommitmsg sending", "idx", i, "height", msg.Height, "mainheight", msg.MainBlockHeight, plog.Debug("paracommitmsg sending", "idx", i, "height", msg.Height, "mainheight", msg.MainBlockHeight,
"blockhash", common.HashHex(msg.BlockHash), "mainHash", common.HashHex(msg.MainBlockHash), "blockhash", common.HashHex(msg.BlockHash), "mainHash", common.HashHex(msg.MainBlockHash),
"from", client.paraClient.authAccount) "from", client.authAccount)
} }
return signTx, count return signTx, count
...@@ -678,7 +687,7 @@ out: ...@@ -678,7 +687,7 @@ out:
isSync = true isSync = true
} }
if client.paraClient.authAccount != "" { if client.authAccount != "" {
client.GetProperFeeRate() client.GetProperFeeRate()
} }
...@@ -836,7 +845,7 @@ func (client *commitMsgClient) getNodeGroupAddrs() (string, error) { ...@@ -836,7 +845,7 @@ func (client *commitMsgClient) getNodeGroupAddrs() (string, error) {
} }
func (client *commitMsgClient) onWalletStatus(status *types.WalletStatus) { func (client *commitMsgClient) onWalletStatus(status *types.WalletStatus) {
if status == nil || client.paraClient.authAccount == "" { if status == nil || client.authAccount == "" {
return return
} }
if !status.IsWalletLock && client.privateKey == nil { if !status.IsWalletLock && client.privateKey == nil {
...@@ -858,7 +867,7 @@ func (client *commitMsgClient) onWalletStatus(status *types.WalletStatus) { ...@@ -858,7 +867,7 @@ func (client *commitMsgClient) onWalletStatus(status *types.WalletStatus) {
} }
func (client *commitMsgClient) onWalletAccount(acc *types.Account) { 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 return
} }
err := client.fetchPriKey() err := client.fetchPriKey()
...@@ -872,7 +881,7 @@ func (client *commitMsgClient) onWalletAccount(acc *types.Account) { ...@@ -872,7 +881,7 @@ func (client *commitMsgClient) onWalletAccount(acc *types.Account) {
} }
func (client *commitMsgClient) fetchPriKey() error { 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) msg := client.paraClient.GetQueueClient().NewMessage("wallet", types.EventDumpPrivkey, req)
err := client.paraClient.GetQueueClient().Send(msg, true) err := client.paraClient.GetQueueClient().Send(msg, true)
......
This diff is collapsed.
// 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
}
This diff is collapsed.
# 平行链有选择的下载包含平行链交易的主链区块方案
## 说明
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 { ...@@ -159,10 +159,6 @@ func (m *multiDldClient) getConns(inv *inventory) error {
//缺省不打开,因为有些节点下载时间不稳定,容易超时出错,后面看怎么优化 //缺省不打开,因为有些节点下载时间不稳定,容易超时出错,后面看怎么优化
func (m *multiDldClient) tryMultiServerDownload() { func (m *multiDldClient) tryMultiServerDownload() {
if !m.paraClient.subCfg.MultiDownloadOpen {
return
}
curMainHeight, err := m.paraClient.GetLastHeightOnMainChain() curMainHeight, err := m.paraClient.GetLastHeightOnMainChain()
if err != nil { if err != nil {
plog.Error("tryMultiServerDownload getMain height", "err", err.Error()) plog.Error("tryMultiServerDownload getMain height", "err", err.Error())
...@@ -224,7 +220,7 @@ func (m *multiDldClient) tryMultiServerDownload() { ...@@ -224,7 +220,7 @@ func (m *multiDldClient) tryMultiServerDownload() {
func (i *inventory) getFirstBlock(d *downloadJob) *types.ParaTxDetail { func (i *inventory) getFirstBlock(d *downloadJob) *types.ParaTxDetail {
if i.isSaveDb { if i.isSaveDb {
block, err := d.getBlockFromDb(i.start) block, err := d.mDldCli.paraClient.getMainBlockFromDb(i.start)
if err != nil { if err != nil {
panic(err) panic(err)
} }
...@@ -238,7 +234,7 @@ func (i *inventory) getLastBlock(d *downloadJob) *types.ParaTxDetail { ...@@ -238,7 +234,7 @@ func (i *inventory) getLastBlock(d *downloadJob) *types.ParaTxDetail {
return nil return nil
} }
if i.isSaveDb { if i.isSaveDb {
block, err := d.getBlockFromDb(i.end) block, err := d.mDldCli.paraClient.getMainBlockFromDb(i.end)
if err != nil { if err != nil {
panic(err) panic(err)
} }
...@@ -257,7 +253,7 @@ func (m *multiDldClient) processDoneJobs(ch chan *downloadJob) { ...@@ -257,7 +253,7 @@ func (m *multiDldClient) processDoneJobs(ch chan *downloadJob) {
func (d *downloadJob) resetInv(i *inventory) { func (d *downloadJob) resetInv(i *inventory) {
if i.isSaveDb { if i.isSaveDb {
d.rmvBatchMainBlocks(i) d.mDldCli.paraClient.rmvBatchMainBlocks(i.start, i.curHeight)
} }
i.curHeight = i.start i.curHeight = i.start
i.txs.Items = nil i.txs.Items = nil
...@@ -268,7 +264,7 @@ func (d *downloadJob) process() { ...@@ -268,7 +264,7 @@ func (d *downloadJob) process() {
for _, inv := range d.invs { for _, inv := range d.invs {
if inv.isSaveDb { if inv.isSaveDb {
for i := inv.start; i <= inv.end; i++ { for i := inv.start; i <= inv.end; i++ {
block, err := d.getBlockFromDb(i) block, err := d.mDldCli.paraClient.getMainBlockFromDb(i)
if err != nil { if err != nil {
panic(err) panic(err)
} }
...@@ -280,7 +276,7 @@ func (d *downloadJob) process() { ...@@ -280,7 +276,7 @@ func (d *downloadJob) process() {
d.mDldCli.paraClient.blockSyncClient.handleLocalChangedMsg() d.mDldCli.paraClient.blockSyncClient.handleLocalChangedMsg()
} else { } else {
//block需要严格顺序执行,数据库错误,panic 重新来过 //block需要严格顺序执行,数据库错误,panic 重新来过
err := d.mDldCli.paraClient.procLocalBlocks(inv.txs) err := d.mDldCli.paraClient.procLocalAddBlocks(inv.txs)
if err != nil { if err != nil {
panic(err) panic(err)
} }
...@@ -292,7 +288,7 @@ func (d *downloadJob) process() { ...@@ -292,7 +288,7 @@ func (d *downloadJob) process() {
func (d *downloadJob) getPreVerifyBlock(inv *inventory) (*types.ParaTxDetail, error) { func (d *downloadJob) getPreVerifyBlock(inv *inventory) (*types.ParaTxDetail, error) {
if inv.isSaveDb { if inv.isSaveDb {
lastBlock, err := d.getBlockFromDb(inv.curHeight - 1) lastBlock, err := d.mDldCli.paraClient.getMainBlockFromDb(inv.curHeight - 1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -328,64 +324,6 @@ func (d *downloadJob) verifyDownloadBlock(inv *inventory, blocks *types.ParaTxDe ...@@ -328,64 +324,6 @@ func (d *downloadJob) verifyDownloadBlock(inv *inventory, blocks *types.ParaTxDe
return nil 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 { func (d *downloadJob) checkInv(lastRetry, pre *types.ParaTxDetail, inv *inventory) error {
if !inv.isDone { if !inv.isDone {
return types.ErrNotFound return types.ErrNotFound
...@@ -515,7 +453,7 @@ func (d *downloadJob) getInvBlocks(inv *inventory, connPool chan *connectCli) { ...@@ -515,7 +453,7 @@ func (d *downloadJob) getInvBlocks(inv *inventory, connPool chan *connectCli) {
//save 之前save到db,后面区块全部save到db //save 之前save到db,后面区块全部save到db
if inv.isSaveDb { if inv.isSaveDb {
d.saveBatchMainBlocks(txs) d.mDldCli.paraClient.saveBatchMainBlocks(txs)
} else { } else {
inv.txs.Items = append(inv.txs.Items, txs.Items...) inv.txs.Items = append(inv.txs.Items, txs.Items...)
} }
...@@ -528,7 +466,7 @@ func (d *downloadJob) getInvBlocks(inv *inventory, connPool chan *connectCli) { ...@@ -528,7 +466,7 @@ func (d *downloadJob) getInvBlocks(inv *inventory, connPool chan *connectCli) {
return return
} }
if !inv.isSaveDb && types.Size(inv.txs) > maxBlockSize { if !inv.isSaveDb && types.Size(inv.txs) > maxBlockSize {
d.saveBatchMainBlocks(inv.txs) d.mDldCli.paraClient.saveBatchMainBlocks(inv.txs)
inv.txs.Items = nil inv.txs.Items = nil
inv.isSaveDb = true inv.isSaveDb = true
} }
......
...@@ -8,66 +8,40 @@ import ( ...@@ -8,66 +8,40 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/hex" "encoding/hex"
"errors"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
) )
func (client *client) setLocalDb(set *types.LocalDBSet) error { func (client *client) GetBlockByHeight(height int64) (*types.Block, error) {
//如果追赶上主链了,则落盘 //from blockchain db
if client.isCaughtUp() { blockDetails, err := client.GetAPI().GetBlocks(&types.ReqBlocks{Start: height, End: height})
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 { if err != nil {
plog.Error("GetBlockByHeight fail", "err", err)
return nil, err return nil, err
} }
if 1 != int64(len(blockDetails.Items)) {
reply := resp.GetData().(*types.LocalReplyValue) plog.Error("GetBlockByHeight count fail", "len", len(blockDetails.Items))
if len(reply.Values) != count {
plog.Error("Parachain getLocalDb count not match", "expert", count, "real", len(reply.Values))
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
return blockDetails.Items[0].Block, nil
return reply.Values, nil
} }
func (client *client) GetBlockByHeight(height int64) (*types.Block, error) { func (client *client) GetBlockHeaders(req *types.ReqBlocks) (*types.Headers, error) {
//from blockchain db //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 { if err != nil {
plog.Error("paracommitmsg get node status block count fail") plog.Error("GetBlockHeaders fail", "err", err)
return nil, err return nil, err
} }
if 1 != int64(len(blockDetails.Items)) {
plog.Error("paracommitmsg get node status block count fail") count := req.End - req.Start + 1
return nil, types.ErrInvalidParam 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信息 // 获取当前平行链block对应主链seq,hash信息
...@@ -88,7 +62,7 @@ func (client *client) getLastBlockMainInfo() (int64, *types.Block, error) { ...@@ -88,7 +62,7 @@ func (client *client) getLastBlockMainInfo() (int64, *types.Block, error) {
func (client *client) getLastBlockInfo() (*types.Block, error) { func (client *client) getLastBlockInfo() (*types.Block, error) {
lastBlock, err := client.RequestLastBlock() lastBlock, err := client.RequestLastBlock()
if err != nil { if err != nil {
plog.Error("Parachain RequestLastBlock fail", "err", err) plog.Error("Parachain getLastBlockInfo fail", "err", err)
return nil, err return nil, err
} }
...@@ -169,3 +143,30 @@ func (client *client) QueryTxOnMainByHash(hash []byte) (*types.TransactionDetail ...@@ -169,3 +143,30 @@ func (client *client) QueryTxOnMainByHash(hash []byte) (*types.TransactionDetail
return detail, nil 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 { ...@@ -39,6 +39,8 @@ type blockSyncClient struct {
isSyncCaughtUpAtom int32 isSyncCaughtUpAtom int32
//isDownloadCaughtUpAtom 下载是否已经追赶上 //isDownloadCaughtUpAtom 下载是否已经追赶上
isDownloadCaughtUpAtom int32 isDownloadCaughtUpAtom int32
//isSyncFirstCaughtUp 系统启动后download 层和sync层第一次都追赶上的设置,后面如果因为回滚或节点切换不同步,则不考虑
isSyncFirstCaughtUp bool
} }
//nextActionType 定义每一轮可执行操作 //nextActionType 定义每一轮可执行操作
...@@ -231,7 +233,7 @@ func (client *blockSyncClient) syncBlocksIfNeed() (bool, error) { ...@@ -231,7 +233,7 @@ func (client *blockSyncClient) syncBlocksIfNeed() (bool, error) {
if err == nil { if err == nil {
isSyncCaughtUp := lastBlock.Height+1 == lastLocalHeight isSyncCaughtUp := lastBlock.Height+1 == lastLocalHeight
client.setSyncCaughtUp(isSyncCaughtUp) client.setSyncCaughtUp(isSyncCaughtUp)
if client.paraClient.authAccount != "" { if client.paraClient.commitMsgClient.authAccount != "" {
client.printDebugInfo("Para sync - add block commit", "isSyncCaughtUp", isSyncCaughtUp) client.printDebugInfo("Para sync - add block commit", "isSyncCaughtUp", isSyncCaughtUp)
client.paraClient.commitMsgClient.updateChainHeightNotify(lastBlock.Height+1, false) client.paraClient.commitMsgClient.updateChainHeightNotify(lastBlock.Height+1, false)
} }
...@@ -250,7 +252,7 @@ func (client *blockSyncClient) syncBlocksIfNeed() (bool, error) { ...@@ -250,7 +252,7 @@ func (client *blockSyncClient) syncBlocksIfNeed() (bool, error) {
//通知发送层 //通知发送层
if err == nil { if err == nil {
client.setSyncCaughtUp(false) client.setSyncCaughtUp(false)
if client.paraClient.authAccount != "" { if client.paraClient.commitMsgClient.authAccount != "" {
client.printDebugInfo("Para sync - rollback block commit", "isSyncCaughtUp", false) client.printDebugInfo("Para sync - rollback block commit", "isSyncCaughtUp", false)
client.paraClient.commitMsgClient.updateChainHeightNotify(lastBlock.Height-1, true) client.paraClient.commitMsgClient.updateChainHeightNotify(lastBlock.Height-1, true)
} }
...@@ -384,7 +386,7 @@ func (client *blockSyncClient) addMinerTx(preStateHash []byte, block *types.Bloc ...@@ -384,7 +386,7 @@ func (client *blockSyncClient) addMinerTx(preStateHash []byte, block *types.Bloc
return err return err
} }
tx.Sign(types.SECP256K1, client.paraClient.privateKey) tx.Sign(types.SECP256K1, client.paraClient.minerPrivateKey)
block.Txs = append([]*types.Transaction{tx}, block.Txs...) block.Txs = append([]*types.Transaction{tx}, block.Txs...)
return nil return nil
...@@ -403,7 +405,12 @@ func (client *blockSyncClient) addBlock(lastBlock *types.Block, localBlock *pt.P ...@@ -403,7 +405,12 @@ func (client *blockSyncClient) addBlock(lastBlock *types.Block, localBlock *pt.P
} }
//挖矿固定难度 //挖矿固定难度
newBlock.Difficulty = cfg.GetP(0).PowLimitBits 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.BlockTime = localBlock.BlockTime
newBlock.MainHash = localBlock.MainHash newBlock.MainHash = localBlock.MainHash
newBlock.MainHeight = localBlock.MainHeight newBlock.MainHeight = localBlock.MainHeight
...@@ -466,7 +473,13 @@ func (client *blockSyncClient) rollbackBlock(block *types.Block) error { ...@@ -466,7 +473,13 @@ func (client *blockSyncClient) rollbackBlock(block *types.Block) error {
func (client *blockSyncClient) writeBlock(prev []byte, paraBlock *types.Block) error { func (client *blockSyncClient) writeBlock(prev []byte, paraBlock *types.Block) error {
//共识模块不执行block,统一由blockchain模块执行block并做去重的处理,返回执行后的blockdetail //共识模块不执行block,统一由blockchain模块执行block并做去重的处理,返回执行后的blockdetail
blockDetail := &types.BlockDetail{Block: paraBlock} 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) msg := client.paraClient.GetQueueClient().NewMessage("blockchain", types.EventAddParaChainBlockDetail, paraBlockDetail)
err := client.paraClient.GetQueueClient().Send(msg, true) err := client.paraClient.GetQueueClient().Send(msg, true)
if err != nil { if err != nil {
......
...@@ -66,7 +66,7 @@ func createParaTestInstance(t *testing.T, q queue.Queue) *client { ...@@ -66,7 +66,7 @@ func createParaTestInstance(t *testing.T, q queue.Queue) *client {
assert.Nil(t, err) assert.Nil(t, err)
priKey, err := secp.PrivKeyFromBytes(pk) priKey, err := secp.PrivKeyFromBytes(pk)
assert.Nil(t, err) assert.Nil(t, err)
para.privateKey = priKey para.minerPrivateKey = priKey
//实例化BlockSyncClient //实例化BlockSyncClient
para.blockSyncClient = &blockSyncClient{ para.blockSyncClient = &blockSyncClient{
......
...@@ -92,7 +92,11 @@ func (client *Client) CreateBlock() { ...@@ -92,7 +92,11 @@ func (client *Client) CreateBlock() {
newblock.ParentHash = lastBlock.Hash(cfg) newblock.ParentHash = lastBlock.Hash(cfg)
newblock.Height = lastBlock.Height + 1 newblock.Height = lastBlock.Height + 1
newblock.Txs = txs 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() newblock.BlockTime = types.Now().Unix()
if lastBlock.BlockTime >= newblock.BlockTime { if lastBlock.BlockTime >= newblock.BlockTime {
newblock.BlockTime = lastBlock.BlockTime + 1 newblock.BlockTime = lastBlock.BlockTime + 1
......
...@@ -184,7 +184,11 @@ func (client *Client) CreateBlock() { ...@@ -184,7 +184,11 @@ func (client *Client) CreateBlock() {
newblock.ParentHash = lastBlock.Hash(cfg) newblock.ParentHash = lastBlock.Hash(cfg)
newblock.Height = lastBlock.Height + 1 newblock.Height = lastBlock.Height + 1
client.AddTxsToBlock(&newblock, txs) 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() newblock.BlockTime = types.Now().Unix()
if lastBlock.BlockTime >= newblock.BlockTime { if lastBlock.BlockTime >= newblock.BlockTime {
newblock.BlockTime = lastBlock.BlockTime + 1 newblock.BlockTime = lastBlock.BlockTime + 1
......
...@@ -747,8 +747,15 @@ func (cs *ConsensusState) createProposalBlock() (block *ttypes.TendermintBlock) ...@@ -747,8 +747,15 @@ func (cs *ConsensusState) createProposalBlock() (block *ttypes.TendermintBlock)
tendermintlog.Error("createProposalBlock createBaseTx fail") tendermintlog.Error("createProposalBlock createBaseTx fail")
return nil return nil
} }
cfg := cs.client.GetQueueClient().GetConfig()
block.Data.Txs[0] = baseTx 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) pblockNew := cs.client.PreExecBlock(block.Data, false)
if pblockNew == nil { if pblockNew == nil {
tendermintlog.Error("createProposalBlock PreExecBlock fail") tendermintlog.Error("createProposalBlock PreExecBlock fail")
......
...@@ -22,7 +22,6 @@ import ( ...@@ -22,7 +22,6 @@ import (
"github.com/33cn/chain33/common/log" "github.com/33cn/chain33/common/log"
"github.com/33cn/chain33/executor" "github.com/33cn/chain33/executor"
"github.com/33cn/chain33/mempool" "github.com/33cn/chain33/mempool"
"github.com/33cn/chain33/p2p"
"github.com/33cn/chain33/queue" "github.com/33cn/chain33/queue"
"github.com/33cn/chain33/rpc" "github.com/33cn/chain33/rpc"
"github.com/33cn/chain33/store" "github.com/33cn/chain33/store"
...@@ -60,14 +59,13 @@ func TestTendermintPerf(t *testing.T) { ...@@ -60,14 +59,13 @@ func TestTendermintPerf(t *testing.T) {
} }
func TendermintPerf(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 chain.Close()
defer mem.Close() defer mem.Close()
defer exec.Close() defer exec.Close()
defer s.Close() defer s.Close()
defer q.Close() defer q.Close()
defer cs.Close() defer cs.Close()
defer p2p.Close()
err := createConn() err := createConn()
for err != nil { for err != nil {
err = createConn() err = createConn()
...@@ -86,7 +84,7 @@ func TendermintPerf(t *testing.T) { ...@@ -86,7 +84,7 @@ func TendermintPerf(t *testing.T) {
time.Sleep(2 * time.Second) 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() flag.Parse()
chain33Cfg := types.NewChain33Config(types.ReadFile("chain33.test.toml")) chain33Cfg := types.NewChain33Config(types.ReadFile("chain33.test.toml"))
var q = queue.New("channel") var q = queue.New("channel")
...@@ -108,14 +106,11 @@ func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, que ...@@ -108,14 +106,11 @@ func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, que
mem := mempool.New(chain33Cfg) mem := mempool.New(chain33Cfg)
mem.SetQueueClient(q.Client()) mem.SetQueueClient(q.Client())
network := p2p.New(chain33Cfg)
network.SetQueueClient(q.Client())
rpc.InitCfg(cfg.RPC) rpc.InitCfg(cfg.RPC)
gapi := rpc.NewGRpcServer(q.Client(), nil) gapi := rpc.NewGRpcServer(q.Client(), nil)
go gapi.Listen() go gapi.Listen()
return q, chain, s, mem, exec, cs, network return q, chain, s, mem, exec, cs
} }
func createConn() error { func createConn() error {
......
...@@ -604,6 +604,12 @@ func (client *Client) Miner(parent, block *types.Block) error { ...@@ -604,6 +604,12 @@ func (client *Client) Miner(parent, block *types.Block) error {
if err != nil { if err != nil {
return err return err
} }
//需要首先对交易进行排序
cfg := client.GetAPI().GetConfig()
if cfg.IsFork(block.Height, "ForkRootHash") {
block.Txs = types.TransactionSort(block.Txs)
}
err = client.WriteBlock(parent.StateHash, block) err = client.WriteBlock(parent.StateHash, block)
if err != nil { if err != nil {
return err return err
......
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null # shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
MAIN_HTTP="" MAIN_HTTP=""
#txhash=""
function run_testcases() { function run_testcases() {
echo "run_testcases" echo "run_testcases"
} }
function debug_function() {
set -x
eval "$@"
set +x
}
function rpc_test() { function rpc_test() {
chain33_RpcTestBegin autonomy chain33_RpcTestBegin autonomy
...@@ -30,4 +22,4 @@ function rpc_test() { ...@@ -30,4 +22,4 @@ function rpc_test() {
} }
debug_function rpc_test "$1" chain33_debug_function rpc_test "$1"
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
set +e set +e
set -o pipefail set -o pipefail
MAIN_HTTP="" MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
gID="" gID=""
...@@ -31,49 +30,35 @@ init() { ...@@ -31,49 +30,35 @@ init() {
chain33_NewAccount() { chain33_NewAccount() {
label=$1 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") req='{"method":"Chain33.NewAccount","params":[{"label":"'"$label"'"}]}'
[ "$result" != "" ] chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.acc.addr|length > 0)' "$FUNCNAME" ".result.acc.addr"
rst=$? glAddr=$RETURN_RESP
echo_rst "$FUNCNAME" "$rst"
glAddr=$result
echo "$glAddr"
} }
chain33_SendTransaction() { chain33_SendTransaction() {
rawTx=$1 rawTx=$1
addr=$2 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}) req='{"method":"Chain33.SignRawTx","params":[{"addr":"'"$addr"'","txHex":"'"$rawTx"'","expire":"120s","fee":10000000,"index":0}]}'
ok=$(echo "${resp}" | jq -r ".error") chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "Chain33.SignRawTx" ".result"
[ "$ok" == null ] signTx=$RETURN_RESP
rst=$?
echo_rst "$FUNCNAME" "$rst" req='{"method":"Chain33.SendTransaction","params":[{"data":"'"$signTx"'"}]}'
chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
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}) gResp=$RETURN_RESP
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
#返回交易 #返回交易
gResp=$(jq -r ".result" <<<"$resp") chain33_QueryTx "$RETURN_RESP" "${MAIN_HTTP}"
echo "tx hash is $gResp"
chain33_QueryTx "$gResp" "${MAIN_HTTP}"
} }
blackwhite_BlackwhiteCreateTx() { blackwhite_BlackwhiteCreateTx() {
#创建交易 #创建交易
addr=$1 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}) req='{"method":"blackwhite.BlackwhiteCreateTx","params":[{"PlayAmount":100000000,"PlayerCount":3,"GameName":"hello","Timeout":600,"Fee":1000000}]}'
ok=$(echo "${resp}" | jq -r ".error") chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
#发送交易 #发送交易
rawTx=$(echo "${resp}" | jq -r ".result") chain33_SendTransaction "$RETURN_RESP" "${addr}"
chain33_SendTransaction "${rawTx}" "${addr}"
gID="${gResp}" gID="${gResp}"
echo "gameID $gID"
} }
blackwhite_BlackwhitePlayTx() { blackwhite_BlackwhitePlayTx() {
...@@ -81,83 +66,54 @@ blackwhite_BlackwhitePlayTx() { ...@@ -81,83 +66,54 @@ blackwhite_BlackwhitePlayTx() {
round1=$2 round1=$2
round2=$3 round2=$3
round3=$4 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}) req='{"method":"blackwhite.BlackwhitePlayTx","params":[{"gameID":"'"$gID"'","amount":100000000,"Fee":1000000,"hashValues":["'"$round1"'","'"$round2"'","'"$round3"'"]}]}'
ok=$(echo "${resp}" | jq -r ".error") chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
#发送交易 #发送交易
rawTx=$(echo "${resp}" | jq -r ".result") chain33_SendTransaction "$RETURN_RESP" "${addr}"
chain33_SendTransaction "${rawTx}" "${addr}"
} }
blackwhite_BlackwhiteShowTx() { blackwhite_BlackwhiteShowTx() {
addr=$1 addr=$1
sec=$2 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}) req='{"method":"blackwhite.BlackwhiteShowTx","params":[{"gameID":"'"$gID"'","secret":"'"$sec"'","Fee":1000000}]}'
ok=$(echo "${resp}" | jq -r ".error") chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result"
[ "$ok" == null ] chain33_SendTransaction "$RETURN_RESP" "${addr}"
rst=$?
echo_rst "$FUNCNAME" "$rst"
#发送交易
rawTx=$(echo "${resp}" | jq -r ".result")
chain33_SendTransaction "${rawTx}" "${addr}"
} }
blackwhite_BlackwhiteTimeoutDoneTx() { blackwhite_BlackwhiteTimeoutDoneTx() {
gameID=$1 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}) req='{"method":"blackwhite.BlackwhiteTimeoutDoneTx","params":[{"gameID":"'"$gameID"'","Fee":1000000}]}'
ok=$(echo "${resp}" | jq -r ".error") chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME"
[ "$ok" == null ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
} }
blackwhite_GetBlackwhiteRoundInfo() { blackwhite_GetBlackwhiteRoundInfo() {
gameID=$1 gameID=$1
execer="blackwhite" req='{"method":"Chain33.Query","params":[{"execer":"blackwhite","funcName":"GetBlackwhiteRoundInfo","payload":{"gameID":"'"$gameID"'"}}]}'
funcName="GetBlackwhiteRoundInfo" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.round | [has("gameID", "status", "playAmount", "playerCount", "curPlayerCount", "loop", "curShowCount", "timeout"),true] | unique | length == 1)' "$FUNCNAME"
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"
} }
blackwhite_GetBlackwhiteByStatusAndAddr() { blackwhite_GetBlackwhiteByStatusAndAddr() {
gameID=$1 addr=$1
addr=$2 req='{"method":"Chain33.Query","params":[{"execer":"blackwhite","funcName":"GetBlackwhiteByStatusAndAddr","payload":{"status":5,"address":"'"$addr"'","count":1,"direction":0,"index":-1}}]}'
execer="blackwhite" 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)'
funcName="GetBlackwhiteByStatusAndAddr" chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
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"
} }
blackwhite_GetBlackwhiteloopResult() { blackwhite_GetBlackwhiteloopResult() {
gameID=$1 gameID=$1
execer="blackwhite" req='{"method":"Chain33.Query","params":[{"execer":"blackwhite","funcName":"GetBlackwhiteloopResult","payload":{"gameID":"'"$gameID"'","loopSeq":0}}]}'
funcName="GetBlackwhiteloopResult" resok='(.error|not) and (.result.gameID == "'"$gameID"'") and (.result.results|length >= 1)'
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}) chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
ok=$(jq '(.error|not) and (.result.gameID == "'"$gameID"'") and (.result.results|length >= 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
} }
function run_testcases() { function run_testcases() {
#密钥 #密钥
sect1="123" sect1="123"
#结果base64.StdEncoding.EncodeToString(common.Sha256([]byte("0"+secret+black)))
# black == "1" white := "0"
#black0="O3LD8NyaeeSCc8xDfvBoacTrQlrY91FHT9ceEOXgs18="
black1="6vm6gJ2wvEIxC8Yc6r/N6lIU5OZk633YMnIfwcZBD0o=" black1="6vm6gJ2wvEIxC8Yc6r/N6lIU5OZk633YMnIfwcZBD0o="
black2="6FXx5aeDSCaq1UrhLO8u0H31Hl8TpvzxuHrgGo9WeFk=" black2="6FXx5aeDSCaq1UrhLO8u0H31Hl8TpvzxuHrgGo9WeFk="
white0="DrNPzA68XiGimZE/igx70kTPJxnIJnVf8NCGnb7XoYU=" white0="DrNPzA68XiGimZE/igx70kTPJxnIJnVf8NCGnb7XoYU="
white1="SB5Pnf6Umf2Wba0dqyNOezq5FEqTd22WPVYAhSA6Lxs=" white1="SB5Pnf6Umf2Wba0dqyNOezq5FEqTd22WPVYAhSA6Lxs="
#white2="OiexKDzIlS1CKr3KBNWEY1k5uXzDI/ou6Dd+x0ByQCM="
#先创建账户地址 #先创建账户地址
chain33_NewAccount "label188" chain33_NewAccount "label188"
...@@ -201,9 +157,8 @@ function run_testcases() { ...@@ -201,9 +157,8 @@ function run_testcases() {
blackwhite_BlackwhiteTimeoutDoneTx "$gID" blackwhite_BlackwhiteTimeoutDoneTx "$gID"
#查询部分 #查询部分
blackwhite_GetBlackwhiteRoundInfo "$gID" blackwhite_GetBlackwhiteRoundInfo "$gID"
blackwhite_GetBlackwhiteByStatusAndAddr "$gID" "${gameAddr1}" blackwhite_GetBlackwhiteByStatusAndAddr "${gameAddr1}"
blackwhite_GetBlackwhiteloopResult "$gID" blackwhite_GetBlackwhiteloopResult "$gID"
} }
function main() { function main() {
...@@ -212,17 +167,8 @@ function main() { ...@@ -212,17 +167,8 @@ function main() {
echo "main_ip=$MAIN_HTTP" echo "main_ip=$MAIN_HTTP"
init init
run_testcases run_testcases
chain33_RpcTestRst blackwhite "$CASE_ERR" 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 #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e set -e
set -o pipefail set -o pipefail
MAIN_HTTP="" MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
MAIN_HTTP="" MAIN_HTTP=""
CASE_ERR=""
#eventId=""
#txhash=""
init() { init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")') ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
...@@ -30,8 +25,7 @@ function main() { ...@@ -30,8 +25,7 @@ function main() {
init init
run_test run_test
chain33_RpcTestRst dposvote "$CASE_ERR" chain33_RpcTestRst dposvote "$CASE_ERR"
} }
main "$1" chain33_debug_function main "$1"
This diff is collapsed.
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{}
}
This diff is collapsed.
This diff is collapsed.
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
}
This diff is collapsed.
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
set -e # shellcheck source=/dev/null
set -o pipefail set -o pipefail
MAIN_HTTP="" MAIN_HTTP=""
...@@ -8,36 +8,24 @@ GAME_ID="" ...@@ -8,36 +8,24 @@ GAME_ID=""
PASSWD="ABCD" PASSWD="ABCD"
HASH_VALUE=$(echo -n "ABCD1" | sha256sum | awk '{print $1}') 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 source ../dapp-test-common.sh
function chain33_GetExecAddr() { function chain33_GetExecAddr() {
#获取GAME合约地址 #获取GAME合约地址
local exector=$1 req='{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"'"$1"'"}]}'
local req='"method":"Chain33.ConvertExectoAddr","params":[{"execname":"'"${exector}"'"}]' chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME"
echo "#request: $req"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
# GAME_ADDR=$(echo "${res}" | jq -r ".result")
echo_rst "$FUNCNAME" "$?"
} }
function CreateGameTx() { function CreateGameTx() {
local amount=$1 local amount=$1
local hash_value=$2 local hash_value=$2
local req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"createGame", "payload":{"amount": '"${amount}"',"hashType":"sha256","hashValue":"'"${hash_value}"'"}}]' local req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"createGame", "payload":{"amount": '"${amount}"',"hashType":"sha256","hashValue":"'"${hash_value}"'"}}]}'
echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
chain33_SignAndSendTx "${RETURN_RESP}" "${PRIVA_A}" "${MAIN_HTTP}"
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}"
GAME_ID=$RAW_TX_HASH GAME_ID=$RAW_TX_HASH
echo_rst "CreateGame query_tx" "$?" echo_rst "CreateGame query_tx" "$?"
...@@ -45,81 +33,43 @@ function CreateGameTx() { ...@@ -45,81 +33,43 @@ function CreateGameTx() {
function MatchGameTx() { function MatchGameTx() {
local gameId=$1 local gameId=$1
local req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"matchGame", "payload":{"gameId": "'"${gameId}"'","guess":2}}]' 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"
echo "#request: $req" chain33_SignAndSendTx "${RETURN_RESP}" "${PRIVA_B}" "${MAIN_HTTP}"
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}"
echo_rst "MatchGame query_tx" "$?" echo_rst "MatchGame query_tx" "$?"
} }
function CloseGameTx() { function CloseGameTx() {
local gameId=$1 local gameId=$1
local secret=$2 local secret=$2
local req='"method":"Chain33.CreateTransaction","params":[{"execer":"'"${EXECTOR}"'", "actionName":"closeGame", "payload":{"gameId": "'"${gameId}"'","secret":"'"${secret}"'","result":1}}]' 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
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" "$?" echo_rst "CloseGame query_tx" "$?"
} }
function CancleGameTx() { function CancleGameTx() {
local gameId=$1 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" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "CancleGame createRawTx" ".result"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}") chain33_SignAndSendTx "${RETURN_RESP}" "${PRIVA_A}" "${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}"
echo_rst "CancleGame query_tx" "$?" echo_rst "CancleGame query_tx" "$?"
} }
function QueryGameByStatus() { function QueryGameByStatus() {
local status=$1 local status=$1
local req='"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameListByStatusAndAddr","payload":{"status":'"${status}"',"address":""}}]' local req='{"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameListByStatusAndAddr","payload":{"status":'"${status}"',"address":""}}]}'
echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not)' "$FUNCNAME" ".result.games"
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}")
echo "#response: $resp"
GAMES=$(echo "${resp}" | jq -r ".result.games")
echo "${GAMES}"
echo_rst "$FUNCNAME" "$?"
} }
function QueryGameByGameId() { function QueryGameByGameId() {
local gameId=$1 local gameId=$1
local status=$2 local status=$2
local req='"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameById","payload":{"gameId":"'"${gameId}"'"}}]' local req='{"method":"Chain33.Query","params":[{"execer":"'"${EXECTOR}"'","funcName":"QueryGameById","payload":{"gameId":"'"${gameId}"'"}}]}'
echo "#request: $req" resok='(.error|not) and (.result.game.status = "'"${status}"'")'
resp=$(curl -ksd "{$req}" "${MAIN_HTTP}") chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
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
} }
function init() { function init() {
...@@ -138,10 +88,8 @@ function init() { ...@@ -138,10 +88,8 @@ function init() {
local main_ip=${MAIN_HTTP//8901/8801} local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key #main chain import pri key
#16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f chain33_ImportPrivkey "$PRIVA_A" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "${main_ip}"
chain33_ImportPrivkey "0xfa21dc33a6144c546537580d28d894355d1e9af7292be175808b0f5737c30849" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "${main_ip}" chain33_ImportPrivkey "$PRIVA_B" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$main_ip"
#16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc
chain33_ImportPrivkey "0x213286d352b01fd740b6eaeb78a4fd316d743dd51d2f12c6789977430a41e0c7" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$main_ip"
local ACCOUNT_A="16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" local ACCOUNT_A="16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f"
local ACCOUNT_B="16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" local ACCOUNT_B="16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc"
...@@ -153,16 +101,14 @@ function init() { ...@@ -153,16 +101,14 @@ function init() {
chain33_applyCoins "$ACCOUNT_B" 12000000000 "${main_ip}" chain33_applyCoins "$ACCOUNT_B" 12000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_B}" "$main_ip" chain33_QueryBalance "${ACCOUNT_B}" "$main_ip"
else else
# tx fee
chain33_applyCoins "$ACCOUNT_A" 1000000000 "${main_ip}" chain33_applyCoins "$ACCOUNT_A" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$main_ip" chain33_QueryBalance "${ACCOUNT_A}" "$main_ip"
chain33_applyCoins "$ACCOUNT_B" 1000000000 "${main_ip}" chain33_applyCoins "$ACCOUNT_B" 1000000000 "${main_ip}"
chain33_QueryBalance "${ACCOUNT_B}" "$main_ip" chain33_QueryBalance "${ACCOUNT_B}" "$main_ip"
local para_ip="${MAIN_HTTP}" local para_ip="${MAIN_HTTP}"
#para chain import pri key chain33_ImportPrivkey "$PRIVA_A" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "$para_ip"
chain33_ImportPrivkey "0xfa21dc33a6144c546537580d28d894355d1e9af7292be175808b0f5737c30849" "16Z3haNPQd9wrnFDw19rtpbgnN2xynNT9f" "game1" "$para_ip" chain33_ImportPrivkey "$PRIVA_B" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$para_ip"
chain33_ImportPrivkey "0x213286d352b01fd740b6eaeb78a4fd316d743dd51d2f12c6789977430a41e0c7" "16GXRfd9xj3XYMDti4y4ht7uzwoh55gZEc" "game2" "$para_ip"
chain33_applyCoins "$ACCOUNT_A" 12000000000 "${para_ip}" chain33_applyCoins "$ACCOUNT_A" 12000000000 "${para_ip}"
chain33_QueryBalance "${ACCOUNT_A}" "$para_ip" chain33_QueryBalance "${ACCOUNT_A}" "$para_ip"
...@@ -181,43 +127,28 @@ function init() { ...@@ -181,43 +127,28 @@ function init() {
function run_test() { function run_test() {
local ip=$1 local ip=$1
CreateGameTx 1000000000 "${HASH_VALUE}" CreateGameTx 1000000000 "${HASH_VALUE}"
QueryGameByGameId "${GAME_ID}" 1 QueryGameByGameId "${GAME_ID}" 1
QueryGameByStatus 1 QueryGameByStatus 1
MatchGameTx "${GAME_ID}" MatchGameTx "${GAME_ID}"
QueryGameByGameId "${GAME_ID}" 2 QueryGameByGameId "${GAME_ID}" 2
QueryGameByStatus 2 QueryGameByStatus 2
CloseGameTx "${GAME_ID}" "${PASSWD}" CloseGameTx "${GAME_ID}" "${PASSWD}"
QueryGameByGameId "${GAME_ID}" 4 QueryGameByGameId "${GAME_ID}" 4
QueryGameByStatus 4 QueryGameByStatus 4
CreateGameTx 500000000 "${HASH_VALUE}" CreateGameTx 500000000 "${HASH_VALUE}"
QueryGameByGameId "${GAME_ID}" 1 QueryGameByGameId "${GAME_ID}" 1
CancleGameTx "${GAME_ID}" CancleGameTx "${GAME_ID}"
QueryGameByGameId "${GAME_ID}" 3 QueryGameByGameId "${GAME_ID}" 3
QueryGameByStatus 3 QueryGameByStatus 3
} }
function main() { function main() {
chain33_RpcTestBegin game
local ip=$1 local ip=$1
MAIN_HTTP=$ip MAIN_HTTP=$ip
chain33_RpcTestBegin game
echo "main_ip=$MAIN_HTTP"
init init
run_test "$MAIN_HTTP" run_test "$MAIN_HTTP"
chain33_RpcTestRst game "$CASE_ERR" chain33_RpcTestRst game "$CASE_ERR"
} }
......
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e set -e
set -o pipefail set -o pipefail
MAIN_HTTP="" MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
MAIN_HTTP="" MAIN_HTTP=""
CASE_ERR=""
guess_admin_addr=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv guess_admin_addr=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
guess_user1_addr=1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM guess_user1_addr=1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM
guess_user2_addr=17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN guess_user2_addr=17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN
...@@ -20,103 +18,38 @@ eventId="" ...@@ -20,103 +18,38 @@ eventId=""
txhash="" txhash=""
guess_game_start() { 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") 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")
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
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}
eventId="${txhash}" eventId="${txhash}"
echo "eventId $eventId"
echo "========== # guess start tx end =========="
chain33_BlockWait 1 ${MAIN_HTTP}
} }
guess_game_bet() { guess_game_bet() {
local priv=$1 local priv=$1
local opt=$2 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"Bet", "payload":{"gameID":"'"${eventId}"'","option":"'"${opt}"'", "betsNum":500000000}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "${priv}" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
guess_game_stop() { 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"StopBet", "payload":{"gameID":"'"${eventId}"'"}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
guess_game_publish() { 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"Publish", "payload":{"gameID":"'"${eventId}"'","result":"A"}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
guess_game_abort() { 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"Abort", "payload":{"gameID":"'"${eventId}"'"}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
guess_QueryGameByID() { guess_QueryGameByID() {
local event_id=$1 local event_id=$1
local status=$2 local status=$2
echo "========== # guess QueryGameByID begin ==========" local req='{"method":"Chain33.Query", "params":[{"execer":"guess","funcName":"QueryGameByID","payload":{"gameID":"'"$event_id"'"}}]}'
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"
#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 =========="
} }
init() { init() {
...@@ -132,10 +65,7 @@ init() { ...@@ -132,10 +65,7 @@ init() {
echo "guess_addr=$guess_addr" echo "guess_addr=$guess_addr"
local main_ip=${MAIN_HTTP//8901/8801} local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM
chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "guess11" "${main_ip}" chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "guess11" "${main_ip}"
#17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN
chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "guess22" "$main_ip" chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "guess22" "$main_ip"
local guess1="1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" local guess1="1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM"
...@@ -148,14 +78,12 @@ init() { ...@@ -148,14 +78,12 @@ init() {
chain33_applyCoins "$guess2" 12000000000 "${main_ip}" chain33_applyCoins "$guess2" 12000000000 "${main_ip}"
chain33_QueryBalance "${guess2}" "$main_ip" chain33_QueryBalance "${guess2}" "$main_ip"
else else
# tx fee
chain33_applyCoins "$guess1" 1000000000 "${main_ip}" chain33_applyCoins "$guess1" 1000000000 "${main_ip}"
chain33_QueryBalance "${guess1}" "$main_ip" chain33_QueryBalance "${guess1}" "$main_ip"
chain33_applyCoins "$guess2" 1000000000 "${main_ip}" chain33_applyCoins "$guess2" 1000000000 "${main_ip}"
chain33_QueryBalance "${guess2}" "$main_ip" chain33_QueryBalance "${guess2}" "$main_ip"
local para_ip="${MAIN_HTTP}" local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "guess11" "$para_ip" chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "guess11" "$para_ip"
chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "guess22" "$para_ip" chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "guess22" "$para_ip"
...@@ -174,7 +102,6 @@ init() { ...@@ -174,7 +102,6 @@ init() {
} }
function run_test() { function run_test() {
#导入地址私钥 #导入地址私钥
chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "user1" "$MAIN_HTTP" chain33_ImportPrivkey "0xc889d2958843fc96d4bd3f578173137d37230e580d65e9074545c61e7e9c1932" "1NrfEBfdFJUUqgbw5ZbHXhdew6NNQumYhM" "user1" "$MAIN_HTTP"
chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "user2" "$MAIN_HTTP" chain33_ImportPrivkey "0xf10c79470dc74c229c4ee73b05d14c58322b771a6c749d27824f6a59bb6c2d73" "17tRkBrccmFiVcLPXgEceRxDzJ2WaDZumN" "user2" "$MAIN_HTTP"
...@@ -320,7 +247,6 @@ function main() { ...@@ -320,7 +247,6 @@ function main() {
init init
run_test run_test
chain33_RpcTestRst guess "$CASE_ERR" chain33_RpcTestRst guess "$CASE_ERR"
} }
......
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e set -e
set -o pipefail set -o pipefail
...@@ -7,67 +8,24 @@ MAIN_HTTP="" ...@@ -7,67 +8,24 @@ MAIN_HTTP=""
addr_A=19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3 addr_A=19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3
addr_B=1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD addr_B=1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
hashlock_lock() { hashlock_lock() {
local secret=$1 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") 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")
chain33_SignAndSendTxWait "$tx" "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
hashlock_send() { hashlock_send() {
local secret=$1 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"hashlock","actionName":"HashlockSend", "payload":{"secret":"'"${secret}"'","fee":100000000}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "0xb76a398c3901dfe5c7335525da88fda4df24c11ad11af4332f00c0953cc2910f" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
hashlock_unlock() { hashlock_unlock() {
local secret=$1 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"hashlock","actionName":"HashlockUnlock", "payload":{"secret":"'"${secret}"'","fee":100000000}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
init() { init() {
...@@ -80,10 +38,7 @@ init() { ...@@ -80,10 +38,7 @@ init() {
fi fi
local main_ip=${MAIN_HTTP//8901/8801} local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3
chain33_ImportPrivkey "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" "19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3" "hashlock1" "${main_ip}" chain33_ImportPrivkey "0x1089b7f980fc467f029b7ae301249b36e3b582c911b1af1a24616c83b3563dcb" "19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3" "hashlock1" "${main_ip}"
#1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD
chain33_ImportPrivkey "0xb76a398c3901dfe5c7335525da88fda4df24c11ad11af4332f00c0953cc2910f" "1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD" "hashlock2" "$main_ip" chain33_ImportPrivkey "0xb76a398c3901dfe5c7335525da88fda4df24c11ad11af4332f00c0953cc2910f" "1FcofeCgU1KYbB8dSa7cV2wjAF2RpMuUQD" "hashlock2" "$main_ip"
local hashlock1="19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3" local hashlock1="19vpbRuz2XtKopQS2ruiVuVZeRdLd5n4t3"
...@@ -129,10 +84,8 @@ function run_test() { ...@@ -129,10 +84,8 @@ function run_test() {
hashlock_send "abc" hashlock_send "abc"
chain33_QueryBalance "$addr_B" "${MAIN_HTTP}" chain33_QueryBalance "$addr_B" "${MAIN_HTTP}"
hashlock_unlock "abc" hashlock_unlock "abc"
hashlock_lock "aef" hashlock_lock "aef"
chain33_QueryBalance "$addr_A" "${MAIN_HTTP}" chain33_QueryBalance "$addr_A" "${MAIN_HTTP}"
sleep 5 sleep 5
hashlock_unlock "aef" hashlock_unlock "aef"
chain33_BlockWait 1 ${MAIN_HTTP} chain33_BlockWait 1 ${MAIN_HTTP}
...@@ -140,13 +93,12 @@ function run_test() { ...@@ -140,13 +93,12 @@ function run_test() {
} }
function main() { function main() {
MAIN_HTTP="$1"
chain33_RpcTestBegin hashlock chain33_RpcTestBegin hashlock
MAIN_HTTP="$1"
echo "ip=$MAIN_HTTP" echo "ip=$MAIN_HTTP"
init init
run_test run_test
chain33_RpcTestRst hashlock "$CASE_ERR" chain33_RpcTestRst hashlock "$CASE_ERR"
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
_ "github.com/33cn/plugin/plugin/dapp/dposvote" //auto gen _ "github.com/33cn/plugin/plugin/dapp/dposvote" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/echo" //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/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/game" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/guess" //auto gen _ "github.com/33cn/plugin/plugin/dapp/guess" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/hashlock" //auto gen _ "github.com/33cn/plugin/plugin/dapp/hashlock" //auto gen
......
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null # shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
...@@ -12,11 +11,6 @@ function init() { ...@@ -12,11 +11,6 @@ function init() {
beneficiary_key=0xf146df80206194c81e0b3171db6aa40c7ad6182a24560698d4871d4dc75223ce beneficiary_key=0xf146df80206194c81e0b3171db6aa40c7ad6182a24560698d4871d4dc75223ce
beneficiary=1DwHQp8S7RS9krQTyrqePxRyvaLcuoQGks beneficiary=1DwHQp8S7RS9krQTyrqePxRyvaLcuoQGks
chain33_applyCoins "${beneficiary}" 10000000000 "${MAIN_HTTP}" chain33_applyCoins "${beneficiary}" 10000000000 "${MAIN_HTTP}"
#paracross_get_money 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
#//beneficiary=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
#beneficiary_key=0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01
#owner=14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
#owner_key=CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944
echo "ipara=$ispara" echo "ipara=$ispara"
manager_name="manage" manager_name="manage"
exec_name="jsvm" exec_name="jsvm"
...@@ -40,55 +34,30 @@ function init() { ...@@ -40,55 +34,30 @@ function init() {
} }
function configJSCreator() { function configJSCreator() {
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${manager_name}'","actionName":"Modify","payload":{"key":"js-creator","op":"add", "value" : "'${beneficiary}'"}}]}' req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'${manager_name}'","actionName":"Modify","payload":{"key":"js-creator","op":"add","value":"'${beneficiary}'"}}]}'
echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
resp=$(curl -ksd "$req" "${MAIN_HTTP}") chain33_SignAndSendTx "$RETURN_RESP" "${super_manager}" "${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}"
} }
function createJSContract() { function createJSContract() {
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${exec_name}'","actionName":"Create","payload":{"name":"'${game}'","code":"'${jsCode}'"}}]}' req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'${exec_name}'","actionName":"Create","payload":{"name":"'${game}'","code":"'${jsCode}'"}}]}'
echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
resp=$(curl -ksd "$req" "${MAIN_HTTP}") chain33_SignAndSendTx "$RETURN_RESP" "${beneficiary_key}" "${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}"
} }
function callJS() { function callJS() {
#the_exec= req='{"method":"Chain33.CreateTransaction","params":[{"execer":"'${user_game}'","actionName":"Call","payload":{"name":"'${game}'","funcname":"hello","args":"{}"}}]}'
req='{"jsonrpc": "2.0", "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"
# echo "#request: $req" chain33_SignAndSendTx "$RETURN_RESP" "${beneficiary_key}" "${MAIN_HTTP}"
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}"
} }
function queryJS() { function queryJS() {
req='{"jsonrpc": "2.0", "method" : "Chain33.Query" , "params":[{"execer":"'${user_game}'","funcName":"Query","payload":{"name":"'${game}'","funcname":"hello", "args" : "{}"}}]}' req='{"method":"Chain33.Query","params":[{"execer":"'${user_game}'","funcName":"Query","payload":{"name":"'${game}'","funcname":"hello","args":"{}"}}]}'
# echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
} }
function run_testcases() { function run_testcases() {
configJSCreator configJSCreator
createJSContract createJSContract
callJS callJS
queryJS queryJS
...@@ -96,13 +65,11 @@ function run_testcases() { ...@@ -96,13 +65,11 @@ function run_testcases() {
function rpc_test() { function rpc_test() {
chain33_RpcTestBegin js chain33_RpcTestBegin js
MAIN_HTTP="$1" MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP" echo "main_ip=$MAIN_HTTP"
init init
run_testcases run_testcases
chain33_RpcTestRst js "$CASE_ERR" chain33_RpcTestRst js "$CASE_ERR"
} }
......
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
MAIN_HTTP="" MAIN_HTTP=""
oracle_addPublisher_unsignedTx="0a066d616e61676512410a3f0a146f7261636c652d7075626c6973682d6576656e741222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a0361646420a08d0630e6b685d696ee9394163a223151344e687572654a784b4e4266373164323642394a336642516f5163666d657a32" oracle_addPublisher_unsignedTx="0a066d616e61676512410a3f0a146f7261636c652d7075626c6973682d6576656e741222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a0361646420a08d0630e6b685d696ee9394163a223151344e687572654a784b4e4266373164323642394a336642516f5163666d657a32"
...@@ -8,7 +9,6 @@ oracle_publisher_key="4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C72 ...@@ -8,7 +9,6 @@ oracle_publisher_key="4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C72
eventId="" eventId=""
txhash="" txhash=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
oracle_AddPublisher() { oracle_AddPublisher() {
...@@ -16,88 +16,52 @@ oracle_AddPublisher() { ...@@ -16,88 +16,52 @@ oracle_AddPublisher() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")') ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ispara=$ispara" echo "ispara=$ispara"
if [ "$ispara" == true ]; then 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 else
chain33_SignRawTx "${oracle_addPublisher_unsignedTx}" "${oracle_publisher_key}" "${MAIN_HTTP}" chain33_SignAndSendTx "${oracle_addPublisher_unsignedTx}" "${oracle_publisher_key}" "${MAIN_HTTP}"
fi fi
} }
oracle_publish_transaction() { oracle_publish_transaction() {
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventPublish","payload":{"type":"football", "subType":"Premier League","time":1747814996,"content":"test","introduction":"test"}}]' req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventPublish","payload":{"type":"football", "subType":"Premier League","time":1747814996,"content":"test","introduction":"test"}}]}'
#echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP}) chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${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}"
eventId="${txhash}" eventId="${txhash}"
echo "eventId $eventId" echo "eventId $eventId"
} }
oracle_prePublishResult_transaction() { oracle_prePublishResult_transaction() {
event_id=$1 event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPrePublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"0:1"}}]' req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPrePublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"0:1"}}]}'
#echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP}) chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${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}"
} }
oracle_eventAbort_transaction() { oracle_eventAbort_transaction() {
event_id=$1 event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventAbort","payload":{"eventID":"'"$event_id"'"}}]' req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventAbort","payload":{"eventID":"'"$event_id"'"}}]}'
#echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP}) chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${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}"
} }
oracle_resultAbort_transaction() { oracle_resultAbort_transaction() {
event_id=$1 event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultAbort","payload":{"eventID":"'"$event_id"'"}}]' req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultAbort","payload":{"eventID":"'"$event_id"'"}}]}'
#echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP}) chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${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}"
} }
oracle_publishResult_transaction() { oracle_publishResult_transaction() {
event_id=$1 event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"1:1"}}]' req='{"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"1:1"}}]}'
#echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result != null)' "$FUNCNAME" ".result"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP}) chain33_SignAndSendTx "$RETURN_RESP" "${oracle_publisher_key}" "${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}"
} }
oracle_QueryOraclesByID() { oracle_QueryOraclesByID() {
event_id=$1 event_id=$1
local req='"method":"Chain33.Query", "params":[{"execer":"oracle","funcName":"QueryOraclesByIDs","payload":{"eventID":["'"$event_id"'"]}}]' req='{"method":"Chain33.Query", "params":[{"execer":"oracle","funcName":"QueryOraclesByIDs","payload":{"eventID":["'"$event_id"'"]}}]}'
#echo "#request: $req" chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result.status[0] | [has("eventID", "status", "type", "subType", "source"),true] | unique | length == 1)' "$FUNCNAME"
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"
} }
function run_test() { function run_test() {
...@@ -134,14 +98,12 @@ function run_test() { ...@@ -134,14 +98,12 @@ function run_test() {
} }
function main() { function main() {
chain33_RpcTestBegin oracle
MAIN_HTTP="$1" MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP" echo "main_ip=$MAIN_HTTP"
chain33_RpcTestBegin oracle
run_test run_test
chain33_RpcTestRst oracle "$CASE_ERR" chain33_RpcTestRst oracle "$CASE_ERR"
} }
main "$1" chain33_debug_function main "$1"
...@@ -33,7 +33,7 @@ checkItem = ["balance"] ...@@ -33,7 +33,7 @@ checkItem = ["balance"]
#send para asset bty #send para asset bty
[[TransferCase]] [[TransferCase]]
id = "btyParaTrans" 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" from = "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
#复用coins的transfer用例,此处to地址比较特殊,为平行链paracross合约的地址 #复用coins的transfer用例,此处to地址比较特殊,为平行链paracross合约的地址
to = "16zsMh7mvNDKPG6E9NVrPhw6zL93gWsTpR" to = "16zsMh7mvNDKPG6E9NVrPhw6zL93gWsTpR"
...@@ -55,7 +55,7 @@ dep = ["tokenFinish"] ...@@ -55,7 +55,7 @@ dep = ["tokenFinish"]
#send para asset token PT #send para asset token PT
[[TransferCase]] [[TransferCase]]
id = "tokenParaTrans" 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" from = "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
#复用coins的transfer用例,此处to地址比较特殊,为平行链paracross合约的地址 #复用coins的transfer用例,此处to地址比较特殊,为平行链paracross合约的地址
to = "16zsMh7mvNDKPG6E9NVrPhw6zL93gWsTpR" to = "16zsMh7mvNDKPG6E9NVrPhw6zL93gWsTpR"
......
...@@ -336,11 +336,11 @@ function para_cross_transfer_withdraw() { ...@@ -336,11 +336,11 @@ function para_cross_transfer_withdraw() {
echo "${hash}" echo "${hash}"
query_tx "${CLI}" "${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}" echo "${hash}"
query_tx "${PARA_CLI}" "${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 local times=200
while true; do while true; do
...@@ -361,6 +361,23 @@ function para_cross_transfer_withdraw() { ...@@ -361,6 +361,23 @@ function para_cross_transfer_withdraw() {
break break
fi fi
done 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() { function token_create_on_mainChain() {
...@@ -426,12 +443,12 @@ function para_cross_transfer_withdraw_for_token() { ...@@ -426,12 +443,12 @@ function para_cross_transfer_withdraw_for_token() {
query_tx "${MAIN_CLI}" "${hash}" query_tx "${MAIN_CLI}" "${hash}"
echo "=========== # 2.transfer asset to para chain =============" 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}" echo "${hash}"
query_tx "${MAIN_CLI}" "${hash}" query_tx "${MAIN_CLI}" "${hash}"
echo "=========== # 3.asset_withdraw from parachain =============" 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 local times=100
while true; do while true; do
......
...@@ -14,3 +14,4 @@ help: ## Display this help screen ...@@ -14,3 +14,4 @@ help: ## Display this help screen
@printf "[command]\n" @printf "[command]\n"
@printf "[nodegroup]: create super node group if not create \n" @printf "[nodegroup]: create super node group if not create \n"
@printf "[wallet]: set node wallet private key if not set \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" genesisAccount="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
#创世数量
genesisAmount=100000000 genesisAmount=100000000
#从主链哪个高度开始同步区块
mainStartHeight=4000000 mainStartHeight=4000000
#平行链授权账户,这里的数量要和下面的authPrikey和authPort保持一致
authAccount=( "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4" "1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR" "1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k" "1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs") authAccount=( "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4" "1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR" "1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k" "1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs")
#授权账户的私钥,为了导入钱包,自动开启共识挖矿
authPrikey=("0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" "0x19c069234f9d3e61135fefbeb7791b149cdf6af536f26bebb310d4cd22c3fee4" "0x7a80a1f75d7360c6123c32a78ecf978c1ac55636f87892df38d8b85a9aeff115" "0xcacb1f5d51700aea07fca2246ab43b0917d70405c65edea9b5063d72eb5c6b71") authPrikey=("0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" "0x19c069234f9d3e61135fefbeb7791b149cdf6af536f26bebb310d4cd22c3fee4" "0x7a80a1f75d7360c6123c32a78ecf978c1ac55636f87892df38d8b85a9aeff115" "0xcacb1f5d51700aea07fca2246ab43b0917d70405c65edea9b5063d72eb5c6b71")
#授权节点的宿主机端口
authPort=("18901" "18902" "18903" "18904") authPort=("18901" "18902" "18903" "18904")
#需要和chain33 主链保持一致 #需要和chain33 主链保持一致
...@@ -32,8 +22,12 @@ superManager="['12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv']" ...@@ -32,8 +22,12 @@ superManager="['12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv']"
tokenApprs="['12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv']" tokenApprs="['12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv']"
#nodegroup create #超级账户创建
#授权账户申请需要在主链上冻结的BTY数量,申请之前需要chain33项目方沟通,需要chain33超级管理员审批通过
authFrozenCoins=0 authFrozenCoins=0
#超级账户组申请者,需要事先在paracross合约转移必须的BTY,数量=申请的授权账户数量*authFrozenCoins
nodeGroupApplier="1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4" nodeGroupApplier="1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"
#超级账户组申请者私钥 签名交易使用
applierPrikey="0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" applierPrikey="0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b"
#超级管理员私钥,在主链上申请不需要填
superManagerPrikey="4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01" superManagerPrikey="4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01"
...@@ -87,6 +87,13 @@ function para_import_wallet() { ...@@ -87,6 +87,13 @@ function para_import_wallet() {
./$CHAIN33_CLI --rpc_laddr "http://localhost:$port" wallet status ./$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() { function start() {
echo "=========== # docker-compose ps =============" echo "=========== # docker-compose ps ============="
docker-compose ps docker-compose ps
...@@ -175,6 +182,7 @@ EOF ...@@ -175,6 +182,7 @@ EOF
volumes: volumes:
- "../storage/parachain$i/paradatadir:/root/paradatadir" - "../storage/parachain$i/paradatadir:/root/paradatadir"
- "../storage/parachain$i/logs:/root/logs" - "../storage/parachain$i/logs:/root/logs"
- "../storage/parachain$i/parawallet:/root/parawallet"
EOF EOF
done done
...@@ -260,6 +268,10 @@ function main() { ...@@ -260,6 +268,10 @@ function main() {
para_set_wallet para_set_wallet
fi fi
if [ "$1" == "miner" ]; then
para_unlock_wallet
fi
echo "===============================parachain startup end=========================================================" echo "===============================parachain startup end========================================================="
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -181,7 +181,7 @@ func makeRecordReceipt(addr string, commit *pt.ParacrossCommitAction) *types.Rec ...@@ -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 { most, commitCount, totalCount int32) *types.Receipt {
log := &pt.ReceiptParacrossDone{ log := &pt.ReceiptParacrossDone{
...@@ -194,6 +194,7 @@ func makeDoneReceipt(cfg *types.Chain33Config, execMainHeight int64, commit *pt. ...@@ -194,6 +194,7 @@ func makeDoneReceipt(cfg *types.Chain33Config, execMainHeight int64, commit *pt.
TxResult: commit.TxResult, TxResult: commit.TxResult,
MainBlockHeight: commit.MainBlockHeight, MainBlockHeight: commit.MainBlockHeight,
MainBlockHash: commit.MainBlockHash, MainBlockHash: commit.MainBlockHash,
ChainExecHeight: execHeight,
} }
key := calcTitleKey(commit.Title) key := calcTitleKey(commit.Title)
status := &pt.ParacrossStatus{ status := &pt.ParacrossStatus{
...@@ -511,7 +512,7 @@ func (a *action) commitTxDone(nodeStatus *pt.ParacrossNodeStatus, stat *pt.Parac ...@@ -511,7 +512,7 @@ func (a *action) commitTxDone(nodeStatus *pt.ParacrossNodeStatus, stat *pt.Parac
} }
//add commit done receipt //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) receipt = mergeReceipt(receipt, receiptDone)
r, err := a.commitTxDoneStep2(nodeStatus, stat, titleStatus) r, err := a.commitTxDoneStep2(nodeStatus, stat, titleStatus)
...@@ -696,7 +697,7 @@ func (a *action) commitTxDoneByStat(stat *pt.ParacrossHeightStatus, titleStatus ...@@ -696,7 +697,7 @@ func (a *action) commitTxDoneByStat(stat *pt.ParacrossHeightStatus, titleStatus
//add commit done receipt //add commit done receipt
cfg := a.api.GetConfig() 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) receipt = mergeReceipt(receipt, receiptDone)
r, err := a.commitTxDoneStep2(mostStatus, stat, titleStatus) r, err := a.commitTxDoneStep2(mostStatus, stat, titleStatus)
......
...@@ -28,6 +28,10 @@ func (p *Paracross) Query_GetTitleHeight(in *pt.ReqParacrossTitleHeight) (types. ...@@ -28,6 +28,10 @@ func (p *Paracross) Query_GetTitleHeight(in *pt.ReqParacrossTitleHeight) (types.
if in == nil { if in == nil {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
cfg := p.GetAPI().GetConfig()
if cfg.IsPara() {
in.Title = cfg.GetTitle()
}
stat, err := p.paracrossGetStateTitleHeight(in.Title, in.Height) stat, err := p.paracrossGetStateTitleHeight(in.Title, in.Height)
if err != nil { if err != nil {
clog.Error("paracross.GetTitleHeight", "title", title, "height", in.Height, "err", err.Error()) 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 ...@@ -63,13 +67,20 @@ func (p *Paracross) Query_GetTitleByHash(in *pt.ReqParacrossTitleHash) (types.Me
//Query_GetNodeGroupAddrs get node group addrs //Query_GetNodeGroupAddrs get node group addrs
func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types.Message, error) { func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
if in == nil || in.GetTitle() == "" { if in == nil {
return nil, types.ErrInvalidParam 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()) ret, key, err := getConfigNodes(p.GetStateDB(), in.GetTitle())
if err != nil { if err != nil {
return nil, errors.Cause(err) return nil, err
} }
var nodes []string var nodes []string
for k := range ret { for k := range ret {
...@@ -83,9 +94,16 @@ func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types. ...@@ -83,9 +94,16 @@ func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types.
//Query_GetNodeAddrInfo get specific node addr info //Query_GetNodeAddrInfo get specific node addr info
func (p *Paracross) Query_GetNodeAddrInfo(in *pt.ReqParacrossNodeInfo) (types.Message, error) { 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 return nil, types.ErrInvalidParam
} }
stat, err := getNodeAddr(p.GetStateDB(), in.Title, in.Addr) stat, err := getNodeAddr(p.GetStateDB(), in.Title, in.Addr)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -94,7 +112,7 @@ func (p *Paracross) Query_GetNodeAddrInfo(in *pt.ReqParacrossNodeInfo) (types.Me ...@@ -94,7 +112,7 @@ func (p *Paracross) Query_GetNodeAddrInfo(in *pt.ReqParacrossNodeInfo) (types.Me
if err != nil { if err != nil {
return nil, err return nil, err
} }
cfg := p.GetAPI().GetConfig()
if pt.IsParaForkHeight(cfg, mainHeight, pt.ForkLoopCheckCommitTxDone) { if pt.IsParaForkHeight(cfg, mainHeight, pt.ForkLoopCheckCommitTxDone) {
stat.QuitId = getParaNodeIDSuffix(stat.QuitId) stat.QuitId = getParaNodeIDSuffix(stat.QuitId)
stat.ProposalId = getParaNodeIDSuffix(stat.ProposalId) stat.ProposalId = getParaNodeIDSuffix(stat.ProposalId)
...@@ -117,14 +135,21 @@ func (p *Paracross) getMainHeight() (int64, error) { ...@@ -117,14 +135,21 @@ func (p *Paracross) getMainHeight() (int64, error) {
//Query_GetNodeIDInfo get specific node addr info //Query_GetNodeIDInfo get specific node addr info
func (p *Paracross) Query_GetNodeIDInfo(in *pt.ReqParacrossNodeInfo) (types.Message, error) { 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 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() mainHeight, err := p.getMainHeight()
if err != nil { if err != nil {
return nil, err return nil, err
} }
cfg := p.GetAPI().GetConfig()
stat, err := getNodeIDWithFork(cfg, p.GetStateDB(), in.Title, mainHeight, in.Id) stat, err := getNodeIDWithFork(cfg, p.GetStateDB(), in.Title, mainHeight, in.Id)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -214,6 +239,10 @@ func (p *Paracross) Query_GetDoneTitleHeight(in *pt.ReqParacrossTitleHeight) (ty ...@@ -214,6 +239,10 @@ func (p *Paracross) Query_GetDoneTitleHeight(in *pt.ReqParacrossTitleHeight) (ty
if in == nil { if in == nil {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
cfg := p.GetAPI().GetConfig()
if cfg.IsPara() {
in.Title = cfg.GetTitle()
}
return p.paracrossGetTitleHeight(in.Title, in.Height) return p.paracrossGetTitleHeight(in.Title, in.Height)
} }
...@@ -300,6 +329,7 @@ func listLocalTitles(db dbm.KVDB) (types.Message, error) { ...@@ -300,6 +329,7 @@ func listLocalTitles(db dbm.KVDB) (types.Message, error) {
MostSameCommit: st.MostSameCommit, MostSameCommit: st.MostSameCommit,
Title: st.Title, Title: st.Title,
Height: st.Height, Height: st.Height,
ChainExecHeight: st.ChainExecHeight,
TxResult: string(st.TxResult), TxResult: string(st.TxResult),
} }
...@@ -385,6 +415,7 @@ func loadLocalTitle(db dbm.KV, title string, height int64) (types.Message, error ...@@ -385,6 +415,7 @@ func loadLocalTitle(db dbm.KV, title string, height int64) (types.Message, error
MostSameCommit: st.MostSameCommit, MostSameCommit: st.MostSameCommit,
Title: st.Title, Title: st.Title,
Height: st.Height, Height: st.Height,
ChainExecHeight: st.ChainExecHeight,
TxResult: hex.EncodeToString(st.TxResult), TxResult: hex.EncodeToString(st.TxResult),
}, nil }, nil
} }
...@@ -457,3 +488,60 @@ func (p *Paracross) Query_GetSelfConsOneStage(in *types.Int64) (types.Message, e ...@@ -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) { func (p *Paracross) Query_ListSelfStages(in *pt.ReqQuerySelfStages) (types.Message, error) {
return p.listSelfStages(in) 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 { ...@@ -328,6 +328,7 @@ message ReceiptParacrossDone {
repeated bytes crossTxHashs = 12; repeated bytes crossTxHashs = 12;
bytes mainBlockHash = 13; bytes mainBlockHash = 13;
int64 mainBlockHeight = 14; int64 mainBlockHeight = 14;
int64 chainExecHeight = 15;
} }
message ReceiptParacrossRecord { message ReceiptParacrossRecord {
...@@ -356,6 +357,8 @@ message RespParacrossDone { ...@@ -356,6 +357,8 @@ message RespParacrossDone {
string stateHash = 6; string stateHash = 6;
uint32 txCounts = 7; uint32 txCounts = 7;
string txResult = 8; string txResult = 8;
//commitDone chainHeight
int64 chainExecHeight= 9;
} }
message RespParacrossTitles { message RespParacrossTitles {
...@@ -421,10 +424,5 @@ message ParaLocalDbBlockInfo { ...@@ -421,10 +424,5 @@ message ParaLocalDbBlockInfo {
} }
service paracross { 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) {} rpc IsSync(ReqNil) returns (IsCaughtUp) {}
} }
\ No newline at end of file
This diff is collapsed.
...@@ -15,7 +15,6 @@ import ( ...@@ -15,7 +15,6 @@ import (
rpctypes "github.com/33cn/chain33/rpc/types" rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ptestNode "github.com/33cn/plugin/plugin/dapp/paracross/testnode" 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/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"golang.org/x/net/context" "golang.org/x/net/context"
...@@ -31,117 +30,6 @@ func newJrpc(api client.QueueProtocolAPI) *Jrpc { ...@@ -31,117 +30,6 @@ func newJrpc(api client.QueueProtocolAPI) *Jrpc {
return &Jrpc{cli: newGrpc(api)} 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) { func TestChannelClient_IsSync(t *testing.T) {
cfg := types.NewChain33Config(ptestNode.DefaultConfig) cfg := types.NewChain33Config(ptestNode.DefaultConfig)
api := new(mocks.QueueProtocolAPI) api := new(mocks.QueueProtocolAPI)
......
...@@ -6,7 +6,10 @@ import ( ...@@ -6,7 +6,10 @@ import (
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
_ "github.com/33cn/chain33/system" _ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/types"
_ "github.com/33cn/plugin/plugin" _ "github.com/33cn/plugin/plugin"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/stretchr/testify/assert"
) )
func TestParaNode(t *testing.T) { func TestParaNode(t *testing.T) {
...@@ -20,4 +23,8 @@ 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") tx = util.CreateTxWithExecer(paraCfg, para.Para.GetGenesisKey(), "user.p.test.none")
para.Para.SendTxRPC(tx) para.Para.SendTxRPC(tx)
para.Para.WaitHeight(2) 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)
} }
This diff is collapsed.
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e set -e
set -o pipefail set -o pipefail
MAIN_HTTP="" MAIN_HTTP=""
GAME_ID="" GAME_ID=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
pokerbull_PlayRawTx() { 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Play","payload":{"gameId":"pokerbull-abc", "value":"1000000000", "round":1}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP} "$FUNCNAME"
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}
} }
pokerbull_QuitRawTx() { 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Quit","payload":{"gameId":"'$GAME_ID'"}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP} "$FUNCNAME"
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}"
} }
pokerbull_ContinueRawTx() { 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Continue","payload":{"gameId":"'$GAME_ID'"}}]}' ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" ${MAIN_HTTP} "$FUNCNAME"
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}"
} }
pokerbull_StartRawTx() { 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") tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"pokerbull","actionName":"Start","payload":{"value":"1000000000", "playerNum":"2"}}]}' ${MAIN_HTTP} | jq -r ".result")
req='{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}'
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]") chain33_Http "$req" ${MAIN_HTTP} '(.result.txs[0].execer != null)' "$FUNCNAME"
ok=$(jq '(.execer != "")' <<<"$data") chain33_SignAndSendTx "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP}
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
chain33_SignRawTx "$tx" "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" ${MAIN_HTTP}
GAME_ID=$RAW_TX_HASH GAME_ID=$RAW_TX_HASH
echo "========== # pokerbull start tx end =========="
chain33_BlockWait 1 "${MAIN_HTTP}" chain33_BlockWait 1 "${MAIN_HTTP}"
} }
pokerbull_QueryResult() { pokerbull_QueryResult() {
echo "========== # pokerbull query result begin ==========" req='{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByID","payload":{"gameId":"'$GAME_ID'"}}]}'
local req='"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByID","payload":{"gameId":"'$GAME_ID'"}}]' resok='(.result.game.gameId == "'"$GAME_ID"'")'
data=$(curl -ksd "{$req}" ${MAIN_HTTP} | jq -r ".result") chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
ok=$(jq '(.game.gameId == "'"$GAME_ID"'")' <<<"$data")
[ "$ok" == true ] req='{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByAddr","payload":{"addr":"14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4"}}]}'
echo_rst "$FUNCNAME" "$?" 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") req='{"method":"Chain33.Query","params":[{"execer":"pokerbull","funcName":"QueryGameByStatus","payload":{"status":"3"}}]}'
[ "$data" != null ] chain33_Http "$req" ${MAIN_HTTP} '(.result != null)' "$FUNCNAME"
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 =========="
} }
init() { init() {
...@@ -104,10 +55,7 @@ init() { ...@@ -104,10 +55,7 @@ init() {
fi fi
local main_ip=${MAIN_HTTP//8901/8801} local main_ip=${MAIN_HTTP//8901/8801}
#main chain import pri key
#14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4
chain33_ImportPrivkey "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" "14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4" "pokerbull1" "${main_ip}" chain33_ImportPrivkey "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" "14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4" "pokerbull1" "${main_ip}"
#1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1
chain33_ImportPrivkey "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" "1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1" "pokerbull2" "$main_ip" chain33_ImportPrivkey "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" "1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1" "pokerbull2" "$main_ip"
local pokerbull1="14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4" local pokerbull1="14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4"
...@@ -120,14 +68,12 @@ init() { ...@@ -120,14 +68,12 @@ init() {
chain33_applyCoins "$pokerbull2" 12000000000 "${main_ip}" chain33_applyCoins "$pokerbull2" 12000000000 "${main_ip}"
chain33_QueryBalance "${pokerbull2}" "$main_ip" chain33_QueryBalance "${pokerbull2}" "$main_ip"
else else
# tx fee
chain33_applyCoins "$pokerbull1" 1000000000 "${main_ip}" chain33_applyCoins "$pokerbull1" 1000000000 "${main_ip}"
chain33_QueryBalance "${pokerbull1}" "$main_ip" chain33_QueryBalance "${pokerbull1}" "$main_ip"
chain33_applyCoins "$pokerbull2" 1000000000 "${main_ip}" chain33_applyCoins "$pokerbull2" 1000000000 "${main_ip}"
chain33_QueryBalance "${pokerbull2}" "$main_ip" chain33_QueryBalance "${pokerbull2}" "$main_ip"
local para_ip="${MAIN_HTTP}" local para_ip="${MAIN_HTTP}"
#para chain import pri key
chain33_ImportPrivkey "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" "14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4" "pokerbull1" "$para_ip" chain33_ImportPrivkey "0x0316d5e33e7bce2455413156cb95209f8c641af352ee5d648c647f24383e4d94" "14VkqML8YTRK4o15Cf97CQhpbnRUa6sJY4" "pokerbull1" "$para_ip"
chain33_ImportPrivkey "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" "1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1" "pokerbull2" "$para_ip" chain33_ImportPrivkey "0xa26038cbdd9e6fbfb85f2c3d032254755e75252b9edccbecc16d9ba117d96705" "1MuVM87DLigWhJxLJKvghTa1po4ZdWtDv1" "pokerbull2" "$para_ip"
...@@ -155,7 +101,6 @@ function run_test() { ...@@ -155,7 +101,6 @@ function run_test() {
pokerbull_PlayRawTx pokerbull_PlayRawTx
pokerbull_QueryResult pokerbull_QueryResult
} }
function main() { function main() {
...@@ -165,7 +110,6 @@ function main() { ...@@ -165,7 +110,6 @@ function main() {
init init
run_test run_test
chain33_RpcTestRst pokerbull "$CASE_ERR" chain33_RpcTestRst pokerbull "$CASE_ERR"
} }
......
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e set -e
set -o pipefail set -o pipefail
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
MAIN_HTTP="" MAIN_HTTP=""
privacy_CreateRawTransaction() { privacy_CreateRawTransaction() {
req='{"method":"privacy.CreateRawTransaction","params":[{"pubkeypair":"0a9d212b2505aefaa8da370319088bbccfac097b007f52ed71d8133456c8185823c8eac43c5e937953d7b6c8e68b0db1f4f03df4946a29f524875118960a35fb", "assetExec":"coins", "tokenname":"BTY", "type":1, "amount":100000000}]}'
local ip=$1 chain33_Http "$req" ${MAIN_HTTP} '.error|not' "$FUNCNAME"
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" "$?"
} }
privacy_GetPrivacyTxByAddr() { privacy_GetPrivacyTxByAddr() {
chain33_Http '{"method":"privacy.GetPrivacyTxByAddr","params":[{"tokenname":"BTY","sendRecvFlag":0,"from":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "direction":1, "count":1}]}' ${MAIN_HTTP} '.error|not' "$FUNCNAME"
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" "$?"
} }
privacy_ShowPrivacyKey() { privacy_ShowPrivacyKey() {
req='{"method":"privacy.ShowPrivacyKey", "params":[{"data":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"}]}'
local ip=$1 resok='(.error|not) and .result.showSuccessful and (.result.pubkeypair=="0a9d212b2505aefaa8da370319088bbccfac097b007f52ed71d8133456c8185823c8eac43c5e937953d7b6c8e68b0db1f4f03df4946a29f524875118960a35fb")'
req='"method":"privacy.ShowPrivacyKey", "params":[{"data":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"}]' chain33_Http "$req" ${MAIN_HTTP} "$resok" "$FUNCNAME"
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" "$?"
} }
privacy_ShowPrivacyAccountInfo() { privacy_ShowPrivacyAccountInfo() {
req='{"method":"privacy.ShowPrivacyAccountInfo", "params":[{"addr":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "token":"BTY", "displaymode":1}]}'
local ip=$1 chain33_Http "$req" ${MAIN_HTTP} '(.error|not) and (.result|[has("utxos", "ftxos", "displaymode"), true] | unique | length == 1)' "$FUNCNAME"
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" "$?"
} }
privacy_ShowPrivacyAccountSpend() { privacy_ShowPrivacyAccountSpend() {
chain33_Http '{"method":"privacy.ShowPrivacyAccountSpend", "params":[{"addr":"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "token":"BTY"}]}' ${MAIN_HTTP} '(.error|not) and .result.utxoHaveTxHashs' "$FUNCNAME"
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" "$?"
} }
privacy_RescanUtxos() { privacy_RescanUtxos() {
chain33_Http '{"method":"privacy.RescanUtxos", "params":[{"addrs":["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"], "flag":0}]}' ${MAIN_HTTP} '(.error|not) and (.result|[has("flag", "repRescanResults"), true] | unique | length == 1)' "$FUNCNAME"
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" "$?"
} }
privacy_EnablePrivacy() { privacy_EnablePrivacy() {
chain33_Http '{"method":"privacy.EnablePrivacy", "params":[{"addrs":["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"]}]}' ${MAIN_HTTP} '(.error|not) and .result.results[0].IsOK' "$FUNCNAME"
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" "$?"
} }
function run_test() { function run_test() {
local ip=$1 privacy_EnablePrivacy
privacy_EnablePrivacy "$ip" privacy_ShowPrivacyKey
privacy_ShowPrivacyKey "$ip" privacy_CreateRawTransaction
privacy_CreateRawTransaction "$ip" privacy_ShowPrivacyAccountInfo
privacy_ShowPrivacyAccountInfo "$ip" privacy_ShowPrivacyAccountSpend
privacy_ShowPrivacyAccountSpend "$ip" privacy_RescanUtxos
privacy_RescanUtxos "$ip" privacy_GetPrivacyTxByAddr
privacy_GetPrivacyTxByAddr "$ip"
} }
function main() { function main() {
MAIN_HTTP="$1"
chain33_RpcTestBegin privacy chain33_RpcTestBegin privacy
MAIN_HTTP="$1"
echo "ip=$MAIN_HTTP" echo "ip=$MAIN_HTTP"
run_test "$MAIN_HTTP" run_test
chain33_RpcTestRst privacy "$CASE_ERR" chain33_RpcTestRst privacy "$CASE_ERR"
} }
main "$1" chain33_debug_function main "$1"
This diff is collapsed.
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
# shellcheck source=/dev/null
set -e set -e
set -o pipefail set -o pipefail
MAIN_HTTP="" MAIN_HTTP=""
# shellcheck source=/dev/null
source ../dapp-test-common.sh source ../dapp-test-common.sh
# TODO # TODO
...@@ -19,7 +19,7 @@ function updateConfig() { ...@@ -19,7 +19,7 @@ function updateConfig() {
return return
fi fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}" chain33_SignAndSendTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
} }
function token_preCreate() { function token_preCreate() {
...@@ -29,7 +29,7 @@ function token_preCreate() { ...@@ -29,7 +29,7 @@ function token_preCreate() {
return return
fi fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}" chain33_SignAndSendTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
} }
function token_finish() { function token_finish() {
...@@ -39,7 +39,7 @@ function token_finish() { ...@@ -39,7 +39,7 @@ function token_finish() {
return return
fi fi
chain33_SignRawTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}" chain33_SignAndSendTx "${unsignedTx}" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" "${MAIN_HTTP}"
} }
function token_sendExec() { function token_sendExec() {
...@@ -49,7 +49,7 @@ function token_sendExec() { ...@@ -49,7 +49,7 @@ function token_sendExec() {
return return
fi fi
chain33_SignRawTx "${unsignedTx}" "$3" "${MAIN_HTTP}" chain33_SignAndSendTx "${unsignedTx}" "$3" "${MAIN_HTTP}"
} }
function createToken() { function createToken() {
...@@ -61,126 +61,45 @@ function createToken() { ...@@ -61,126 +61,45 @@ function createToken() {
} }
retrieve_Backup() { retrieve_Backup() {
echo "========== # retrieve backup begin =========="
local req='{"method":"retrieve.CreateRawRetrieveBackupTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'","delayPeriod": 61}]}' local req='{"method":"retrieve.CreateRawRetrieveBackupTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'","delayPeriod": 61}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result") tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "$retrieve2_key" ${MAIN_HTTP} "$FUNCNAME"
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}"
} }
retrieve_Prepare() { retrieve_Prepare() {
echo "========== # retrieve prepare begin =========="
local req='{"method":"retrieve.CreateRawRetrievePrepareTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}' local req='{"method":"retrieve.CreateRawRetrievePrepareTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result") tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "$retrieve1_key" ${MAIN_HTTP} "$FUNCNAME"
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}"
} }
retrieve_Perform() { retrieve_Perform() {
echo "========== # retrieve perform begin =========="
local req='{"method":"retrieve.CreateRawRetrievePerformTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}' local req='{"method":"retrieve.CreateRawRetrievePerformTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result") tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "$retrieve1_key" ${MAIN_HTTP} "$FUNCNAME"
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}"
} }
retrieve_Perform_Token() { retrieve_Perform_Token() {
echo "========== # retrieve perform begin =========="
local req='{"method":"retrieve.CreateRawRetrievePerformTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'","assets": [{"exec":"token","symbol":"'"$symbol"'"}] }]}' local req='{"method":"retrieve.CreateRawRetrievePerformTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'","assets": [{"exec":"token","symbol":"'"$symbol"'"}] }]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result") tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "$retrieve1_key" ${MAIN_HTTP} "$FUNCNAME"
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}"
} }
retrieve_Cancel() { retrieve_Cancel() {
echo "========== # retrieve cancel begin =========="
local req='{"method":"retrieve.CreateRawRetrieveCancelTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}' local req='{"method":"retrieve.CreateRawRetrieveCancelTx","params":[{"backupAddr":"'$retrieve1'","defaultAddr":"'$retrieve2'"}]}'
tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result") tx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
chain33_SignAndSendTxWait "$tx" "$retrieve2_key" ${MAIN_HTTP} "$FUNCNAME"
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}"
} }
retrieve_QueryResult() { retrieve_QueryResult() {
echo "========== # retrieve query result begin =========="
local status=$1 local status=$1
local req='{"method":"Chain33.Query","params":[{"execer":"retrieve","funcName":"GetRetrieveInfo","payload":{"backupAddress":"'$retrieve1'", "defaultAddress":"'$retrieve2'"}}]}' local req='{"method":"Chain33.Query","params":[{"execer":"retrieve","funcName":"GetRetrieveInfo","payload":{"backupAddress":"'$retrieve1'", "defaultAddress":"'$retrieve2'"}}]}'
data=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result") chain33_Http "$req" ${MAIN_HTTP} '(.result.status == '"$status"')' "$FUNCNAME"
ok=$(jq '(.status == '"$status"')' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
echo "========== # retrieve query result end =========="
} }
retrieve_QueryAssetResult() { retrieve_QueryAssetResult() {
echo "========== # retrieve query result begin =========="
local status=$1 local status=$1
local req='{"method":"Chain33.Query","params":[{"execer":"retrieve","funcName":"GetRetrieveInfo","payload":{"backupAddress":"'$retrieve1'", "defaultAddress":"'$retrieve2'","assetExec":"token", "assetSymbol":"'"$symbol"'"}}]}' 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") chain33_Http "$req" ${MAIN_HTTP} '(.result.status == '"$status"')' "$FUNCNAME"
ok=$(jq '(.status == '"$status"')' <<<"$data")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
echo "========== # retrieve query result end =========="
} }
init() { init() {
...@@ -207,7 +126,6 @@ init() { ...@@ -207,7 +126,6 @@ init() {
chain33_applyCoins "${retrieve2}" 10000000000 "${MAIN_HTTP}" chain33_applyCoins "${retrieve2}" 10000000000 "${MAIN_HTTP}"
if [ "$ispara" == true ]; then if [ "$ispara" == true ]; then
# for fee
local main_ip=${MAIN_HTTP//8901/8801} local main_ip=${MAIN_HTTP//8901/8801}
chain33_applyCoins "${retrieve1}" 1000000000 "${main_ip}" chain33_applyCoins "${retrieve1}" 1000000000 "${main_ip}"
chain33_applyCoins "${retrieve2}" 1000000000 "${main_ip}" chain33_applyCoins "${retrieve2}" 1000000000 "${main_ip}"
...@@ -244,15 +162,13 @@ function run_test() { ...@@ -244,15 +162,13 @@ function run_test() {
} }
function main() { function main() {
MAIN_HTTP="$1"
chain33_RpcTestBegin retrieve chain33_RpcTestBegin retrieve
MAIN_HTTP="$1"
echo "ip=$MAIN_HTTP" echo "ip=$MAIN_HTTP"
init init
run_test run_test
chain33_RpcTestRst retrieve "$CASE_ERR" chain33_RpcTestRst retrieve "$CASE_ERR"
} }
set -x
chain33_debug_function main "$1" chain33_debug_function main "$1"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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