Commit 48dbbc8b authored by 张振华's avatar 张振华

Merge branch 'master' into guess-rpc-test

parents 16d381fc e3d68c56
......@@ -18,8 +18,8 @@ import (
)
var (
consensusInterval = 16 //about 1 new block interval
minerInterval = 5
consensusInterval = 10 //about 1 new block interval
minerInterval = 10 //5s的主块间隔后分叉概率增加,10s可以消除一些分叉回退
)
type commitMsgClient struct {
......
This diff is collapsed.
......@@ -251,36 +251,25 @@ func CreateRawNodeManageCmd() *cobra.Command {
}
func addNodeManageFlags(cmd *cobra.Command) {
cmd.Flags().StringP("operation", "o", "", "operation:join,quit,vote")
cmd.Flags().Uint32P("operation", "o", 0, "operation:1:join,2:vote,3:quit")
cmd.MarkFlagRequired("operation")
cmd.Flags().StringP("addr", "a", "", "operating target addr")
cmd.MarkFlagRequired("addrs")
cmd.Flags().StringP("value", "v", "", "vote value: yes,no")
cmd.Flags().Float64P("coins_frozen", "c", 0, "join to frozen coins amount, not less config")
cmd.Flags().StringP("id", "i", "", "operating target id")
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")
}
func createNodeTx(cmd *cobra.Command, args []string) {
op, _ := cmd.Flags().GetString("operation")
op, _ := cmd.Flags().GetUint32("operation")
opAddr, _ := cmd.Flags().GetString("addr")
val, _ := cmd.Flags().GetString("value")
id, _ := cmd.Flags().GetString("id")
val, _ := cmd.Flags().GetUint32("value")
coins, _ := cmd.Flags().GetFloat64("coins_frozen")
if op != "vote" && op != "quit" && op != "join" {
fmt.Println("operation should be one of join,quit,vote")
return
}
if opAddr == "" {
fmt.Println("addr parameter should not be null")
return
}
if op == "vote" && (val != "yes" && val != "no") {
fmt.Println("vote operation value parameter require yes or no value")
return
}
payload := &pt.ParaNodeAddrConfig{Op: op, Value: val, Addr: opAddr, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
payload := &pt.ParaNodeAddrConfig{Op: op, Id: id, Value: val, Addr: opAddr, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pt.ParaX),
ActionName: "NodeConfig",
......@@ -305,11 +294,12 @@ func CreateNodeGroupApplyCmd() *cobra.Command {
}
func addNodeGroupApplyCmdFlags(cmd *cobra.Command) {
cmd.Flags().Uint32P("operation", "o", 0, "operation:1:apply,2:approve,3:quit")
cmd.Flags().Uint32P("operation", "o", 0, "operation:1:apply,2:approve,3:quit,4:modify")
cmd.MarkFlagRequired("operation")
cmd.Flags().StringP("id", "i", "", "apply id for nodegroup ")
cmd.Flags().StringP("addrs", "a", "", "addrs apply for super node,split by ',' ")
cmd.MarkFlagRequired("addrs")
cmd.Flags().Float64P("coins_frozen", "c", 0, "coins amount to frozen, not less config")
......@@ -318,18 +308,10 @@ func addNodeGroupApplyCmdFlags(cmd *cobra.Command) {
func nodeGroupApply(cmd *cobra.Command, args []string) {
op, _ := cmd.Flags().GetUint32("operation")
addrs, _ := cmd.Flags().GetString("addrs")
id, _ := cmd.Flags().GetString("id")
coins, _ := cmd.Flags().GetFloat64("coins_frozen")
if op == 0 || op > 3 {
fmt.Println("operation should be one of 1:apply,2:approve,3:quit")
return
}
if addrs == "" {
fmt.Println("addrs should not be nil")
return
}
payload := &pt.ParaNodeGroupConfig{Op: op, Addrs: addrs, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
payload := &pt.ParaNodeGroupConfig{Op: op, Id: id, Addrs: addrs, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pt.ParaX),
ActionName: "NodeGroupConfig",
......@@ -486,7 +468,7 @@ func addNodeBodyCmdFlags(cmd *cobra.Command) {
cmd.MarkFlagRequired("title")
cmd.Flags().StringP("addr", "a", "", "addr apply for super user")
cmd.MarkFlagRequired("addr")
cmd.Flags().StringP("id", "i", "", "id apply for super user")
}
......@@ -494,12 +476,14 @@ 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,
Id: id,
}
var res pt.ParaNodeAddrStatus
var res pt.ParaNodeIdStatus
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeStatus", params, &res)
ctx.Run()
}
......
......@@ -77,7 +77,7 @@ func getConfigManageNodes(db dbm.KV, title string) (map[string]struct{}, []strin
}
func getParacrossNodes(db dbm.KV, title string) (map[string]struct{}, []string, error) {
key := calcParaNodeGroupKey(title)
key := calcParaNodeGroupAddrsKey(title)
return getNodes(db, key)
}
......@@ -418,7 +418,12 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
return receipt, nil
}
if enableParacrossTransfer && commit.Status.Height > 0 && len(commit.Status.CrossTxHashs) > 0 {
haveCrossTxs := len(commit.Status.CrossTxHashs) > 0
if commit.Status.Height > 0 && types.IsDappFork(commit.Status.MainBlockHeight, pt.ParaX, pt.ForkCommitTx) && commit.Status.CrossTxHashs[0] == nil {
haveCrossTxs = false
}
if enableParacrossTransfer && commit.Status.Height > 0 && haveCrossTxs {
clog.Debug("paracross.Commit commitDone", "do cross", "")
crossTxReceipt, err := a.execCrossTxs(commit)
if err != nil {
......@@ -459,10 +464,10 @@ func (a *action) execCrossTx(tx *types.TransactionDetail, commit *pt.ParacrossCo
}
func getCrossTxHashs(api client.QueueProtocolAPI, commit *pt.ParacrossCommitAction) ([][]byte, []byte, error) {
crossTxHashs := commit.Status.CrossTxHashs
crossTxResult := commit.Status.CrossTxResult
if types.IsDappFork(commit.Status.MainBlockHeight, pt.ParaX, pt.ForkCommitTx) {
if len(commit.Status.CrossTxHashs) == 0 {
clog.Error("getCrossTxHashs len=0", "paraHeight", commit.Status.Height,
"mainHeight", commit.Status.MainBlockHeight, "mainHash", hex.EncodeToString(commit.Status.MainBlockHash))
return nil, nil, types.ErrCheckTxHash
}
blockDetail, err := GetBlock(api, commit.Status.MainBlockHash)
......@@ -479,23 +484,32 @@ func getCrossTxHashs(api client.QueueProtocolAPI, commit *pt.ParacrossCommitActi
baseCheckTxHash := CalcTxHashsHash(baseHashs)
crossCheckHash := CalcTxHashsHash(paraCrossHashs)
if !bytes.Equal(commit.Status.CrossTxHashs[0], crossCheckHash) {
clog.Error("getCrossTxHashs para hash not equal", "main.crossHash", hex.EncodeToString(crossCheckHash),
clog.Error("getCrossTxHashs para hash not equal", "paraHeight", commit.Status.Height,
"mainHeight", commit.Status.MainBlockHeight, "mainHash", hex.EncodeToString(commit.Status.MainBlockHash),
"main.crossHash", hex.EncodeToString(crossCheckHash),
"commit.crossHash", hex.EncodeToString(commit.Status.CrossTxHashs[0]),
"main.baseHash", hex.EncodeToString(baseCheckTxHash), "commit.baseHash", hex.EncodeToString(commit.Status.TxHashs[0]))
for _, hash := range baseHashs {
clog.Error("getCrossTxHashs base tx hash", "txhash", hex.EncodeToString(hash))
}
for _, hash := range paraCrossHashs {
clog.Error("getCrossTxHashs paracross tx hash", "txhash", hex.EncodeToString(hash))
}
return nil, nil, types.ErrCheckTxHash
}
//只获取跨链tx
crossTxHashs = paraCrossHashs
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 paraCrossHashs, rst, nil
}
return crossTxHashs, crossTxResult, nil
return commit.Status.CrossTxHashs, commit.Status.CrossTxResult, nil
}
func (a *action) execCrossTxs(commit *pt.ParacrossCommitAction) (*types.Receipt, error) {
......
......@@ -64,11 +64,11 @@ func (e *Paracross) ExecDelLocal_NodeConfig(payload *pt.ParaNodeAddrConfig, tx *
}
if g.Prev != nil {
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Current.ApplyAddr, g.Prev.Status), Value: types.Encode(g.Prev)})
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.ApplyAddr, g.Current.Status), Value: nil})
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Current.Status, g.Current.Id), Value: nil})
} else if log.Ty == pt.TyLogParaNodeVoteDone {
var g pt.ReceiptParaNodeVoteDone
err := types.Decode(log.Log, &g)
......@@ -86,8 +86,7 @@ func (e *Paracross) ExecDelLocal_NodeConfig(payload *pt.ParaNodeAddrConfig, tx *
func (e *Paracross) ExecDelLocal_NodeGroupConfig(payload *pt.ParaNodeGroupConfig, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
var set types.LocalDBSet
for _, log := range receiptData.Logs {
if log.Ty == pt.TyLogParaNodeGroupApply || log.Ty == pt.TyLogParaNodeGroupApprove ||
log.Ty == pt.TyLogParaNodeGroupQuit {
if log.Ty == pt.TyLogParaNodeGroupConfig {
var g pt.ReceiptParaNodeGroupConfig
err := types.Decode(log.Log, &g)
if err != nil {
......@@ -95,11 +94,11 @@ func (e *Paracross) ExecDelLocal_NodeGroupConfig(payload *pt.ParaNodeGroupConfig
}
if g.Prev != nil {
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeGroupStatusTitle(g.Prev.Status, g.Current.Title), Value: types.Encode(g.Prev)})
Key: calcLocalNodeGroupStatusTitle(g.Prev.Status, g.Current.Title, g.Current.Id), Value: types.Encode(g.Prev)})
}
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeGroupStatusTitle(g.Current.Status, g.Current.Title), Value: nil})
Key: calcLocalNodeGroupStatusTitle(g.Current.Status, g.Current.Title, g.Current.Id), Value: nil})
}
}
return &set, nil
......
......@@ -67,11 +67,11 @@ func (e *Paracross) ExecLocal_NodeConfig(payload *pt.ParaNodeAddrConfig, tx *typ
}
if g.Prev != nil {
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Current.ApplyAddr, g.Prev.Status), Value: nil})
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.ApplyAddr, g.Current.Status),
Key: calcLocalNodeTitleStatus(g.Current.Title, g.Current.Status, g.Current.Id),
Value: types.Encode(g.Current)})
} else if log.Ty == pt.TyLogParaNodeVoteDone {
var g pt.ReceiptParaNodeVoteDone
......@@ -90,8 +90,7 @@ func (e *Paracross) ExecLocal_NodeConfig(payload *pt.ParaNodeAddrConfig, tx *typ
func (e *Paracross) ExecLocal_NodeGroupConfig(payload *pt.ParaNodeGroupConfig, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
var set types.LocalDBSet
for _, log := range receiptData.Logs {
if log.Ty == pt.TyLogParaNodeGroupApply || log.Ty == pt.TyLogParaNodeGroupApprove ||
log.Ty == pt.TyLogParaNodeGroupQuit {
if log.Ty == pt.TyLogParaNodeGroupConfig {
var g pt.ReceiptParaNodeGroupConfig
err := types.Decode(log.Log, &g)
if err != nil {
......@@ -99,11 +98,11 @@ func (e *Paracross) ExecLocal_NodeGroupConfig(payload *pt.ParaNodeGroupConfig, t
}
if g.Prev != nil {
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeGroupStatusTitle(g.Prev.Status, g.Current.Title), Value: nil})
Key: calcLocalNodeGroupStatusTitle(g.Prev.Status, g.Current.Title, g.Current.Id), Value: nil})
}
set.KV = append(set.KV, &types.KeyValue{
Key: calcLocalNodeGroupStatusTitle(g.Current.Status, g.Current.Title), Value: types.Encode(g.Current)})
Key: calcLocalNodeGroupStatusTitle(g.Current.Status, g.Current.Title, g.Current.Id), Value: types.Encode(g.Current)})
}
}
return &set, nil
......
......@@ -16,7 +16,9 @@ var (
managerConfigNodes string //manager 合约配置的nodes
paraConfigNodes string //平行链自组织配置的nodes,最初是从manager同步过来
paraConfigNodeAddr string //平行链配置节点账户
paraNodeGroupApplyAddrs string
paraNodeGroupStatusAddrs string //正在申请的addrs
paraNodeID string
paraNodeGroupID string
localTx string
localTitle string
localTitleHeight string
......@@ -32,7 +34,9 @@ func setPrefix() {
managerConfigNodes = "paracross-nodes-"
paraConfigNodes = "mavl-paracross-nodes-title-"
paraConfigNodeAddr = "mavl-paracross-nodes-titleAddr-"
paraNodeGroupApplyAddrs = "mavl-paracross-nodegroup-apply-title-"
paraNodeGroupStatusAddrs = "mavl-paracross-nodegroup-apply-title-"
paraNodeID = "mavl-paracross-title-nodeid-"
paraNodeGroupID = "mavl-paracross-title-nodegroupid-"
localTx = "LODB-paracross-titleHeightAddr-"
localTitle = "LODB-paracross-title-"
localTitleHeight = "LODB-paracross-titleHeight-"
......@@ -62,7 +66,7 @@ func calcManageConfigNodesKey(title string) []byte {
return []byte(types.ManageKey(key))
}
func calcParaNodeGroupKey(title string) []byte {
func calcParaNodeGroupAddrsKey(title string) []byte {
return []byte(fmt.Sprintf(paraConfigNodes+"%s", title))
}
......@@ -70,8 +74,16 @@ func calcParaNodeAddrKey(title string, addr string) []byte {
return []byte(fmt.Sprintf(paraConfigNodeAddr+"%s-%s", title, addr))
}
func calcParaNodeGroupApplyKey(title string) []byte {
return []byte(fmt.Sprintf(paraNodeGroupApplyAddrs+"%s", title))
func calcParaNodeGroupStatusKey(title string) []byte {
return []byte(fmt.Sprintf(paraNodeGroupStatusAddrs+"%s", title))
}
func calcParaNodeIDKey(title, hash string) string {
return fmt.Sprintf(paraNodeID+"%s-%s", title, hash)
}
func calcParaNodeGroupIDKey(title, hash string) string {
return fmt.Sprintf(paraNodeGroupID+"%s-%s", title, hash)
}
func calcLocalTxKey(title string, height int64, addr string) []byte {
......@@ -90,22 +102,30 @@ func calcLocalAssetKey(hash []byte) []byte {
return []byte(fmt.Sprintf(localAssetKey+"%s", hash))
}
func calcLocalNodeTitleStatus(title, addr string, status int32) []byte {
return []byte(fmt.Sprintf(localNodeTitleStatus+"%s-%02d-%s", title, status, addr))
func calcLocalNodeTitleStatus(title string, status int32, id string) []byte {
return []byte(fmt.Sprintf(localNodeTitleStatus+"%s-%02d-%s", title, status, id))
}
func calcLocalNodeStatusPrefix(title string, status int32) []byte {
return []byte(fmt.Sprintf(localNodeTitleStatus+"%s-%02d", title, status))
return []byte(fmt.Sprintf(localNodeTitleStatus+"%s-%02d-", title, status))
}
func calcLocalNodeTitlePrefix(title string) []byte {
return []byte(fmt.Sprintf(localNodeTitleStatus+"%s-", title))
}
func calcLocalNodeTitleDone(title, addr string) []byte {
return []byte(fmt.Sprintf(localNodeTitleDone+"%s-%s", title, addr))
}
func calcLocalNodeGroupStatusTitle(status int32, title string) []byte {
return []byte(fmt.Sprintf(localNodeGroupStatusTitle+"%02d-%s", status, title))
func calcLocalNodeGroupStatusTitle(status int32, title, id string) []byte {
return []byte(fmt.Sprintf(localNodeGroupStatusTitle+"%02d-%s-%s", status, title, id))
}
func calcLocalNodeGroupStatusPrefix(status int32) []byte {
return []byte(fmt.Sprintf(localNodeGroupStatusTitle+"%02d", status))
return []byte(fmt.Sprintf(localNodeGroupStatusTitle+"%02d-", status))
}
func calcLocalNodeGroupAllPrefix() []byte {
return []byte(fmt.Sprintf(localNodeGroupStatusTitle))
}
......@@ -75,7 +75,7 @@ func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types.
nodes = append(nodes, k)
}
var reply types.ReplyConfig
reply.Key = string(calcParaNodeGroupKey(in.GetTitle()))
reply.Key = string(calcParaNodeGroupAddrsKey(in.GetTitle()))
reply.Value = fmt.Sprint(nodes)
return &reply, nil
}
......@@ -85,7 +85,24 @@ func (p *Paracross) Query_GetNodeAddrInfo(in *pt.ReqParacrossNodeInfo) (types.Me
if in == nil || in.Title == "" || in.Addr == "" {
return nil, types.ErrInvalidParam
}
stat, err := getNodeAddr(p.GetStateDB(), in.Title, in.Addr)
addrStat, err := getNodeAddr(p.GetStateDB(), in.Title, in.Addr)
if err != nil {
return nil, err
}
stat, err := getNodeID(p.GetStateDB(), addrStat.ProposalId)
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) {
if in == nil || in.Title == "" || in.Id == "" {
return nil, types.ErrInvalidParam
}
stat, err := getNodeID(p.GetStateDB(), in.Id)
if err != nil {
return nil, err
}
......@@ -114,7 +131,7 @@ func (p *Paracross) Query_GetNodeGroupStatus(in *pt.ReqParacrossNodeInfo) (types
//Query_ListNodeGroupStatus list node info by status
func (p *Paracross) Query_ListNodeGroupStatus(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
if in == nil || in.Status == 0 {
if in == nil {
return nil, types.ErrInvalidParam
}
return listLocalNodeGroupStatus(p.GetLocalDB(), in.Status)
......@@ -212,7 +229,7 @@ func listLocalTitles(db dbm.KVDB) (types.Message, error) {
MostSameCommit: st.MostSameCommit,
Title: st.Title,
Height: st.Height,
StateHash: hex.EncodeToString(st.StateHash),
StateHash: common.ToHex(st.StateHash),
TxCounts: st.TxCounts,
TxResult: hex.EncodeToString(st.TxResult),
}
......@@ -230,12 +247,12 @@ func listNodeStatus(db dbm.KVDB, prefix []byte) (types.Message, error) {
var resp pt.RespParacrossNodeAddrs
for _, r := range res {
var st pt.ParaNodeAddrStatus
var st pt.ParaNodeIdStatus
err = types.Decode(r, &st)
if err != nil {
panic(err)
}
resp.Addrs = append(resp.Addrs, &st)
resp.Ids = append(resp.Ids, &st)
}
return &resp, nil
}
......@@ -253,19 +270,31 @@ func listNodeGroupStatus(db dbm.KVDB, prefix []byte) (types.Message, error) {
if err != nil {
panic(err)
}
resp.Addrs = append(resp.Addrs, &st)
resp.Ids = append(resp.Ids, &st)
}
return &resp, nil
}
//按状态遍历
func listLocalNodeStatus(db dbm.KVDB, title string, status int32) (types.Message, error) {
prefix := calcLocalNodeStatusPrefix(title, status)
var prefix []byte
if status == 0 {
prefix = calcLocalNodeTitlePrefix(title)
} else {
prefix = calcLocalNodeStatusPrefix(title, status)
}
return listNodeStatus(db, prefix)
}
func listLocalNodeGroupStatus(db dbm.KVDB, status int32) (types.Message, error) {
prefix := calcLocalNodeGroupStatusPrefix(status)
var prefix []byte
if status == 0 {
prefix = calcLocalNodeGroupAllPrefix()
} else {
prefix = calcLocalNodeGroupStatusPrefix(status)
}
return listNodeGroupStatus(db, prefix)
}
......@@ -287,7 +316,7 @@ func loadLocalTitle(db dbm.KV, title string, height int64) (types.Message, error
MostSameCommit: st.MostSameCommit,
Title: st.Title,
Height: st.Height,
StateHash: hex.EncodeToString(st.StateHash),
StateHash: common.ToHex(st.StateHash),
TxCounts: st.TxCounts,
TxResult: hex.EncodeToString(st.TxResult),
}, nil
......
......@@ -62,8 +62,10 @@ func getMiners(detail *pt.ParacrossStatusDetails, blockHash []byte) []string {
//
func mergeReceipt(receipt1, receipt2 *types.Receipt) *types.Receipt {
if receipt2 != nil {
receipt1.KV = append(receipt1.KV, receipt2.KV...)
receipt1.Logs = append(receipt1.Logs, receipt2.Logs...)
}
receipt1.KV = append(receipt1.KV, receipt2.KV...)
receipt1.Logs = append(receipt1.Logs, receipt2.Logs...)
return receipt1
}
......@@ -74,7 +74,7 @@ func (suite *NodeManageTestSuite) SetupSuite() {
}
func (suite *NodeManageTestSuite) TestSetup() {
nodeConfigKey := calcParaNodeGroupKey(Title)
nodeConfigKey := calcParaNodeGroupAddrsKey(Title)
suite.T().Log(string(nodeConfigKey))
_, err := suite.stateDB.Get(nodeConfigKey)
if err != nil {
......@@ -96,6 +96,11 @@ func nodeCommitImpl(suite suite.Suite, exec *Paracross, privkeyStr string, tx *t
assert.NotNil(suite.T(), receipt)
assert.Nil(suite.T(), err)
for _, v := range receipt.KV {
if err := exec.GetStateDB().Set(v.Key, v.Value); err != nil {
panic(err)
}
}
return
}
......@@ -104,52 +109,52 @@ func checkGroupApplyReceipt(suite *NodeManageTestSuite, receipt *types.Receipt)
assert.Len(suite.T(), receipt.KV, 1)
assert.Len(suite.T(), receipt.Logs, 1)
var stat pt.ParaNodeAddrStatus
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.TyLogParaNodeGroupApply), receipt.Logs[0].Ty)
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, 6)
assert.Len(suite.T(), receipt.Logs, 6)
assert.Len(suite.T(), receipt.KV, 11)
assert.Len(suite.T(), receipt.Logs, 7)
len := len(receipt.KV)
var stat pt.ParaNodeAddrStatus
var stat pt.ParaNodeIdStatus
err := types.Decode(receipt.KV[len-1].Value, &stat)
assert.Nil(suite.T(), err, "decode ParaNodeAddrStatus failed")
//suite.T().Log("titleHeight", titleHeight)
assert.Equal(suite.T(), int32(pt.TyLogParaNodeGroupApprove), receipt.Logs[len-1].Ty)
//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, 1)
assert.Len(suite.T(), receipt.KV, 2)
assert.Len(suite.T(), receipt.Logs, 1)
var stat pt.ParaNodeAddrStatus
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.TyLogParaNodeConfig), receipt.Logs[0].Ty)
assert.Equal(suite.T(), int32(pt.ParacrossNodeAdding), stat.Status)
assert.Equal(suite.T(), int32(pt.ParacrossNodeJoining), stat.Status)
assert.NotNil(suite.T(), stat.Votes)
}
func checkQuitReceipt(suite *NodeManageTestSuite, receipt *types.Receipt) {
assert.Equal(suite.T(), receipt.Ty, int32(types.ExecOk))
assert.Len(suite.T(), receipt.KV, 1)
assert.Len(suite.T(), receipt.KV, 2)
assert.Len(suite.T(), receipt.Logs, 1)
var stat pt.ParaNodeAddrStatus
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)
......@@ -161,10 +166,8 @@ func checkQuitReceipt(suite *NodeManageTestSuite, receipt *types.Receipt) {
func checkVoteReceipt(suite *NodeManageTestSuite, receipt *types.Receipt, count int) {
assert.Equal(suite.T(), receipt.Ty, int32(types.ExecOk))
assert.Len(suite.T(), receipt.KV, 1)
assert.Len(suite.T(), receipt.Logs, 1)
var stat pt.ParaNodeAddrStatus
var stat pt.ParaNodeIdStatus
err := types.Decode(receipt.KV[0].Value, &stat)
assert.Nil(suite.T(), err, "decode ParaNodeAddrStatus failed")
assert.Len(suite.T(), stat.Votes.Votes, count)
......@@ -172,43 +175,47 @@ func checkVoteReceipt(suite *NodeManageTestSuite, receipt *types.Receipt, count
}
func checkVoteDoneReceipt(suite *NodeManageTestSuite, receipt *types.Receipt, count int, join bool) {
suite.NotNil(receipt)
assert.Equal(suite.T(), receipt.Ty, int32(types.ExecOk))
assert.Len(suite.T(), receipt.KV, 2)
assert.Len(suite.T(), receipt.Logs, 3)
var stat pt.ParaNodeAddrStatus
err := types.Decode(receipt.KV[0].Value, &stat)
assert.Nil(suite.T(), err, "decode ParaNodeAddrStatus failed")
assert.Len(suite.T(), stat.Votes.Votes, count)
suite.T().Log("checkVoteDoneReceipt", "kvlen", len(receipt.KV))
var item types.ConfigItem
err = types.Decode(receipt.KV[1].Value, &item)
assert.Nil(suite.T(), err, "decode ParaNodeAddrStatus failed")
_, arry, err := getParacrossNodes(suite.stateDB, Title)
suite.Suite.Nil(err)
if join {
suite.Contains(item.GetArr().Value, Account14K)
suite.Contains(arry, Account14K)
} else {
suite.NotContains(item.GetArr().Value, Account14K)
suite.NotContains(arry, Account14K)
}
}
func voteTest(suite *NodeManageTestSuite, addr string, join bool) {
func voteTest(suite *NodeManageTestSuite, id string, join bool) {
var count int
config := &pt.ParaNodeAddrConfig{
Op: pt.ParaNodeVote,
Addr: addr,
Id: id,
Value: pt.ParaNodeVoteYes,
}
tx, err := pt.CreateRawNodeConfigTx(config)
suite.Nil(err)
count++
receipt := nodeCommit(suite, PrivKeyA, tx)
checkVoteReceipt(suite, receipt, 1)
checkVoteReceipt(suite, receipt, count)
count++
receipt = nodeCommit(suite, PrivKeyB, tx)
checkVoteReceipt(suite, receipt, 2)
checkVoteReceipt(suite, receipt, count)
count++
if !join {
receipt = nodeCommit(suite, PrivKey14K, tx)
checkVoteReceipt(suite, receipt, count)
count++
}
receipt = nodeCommit(suite, PrivKeyC, tx)
checkVoteDoneReceipt(suite, receipt, 3, join)
checkVoteDoneReceipt(suite, receipt, count, join)
}
func (suite *NodeManageTestSuite) testNodeGroupConfigQuit() {
......@@ -222,9 +229,14 @@ func (suite *NodeManageTestSuite) testNodeGroupConfigQuit() {
receipt := nodeCommit(suite, PrivKeyB, tx)
checkGroupApplyReceipt(suite, receipt)
suite.Equal(int32(pt.TyLogParaNodeGroupConfig), receipt.Logs[0].Ty)
var g pt.ReceiptParaNodeGroupConfig
err = types.Decode(receipt.Logs[0].Log, &g)
suite.Nil(err)
config = &pt.ParaNodeGroupConfig{
Addrs: applyAddrs,
Op: pt.ParacrossNodeGroupQuit,
Id: g.Current.Id,
Op: pt.ParacrossNodeGroupQuit,
}
tx, err = pt.CreateRawNodeGroupApplyTx(config)
suite.Nil(err)
......@@ -247,9 +259,14 @@ func (suite *NodeManageTestSuite) testNodeGroupConfig() {
receipt := nodeCommit(suite, PrivKeyB, tx)
checkGroupApplyReceipt(suite, receipt)
suite.Equal(int32(pt.TyLogParaNodeGroupConfig), receipt.Logs[0].Ty)
var g pt.ReceiptParaNodeGroupConfig
err = types.Decode(receipt.Logs[0].Log, &g)
suite.Nil(err)
config = &pt.ParaNodeGroupConfig{
Addrs: applyAddrs,
Op: pt.ParacrossNodeGroupApprove,
Id: g.Current.Id,
Op: pt.ParacrossNodeGroupApprove,
}
tx, err = pt.CreateRawNodeGroupApplyTx(config)
suite.Nil(err)
......@@ -271,13 +288,18 @@ func (suite *NodeManageTestSuite) testNodeConfig() {
receipt := nodeCommit(suite, PrivKey14K, tx)
checkJoinReceipt(suite, receipt)
suite.Equal(int32(pt.TyLogParaNodeConfig), receipt.Logs[0].Ty)
var g pt.ReceiptParaNodeConfig
err = types.Decode(receipt.Logs[0].Log, &g)
suite.Nil(err)
//vote test
voteTest(suite, Account14K, true)
voteTest(suite, g.Current.Id, true)
//Quit test
config = &pt.ParaNodeAddrConfig{
Op: pt.ParaNodeQuit,
Addr: Account1MC,
Op: pt.ParaNodeQuit,
Id: g.Current.Id,
}
tx, err = pt.CreateRawNodeConfigTx(config)
suite.Nil(err)
......@@ -285,7 +307,7 @@ func (suite *NodeManageTestSuite) testNodeConfig() {
checkQuitReceipt(suite, receipt)
//vote test
voteTest(suite, Account1MC, false)
voteTest(suite, g.Current.Id, false)
}
func (suite *NodeManageTestSuite) TestExec() {
......@@ -310,22 +332,22 @@ func (suite *NodeManageTestSuite) TearDownSuite() {
func TestGetAddrGroup(t *testing.T) {
addrs := " 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4, 1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR, 1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k, ,,, 1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs , "
retAddrs := getAddrGroup(addrs)
retAddrs := getConfigAddrs(addrs)
expectAddrs := []string{"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4", "1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR", "1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k", "1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs"}
assert.Equal(t, expectAddrs, retAddrs)
addrs = " 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4 , , "
retAddrs = getAddrGroup(addrs)
retAddrs = getConfigAddrs(addrs)
expectAddrs = []string{"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}
assert.Equal(t, expectAddrs, retAddrs)
addrs = " , "
ret := getAddrGroup(addrs)
ret := getConfigAddrs(addrs)
assert.Equal(t, []string(nil), ret)
assert.Equal(t, 0, len(ret))
addrs = " "
ret = getAddrGroup(addrs)
ret = getConfigAddrs(addrs)
assert.Equal(t, []string(nil), ret)
assert.Equal(t, 0, len(ret))
......
......@@ -47,71 +47,77 @@ message ParacrossConsensusStatus {
string consensBlockHash = 4;
}
message ParaNodeAddrConfig{
message ParaNodeAddrConfig {
string title = 1;
string op = 2;
string addr = 3;
string value = 4;
int64 coinsFrozen = 5;
uint32 op = 2;
string id = 3;
string addr = 4;
uint32 value = 5;
int64 coinsFrozen = 6;
}
message ParaNodeVoteDetail{
message ParaNodeVoteDetail {
repeated string addrs = 1;
repeated string votes = 2;
}
message ParaNodeAddrStatus{
int32 status = 1;
string title = 2;
string applyAddr = 3;
int64 coinsFrozen = 4;
ParaNodeVoteDetail votes = 5;
string fromAddr = 6;
message ParaNodeAddrIdStatus {
string proposalId = 1;
}
message ParaNodeIdStatus {
string id = 1;
int32 status = 2;
string title = 3;
string targetAddr = 4;
int64 coinsFrozen = 5;
ParaNodeVoteDetail votes = 6;
string fromAddr = 7;
int64 height = 8;
}
message ReceiptParaNodeConfig {
string addr = 1;
ParaNodeAddrConfig config = 2;
ParaNodeAddrStatus prev = 3;
ParaNodeAddrStatus current = 4;
ParaNodeIdStatus prev = 3;
ParaNodeIdStatus current = 4;
}
message ReceiptParaNodeVoteRecord {
string fromAddr = 1;
string voteAddr = 2;
int32 value = 3;
}
message ReceiptParaNodeVoteDone {
string title = 1;
string targetAddr = 2;
int32 totalNodes = 3;
int32 totalVote = 4;
int32 mostVote = 5;
string voteRst = 6;
int32 doneStatus = 7;
string id = 1;
string title = 2;
string targetAddr = 3;
int32 totalNodes = 4;
int32 totalVote = 5;
int32 mostVote = 6;
string voteRst = 7;
int32 doneStatus = 8;
}
message ParaNodeGroupConfig {
string title = 1;
uint32 op = 2;
string addrs = 3;
int64 coinsFrozen = 4;
uint32 emptyBlockInterval = 5;
string id = 3;
string addrs = 4;
int64 coinsFrozen = 5;
uint32 emptyBlockInterval = 6;
}
message ParaNodeGroupStatus {
int32 status = 1;
string title = 2;
string applyAddr = 3;
int64 coinsFrozen = 4;
uint32 emptyBlockInterval = 5;
int64 mainHeight = 6;
string fromAddr = 7;
string id = 1;
int32 status = 2;
string title = 3;
string targetAddrs = 4;
int64 coinsFrozen = 5;
uint32 emptyBlockInterval = 6;
int64 mainHeight = 7;
string fromAddr = 8;
int64 height = 9;
}
message ReceiptParaNodeGroupConfig {
......@@ -125,16 +131,18 @@ message ReceiptParaNodeGroupConfig {
// node query
message ReqParacrossNodeInfo {
string title = 1;
string addr = 2;
int32 status = 3;
string id = 2;
string addr = 3;
int32 status = 4;
}
message RespParacrossNodeAddrs {
repeated ParaNodeAddrStatus addrs = 1;
repeated ParaNodeIdStatus ids = 1;
}
message RespParacrossNodeGroups {
repeated ParaNodeGroupStatus addrs = 1;
repeated ParaNodeGroupStatus ids = 1;
}
message ParaBlock2MainMap {
......
......@@ -180,13 +180,26 @@ func (c *Jrpc) GetBlock2MainInfo(req *types.ReqBlocks, result *interface{}) erro
}
// GetNodeStatus get super node status
func (c *channelClient) GetNodeStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeAddrStatus, error) {
func (c *channelClient) GetNodeStatus(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*pt.ParaNodeIdStatus, error) {
r := *req
data, err := c.Query(pt.GetExecName(), "GetNodeAddrInfo", &r)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParaNodeAddrStatus); ok {
if resp, ok := data.(*pt.ParaNodeIdStatus); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetNodeStatus 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)
if err != nil {
return nil, err
}
if resp, ok := data.(*pt.ParaNodeIdStatus); ok {
return resp, nil
}
return nil, types.ErrDecode
......@@ -194,7 +207,20 @@ func (c *channelClient) GetNodeStatus(ctx context.Context, req *pt.ReqParacrossN
// GetNodeStatus get super node status
func (c *Jrpc) GetNodeStatus(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.GetNodeStatus(context.Background(), req)
if req == nil || (req.Addr == "" && req.Id == "") {
return types.ErrInvalidParam
}
var data *pt.ParaNodeIdStatus
var err error
if req.Addr != "" {
data, err = c.cli.GetNodeStatus(context.Background(), req)
}
if req.Id != "" {
data, err = c.cli.GetNodeIDStatus(context.Background(), req)
}
*result = data
return err
}
......
......@@ -47,8 +47,6 @@ var (
ErrParaNodeGroupFrozenCoinsNotEnough = errors.New("ErrParaNodeGroupFrozenCoinsNotEnough")
//ErrParaNodeGroupStatusWrong node group process wrong status
ErrParaNodeGroupStatusWrong = errors.New("ErrParaNodeGroupStatusWrong")
//ErrParaNodeGroupAddrNotMatch group addrs not match with apply
ErrParaNodeGroupAddrNotMatch = errors.New("ErrParaNodeGroupAddrNotMatch")
//ErrParaConsensStopBlocksNotReach consensus stop blocks not reach
ErrParaConsensStopBlocksNotReach = errors.New("ErrParaConsensStopBlocksNotReach")
)
......@@ -37,12 +37,11 @@ const (
// TyLogParaAssetDeposit asset deposit log key
TyLogParaAssetDeposit = 656
// TyLogParaNodeConfig config super node log key
TyLogParaNodeConfig = 657
TyLogParaNodeVoteDone = 658
TyLogParaNodeGroupUpdate = 659
TyLogParaNodeGroupApply = 660
TyLogParaNodeGroupApprove = 661
TyLogParaNodeGroupQuit = 662
TyLogParaNodeConfig = 657
TyLogParaNodeVoteDone = 658
TyLogParaNodeGroupAddrsUpdate = 659
TyLogParaNodeGroupConfig = 660
TyLogParaNodeGroupStatusUpdate = 664
)
type paracrossCommitTx struct {
......@@ -90,19 +89,27 @@ const (
// node config op
const (
ParaNodeJoin = "join"
ParaNodeQuit = "quit"
ParaNodeVote = "vote"
ParaNodeJoin = iota + 1
ParaNodeVote
ParaNodeQuit
)
ParaNodeVoteYes = "yes"
ParaNodeVoteNo = "no"
// node vote op
const (
ParaNodeVoteInvalid = iota
ParaNodeVoteYes
ParaNodeVoteNo
ParaNodeVoteEnd
)
// ParaNodeVoteStr ...
var ParaNodeVoteStr = []string{"invalid", "yes", "no"}
const (
// ParacrossNodeAdding apply for adding group
ParacrossNodeAdding = iota + 1
// ParacrossNodeAdded pass to add by votes
ParacrossNodeAdded
// ParacrossNodeJoining apply for adding group
ParacrossNodeJoining = iota + 1
// ParacrossNodeJoined pass to add by votes
ParacrossNodeJoined
// ParacrossNodeQuiting apply for quiting
ParacrossNodeQuiting
// ParacrossNodeQuited pass to quite by votes
......@@ -116,6 +123,8 @@ const (
ParacrossNodeGroupApprove
//ParacrossNodeGroupQuit applyer quit the apply when not be approved
ParacrossNodeGroupQuit
//ParacrossNodeGroupModify applyer modify some parameters
ParacrossNodeGroupModify
)
var (
......@@ -179,6 +188,7 @@ func createRawCommitTx(status *ParacrossNodeStatus, name string, fee int64) (*ty
func CreateRawNodeConfigTx(config *ParaNodeAddrConfig) (*types.Transaction, error) {
config.Title = types.GetTitle()
config.Addr = strings.Trim(config.Addr, " ")
config.Id = strings.Trim(config.Id, " ")
action := &ParacrossAction{
Ty: ParacrossActionNodeConfig,
......@@ -195,6 +205,7 @@ func CreateRawNodeConfigTx(config *ParaNodeAddrConfig) (*types.Transaction, erro
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)
......
This diff is collapsed.
......@@ -54,19 +54,18 @@ func (p *ParacrossType) GetName() string {
// GetLogMap get receipt log map
func (p *ParacrossType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{
TyLogParacrossCommit: {Ty: reflect.TypeOf(ReceiptParacrossCommit{}), Name: "LogParacrossCommit"},
TyLogParacrossCommitDone: {Ty: reflect.TypeOf(ReceiptParacrossDone{}), Name: "LogParacrossCommitDone"},
TyLogParacrossCommitRecord: {Ty: reflect.TypeOf(ReceiptParacrossRecord{}), Name: "LogParacrossCommitRecord"},
TyLogParaAssetWithdraw: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogParaAssetWithdraw"},
TyLogParaAssetTransfer: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogParaAssetTransfer"},
TyLogParaAssetDeposit: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogParaAssetDeposit"},
TyLogParacrossMiner: {Ty: reflect.TypeOf(ReceiptParacrossMiner{}), Name: "LogParacrossMiner"},
TyLogParaNodeConfig: {Ty: reflect.TypeOf(ReceiptParaNodeConfig{}), Name: "LogParaNodeConfig"},
TyLogParaNodeGroupUpdate: {Ty: reflect.TypeOf(types.ReceiptConfig{}), Name: "LogParaNodeGroupUpdate"},
TyLogParaNodeVoteDone: {Ty: reflect.TypeOf(ReceiptParaNodeVoteDone{}), Name: "LogParaNodeVoteDone"},
TyLogParaNodeGroupApply: {Ty: reflect.TypeOf(ReceiptParaNodeGroupConfig{}), Name: "LogParaNodeGroupApply"},
TyLogParaNodeGroupApprove: {Ty: reflect.TypeOf(ReceiptParaNodeGroupConfig{}), Name: "LogParaNodeGroupApprove"},
TyLogParaNodeGroupQuit: {Ty: reflect.TypeOf(ReceiptParaNodeGroupConfig{}), Name: "LogParaNodeGroupQuit"},
TyLogParacrossCommit: {Ty: reflect.TypeOf(ReceiptParacrossCommit{}), Name: "LogParacrossCommit"},
TyLogParacrossCommitDone: {Ty: reflect.TypeOf(ReceiptParacrossDone{}), Name: "LogParacrossCommitDone"},
TyLogParacrossCommitRecord: {Ty: reflect.TypeOf(ReceiptParacrossRecord{}), Name: "LogParacrossCommitRecord"},
TyLogParaAssetWithdraw: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogParaAssetWithdraw"},
TyLogParaAssetTransfer: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogParaAssetTransfer"},
TyLogParaAssetDeposit: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogParaAssetDeposit"},
TyLogParacrossMiner: {Ty: reflect.TypeOf(ReceiptParacrossMiner{}), Name: "LogParacrossMiner"},
TyLogParaNodeConfig: {Ty: reflect.TypeOf(ReceiptParaNodeConfig{}), Name: "LogParaNodeConfig"},
TyLogParaNodeGroupAddrsUpdate: {Ty: reflect.TypeOf(types.ReceiptConfig{}), Name: "LogParaNodeGroupAddrsUpdate"},
TyLogParaNodeVoteDone: {Ty: reflect.TypeOf(ReceiptParaNodeVoteDone{}), Name: "LogParaNodeVoteDone"},
TyLogParaNodeGroupConfig: {Ty: reflect.TypeOf(ReceiptParaNodeGroupConfig{}), Name: "LogParaNodeGroupConfig"},
TyLogParaNodeGroupStatusUpdate: {Ty: reflect.TypeOf(ReceiptParaNodeGroupConfig{}), Name: "LogParaNodeGroupStatusUpdate"},
}
}
......
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