Commit 88942a63 authored by mdj33's avatar mdj33 Committed by vipwzw

add node group apply and coin frozen process

parent 645fdab2
...@@ -212,3 +212,7 @@ superManager=[ ...@@ -212,3 +212,7 @@ superManager=[
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK" "1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK"
] ]
[exec.sub.paracross]
nodeGroupFrozenCoins=0
...@@ -33,6 +33,7 @@ func ParcCmd() *cobra.Command { ...@@ -33,6 +33,7 @@ func ParcCmd() *cobra.Command {
CreateRawWithdrawCmd(), CreateRawWithdrawCmd(),
CreateRawTransferToExecCmd(), CreateRawTransferToExecCmd(),
CreateRawNodeManageCmd(), CreateRawNodeManageCmd(),
CreateNodeGroupApplyCmd(),
GetParaInfoCmd(), GetParaInfoCmd(),
GetParaListCmd(), GetParaListCmd(),
GetNodeGroupCmd(), GetNodeGroupCmd(),
...@@ -248,22 +249,27 @@ func CreateRawNodeManageCmd() *cobra.Command { ...@@ -248,22 +249,27 @@ func CreateRawNodeManageCmd() *cobra.Command {
} }
func addNodeManageFlags(cmd *cobra.Command) { func addNodeManageFlags(cmd *cobra.Command) {
cmd.Flags().StringP("operation", "o", "", "operation:join,quit,vote,takeover") cmd.Flags().StringP("operation", "o", "", "operation:join,quit,vote")
cmd.MarkFlagRequired("operation") cmd.MarkFlagRequired("operation")
cmd.Flags().StringP("addr", "a", "", "operating target addr") cmd.Flags().StringP("addr", "a", "", "operating target addr")
cmd.MarkFlagRequired("addrs")
cmd.Flags().StringP("value", "v", "", "vote value: yes,no") cmd.Flags().StringP("value", "v", "", "vote value: yes,no")
cmd.Flags().Int64P("coins_frozen", "c", 0, "join to frozen coins amount, not less config")
} }
func createNodeTx(cmd *cobra.Command, args []string) { func createNodeTx(cmd *cobra.Command, args []string) {
op, _ := cmd.Flags().GetString("operation") op, _ := cmd.Flags().GetString("operation")
opAddr, _ := cmd.Flags().GetString("addr") opAddr, _ := cmd.Flags().GetString("addr")
val, _ := cmd.Flags().GetString("value") val, _ := cmd.Flags().GetString("value")
if op != "vote" && op != "quit" && op != "join" && op != "takeover" { coins, _ := cmd.Flags().GetInt64("coins_frozen")
fmt.Println("operation should be one of join,quit,vote,takeover")
if op != "vote" && op != "quit" && op != "join" {
fmt.Println("operation should be one of join,quit,vote")
return return
} }
if (op == "vote" || op == "join" || op == "quit") && opAddr == "" { if opAddr == "" {
fmt.Println("addr parameter should not be null") fmt.Println("addr parameter should not be null")
return return
} }
...@@ -272,7 +278,7 @@ func createNodeTx(cmd *cobra.Command, args []string) { ...@@ -272,7 +278,7 @@ func createNodeTx(cmd *cobra.Command, args []string) {
return return
} }
payload := &pt.ParaNodeAddrConfig{Op: op, Value: val, Addr: opAddr} payload := &pt.ParaNodeAddrConfig{Op: op, Value: val, Addr: opAddr, CoinsFrozen: coins}
params := &rpctypes.CreateTxIn{ params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pt.ParaX), Execer: types.ExecName(pt.ParaX),
ActionName: "NodeConfig", ActionName: "NodeConfig",
...@@ -285,6 +291,54 @@ func createNodeTx(cmd *cobra.Command, args []string) { ...@@ -285,6 +291,54 @@ func createNodeTx(cmd *cobra.Command, args []string) {
} }
// CreateNodeGroupApplyCmd get node group addr
func CreateNodeGroupApplyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "nodegroup",
Short: "apply for para chain's super node group",
Run: nodeGroupApply,
}
addNodeGroupApplyCmdFlags(cmd)
return cmd
}
func addNodeGroupApplyCmdFlags(cmd *cobra.Command) {
cmd.Flags().Uint32P("operation", "o", 0, "operation:1:apply,2:approve,3:quit")
cmd.MarkFlagRequired("operation")
cmd.Flags().StringP("addrs", "a", "", "addrs apply for super node,split by ',' ")
cmd.MarkFlagRequired("addrs")
cmd.Flags().Int64P("coins_frozen", "c", 0, "coins amount to frozen, not less config")
}
func nodeGroupApply(cmd *cobra.Command, args []string) {
op, _ := cmd.Flags().GetUint32("operation")
addrs, _ := cmd.Flags().GetString("addrs")
coins, _ := cmd.Flags().GetInt64("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.ParaNodeGroupApply{Op: op, Addrs: addrs, CoinsFrozen: coins}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pt.ParaX),
ActionName: "NodeGroupApply",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// IsSyncCmd query parachain is sync // IsSyncCmd query parachain is sync
func IsSyncCmd() *cobra.Command { func IsSyncCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
...@@ -315,6 +369,7 @@ func GetHeightCmd() *cobra.Command { ...@@ -315,6 +369,7 @@ func GetHeightCmd() *cobra.Command {
func addTitleFlags(cmd *cobra.Command) { func addTitleFlags(cmd *cobra.Command) {
cmd.Flags().StringP("title", "t", "", "parallel chain's title, default null in para chain") cmd.Flags().StringP("title", "t", "", "parallel chain's title, default null in para chain")
cmd.MarkFlagRequired("title")
} }
func consusHeight(cmd *cobra.Command, args []string) { func consusHeight(cmd *cobra.Command, args []string) {
...@@ -484,8 +539,8 @@ func nodeList(cmd *cobra.Command, args []string) { ...@@ -484,8 +539,8 @@ func nodeList(cmd *cobra.Command, args []string) {
// GetNodeGroupCmd get node group addr // GetNodeGroupCmd get node group addr
func GetNodeGroupCmd() *cobra.Command { func GetNodeGroupCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "node_group", Use: "nodegroup_list",
Short: "Get super node group by title", Short: "Get super node group list by title or status",
Run: nodeGroup, Run: nodeGroup,
} }
addNodeGroupCmdFlags(cmd) addNodeGroupCmdFlags(cmd)
...@@ -495,13 +550,22 @@ func GetNodeGroupCmd() *cobra.Command { ...@@ -495,13 +550,22 @@ func GetNodeGroupCmd() *cobra.Command {
func addNodeGroupCmdFlags(cmd *cobra.Command) { func addNodeGroupCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("title", "t", "", "parallel chain's title") cmd.Flags().StringP("title", "t", "", "parallel chain's title")
cmd.MarkFlagRequired("title") cmd.MarkFlagRequired("title")
cmd.Flags().Int32P("status", "s", 0, "status:1:apply,2:approve,3:quit")
cmd.MarkFlagRequired("status")
} }
func nodeGroup(cmd *cobra.Command, args []string) { func nodeGroup(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
title, _ := cmd.Flags().GetString("title") title, _ := cmd.Flags().GetString("title")
status, _ := cmd.Flags().GetInt32("status")
params := pt.ReqParacrossNodeInfo{
Title: title,
Status: status,
}
var res types.ReplyConfig var res types.ReplyConfig
ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeGroup", types.ReqString{Data: title}, &res) ctx := jsonclient.NewRPCCtx(rpcLaddr, "paracross.GetNodeGroup", params, &res)
ctx.Run() ctx.Run()
} }
...@@ -92,3 +92,8 @@ func (e *Paracross) Exec_NodeConfig(payload *pt.ParaNodeAddrConfig, tx *types.Tr ...@@ -92,3 +92,8 @@ func (e *Paracross) Exec_NodeConfig(payload *pt.ParaNodeAddrConfig, tx *types.Tr
a := newAction(e, tx) a := newAction(e, tx)
return a.NodeConfig(payload) return a.NodeConfig(payload)
} }
func (e *Paracross) Exec_NodeGroupConfig(payload *pt.ParaNodeGroupApply, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(e, tx)
return a.NodeGroupConfig(payload)
}
...@@ -16,6 +16,7 @@ var ( ...@@ -16,6 +16,7 @@ var (
managerConfigNodes string //manager 合约配置的nodes managerConfigNodes string //manager 合约配置的nodes
paraConfigNodes string //平行链自组织配置的nodes,最初是从manager同步过来 paraConfigNodes string //平行链自组织配置的nodes,最初是从manager同步过来
paraConfigNodeAddr string //平行链配置节点账户 paraConfigNodeAddr string //平行链配置节点账户
paraNodeGroupApplyAddrs string
localTx string localTx string
localTitle string localTitle string
localTitleHeight string localTitleHeight string
...@@ -30,6 +31,7 @@ func setPrefix() { ...@@ -30,6 +31,7 @@ func setPrefix() {
managerConfigNodes = "paracross-nodes-" managerConfigNodes = "paracross-nodes-"
paraConfigNodes = "mavl-paracross-nodes-title-" paraConfigNodes = "mavl-paracross-nodes-title-"
paraConfigNodeAddr = "mavl-paracross-nodes-titleAddr-" paraConfigNodeAddr = "mavl-paracross-nodes-titleAddr-"
paraNodeGroupApplyAddrs = "mavl-paracross-nodegroup-apply-title-"
localTx = "LODB-paracross-titleHeightAddr-" localTx = "LODB-paracross-titleHeightAddr-"
localTitle = "LODB-paracross-title-" localTitle = "LODB-paracross-title-"
localTitleHeight = "LODB-paracross-titleHeight-" localTitleHeight = "LODB-paracross-titleHeight-"
...@@ -65,6 +67,10 @@ func calcParaNodeAddrKey(title string, addr string) []byte { ...@@ -65,6 +67,10 @@ func calcParaNodeAddrKey(title string, addr string) []byte {
return []byte(fmt.Sprintf(paraConfigNodeAddr+"%s-%s", title, addr)) return []byte(fmt.Sprintf(paraConfigNodeAddr+"%s-%s", title, addr))
} }
func calcParaNodeGroupApplyKey(title string) []byte {
return []byte(fmt.Sprintf(paraNodeGroupApplyAddrs+"%s", title))
}
func calcLocalTxKey(title string, height int64, addr string) []byte { func calcLocalTxKey(title string, height int64, addr string) []byte {
return []byte(fmt.Sprintf(localTx+"%s-%012-%s", title, height, addr)) return []byte(fmt.Sprintf(localTx+"%s-%012-%s", title, height, addr))
} }
......
...@@ -300,7 +300,8 @@ func (c *Paracross) allow(tx *types.Transaction, index int) error { ...@@ -300,7 +300,8 @@ func (c *Paracross) allow(tx *types.Transaction, index int) error {
return nil return nil
} }
if types.IsDappFork(c.GetHeight(), pt.ParaX, pt.ForkCommitTx) { if types.IsDappFork(c.GetHeight(), pt.ParaX, pt.ForkCommitTx) {
if payload.Ty == pt.ParacrossActionCommit || payload.Ty == pt.ParacrossActionNodeConfig { if payload.Ty == pt.ParacrossActionCommit || payload.Ty == pt.ParacrossActionNodeConfig ||
payload.Ty == pt.ParacrossActionNodeGroupApply {
return nil return nil
} }
} }
......
...@@ -36,11 +36,11 @@ func (p *Paracross) Query_GetTitleByHash(in *pt.ReqParacrossTitleHash) (types.Me ...@@ -36,11 +36,11 @@ func (p *Paracross) Query_GetTitleByHash(in *pt.ReqParacrossTitleHash) (types.Me
} }
//Query_GetNodeGroup get node group addrs //Query_GetNodeGroup get node group addrs
func (p *Paracross) Query_GetNodeGroup(in *types.ReqString) (types.Message, error) { func (p *Paracross) Query_GetNodeGroup(in *pt.ReqParacrossNodeInfo) (types.Message, error) {
if in == nil { if in == nil {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
key := calcParaNodeGroupKey(in.GetData()) key := calcParaNodeGroupKey(in.GetTitle())
ret, _, err := getNodes(p.GetStateDB(), key) ret, _, err := getNodes(p.GetStateDB(), key)
if err != nil { if err != nil {
return nil, errors.Cause(err) return nil, errors.Cause(err)
......
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"strings"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
manager "github.com/33cn/chain33/system/dapp/manage/types" manager "github.com/33cn/chain33/system/dapp/manage/types"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -16,7 +18,8 @@ import ( ...@@ -16,7 +18,8 @@ import (
) )
var ( var (
conf = types.ConfSub(manager.ManageX) confManager = types.ConfSub(manager.ManageX)
conf = types.ConfSub(pt.ParaX)
) )
func deepCopy(dst, src interface{}) error { func deepCopy(dst, src interface{}) error {
...@@ -88,6 +91,27 @@ func makeNodeConfigReceipt(addr string, config *pt.ParaNodeAddrConfig, prev, cur ...@@ -88,6 +91,27 @@ func makeNodeConfigReceipt(addr string, config *pt.ParaNodeAddrConfig, prev, cur
} }
} }
func makeParaNodeGroupApplyReiceipt(title, addr string, prev, current *pt.ParaNodeAddrStatus, logTy int32) *types.Receipt {
key := calcParaNodeGroupApplyKey(title)
log := &pt.ReceiptParaNodeConfig{
Addr: addr,
Prev: prev,
Current: current,
}
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(current)},
},
Logs: []*types.ReceiptLog{
{
Ty: logTy,
Log: types.Encode(log),
},
},
}
}
func makeParaNodeGroupReiceipt(title string, prev, current *types.ConfigItem) *types.Receipt { func makeParaNodeGroupReiceipt(title string, prev, current *types.ConfigItem) *types.Receipt {
key := calcParaNodeGroupKey(title) key := calcParaNodeGroupKey(title)
log := &types.ReceiptConfig{Prev: prev, Current: current} log := &types.ReceiptConfig{Prev: prev, Current: current}
...@@ -105,7 +129,7 @@ func makeParaNodeGroupReiceipt(title string, prev, current *types.ConfigItem) *t ...@@ -105,7 +129,7 @@ func makeParaNodeGroupReiceipt(title string, prev, current *types.ConfigItem) *t
} }
} }
func (a *action) nodeAdd(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) { func (a *action) nodeJoin(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) {
key := calcParaNodeGroupKey(config.Title) key := calcParaNodeGroupKey(config.Title)
nodes, _, err := getNodes(a.db, key) nodes, _, err := getNodes(a.db, key)
if err != nil { if err != nil {
...@@ -115,6 +139,16 @@ func (a *action) nodeAdd(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) ...@@ -115,6 +139,16 @@ func (a *action) nodeAdd(config *pt.ParaNodeAddrConfig) (*types.Receipt, error)
return nil, errors.Wrapf(pt.ErrParaNodeAddrExisted, "nodeAddr existed:%s", a.fromaddr) return nil, errors.Wrapf(pt.ErrParaNodeAddrExisted, "nodeAddr existed:%s", a.fromaddr)
} }
receipt := &types.Receipt{Ty: types.ExecOk}
if !types.IsPara() {
r, err := a.nodeGroupCoinsFrozen([]string{a.fromaddr}, config.CoinsFrozen)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
}
key = calcParaNodeAddrKey(config.Title, config.Addr) key = calcParaNodeAddrKey(config.Title, config.Addr)
stat, err := getNodeAddr(a.db, key) stat, err := getNodeAddr(a.db, key)
if err != nil { if err != nil {
...@@ -125,29 +159,37 @@ func (a *action) nodeAdd(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) ...@@ -125,29 +159,37 @@ func (a *action) nodeAdd(config *pt.ParaNodeAddrConfig) (*types.Receipt, error)
stat := &pt.ParaNodeAddrStatus{Status: pt.ParacrossNodeAdding, stat := &pt.ParaNodeAddrStatus{Status: pt.ParacrossNodeAdding,
Title: config.Title, Title: config.Title,
ApplyAddr: config.Addr, ApplyAddr: config.Addr,
Votes: &pt.ParaNodeVoteDetail{}} Votes: &pt.ParaNodeVoteDetail{},
CoinsFrozen: config.CoinsFrozen}
saveNodeAddr(a.db, key, stat) saveNodeAddr(a.db, key, stat)
return makeNodeConfigReceipt(a.fromaddr, config, nil, stat), nil r := makeNodeConfigReceipt(a.fromaddr, config, nil, stat)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
} }
var copyStat pt.ParaNodeAddrStatus var copyStat pt.ParaNodeAddrStatus
err = deepCopy(&copyStat, stat) err = deepCopy(&copyStat, stat)
if err != nil { if err != nil {
clog.Error("nodeaccount.nodeAdd deep copy fail", "copy", copyStat, "stat", stat) clog.Error("nodeaccount.nodeJoin deep copy fail", "copy", copyStat, "stat", stat)
return nil, err return nil, err
} }
if stat.Status != pt.ParacrossNodeQuited { if stat.Status != pt.ParacrossNodeQuited {
clog.Error("nodeaccount.nodeAdd key exist", "key", string(key), "status", stat) clog.Error("nodeaccount.nodeJoin key exist", "key", string(key), "status", stat)
return nil, pt.ErrParaNodeAddrExisted return nil, pt.ErrParaNodeAddrExisted
} }
stat.Status = pt.ParacrossNodeAdding stat.Status = pt.ParacrossNodeAdding
stat.CoinsFrozen = config.CoinsFrozen
stat.Votes = &pt.ParaNodeVoteDetail{} stat.Votes = &pt.ParaNodeVoteDetail{}
saveNodeAddr(a.db, key, stat) saveNodeAddr(a.db, key, stat)
return makeNodeConfigReceipt(a.fromaddr, config, &copyStat, stat), nil r := makeNodeConfigReceipt(a.fromaddr, config, &copyStat, stat)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
} }
func (a *action) nodeDelete(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) { func (a *action) nodeQuit(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) {
key := calcParaNodeGroupKey(config.Title) key := calcParaNodeGroupKey(config.Title)
nodes, _, err := getNodes(a.db, key) nodes, _, err := getNodes(a.db, key)
if err != nil { if err != nil {
...@@ -166,27 +208,49 @@ func (a *action) nodeDelete(config *pt.ParaNodeAddrConfig) (*types.Receipt, erro ...@@ -166,27 +208,49 @@ func (a *action) nodeDelete(config *pt.ParaNodeAddrConfig) (*types.Receipt, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
//refused or quiting
if stat.Status != pt.ParacrossNodeAdded { if stat.Status == pt.ParacrossNodeQuiting || stat.Status == pt.ParacrossNodeQuited {
clog.Error("nodeaccount.nodeDelete wrong status", "key", string(key), "status", stat) clog.Error("nodeaccount.nodeQuit wrong status", "key", string(key), "status", stat)
return nil, errors.Wrapf(pt.ErrParaUnSupportNodeOper, "nodeAddr %s not be added status:%d", a.fromaddr, stat.Status) return nil, errors.Wrapf(pt.ErrParaUnSupportNodeOper, "nodeAddr %s was quit status:%d", a.fromaddr, stat.Status)
} }
var copyStat pt.ParaNodeAddrStatus var copyStat pt.ParaNodeAddrStatus
err = deepCopy(&copyStat, stat) err = deepCopy(&copyStat, stat)
if err != nil { if err != nil {
clog.Error("nodeaccount.nodeDelete deep copy fail", "copy", copyStat, "stat", stat) clog.Error("nodeaccount.nodeQuit deep copy fail", "copy", copyStat, "stat", stat)
return nil, err return nil, err
} }
if stat.Status == pt.ParacrossNodeAdded {
stat.Status = pt.ParacrossNodeQuiting stat.Status = pt.ParacrossNodeQuiting
stat.Votes = &pt.ParaNodeVoteDetail{} stat.Votes = &pt.ParaNodeVoteDetail{}
saveNodeAddr(a.db, key, stat) saveNodeAddr(a.db, key, stat)
return makeNodeConfigReceipt(a.fromaddr, config, &copyStat, stat), nil return makeNodeConfigReceipt(a.fromaddr, config, &copyStat, stat), nil
}
//still adding status, quit directly
receipt := &types.Receipt{Ty: types.ExecOk}
if !types.IsPara() {
r, err := a.nodeGroupCoinsActive([]string{a.fromaddr}, stat.CoinsFrozen)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
}
stat.Status = pt.ParacrossNodeQuited
stat.Votes = &pt.ParaNodeVoteDetail{}
saveNodeAddr(a.db, key, stat)
r := makeNodeConfigReceipt(a.fromaddr, config, &copyStat, stat)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
} }
// IsSuperManager is supper manager or not // IsSuperManager is supper manager or not
func isSuperManager(addr string) bool { func isSuperManager(addr string) bool {
for _, m := range conf.GStrList("superManager") { for _, m := range confManager.GStrList("superManager") {
if addr == m { if addr == m {
return true return true
} }
...@@ -297,6 +361,15 @@ func (a *action) nodeVote(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) ...@@ -297,6 +361,15 @@ func (a *action) nodeVote(config *pt.ParaNodeAddrConfig) (*types.Receipt, error)
return nil, err return nil, err
} }
stat.Status = pt.ParacrossNodeQuited stat.Status = pt.ParacrossNodeQuited
if !types.IsPara() {
r, err := a.nodeGroupCoinsActive([]string{stat.ApplyAddr}, stat.CoinsFrozen)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
}
} }
} }
saveNodeAddr(a.db, key, stat) saveNodeAddr(a.db, key, stat)
...@@ -355,89 +428,354 @@ func unpdateNodeGroup(db dbm.KV, title, addr string, add bool) (*types.Receipt, ...@@ -355,89 +428,354 @@ func unpdateNodeGroup(db dbm.KV, title, addr string, add bool) (*types.Receipt,
return makeParaNodeGroupReiceipt(title, &copyItem, &item), nil return makeParaNodeGroupReiceipt(title, &copyItem, &item), nil
} }
func (a *action) nodeTakeover(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) { func (a *action) checkConfig(title string) error {
key := calcManageConfigNodesKey(config.Title) if !validTitle(title) {
_, nodes, err := getNodes(a.db, key) return pt.ErrInvalidTitle
}
forkHeight := types.GetDappFork(pt.ParaX, pt.ForkCommitTx)
if types.IsPara() {
forkHeight = types.Conf("config.consensus.sub.para").GInt("MainForkParacrossCommitTx")
if forkHeight == -1 || forkHeight == 0 {
forkHeight = types.MaxHeight
}
}
if a.exec.GetMainHeight() < forkHeight {
return types.ErrNotSupport
}
return nil
}
//NodeConfig support super account node config
func (a *action) NodeConfig(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) {
err := a.checkConfig(config.Title)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(nodes) == 0 {
return nil, pt.ErrParaManageNodesNotSet if config.Op == pt.ParaNodeJoin {
if config.Addr != a.fromaddr {
return nil, types.ErrFromAddr
} }
return a.nodeJoin(config)
var item types.ConfigItem } else if config.Op == pt.ParaNodeQuit {
key = calcParaNodeGroupKey(config.Title) if config.Addr != a.fromaddr {
return nil, types.ErrFromAddr
}
return a.nodeQuit(config)
} else if config.Op == pt.ParaNodeVote {
return a.nodeVote(config)
} else {
return nil, pt.ErrParaUnSupportNodeOper
}
}
//NodeConfig support super account node config
func (a *action) NodeGroupConfig(config *pt.ParaNodeGroupApply) (*types.Receipt, error) {
err := a.checkConfig(config.Title)
if err != nil {
return nil, err
}
if len(config.Addrs) == 0 {
return nil, types.ErrInvalidParam
}
if config.Op == pt.ParacrossNodeGroupApply {
if !strings.Contains(config.Addrs, a.fromaddr) {
clog.Error("node group apply fromaddr not one of apply addrs", "addr", a.fromaddr, "apply", config.Addrs)
return nil, types.ErrNotAllow
}
err := a.checkNodeGroupExist(config.Title)
if err != nil {
return nil, err
}
return a.nodeGroupApply(config)
} else if config.Op == pt.ParacrossNodeGroupApprove {
err := a.checkNodeGroupExist(config.Title)
if err != nil {
return nil, err
}
return a.nodeGroupApprove(config)
} else if config.Op == pt.ParacrossNodeGroupQuit {
if !strings.Contains(config.Addrs, a.fromaddr) {
clog.Error("node group apply fromaddr not one of apply addrs", "addr", a.fromaddr, "apply", config.Addrs)
return nil, types.ErrNotAllow
}
return a.nodeGroupQuit(config)
} else {
return nil, pt.ErrParaUnSupportNodeOper
}
}
func getAddrGroup(addr string) []string {
if strings.Contains(addr, ",") {
repeats := make(map[string]bool)
var addrs []string
s := strings.Trim(addr, " ")
s = strings.Trim(s, ",")
ss := strings.Split(s, ",")
for _, v := range ss {
v = strings.Trim(v, " ")
if !repeats[v] {
addrs = append(addrs, v)
repeats[v] = true
}
}
return addrs
}
return []string{addr}
}
func (a *action) checkNodeGroupExist(title string) error {
key := calcParaNodeGroupKey(title)
value, err := a.db.Get(key) value, err := a.db.Get(key)
if err != nil && !isNotFound(err) { if err != nil && !isNotFound(err) {
return nil, err return err
} }
if value != nil { if value != nil {
clog.Error("node group apply, group existed")
return pt.ErrParaNodeGroupExisted
}
return nil
}
func (a *action) nodeGroupCoinsFrozen(addrs []string, configCoinsFrozen int64) (*types.Receipt, error) {
receipt := &types.Receipt{}
confCoins := confManager.GInt("nodeGroupFrozenCoins")
if configCoinsFrozen < confCoins {
return nil, pt.ErrParaNodeGroupFrozenCoinsNotEnough
}
var logs []*types.ReceiptLog
var kv []*types.KeyValue
for _, addr := range addrs {
receipt, err := a.coinsAccount.ExecFrozen(addr, a.execaddr, configCoinsFrozen)
if err != nil {
clog.Error("node group apply", "addr", addr, "execaddr", a.execaddr, "amount", configCoinsFrozen)
return nil, err
}
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
}
receipt.KV = append(receipt.KV, kv...)
receipt.Logs = append(receipt.Logs, logs...)
return receipt, nil
}
func (a *action) nodeGroupCoinsActive(addrs []string, configCoinsFrozen int64) (*types.Receipt, error) {
receipt := &types.Receipt{}
var logs []*types.ReceiptLog
var kv []*types.KeyValue
for _, addr := range addrs {
receipt, err := a.coinsAccount.ExecActive(addr, a.execaddr, configCoinsFrozen)
if err != nil {
clog.Error("node group apply", "addr", addr, "execaddr", a.execaddr, "amount", configCoinsFrozen)
return nil, err
}
logs = append(logs, receipt.Logs...)
kv = append(kv, receipt.KV...)
}
receipt.KV = append(receipt.KV, kv...)
receipt.Logs = append(receipt.Logs, logs...)
return receipt, nil
}
// NodeGroupApply
func (a *action) nodeGroupApply(config *pt.ParaNodeGroupApply) (*types.Receipt, error) {
key := calcParaNodeGroupApplyKey(title)
status, err := getNodeAddr(a.db, key)
if err != nil && !isNotFound(err) {
return nil, err
}
if status != nil && status.Status != pt.ParacrossNodeGroupQuit {
clog.Error("node group apply exist", "status", status.Status)
return nil, pt.ErrParaNodeGroupExisted return nil, pt.ErrParaNodeGroupExisted
} }
item.Key = string(key) addrs := getAddrGroup(config.Addrs)
emptyValue := &types.ArrayConfig{Value: make([]string, 0)} receipt := &types.Receipt{Ty: types.ExecOk}
arr := types.ConfigItem_Arr{Arr: emptyValue} //main chain
item.Value = &arr if !types.IsPara() {
r, err := a.nodeGroupCoinsFrozen(addrs, config.CoinsFrozen)
if err != nil {
return nil, err
}
copyItem := item receipt.KV = append(receipt.KV, r.KV...)
item.GetArr().Value = append(item.GetArr().Value, nodes...) receipt.Logs = append(receipt.Logs, r.Logs...)
item.Addr = a.fromaddr }
a.db.Set(key, types.Encode(&item))
receipt := makeParaNodeGroupReiceipt(config.Title, &copyItem, &item)
//update add addr stat := &pt.ParaNodeAddrStatus{Status: pt.ParacrossNodeGroupApply,
for _, addr := range nodes {
key = calcParaNodeAddrKey(config.Title, addr)
stat := &pt.ParaNodeAddrStatus{Status: pt.ParacrossNodeAdded,
Title: config.Title, Title: config.Title,
ApplyAddr: addr, ApplyAddr: strings.Join(addrs, ","),
Votes: &pt.ParaNodeVoteDetail{}} CoinsFrozen: config.CoinsFrozen}
saveNodeAddr(a.db, key, stat) saveNodeAddr(a.db, key, stat)
config.Addr = addr r := makeParaNodeGroupApplyReiceipt(config.Title, a.fromaddr, nil, stat, pt.TyLogParaNodeGroupApply)
r := makeNodeConfigReceipt(a.fromaddr, config, nil, stat) receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
}
func (a *action) nodeGroupQuit(config *pt.ParaNodeGroupApply) (*types.Receipt, error) {
key := calcParaNodeGroupApplyKey(title)
status, err := getNodeAddr(a.db, key)
if err != nil {
return nil, err
}
if status != nil && status.Status != pt.ParacrossNodeGroupApply {
clog.Error("node group apply exist", "status", status.Status)
return nil, pt.ErrParaNodeGroupStatusWrong
}
applyAddrs, err := checkNodeGroupAddrsMatch(status.ApplyAddr, config.Addrs)
if err != nil {
return nil, err
}
receipt := &types.Receipt{Ty: types.ExecOk}
//main chain
if !types.IsPara() {
r, err := a.nodeGroupCoinsActive(applyAddrs, status.CoinsFrozen)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...) receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...) receipt.Logs = append(receipt.Logs, r.Logs...)
} }
stat := &pt.ParaNodeAddrStatus{Status: pt.ParacrossNodeGroupQuit,
Title: config.Title,
ApplyAddr: status.ApplyAddr,
CoinsFrozen: status.CoinsFrozen}
saveNodeAddr(a.db, key, stat)
r := makeParaNodeGroupApplyReiceipt(config.Title, a.fromaddr, nil, stat, pt.TyLogParaNodeGroupQuit)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil return receipt, nil
} }
//NodeConfig support super account node config func checkNodeGroupAddrsMatch(applyAddr, confAddr string) ([]string, error) {
func (a *action) NodeConfig(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) { confAddrs := getAddrGroup(confAddr)
if !validTitle(config.Title) { applyAddrs := strings.Split(applyAddr, ",")
return nil, pt.ErrInvalidTitle
applys := make(map[string]bool)
configs := make(map[string]bool)
diff := []string{}
for _, addr := range applyAddrs {
applys[addr] = true
}
for _, addr := range confAddrs {
configs[addr] = true
}
if len(applys) != len(configs) {
clog.Error("node group addrs count not match", "apply", applyAddr, "quit", confAddr)
return nil, pt.ErrParaNodeGroupAddrNotMatch
} }
forkHeight := types.GetDappFork(pt.ParaX, pt.ForkCommitTx) for _, addr := range confAddrs {
if types.IsPara() { if !applys[addr] {
forkHeight = types.Conf("config.consensus.sub.para").GInt("MainForkParacrossCommitTx") diff = append(diff, addr)
if forkHeight == -1 || forkHeight == 0 {
forkHeight = types.MaxHeight
} }
} }
if a.exec.GetMainHeight() < forkHeight { if len(diff) > 0 {
return nil, types.ErrNotSupport clog.Error("node group addrs not match", "apply", applyAddr, "quit", confAddr)
return nil, pt.ErrParaNodeGroupAddrNotMatch
} }
return confAddrs, nil
if config.Op == pt.ParaNodeJoin { }
if config.Addr != a.fromaddr {
return nil, types.ErrFromAddr // NodeGroupApprove super addr approve the node group apply
func (a *action) nodeGroupApprove(config *pt.ParaNodeGroupApply) (*types.Receipt, error) {
if !isSuperManager(a.fromaddr) {
clog.Error("node group approve not super manager", "addr", a.fromaddr)
return nil, types.ErrNotAllow
} }
return a.nodeAdd(config)
} else if config.Op == pt.ParaNodeQuit { key := calcParaNodeGroupApplyKey(title)
if config.Addr != a.fromaddr { status, err := getNodeAddr(a.db, key)
return nil, types.ErrFromAddr if err != nil {
return nil, err
}
if status.Status != pt.ParacrossNodeGroupApply {
clog.Error("node group approve not apply status", "status", status.Status)
return nil, pt.ErrParaNodeGroupStatusWrong
} }
return a.nodeDelete(config)
} else if config.Op == pt.ParaNodeVote { applyAddrs, err := checkNodeGroupAddrsMatch(status.ApplyAddr, config.Addrs)
return a.nodeVote(config) if err != nil {
} else if config.Op == pt.ParaNodeTakeover { return nil, err
return a.nodeTakeover(config) }
} else { receipt := &types.Receipt{Ty: types.ExecOk}
return nil, pt.ErrParaUnSupportNodeOper //create the node group
r, err := a.nodeGroupCreate(config.Title, applyAddrs, config.CoinsFrozen)
if err != nil {
return nil, err
} }
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
stat := &pt.ParaNodeAddrStatus{Status: pt.ParacrossNodeGroupApprove,
Title: config.Title,
ApplyAddr: status.ApplyAddr,
CoinsFrozen: status.CoinsFrozen}
saveNodeAddr(a.db, key, stat)
r = makeParaNodeGroupApplyReiceipt(config.Title, a.fromaddr, status, stat, pt.TyLogParaNodeGroupApprove)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
}
func (a *action) nodeGroupCreate(title string, nodes []string, coinFrozen int64) (*types.Receipt, error) {
var item types.ConfigItem
key := calcParaNodeGroupKey(title)
item.Key = string(key)
emptyValue := &types.ArrayConfig{Value: make([]string, 0)}
arr := types.ConfigItem_Arr{Arr: emptyValue}
item.Value = &arr
copyItem := item
item.GetArr().Value = append(item.GetArr().Value, nodes...)
item.Addr = a.fromaddr
a.db.Set(key, types.Encode(&item))
receipt := makeParaNodeGroupReiceipt(title, &copyItem, &item)
//update addr status
for _, addr := range nodes {
key = calcParaNodeAddrKey(title, addr)
stat := &pt.ParaNodeAddrStatus{Status: pt.ParacrossNodeAdded,
Title: title,
ApplyAddr: addr,
Votes: &pt.ParaNodeVoteDetail{},
CoinsFrozen: coinFrozen}
saveNodeAddr(a.db, key, stat)
config := &pt.ParaNodeAddrConfig{
Title: title,
Addr: addr,
CoinsFrozen: coinFrozen,
}
r := makeNodeConfigReceipt(a.fromaddr, config, nil, stat)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
}
return receipt, nil
} }
...@@ -39,6 +39,7 @@ message ParaNodeAddrConfig{ ...@@ -39,6 +39,7 @@ message ParaNodeAddrConfig{
string op = 2; string op = 2;
string addr = 3; string addr = 3;
string value = 4; string value = 4;
int64 coinsFrozen = 5;
} }
...@@ -51,7 +52,8 @@ message ParaNodeAddrStatus{ ...@@ -51,7 +52,8 @@ message ParaNodeAddrStatus{
int32 status = 1; int32 status = 1;
string title = 2; string title = 2;
string applyAddr = 3; string applyAddr = 3;
ParaNodeVoteDetail votes = 4; int64 coinsFrozen = 4;
ParaNodeVoteDetail votes = 5;
} }
...@@ -79,6 +81,15 @@ message ReceiptParaNodeVoteDone { ...@@ -79,6 +81,15 @@ message ReceiptParaNodeVoteDone {
} }
message ParaNodeGroupApply{
string title = 1;
uint32 op = 2;
string addrs = 3;
int64 coinsFrozen = 4;
}
// node query // node query
message ReqParacrossNodeInfo { message ReqParacrossNodeInfo {
string title = 1; string title = 1;
...@@ -137,6 +148,8 @@ message ParacrossAction { ...@@ -137,6 +148,8 @@ message ParacrossAction {
AssetsWithdraw withdraw = 7; AssetsWithdraw withdraw = 7;
AssetsTransferToExec transferToExec = 8; AssetsTransferToExec transferToExec = 8;
ParaNodeAddrConfig nodeConfig = 9; ParaNodeAddrConfig nodeConfig = 9;
ParaNodeGroupApply nodeGroupConfig= 10;
} }
int32 ty = 2; int32 ty = 2;
......
...@@ -169,7 +169,7 @@ func (c *Jrpc) GetBlock2MainInfo(req *types.ReqBlocks, result *interface{}) erro ...@@ -169,7 +169,7 @@ func (c *Jrpc) GetBlock2MainInfo(req *types.ReqBlocks, result *interface{}) erro
} }
// GetNodeGroup get super node group // GetNodeGroup get super node group
func (c *channelClient) GetNodeGroup(ctx context.Context, req *types.ReqString) (*types.ReplyConfig, error) { func (c *channelClient) GetNodeGroup(ctx context.Context, req *pt.ReqParacrossNodeInfo) (*types.ReplyConfig, error) {
r := *req r := *req
data, err := c.Query(pt.GetExecName(), "GetNodeGroup", &r) data, err := c.Query(pt.GetExecName(), "GetNodeGroup", &r)
if err != nil { if err != nil {
...@@ -182,7 +182,7 @@ func (c *channelClient) GetNodeGroup(ctx context.Context, req *types.ReqString) ...@@ -182,7 +182,7 @@ func (c *channelClient) GetNodeGroup(ctx context.Context, req *types.ReqString)
} }
// GetNodeGroup get super node group // GetNodeGroup get super node group
func (c *Jrpc) GetNodeGroup(req *types.ReqString, result *interface{}) error { func (c *Jrpc) GetNodeGroup(req *pt.ReqParacrossNodeInfo, result *interface{}) error {
data, err := c.cli.GetNodeGroup(context.Background(), req) data, err := c.cli.GetNodeGroup(context.Background(), req)
*result = data *result = data
return err return err
......
...@@ -43,4 +43,10 @@ var ( ...@@ -43,4 +43,10 @@ var (
ErrParaNodeGroupLastAddr = errors.New("ErrParaNodeGroupLastAddr") ErrParaNodeGroupLastAddr = errors.New("ErrParaNodeGroupLastAddr")
//ErrParaNodeVoteSelf vote self not allow //ErrParaNodeVoteSelf vote self not allow
ErrParaNodeVoteSelf = errors.New("ErrParaNodeVoteSelf") ErrParaNodeVoteSelf = errors.New("ErrParaNodeVoteSelf")
//ErrParaNodeGroupLessFrozenCoins 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")
//ErrParaNodeGroupAddrNotMatch
ErrParaNodeGroupAddrNotMatch = errors.New("ErrParaNodeGroupAddrNotMatch")
) )
...@@ -39,6 +39,9 @@ const ( ...@@ -39,6 +39,9 @@ const (
TyLogParaNodeConfig = 657 TyLogParaNodeConfig = 657
TyLogParaNodeVoteDone = 658 TyLogParaNodeVoteDone = 658
TyLogParaNodeGroupUpdate = 659 TyLogParaNodeGroupUpdate = 659
TyLogParaNodeGroupApply = 660
TyLogParaNodeGroupApprove = 661
TyLogParaNodeGroupQuit = 662
) )
type paracrossCommitTx struct { type paracrossCommitTx struct {
...@@ -72,6 +75,8 @@ const ( ...@@ -72,6 +75,8 @@ const (
ParacrossActionAssetWithdraw ParacrossActionAssetWithdraw
//ParacrossActionNodeConfig para super node config //ParacrossActionNodeConfig para super node config
ParacrossActionNodeConfig ParacrossActionNodeConfig
//ParacrossActionNodeGroupApply
ParacrossActionNodeGroupApply
) )
// status // status
...@@ -87,7 +92,6 @@ const ( ...@@ -87,7 +92,6 @@ const (
ParaNodeJoin = "join" ParaNodeJoin = "join"
ParaNodeQuit = "quit" ParaNodeQuit = "quit"
ParaNodeVote = "vote" ParaNodeVote = "vote"
ParaNodeTakeover = "takeover"
ParaNodeVoteYes = "yes" ParaNodeVoteYes = "yes"
ParaNodeVoteNo = "no" ParaNodeVoteNo = "no"
...@@ -104,6 +108,12 @@ const ( ...@@ -104,6 +108,12 @@ const (
ParacrossNodeQuited ParacrossNodeQuited
) )
const (
ParacrossNodeGroupApply = iota + 1
ParacrossNodeGroupApprove
ParacrossNodeGroupQuit
)
var ( var (
// ParacrossActionCommitStr Commit string // ParacrossActionCommitStr Commit string
ParacrossActionCommitStr = string("Commit") ParacrossActionCommitStr = string("Commit")
...@@ -176,6 +186,22 @@ func CreateRawNodeConfigTx(config *ParaNodeAddrConfig) (*types.Transaction, erro ...@@ -176,6 +186,22 @@ func CreateRawNodeConfigTx(config *ParaNodeAddrConfig) (*types.Transaction, erro
return tx, nil return tx, nil
} }
func CreateRawNodeGroupApplyTx(apply *ParaNodeGroupApply) (*types.Transaction, error) {
apply.Title = types.GetTitle()
action := &ParacrossAction{
Ty: ParacrossActionNodeGroupApply,
Value: &ParacrossAction_NodeGroupConfig{apply},
}
tx := &types.Transaction{
Payload: types.Encode(action),
}
return tx, nil
}
// CreateRawAssetTransferTx create asset transfer tx // CreateRawAssetTransferTx create asset transfer tx
func CreateRawAssetTransferTx(param *types.CreateTx) (*types.Transaction, error) { func CreateRawAssetTransferTx(param *types.CreateTx) (*types.Transaction, error) {
// 跨链交易需要在主链和平行链上执行, 所以应该可以在主链和平行链上构建 // 跨链交易需要在主链和平行链上执行, 所以应该可以在主链和平行链上构建
......
...@@ -122,6 +122,17 @@ func (p ParacrossType) CreateTx(action string, message json.RawMessage) (*types. ...@@ -122,6 +122,17 @@ func (p ParacrossType) CreateTx(action string, message json.RawMessage) (*types.
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
return CreateRawNodeConfigTx(&param) return CreateRawNodeConfigTx(&param)
} else if action == "NodeGroupApply" {
if !types.IsPara() {
return nil, types.ErrNotSupport
}
var param ParaNodeGroupApply
err := json.Unmarshal(message, &param)
if err != nil {
glog.Error("CreateTx.NodeGroupApply", "Error", err)
return nil, types.ErrInvalidParam
}
return CreateRawNodeGroupApplyTx(&param)
} }
return nil, types.ErrNotSupport return nil, types.ErrNotSupport
......
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