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