Commit 3f9d8627 authored by pengjun's avatar pengjun

Merge remote-tracking branch 'upstream/master'

parents d21a8b15 8fde398d
...@@ -8,7 +8,7 @@ function dapp_test_rpc() { ...@@ -8,7 +8,7 @@ function dapp_test_rpc() {
echo "============ # dapp rpc test begin =============" echo "============ # dapp rpc test begin ============="
if [ -d dapptest ]; then if [ -d dapptest ]; then
cd dapptest || return cd dapptest || return
dir=$(find . -maxdepth 1 -type d ! -name dapptest ! -name blackwhite ! -name . | sed 's/^\.\///') dir=$(find . -maxdepth 1 -type d ! -name dapptest ! -name . | sed 's/^\.\///')
for app in $dir; do for app in $dir; do
echo "=========== # $app rpc test =============" echo "=========== # $app rpc test ============="
./"$app/${RPC_TESTFILE}" "$ip" ./"$app/${RPC_TESTFILE}" "$ip"
......
...@@ -34,7 +34,7 @@ const ( ...@@ -34,7 +34,7 @@ const (
addAct int64 = 1 //add para block action addAct int64 = 1 //add para block action
delAct int64 = 2 //reference blockstore.go, del para block action delAct int64 = 2 //reference blockstore.go, del para block action
minBlockNum = 6 //min block number startHeight before lastHeight in mainchain minBlockNum = 100 //min block number startHeight before lastHeight in mainchain
) )
var ( var (
...@@ -198,13 +198,14 @@ func (client *client) InitBlock() { ...@@ -198,13 +198,14 @@ func (client *client) InitBlock() {
} }
if block == nil { if block == nil {
startSeq := client.GetStartSeq(startHeight) startSeq, mainHash := client.GetStartSeq(startHeight)
// 创世区块 // 创世区块
newblock := &types.Block{} newblock := &types.Block{}
newblock.Height = 0 newblock.Height = 0
newblock.BlockTime = genesisBlockTime newblock.BlockTime = genesisBlockTime
newblock.ParentHash = zeroHash[:] newblock.ParentHash = zeroHash[:]
newblock.MainHash = zeroHash[:] newblock.MainHash = mainHash
newblock.MainHeight = startHeight
tx := client.CreateGenesisTx() tx := client.CreateGenesisTx()
newblock.Txs = tx newblock.Txs = tx
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs) newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
...@@ -219,9 +220,9 @@ func (client *client) InitBlock() { ...@@ -219,9 +220,9 @@ func (client *client) InitBlock() {
} }
// GetStartSeq get startSeq in mainchain // GetStartSeq get startSeq in mainchain
func (client *client) GetStartSeq(height int64) int64 { func (client *client) GetStartSeq(height int64) (int64, []byte) {
if height == 0 { if height == 0 {
return 0 return 0, nil
} }
lastHeight, err := client.GetLastHeightOnMainChain() lastHeight, err := client.GetLastHeightOnMainChain()
...@@ -248,12 +249,12 @@ func (client *client) GetStartSeq(height int64) int64 { ...@@ -248,12 +249,12 @@ func (client *client) GetStartSeq(height int64) int64 {
hint.Stop() hint.Stop()
plog.Info(fmt.Sprintf("lastHeight more than %d blocks after startHeight", minBlockNum), "lastHeight", lastHeight, "startHeight", height) plog.Info(fmt.Sprintf("lastHeight more than %d blocks after startHeight", minBlockNum), "lastHeight", lastHeight, "startHeight", height)
seq, err := client.GetSeqByHeightOnMainChain(height) seq, hash, err := client.GetSeqByHeightOnMainChain(height)
if err != nil { if err != nil {
panic(err) panic(err)
} }
plog.Info("the start sequence in mainchain", "startHeight", height, "startSeq", seq) plog.Info("the start sequence in mainchain", "startHeight", height, "startSeq", seq)
return seq return seq, hash
} }
func (client *client) CreateGenesisTx() (ret []*types.Transaction) { func (client *client) CreateGenesisTx() (ret []*types.Transaction) {
...@@ -306,33 +307,42 @@ func (client *client) GetBlockByHeight(height int64) (*types.Block, error) { ...@@ -306,33 +307,42 @@ func (client *client) GetBlockByHeight(height int64) (*types.Block, error) {
return blockDetails.Items[0].Block, nil return blockDetails.Items[0].Block, nil
} }
func (client *client) getLastBlockInfo() (int64, *types.Block, error) { // 获取上一个平行链对应主链seq,hash信息
lastBlock, err := client.RequestLastBlock() // 对于平行链创世区块特殊场景:
// 1,创世区块seq从-1开始,也就是从主链0高度同步区块,主链seq从0开始,平行链对seq=0的区块校验时候做特殊处理,不校验parentHash
// 2,创世区块seq不是-1, 也就是从主链seq=n高度同步区块,此时创世区块记录了起始高度对应的主链hash,通过hash获取当前seq,然后创世区块需要倒退一个seq,lastSeq=n-1,
// 因为对于云端主链节点,创世区块记录seq在不同主链节点上差异很大,通过记录的主链hash获取的真实seq-1来使用,主链hash使用对应区块的parenthash做校验目的
func (client *client) getLastBlockMainInfo() (int64, []byte, error) {
lastSeq, lastBlock, err := client.getLastBlockInfo()
if err != nil { if err != nil {
plog.Error("Parachain RequestLastBlock fail", "err", err)
return -2, nil, err return -2, nil, err
} }
blockedSeq, err := client.GetBlockedSeq(lastBlock.Hash()) if lastBlock.Height == 0 && lastSeq > -1 {
mainBlock, err := client.GetBlockOnMainByHash(lastBlock.MainHash)
if err != nil { if err != nil {
plog.Error("Parachain GetBlockedSeq fail", "err", err)
return -2, nil, err return -2, nil, err
} }
// 平行链创世区块特殊场景: mainSeq, err := client.GetSeqByHashOnMainChain(lastBlock.MainHash)
// 1,创世区块seq从-1开始,也就是从主链0高度同步区块,主链seq从0开始,平行链对seq=0的区块做特殊处理,不校验parentHash
// 2,创世区块seq不是-1, 也就是从主链seq=n高度同步区块,此时创世区块倒退一个seq,blockedSeq=n-1,
// 由于创世区块本身没有记录主块hash,需要通过最初记录的seq获取,有可能n-1 seq 是回退block 获取的Hash不对,这里获取主链第n seq的parentHash
// 在genesis create时候直接设mainhash也可以,但是会导致已有平行链所有block hash变化
if lastBlock.Height == 0 && blockedSeq > -1 {
main, err := client.GetBlockOnMainBySeq(blockedSeq + 1)
if err != nil { if err != nil {
return -2, nil, err return -2, nil, err
} }
lastBlock.MainHash = main.Detail.Block.ParentHash return mainSeq - 1, mainBlock.ParentHash, nil
lastBlock.MainHeight = main.Detail.Block.Height - 1
return blockedSeq, lastBlock, nil
} }
return lastSeq, lastBlock.MainHash, nil
}
func (client *client) getLastBlockInfo() (int64, *types.Block, error) {
lastBlock, err := client.RequestLastBlock()
if err != nil {
plog.Error("Parachain RequestLastBlock fail", "err", err)
return -2, nil, err
}
blockedSeq, err := client.GetBlockedSeq(lastBlock.Hash())
if err != nil {
plog.Error("Parachain GetBlockedSeq fail", "err", err)
return -2, nil, err
}
return blockedSeq, lastBlock, nil return blockedSeq, lastBlock, nil
} }
...@@ -365,13 +375,13 @@ func (client *client) GetLastSeqOnMainChain() (int64, error) { ...@@ -365,13 +375,13 @@ func (client *client) GetLastSeqOnMainChain() (int64, error) {
return seq.Data, nil return seq.Data, nil
} }
func (client *client) GetSeqByHeightOnMainChain(height int64) (int64, error) { func (client *client) GetSeqByHeightOnMainChain(height int64) (int64, []byte, error) {
hash, err := client.GetHashByHeightOnMainChain(height) hash, err := client.GetHashByHeightOnMainChain(height)
if err != nil { if err != nil {
return -1, err return -1, nil, err
} }
seq, err := client.GetSeqByHashOnMainChain(hash) seq, err := client.GetSeqByHashOnMainChain(hash)
return seq, err return seq, hash, err
} }
func (client *client) GetHashByHeightOnMainChain(height int64) ([]byte, error) { func (client *client) GetHashByHeightOnMainChain(height int64) ([]byte, error) {
...@@ -410,6 +420,16 @@ func (client *client) GetBlockOnMainBySeq(seq int64) (*types.BlockSeq, error) { ...@@ -410,6 +420,16 @@ func (client *client) GetBlockOnMainBySeq(seq int64) (*types.BlockSeq, error) {
return blockSeq, nil return blockSeq, nil
} }
func (client *client) GetBlockOnMainByHash(hash []byte) (*types.Block, error) {
blocks, err := client.grpcClient.GetBlockByHashes(context.Background(), &types.ReqHashes{Hashes: [][]byte{hash}})
if err != nil || blocks.Items[0] == nil {
plog.Error("GetBlockOnMainByHash Not found", "blockhash", common.ToHex(hash))
return nil, err
}
return blocks.Items[0].Block, nil
}
// preBlockHash to identify the same main node // preBlockHash to identify the same main node
func (client *client) RequestTx(currSeq int64, preMainBlockHash []byte) ([]*types.Transaction, *types.BlockSeq, error) { func (client *client) RequestTx(currSeq int64, preMainBlockHash []byte) ([]*types.Transaction, *types.BlockSeq, error) {
plog.Debug("Para consensus RequestTx") plog.Debug("Para consensus RequestTx")
...@@ -466,13 +486,13 @@ func (client *client) RequestTx(currSeq int64, preMainBlockHash []byte) ([]*type ...@@ -466,13 +486,13 @@ func (client *client) RequestTx(currSeq int64, preMainBlockHash []byte) ([]*type
// for genesis seq=-1 scenario, mainHash not care, as the 0 seq instead of -1 // for genesis seq=-1 scenario, mainHash not care, as the 0 seq instead of -1
// not seq=-1 scenario, mainHash needed // not seq=-1 scenario, mainHash needed
func (client *client) syncFromGenesisBlock() (int64, []byte, error) { func (client *client) syncFromGenesisBlock() (int64, []byte, error) {
lastSeq, lastBlock, err := client.getLastBlockInfo() lastSeq, lastMainHash, err := client.getLastBlockMainInfo()
if err != nil { if err != nil {
plog.Error("Parachain getLastBlockInfo fail", "err", err) plog.Error("Parachain getLastBlockInfo fail", "err", err)
return -2, nil, err return -2, nil, err
} }
plog.Info("syncFromGenesisBlock sync from height 0") plog.Info("syncFromGenesisBlock sync from height 0")
return lastSeq + 1, lastBlock.MainHash, nil return lastSeq + 1, lastMainHash, nil
} }
// search base on para block but not last MainBlockHash, last MainBlockHash can not back tracing // search base on para block but not last MainBlockHash, last MainBlockHash can not back tracing
...@@ -561,12 +581,11 @@ func (client *client) removeBlocks(endHeight int64) error { ...@@ -561,12 +581,11 @@ func (client *client) removeBlocks(endHeight int64) error {
func (client *client) CreateBlock() { func (client *client) CreateBlock() {
incSeqFlag := true incSeqFlag := true
//system startup, take the last added block's seq is ok //system startup, take the last added block's seq is ok
currSeq, lastBlock, err := client.getLastBlockInfo() currSeq, lastSeqMainHash, err := client.getLastBlockMainInfo()
if err != nil { if err != nil {
plog.Error("Parachain getLastBlockInfo fail", "err", err.Error()) plog.Error("Parachain getLastBlockInfo fail", "err", err.Error())
return return
} }
lastSeqMainHash := lastBlock.MainHash
for { for {
//should be lastSeq but not LastBlockSeq as del block case the seq is not equal //should be lastSeq but not LastBlockSeq as del block case the seq is not equal
lastSeq, err := client.GetLastSeq() lastSeq, err := client.GetLastSeq()
...@@ -660,15 +679,6 @@ func (client *client) addMinerTx(preStateHash []byte, block *types.Block, main * ...@@ -660,15 +679,6 @@ func (client *client) addMinerTx(preStateHash []byte, block *types.Block, main *
MainBlockHeight: main.Detail.Block.Height, MainBlockHeight: main.Detail.Block.Height,
} }
//获取当前区块的所有原始tx hash 和跨链hash作为bitmap base hashs,因为有可能在执行过程中有些tx 执行error被剔除掉
if main.Detail.Block.Height >= mainForkParacrossCommitTx {
for _, tx := range txs {
status.TxHashs = append(status.TxHashs, tx.Hash())
}
txHashs := paraexec.FilterParaCrossTxHashes(types.GetTitle(), txs)
status.CrossTxHashs = append(status.CrossTxHashs, txHashs...)
}
tx, err := pt.CreateRawMinerTx(&pt.ParacrossMinerAction{ tx, err := pt.CreateRawMinerTx(&pt.ParacrossMinerAction{
Status: status, Status: status,
IsSelfConsensus: isParaSelfConsensusForked(status.MainBlockHeight), IsSelfConsensus: isParaSelfConsensusForked(status.MainBlockHeight),
......
...@@ -13,8 +13,12 @@ import ( ...@@ -13,8 +13,12 @@ import (
"testing" "testing"
"time" "time"
apimocks "github.com/33cn/chain33/client/mocks"
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/queue"
qmocks "github.com/33cn/chain33/queue/mocks"
drivers "github.com/33cn/chain33/system/consensus"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
typesmocks "github.com/33cn/chain33/types/mocks" typesmocks "github.com/33cn/chain33/types/mocks"
paraexec "github.com/33cn/plugin/plugin/dapp/paracross/executor" paraexec "github.com/33cn/plugin/plugin/dapp/paracross/executor"
...@@ -220,3 +224,43 @@ func TestAddMinerTx(t *testing.T) { ...@@ -220,3 +224,43 @@ func TestAddMinerTx(t *testing.T) {
assert.False(t, ret) assert.False(t, ret)
} }
func initBlock() {
println("initblock")
}
func TestGetLastBlockInfo(t *testing.T) {
para := new(client)
baseCli := drivers.NewBaseClient(&types.Consensus{Name: "name"})
para.BaseClient = baseCli
grpcClient := &typesmocks.Chain33Client{}
qClient := &qmocks.Client{}
para.InitClient(qClient, initBlock)
api := &apimocks.QueueProtocolAPI{}
para.SetAPI(api)
para.grpcClient = grpcClient
block := &types.Block{Height: 0}
msg := queue.NewMessage(0, "", 1, block)
qClient.On("NewMessage", mock.Anything, mock.Anything, mock.Anything).Return(msg)
qClient.On("Send", mock.Anything, mock.Anything).Return(nil)
qClient.On("Wait", mock.Anything).Return(msg, nil)
api.On("GetSequenceByHash", mock.Anything).Return(&types.Int64{Data: int64(1)}, nil)
mainBlock := &types.Block{ParentHash: []byte("phash")}
mainDetail := &types.BlockDetail{Block: mainBlock}
blocks := &types.BlockDetails{}
blocks.Items = append(blocks.Items, mainDetail)
grpcClient.On("GetBlockByHashes", mock.Anything, mock.Anything).Return(blocks, nil)
grpcClient.On("GetSequenceByHash", mock.Anything, mock.Anything).Return(&types.Int64{Data: int64(10)}, nil)
mainSeq, hash, err := para.getLastBlockMainInfo()
assert.NoError(t, err)
assert.Equal(t, int64(9), mainSeq)
assert.Equal(t, []byte("phash"), hash)
}
...@@ -19,7 +19,7 @@ import ( ...@@ -19,7 +19,7 @@ import (
var ( var (
consensusInterval = 16 //about 1 new block interval consensusInterval = 16 //about 1 new block interval
minerInterval = 2 minerInterval = 5
) )
type commitMsgClient struct { type commitMsgClient struct {
...@@ -130,6 +130,9 @@ out: ...@@ -130,6 +130,9 @@ out:
plog.Error("para commit msg read tick", "err", err.Error()) plog.Error("para commit msg read tick", "err", err.Error())
continue continue
} }
if len(status) == 0 {
continue
}
signTx, count, err := client.calcCommitMsgTxs(status) signTx, count, err := client.calcCommitMsgTxs(status)
if err != nil || signTx == nil { if err != nil || signTx == nil {
...@@ -426,9 +429,20 @@ func (client *commitMsgClient) getNodeStatus(start, end int64) ([]*pt.ParacrossN ...@@ -426,9 +429,20 @@ func (client *commitMsgClient) getNodeStatus(start, end int64) ([]*pt.ParacrossN
nodeList[block.Block.Height].StateHash = block.Block.StateHash nodeList[block.Block.Height].StateHash = block.Block.StateHash
} }
var needSentTxs uint32
for i := 0; i < int(count); i++ { for i := 0; i < int(count); i++ {
ret = append(ret, nodeList[req.Start+int64(i)]) ret = append(ret, nodeList[req.Start+int64(i)])
needSentTxs += nodeList[req.Start+int64(i)].NonCommitTxCounts
} }
//1.如果是只有commit tx的空块,推迟发送,直到等到一个完全没有commit tx的空块或者其他tx的块
//2,如果20个块都是 commit tx的空块,20个块打包一次发送,尽量减少commit tx造成的空块
//3,如果形如xxoxx的块排列,x代表commit空块,o代表实际的块,即只要不全部是commit块,也要全部打包一起发出去
//如果=0 意味着全部是paracross commit tx,延迟发送
if needSentTxs == 0 && count < types.TxGroupMaxCount {
plog.Debug("para commitmsg getNodeStatus all self consensus commit tx,send delay", "start", start, "end", end)
return nil, nil
}
return ret, nil return ret, nil
} }
......
...@@ -710,13 +710,15 @@ func (client *Client) createBlock() (*types.Block, *types.Block) { ...@@ -710,13 +710,15 @@ func (client *Client) createBlock() (*types.Block, *types.Block) {
func (client *Client) updateBlock(block *types.Block, txHashList [][]byte) (*types.Block, *types.Block, [][]byte) { func (client *Client) updateBlock(block *types.Block, txHashList [][]byte) (*types.Block, *types.Block, [][]byte) {
lastBlock := client.GetCurrentBlock() lastBlock := client.GetCurrentBlock()
newblock := *block newblock := *block
//需要去重复tx newblock.BlockTime = types.Now().Unix()
//需要去重复tx并删除过期tx交易
if lastBlock.Height != newblock.Height-1 { if lastBlock.Height != newblock.Height-1 {
newblock.Txs = client.CheckTxDup(newblock.Txs) newblock.Txs = client.CheckTxDup(newblock.Txs)
newblock.Txs = client.CheckTxExpire(newblock.Txs, lastBlock.Height+1, newblock.BlockTime)
} }
newblock.ParentHash = lastBlock.Hash() newblock.ParentHash = lastBlock.Hash()
newblock.Height = lastBlock.Height + 1 newblock.Height = lastBlock.Height + 1
newblock.BlockTime = types.Now().Unix()
cfg := types.GetP(newblock.Height) cfg := types.GetP(newblock.Height)
var txs []*types.Transaction var txs []*types.Transaction
if len(newblock.Txs) < int(cfg.MaxTxNumber-1) { if len(newblock.Txs) < int(cfg.MaxTxNumber-1) {
......
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2128 # shellcheck disable=SC2128
set -e set +e
set -o pipefail set -o pipefail
set -x
MAIN_HTTP="" MAIN_HTTP=""
CASE_ERR="" CASE_ERR=""
...@@ -24,6 +25,19 @@ glAddr="" ...@@ -24,6 +25,19 @@ glAddr=""
gameAddr1="" gameAddr1=""
gameAddr2="" gameAddr2=""
gameAddr3="" gameAddr3=""
bwExecAddr=""
init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ipara=$ispara"
if [ "$ispara" == true ]; then
bwExecAddr=$(curl -ksd '{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"user.p.para.blackwhite"}]}' ${MAIN_HTTP} | jq -r ".result")
else
bwExecAddr=$(curl -ksd '{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"blackwhite"}]}' ${MAIN_HTTP} | jq -r ".result")
fi
echo "bwExecAddr=$bwExecAddr"
}
chain33_NewAccount() { chain33_NewAccount() {
label=$1 label=$1
...@@ -58,8 +72,9 @@ chain33_SendToAddress() { ...@@ -58,8 +72,9 @@ chain33_SendToAddress() {
from=$1 from=$1
to=$2 to=$2
amount=$3 amount=$3
http=$4
note="test" note="test"
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.SendToAddress","params":[{"from":"'"$from"'","to":"'"$to"'","amount":'"$amount"',"note":"'"$note"'"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP}) resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.SendToAddress","params":[{"from":"'"$from"'","to":"'"$to"'","amount":'"$amount"',"note":"'"$note"'"}]}' -H 'content-type:text/plain;' "${http}")
ok=$(jq '(.error|not)' <<<"$resp") ok=$(jq '(.error|not)' <<<"$resp")
[ "$ok" == true ] [ "$ok" == true ]
rst=$? rst=$?
...@@ -195,17 +210,24 @@ function run_testcases() { ...@@ -195,17 +210,24 @@ function run_testcases() {
#给每个账户分别转帐 #给每个账户分别转帐
origAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv" origAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
chain33_SendToAddress "${origAddr}" "${gameAddr1}" 1000000000
chain33_SendToAddress "${origAddr}" "${gameAddr2}" 1000000000 #主链中相应账户需要转帐
chain33_SendToAddress "${origAddr}" "${gameAddr3}" 1000000000 M_HTTP=${MAIN_HTTP//8901/8801}
chain33_SendToAddress "${origAddr}" "${gameAddr1}" 1000000000 "${M_HTTP}"
chain33_SendToAddress "${origAddr}" "${gameAddr2}" 1000000000 "${M_HTTP}"
chain33_SendToAddress "${origAddr}" "${gameAddr3}" 1000000000 "${M_HTTP}"
#平行链相应账户需要转帐
chain33_SendToAddress "${origAddr}" "${gameAddr1}" 1000000000 "${MAIN_HTTP}"
chain33_SendToAddress "${origAddr}" "${gameAddr2}" 1000000000 "${MAIN_HTTP}"
chain33_SendToAddress "${origAddr}" "${gameAddr3}" 1000000000 "${MAIN_HTTP}"
block_wait 1 block_wait 1
#给游戏合约中转帐 #给游戏合约中转帐
bwExecAddr="146wei89zoX5TNQKATBJmduNPEtSKTXi1z" chain33_SendToAddress "${gameAddr1}" "${bwExecAddr}" 500000000 "${MAIN_HTTP}"
chain33_SendToAddress "${gameAddr1}" "${bwExecAddr}" 500000000 chain33_SendToAddress "${gameAddr2}" "${bwExecAddr}" 500000000 "${MAIN_HTTP}"
chain33_SendToAddress "${gameAddr2}" "${bwExecAddr}" 500000000 chain33_SendToAddress "${gameAddr3}" "${bwExecAddr}" 500000000 "${MAIN_HTTP}"
chain33_SendToAddress "${gameAddr3}" "${bwExecAddr}" 500000000
block_wait 1 block_wait 1
blackwhite_BlackwhiteCreateTx "${gameAddr1}" blackwhite_BlackwhiteCreateTx "${gameAddr1}"
...@@ -233,6 +255,7 @@ function main() { ...@@ -233,6 +255,7 @@ function main() {
MAIN_HTTP="$1" MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP" echo "main_ip=$MAIN_HTTP"
init
run_testcases run_testcases
if [ -n "$CASE_ERR" ]; then if [ -n "$CASE_ERR" ]; then
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package rpc package rpc
import ( import (
context "golang.org/x/net/context" "golang.org/x/net/context"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
bw "github.com/33cn/plugin/plugin/dapp/blackwhite/types" bw "github.com/33cn/plugin/plugin/dapp/blackwhite/types"
...@@ -19,7 +19,7 @@ func (c *channelClient) Create(ctx context.Context, head *bw.BlackwhiteCreate) ( ...@@ -19,7 +19,7 @@ func (c *channelClient) Create(ctx context.Context, head *bw.BlackwhiteCreate) (
tx := &types.Transaction{ tx := &types.Transaction{
Payload: types.Encode(val), Payload: types.Encode(val),
} }
data, err := types.FormatTxEncode(string(bw.ExecerBlackwhite), tx) data, err := types.FormatTxEncode(types.ExecName(string(bw.ExecerBlackwhite)), tx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -34,7 +34,7 @@ func (c *channelClient) Show(ctx context.Context, head *bw.BlackwhiteShow) (*typ ...@@ -34,7 +34,7 @@ func (c *channelClient) Show(ctx context.Context, head *bw.BlackwhiteShow) (*typ
tx := &types.Transaction{ tx := &types.Transaction{
Payload: types.Encode(val), Payload: types.Encode(val),
} }
data, err := types.FormatTxEncode(string(bw.ExecerBlackwhite), tx) data, err := types.FormatTxEncode(types.ExecName(string(bw.ExecerBlackwhite)), tx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -49,7 +49,7 @@ func (c *channelClient) Play(ctx context.Context, head *bw.BlackwhitePlay) (*typ ...@@ -49,7 +49,7 @@ func (c *channelClient) Play(ctx context.Context, head *bw.BlackwhitePlay) (*typ
tx := &types.Transaction{ tx := &types.Transaction{
Payload: types.Encode(val), Payload: types.Encode(val),
} }
data, err := types.FormatTxEncode(string(bw.ExecerBlackwhite), tx) data, err := types.FormatTxEncode(types.ExecName(string(bw.ExecerBlackwhite)), tx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -64,7 +64,7 @@ func (c *channelClient) TimeoutDone(ctx context.Context, head *bw.BlackwhiteTime ...@@ -64,7 +64,7 @@ func (c *channelClient) TimeoutDone(ctx context.Context, head *bw.BlackwhiteTime
tx := &types.Transaction{ tx := &types.Transaction{
Payload: types.Encode(val), Payload: types.Encode(val),
} }
data, err := types.FormatTxEncode(string(bw.ExecerBlackwhite), tx) data, err := types.FormatTxEncode(types.ExecName(string(bw.ExecerBlackwhite)), tx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/usr/bin/env bash
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
chmod +x ./build/test-rpc.sh
cp ./build/test-rpc.sh "${OUT_TESTDIR}"
This diff is collapsed.
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/33cn/chain33/pluginmgr" "github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/evm/commands" "github.com/33cn/plugin/plugin/dapp/evm/commands"
"github.com/33cn/plugin/plugin/dapp/evm/executor" "github.com/33cn/plugin/plugin/dapp/evm/executor"
"github.com/33cn/plugin/plugin/dapp/evm/rpc"
"github.com/33cn/plugin/plugin/dapp/evm/types" "github.com/33cn/plugin/plugin/dapp/evm/types"
) )
...@@ -17,6 +18,6 @@ func init() { ...@@ -17,6 +18,6 @@ func init() {
ExecName: executor.GetName(), ExecName: executor.GetName(),
Exec: executor.Init, Exec: executor.Init,
Cmd: commands.EvmCmd, Cmd: commands.EvmCmd,
RPC: nil, RPC: rpc.Init,
}) })
} }
...@@ -147,3 +147,35 @@ message EvmQueryResp { ...@@ -147,3 +147,35 @@ message EvmQueryResp {
string rawData = 4; string rawData = 4;
string jsonData = 5; string jsonData = 5;
} }
message EvmContractCreateReq {
string code = 1;
int64 fee = 2;
string note = 3;
string alias = 4;
string caller = 5;
string abi = 6;
string expire = 7;
string paraName = 8;
}
message EvmContractCallReq {
uint64 amount = 1;
string code = 2;
int64 fee = 3;
string note = 4;
string caller = 5;
string abi = 6;
string exec = 7;
string expire = 8;
string paraName = 9;
}
message EvmContractTransferReq {
string caller = 1;
float amount = 2;
string exec = 3;
string expire = 4;
bool isWithdraw = 5;
string paraName = 6;
}
\ 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 rpc
import (
"context"
"encoding/hex"
"github.com/33cn/chain33/types"
evm "github.com/33cn/plugin/plugin/dapp/evm/types"
)
// EvmCreateTx 创建Evm合约接口
func (c *Jrpc) EvmCreateTx(parm *evm.EvmContractCreateReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Create(context.Background(), *parm)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// EvmCallTx 调用Evm合约接口
func (c *Jrpc) EvmCallTx(parm *evm.EvmContractCallReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Call(context.Background(), *parm)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// EvmTransferTx Evm转账接口
func (c *Jrpc) EvmTransferTx(parm *evm.EvmContractTransferReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Transfer(context.Background(), *parm, false)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// EvmWithdrawTx Evm转账接口
func (c *Jrpc) EvmWithdrawTx(parm *evm.EvmContractTransferReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Transfer(context.Background(), *parm, true)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"context"
"fmt"
"math/rand"
"os"
"time"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
cty "github.com/33cn/chain33/system/dapp/coins/types"
"github.com/33cn/chain33/types"
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
)
// CreateEvmCallTx 创建未签名的调用evm交易
func (c *channelClient) Create(ctx context.Context, in evmtypes.EvmContractCreateReq) (*types.UnsignTx, error) {
bCode, err := common.FromHex(in.Code)
if err != nil {
fmt.Fprintln(os.Stderr, "parse evm code error", err)
return nil, err
}
action := evmtypes.EVMContractAction{Amount: 0, Code: bCode, GasLimit: 0, GasPrice: 0, Note: in.Note, Abi: in.Abi}
execer := types.ExecName(in.ParaName + "evm")
addr := address.ExecAddress(types.ExecName(in.ParaName + "evm"))
tx := &types.Transaction{Execer: []byte(execer), Payload: types.Encode(&action), Fee: 0, To: addr}
tx.Fee, _ = tx.GetRealFee(types.GInt("MinFee"))
if tx.Fee < in.Fee {
tx.Fee += in.Fee
}
random := rand.New(rand.NewSource(time.Now().UnixNano()))
tx.Nonce = random.Int63()
txHex := types.Encode(tx)
return &types.UnsignTx{Data: txHex}, nil
}
func (c *channelClient) Call(ctx context.Context, in evmtypes.EvmContractCallReq) (*types.UnsignTx, error) {
amountInt64 := in.Amount * 1e4 * 1e4
feeInt64 := in.Fee * 1e4 * 1e4
toAddr := address.ExecAddress(in.Exec)
bCode, err := common.FromHex(in.Code)
if err != nil {
fmt.Fprintln(os.Stderr, "parse evm code error", err)
return nil, err
}
action := evmtypes.EVMContractAction{Amount: amountInt64, Code: bCode, GasLimit: 0, GasPrice: 0, Note: in.Note, Abi: in.Abi}
tx := &types.Transaction{Execer: []byte(in.Exec), Payload: types.Encode(&action), Fee: 0, To: toAddr}
tx.Fee, _ = tx.GetRealFee(types.GInt("MinFee"))
if tx.Fee < feeInt64 {
tx.Fee += feeInt64
}
random := rand.New(rand.NewSource(time.Now().UnixNano()))
tx.Nonce = random.Int63()
txHex := types.Encode(tx)
return &types.UnsignTx{Data: txHex}, nil
}
func (c *channelClient) Transfer(ctx context.Context, in evmtypes.EvmContractTransferReq, isWithdraw bool) (*types.UnsignTx, error) {
var tx *types.Transaction
transfer := &cty.CoinsAction{}
amountInt64 := int64(in.Amount*1e4) * 1e4
execName := in.Exec
if isWithdraw {
transfer.Value = &cty.CoinsAction_Withdraw{Withdraw: &types.AssetsWithdraw{Amount: amountInt64, ExecName: execName, To: address.ExecAddress(execName)}}
transfer.Ty = cty.CoinsActionWithdraw
} else {
transfer.Value = &cty.CoinsAction_TransferToExec{TransferToExec: &types.AssetsTransferToExec{Amount: amountInt64, ExecName: execName, To: address.ExecAddress(execName)}}
transfer.Ty = cty.CoinsActionTransferToExec
}
if in.ParaName == "" {
tx = &types.Transaction{Execer: []byte(types.ExecName(in.ParaName + "coins")), Payload: types.Encode(transfer), To: address.ExecAddress(execName)}
} else {
tx = &types.Transaction{Execer: []byte(types.ExecName(in.ParaName + "coins")), Payload: types.Encode(transfer), To: address.ExecAddress(types.ExecName(in.ParaName + "coins"))}
}
var err error
tx.Fee, err = tx.GetRealFee(types.GInt("MinFee"))
if err != nil {
return nil, err
}
random := rand.New(rand.NewSource(time.Now().UnixNano()))
tx.Nonce = random.Int63()
txHex := types.Encode(tx)
return &types.UnsignTx{Data: txHex}, nil
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"github.com/33cn/chain33/rpc/types"
)
// Jrpc json rpc struct
type Jrpc struct {
cli *channelClient
}
// Grpc grpc struct
type Grpc struct {
*channelClient
}
type channelClient struct {
types.ChannelClient
}
// Init init grpc param
func Init(name string, s types.RPCServer) {
cli := &channelClient{}
grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc)
}
This diff is collapsed.
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/usr/bin/env bash
output_dir=${1}
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${output_dir}/$strapp"
[ ! -e "${OUT_DIR}" ] && mkdir -p "${OUT_DIR}"
# shellcheck disable=SC2086
cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
cp ./build/test-rpc.sh "${OUT_TESTDIR}"
cp ../executor/test.js "${OUT_TESTDIR}"
#!/usr/bin/env bash
# shellcheck disable=SC2128
MAIN_HTTP=""
CASE_ERR=""
#color
RED='\033[1;31m'
GRE='\033[1;32m'
NOC='\033[0m'
# base functions
# $2=0 means true, other false
function echo_rst() {
if [ "$2" -eq 0 ]; then
echo -e "${GRE}$1 ok${NOC}"
else
echo -e "${RED}$1 fail${NOC}"
CASE_ERR="err"
fi
}
function Chain33_SendToAddress() {
local from="$1"
local to="$2"
local amount=$3
local req='{"method":"Chain33.SendToAddress", "params":[{"from":"'"$from"'","to":"'"$to"'", "amount":'"$amount"', "note":"test\n"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.hash|length==66)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
hash=$(jq '(.result.hash)' <<<"$resp")
echo "hash=$hash"
# query_tx "$hash"
}
function sign_raw_tx() {
txHex="$1"
priKey="$2"
req='{"method":"Chain33.SignRawTx","params":[{"privkey":"'"$priKey"'","txHex":"'"$txHex"'","expire":"120s"}]}'
# echo "#request SignRawTx: $req"
resp=$(curl -ksd "$req" ${MAIN_HTTP})
signedTx=$(jq -r ".result" <<<"$resp")
# echo "signedTx=$signedTx"
if [ "$signedTx" != null ]; then
send_tx "$signedTx"
else
echo "signedTx null error"
fi
}
function send_tx() {
signedTx=$1
req='{"method":"Chain33.SendTransaction","params":[{"token":"BTY","data":"'"$signedTx"'"}]}'
# echo "#request sendTx: $req"
# curl -ksd "$req" ${MAIN_HTTP}
resp=$(curl -ksd "$req" ${MAIN_HTTP})
err=$(jq '(.error)' <<<"$resp")
txhash=$(jq -r ".result" <<<"$resp")
if [ "$err" == null ]; then
# echo "tx hash: $txhash"
query_tx "$txhash"
else
echo "send tx error:$err"
fi
}
function block_wait() {
req='{"method":"Chain33.GetLastHeader","params":[{}]}'
cur_height=$(curl -ksd "$req" ${MAIN_HTTP} | jq ".result.height")
expect=$((cur_height + ${1}))
local count=0
while true; do
new_height=$(curl -ksd "$req" ${MAIN_HTTP} | jq ".result.height")
if [ "${new_height}" -ge "${expect}" ]; then
break
fi
count=$((count + 1))
sleep 1
done
echo "wait new block $count s, cur height=$expect,old=$cur_height"
}
function query_tx() {
block_wait 1
txhash="$1"
# echo "req=$req"
local times=10
while true; do
req='{"method":"Chain33.QueryTransaction","params":[{"hash":"'"$txhash"'"}]}'
ret=$(curl -ksd "$req" ${MAIN_HTTP})
tx=$(jq -r ".result.tx.hash" <<<"$ret")
echo "====query tx= ${1}, return=$ret "
if [ "${tx}" != "${1}" ]; then
block_wait 1
times=$((times - 1))
if [ $times -le 0 ]; then
echo "====query tx=$1 failed"
echo "req=$req"
curl -ksd "$req" ${MAIN_HTTP}
exit 1
fi
else
exec_ok=$(jq '(.result.receipt.tyName == "ExecOk")' <<<"$ret")
[ "$exec_ok" == true ]
echo_rst "query tx=$1" $?
break
fi
done
}
function init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
beneficiary=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
beneficiary_key=0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01
#owner=14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
#owner_key=CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944
echo "ipara=$ispara"
manager_name="manage"
exec_name="jsvm"
game="game"
user_game="user.${exec_name}.${game}"
super_manager=0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01
if [ "$ispara" == true ]; then
exec_name="user.p.para."${exec_name}
manager_name="user.p.para."${manager_name}
user_game="user.p.para."${user_game}
super_manager=0xc34b5d9d44ac7b754806f761d3d4d2c4fe5214f6b074c19f069c4f5c2a29c8cc
fi
exec_addr=$(curl -ksd '{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"'${exec_name}'"}]}' ${MAIN_HTTP} | jq -r ".result")
echo "exec_addr=${exec_addr}"
# json 中 \n \t 需要转意, " 影响json的结构, 需要转意
jsCode=$(sed 's/"/\\"/g' <./js/test.js | sed ':a;N;s/\n/\\n/g;ta' | sed 's/\t/\\t/g')
}
function configJSCreator() {
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${manager_name}'","actionName":"Modify","payload":{"key":"js-creator","op":"add", "value" : "'${beneficiary}'"}}]}'
echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${super_manager}"
}
function createJSContract() {
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${exec_name}'","actionName":"Create","payload":{"name":"'${game}'","code":"'${jsCode}'"}}]}'
echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${beneficiary_key}"
}
function callJS() {
#the_exec=
req='{"jsonrpc": "2.0", "method" : "Chain33.CreateTransaction" , "params":[{"execer":"'${user_game}'","actionName":"Call","payload":{"name":"'${game}'","funcname":"hello", "args" : "{}"}}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${beneficiary_key}"
}
function queryJS() {
req='{"jsonrpc": "2.0", "method" : "Chain33.Query" , "params":[{"execer":"'${user_game}'","funcName":"Query","payload":{"name":"'${game}'","funcname":"hello", "args" : "{}"}}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
function run_testcases() {
configJSCreator
createJSContract
callJS
queryJS
}
function debug_function() {
set -x
eval "$@"
set +x
}
function rpc_test() {
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
init
run_testcases
if [ -n "$CASE_ERR" ]; then
echo "=======js rpc test error ==========="
exit 1
else
echo "====== js rpc test pass ==========="
fi
}
rpc_test "$1"
...@@ -7,14 +7,28 @@ import ( ...@@ -7,14 +7,28 @@ import (
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto" "github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
) )
func (c *js) userExecName(name string, local bool) string {
execer := "user." + ptypes.JsX + "." + name
if local {
execer = types.ExecName(execer)
}
return execer
}
// execName 在create 时为 jsvm
// 在 call 时为 user.jsvm.game
func (c *js) checkTxExec(txExec string, execName string) bool {
return txExec == types.ExecName(execName)
}
func (c *js) Exec_Create(payload *jsproto.Create, tx *types.Transaction, index int) (*types.Receipt, error) { func (c *js) Exec_Create(payload *jsproto.Create, tx *types.Transaction, index int) (*types.Receipt, error) {
err := checkPriv(tx.From(), ptypes.JsCreator, c.GetStateDB()) err := checkPriv(tx.From(), ptypes.JsCreator, c.GetStateDB())
if err != nil { if err != nil {
return nil, err return nil, err
} }
execer := types.ExecName("user." + ptypes.JsX + "." + payload.Name) execer := c.userExecName(payload.Name, false)
if string(tx.Execer) != ptypes.JsX { if !c.checkTxExec(string(tx.Execer), ptypes.JsX) {
return nil, types.ErrExecNameNotMatch return nil, types.ErrExecNameNotMatch
} }
c.prefix = types.CalcStatePrefix([]byte(execer)) c.prefix = types.CalcStatePrefix([]byte(execer))
...@@ -41,8 +55,8 @@ func (c *js) Exec_Create(payload *jsproto.Create, tx *types.Transaction, index i ...@@ -41,8 +55,8 @@ func (c *js) Exec_Create(payload *jsproto.Create, tx *types.Transaction, index i
} }
func (c *js) Exec_Call(payload *jsproto.Call, tx *types.Transaction, index int) (*types.Receipt, error) { func (c *js) Exec_Call(payload *jsproto.Call, tx *types.Transaction, index int) (*types.Receipt, error) {
execer := types.ExecName("user." + ptypes.JsX + "." + payload.Name) execer := c.userExecName(payload.Name, false)
if string(tx.Execer) != execer { if !c.checkTxExec(string(tx.Execer), execer) {
return nil, types.ErrExecNameNotMatch return nil, types.ErrExecNameNotMatch
} }
c.prefix = types.CalcStatePrefix([]byte(execer)) c.prefix = types.CalcStatePrefix([]byte(execer))
......
...@@ -2,7 +2,6 @@ package executor ...@@ -2,7 +2,6 @@ package executor
import ( import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ptypes "github.com/33cn/plugin/plugin/dapp/js/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto" "github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
) )
...@@ -11,7 +10,7 @@ func (c *js) ExecDelLocal_Create(payload *jsproto.Create, tx *types.Transaction, ...@@ -11,7 +10,7 @@ func (c *js) ExecDelLocal_Create(payload *jsproto.Create, tx *types.Transaction,
} }
func (c *js) ExecDelLocal_Call(payload *jsproto.Call, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (c *js) ExecDelLocal_Call(payload *jsproto.Call, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
execer := types.ExecName("user." + ptypes.JsX + "." + payload.Name) execer := c.userExecName(payload.Name, true)
r := &types.LocalDBSet{} r := &types.LocalDBSet{}
c.prefix = types.CalcLocalPrefix([]byte(execer)) c.prefix = types.CalcLocalPrefix([]byte(execer))
kvs, err := c.DelRollbackKV(tx, []byte(execer)) kvs, err := c.DelRollbackKV(tx, []byte(execer))
......
...@@ -2,7 +2,6 @@ package executor ...@@ -2,7 +2,6 @@ package executor
import ( import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ptypes "github.com/33cn/plugin/plugin/dapp/js/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto" "github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
) )
...@@ -11,7 +10,7 @@ func (c *js) ExecLocal_Create(payload *jsproto.Create, tx *types.Transaction, re ...@@ -11,7 +10,7 @@ func (c *js) ExecLocal_Create(payload *jsproto.Create, tx *types.Transaction, re
} }
func (c *js) ExecLocal_Call(payload *jsproto.Call, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (c *js) ExecLocal_Call(payload *jsproto.Call, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
execer := types.ExecName("user." + ptypes.JsX + "." + payload.Name) execer := c.userExecName(payload.Name, true)
c.prefix = types.CalcLocalPrefix([]byte(execer)) c.prefix = types.CalcLocalPrefix([]byte(execer))
jsvalue, err := c.callVM("execlocal", payload, tx, index, receiptData) jsvalue, err := c.callVM("execlocal", payload, tx, index, receiptData)
if err != nil { if err != nil {
......
...@@ -4,12 +4,11 @@ import ( ...@@ -4,12 +4,11 @@ import (
"fmt" "fmt"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ptypes "github.com/33cn/plugin/plugin/dapp/js/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto" "github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
) )
func (c *js) Query_Query(payload *jsproto.Call) (types.Message, error) { func (c *js) Query_Query(payload *jsproto.Call) (types.Message, error) {
execer := types.ExecName("user." + ptypes.JsX + "." + payload.Name) execer := c.userExecName(payload.Name, true)
c.prefix = types.CalcLocalPrefix([]byte(execer)) c.prefix = types.CalcLocalPrefix([]byte(execer))
jsvalue, err := c.callVM("query", payload, nil, 0, nil) jsvalue, err := c.callVM("query", payload, nil, 0, nil)
if err != nil { if err != nil {
......
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/bin/sh
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
cp ./build/test-rpc.sh "${OUT_TESTDIR}"
This diff is collapsed.
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/usr/bin/env bash
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
chmod +x ./build/test-rpc.sh
cp ./build/test-rpc.sh "${OUT_TESTDIR}"
#!/usr/bin/env bash
# shellcheck disable=SC2128
MAIN_HTTP=""
CASE_ERR=""
oracle_addPublisher_unsignedTx="0a066d616e61676512410a3f0a146f7261636c652d7075626c6973682d6576656e741222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a0361646420a08d0630e6b685d696ee9394163a223151344e687572654a784b4e4266373164323642394a336642516f5163666d657a32"
oracle_addPublisher_unsignedTx_para="0a12757365722e702e706172612e6d616e61676512410a3f0a146f7261636c652d7075626c6973682d6576656e741222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a0361646420a08d0630a186de8894c9aa864d3a22314469484633317577783977356a6a733571514269474a6b4e686e71656564763157"
oracle_publisher_addr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
eventId=""
txhash=""
#color
RED='\033[1;31m'
GRE='\033[1;32m'
NOC='\033[0m'
# $2=0 means true, other false
echo_rst() {
if [ "$2" -eq 0 ]; then
echo -e "${GRE}$1 ok${NOC}"
else
echo -e "${RED}$1 fail${NOC}"
CASE_ERR="err"
fi
}
oracle_AddPublisher() {
echo "=============== # Add publisher ==============="
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ispara=$ispara"
if [ "$ispara" == true ]; then
signAndSendRawTx "${oracle_addPublisher_unsignedTx_para}" "${oracle_publisher_addr}"
else
signAndSendRawTx "${oracle_addPublisher_unsignedTx}" "${oracle_publisher_addr}"
fi
}
oracle_publish_transaction() {
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventPublish","payload":{"type":"football", "subType":"Premier League","time":1747814996,"content":"test","introduction":"test"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
signAndSendRawTx "$rawtx" "${oracle_publisher_addr}"
eventId="${txhash}"
echo "eventId $eventId"
}
oracle_prePublishResult_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPrePublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"0:1"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
signAndSendRawTx "$rawtx" "${oracle_publisher_addr}"
}
oracle_eventAbort_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"EventAbort","payload":{"eventID":"'"$event_id"'"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
signAndSendRawTx "$rawtx" "${oracle_publisher_addr}"
}
oracle_resultAbort_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultAbort","payload":{"eventID":"'"$event_id"'"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
signAndSendRawTx "$rawtx" "${oracle_publisher_addr}"
}
oracle_publishResult_transaction() {
event_id=$1
req='"method":"Chain33.CreateTransaction","params":[{"execer":"oracle","actionName":"ResultPublish","payload":{"eventID":"'"$event_id"'", "source":"sina sport","result":"1:1"}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
signAndSendRawTx "$rawtx" "${oracle_publisher_addr}"
}
# 签名并发送
signAndSendRawTx() {
unsignedTx=$1
addr=$2
req='"method":"Chain33.SignRawTx","params":[{"addr":"'${addr}'","txHex":"'${unsignedTx}'","expire":"120s"}]'
signedTx=$(curl -ksd "{$req}" ${MAIN_HTTP} | jq -r ".result")
if [ "$signedTx" == "null" ]; then
echo "An error occurred while signing"
else
sendSignedTx "$signedTx"
fi
}
sendSignedTx() {
signedTx=$1
local req='"method":"Chain33.SendTransaction","params":[{"token":"","data":"'"$signedTx"'"}]'
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
ok=$(echo "${resp}" | jq -r ".error")
[ "$ok" == null ]
rst=$?
#echo_rst "$FUNCNAME" "$rst"
txhash=$(echo "${resp}" | jq -r ".result")
echo "tx hash is $txhash"
}
oracle_QueryOraclesByID() {
event_id=$1
local req='"method":"Chain33.Query", "params":[{"execer":"oracle","funcName":"QueryOraclesByIDs","payload":{"eventID":["'"$event_id"'"]}}]'
#echo "#request: $req"
resp=$(curl -ksd "{$req}" ${MAIN_HTTP})
echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.status[0] | [has("eventID", "status", "type", "subType", "source"),true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
function block_wait() {
local req='"method":"Chain33.GetLastHeader","params":[]'
cur_height=$(curl -ksd "{$req}" ${MAIN_HTTP} | jq ".result.height")
expect=$((cur_height + ${1}))
local count=0
while true; do
new_height=$(curl -ksd "{$req}" ${MAIN_HTTP} | jq ".result.height")
if [ "${new_height}" -ge "${expect}" ]; then
break
fi
count=$((count + 1))
sleep 1
done
echo "wait new block $count s, cur height=$expect,old=$cur_height"
}
function queryTransaction() {
block_wait 1
local txhash="$1"
local req='"method":"Chain33.QueryTransaction","params":[{"hash":"'"$txhash"'"}]'
local times=10
while true; do
ret=$(curl -ksd "{$req}" ${MAIN_HTTP} | jq -r ".result.tx.hash")
if [ "${ret}" != "${1}" ]; then
block_wait 1
times=$((times - 1))
if [ $times -le 0 ]; then
echo "====query tx=$1 failed"
echo "req=$req"
curl -ksd "{$req}" ${MAIN_HTTP}
return 1
exit 1
fi
else
echo "====query tx=$1 success"
return 0
break
fi
done
}
function run_test() {
# 增加发布人
oracle_AddPublisher
# 生成发布事件的交易
oracle_publish_transaction
# 预发布事件结果交易
oracle_prePublishResult_transaction "$eventId"
# 事件正式发布
oracle_publishResult_transaction "$eventId"
# 根据ID查询事件
block_wait 2
oracle_QueryOraclesByID "$eventId"
# 生成发布事件的交易
oracle_publish_transaction
# 取消事件发布
oracle_eventAbort_transaction "$eventId"
# 根据ID查询事件
block_wait 2
oracle_QueryOraclesByID "$eventId"
# 生成发布事件的交易
oracle_publish_transaction
# 预发布事件结果交易
oracle_prePublishResult_transaction "$eventId"
# 取消事件预发布
oracle_resultAbort_transaction "$eventId"
# 根据ID查询事件
block_wait 2
oracle_QueryOraclesByID "$eventId"
}
function main() {
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
echo "=========== # oracle rpc test start============="
run_test
if [ -n "$CASE_ERR" ]; then
echo -e "${RED}=============Oracle Rpc Test Fail=============${NOC}"
exit 1
else
echo -e "${GRE}=============Oracle Rpc Test Pass==============${NOC}"
fi
echo "=========== # oracle rpc test end============="
}
main "$1"
...@@ -62,7 +62,7 @@ grpcFuncWhitelist=["*"] ...@@ -62,7 +62,7 @@ grpcFuncWhitelist=["*"]
mainnetJrpcAddr= "http://localhost:8801" mainnetJrpcAddr= "http://localhost:8801"
[mempool] [mempool]
name="timeline" name="para"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
......
...@@ -63,7 +63,7 @@ grpcFuncWhitelist=["*"] ...@@ -63,7 +63,7 @@ grpcFuncWhitelist=["*"]
[mempool] [mempool]
name="timeline" name="para"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
...@@ -154,6 +154,7 @@ tokenApprs = [ ...@@ -154,6 +154,7 @@ tokenApprs = [
] ]
[exec.sub.paracross] [exec.sub.paracross]
#平行链自共识停止n个块后,超级账户可以直接参与投票
paraConsensusStopBlocks=100 paraConsensusStopBlocks=100
[pprof] [pprof]
......
This diff is collapsed.
...@@ -415,7 +415,7 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error ...@@ -415,7 +415,7 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
saveTitle(a.db, calcTitleKey(commit.Status.Title), titleStatus) saveTitle(a.db, calcTitleKey(commit.Status.Title), titleStatus)
clog.Info("paracross.Commit commit done", "height", commit.Status.Height, clog.Info("paracross.Commit commit done", "height", commit.Status.Height,
"cross tx bitmap", hex.EncodeToString(commit.Status.CrossTxResult), "statusBlockHash", hex.EncodeToString(titleStatus.BlockHash)) "cross tx bitmap", string(commit.Status.CrossTxResult), "statusBlockHash", hex.EncodeToString(titleStatus.BlockHash))
//parallel chain not need to process cross commit tx here //parallel chain not need to process cross commit tx here
if types.IsPara() { if types.IsPara() {
...@@ -491,7 +491,13 @@ func getCrossTxHashs(api client.QueueProtocolAPI, commit *pt.ParacrossCommitActi ...@@ -491,7 +491,13 @@ func getCrossTxHashs(api client.QueueProtocolAPI, commit *pt.ParacrossCommitActi
//只获取跨链tx //只获取跨链tx
crossTxHashs = paraCrossHashs crossTxHashs = paraCrossHashs
crossTxResult = commit.Status.CrossTxResult rst, err := hex.DecodeString(string(commit.Status.CrossTxResult))
if err != nil {
clog.Error("getCrossTxHashs decode string", "CrossTxResult", string(commit.Status.CrossTxResult),
"commit.height", commit.Status.Height)
return nil, nil, types.ErrInvalidParam
}
crossTxResult = rst
} }
return crossTxHashs, crossTxResult, nil return crossTxHashs, crossTxResult, nil
} }
......
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
package executor package executor
import ( import (
"bytes"
"encoding/hex"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
...@@ -125,41 +129,81 @@ func (e *Paracross) ExecLocal_AssetWithdraw(payload *types.AssetsWithdraw, tx *t ...@@ -125,41 +129,81 @@ func (e *Paracross) ExecLocal_AssetWithdraw(payload *types.AssetsWithdraw, tx *t
return nil, nil return nil, nil
} }
func setMinerTxResult(payload *pt.ParacrossMinerAction, txs []*types.Transaction, receipts []*types.ReceiptData) { func setMinerTxResult(payload *pt.ParacrossMinerAction, txs []*types.Transaction, receipts []*types.ReceiptData) error {
var curTxHashs, paraTxHashs [][]byte isCommitTx := make(map[string]bool)
var curTxHashs, paraTxHashs, crossTxHashs [][]byte
for _, tx := range txs { for _, tx := range txs {
hash := tx.Hash() hash := tx.Hash()
curTxHashs = append(curTxHashs, hash) curTxHashs = append(curTxHashs, hash)
//对user.p.xx.paracross ,actionTy==commit 的tx不需要再发回主链
if types.IsMyParaExecName(string(tx.Execer)) && bytes.HasSuffix(tx.Execer, []byte(pt.ParaX)) {
var payload pt.ParacrossAction
err := types.Decode(tx.Payload, &payload)
if err != nil {
clog.Error("setMinerTxResult", "txHash", common.ToHex(hash))
return err
}
if payload.Ty == pt.ParacrossActionCommit {
isCommitTx[string(hash)] = true
}
}
//跨链交易包含了主链交易,需要过滤出来 //跨链交易包含了主链交易,需要过滤出来
if types.IsMyParaExecName(string(tx.Execer)) { if types.IsMyParaExecName(string(tx.Execer)) && !isCommitTx[string(hash)] {
paraTxHashs = append(paraTxHashs, hash) paraTxHashs = append(paraTxHashs, hash)
} }
} }
crossTxHashs := FilterParaMainCrossTxHashes(types.GetTitle(), txs) totalCrossTxHashs := FilterParaMainCrossTxHashes(types.GetTitle(), txs)
for _, crossHash := range totalCrossTxHashs {
if !isCommitTx[string(crossHash)] {
crossTxHashs = append(crossTxHashs, crossHash)
}
}
payload.Status.TxHashs = paraTxHashs payload.Status.TxHashs = paraTxHashs
payload.Status.TxResult = util.CalcBitMap(paraTxHashs, curTxHashs, receipts) payload.Status.TxResult = util.CalcBitMap(paraTxHashs, curTxHashs, receipts)
payload.Status.CrossTxHashs = crossTxHashs payload.Status.CrossTxHashs = crossTxHashs
payload.Status.CrossTxResult = util.CalcBitMap(crossTxHashs, curTxHashs, receipts) payload.Status.CrossTxResult = util.CalcBitMap(crossTxHashs, curTxHashs, receipts)
return nil
} }
func setMinerTxResultFork(payload *pt.ParacrossMinerAction, txs []*types.Transaction, receipts []*types.ReceiptData) { func setMinerTxResultFork(status *pt.ParacrossNodeStatus, txs []*types.Transaction, receipts []*types.ReceiptData) error {
isCommitTx := make(map[string]bool)
var curTxHashs [][]byte var curTxHashs [][]byte
for _, tx := range txs { for _, tx := range txs {
hash := tx.Hash() hash := tx.Hash()
curTxHashs = append(curTxHashs, hash) curTxHashs = append(curTxHashs, hash)
if types.IsMyParaExecName(string(tx.Execer)) && bytes.HasSuffix(tx.Execer, []byte(pt.ParaX)) {
var payload pt.ParacrossAction
err := types.Decode(tx.Payload, &payload)
if err != nil {
clog.Error("setMinerTxResultFork", "txHash", common.ToHex(hash))
return err
}
if payload.Ty == pt.ParacrossActionCommit {
isCommitTx[string(hash)] = true
} }
baseTxHashs := payload.Status.TxHashs }
baseCrossTxHashs := payload.Status.CrossTxHashs }
status.TxCounts = uint32(len(curTxHashs))
//有tx且全部是user.p.x.paracross的commit tx时候设为0
status.NonCommitTxCounts = 1
if len(curTxHashs) != 0 && len(curTxHashs) == len(isCommitTx) {
status.NonCommitTxCounts = 0
}
crossTxHashs := FilterParaCrossTxHashes(types.GetTitle(), txs)
//主链自己过滤平行链tx, 对平行链执行失败的tx主链无法识别,主链和平行链需要获取相同的最初的tx map //主链自己过滤平行链tx, 对平行链执行失败的tx主链无法识别,主链和平行链需要获取相同的最初的tx map
//全部平行链tx结果 //全部平行链tx结果
payload.Status.TxResult = util.CalcBitMap(baseTxHashs, curTxHashs, receipts) status.TxResult = []byte(hex.EncodeToString(util.CalcBitMap(curTxHashs, curTxHashs, receipts)))
//跨链tx结果 //跨链tx结果
payload.Status.CrossTxResult = util.CalcBitMap(baseCrossTxHashs, curTxHashs, receipts) status.CrossTxResult = []byte(hex.EncodeToString(util.CalcBitMap(crossTxHashs, curTxHashs, receipts)))
status.TxHashs = [][]byte{CalcTxHashsHash(curTxHashs)}
status.CrossTxHashs = [][]byte{CalcTxHashsHash(crossTxHashs)}
payload.Status.TxHashs = [][]byte{CalcTxHashsHash(baseTxHashs)} return nil
payload.Status.CrossTxHashs = [][]byte{CalcTxHashsHash(baseCrossTxHashs)}
} }
//ExecLocal_Miner miner tx local db process //ExecLocal_Miner miner tx local db process
...@@ -175,9 +219,15 @@ func (e *Paracross) ExecLocal_Miner(payload *pt.ParacrossMinerAction, tx *types. ...@@ -175,9 +219,15 @@ func (e *Paracross) ExecLocal_Miner(payload *pt.ParacrossMinerAction, tx *types.
//removed the 0 vote tx //removed the 0 vote tx
if payload.Status.MainBlockHeight >= forkHeight { if payload.Status.MainBlockHeight >= forkHeight {
setMinerTxResultFork(payload, txs[1:], e.GetReceipt()[1:]) err := setMinerTxResultFork(payload.Status, txs[1:], e.GetReceipt()[1:])
if err != nil {
return nil, err
}
} else { } else {
setMinerTxResult(payload, txs[1:], e.GetReceipt()[1:]) err := setMinerTxResult(payload, txs[1:], e.GetReceipt()[1:])
if err != nil {
return nil, err
}
} }
set.KV = append(set.KV, &types.KeyValue{ set.KV = append(set.KV, &types.KeyValue{
......
...@@ -488,10 +488,14 @@ func (s *VoteTestSuite) TestVoteTx() { ...@@ -488,10 +488,14 @@ func (s *VoteTestSuite) TestVoteTx() {
tx7, err := createAssetTransferTx(s.Suite, PrivKeyC, nil) tx7, err := createAssetTransferTx(s.Suite, PrivKeyC, nil)
s.Nil(err) s.Nil(err)
tx8, err := createCrossCommitTx(s.Suite)
s.Nil(err)
txs := []*types.Transaction{tx, tx1, tx2} txs := []*types.Transaction{tx, tx1, tx2}
txs = append(txs, txGroup34...) txs = append(txs, txGroup34...)
txs = append(txs, txGroup56...) txs = append(txs, txGroup56...)
txs = append(txs, tx7) txs = append(txs, tx7)
txs = append(txs, tx8)
s.exec.SetTxs(txs) s.exec.SetTxs(txs)
//for i,tx := range txs{ //for i,tx := range txs{
...@@ -508,7 +512,8 @@ func (s *VoteTestSuite) TestVoteTx() { ...@@ -508,7 +512,8 @@ func (s *VoteTestSuite) TestVoteTx() {
recpt5 := &types.ReceiptData{Ty: types.ExecPack} recpt5 := &types.ReceiptData{Ty: types.ExecPack}
recpt6 := &types.ReceiptData{Ty: types.ExecPack} recpt6 := &types.ReceiptData{Ty: types.ExecPack}
recpt7 := &types.ReceiptData{Ty: types.ExecOk} recpt7 := &types.ReceiptData{Ty: types.ExecOk}
receipts := []*types.ReceiptData{recpt0, recpt1, recpt2, recpt3, recpt4, recpt5, recpt6, recpt7} recpt8 := &types.ReceiptData{Ty: types.ExecOk}
receipts := []*types.ReceiptData{recpt0, recpt1, recpt2, recpt3, recpt4, recpt5, recpt6, recpt7, recpt8}
s.exec.SetReceipt(receipts) s.exec.SetReceipt(receipts)
set, err := s.exec.ExecLocal(tx, recpt0, 0) set, err := s.exec.ExecLocal(tx, recpt0, 0)
s.Nil(err) s.Nil(err)
...@@ -615,8 +620,8 @@ func (s *VoteTestSuite) TestVoteTxFork() { ...@@ -615,8 +620,8 @@ func (s *VoteTestSuite) TestVoteTxFork() {
if bytes.Equal(key, kv.Key) { if bytes.Equal(key, kv.Key) {
var rst pt.ParacrossNodeStatus var rst pt.ParacrossNodeStatus
types.Decode(kv.GetValue(), &rst) types.Decode(kv.GetValue(), &rst)
s.Equal([]uint8([]byte{0x8e}), rst.TxResult) s.Equal([]byte("8e"), rst.TxResult)
s.Equal([]uint8([]byte{0x22}), rst.CrossTxResult) s.Equal([]byte("22"), rst.CrossTxResult)
s.Equal(1, len(rst.TxHashs)) s.Equal(1, len(rst.TxHashs))
s.Equal(1, len(rst.CrossTxHashs)) s.Equal(1, len(rst.CrossTxHashs))
...@@ -697,6 +702,24 @@ func createCrossParaTx(s suite.Suite, to []byte) (*types.Transaction, error) { ...@@ -697,6 +702,24 @@ func createCrossParaTx(s suite.Suite, to []byte) (*types.Transaction, error) {
return tx, nil return tx, nil
} }
func createCrossCommitTx(s suite.Suite) (*types.Transaction, error) {
status := &pt.ParacrossNodeStatus{MainBlockHash: []byte("hash"), MainBlockHeight: 0, Title: Title}
tx, err := pt.CreateRawCommitTx4MainChain(status, Title+pt.ParaX, 0)
assert.Nil(s.T(), err, "create asset transfer failed")
if err != nil {
return nil, err
}
//tx, err = signTx(s, tx, privFrom)
//assert.Nil(s.T(), err, "sign asset transfer failed")
//if err != nil {
// return nil, err
//}
return tx, nil
}
func createTxsGroup(s suite.Suite, txs []*types.Transaction) ([]*types.Transaction, error) { func createTxsGroup(s suite.Suite, txs []*types.Transaction) ([]*types.Transaction, error) {
group, err := types.CreateTxGroup(txs) group, err := types.CreateTxGroup(txs)
if err != nil { if err != nil {
......
...@@ -55,6 +55,7 @@ message ParaNodeAddrStatus{ ...@@ -55,6 +55,7 @@ message ParaNodeAddrStatus{
string applyAddr = 3; string applyAddr = 3;
int64 coinsFrozen = 4; int64 coinsFrozen = 4;
ParaNodeVoteDetail votes = 5; ParaNodeVoteDetail votes = 5;
string fromAddr = 6;
} }
...@@ -98,6 +99,7 @@ message ParaNodeGroupStatus { ...@@ -98,6 +99,7 @@ message ParaNodeGroupStatus {
int64 coinsFrozen = 4; int64 coinsFrozen = 4;
uint32 emptyBlockInterval = 5; uint32 emptyBlockInterval = 5;
int64 mainHeight = 6; int64 mainHeight = 6;
string fromAddr = 7;
} }
message ReceiptParaNodeGroupConfig { message ReceiptParaNodeGroupConfig {
...@@ -149,6 +151,7 @@ message ParacrossNodeStatus { ...@@ -149,6 +151,7 @@ message ParacrossNodeStatus {
repeated bytes txHashs = 11; repeated bytes txHashs = 11;
bytes crossTxResult = 12; bytes crossTxResult = 12;
repeated bytes crossTxHashs = 13; repeated bytes crossTxHashs = 13;
uint32 nonCommitTxCounts = 14;
} }
message ParacrossCommitAction { message ParacrossCommitAction {
......
This diff is collapsed.
...@@ -26,7 +26,7 @@ func init() { ...@@ -26,7 +26,7 @@ func init() {
types.RegistorExecutor(ParaX, NewType()) types.RegistorExecutor(ParaX, NewType())
types.RegisterDappFork(ParaX, "Enable", 0) types.RegisterDappFork(ParaX, "Enable", 0)
types.RegisterDappFork(ParaX, "ForkParacrossWithdrawFromParachain", 1298600) types.RegisterDappFork(ParaX, "ForkParacrossWithdrawFromParachain", 1298600)
types.RegisterDappFork(ParaX, ForkCommitTx, types.MaxHeight) types.RegisterDappFork(ParaX, ForkCommitTx, 1850000)
} }
// GetExecName get para exec name // GetExecName get para exec name
......
...@@ -202,6 +202,7 @@ ForkStateDBSet=-1 #fork 6.2 ...@@ -202,6 +202,7 @@ ForkStateDBSet=-1 #fork 6.2
ForkLocalDBAccess=-1 #fork 6.2 ForkLocalDBAccess=-1 #fork 6.2
ForkBlockCheck=-1 #fork 6.2 ForkBlockCheck=-1 #fork 6.2
ForkBase58AddressCheck=-1 #fork6.2 ForkBase58AddressCheck=-1 #fork6.2
ForkEnableParaRegExec=0
[fork.sub.coins] [fork.sub.coins]
Enable=0 Enable=0
[fork.sub.ticket] [fork.sub.ticket]
......
...@@ -108,11 +108,11 @@ func (t *token) getAccountTokenAssets(req *tokenty.ReqAccountTokenAssets) (types ...@@ -108,11 +108,11 @@ func (t *token) getAccountTokenAssets(req *tokenty.ReqAccountTokenAssets) (types
return nil, err return nil, err
} }
var acc1 *types.Account var acc1 *types.Account
if req.Execer != "" { if req.Execer == t.GetName() {
execaddress := address.ExecAddress(req.Execer)
acc1 = acc.LoadExecAccount(req.Address, execaddress)
} else if req.Execer == t.GetName() {
acc1 = acc.LoadAccount(req.Address) acc1 = acc.LoadAccount(req.Address)
} else if req.Execer != "" {
execAddress := address.ExecAddress(req.Execer)
acc1 = acc.LoadExecAccount(req.Address, execAddress)
} }
if acc1 == nil { if acc1 == nil {
continue continue
......
...@@ -152,6 +152,9 @@ func TestToken(t *testing.T) { ...@@ -152,6 +152,9 @@ func TestToken(t *testing.T) {
set, err := exec.ExecLocal(createTx, receiptDate, int(1)) set, err := exec.ExecLocal(createTx, receiptDate, int(1))
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, set) assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
p2 := &pty.TokenFinishCreate{ p2 := &pty.TokenFinishCreate{
Symbol: Symbol, Symbol: Symbol,
...@@ -176,13 +179,16 @@ func TestToken(t *testing.T) { ...@@ -176,13 +179,16 @@ func TestToken(t *testing.T) {
stateDB.Set(kv.Key, kv.Value) stateDB.Set(kv.Key, kv.Value)
} }
accDB, _ := account.NewAccountDB(pty.TokenX, Symbol, stateDB) accDB, _ := account.NewAccountDB(pty.TokenX, Symbol, stateDB)
accChcek := accDB.LoadAccount(string(Nodes[0])) accCheck := accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal, accChcek.Balance) assert.Equal(t, tokenTotal, accCheck.Balance)
receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs} receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx2, receiptDate, int(1)) set, err = exec.ExecLocal(createTx2, receiptDate, int(1))
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, set) assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
// mint burn // mint burn
p3 := &pty.TokenMint{ p3 := &pty.TokenMint{
...@@ -208,13 +214,16 @@ func TestToken(t *testing.T) { ...@@ -208,13 +214,16 @@ func TestToken(t *testing.T) {
stateDB.Set(kv.Key, kv.Value) stateDB.Set(kv.Key, kv.Value)
} }
accChcek = accDB.LoadAccount(string(Nodes[0])) accCheck = accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal+tokenMint, accChcek.Balance) assert.Equal(t, tokenTotal+tokenMint, accCheck.Balance)
receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs} receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx3, receiptDate, int(1)) set, err = exec.ExecLocal(createTx3, receiptDate, int(1))
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, set) assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
p4 := &pty.TokenBurn{ p4 := &pty.TokenBurn{
Symbol: Symbol, Symbol: Symbol,
...@@ -238,13 +247,31 @@ func TestToken(t *testing.T) { ...@@ -238,13 +247,31 @@ func TestToken(t *testing.T) {
for _, kv := range receipt.KV { for _, kv := range receipt.KV {
stateDB.Set(kv.Key, kv.Value) stateDB.Set(kv.Key, kv.Value)
} }
accChcek = accDB.LoadAccount(string(Nodes[0])) accCheck = accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal+tokenMint-tokenBurn, accChcek.Balance) assert.Equal(t, tokenTotal+tokenMint-tokenBurn, accCheck.Balance)
receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs} receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx4, receiptDate, int(1)) set, err = exec.ExecLocal(createTx4, receiptDate, int(1))
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, set) assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
tokenExec, ok := exec.(*token)
assert.True(t, ok)
in := pty.ReqAccountTokenAssets{
Address: string(Nodes[0]),
Execer: pty.TokenX,
}
out, err := tokenExec.Query_GetAccountTokenAssets(&in)
assert.Nil(t, err)
reply := out.(*pty.ReplyAccountTokenAssets)
assert.Equal(t, 1, len(reply.TokenAssets))
assert.NotEqual(t, 0, reply.TokenAssets[0].Account.Balance)
assert.Equal(t, string(Nodes[0]), reply.TokenAssets[0].Account.Addr)
t.Log(reply.TokenAssets)
} }
func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) { func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) {
......
...@@ -10,3 +10,7 @@ OUT_DIR="${output_dir}/$strapp" ...@@ -10,3 +10,7 @@ OUT_DIR="${output_dir}/$strapp"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
cp ./build/* "${OUT_DIR}" cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
cp ./build/test-rpc.sh "${OUT_TESTDIR}"
#!/usr/bin/env bash
# shellcheck disable=SC2128
MAIN_HTTP=""
CASE_ERR=""
#color
RED='\033[1;31m'
GRE='\033[1;32m'
NOC='\033[0m'
# base functions
# $2=0 means true, other false
function echo_rst() {
if [ "$2" -eq 0 ]; then
echo -e "${GRE}$1 ok${NOC}"
else
echo -e "${RED}$1 fail${NOC}"
CASE_ERR="err"
fi
}
function Chain33_SendToAddress() {
local from="$1"
local to="$2"
local amount=$3
local req='{"method":"Chain33.SendToAddress", "params":[{"from":"'"$from"'","to":"'"$to"'", "amount":'"$amount"', "note":"test\n"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.hash|length==66)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
hash=$(jq '(.result.hash)' <<<"$resp")
echo "hash=$hash"
# query_tx "$hash"
}
function sign_raw_tx() {
txHex="$1"
priKey="$2"
req='{"method":"Chain33.SignRawTx","params":[{"privkey":"'"$priKey"'","txHex":"'"$txHex"'","expire":"120s"}]}'
# echo "#request SignRawTx: $req"
signedTx=$(curl -ksd "$req" ${MAIN_HTTP} | jq -r ".result")
# echo "signedTx=$signedTx"
if [ "$signedTx" != null ]; then
send_tx "$signedTx"
else
echo "signedTx null error"
fi
}
function send_tx() {
signedTx=$1
req='{"method":"Chain33.SendTransaction","params":[{"token":"BTY","data":"'"$signedTx"'"}]}'
# echo "#request sendTx: $req"
# curl -ksd "$req" ${MAIN_HTTP}
resp=$(curl -ksd "$req" ${MAIN_HTTP})
err=$(jq '(.error)' <<<"$resp")
txhash=$(jq -r ".result" <<<"$resp")
if [ "$err" == null ]; then
# echo "tx hash: $txhash"
query_tx "$txhash"
else
echo "send tx error:$err"
fi
}
function block_wait() {
req='{"method":"Chain33.GetLastHeader","params":[{}]}'
cur_height=$(curl -ksd "$req" ${MAIN_HTTP} | jq ".result.height")
expect=$((cur_height + ${1}))
local count=0
while true; do
new_height=$(curl -ksd "$req" ${MAIN_HTTP} | jq ".result.height")
if [ "${new_height}" -ge "${expect}" ]; then
break
fi
count=$((count + 1))
sleep 1
done
echo "wait new block $count s, cur height=$expect,old=$cur_height"
}
function query_tx() {
block_wait 1
txhash="$1"
# echo "req=$req"
local times=10
while true; do
req='{"method":"Chain33.QueryTransaction","params":[{"hash":"'"$txhash"'"}]}'
ret=$(curl -ksd "$req" ${MAIN_HTTP})
tx=$(jq -r ".result.tx.hash" <<<"$ret")
echo "====query tx= ${1}, return=$ret "
if [ "${tx}" != "${1}" ]; then
block_wait 1
times=$((times - 1))
if [ $times -le 0 ]; then
echo "====query tx=$1 failed"
echo "req=$req"
curl -ksd "$req" ${MAIN_HTTP}
exit 1
fi
else
exec_err=$(jq '(.result.receipt.logs[0].tyName == "LogErr")' <<<"$ret")
[ "$exec_err" != true ]
echo "====query tx=$1 success"
break
fi
done
}
function query_unfreezeID() {
block_wait 1
# echo "req=$req"
local times=10
while true; do
req='{"method":"Chain33.QueryTransaction","params":[{"hash":"'"$txhash"'"}]}'
ret=$(curl -ksd "$req" ${MAIN_HTTP})
tx=$(jq -r ".result.tx.hash" <<<"$ret")
echo "====query tx= ${txhash}, return=$ret "
if [ "${tx}" != "${txhash}" ]; then
block_wait 1
times=$((times - 1))
if [ $times -le 0 ]; then
echo "====query tx=$txhash failed"
echo "req=$req"
curl -ksd "$req" ${MAIN_HTTP}
exit 1
fi
else
unfreeze_id=$(jq '(.result.receipt.logs['"$uid_index"'].log.current.unfreezeID)' <<<"$ret")
#echo "${unfreeze_id}"
unfreeze_id2=${unfreeze_id#\"mavl-unfreeze-}
uid=${unfreeze_id2%\"}
echo "====query tx=$txhash success"
break
fi
done
}
function init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
echo "ipara=$ispara"
exec_name="unfreeze"
uid_index=2
if [ "$ispara" == true ]; then
exec_name="user.p.para."${exec_name}
uid_index=1
fi
exec_addr=$(curl -ksd '{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"'${exec_name}'"}]}' ${MAIN_HTTP} | jq -r ".result")
echo "exec_addr=${exec_addr}"
beneficiary=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
beneficiary_key=0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01
owner=14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
owner_key=CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944
#unfreeze_exec_addr=15YsqAuXeEXVHgm6RVx4oJaAAnhtwqnu3H
Chain33_SendToAddress "$owner" "$exec_addr" 500000000
Chain33_SendToAddress "$beneficiary" "$exec_addr" 500000000
block_wait 1
}
function CreateRawUnfreezeCreate() {
req='{"jsonrpc": "2.0", "method" : "unfreeze.CreateRawUnfreezeCreate" , "params":[{"startTime":10000,"assetExec":"coins","assetSymbol":"bty","totalCount":400000000,"beneficiary":"'$beneficiary'","means":"FixAmount","fixAmount": {"period":10,"amount":1000000}}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "$owner_key"
query_unfreezeID
}
function CreateRawUnfreezeWithdraw() {
sleep 10
req='{"method":"unfreeze.CreateRawUnfreezeWithdraw","params":[{"unfreezeID":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${beneficiary_key}"
}
function CreateRawUnfreezeTerminate() {
req='{"method":"unfreeze.CreateRawUnfreezeTerminate","params":[{"unfreezeID":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "$owner_key"
block_wait 2
}
function GetUnfreeze() {
req='{"method":"unfreeze.GetUnfreeze","params":[{"data":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
function GetUnfreezeWithdraw() {
req='{"method":"unfreeze.GetUnfreezeWithdraw","params":[{"data":"'${uid}'"}]}'
# echo "#request: $req"
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#resp: $resp"
ok=$(jq '(.error|not) and (.result != "")' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
function run_testcases() {
CreateRawUnfreezeCreate
CreateRawUnfreezeWithdraw
GetUnfreeze
GetUnfreezeWithdraw
CreateRawUnfreezeTerminate
}
function debug_function() {
set -x
eval "$@"
set +x
}
function rpc_test() {
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
init
run_testcases
if [ -n "$CASE_ERR" ]; then
echo "=======unfreeze rpc test error ==========="
exit 1
else
echo "====== unfreeze rpc test pass ==========="
fi
}
debug_function rpc_test "$1"
...@@ -63,7 +63,7 @@ func (c *Jrpc) CreateRawUnfreezeCreate(param *pty.UnfreezeCreate, result *interf ...@@ -63,7 +63,7 @@ func (c *Jrpc) CreateRawUnfreezeCreate(param *pty.UnfreezeCreate, result *interf
if param == nil { if param == nil {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "UnfreezeCreateTX", param) data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "Create", param)
if err != nil { if err != nil {
return err return err
} }
...@@ -76,7 +76,7 @@ func (c *Jrpc) CreateRawUnfreezeWithdraw(param *pty.UnfreezeWithdraw, result *in ...@@ -76,7 +76,7 @@ func (c *Jrpc) CreateRawUnfreezeWithdraw(param *pty.UnfreezeWithdraw, result *in
if param == nil { if param == nil {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "UnfreezeWithdrawTx", param) data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "Withdraw", param)
if err != nil { if err != nil {
return err return err
} }
...@@ -89,7 +89,7 @@ func (c *Jrpc) CreateRawUnfreezeTerminate(param *pty.UnfreezeTerminate, result * ...@@ -89,7 +89,7 @@ func (c *Jrpc) CreateRawUnfreezeTerminate(param *pty.UnfreezeTerminate, result *
if param == nil { if param == nil {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "UnfreezeTerminateTx", param) data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "Terminate", param)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -3,3 +3,41 @@ ...@@ -3,3 +3,41 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package types package types
import (
"encoding/json"
"github.com/33cn/chain33/types"
)
type parseUnfreezeCreate struct {
StartTime int64 `protobuf:"varint,1,opt,name=startTime,proto3" json:"startTime,omitempty"`
AssetExec string `protobuf:"bytes,2,opt,name=assetExec,proto3" json:"assetExec,omitempty"`
AssetSymbol string `protobuf:"bytes,3,opt,name=assetSymbol,proto3" json:"assetSymbol,omitempty"`
TotalCount int64 `protobuf:"varint,4,opt,name=totalCount,proto3" json:"totalCount,omitempty"`
Beneficiary string `protobuf:"bytes,5,opt,name=beneficiary,proto3" json:"beneficiary,omitempty"`
Means string `protobuf:"bytes,6,opt,name=means,proto3" json:"means,omitempty"`
FixAmount *FixAmount `json:"fixAmount,omitempty"`
LeftProportion *LeftProportion `json:"leftProportion,omitempty"`
}
// UnmarshalJSON 解析UnfreezeCreate
func (m *UnfreezeCreate) UnmarshalJSON(v []byte) error {
var c parseUnfreezeCreate
err := json.Unmarshal(v, &c)
if err != nil {
return err
}
if c.Means == FixAmountX && c.FixAmount != nil {
m.MeansOpt = &UnfreezeCreate_FixAmount{FixAmount: c.FixAmount}
} else if c.Means == LeftProportionX && c.LeftProportion != nil {
m.MeansOpt = &UnfreezeCreate_LeftProportion{LeftProportion: c.LeftProportion}
} else {
return types.ErrInvalidParam
}
m.StartTime = c.StartTime
m.AssetSymbol, m.AssetExec = c.AssetSymbol, c.AssetExec
m.TotalCount, m.Beneficiary = c.TotalCount, c.Beneficiary
m.Means = c.Means
return nil
}
...@@ -75,8 +75,8 @@ func (u *UnfreezeType) GetTypeMap() map[string]int32 { ...@@ -75,8 +75,8 @@ func (u *UnfreezeType) GetTypeMap() map[string]int32 {
} }
// CreateTx 创建交易 // CreateTx 创建交易
func (u UnfreezeType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) { func (u *UnfreezeType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) {
tlog.Debug("UnfreezeType.CreateTx", "action", action) tlog.Error("UnfreezeType.CreateTx", "action", action, "message", string(message))
if action == Action_CreateUnfreeze { if action == Action_CreateUnfreeze {
var param UnfreezeCreate var param UnfreezeCreate
err := types.JSONToPB(message, &param) err := types.JSONToPB(message, &param)
...@@ -107,12 +107,13 @@ func (u UnfreezeType) CreateTx(action string, message json.RawMessage) (*types.T ...@@ -107,12 +107,13 @@ func (u UnfreezeType) CreateTx(action string, message json.RawMessage) (*types.T
} }
// RPC_UnfreezeCreateTx 创建冻结合约交易入口 // RPC_UnfreezeCreateTx 创建冻结合约交易入口
func (u UnfreezeType) RPC_UnfreezeCreateTx(parm *UnfreezeCreate) (*types.Transaction, error) { func (u *UnfreezeType) RPC_UnfreezeCreateTx(parm *UnfreezeCreate) (*types.Transaction, error) {
return CreateUnfreezeCreateTx(types.GetParaName(), parm) return CreateUnfreezeCreateTx(types.GetParaName(), parm)
} }
// CreateUnfreezeCreateTx 创建冻结合约交易 // CreateUnfreezeCreateTx 创建冻结合约交易
func CreateUnfreezeCreateTx(title string, parm *UnfreezeCreate) (*types.Transaction, error) { func CreateUnfreezeCreateTx(title string, parm *UnfreezeCreate) (*types.Transaction, error) {
tlog.Error("CreateUnfreezeCreateTx", "parm", parm)
if parm == nil { if parm == nil {
tlog.Error("RPC_UnfreezeCreateTx", "parm", parm) tlog.Error("RPC_UnfreezeCreateTx", "parm", parm)
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
...@@ -140,7 +141,7 @@ func CreateUnfreezeCreateTx(title string, parm *UnfreezeCreate) (*types.Transact ...@@ -140,7 +141,7 @@ func CreateUnfreezeCreateTx(title string, parm *UnfreezeCreate) (*types.Transact
} }
// RPC_UnfreezeWithdrawTx 创建提币交易入口 // RPC_UnfreezeWithdrawTx 创建提币交易入口
func (u UnfreezeType) RPC_UnfreezeWithdrawTx(parm *UnfreezeWithdraw) (*types.Transaction, error) { func (u *UnfreezeType) RPC_UnfreezeWithdrawTx(parm *UnfreezeWithdraw) (*types.Transaction, error) {
return CreateUnfreezeWithdrawTx(types.GetParaName(), parm) return CreateUnfreezeWithdrawTx(types.GetParaName(), parm)
} }
...@@ -168,7 +169,7 @@ func CreateUnfreezeWithdrawTx(title string, parm *UnfreezeWithdraw) (*types.Tran ...@@ -168,7 +169,7 @@ func CreateUnfreezeWithdrawTx(title string, parm *UnfreezeWithdraw) (*types.Tran
} }
// RPC_UnfreezeTerminateTx 创建终止冻结合约入口 // RPC_UnfreezeTerminateTx 创建终止冻结合约入口
func (u UnfreezeType) RPC_UnfreezeTerminateTx(parm *UnfreezeTerminate) (*types.Transaction, error) { func (u *UnfreezeType) RPC_UnfreezeTerminateTx(parm *UnfreezeTerminate) (*types.Transaction, error) {
return CreateUnfreezeTerminateTx(types.GetParaName(), parm) return CreateUnfreezeTerminateTx(types.GetParaName(), parm)
} }
......
...@@ -61,7 +61,7 @@ func DisableLog() { ...@@ -61,7 +61,7 @@ func DisableLog() {
func init() { func init() {
drivers.Reg("kvmvccmavl", New) drivers.Reg("kvmvccmavl", New)
types.RegisterDappFork("store-kvmvccmavl", "ForkKvmvccmavl", types.MaxHeight) types.RegisterDappFork("store-kvmvccmavl", "ForkKvmvccmavl", 186*10000)
} }
// KVmMavlStore provide kvmvcc and mavl store interface implementation // KVmMavlStore provide kvmvcc and mavl store interface implementation
......
...@@ -129,12 +129,8 @@ func (m *mockBlockChain) SetQueueClient(q queue.Queue) { ...@@ -129,12 +129,8 @@ func (m *mockBlockChain) SetQueueClient(q queue.Queue) {
msg.ReplyErr("Do not support", types.ErrInvalidParam) msg.ReplyErr("Do not support", types.ErrInvalidParam)
} }
case types.EventLocalList: case types.EventLocalList:
if req, ok := msg.GetData().(*types.LocalDBList); ok { if _, ok := msg.GetData().(*types.LocalDBList); ok {
if len(req.Key) > 0 && bytes.Equal(req.Key, []byte("Statistics:TicketInfoOrder:Addr:case1")) {
msg.Reply(client.NewMessage(blockchainKey, types.EventReplyQuery, &types.TicketMinerInfo{}))
} else {
msg.Reply(client.NewMessage(blockchainKey, types.EventReplyQuery, &types.LocalReplyValue{})) msg.Reply(client.NewMessage(blockchainKey, types.EventReplyQuery, &types.LocalReplyValue{}))
}
} else { } else {
msg.ReplyErr("Do not support", types.ErrInvalidParam) msg.ReplyErr("Do not support", types.ErrInvalidParam)
} }
......
...@@ -250,10 +250,10 @@ func (a *AddrBook) loadDb() bool { ...@@ -250,10 +250,10 @@ func (a *AddrBook) loadDb() bool {
if err != nil { if err != nil {
panic(err) panic(err)
} }
return false
}
} else {
a.setKey(string(privkey), a.genPubkey(string(privkey))) a.setKey(string(privkey), a.genPubkey(string(privkey)))
}
iteror := a.bookDb.Iterator(nil, nil, false) iteror := a.bookDb.Iterator(nil, nil, false)
for iteror.Next() { for iteror.Next() {
...@@ -391,6 +391,18 @@ func (a *AddrBook) setKey(privkey, pubkey string) { ...@@ -391,6 +391,18 @@ func (a *AddrBook) setKey(privkey, pubkey string) {
} }
//ResetPeerkey reset priv,pub key
func (a *AddrBook) ResetPeerkey(privkey, pubkey string) {
a.keymtx.Lock()
defer a.keymtx.Unlock()
a.privkey = privkey
a.pubkey = pubkey
err := a.bookDb.Set([]byte(privKeyTag), []byte(privkey))
if err != nil {
panic(err)
}
}
// GetPrivPubKey return privkey and pubkey // GetPrivPubKey return privkey and pubkey
func (a *AddrBook) GetPrivPubKey() (string, string) { func (a *AddrBook) GetPrivPubKey() (string, string) {
a.keymtx.Lock() a.keymtx.Lock()
......
...@@ -26,6 +26,10 @@ func (n *Node) destroyPeer(peer *Peer) { ...@@ -26,6 +26,10 @@ func (n *Node) destroyPeer(peer *Peer) {
func (n *Node) monitorErrPeer() { func (n *Node) monitorErrPeer() {
for { for {
peer := <-n.nodeInfo.monitorChan peer := <-n.nodeInfo.monitorChan
if peer == nil {
log.Info("monitorChan close")
return
}
if !peer.version.IsSupport() { if !peer.version.IsSupport() {
//如果版本不支持,直接删除节点 //如果版本不支持,直接删除节点
log.Info("VersoinMonitor", "NotSupport,addr", peer.Addr()) log.Info("VersoinMonitor", "NotSupport,addr", peer.Addr())
...@@ -260,6 +264,10 @@ func (n *Node) nodeReBalance() { ...@@ -260,6 +264,10 @@ func (n *Node) nodeReBalance() {
defer ticker.Stop() defer ticker.Stop()
for { for {
if n.isClose() {
log.Debug("nodeReBalance", "loop", "done")
return
}
<-ticker.C <-ticker.C
log.Info("nodeReBalance", "cacheSize", n.CacheBoundsSize()) log.Info("nodeReBalance", "cacheSize", n.CacheBoundsSize())
...@@ -362,7 +370,10 @@ func (n *Node) monitorPeers() { ...@@ -362,7 +370,10 @@ func (n *Node) monitorPeers() {
defer ticker.Stop() defer ticker.Stop()
_, selfName := n.nodeInfo.addrBook.GetPrivPubKey() _, selfName := n.nodeInfo.addrBook.GetPrivPubKey()
for { for {
if n.isClose() {
log.Debug("monitorPeers", "loop", "done")
return
}
<-ticker.C <-ticker.C
localBlockHeight, err := p2pcli.GetBlockHeight(n.nodeInfo) localBlockHeight, err := p2pcli.GetBlockHeight(n.nodeInfo)
if err != nil { if err != nil {
......
...@@ -158,6 +158,8 @@ func (na *NetAddress) DialTimeout(version int32) (*grpc.ClientConn, error) { ...@@ -158,6 +158,8 @@ func (na *NetAddress) DialTimeout(version int32) (*grpc.ClientConn, error) {
log.Debug("grpc DialCon", "did not connect", err, "addr", na.String()) log.Debug("grpc DialCon", "did not connect", err, "addr", na.String())
return nil, err return nil, err
} }
//p2p version check 通过版本协议,获取通信session
//判断是否对方是否支持压缩 //判断是否对方是否支持压缩
cli := pb.NewP2PgserviceClient(conn) cli := pb.NewP2PgserviceClient(conn)
_, err = cli.GetHeaders(context.Background(), &pb.P2PGetHeaders{StartHeight: 0, EndHeight: 0, Version: version}, grpc.FailFast(true)) _, err = cli.GetHeaders(context.Background(), &pb.P2PGetHeaders{StartHeight: 0, EndHeight: 0, Version: version}, grpc.FailFast(true))
...@@ -186,7 +188,5 @@ func (na *NetAddress) DialTimeout(version int32) (*grpc.ClientConn, error) { ...@@ -186,7 +188,5 @@ func (na *NetAddress) DialTimeout(version int32) (*grpc.ClientConn, error) {
return nil, err return nil, err
} }
//p2p version check
return conn, nil return conn, nil
} }
...@@ -33,6 +33,7 @@ func (n *Node) Start() { ...@@ -33,6 +33,7 @@ func (n *Node) Start() {
} }
n.detectNodeAddr() n.detectNodeAddr()
n.monitor() n.monitor()
atomic.StoreInt32(&n.closed, 0)
go n.doNat() go n.doNat()
} }
...@@ -45,12 +46,14 @@ func (n *Node) Close() { ...@@ -45,12 +46,14 @@ func (n *Node) Close() {
} }
log.Debug("stop", "listen", "closed") log.Debug("stop", "listen", "closed")
n.nodeInfo.addrBook.Close() n.nodeInfo.addrBook.Close()
n.nodeInfo.monitorChan <- nil
log.Debug("stop", "addrBook", "closed") log.Debug("stop", "addrBook", "closed")
n.removeAll() n.removeAll()
if Filter != nil { if Filter != nil {
Filter.Close() Filter.Close()
} }
n.deleteNatMapPort() n.deleteNatMapPort()
log.Info("stop", "PeerRemoeAll", "closed") log.Info("stop", "PeerRemoeAll", "closed")
} }
......
...@@ -7,9 +7,11 @@ package p2p ...@@ -7,9 +7,11 @@ package p2p
import ( import (
"fmt" "fmt"
"math/rand"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/33cn/chain33/client"
l "github.com/33cn/chain33/common/log/log15" l "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/queue" "github.com/33cn/chain33/queue"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -24,13 +26,17 @@ var ( ...@@ -24,13 +26,17 @@ var (
// P2p interface // P2p interface
type P2p struct { type P2p struct {
api client.QueueProtocolAPI
client queue.Client client queue.Client
node *Node node *Node
p2pCli EventInterface p2pCli EventInterface
txCapcity int32 txCapcity int32
txFactory chan struct{} txFactory chan struct{}
otherFactory chan struct{} otherFactory chan struct{}
waitRestart chan struct{}
closed int32 closed int32
restart int32
cfg *types.P2P
} }
// New produce a p2p object // New produce a p2p object
...@@ -71,7 +77,9 @@ func New(cfg *types.P2P) *P2p { ...@@ -71,7 +77,9 @@ func New(cfg *types.P2P) *P2p {
p2p.p2pCli = NewP2PCli(p2p) p2p.p2pCli = NewP2PCli(p2p)
p2p.txFactory = make(chan struct{}, 1000) // 1000 task p2p.txFactory = make(chan struct{}, 1000) // 1000 task
p2p.otherFactory = make(chan struct{}, 1000) //other task 1000 p2p.otherFactory = make(chan struct{}, 1000) //other task 1000
p2p.waitRestart = make(chan struct{}, 1)
p2p.txCapcity = 1000 p2p.txCapcity = 1000
p2p.cfg = cfg
return p2p return p2p
} }
...@@ -82,6 +90,10 @@ func (network *P2p) isClose() bool { ...@@ -82,6 +90,10 @@ func (network *P2p) isClose() bool {
return atomic.LoadInt32(&network.closed) == 1 return atomic.LoadInt32(&network.closed) == 1
} }
func (network *P2p) isRestart() bool {
return atomic.LoadInt32(&network.restart) == 1
}
// Close network client // Close network client
func (network *P2p) Close() { func (network *P2p) Close() {
atomic.StoreInt32(&network.closed, 1) atomic.StoreInt32(&network.closed, 1)
...@@ -89,25 +101,48 @@ func (network *P2p) Close() { ...@@ -89,25 +101,48 @@ func (network *P2p) Close() {
network.node.Close() network.node.Close()
log.Debug("close", "node", "done") log.Debug("close", "node", "done")
if network.client != nil { if network.client != nil {
if !network.isRestart() {
network.client.Close() network.client.Close()
} }
}
network.node.pubsub.Shutdown() network.node.pubsub.Shutdown()
} }
// SetQueueClient set the queue // SetQueueClient set the queue
func (network *P2p) SetQueueClient(client queue.Client) { func (network *P2p) SetQueueClient(cli queue.Client) {
network.client = client var err error
network.node.SetQueueClient(client) if network.client == nil {
go func() { network.client = cli
log.Info("p2p", "setqueuecliet", "ok")
network.node.Start() }
network.subP2pMsg() network.api, err = client.New(cli, nil)
err := network.loadP2PPrivKeyToWallet()
if err != nil { if err != nil {
return panic("SetQueueClient client.New err")
} }
}() network.node.SetQueueClient(cli)
go func(p2p *P2p) {
p2p.node.Start()
if p2p.isRestart() {
//reset
atomic.StoreInt32(&p2p.closed, 0)
atomic.StoreInt32(&p2p.restart, 0)
network.waitRestart <- struct{}{}
} else {
p2p.subP2pMsg()
go p2p.loadP2PPrivKeyToWallet()
go p2p.genAirDropKeyFromWallet()
}
log.Debug("SetQueueClient gorountine ret")
}(network)
} }
func (network *P2p) showTaskCapcity() { func (network *P2p) showTaskCapcity() {
...@@ -124,6 +159,93 @@ func (network *P2p) showTaskCapcity() { ...@@ -124,6 +159,93 @@ func (network *P2p) showTaskCapcity() {
} }
} }
func (network *P2p) genAirDropKeyFromWallet() error {
for {
if network.isClose() {
return nil
}
msg := network.client.NewMessage("wallet", types.EventGetWalletStatus, nil)
err := network.client.SendTimeout(msg, true, time.Minute)
if err != nil {
log.Error("genAirDropKeyFromWallet", "Error", err.Error())
time.Sleep(time.Second)
continue
}
resp, err := network.client.WaitTimeout(msg, time.Minute)
if err != nil {
time.Sleep(time.Second)
continue
}
if resp.GetData().(*types.WalletStatus).GetIsWalletLock() { //上锁
time.Sleep(time.Second)
continue
}
if !resp.GetData().(*types.WalletStatus).GetIsHasSeed() { //无种子
time.Sleep(time.Second)
continue
}
break
}
r := rand.New(rand.NewSource(types.Now().Unix()))
var minIndex int32 = 100000000
randIndex := minIndex + r.Int31n(1000000)
reqIndex := &types.Int32{Data: randIndex}
msg, err := network.api.ExecWalletFunc("wallet", "NewAccountByIndex", reqIndex)
if err != nil {
log.Error("genAirDropKeyFromWallet", "err", err)
return err
}
var hexPrivkey string
if reply, ok := msg.(*types.ReplyString); !ok {
log.Error("genAirDropKeyFromWallet", "wrong format data", "")
panic(err)
} else {
hexPrivkey = reply.GetData()
}
log.Info("genAirDropKeyFromWallet", "hexprivkey", hexPrivkey)
if hexPrivkey[:2] == "0x" {
hexPrivkey = hexPrivkey[2:]
}
hexPubkey, err := P2pComm.Pubkey(hexPrivkey)
if err != nil {
log.Error("genAirDropKeyFromWallet", "gen pub error", err)
panic(err)
}
log.Info("genAirDropKeyFromWallet", "pubkey", hexPubkey)
_, pub := network.node.nodeInfo.addrBook.GetPrivPubKey()
if pub == hexPubkey {
return nil
}
//覆盖addrbook 中的公私钥对
network.node.nodeInfo.addrBook.ResetPeerkey(hexPrivkey, hexPubkey)
//重启p2p模块
log.Info("genAirDropKeyFromWallet", "p2p will Restart....")
network.ReStart()
return nil
}
// ReStart p2p
func (network *P2p) ReStart() {
atomic.StoreInt32(&network.restart, 1)
network.Close()
node, err := NewNode(network.cfg) //创建新的node节点
if err != nil {
panic(err.Error())
}
network.node = node
network.SetQueueClient(network.client)
}
func (network *P2p) loadP2PPrivKeyToWallet() error { func (network *P2p) loadP2PPrivKeyToWallet() error {
for { for {
...@@ -193,15 +315,23 @@ func (network *P2p) subP2pMsg() { ...@@ -193,15 +315,23 @@ func (network *P2p) subP2pMsg() {
go network.showTaskCapcity() go network.showTaskCapcity()
go func() { go func() {
defer func() {
close(network.otherFactory)
close(network.txFactory)
}()
var taskIndex int64 var taskIndex int64
network.client.Sub("p2p") network.client.Sub("p2p")
for msg := range network.client.Recv() { for msg := range network.client.Recv() {
if network.isRestart() {
//wait for restart
log.Info("waitp2p restart....")
<-network.waitRestart
log.Info("p2p restart ok....")
}
if network.isClose() { if network.isClose() {
log.Debug("subP2pMsg", "loop", "done") log.Debug("subP2pMsg", "loop", "done")
close(network.otherFactory)
close(network.txFactory)
return return
} }
taskIndex++ taskIndex++
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"github.com/33cn/chain33/queue" "github.com/33cn/chain33/queue"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/33cn/chain33/wallet"
//"github.com/33cn/chain33/util/testnode" //"github.com/33cn/chain33/util/testnode"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
...@@ -33,6 +34,36 @@ func init() { ...@@ -33,6 +34,36 @@ func init() {
p2pModule = initP2p(33802, dataDir) p2pModule = initP2p(33802, dataDir)
p2pModule.Wait() p2pModule.Wait()
go func() { go func() {
cfg, sub := types.InitCfg("../cmd/chain33/chain33.test.toml")
wcli := wallet.New(cfg.Wallet, sub.Wallet)
client := q.Client()
wcli.SetQueueClient(client)
//导入种子,解锁钱包
password := "a12345678"
seed := "cushion canal bitter result harvest sentence ability time steel basket useful ask depth sorry area course purpose search exile chapter mountain project ranch buffalo"
saveSeedByPw := &types.SaveSeedByPw{Seed: seed, Passwd: password}
msgSaveEmpty := client.NewMessage("wallet", types.EventSaveSeed, saveSeedByPw)
client.Send(msgSaveEmpty, true)
_, err := client.Wait(msgSaveEmpty)
if err != nil {
return
}
walletUnLock := &types.WalletUnLock{
Passwd: password,
Timeout: 0,
WalletOrTicket: false,
}
msgUnlock := client.NewMessage("wallet", types.EventWalletUnLock, walletUnLock)
client.Send(msgUnlock, true)
_, err = client.Wait(msgUnlock)
if err != nil {
return
}
}()
go func() {
blockchainKey := "blockchain" blockchainKey := "blockchain"
client := q.Client() client := q.Client()
client.Sub(blockchainKey) client.Sub(blockchainKey)
...@@ -163,7 +194,7 @@ func TestPeer(t *testing.T) { ...@@ -163,7 +194,7 @@ func TestPeer(t *testing.T) {
assert.IsType(t, "string", peer.GetPeerName()) assert.IsType(t, "string", peer.GetPeerName())
localP2P.node.AddCachePeer(peer) localP2P.node.AddCachePeer(peer)
// peer.GetRunning()
localP2P.node.natOk() localP2P.node.natOk()
localP2P.node.flushNodePort(43803, 43802) localP2P.node.flushNodePort(43803, 43802)
p2pcli := NewNormalP2PCli() p2pcli := NewNormalP2PCli()
...@@ -193,6 +224,8 @@ func TestPeer(t *testing.T) { ...@@ -193,6 +224,8 @@ func TestPeer(t *testing.T) {
_, err = p2pcli.GetAddr(peer) _, err = p2pcli.GetAddr(peer)
assert.Nil(t, err) assert.Nil(t, err)
localP2P.node.pubsub.FIFOPub(&types.P2PTx{Tx: &types.Transaction{}}, "tx")
localP2P.node.pubsub.FIFOPub(&types.P2PBlock{Block: &types.Block{}}, "block")
// //测试获取高度 // //测试获取高度
height, err := p2pcli.GetBlockHeight(localP2P.node.nodeInfo) height, err := p2pcli.GetBlockHeight(localP2P.node.nodeInfo)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -204,7 +237,12 @@ func TestPeer(t *testing.T) { ...@@ -204,7 +237,12 @@ func TestPeer(t *testing.T) {
job.GetFreePeer(1) job.GetFreePeer(1)
var ins []*types.Inventory var ins []*types.Inventory
var inv types.Inventory
inv.Ty = msgBlock
inv.Height = 2
ins = append(ins, &inv)
var bChan = make(chan *types.BlockPid, 256) var bChan = make(chan *types.BlockPid, 256)
job.syncDownloadBlock(peer, ins[0], bChan)
respIns := job.DownloadBlock(ins, bChan) respIns := job.DownloadBlock(ins, bChan)
t.Log(respIns) t.Log(respIns)
job.ResetDownloadPeers([]*Peer{peer}) job.ResetDownloadPeers([]*Peer{peer})
...@@ -277,6 +315,7 @@ func TestGrpcStreamConns(t *testing.T) { ...@@ -277,6 +315,7 @@ func TestGrpcStreamConns(t *testing.T) {
_, err = cli.ServerStreamSend(context.Background(), ping) _, err = cli.ServerStreamSend(context.Background(), ping)
assert.Nil(t, err) assert.Nil(t, err)
_, err = cli.ServerStreamRead(context.Background()) _, err = cli.ServerStreamRead(context.Background())
assert.Nil(t, err) assert.Nil(t, err)
var emptyBlock types.P2PBlock var emptyBlock types.P2PBlock
...@@ -359,6 +398,7 @@ func TestAddrBook(t *testing.T) { ...@@ -359,6 +398,7 @@ func TestAddrBook(t *testing.T) {
assert.Equal(t, addrBook.genPubkey(hex.EncodeToString(prv)), pubstr) assert.Equal(t, addrBook.genPubkey(hex.EncodeToString(prv)), pubstr)
addrBook.Save() addrBook.Save()
addrBook.GetAddrs() addrBook.GetAddrs()
addrBook.ResetPeerkey(hex.EncodeToString(prv), pubstr)
} }
func TestBytesToInt32(t *testing.T) { func TestBytesToInt32(t *testing.T) {
...@@ -393,8 +433,15 @@ func TestP2pListen(t *testing.T) { ...@@ -393,8 +433,15 @@ func TestP2pListen(t *testing.T) {
listen1.Close() listen1.Close()
listen2.Close() listen2.Close()
} }
func TestP2pRestart(t *testing.T) {
assert.Equal(t, false, p2pModule.isClose())
assert.Equal(t, false, p2pModule.isRestart())
p2pModule.ReStart()
}
func TestP2pClose(t *testing.T) { func TestP2pClose(t *testing.T) {
p2pModule.Wait()
p2pModule.Close() p2pModule.Close()
os.RemoveAll(dataDir) os.RemoveAll(dataDir)
} }
...@@ -364,6 +364,7 @@ func (m *Cli) GetHeaders(msg *queue.Message, taskindex int64) { ...@@ -364,6 +364,7 @@ func (m *Cli) GetHeaders(msg *queue.Message, taskindex int64) {
msg.Reply(m.network.client.NewMessage("blockchain", pb.EventReply, pb.Reply{Msg: []byte("no pid")})) msg.Reply(m.network.client.NewMessage("blockchain", pb.EventReply, pb.Reply{Msg: []byte("no pid")}))
return return
} }
msg.Reply(m.network.client.NewMessage("blockchain", pb.EventReply, pb.Reply{IsOk: true, Msg: []byte("ok")})) msg.Reply(m.network.client.NewMessage("blockchain", pb.EventReply, pb.Reply{IsOk: true, Msg: []byte("ok")}))
peers, infos := m.network.node.GetActivePeers() peers, infos := m.network.node.GetActivePeers()
for paddr, info := range infos { for paddr, info := range infos {
...@@ -411,6 +412,7 @@ func (m *Cli) GetBlocks(msg *queue.Message, taskindex int64) { ...@@ -411,6 +412,7 @@ func (m *Cli) GetBlocks(msg *queue.Message, taskindex int64) {
req := msg.GetData().(*pb.ReqBlocks) req := msg.GetData().(*pb.ReqBlocks)
log.Info("GetBlocks", "start", req.GetStart(), "end", req.GetEnd()) log.Info("GetBlocks", "start", req.GetStart(), "end", req.GetEnd())
pids := req.GetPid() pids := req.GetPid()
log.Info("GetBlocks", "pids", pids)
var Inventorys = make([]*pb.Inventory, 0) var Inventorys = make([]*pb.Inventory, 0)
for i := req.GetStart(); i <= req.GetEnd(); i++ { for i := req.GetStart(); i <= req.GetEnd(); i++ {
var inv pb.Inventory var inv pb.Inventory
...@@ -424,7 +426,7 @@ func (m *Cli) GetBlocks(msg *queue.Message, taskindex int64) { ...@@ -424,7 +426,7 @@ func (m *Cli) GetBlocks(msg *queue.Message, taskindex int64) {
var downloadPeers []*Peer var downloadPeers []*Peer
peers, infos := m.network.node.GetActivePeers() peers, infos := m.network.node.GetActivePeers()
if len(pids) > 0 && pids[0] != "" { //指定Pid 下载数据 if len(pids) > 0 && pids[0] != "" { //指定Pid 下载数据
log.Info("fetch from peer in pids") log.Info("fetch from peer in pids", "pids", pids)
var pidmap = make(map[string]bool) var pidmap = make(map[string]bool)
for _, pid := range pids { for _, pid := range pids {
pidmap[pid] = true pidmap[pid] = true
......
...@@ -89,7 +89,6 @@ func (s *P2pserver) Ping(ctx context.Context, in *pb.P2PPing) (*pb.P2PPong, erro ...@@ -89,7 +89,6 @@ func (s *P2pserver) Ping(ctx context.Context, in *pb.P2PPing) (*pb.P2PPong, erro
} }
} }
log.Debug("Send Pong", "Nonce", in.GetNonce()) log.Debug("Send Pong", "Nonce", in.GetNonce())
return &pb.P2PPong{Nonce: in.GetNonce()}, nil return &pb.P2PPong{Nonce: in.GetNonce()}, nil
...@@ -413,11 +412,28 @@ func (s *P2pserver) ServerStreamSend(in *pb.P2PPing, stream pb.P2Pgservice_Serve ...@@ -413,11 +412,28 @@ func (s *P2pserver) ServerStreamSend(in *pb.P2PPing, stream pb.P2Pgservice_Serve
log.Debug("ServerStreamSend") log.Debug("ServerStreamSend")
peername := hex.EncodeToString(in.GetSign().GetPubkey()) peername := hex.EncodeToString(in.GetSign().GetPubkey())
defer s.deleteInBoundPeerInfo(peername)
defer func() { s.deleteSChan <- stream }()
dataChain := s.addStreamHandler(stream) dataChain := s.addStreamHandler(stream)
for data := range dataChain { for data := range dataChain {
if s.IsClose() { if s.IsClose() {
return fmt.Errorf("node close") return fmt.Errorf("node close")
} }
innerpeer := s.getInBoundPeerInfo(peername)
if innerpeer != nil {
if !s.checkVersion(innerpeer.p2pversion) {
log.Error("ServerStreamSend CheckVersion", "version", innerpeer.p2pversion)
if innerpeer.p2pversion == 0 {
return fmt.Errorf("version empty")
}
return pb.ErrVersion
}
} else {
return fmt.Errorf("no peer info")
}
p2pdata := new(pb.BroadCastData) p2pdata := new(pb.BroadCastData)
if block, ok := data.(*pb.P2PBlock); ok { if block, ok := data.(*pb.P2PBlock); ok {
if block.GetBlock() != nil { if block.GetBlock() != nil {
...@@ -441,8 +457,8 @@ func (s *P2pserver) ServerStreamSend(in *pb.P2PPing, stream pb.P2Pgservice_Serve ...@@ -441,8 +457,8 @@ func (s *P2pserver) ServerStreamSend(in *pb.P2PPing, stream pb.P2Pgservice_Serve
err := stream.Send(p2pdata) err := stream.Send(p2pdata)
if err != nil { if err != nil {
s.deleteSChan <- stream //s.deleteSChan <- stream
s.deleteInBoundPeerInfo(peername) //s.deleteInBoundPeerInfo(peername)
return err return err
} }
} }
...@@ -465,12 +481,15 @@ func (s *P2pserver) ServerStreamRead(stream pb.P2Pgservice_ServerStreamReadServe ...@@ -465,12 +481,15 @@ func (s *P2pserver) ServerStreamRead(stream pb.P2Pgservice_ServerStreamReadServe
return fmt.Errorf("ctx.Addr format err") return fmt.Errorf("ctx.Addr format err")
} }
} else { } else {
return fmt.Errorf("getctx err") return fmt.Errorf("getctx err")
} }
var hash [64]byte var hash [64]byte
var peeraddr, peername string var peeraddr, peername string
defer s.deleteInBoundPeerInfo(peername) defer s.deleteInBoundPeerInfo(peername)
defer stream.SendAndClose(&pb.ReqNil{})
var in = new(pb.BroadCastData) var in = new(pb.BroadCastData)
for { for {
...@@ -484,6 +503,17 @@ func (s *P2pserver) ServerStreamRead(stream pb.P2Pgservice_ServerStreamReadServe ...@@ -484,6 +503,17 @@ func (s *P2pserver) ServerStreamRead(stream pb.P2Pgservice_ServerStreamReadServe
} }
if block := in.GetBlock(); block != nil { if block := in.GetBlock(); block != nil {
innerpeer := s.getInBoundPeerInfo(peername)
if innerpeer != nil {
log.Error("ServerStreamRead CheckVersion", "version", innerpeer.p2pversion, "ip", remoteIP)
if !s.checkVersion(innerpeer.p2pversion) {
return pb.ErrVersion
}
} else {
log.Error("ServerStreamRead", "no peer info", "")
return fmt.Errorf("no peer info")
}
hex.Encode(hash[:], block.GetBlock().Hash()) hex.Encode(hash[:], block.GetBlock().Hash())
blockhash := string(hash[:]) blockhash := string(hash[:])
...@@ -507,6 +537,15 @@ func (s *P2pserver) ServerStreamRead(stream pb.P2Pgservice_ServerStreamReadServe ...@@ -507,6 +537,15 @@ func (s *P2pserver) ServerStreamRead(stream pb.P2Pgservice_ServerStreamReadServe
} }
} else if tx := in.GetTx(); tx != nil { } else if tx := in.GetTx(); tx != nil {
innerpeer := s.getInBoundPeerInfo(peername)
if innerpeer != nil {
if !s.checkVersion(innerpeer.p2pversion) {
return pb.ErrVersion
}
} else {
return fmt.Errorf("no peer info")
}
hex.Encode(hash[:], tx.GetTx().Hash()) hex.Encode(hash[:], tx.GetTx().Hash())
txhash := string(hash[:]) txhash := string(hash[:])
log.Debug("ServerStreamRead", "txhash:", txhash) log.Debug("ServerStreamRead", "txhash:", txhash)
......
...@@ -181,7 +181,7 @@ func (p *Peer) sendStream() { ...@@ -181,7 +181,7 @@ func (p *Peer) sendStream() {
//Stream Send data //Stream Send data
for { for {
if !p.GetRunning() { if !p.GetRunning() {
log.Info("sendStream peer is not running") log.Info("sendStream peer connect closed", "peerid", p.GetPeerName())
return return
} }
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
...@@ -239,6 +239,9 @@ func (p *Peer) sendStream() { ...@@ -239,6 +239,9 @@ func (p *Peer) sendStream() {
SEND_LOOP: SEND_LOOP:
for { for {
if !p.GetRunning() {
return
}
select { select {
case task := <-p.taskChan: case task := <-p.taskChan:
if !p.GetRunning() { if !p.GetRunning() {
...@@ -247,7 +250,7 @@ func (p *Peer) sendStream() { ...@@ -247,7 +250,7 @@ func (p *Peer) sendStream() {
log.Error("CloseSend", "err", errs) log.Error("CloseSend", "err", errs)
} }
cancel() cancel()
log.Error("sendStream peer is not running") log.Error("sendStream peer connect closed", "peerName", p.GetPeerName())
return return
} }
p2pdata := new(pb.BroadCastData) p2pdata := new(pb.BroadCastData)
...@@ -263,6 +266,7 @@ func (p *Peer) sendStream() { ...@@ -263,6 +266,7 @@ func (p *Peer) sendStream() {
log.Debug("sendStream", "find peer height>this broadblock ,send process", "break") log.Debug("sendStream", "find peer height>this broadblock ,send process", "break")
continue continue
} }
} }
p2pdata.Value = &pb.BroadCastData_Block{Block: block} p2pdata.Value = &pb.BroadCastData_Block{Block: block}
...@@ -344,6 +348,7 @@ func (p *Peer) readStream() { ...@@ -344,6 +348,7 @@ func (p *Peer) readStream() {
} }
return return
} }
data, err := resp.Recv() data, err := resp.Recv()
P2pComm.CollectPeerStat(err, p) P2pComm.CollectPeerStat(err, p)
if err != nil { if err != nil {
...@@ -425,6 +430,10 @@ func (p *Peer) readStream() { ...@@ -425,6 +430,10 @@ func (p *Peer) readStream() {
// GetRunning get running ok or not // GetRunning get running ok or not
func (p *Peer) GetRunning() bool { func (p *Peer) GetRunning() bool {
if p.node.isClose() {
return false
}
return atomic.LoadInt32(&p.isclose) != 1 return atomic.LoadInt32(&p.isclose) != 1
} }
......
...@@ -76,17 +76,15 @@ func (j *JSONRPCServer) Listen() (int, error) { ...@@ -76,17 +76,15 @@ func (j *JSONRPCServer) Listen() (int, error) {
} }
//格式做一个检查 //格式做一个检查
client, err := parseJSONRpcParams(data) client, err := parseJSONRpcParams(data)
errstr := "nil"
if err != nil { if err != nil {
errstr = err.Error() err = fmt.Errorf(`invalid json request err:%s`, err.Error())
log.Debug("JSONRPCServer", "request", string(data), "parseErr", err)
writeError(w, r, 0, err.Error())
return
} }
funcName := strings.Split(client.Method, ".")[len(strings.Split(client.Method, "."))-1] funcName := strings.Split(client.Method, ".")[len(strings.Split(client.Method, "."))-1]
if !checkFilterPrintFuncBlacklist(funcName) { if !checkFilterPrintFuncBlacklist(funcName) {
log.Debug("JSONRPCServer", "request", string(data), "err", errstr) log.Debug("JSONRPCServer", "request", string(data))
}
if err != nil {
writeError(w, r, 0, fmt.Sprintf(`parse request err %s`, err.Error()))
return
} }
//Release local request //Release local request
ipaddr := net.ParseIP(ip) ipaddr := net.ParseIP(ip)
......
...@@ -215,7 +215,7 @@ func createTxGroup(cmd *cobra.Command, args []string) { ...@@ -215,7 +215,7 @@ func createTxGroup(cmd *cobra.Command, args []string) {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
return return
} }
err = group.Check(0, types.GInt("MinFee"), types.GInt("MaxFee")) err = group.CheckWithFork(true, true, 0, types.GInt("MinFee"), types.GInt("MaxFee"))
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
return return
......
...@@ -148,26 +148,6 @@ type GetTotalCoinsResult struct { ...@@ -148,26 +148,6 @@ type GetTotalCoinsResult struct {
DifferenceAmount string `json:"differenceAmount,omitempty"` DifferenceAmount string `json:"differenceAmount,omitempty"`
} }
// GetTicketStatisticResult defines ticketstatistic result rpc command
type GetTicketStatisticResult struct {
CurrentOpenCount int64 `json:"currentOpenCount"`
TotalMinerCount int64 `json:"totalMinerCount"`
TotalCloseCount int64 `json:"totalCloseCount"`
}
// GetTicketMinerInfoResult defines ticker minerinformation result rpc command
type GetTicketMinerInfoResult struct {
TicketID string `json:"ticketId"`
Status string `json:"status"`
PrevStatus string `json:"prevStatus"`
IsGenesis bool `json:"isGenesis"`
CreateTime string `json:"createTime"`
MinerTime string `json:"minerTime"`
CloseTime string `json:"closeTime"`
MinerValue int64 `json:"minerValue,omitempty"`
MinerAddress string `json:"minerAddress,omitempty"`
}
// UTXOGlobalIndex defines utxo globalindex command // UTXOGlobalIndex defines utxo globalindex command
type UTXOGlobalIndex struct { type UTXOGlobalIndex struct {
// Height int64 `json:"height,omitempty"` // Height int64 `json:"height,omitempty"`
......
...@@ -35,20 +35,28 @@ func Register(name string, create DriverCreate, height int64) { ...@@ -35,20 +35,28 @@ func Register(name string, create DriverCreate, height int64) {
if _, dup := registedExecDriver[name]; dup { if _, dup := registedExecDriver[name]; dup {
panic("Execute: Register called twice for driver " + name) panic("Execute: Register called twice for driver " + name)
} }
driverWithHeight := &driverWithHeight{ driverHeight := &driverWithHeight{
create: create, create: create,
height: height, height: height,
} }
registedExecDriver[name] = driverWithHeight registedExecDriver[name] = driverHeight
//考虑到前期平行链兼容性和防止误操作(平行链下转账到一个主链合约),也会注册主链合约(不带前缀)的地址
registerAddress(name)
execDrivers[ExecAddress(name)] = driverHeight
if types.IsPara() { if types.IsPara() {
paraHeight := types.GetFork("ForkEnableParaRegExec")
if paraHeight < height {
paraHeight = height
}
//平行链的合约地址是通过user.p.x.name计算的 //平行链的合约地址是通过user.p.x.name计算的
paraDriverName := types.ExecName(name) paraDriverName := types.ExecName(name)
registerAddress(paraDriverName) registerAddress(paraDriverName)
execDrivers[ExecAddress(paraDriverName)] = driverWithHeight execDrivers[ExecAddress(paraDriverName)] = &driverWithHeight{
create: create,
height: paraHeight,
}
} }
//考虑到前期平行链兼容性和防止误操作(平行链下转账到一个主链合约),也会注册主链合约(不带前缀)的地址
registerAddress(name)
execDrivers[ExecAddress(name)] = driverWithHeight
} }
// LoadDriver load driver // LoadDriver load driver
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package store package store
import ( import (
"sync"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
clog "github.com/33cn/chain33/common/log" clog "github.com/33cn/chain33/common/log"
log "github.com/33cn/chain33/common/log/log15" log "github.com/33cn/chain33/common/log/log15"
...@@ -61,6 +63,7 @@ type BaseStore struct { ...@@ -61,6 +63,7 @@ type BaseStore struct {
qclient queue.Client qclient queue.Client
done chan struct{} done chan struct{}
child SubStore child SubStore
wg sync.WaitGroup
} }
// NewBaseStore new base store struct // NewBaseStore new base store struct
...@@ -94,7 +97,9 @@ func (store *BaseStore) Wait() {} ...@@ -94,7 +97,9 @@ func (store *BaseStore) Wait() {}
func (store *BaseStore) processMessage(msg *queue.Message) { func (store *BaseStore) processMessage(msg *queue.Message) {
client := store.qclient client := store.qclient
if msg.Ty == types.EventStoreSet { if msg.Ty == types.EventStoreSet {
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
datas := msg.GetData().(*types.StoreSetWithSync) datas := msg.GetData().(*types.StoreSetWithSync)
hash, err := store.child.Set(datas.Storeset, datas.Sync) hash, err := store.child.Set(datas.Storeset, datas.Sync)
if err != nil { if err != nil {
...@@ -104,13 +109,17 @@ func (store *BaseStore) processMessage(msg *queue.Message) { ...@@ -104,13 +109,17 @@ func (store *BaseStore) processMessage(msg *queue.Message) {
msg.Reply(client.NewMessage("", types.EventStoreSetReply, &types.ReplyHash{Hash: hash})) msg.Reply(client.NewMessage("", types.EventStoreSetReply, &types.ReplyHash{Hash: hash}))
}() }()
} else if msg.Ty == types.EventStoreGet { } else if msg.Ty == types.EventStoreGet {
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
datas := msg.GetData().(*types.StoreGet) datas := msg.GetData().(*types.StoreGet)
values := store.child.Get(datas) values := store.child.Get(datas)
msg.Reply(client.NewMessage("", types.EventStoreGetReply, &types.StoreReplyValue{Values: values})) msg.Reply(client.NewMessage("", types.EventStoreGetReply, &types.StoreReplyValue{Values: values}))
}() }()
} else if msg.Ty == types.EventStoreMemSet { //只是在内存中set 一下,并不改变状态 } else if msg.Ty == types.EventStoreMemSet { //只是在内存中set 一下,并不改变状态
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
datas := msg.GetData().(*types.StoreSetWithSync) datas := msg.GetData().(*types.StoreSetWithSync)
var hash []byte var hash []byte
var err error var err error
...@@ -126,7 +135,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) { ...@@ -126,7 +135,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) {
msg.Reply(client.NewMessage("", types.EventStoreSetReply, &types.ReplyHash{Hash: hash})) msg.Reply(client.NewMessage("", types.EventStoreSetReply, &types.ReplyHash{Hash: hash}))
}() }()
} else if msg.Ty == types.EventStoreCommit { //把内存中set 的交易 commit } else if msg.Ty == types.EventStoreCommit { //把内存中set 的交易 commit
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
req := msg.GetData().(*types.ReqHash) req := msg.GetData().(*types.ReqHash)
var hash []byte var hash []byte
var err error var err error
...@@ -145,7 +156,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) { ...@@ -145,7 +156,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) {
} }
}() }()
} else if msg.Ty == types.EventStoreRollback { } else if msg.Ty == types.EventStoreRollback {
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
req := msg.GetData().(*types.ReqHash) req := msg.GetData().(*types.ReqHash)
hash, err := store.child.Rollback(req) hash, err := store.child.Rollback(req)
if err != nil { if err != nil {
...@@ -155,7 +168,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) { ...@@ -155,7 +168,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) {
} }
}() }()
} else if msg.Ty == types.EventStoreGetTotalCoins { } else if msg.Ty == types.EventStoreGetTotalCoins {
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
req := msg.GetData().(*types.IterateRangeByStateHash) req := msg.GetData().(*types.IterateRangeByStateHash)
resp := &types.ReplyGetTotalCoins{} resp := &types.ReplyGetTotalCoins{}
resp.Count = req.Count resp.Count = req.Count
...@@ -163,7 +178,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) { ...@@ -163,7 +178,9 @@ func (store *BaseStore) processMessage(msg *queue.Message) {
msg.Reply(client.NewMessage("", types.EventGetTotalCoinsReply, resp)) msg.Reply(client.NewMessage("", types.EventGetTotalCoinsReply, resp))
}() }()
} else if msg.Ty == types.EventStoreDel { } else if msg.Ty == types.EventStoreDel {
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
req := msg.GetData().(*types.StoreDel) req := msg.GetData().(*types.StoreDel)
hash, err := store.child.Del(req) hash, err := store.child.Del(req)
if err != nil { if err != nil {
...@@ -173,13 +190,19 @@ func (store *BaseStore) processMessage(msg *queue.Message) { ...@@ -173,13 +190,19 @@ func (store *BaseStore) processMessage(msg *queue.Message) {
} }
}() }()
} else if msg.Ty == types.EventStoreList { } else if msg.Ty == types.EventStoreList {
store.wg.Add(1)
go func() { go func() {
defer store.wg.Done()
req := msg.GetData().(*types.StoreList) req := msg.GetData().(*types.StoreList)
query := NewStoreListQuery(store.child, req) query := NewStoreListQuery(store.child, req)
msg.Reply(client.NewMessage("", types.EventStoreListReply, query.Run())) msg.Reply(client.NewMessage("", types.EventStoreListReply, query.Run()))
}() }()
} else { } else {
go store.child.ProcEvent(msg) store.wg.Add(1)
go func() {
defer store.wg.Done()
store.child.ProcEvent(msg)
}()
} }
} }
...@@ -193,6 +216,7 @@ func (store *BaseStore) Close() { ...@@ -193,6 +216,7 @@ func (store *BaseStore) Close() {
if store.qclient != nil { if store.qclient != nil {
store.qclient.Close() store.qclient.Close()
<-store.done <-store.done
store.wg.Wait()
} }
store.db.Close() store.db.Close()
} }
......
...@@ -214,6 +214,8 @@ func SetTestNetFork() { ...@@ -214,6 +214,8 @@ func SetTestNetFork() {
systemFork.SetFork("chain33", "ForkLocalDBAccess", 1572391) systemFork.SetFork("chain33", "ForkLocalDBAccess", 1572391)
systemFork.SetFork("chain33", "ForkTxGroupPara", 1687250) systemFork.SetFork("chain33", "ForkTxGroupPara", 1687250)
systemFork.SetFork("chain33", "ForkBase58AddressCheck", 1800000) systemFork.SetFork("chain33", "ForkBase58AddressCheck", 1800000)
//这个fork只影响平行链,注册类似user.p.x.exec的driver,新开的平行链设为0即可,老的平行链要设置新的高度
systemFork.SetFork("chain33", "ForkEnableParaRegExec", 0)
} }
......
...@@ -34,33 +34,6 @@ message IterateRangeByStateHash { ...@@ -34,33 +34,6 @@ message IterateRangeByStateHash {
int64 count = 4; int64 count = 4;
} }
message TicketStatistic {
//当前在挖的ticket
int64 currentOpenCount = 1;
//一共挖到的ticket
int64 totalMinerCount = 2;
//一共取消的ticket
int64 totalCancleCount = 3;
}
message TicketMinerInfo {
string ticketId = 1;
// 1 -> 可挖矿 2 -> 已挖成功 3-> 已关闭
int32 status = 2;
int32 prevStatus = 3;
// genesis 创建的私钥比较特殊
bool isGenesis = 4;
//创建ticket时间
int64 createTime = 5;
// ticket挖矿时间
int64 minerTime = 6;
//关闭ticket时间
int64 closeTime = 7;
//挖到的币的数目
int64 minerValue = 8;
string minerAddress = 9;
}
message TotalAmount { message TotalAmount {
// 统计的总数 // 统计的总数
int64 total = 1; int64 total = 1;
......
...@@ -176,6 +176,7 @@ ForkMultiSignAddress=1298600 ...@@ -176,6 +176,7 @@ ForkMultiSignAddress=1298600
ForkBlockCheck=1725000 ForkBlockCheck=1725000
ForkLocalDBAccess=1 ForkLocalDBAccess=1
ForkBase58AddressCheck=1800000 ForkBase58AddressCheck=1800000
ForkEnableParaRegExec=0
[fork.sub.coins] [fork.sub.coins]
Enable=0 Enable=0
......
...@@ -197,6 +197,7 @@ ForkMultiSignAddress=1298600 ...@@ -197,6 +197,7 @@ ForkMultiSignAddress=1298600
ForkBlockCheck=1 ForkBlockCheck=1
ForkLocalDBAccess=0 ForkLocalDBAccess=0
ForkBase58AddressCheck=1800000 ForkBase58AddressCheck=1800000
ForkEnableParaRegExec=0
[fork.sub.coins] [fork.sub.coins]
Enable=0 Enable=0
......
...@@ -11,7 +11,7 @@ import ( ...@@ -11,7 +11,7 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
"strconv" "strconv"
...@@ -172,8 +172,8 @@ func (txgroup *Transactions) IsExpire(height, blocktime int64) bool { ...@@ -172,8 +172,8 @@ func (txgroup *Transactions) IsExpire(height, blocktime int64) bool {
return false return false
} }
//Check height == 0 的时候,不做检查 //CheckWithFork 和fork 无关的有个检查函数
func (txgroup *Transactions) Check(height, minfee, maxFee int64) error { func (txgroup *Transactions) CheckWithFork(checkFork, paraFork bool, height, minfee, maxFee int64) error {
txs := txgroup.Txs txs := txgroup.Txs
if len(txs) < 2 { if len(txs) < 2 {
return ErrTxGroupCountLessThanTwo return ErrTxGroupCountLessThanTwo
...@@ -193,7 +193,7 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error { ...@@ -193,7 +193,7 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
} }
//txgroup 只允许一条平行链的交易, 且平行链txgroup须全部是平行链tx //txgroup 只允许一条平行链的交易, 且平行链txgroup须全部是平行链tx
//如果平行链已经在主链分叉高度前运行了一段时间且有跨链交易,平行链需要自己设置这个fork //如果平行链已经在主链分叉高度前运行了一段时间且有跨链交易,平行链需要自己设置这个fork
if IsFork(height, "ForkTxGroupPara") { if paraFork {
if len(para) > 1 { if len(para) > 1 {
tlog.Info("txgroup has multi para transaction") tlog.Info("txgroup has multi para transaction")
return ErrTxGroupParaCount return ErrTxGroupParaCount
...@@ -225,7 +225,7 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error { ...@@ -225,7 +225,7 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
if txs[0].Fee < totalfee { if txs[0].Fee < totalfee {
return ErrTxFeeTooLow return ErrTxFeeTooLow
} }
if txs[0].Fee > maxFee && maxFee > 0 && IsFork(height, "ForkBlockCheck") { if txs[0].Fee > maxFee && maxFee > 0 && checkFork {
return ErrTxFeeTooHigh return ErrTxFeeTooHigh
} }
//检查hash是否符合要求 //检查hash是否符合要求
...@@ -261,6 +261,13 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error { ...@@ -261,6 +261,13 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
return nil return nil
} }
//Check height == 0 的时候,不做检查
func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
paraFork := IsFork(height, "ForkTxGroupPara")
checkFork := IsFork(height, "ForkBlockCheck")
return txgroup.CheckWithFork(checkFork, paraFork, height, minfee, maxFee)
}
//TransactionCache 交易缓存结构 //TransactionCache 交易缓存结构
type TransactionCache struct { type TransactionCache struct {
*Transaction *Transaction
......
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