Commit f94e04d5 authored by 张振华's avatar 张振华

Merge branch 'master' into dpos

parents c48b4c11 01f6506d
......@@ -150,3 +150,9 @@ chain33_QueryExecBalance() {
ok=$(jq '(.error|not) and (.result[0] | [has("balance", "frozen"), true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
}
chain33_GetAccounts() {
local MAIN_HTTP=$1
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetAccounts","params":[{}]}' -H 'content-type:text/plain;' "${MAIN_HTTP}")
echo "$resp"
}
......@@ -98,6 +98,7 @@ function base_init() {
sed -i $sedfix 's/^minerdisable=.*/minerdisable=false/g' chain33.toml
sed -i $sedfix 's/^nodeGroupFrozenCoins=.*/nodeGroupFrozenCoins=20/g' chain33.toml
sed -i $sedfix 's/^paraConsensusStopBlocks=.*/paraConsensusStopBlocks=100/g' chain33.toml
# ticket
sed -i $sedfix 's/^ticketPrice =.*/ticketPrice = 10000/g' chain33.toml
......
......@@ -216,6 +216,7 @@ superManager=[
]
[exec.sub.paracross]
nodeGroupFrozenCoins=0
paraConsensusStopBlocks=100
#平行链共识停止后主链等待的高度
paraConsensusStopBlocks=30000
......@@ -40,6 +40,7 @@ func (client *commitMsgClient) handler() {
var isRollback bool
var notification []int64 //记录每次系统重启后 min and current height
var finishHeight int64
var consensHeight int64
var sendingHeight int64 //当前发送的最大高度
var sendingMsgs []*pt.ParacrossNodeStatus
var readTick <-chan time.Time
......@@ -155,7 +156,7 @@ out:
//获取正在共识的高度,同步有两层意思,一个是主链跟其他节点完成了同步,另一个是当前平行链节点的高度追赶上了共识高度
//一般来说高度增长从小到大: notifiy[0] -- selfConsensusHeight(mainHeight) -- finishHeight -- sendingHeight -- notify[1]
case rsp := <-consensusCh:
consensHeight := rsp.Height
consensHeight = rsp.Height
plog.Info("para consensus rcv", "notify", notification, "sending", len(sendingMsgs),
"consensHeigt", rsp.Height, "finished", finishHeight, "sync", isSync, "miner", readTick != nil, "consensBlockHash", common.ToHex(rsp.BlockHash))
......@@ -193,7 +194,6 @@ out:
finishHeight = consensHeight
sendingMsgs = nil
client.currentTx = nil
isSync = true
}
case miner := <-client.minerSwitch:
......@@ -212,6 +212,9 @@ out:
ticker = time.NewTicker(time.Second * time.Duration(minerInterval))
readTick = ticker.C
plog.Info("para consensus start mining")
//钱包开启后,从共识高度重新开始发送,在需要重发共识时候,不需要重启设备
finishHeight = consensHeight
}
case <-client.quit:
......
......@@ -2,21 +2,11 @@
# shellcheck disable=SC2128
set +e
set -o pipefail
set -x
MAIN_HTTP=""
CASE_ERR=""
# $2=0 means true, other false
echo_rst() {
if [ "$2" -eq 0 ]; then
echo "$1 ok"
else
echo "$1 err"
CASE_ERR="err"
fi
}
# shellcheck source=/dev/null
source ../dapp-test-common.sh
gID=""
gResp=""
......@@ -49,38 +39,6 @@ chain33_NewAccount() {
echo "$glAddr"
}
function block_wait() {
if [ "$#" -lt 1 ]; then
echo "wrong block_wait params"
exit 1
fi
cur_height=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetLastHeader","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result.height")
expect=$((cur_height + ${1}))
local count=0
while true; do
new_height=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetLastHeader","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".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"
}
chain33_SendToAddress() {
from=$1
to=$2
amount=$3
http=$4
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;' "${http}")
ok=$(jq '(.error|not)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_SendTransaction() {
rawTx=$1
addr=$2
......@@ -98,8 +56,9 @@ chain33_SendTransaction() {
rst=$?
echo_rst "$FUNCNAME" "$rst"
#返回交易
gResp=$(echo "${resp}" | jq -r ".result")
gResp=$(jq -r ".result" <<<"$resp")
echo "tx hash is $gResp"
chain33_QueryTx "$gResp" "${MAIN_HTTP}"
}
blackwhite_BlackwhiteCreateTx() {
......@@ -211,6 +170,8 @@ function run_testcases() {
#给每个账户分别转帐
origAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
chain33_GetAccounts "${MAIN_HTTP}"
#主链中相应账户需要转帐
M_HTTP=${MAIN_HTTP//8901/8801}
chain33_SendToAddress "${origAddr}" "${gameAddr1}" 1000000000 "${M_HTTP}"
......@@ -222,29 +183,23 @@ function run_testcases() {
chain33_SendToAddress "${origAddr}" "${gameAddr2}" 1000000000 "${MAIN_HTTP}"
chain33_SendToAddress "${origAddr}" "${gameAddr3}" 1000000000 "${MAIN_HTTP}"
block_wait 1
#给游戏合约中转帐
chain33_SendToAddress "${gameAddr1}" "${bwExecAddr}" 500000000 "${MAIN_HTTP}"
chain33_SendToAddress "${gameAddr2}" "${bwExecAddr}" 500000000 "${MAIN_HTTP}"
chain33_SendToAddress "${gameAddr3}" "${bwExecAddr}" 500000000 "${MAIN_HTTP}"
block_wait 1
blackwhite_BlackwhiteCreateTx "${gameAddr1}"
block_wait 1
blackwhite_BlackwhitePlayTx "${gameAddr1}" "${white0}" "${white1}" "${black2}"
blackwhite_BlackwhitePlayTx "${gameAddr2}" "${white0}" "${black1}" "${black2}"
blackwhite_BlackwhitePlayTx "${gameAddr3}" "${white0}" "${black1}" "${black2}"
block_wait 1
blackwhite_BlackwhiteShowTx "${gameAddr1}" "${sect1}"
blackwhite_BlackwhiteShowTx "${gameAddr2}" "${sect1}"
blackwhite_BlackwhiteShowTx "${gameAddr3}" "${sect1}"
blackwhite_BlackwhiteTimeoutDoneTx "$gID"
#查询部分
block_wait 3
blackwhite_GetBlackwhiteRoundInfo "$gID"
blackwhite_GetBlackwhiteByStatusAndAddr "$gID" "${gameAddr1}"
blackwhite_GetBlackwhiteloopResult "$gID"
......@@ -256,6 +211,7 @@ function main() {
echo "main_ip=$MAIN_HTTP"
init
run_testcases
if [ -n "$CASE_ERR" ]; then
......@@ -264,4 +220,10 @@ function main() {
fi
}
main "$1"
function debug_function() {
set -x
eval "$@"
set +x
}
debug_function main "$1"
#!/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
# shellcheck source=/dev/null
source ../dapp-test-common.sh
}
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
}
MAIN_HTTP=""
function init() {
ispara=$(echo '"'"${MAIN_HTTP}"'"' | jq '.|contains("8901")')
......@@ -149,7 +41,7 @@ function configJSCreator() {
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${super_manager}"
chain33_SignRawTx "$rawtx" "${super_manager}" "${MAIN_HTTP}"
}
function createJSContract() {
......@@ -161,7 +53,7 @@ function createJSContract() {
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${beneficiary_key}"
chain33_SignRawTx "$rawtx" "${beneficiary_key}" "${MAIN_HTTP}"
}
function callJS() {
......@@ -174,7 +66,7 @@ function callJS() {
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${beneficiary_key}"
chain33_SignRawTx "$rawtx" "${beneficiary_key}" "${MAIN_HTTP}"
}
function queryJS() {
......
Title="user.p.para."
CoinSymbol="paracoin"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
......
Title="user.p.guodun."
# TestNet=true
CoinSymbol="paracoin"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
......
This diff is collapsed.
......@@ -38,6 +38,7 @@ func ParcCmd() *cobra.Command {
GetParaListCmd(),
GetNodeGroupCmd(),
GetNodeInfoCmd(),
GetNodeIDInfoCmd(),
GetNodeListCmd(),
NodeGroupStatusCmd(),
NodeGroupListCmd(),
......@@ -251,12 +252,12 @@ func CreateRawNodeManageCmd() *cobra.Command {
}
func addNodeManageFlags(cmd *cobra.Command) {
cmd.Flags().Uint32P("operation", "o", 0, "operation:1:join,2:vote,3:quit")
cmd.Flags().Uint32P("operation", "o", 0, "operation:1:join,2:vote,3:quit,4:cancel")
cmd.MarkFlagRequired("operation")
cmd.Flags().StringP("addr", "a", "", "operating target addr")
cmd.Flags().StringP("addr", "a", "", "operating target addr[optional]")
cmd.Flags().StringP("id", "i", "", "operating target id")
cmd.Flags().StringP("id", "i", "", "operating target id[optional]")
cmd.Flags().Uint32P("value", "v", 1, "vote value: 1:yes,2:no")
cmd.Flags().Float64P("coins_frozen", "c", 0, "frozen coins amount, should not less nodegroup's")
......@@ -455,8 +456,8 @@ func paraList(cmd *cobra.Command, args []string) {
// GetNodeInfoCmd get node current status
func GetNodeInfoCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "node_status",
Short: "Get node current vote status",
Use: "node_addr_status",
Short: "Get node current status:10:joined,11:quited from nodegroup",
Run: nodeInfo,
}
addNodeBodyCmdFlags(cmd)
......@@ -468,7 +469,7 @@ func addNodeBodyCmdFlags(cmd *cobra.Command) {
cmd.MarkFlagRequired("title")
cmd.Flags().StringP("addr", "a", "", "addr apply for super user")
cmd.Flags().StringP("id", "i", "", "id apply for super user")
cmd.MarkFlagRequired("addr")
}
......@@ -476,15 +477,47 @@ func nodeInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
title, _ := cmd.Flags().GetString("title")
addr, _ := cmd.Flags().GetString("addr")
id, _ := cmd.Flags().GetString("id")
params := pt.ReqParacrossNodeInfo{
Title: title,
Addr: addr,
}
var res pt.ParaNodeAddrIdStatus
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeAddrStatus", params, &res)
ctx.Run()
}
// GetNodeIDInfoCmd get node current status
func GetNodeIDInfoCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "node_id_status",
Short: "Get node id current vote status:0:all,1:joining,2:quiting,3:closed,4:canceled",
Run: nodeIDInfo,
}
addNodeIDBodyCmdFlags(cmd)
return cmd
}
func addNodeIDBodyCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("title", "t", "", "parallel chain's title")
cmd.MarkFlagRequired("title")
cmd.Flags().StringP("id", "i", "", "id apply for super user")
cmd.MarkFlagRequired("id")
}
func nodeIDInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
title, _ := cmd.Flags().GetString("title")
id, _ := cmd.Flags().GetString("id")
params := pt.ReqParacrossNodeInfo{
Title: title,
Id: id,
}
var res pt.ParaNodeIdStatus
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeStatus", params, &res)
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeIDStatus", params, &res)
ctx.Run()
}
......
......@@ -260,6 +260,19 @@ func (a *action) getNodesGroup(title string) (map[string]struct{}, error) {
return nodes, nil
}
//根据nodes过滤掉可能退出了的addrs
func updateCommitAddrs(stat *pt.ParacrossHeightStatus, nodes map[string]struct{}) {
details := &pt.ParacrossStatusDetails{}
for i, addr := range stat.Details.Addrs {
if _, ok := nodes[addr]; ok {
details.Addrs = append(details.Addrs, addr)
details.BlockHash = append(details.BlockHash, stat.Details.BlockHash[i])
}
}
stat.Details = details
}
func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error) {
err := checkCommitInfo(commit)
if err != nil {
......@@ -364,6 +377,11 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
}
receipt = makeCommitReceipt(a.fromaddr, commit, &copyStat, stat)
}
if types.IsDappFork(commit.Status.MainBlockHeight, pt.ParaX, pt.ForkCommitTx) {
updateCommitAddrs(stat, nodes)
}
clog.Info("paracross.Commit commit", "stat.title", stat.Title, "stat.height", stat.Height, "notes", len(nodes))
for i, v := range stat.Details.Addrs {
clog.Info("paracross.Commit commit detail", "addr", v, "hash", hex.EncodeToString(stat.Details.BlockHash[i]))
......
......@@ -100,6 +100,20 @@ func (e *Paracross) ExecDelLocal_NodeGroupConfig(payload *pt.ParaNodeGroupConfig
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeGroupStatusTitle(g.Current.Status, g.Current.Title, g.Current.Id), Value: nil})
}
if log.Ty == pt.TyLogParaNodeConfig {
var g pt.ReceiptParaNodeConfig
err := types.Decode(log.Log, &g)
if err != nil {
return nil, err
}
if g.Prev != nil {
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Prev.Status, g.Prev.Id), Value: types.Encode(g.Prev)})
}
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Current.Status, g.Current.Id), Value: nil})
}
}
return &set, nil
}
......
......@@ -104,6 +104,21 @@ func (e *Paracross) ExecLocal_NodeGroupConfig(payload *pt.ParaNodeGroupConfig, t
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeGroupStatusTitle(g.Current.Status, g.Current.Title, g.Current.Id), Value: types.Encode(g.Current)})
}
if log.Ty == pt.TyLogParaNodeConfig {
var g pt.ReceiptParaNodeConfig
err := types.Decode(log.Log, &g)
if err != nil {
return nil, err
}
if g.Prev != nil {
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Prev.Status, g.Current.Id), Value: nil})
}
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Current.Status, g.Current.Id),
Value: types.Encode(g.Current)})
}
}
return &set, nil
}
......
......@@ -85,19 +85,15 @@ func (p *Paracross) Query_GetNodeAddrInfo(in *pt.ReqParacrossNodeInfo) (types.Me
if in == nil || in.Title == "" || in.Addr == "" {
return nil, types.ErrInvalidParam
}
addrStat, err := getNodeAddr(p.GetStateDB(), in.Title, in.Addr)
if err != nil {
return nil, err
}
stat, err := getNodeID(p.GetStateDB(), addrStat.ProposalId)
stat, err := getNodeAddr(p.GetStateDB(), in.Title, in.Addr)
if err != nil {
return nil, err
}
return stat, nil
}
//Query_GetNodeIdInfo get specific node addr info
func (p *Paracross) Query_GetNodeIdInfo(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
//Query_GetNodeIDInfo get specific node addr info
func (p *Paracross) Query_GetNodeIDInfo(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
if in == nil || in.Title == "" || in.Id == "" {
return nil, types.ErrInvalidParam
}
......
......@@ -109,34 +109,17 @@ func checkGroupApplyReceipt(suite *NodeManageTestSuite, receipt *types.Receipt)
assert.Len(suite.T(), receipt.KV, 1)
assert.Len(suite.T(), receipt.Logs, 1)
var stat pt.ParaNodeIdStatus
err := types.Decode(receipt.KV[0].Value, &stat)
assert.Nil(suite.T(), err, "decode ParaNodeAddrStatus failed")
//suite.T().Log("titleHeight", titleHeight)
assert.Equal(suite.T(), int32(pt.TyLogParaNodeGroupConfig), receipt.Logs[0].Ty)
assert.Equal(suite.T(), int32(pt.ParacrossNodeGroupApply), stat.Status)
}
func checkGroupApproveReceipt(suite *NodeManageTestSuite, receipt *types.Receipt) {
assert.Equal(suite.T(), receipt.Ty, int32(types.ExecOk))
assert.Len(suite.T(), receipt.KV, 11)
assert.Len(suite.T(), receipt.Logs, 7)
len := len(receipt.KV)
var stat pt.ParaNodeIdStatus
err := types.Decode(receipt.KV[len-1].Value, &stat)
assert.Nil(suite.T(), err, "decode ParaNodeAddrStatus failed")
//suite.T().Log("ty len-1", receipt.Logs[lenLogs-1].Ty,"len",lenLogs)
assert.Equal(suite.T(), int32(pt.TyLogParaNodeGroupStatusUpdate), receipt.Logs[7-1].Ty)
assert.Equal(suite.T(), int32(pt.ParacrossNodeGroupApprove), stat.Status)
}
func checkJoinReceipt(suite *NodeManageTestSuite, receipt *types.Receipt) {
assert.Equal(suite.T(), receipt.Ty, int32(types.ExecOk))
assert.Len(suite.T(), receipt.KV, 2)
assert.Len(suite.T(), receipt.KV, 1)
assert.Len(suite.T(), receipt.Logs, 1)
var stat pt.ParaNodeIdStatus
......@@ -151,7 +134,7 @@ func checkJoinReceipt(suite *NodeManageTestSuite, receipt *types.Receipt) {
func checkQuitReceipt(suite *NodeManageTestSuite, receipt *types.Receipt) {
assert.Equal(suite.T(), receipt.Ty, int32(types.ExecOk))
assert.Len(suite.T(), receipt.KV, 2)
assert.Len(suite.T(), receipt.KV, 1)
assert.Len(suite.T(), receipt.Logs, 1)
var stat pt.ParaNodeIdStatus
......@@ -298,14 +281,18 @@ func (suite *NodeManageTestSuite) testNodeConfig() {
//Quit test
config = &pt.ParaNodeAddrConfig{
Op: pt.ParaNodeQuit,
Id: g.Current.Id,
Op: pt.ParaNodeQuit,
Addr: Account14K,
}
tx, err = pt.CreateRawNodeConfigTx(config)
suite.Nil(err)
receipt = nodeCommit(suite, PrivKeyD, tx)
checkQuitReceipt(suite, receipt)
suite.Equal(int32(pt.TyLogParaNodeConfig), receipt.Logs[0].Ty)
err = types.Decode(receipt.Logs[0].Log, &g)
suite.Nil(err)
//vote test
voteTest(suite, g.Current.Id, false)
}
......@@ -352,3 +339,18 @@ func TestGetAddrGroup(t *testing.T) {
assert.Equal(t, 0, len(ret))
}
func TestUpdateVotes(t *testing.T) {
stat := &pt.ParaNodeIdStatus{}
votes := &pt.ParaNodeVoteDetail{
Addrs: []string{"AA", "BB", "CC"},
Votes: []string{"yes", "no", "no"}}
stat.Votes = votes
nodes := make(map[string]struct{})
nodes["BB"] = struct{}{}
nodes["CC"] = struct{}{}
updateVotes(stat, nodes)
assert.Equal(t, []string{"BB", "CC"}, stat.Votes.Addrs)
assert.Equal(t, []string{"no", "no"}, stat.Votes.Votes)
}
......@@ -63,7 +63,11 @@ message ParaNodeVoteDetail {
}
message ParaNodeAddrIdStatus {
string proposalId = 1;
string addr = 1;
string proposalId = 2;
string quitId = 3;
int32 status = 4;
string title = 5;
}
message ParaNodeIdStatus {
......@@ -85,6 +89,11 @@ message ReceiptParaNodeConfig {
ParaNodeIdStatus current = 4;
}
message ReceiptParaNodeAddrStatUpdate {
string fromAddr = 1;
ParaNodeAddrIdStatus prev = 2;
ParaNodeAddrIdStatus current = 3;
}
message ReceiptParaNodeVoteDone {
string id = 1;
......@@ -104,7 +113,6 @@ message ParaNodeGroupConfig {
string id = 3;
string addrs = 4;
int64 coinsFrozen = 5;
uint32 emptyBlockInterval = 6;
}
......@@ -114,10 +122,8 @@ message ParaNodeGroupStatus {
string title = 3;
string targetAddrs = 4;
int64 coinsFrozen = 5;
uint32 emptyBlockInterval = 6;
int64 mainHeight = 7;
string fromAddr = 8;
int64 height = 9;
string fromAddr = 6;
int64 height = 7;
}
message ReceiptParaNodeGroupConfig {
......
......@@ -49,6 +49,9 @@ func (c *Jrpc) GetHeight(req *types.ReqString, result *interface{}) error {
}
data, err := c.cli.GetTitle(context.Background(), req)
if err != nil {
return err
}
*result = *data
return err
......@@ -68,6 +71,9 @@ func (c *channelClient) ListTitles(ctx context.Context, req *types.ReqNil) (*pt.
// ListTitles get paracross consensus titles list
func (c *Jrpc) ListTitles(req *types.ReqNil, result *interface{}) error {
data, err := c.cli.ListTitles(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -89,6 +95,9 @@ func (c *Jrpc) GetTitleHeight(req *pt.ReqParacrossTitleHeight, result *interface
return types.ErrInvalidParam
}
data, err := c.cli.GetTitleHeight(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -121,6 +130,9 @@ func (c *Jrpc) GetAssetTxResult(req *types.ReqHash, result *interface{}) error {
return types.ErrInvalidParam
}
data, err := c.cli.GetAssetTxResult(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -175,27 +187,30 @@ func (c *Jrpc) GetBlock2MainInfo(req *types.ReqBlocks, result *interface{}) erro
}
ret, err := c.cli.GetBlock2MainInfo(context.Background(), req)
if err != nil {
return err
}
*result = *ret
return err
return nil
}
// GetNodeStatus get super node status
func (c *channelClient) GetNodeStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeIdStatus, error) {
// GetNodeAddrStatus get super node status
func (c *channelClient) GetNodeAddrStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeAddrIdStatus, error) {
r := *req
data, err := c.Query(pt.GetExecName(), "GetNodeAddrInfo", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParaNodeIdStatus); ok {
if resp, ok := data.(*pt.ParaNodeAddrIdStatus); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeStatus get super node status
// GetNodeIDStatus get super node status
func (c *channelClient) GetNodeIDStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeIdStatus, error) {
r := *req
data, err := c.Query(pt.GetExecName(), "GetNodeIdInfo", &r)
data, err := c.Query(pt.GetExecName(), "GetNodeIDInfo", &r)
if err != nil {
return nil, err
}
......@@ -205,22 +220,30 @@ func (c *channelClient) GetNodeIDStatus(ctx context.Context, req *pt.ReqParacros
return nil, types.ErrDecode
}
// GetNodeStatus get super node status
func (c *Jrpc) GetNodeStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
if req == nil || (req.Addr == "" && req.Id == "") {
// GetNodeAddrStatus get super node status
func (c *Jrpc) GetNodeAddrStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
if req == nil || req.Addr == "" {
return types.ErrInvalidParam
}
var data *pt.ParaNodeIdStatus
var err error
if req.Addr != "" {
data, err = c.cli.GetNodeStatus(context.Background(), req)
data, err := c.cli.GetNodeAddrStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
if req.Id != "" {
data, err = c.cli.GetNodeIDStatus(context.Background(), req)
// GetNodeIDStatus get super node status
func (c *Jrpc) GetNodeIDStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
if req == nil || req.Id == "" {
return types.ErrInvalidParam
}
data, err := c.cli.GetNodeIDStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -241,6 +264,9 @@ func (c *channelClient) ListNodeStatus(ctx context.Context, req *pt.ReqParacross
//ListNodeStatus list super node by status
func (c *Jrpc) ListNodeStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.ListNodeStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -261,6 +287,9 @@ func (c *channelClient) GetNodeGroupAddrs(ctx context.Context, req *pt.ReqParacr
// GetNodeGroupAddrs get super node group addrs
func (c *Jrpc) GetNodeGroupAddrs(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.GetNodeGroupAddrs(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -281,6 +310,9 @@ func (c *channelClient) GetNodeGroupStatus(ctx context.Context, req *pt.ReqParac
// GetNodeGroupStatus get super node group status
func (c *Jrpc) GetNodeGroupStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.GetNodeGroupStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -301,6 +333,9 @@ func (c *channelClient) ListNodeGroupStatus(ctx context.Context, req *pt.ReqPara
//ListNodeGroupStatus list super node group by status
func (c *Jrpc) ListNodeGroupStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.ListNodeGroupStatus(context.Background(), req)
if err != nil {
return err
}
*result = data
return err
}
......@@ -3,6 +3,7 @@ package testnode
//DefaultConfig default config for testnode
var DefaultConfig = `
Title="user.p.guodun."
CoinSymbol="bty"
# TestNet=true
[log]
......
......@@ -45,8 +45,8 @@ var (
ErrParaNodeVoteSelf = errors.New("ErrParaNodeVoteSelf")
//ErrParaNodeGroupFrozenCoinsNotEnough node group coins in tx less than conf's minimum coins
ErrParaNodeGroupFrozenCoinsNotEnough = errors.New("ErrParaNodeGroupFrozenCoinsNotEnough")
//ErrParaNodeGroupStatusWrong node group process wrong status
ErrParaNodeGroupStatusWrong = errors.New("ErrParaNodeGroupStatusWrong")
//ErrParaNodeOpStatusWrong node process wrong status
ErrParaNodeOpStatusWrong = errors.New("ErrParaNodeOpStatusWrong")
//ErrParaConsensStopBlocksNotReach consensus stop blocks not reach
ErrParaConsensStopBlocksNotReach = errors.New("ErrParaConsensStopBlocksNotReach")
)
......@@ -41,6 +41,7 @@ const (
TyLogParaNodeVoteDone = 658
TyLogParaNodeGroupAddrsUpdate = 659
TyLogParaNodeGroupConfig = 660
TyLogParaNodeStatusUpdate = 661
TyLogParaNodeGroupStatusUpdate = 664
)
......@@ -92,6 +93,7 @@ const (
ParaNodeJoin = iota + 1
ParaNodeVote
ParaNodeQuit
ParaNodeCancel
)
// node vote op
......@@ -106,16 +108,24 @@ const (
var ParaNodeVoteStr = []string{"invalid", "yes", "no"}
const (
// ParacrossNodeJoining apply for adding group
ParacrossNodeJoining = iota + 1
// ParacrossNodeJoined pass to add by votes
ParacrossNodeJoined
// ParacrossNodeQuiting apply for quiting
ParacrossNodeQuiting
ParacrossNodeJoined = iota + 10
// ParacrossNodeQuited pass to quite by votes
ParacrossNodeQuited
)
//voting status
const (
// ParacrossNodeIDJoining apply for join group
ParacrossNodeJoining = iota + 1
// ParacrossNodeIDQuiting apply for quiting group
ParacrossNodeQuiting
// ParacrossNodeIDClosed id voting closed
ParacrossNodeClosed
// ParacrossNodeCanceled to cancel apply of joining or quiting
ParacrossNodeCanceled
)
const (
//ParacrossNodeGroupApply apply for para chain node group initially
ParacrossNodeGroupApply = iota + 1
......@@ -204,12 +214,7 @@ func CreateRawNodeConfigTx(config *ParaNodeAddrConfig) (*types.Transaction, erro
//CreateRawNodeGroupApplyTx create raw tx for node group
func CreateRawNodeGroupApplyTx(apply *ParaNodeGroupConfig) (*types.Transaction, error) {
apply.Title = types.GetTitle()
apply.EmptyBlockInterval = 4
apply.Id = strings.Trim(apply.Id, " ")
interval := types.Conf("config.consensus.sub.para").GInt("emptyBlockInterval")
if interval > 0 {
apply.EmptyBlockInterval = uint32(interval)
}
action := &ParacrossAction{
Ty: ParacrossActionNodeGroupApply,
......
This diff is collapsed.
......@@ -62,6 +62,7 @@ func (p *ParacrossType) GetLogMap() map[int64]*types.LogInfo {
TyLogParaAssetDeposit: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogParaAssetDeposit"},
TyLogParacrossMiner: {Ty: reflect.TypeOf(ReceiptParacrossMiner{}), Name: "LogParacrossMiner"},
TyLogParaNodeConfig: {Ty: reflect.TypeOf(ReceiptParaNodeConfig{}), Name: "LogParaNodeConfig"},
TyLogParaNodeStatusUpdate: {Ty: reflect.TypeOf(ReceiptParaNodeAddrStatUpdate{}), Name: "LogParaNodeAddrStatUpdate"},
TyLogParaNodeGroupAddrsUpdate: {Ty: reflect.TypeOf(types.ReceiptConfig{}), Name: "LogParaNodeGroupAddrsUpdate"},
TyLogParaNodeVoteDone: {Ty: reflect.TypeOf(ReceiptParaNodeVoteDone{}), Name: "LogParaNodeVoteDone"},
TyLogParaNodeGroupConfig: {Ty: reflect.TypeOf(ReceiptParaNodeGroupConfig{}), Name: "LogParaNodeGroupConfig"},
......
#!/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"
}
# shellcheck source=/dev/null
source ../dapp-test-common.sh
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
}
MAIN_HTTP=""
txhash=""
function query_unfreezeID() {
block_wait 1
chain33_BlockWait 1 "$MAIN_HTTP"
# echo "req=$req"
local times=10
......@@ -161,8 +55,8 @@ function init() {
owner_key=CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944
#unfreeze_exec_addr=15YsqAuXeEXVHgm6RVx4oJaAAnhtwqnu3H
Chain33_SendToAddress "$owner" "$exec_addr" 500000000
Chain33_SendToAddress "$beneficiary" "$exec_addr" 500000000
Chain33_SendToAddress "$owner" "$exec_addr" 500000000 "${MAIN_HTTP}"
Chain33_SendToAddress "$beneficiary" "$exec_addr" 500000000 "${MAIN_HTTP}"
block_wait 1
}
......@@ -175,7 +69,7 @@ function CreateRawUnfreezeCreate() {
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "$owner_key"
chain33_SignRawTx "$rawtx" "$owner_key" "${MAIN_HTTP}"
query_unfreezeID
}
......@@ -189,8 +83,9 @@ function CreateRawUnfreezeWithdraw() {
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "${beneficiary_key}"
chain33_SignRawTx "$rawtx" "${beneficiary_key}" "${MAIN_HTTP}"
}
function CreateRawUnfreezeTerminate() {
req='{"method":"unfreeze.CreateRawUnfreezeTerminate","params":[{"unfreezeID":"'${uid}'"}]}'
# echo "#request: $req"
......@@ -200,7 +95,7 @@ function CreateRawUnfreezeTerminate() {
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
rawtx=$(jq -r ".result" <<<"$resp")
sign_raw_tx "$rawtx" "$owner_key"
chain33_SignRawTx "$rawtx" "$owner_key" "${MAIN_HTTP}"
block_wait 2
}
......
......@@ -58,6 +58,6 @@ matrix:
- sudo mv docker-compose /usr/local/bin
script:
- make build_ci
- make autotest_ci
- make autotest dapp=all
- make docker-compose && make docker-compose-down
......@@ -49,14 +49,6 @@ function config_chain33() {
else
sed -i $sedfix '/^Title/a TestNet=true' ${chain33Config}
fi
#update fee
sed -i $sedfix 's/Fee=.*/Fee=100000/' ${chain33Config}
#update block time
#update wallet store driver
sed -i $sedfix '/^\[wallet\]/,/^\[wallet./ s/^driver.*/driver="leveldb"/' ${chain33Config}
}
function config_autotest() {
......
......@@ -40,12 +40,10 @@ function config_chain33() {
fi
#update fee
sed -i $sedfix 's/Fee=.*/Fee=100000/' ${chain33Config}
#update block time
# sed -i $sedfix 's/Fee=.*/Fee=100000/' ${chain33Config}
#update wallet store driver
sed -i $sedfix '/^\[wallet\]/,/^\[wallet./ s/^driver.*/driver="leveldb"/' ${chain33Config}
# sed -i $sedfix '/^\[wallet\]/,/^\[wallet./ s/^driver.*/driver="leveldb"/' ${chain33Config}
}
autotestConfig="autotest.toml"
......
......@@ -138,13 +138,17 @@ chain33_GetHeaders() {
chain33_GetLastMemPool() {
req='"method":"Chain33.GetLastMemPool", "params":[{}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$1")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.txs|length >= 0)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
if [ "$IS_PARA" == true ]; then
echo_rst "$FUNCNAME" 2
else
req='"method":"Chain33.GetLastMemPool", "params":[{}]'
echo "#request: $req"
resp=$(curl -ksd "{$req}" "$1")
#echo "#response: $resp"
ok=$(jq '(.error|not) and (.result.txs|length >= 0)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
fi
}
chain33_GetProperFee() {
......@@ -394,11 +398,16 @@ chain33_GetTxByHashes() {
}
chain33_GetMempool() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetMempool","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs|length >= 0)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
if [ "$IS_PARA" == true ]; then
echo_rst "$FUNCNAME" 2
else
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetMempool","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs|length >= 0)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
fi
}
chain33_GetAccountsV2() {
......
......@@ -54,6 +54,8 @@ dbPath="datadir/addrbook"
dbCache=4
# GRPC请求日志文件
grpcLogFile="grpc33.log"
#waitPid 等待seed导入
waitPid=false
[rpc]
# jrpc绑定地址
......
......@@ -53,6 +53,8 @@ grpcLogFile="grpc33.log"
version=216
verMix=216
verMax=217
#waitPid 等待seed导入
waitPid=false
[rpc]
jrpcBindAddr="localhost:8801"
......@@ -69,6 +71,7 @@ name="timeline"
poolCacheSize=10240
minTxFee=100000
maxTxNumPerAccount=100
isLevelFee=false
[mempool.sub.timeline]
poolCacheSize=10240
......@@ -163,6 +166,7 @@ minerwhitelist=["*"]
[exec]
isFree=false
minExecFee=100000
maxExecFee=1000000000
enableStat=false
enableMVCC=false
......
Title="chain33"
TestNet=true
FixTime=false
# 配置主币的名称: 比特元链bty, 部分未配置的平行链需要配置为 bty, 新的平行链配置 para或其他, 不配置panic
CoinSymbol="bty"
[log]
......@@ -77,6 +78,8 @@ dbPath="datadir/addrbook"
dbCache=4
# GRPC请求日志文件
grpcLogFile="grpc33.log"
#waitPid 等待seed导入
waitPid=false
[rpc]
# jrpc绑定地址
......@@ -105,7 +108,10 @@ poolCacheSize=10240
minTxFee=100000
# 每个账户在mempool中得最大交易数量,默认100
maxTxNumPerAccount=100
# 最大得交易手续费用,这个没有默认值,必填,一般是100000
maxTxFee=1000000000
# 是否开启阶梯手续费
isLevelFee=false
[mempool.sub.timeline]
# mempool缓存容量大小,默认10240
......
......@@ -243,15 +243,7 @@ func (a *AddrBook) genPubkey(privkey string) string {
func (a *AddrBook) loadDb() bool {
a.bookDb = db.NewDB("addrbook", a.cfg.Driver, a.cfg.DbPath, a.cfg.DbCache)
privkey, err := a.bookDb.Get([]byte(privKeyTag))
if len(privkey) == 0 || err != nil {
a.initKey()
privkey, _ := a.GetPrivPubKey()
err := a.bookDb.Set([]byte(privKeyTag), []byte(privkey))
if err != nil {
panic(err)
}
} else {
if len(privkey) != 0 && err == nil {
a.setKey(string(privkey), a.genPubkey(string(privkey)))
}
......@@ -393,10 +385,12 @@ 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
if privkey == "" || pubkey == "" {
a.initKey()
privkey, pubkey = a.GetPrivPubKey()
}
a.setKey(privkey, pubkey)
err := a.bookDb.Set([]byte(privKeyTag), []byte(privkey))
if err != nil {
panic(err)
......
......@@ -34,12 +34,6 @@ const (
maxSamIPNum = 20
)
var (
// LocalAddr local address
LocalAddr string
//defaultPort = 13802
)
const (
defalutNatPort = 23802
maxOutBoundNum = 25
......
......@@ -147,6 +147,7 @@ func (d *DownloadJob) GetFreePeer(blockHeight int64) *Peer {
var jobNum int32 = 10
var bestPeer *Peer
for _, peer := range d.downloadPeers {
pbpeer, ok := infos[peer.Addr()]
if ok {
if len(peer.GetPeerName()) == 0 {
......@@ -194,6 +195,7 @@ func (d *DownloadJob) DownloadBlock(invs []*pb.Inventory,
REGET:
freePeer := d.GetFreePeer(inv.GetHeight()) //获取当前任务数最少的节点,相当于 下载速度最快的节点
if freePeer == nil {
log.Debug("no free peer")
time.Sleep(time.Millisecond * 100)
goto REGET
}
......
......@@ -123,7 +123,8 @@ func (n *Node) flushNodePort(localport, export uint16) {
n.nodeInfo.SetExternalAddr(exaddr)
n.nodeInfo.addrBook.AddOurAddress(exaddr)
}
if listenAddr, err := NewNetAddressString(fmt.Sprintf("%v:%v", LocalAddr, localport)); err == nil {
if listenAddr, err := NewNetAddressString(fmt.Sprintf("%v:%v", n.nodeInfo.GetListenAddr().IP.String(), localport)); err == nil {
n.nodeInfo.SetListenAddr(listenAddr)
n.nodeInfo.addrBook.AddOurAddress(listenAddr)
}
......@@ -354,9 +355,9 @@ func (n *Node) detectNodeAddr() {
for {
cfg := n.nodeInfo.cfg
laddr := P2pComm.GetLocalAddr()
LocalAddr = laddr
//LocalAddr = laddr
log.Info("DetectNodeAddr", "addr:", laddr)
if len(LocalAddr) == 0 {
if laddr == "" {
log.Error("DetectNodeAddr", "NetWork Disable p2p Disable", "Retry until Network enable")
time.Sleep(time.Second * 5)
continue
......
......@@ -34,9 +34,10 @@ type P2p struct {
txFactory chan struct{}
otherFactory chan struct{}
waitRestart chan struct{}
closed int32
restart int32
cfg *types.P2P
closed int32
restart int32
cfg *types.P2P
}
// New produce a p2p object
......@@ -96,15 +97,15 @@ func (network *P2p) isRestart() bool {
// Close network client
func (network *P2p) Close() {
log.Info("p2p network start shutdown")
atomic.StoreInt32(&network.closed, 1)
log.Debug("close", "network", "ShowTaskCapcity done")
network.node.Close()
log.Debug("close", "node", "done")
if network.client != nil {
if !network.isRestart() {
network.client.Close()
}
}
network.node.pubsub.Shutdown()
......@@ -126,25 +127,74 @@ func (network *P2p) SetQueueClient(cli queue.Client) {
go func(p2p *P2p) {
p2p.node.Start()
if p2p.isRestart() {
//reset
p2p.node.Start()
atomic.StoreInt32(&p2p.closed, 0)
atomic.StoreInt32(&p2p.restart, 0)
network.waitRestart <- struct{}{}
return
}
p2p.subP2pMsg()
key, pub := p2p.node.nodeInfo.addrBook.GetPrivPubKey()
log.Debug("key pub:", pub, "")
if key == "" {
if p2p.cfg.WaitPid { //key为空,则为初始钱包,阻塞模式,一直等到钱包导入助记词,解锁
if p2p.genAirDropKeyFromWallet() != nil {
return
}
} else {
//创建随机Pid,会同时出现node award ,airdropaddr
p2p.node.nodeInfo.addrBook.ResetPeerkey(key, pub)
go p2p.genAirDropKeyFromWallet()
}
} else {
p2p.subP2pMsg()
go p2p.loadP2PPrivKeyToWallet()
//key 有两种可能,老版本的随机key,也有可能是seed的key, 非阻塞模式
go p2p.genAirDropKeyFromWallet()
}
p2p.node.Start()
log.Debug("SetQueueClient gorountine ret")
}(network)
}
func (network *P2p) loadP2PPrivKeyToWallet() error {
var parm types.ReqWalletImportPrivkey
parm.Privkey, _ = network.node.nodeInfo.addrBook.GetPrivPubKey()
parm.Label = "node award"
ReTry:
msg := network.client.NewMessage("wallet", types.EventWalletImportPrivkey, &parm)
err := network.client.SendTimeout(msg, true, time.Minute)
if err != nil {
log.Error("ImportPrivkey", "Error", err.Error())
return err
}
resp, err := network.client.WaitTimeout(msg, time.Minute)
if err != nil {
if err == types.ErrPrivkeyExist {
return nil
}
if err == types.ErrLabelHasUsed {
//切换随机lable
parm.Label = fmt.Sprintf("node award %v", P2pComm.RandStr(3))
time.Sleep(time.Second)
goto ReTry
}
log.Error("loadP2PPrivKeyToWallet", "err", err.Error())
return err
}
log.Debug("loadP2PPrivKeyToWallet", "resp", resp.GetData())
return nil
}
func (network *P2p) showTaskCapcity() {
ticker := time.NewTicker(time.Second * 5)
log.Info("ShowTaskCapcity", "Capcity", atomic.LoadInt32(&network.txCapcity))
......@@ -160,10 +210,11 @@ func (network *P2p) showTaskCapcity() {
}
func (network *P2p) genAirDropKeyFromWallet() error {
_, savePub := network.node.nodeInfo.addrBook.GetPrivPubKey()
for {
if network.isClose() {
return nil
log.Error("genAirDropKeyFromWallet", "p2p closed", "")
return fmt.Errorf("p2p closed")
}
msg := network.client.NewMessage("wallet", types.EventGetWalletStatus, nil)
err := network.client.SendTimeout(msg, true, time.Minute)
......@@ -179,12 +230,20 @@ func (network *P2p) genAirDropKeyFromWallet() error {
continue
}
if resp.GetData().(*types.WalletStatus).GetIsWalletLock() { //上锁
if savePub == "" {
log.Warn("P2P Stuck ! Wallet must be unlock and save with mnemonics")
}
time.Sleep(time.Second)
continue
}
if !resp.GetData().(*types.WalletStatus).GetIsHasSeed() { //无种子
time.Sleep(time.Second)
if savePub == "" {
log.Warn("P2P Stuck ! Wallet must be imported with mnemonics")
}
time.Sleep(time.Second * 5)
continue
}
......@@ -208,7 +267,6 @@ func (network *P2p) genAirDropKeyFromWallet() error {
} else {
hexPrivkey = reply.GetData()
}
log.Info("genAirDropKeyFromWallet", "hexprivkey", hexPrivkey)
if hexPrivkey[:2] == "0x" {
hexPrivkey = hexPrivkey[2:]
}
......@@ -221,19 +279,30 @@ func (network *P2p) genAirDropKeyFromWallet() error {
log.Info("genAirDropKeyFromWallet", "pubkey", hexPubkey)
_, pub := network.node.nodeInfo.addrBook.GetPrivPubKey()
if pub == hexPubkey {
if savePub == hexPubkey {
return nil
}
if savePub != "" {
//priv,pub是随机公私钥对,兼容老版本,先对其进行导入钱包处理
err = network.loadP2PPrivKeyToWallet()
if err != nil {
log.Error("genAirDropKeyFromWallet", "loadP2PPrivKeyToWallet error", err)
panic(err)
}
network.node.nodeInfo.addrBook.ResetPeerkey(hexPrivkey, hexPubkey)
//重启p2p模块
log.Info("genAirDropKeyFromWallet", "p2p will Restart....")
network.ReStart()
return nil
}
//覆盖addrbook 中的公私钥对
network.node.nodeInfo.addrBook.ResetPeerkey(hexPrivkey, hexPubkey)
//重启p2p模块
log.Info("genAirDropKeyFromWallet", "p2p will Restart....")
network.ReStart()
return nil
}
// ReStart p2p
//ReStart p2p
func (network *P2p) ReStart() {
atomic.StoreInt32(&network.restart, 1)
network.Close()
......@@ -246,67 +315,6 @@ func (network *P2p) ReStart() {
network.SetQueueClient(network.client)
}
func (network *P2p) loadP2PPrivKeyToWallet() 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("GetWalletStatus", "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
}
var parm types.ReqWalletImportPrivkey
parm.Privkey, _ = network.node.nodeInfo.addrBook.GetPrivPubKey()
parm.Label = "node award"
ReTry:
msg := network.client.NewMessage("wallet", types.EventWalletImportPrivkey, &parm)
err := network.client.SendTimeout(msg, true, time.Minute)
if err != nil {
log.Error("ImportPrivkey", "Error", err.Error())
return err
}
resp, err := network.client.WaitTimeout(msg, time.Minute)
if err != nil {
if err == types.ErrPrivkeyExist {
return nil
}
if err == types.ErrLabelHasUsed {
//切换随机lable
parm.Label = fmt.Sprintf("node award %v", P2pComm.RandStr(3))
time.Sleep(time.Second)
goto ReTry
}
log.Error("loadP2PPrivKeyToWallet", "err", err.Error())
return err
}
log.Debug("loadP2PPrivKeyToWallet", "resp", resp.GetData())
return nil
}
func (network *P2p) subP2pMsg() {
if network.client == nil {
......
......@@ -2,6 +2,7 @@ package p2p
import (
"encoding/hex"
//"fmt"
"net"
"os"
"sort"
......@@ -31,8 +32,6 @@ func init() {
q = queue.New("channel")
go q.Start()
p2pModule = initP2p(33802, dataDir)
p2pModule.Wait()
go func() {
cfg, sub := types.InitCfg("../cmd/chain33/chain33.test.toml")
......@@ -115,6 +114,9 @@ func init() {
}
}
}()
time.Sleep(time.Second)
p2pModule = initP2p(53802, dataDir)
p2pModule.Wait()
}
......@@ -128,9 +130,14 @@ func initP2p(port int32, dbpath string) *P2p {
cfg.Version = 119
cfg.ServerStart = true
cfg.Driver = "leveldb"
p2pcli := New(cfg)
p2pcli.SetQueueClient(q.Client())
p2pcli.node.nodeInfo.addrBook.initKey()
privkey, _ := p2pcli.node.nodeInfo.addrBook.GetPrivPubKey()
p2pcli.node.nodeInfo.addrBook.bookDb.Set([]byte(privKeyTag), []byte(privkey))
p2pcli.node.nodeInfo.SetServiceTy(7)
p2pcli.SetQueueClient(q.Client())
return p2pcli
}
......@@ -162,17 +169,19 @@ func TestNetInfo(t *testing.T) {
p2pModule.node.nodeInfo.SetNatDone()
p2pModule.node.nodeInfo.Get()
p2pModule.node.nodeInfo.Set(p2pModule.node.nodeInfo)
assert.NotNil(t, p2pModule.node.nodeInfo.GetListenAddr())
assert.NotNil(t, p2pModule.node.nodeInfo.GetExternalAddr())
}
//测试Peer
func TestPeer(t *testing.T) {
conn, err := grpc.Dial("localhost:33802", grpc.WithInsecure(),
conn, err := grpc.Dial("localhost:53802", grpc.WithInsecure(),
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")))
assert.Nil(t, err)
defer conn.Close()
remote, err := NewNetAddressString("127.0.0.1:33802")
remote, err := NewNetAddressString("127.0.0.1:53802")
assert.Nil(t, err)
localP2P := initP2p(43802, "testdata2")
......@@ -219,7 +228,7 @@ func TestPeer(t *testing.T) {
_, err = p2pcli.SendVersion(peer, localP2P.node.nodeInfo)
assert.Nil(t, err)
t.Log(p2pcli.CheckPeerNatOk("localhost:33802"))
t.Log(p2pcli.CheckPeerNatOk("localhost:53802"))
t.Log("checkself:", p2pcli.CheckSelf("loadhost:43803", localP2P.node.nodeInfo))
_, err = p2pcli.GetAddr(peer)
assert.Nil(t, err)
......@@ -230,7 +239,7 @@ func TestPeer(t *testing.T) {
height, err := p2pcli.GetBlockHeight(localP2P.node.nodeInfo)
assert.Nil(t, err)
assert.Equal(t, int(height), 2019)
assert.Equal(t, false, p2pcli.CheckSelf("localhost:33802", localP2P.node.nodeInfo))
assert.Equal(t, false, p2pcli.CheckSelf("localhost:53802", localP2P.node.nodeInfo))
//测试下载
job := NewDownloadJob(NewP2PCli(localP2P).(*Cli), []*Peer{peer})
......@@ -271,7 +280,7 @@ func TestGrpcConns(t *testing.T) {
var conns []*grpc.ClientConn
for i := 0; i < maxSamIPNum; i++ {
conn, err := grpc.Dial("localhost:33802", grpc.WithInsecure(),
conn, err := grpc.Dial("localhost:53802", grpc.WithInsecure(),
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")))
assert.Nil(t, err)
......@@ -282,7 +291,7 @@ func TestGrpcConns(t *testing.T) {
conns = append(conns, conn)
}
conn, err := grpc.Dial("localhost:33802", grpc.WithInsecure(),
conn, err := grpc.Dial("localhost:53802", grpc.WithInsecure(),
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")))
assert.Nil(t, err)
cli := types.NewP2PgserviceClient(conn)
......@@ -300,7 +309,7 @@ func TestGrpcConns(t *testing.T) {
//测试grpc 流多连接
func TestGrpcStreamConns(t *testing.T) {
conn, err := grpc.Dial("localhost:33802", grpc.WithInsecure(),
conn, err := grpc.Dial("localhost:53802", grpc.WithInsecure(),
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")))
assert.Nil(t, err)
cli := types.NewP2PgserviceClient(conn)
......@@ -329,7 +338,7 @@ func TestGrpcStreamConns(t *testing.T) {
func TestP2pComm(t *testing.T) {
addrs := P2pComm.AddrRouteble([]string{"localhost:33802"})
addrs := P2pComm.AddrRouteble([]string{"localhost:53802"})
t.Log(addrs)
i32 := P2pComm.BytesToInt32([]byte{0xff})
......@@ -398,7 +407,13 @@ func TestAddrBook(t *testing.T) {
assert.Equal(t, addrBook.genPubkey(hex.EncodeToString(prv)), pubstr)
addrBook.Save()
addrBook.GetAddrs()
addrBook.ResetPeerkey("", "")
privkey, _ := addrBook.GetPrivPubKey()
assert.NotEmpty(t, privkey)
addrBook.ResetPeerkey(hex.EncodeToString(prv), pubstr)
resetkey, _ := addrBook.GetPrivPubKey()
assert.NotEqual(t, resetkey, privkey)
}
func TestBytesToInt32(t *testing.T) {
......
......@@ -630,8 +630,8 @@ func (m *Cli) getLocalPeerInfo() (*pb.P2PPeerInfo, error) {
localpeerinfo.Name = pub
localpeerinfo.MempoolSize = int32(meminfo.GetSize())
if m.network.node.nodeInfo.GetExternalAddr().IP == nil {
localpeerinfo.Addr = LocalAddr
localpeerinfo.Port = int32(m.network.node.listenPort)
localpeerinfo.Addr = m.network.node.nodeInfo.GetListenAddr().IP.String()
localpeerinfo.Port = int32(m.network.node.nodeInfo.GetListenAddr().Port)
} else {
localpeerinfo.Addr = m.network.node.nodeInfo.GetExternalAddr().IP.String()
localpeerinfo.Port = int32(m.network.node.nodeInfo.GetExternalAddr().Port)
......
......@@ -574,7 +574,7 @@ func (s *P2pserver) ServerStreamRead(stream pb.P2Pgservice_ServerStreamReadServe
if s.node.Size() > 0 {
if remoteIP != LocalAddr && remoteIP != s.node.nodeInfo.GetExternalAddr().IP.String() {
if remoteIP != s.node.nodeInfo.GetListenAddr().IP.String() && remoteIP != s.node.nodeInfo.GetExternalAddr().IP.String() {
s.node.nodeInfo.SetServiceTy(Service)
}
}
......
......@@ -281,6 +281,35 @@ func (mem *Mempool) RemoveTxsOfBlock(block *types.Block) bool {
return true
}
// GetProperFeeRate 获取合适的手续费率
func (mem *Mempool) GetProperFeeRate() int64 {
baseFeeRate := mem.cache.GetProperFee()
if mem.cfg.IsLevelFee {
return mem.getLevelFeeRate(baseFeeRate)
}
return baseFeeRate
}
// getLevelFeeRate 获取合适的阶梯手续费率
func (mem *Mempool) getLevelFeeRate(baseFeeRate int64) int64 {
var feeRate int64
sumByte := mem.cache.TotalByte()
maxTxNumber := types.GetP(mem.Height()).MaxTxNumber
switch {
case (sumByte > int64(types.MaxBlockSize/100) && sumByte < int64(types.MaxBlockSize/20)) ||
(int64(mem.Size()) >= maxTxNumber/10 && int64(mem.Size()) < maxTxNumber/2):
feeRate = 10 * baseFeeRate
case sumByte >= int64(types.MaxBlockSize/20) || int64(mem.Size()) >= maxTxNumber/2:
feeRate = 100 * baseFeeRate
default:
return baseFeeRate
}
if feeRate > 10000000 {
feeRate = 10000000
}
return feeRate
}
// Mempool.DelBlock将回退的区块内的交易重新加入mempool中
func (mem *Mempool) delBlock(block *types.Block) {
if len(block.Txs) <= 0 {
......
......@@ -6,6 +6,7 @@ package mempool
import (
"github.com/33cn/chain33/types"
"github.com/golang/protobuf/proto"
)
//QueueCache 排队交易处理
......@@ -30,7 +31,9 @@ type Item struct {
type txCache struct {
*AccountTxIndex
*LastTxCache
qcache QueueCache
qcache QueueCache
totalFee int64
totalByte int64
}
//NewTxCache init accountIndex and last cache
......@@ -59,6 +62,8 @@ func (cache *txCache) Remove(hash string) {
}
cache.AccountTxIndex.Remove(tx)
cache.LastTxCache.Remove(tx)
cache.totalFee -= tx.Fee
cache.totalByte -= int64(proto.Size(tx))
}
//Exist 是否存在
......@@ -69,6 +74,14 @@ func (cache *txCache) Exist(hash string) bool {
return cache.qcache.Exist(hash)
}
//GetProperFee 获取合适手续费
func (cache *txCache) GetProperFee() int64 {
if cache.qcache == nil {
return 0
}
return cache.qcache.GetProperFee()
}
//Size cache tx num
func (cache *txCache) Size() int {
if cache.qcache == nil {
......@@ -77,6 +90,16 @@ func (cache *txCache) Size() int {
return cache.qcache.Size()
}
//TotalFee 手续费总和
func (cache *txCache) TotalFee() int64 {
return cache.totalFee
}
//TotalByte 交易字节数总和
func (cache *txCache) TotalByte() int64 {
return cache.totalByte
}
//Walk iter all txs
func (cache *txCache) Walk(count int, cb func(tx *Item) bool) {
if cache.qcache == nil {
......@@ -107,6 +130,8 @@ func (cache *txCache) Push(tx *types.Transaction) error {
return err
}
cache.LastTxCache.Push(tx)
cache.totalFee += tx.Fee
cache.totalByte += int64(proto.Size(tx))
return nil
}
......
......@@ -92,6 +92,13 @@ func (mem *Mempool) checkTxs(msg *queue.Message) *queue.Message {
msg.Data = err
return msg
}
if mem.cfg.IsLevelFee {
err = mem.checkLevelFee(tx)
if err != nil {
msg.Data = err
return msg
}
}
//检查txgroup 中的每个交易
txs, err := tx.GetTxGroup()
if err != nil {
......@@ -114,7 +121,21 @@ func (mem *Mempool) checkTxs(msg *queue.Message) *queue.Message {
return msg
}
//checkTxList 检查账户余额是否足够,并加入到Mempool,成功则传入goodChan,若加入Mempool失败则传入badChan
// checkLevelFee 检查阶梯手续费
func (mem *Mempool) checkLevelFee(tx *types.TransactionCache) error {
//获取mempool里所有交易手续费总和
feeRate := mem.GetProperFeeRate()
totalfee, err := tx.GetTotalFee(feeRate)
if err != nil {
return err
}
if tx.Fee < totalfee {
return types.ErrTxFeeTooLow
}
return nil
}
//checkTxRemote 检查账户余额是否足够,并加入到Mempool,成功则传入goodChan,若加入Mempool失败则传入badChan
func (mem *Mempool) checkTxRemote(msg *queue.Message) *queue.Message {
tx := msg.GetData().(types.TxGroup)
lastheader := mem.GetHeader()
......
......@@ -189,9 +189,9 @@ func (mem *Mempool) eventGetAddrTxs(msg *queue.Message) {
msg.Reply(mem.client.NewMessage("", types.EventReplyAddrTxs, txlist))
}
// eventGetProperFee 获取排队策略中合适的手续费
// eventGetProperFee 获取排队策略中合适的手续费
func (mem *Mempool) eventGetProperFee(msg *queue.Message) {
properFee := mem.cache.qcache.GetProperFee()
properFee := mem.GetProperFeeRate()
msg.Reply(mem.client.NewMessage("rpc", types.EventReplyProperFee,
&types.ReplyProperFee{ProperFee: properFee}))
}
......
......@@ -58,6 +58,10 @@ func (cache *SimpleQueue) Push(tx *Item) error {
// Remove 删除数据
func (cache *SimpleQueue) Remove(hash string) error {
_, err := cache.GetItem(hash)
if err != nil {
return err
}
cache.txList.Remove(hash)
return nil
}
......
Title="chain33"
TestNet=true
CoinSymbol="bty"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
loglevel = "debug"
logConsoleLevel = "info"
# 日志文件名,可带目录,所有生成的日志文件都放到此目录下
logFile = "logs/chain33.log"
# 单个日志文件的最大值(单位:兆)
maxFileSize = 20
# 最多保存的历史日志文件个数
maxBackups = 20
# 最多保存的历史日志消息(单位:天)
maxAge = 28
# 日志文件名是否使用本地事件(否则使用UTC时间)
localTime = true
# 历史日志文件是否压缩(压缩格式为gz)
compress = false
# 是否打印调用源文件和行号
callerFile = true
# 是否打印调用方法
callerFunction = true
[blockchain]
defCacheSize=128
maxFetchBlockNum=128
timeoutSeconds=5
batchBlockNum=128
driver="memdb"
dbPath="datadir"
dbCache=64
isStrongConsistency=true
singleMode=true
batchsync=false
isRecordBlockSequence=true
isParaChain=false
enableTxQuickIndex=false
[p2p]
port=13802
seeds=["47.104.125.151:13802","47.104.125.97:13802","47.104.125.177:13802"]
enable=true
isSeed=true
serverStart=true
msgCacheSize=10240
driver="memdb"
dbPath="datadir/addrbook"
dbCache=4
grpcLogFile="grpc33.log"
version=216
verMix=216
verMax=217
[rpc]
jrpcBindAddr="localhost:8801"
grpcBindAddr="localhost:8802"
whitelist=["127.0.0.1"]
jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"]
enableTLS=false
certFile="cert.pem"
keyFile="key.pem"
[mempool]
name="timeline"
poolCacheSize=10240
minTxFee=100000
maxTxNumPerAccount=100
isLevelFee=false
[mempool.sub.timeline]
poolCacheSize=10240
[mempool.sub.score]
poolCacheSize=10240
timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s
pricePower=1 #常量比例
[mempool.sub.price]
poolCacheSize=10240
[consensus]
name="solo"
minerstart=true
genesisBlockTime=1514533394
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
[mver.consensus]
fundKeyAddr = "1BQXS6TxaYYG5mADaWij4AxhZZUTpw95a5"
coinReward = 18
coinDevFund = 12
ticketPrice = 10000
powLimitBits = "0x1f00ffff"
retargetAdjustmentFactor = 4
futureBlockTime = 16
ticketFrozenTime = 5 #5s only for test
ticketWithdrawTime = 10 #10s only for test
ticketMinerWaitTime = 2 #2s only for test
maxTxNumber = 4 #160
targetTimespan = 2304
targetTimePerBlock = 16
[mver.consensus.ForkChainParamV1]
maxTxNumber = 10000
targetTimespan = 288 #only for test
targetTimePerBlock = 2
[mver.consensus.ForkChainParamV2]
powLimitBits = "0x1f2fffff"
[consensus.sub.solo]
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
genesisBlockTime=1514533394
hotkeyAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
waitTxMs=10
[consensus.sub.ticket]
genesisBlockTime=1514533394
[[consensus.sub.ticket.genesis]]
minerAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
returnAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
count=10000
[[consensus.sub.ticket.genesis]]
minerAddr="1PUiGcbsccfxW3zuvHXZBJfznziph5miAo"
returnAddr="1EbDHAXpoiewjPLX9uqoz38HsKqMXayZrF"
count=10000
[[consensus.sub.ticket.genesis]]
minerAddr="1EDnnePAZN48aC2hiTDzhkczfF39g1pZZX"
returnAddr="1KcCVZLSQYRUwE5EXTsAoQs9LuJW6xwfQa"
count=10000
[store]
name="mavl"
driver="memdb"
dbPath="datadir/mavltree"
dbCache=128
[store.sub.mavl]
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneHeight=10000
# 是否使能mavl数据载入内存
enableMemTree=false
# 是否使能mavl叶子节点数据载入内存
enableMemVal=false
[wallet]
minFee=1000000
driver="memdb"
dbPath="datadir/wallet"
dbCache=16
signType="secp256k1"
[wallet.sub.ticket]
minerwhitelist=["*"]
[exec]
isFree=false
minExecFee=100000
maxExecFee=1000000000
enableStat=false
enableMVCC=false
[exec.sub.token]
saveTokenTxList=true
tokenApprs = [
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK",
"1LY8GFia5EiyoTodMLfkB5PHNNpXRqxhyB",
"1GCzJDS6HbgTQ2emade7mEJGGWFfA15pS9",
"1JYB8sxi4He5pZWHCd3Zi2nypQ4JMB6AxN",
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
]
[exec.sub.relay]
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
[exec.sub.cert]
# 是否启用证书验证和签名
enable=false
# 加密文件路径
cryptoPath="authdir/crypto"
# 带证书签名类型,支持"auth_ecdsa", "auth_sm2"
signType="auth_ecdsa"
[exec.sub.manage]
superManager=[
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK"
]
[health]
listenAddr="localhost:8805"
checkInterval=1
unSyncMaxTimes=2
......@@ -68,6 +68,7 @@ type Mempool struct {
// 每个账户在mempool中得最大交易数量,默认100
MaxTxNumPerAccount int64 `protobuf:"varint,5,opt,name=maxTxNumPerAccount" json:"maxTxNumPerAccount,omitempty"`
MaxTxLast int64 `protobuf:"varint,6,opt,name=maxTxLast" json:"maxTxLast,omitempty"`
IsLevelFee bool `protobuf:"varint,7,opt,name=isLevelFee" json:"isLevelFee,omitempty"`
}
// Consensus 配置
......@@ -176,6 +177,8 @@ type P2P struct {
InnerBounds int32 `protobuf:"varint,15,opt,name=innerBounds" json:"innerBounds,omitempty"`
// 是否使用Github获取种子节点
UseGithub bool `protobuf:"varint,16,opt,name=useGithub" json:"useGithub,omitempty"`
//是否等待Pid
WaitPid bool `protobuf:"varint,17,opt,name=waitPid" json:"waitPid,omitempty"`
}
// RPC 配置
......
......@@ -286,6 +286,12 @@ func Init(t string, cfg *Config) {
panic("config CoinSymbol must without '-'")
}
coinSymbol = cfg.CoinSymbol
} else {
if isPara() {
panic("must config CoinSymbol in para chain")
} else {
coinSymbol = DefaultCoinsSymbol
}
}
}
//local 只用于单元测试
......
......@@ -33,6 +33,11 @@ const (
NoneX = "none"
)
//DefaultCoinsSymbol 默认的主币名称
const (
DefaultCoinsSymbol = "bty"
)
//UserKeyX 用户自定义执行器前缀byte类型
var (
UserKey = []byte(UserKeyX)
......
......@@ -2,6 +2,7 @@ Title="user.p.guodun."
TestNet=false
FixTime=false
EnableParaFork=true
CoinSymbol="gd"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
......
......@@ -2,6 +2,7 @@ Title="user.p.guodun2."
TestNet=false
FixTime=false
EnableParaFork=false
CoinSymbol="gd2"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
......
......@@ -348,6 +348,28 @@ func (tx *TransactionCache) Check(height, minfee, maxFee int64) error {
return tx.checkok
}
//GetTotalFee 获取交易真实费用
func (tx *TransactionCache) GetTotalFee(minFee int64) (int64, error) {
txgroup, err := tx.GetTxGroup()
if err != nil {
tx.checkok = err
return 0, err
}
var totalfee int64
if txgroup == nil {
return tx.GetRealFee(minFee)
}
txs := txgroup.Txs
for i := 0; i < len(txs); i++ {
fee, err := txs[i].GetRealFee(minFee)
if err != nil {
return 0, err
}
totalfee += fee
}
return totalfee, nil
}
//GetTxGroup 获取交易组
func (tx *TransactionCache) GetTxGroup() (*Transactions, error) {
var err error
......
......@@ -49,6 +49,7 @@ var (
datadir = flag.String("datadir", "", "data dir of chain33, include logs and datas")
versionCmd = flag.Bool("v", false, "version")
fixtime = flag.Bool("fixtime", false, "fix time")
waitPid = flag.Bool("waitpid", false, "p2p stuck until seed save info wallet & wallet unlock")
)
//RunChain33 : run Chain33
......@@ -91,6 +92,9 @@ func RunChain33(name string) {
if *fixtime {
cfg.FixTime = *fixtime
}
if *waitPid {
cfg.P2P.WaitPid = *waitPid
}
//set test net flag
types.Init(cfg.Title, cfg)
if cfg.FixTime {
......
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