Commit 3abdcf52 authored by madengji's avatar madengji Committed by 33cn

para bind miner cmd

parent 073e10e3
...@@ -321,11 +321,13 @@ func superNodeCmd() *cobra.Command { ...@@ -321,11 +321,13 @@ func superNodeCmd() *cobra.Command {
cmd.AddCommand(nodeVoteCmd()) cmd.AddCommand(nodeVoteCmd())
cmd.AddCommand(nodeQuitCmd()) cmd.AddCommand(nodeQuitCmd())
cmd.AddCommand(nodeCancelCmd()) cmd.AddCommand(nodeCancelCmd())
cmd.AddCommand(nodeBindCmd())
cmd.AddCommand(getNodeInfoCmd()) cmd.AddCommand(getNodeInfoCmd())
cmd.AddCommand(getNodeIDInfoCmd()) cmd.AddCommand(getNodeIDInfoCmd())
cmd.AddCommand(getNodeListCmd()) cmd.AddCommand(getNodeListCmd())
cmd.AddCommand(nodeModifyCmd()) cmd.AddCommand(nodeModifyCmd())
cmd.AddCommand(getNodeBindListCmd())
return cmd return cmd
} }
...@@ -518,6 +520,87 @@ func createNodeModifyTx(cmd *cobra.Command, args []string) { ...@@ -518,6 +520,87 @@ func createNodeModifyTx(cmd *cobra.Command, args []string) {
} }
func nodeBindCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "bind",
Short: "bind miner for specific account",
Run: createNodeBindTx,
}
addNodeBindFlags(cmd)
return cmd
}
func addNodeBindFlags(cmd *cobra.Command) {
cmd.Flags().Uint32P("action", "a", 1, "action bind:1 or unbind:2")
cmd.MarkFlagRequired("action")
cmd.Flags().Uint64P("coins", "c", 0, "bind coins, unbind not needed")
cmd.Flags().StringP("node", "n", "", "target node to bind/unbind miner")
cmd.MarkFlagRequired("node")
}
func createNodeBindTx(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
action, _ := cmd.Flags().GetUint32("action")
node, _ := cmd.Flags().GetString("node")
coins, _ := cmd.Flags().GetUint32("coins")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
if action == 1 && coins == 0 {
fmt.Fprintln(os.Stderr, "coins should bigger than 0")
}
payload := &pt.ParaBindMinerInfo{BindAction: int32(action), BindCount: int64(coins), TargetAddr: node}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
ActionName: "ParaBindMiner",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
func getNodeBindListCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "bind_list",
Short: "Get node bind miner account list",
Run: nodeBindInfo,
}
addNodeBindCmdFlags(cmd)
return cmd
}
func addNodeBindCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("node", "n", "", "super node addr to bind miner")
cmd.MarkFlagRequired("node")
}
func nodeBindInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
addr, _ := cmd.Flags().GetString("addr")
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetNodeBindMinerList"
params.Payload = types.MustPBToJSON(&types.ReqString{Data: addr})
var res pt.RespParaNodeBindList
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
// getNodeInfoCmd get node current status // getNodeInfoCmd get node current status
func getNodeInfoCmd() *cobra.Command { func getNodeInfoCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
......
...@@ -533,3 +533,28 @@ func (p *Paracross) Query_GetHeight(req *types.ReqString) (*pt.ParacrossConsensu ...@@ -533,3 +533,28 @@ func (p *Paracross) Query_GetHeight(req *types.ReqString) (*pt.ParacrossConsensu
} }
return nil, types.ErrDecode return nil, types.ErrDecode
} }
// Query_GetNodeBindMinerList query get super node bind miner list
func (p *Paracross) Query_GetNodeBindMinerList(in *types.ReqString) (types.Message, error) {
if in == nil || len(in.Data) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "in=%v", in)
}
list, err := getBindNodeInfo(p.GetStateDB(), in.Data)
if err != nil {
return nil, err
}
var resp pt.RespParaNodeBindList
resp.List = list
for _, addr := range list.Miners {
info, err := getBindAddrInfo(p.GetStateDB(), in.Data, addr)
if err != nil {
return nil, err
}
resp.Details = append(resp.Details, info)
}
return &resp, nil
}
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types" pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
) )
...@@ -18,7 +19,7 @@ const ( ...@@ -18,7 +19,7 @@ const (
func (a *action) getBindAddrs(nodes []string, statusHeight int64) []*pt.ParaNodeBindList { func (a *action) getBindAddrs(nodes []string, statusHeight int64) []*pt.ParaNodeBindList {
var lists []*pt.ParaNodeBindList var lists []*pt.ParaNodeBindList
for _, m := range nodes { for _, m := range nodes {
list, err := a.getBindNodeInfo(m) list, err := getBindNodeInfo(a.db, m)
if isNotFound(errors.Cause(err)) { if isNotFound(errors.Cause(err)) {
continue continue
} }
...@@ -78,7 +79,7 @@ func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindLis ...@@ -78,7 +79,7 @@ func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindLis
var bindAddrList []*pt.ParaBindMinerInfo var bindAddrList []*pt.ParaBindMinerInfo
for _, node := range bindList { for _, node := range bindList {
for _, miner := range node.Miners { for _, miner := range node.Miners {
info, err := a.getBindAddrInfo(node.SuperNode, miner) info, err := getBindAddrInfo(a.db, node.SuperNode, miner)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
...@@ -113,7 +114,6 @@ func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindLis ...@@ -113,7 +114,6 @@ func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindLis
// reward 挖矿奖励, 主要处理挖矿分配逻辑,先实现基本策略,后面根据需求进行重构 // reward 挖矿奖励, 主要处理挖矿分配逻辑,先实现基本策略,后面根据需求进行重构
func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHeightStatus) (*types.Receipt, error) { func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHeightStatus) (*types.Receipt, error) {
//获取挖矿相关配置,这里需注意是共识的高度,而不是交易的高度 //获取挖矿相关配置,这里需注意是共识的高度,而不是交易的高度
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
coinReward := cfg.MGInt("mver.consensus.paracross.coinReward", nodeStatus.Height) * types.Coin coinReward := cfg.MGInt("mver.consensus.paracross.coinReward", nodeStatus.Height) * types.Coin
...@@ -169,7 +169,6 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe ...@@ -169,7 +169,6 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe
// getMiners 获取提交共识消息的矿工地址 // getMiners 获取提交共识消息的矿工地址
func getMiners(detail *pt.ParacrossStatusDetails, blockHash []byte) []string { func getMiners(detail *pt.ParacrossStatusDetails, blockHash []byte) []string {
addrs := make([]string, 0) addrs := make([]string, 0)
for i, hash := range detail.BlockHash { for i, hash := range detail.BlockHash {
if bytes.Equal(hash, blockHash) { if bytes.Equal(hash, blockHash) {
...@@ -242,21 +241,16 @@ func makeNodeBindReceipt(addr string, prev, current *pt.ParaNodeBindList) *types ...@@ -242,21 +241,16 @@ func makeNodeBindReceipt(addr string, prev, current *pt.ParaNodeBindList) *types
//绑定到超级节点 //绑定到超级节点
func (a *action) bind2Node(node string) (*types.Receipt, error) { func (a *action) bind2Node(node string) (*types.Receipt, error) {
key := calcParaBindMinerNode(node) info, err := getBindNodeInfo(a.db, node)
data, err := a.db.Get(key) if !isNotFound(errors.Cause(err)) {
if err != nil && err != types.ErrNotFound { return nil, errors.Wrap(err, "bind2Node")
return nil, errors.Wrapf(err, "unbind2Node get failed node=%s", node)
} }
//found //found
if len(data) > 0 { if info != nil {
var list pt.ParaNodeBindList listCopy := *info
err = types.Decode(data, &list) info.Miners = append(info.Miners, a.fromaddr)
if err != nil { return makeNodeBindReceipt(node, &listCopy, info), nil
return nil, errors.Wrapf(err, "bind2Node decode failed node=%s", node)
}
listCopy := list
list.Miners = append(list.Miners, a.fromaddr)
return makeNodeBindReceipt(node, &listCopy, &list), nil
} }
//unfound //unfound
var list pt.ParaNodeBindList var list pt.ParaNodeBindList
...@@ -267,7 +261,7 @@ func (a *action) bind2Node(node string) (*types.Receipt, error) { ...@@ -267,7 +261,7 @@ func (a *action) bind2Node(node string) (*types.Receipt, error) {
//从超级节点解绑 //从超级节点解绑
func (a *action) unbind2Node(node string) (*types.Receipt, error) { func (a *action) unbind2Node(node string) (*types.Receipt, error) {
list, err := a.getBindNodeInfo(node) list, err := getBindNodeInfo(a.db, node)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "unbind2Node") return nil, errors.Wrap(err, "unbind2Node")
} }
...@@ -281,9 +275,9 @@ func (a *action) unbind2Node(node string) (*types.Receipt, error) { ...@@ -281,9 +275,9 @@ func (a *action) unbind2Node(node string) (*types.Receipt, error) {
} }
func (a *action) getBindNodeInfo(node string) (*pt.ParaNodeBindList, error) { func getBindNodeInfo(db dbm.KV, node string) (*pt.ParaNodeBindList, error) {
key := calcParaBindMinerNode(node) key := calcParaBindMinerNode(node)
data, err := a.db.Get(key) data, err := db.Get(key)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "get key failed node=%s", node) return nil, errors.Wrapf(err, "get key failed node=%s", node)
} }
...@@ -296,9 +290,9 @@ func (a *action) getBindNodeInfo(node string) (*pt.ParaNodeBindList, error) { ...@@ -296,9 +290,9 @@ func (a *action) getBindNodeInfo(node string) (*pt.ParaNodeBindList, error) {
return &list, nil return &list, nil
} }
func (a *action) getBindAddrInfo(node, addr string) (*pt.ParaBindMinerInfo, error) { func getBindAddrInfo(db dbm.KV, node, addr string) (*pt.ParaBindMinerInfo, error) {
key := calcParaBindMinerAddr(node, addr) key := calcParaBindMinerAddr(node, addr)
data, err := a.db.Get(key) data, err := db.Get(key)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "get key failed node=%s,addr=%s", node, addr) return nil, errors.Wrapf(err, "get key failed node=%s,addr=%s", node, addr)
} }
...@@ -311,79 +305,74 @@ func (a *action) getBindAddrInfo(node, addr string) (*pt.ParaBindMinerInfo, erro ...@@ -311,79 +305,74 @@ func (a *action) getBindAddrInfo(node, addr string) (*pt.ParaBindMinerInfo, erro
return &info, nil return &info, nil
} }
func (a *action) bindOp(info *pt.ParaBindMinerInfo) (*types.Receipt, error) { func (a *action) bindOp(cmd *pt.ParaBindMinerInfo) (*types.Receipt, error) {
if len(info.Addr) > 0 && info.Addr != a.fromaddr { if len(cmd.Addr) > 0 && cmd.Addr != a.fromaddr {
return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner addr=%s not from addr %s", info.Addr, a.fromaddr) return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner addr=%s not from addr %s", cmd.Addr, a.fromaddr)
} }
if info.BindCount <= 0 { if cmd.BindCount <= 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner bindCount nil from addr %s", a.fromaddr) return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner bindCount nil from addr %s", a.fromaddr)
} }
ok, err := a.isValidSuperNode(info.TargetAddr) ok, err := a.isValidSuperNode(cmd.TargetAddr)
if err != nil || !ok { if err != nil || !ok {
return nil, errors.Wrapf(err, "invalid target node=%s", info.TargetAddr) return nil, errors.Wrapf(err, "invalid target node=%s", cmd.TargetAddr)
} }
key := calcParaBindMinerAddr(info.TargetAddr, a.fromaddr) current, err := getBindAddrInfo(a.db, cmd.TargetAddr, a.fromaddr)
data, err := a.db.Get(key) if !isNotFound(errors.Cause(err)) {
if err != nil && err != types.ErrNotFound { return nil, errors.Wrap(err, "getBindAddrInfo")
return nil, err
} }
//found, 修改当前的绑定 //found, 修改当前的绑定
if len(data) > 0 { if current != nil {
var receipt *types.Receipt var receipt *types.Receipt
var acct pt.ParaBindMinerInfo
err = types.Decode(data, &acct)
if err != nil {
return nil, errors.Wrapf(err, "bindOp decode for addr=%s", a.fromaddr)
}
if info.BindCount == acct.BindCount { if cmd.BindCount == current.BindCount {
return nil, errors.Wrapf(types.ErrInvalidParam, "bindOp bind coins not change current=%d, modify=%d", return nil, errors.Wrapf(types.ErrInvalidParam, "bind coins same current=%d, cmd=%d", current.BindCount, cmd.BindCount)
acct.BindCount, info.BindCount)
} }
//释放一部分冻结coins //释放一部分冻结coins
if info.BindCount < acct.BindCount { if cmd.BindCount < current.BindCount {
receipt, err = a.coinsAccount.ExecActive(a.fromaddr, a.execaddr, (acct.BindCount-info.BindCount)*types.Coin) receipt, err = a.coinsAccount.ExecActive(a.fromaddr, a.execaddr, (current.BindCount-cmd.BindCount)*types.Coin)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "bindOp Active addr=%s,execaddr=%s,coins=%d", a.fromaddr, a.execaddr, acct.BindCount-info.BindCount) return nil, errors.Wrapf(err, "bindOp Active addr=%s,execaddr=%s,coins=%d", a.fromaddr, a.execaddr, current.BindCount-cmd.BindCount)
} }
} }
//冻结更多 //冻结更多
receipt, err = a.coinsAccount.ExecFrozen(a.fromaddr, a.execaddr, (info.BindCount-acct.BindCount)*types.Coin) receipt, err = a.coinsAccount.ExecFrozen(a.fromaddr, a.execaddr, (cmd.BindCount-current.BindCount)*types.Coin)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "bindOp frozen more addr=%s,execaddr=%s,coins=%d", a.fromaddr, a.execaddr, info.BindCount-acct.BindCount) return nil, errors.Wrapf(err, "bindOp frozen more addr=%s,execaddr=%s,coins=%d", a.fromaddr, a.execaddr, cmd.BindCount-current.BindCount)
} }
acctCopy := acct acctCopy := *current
acct.BindCount = info.BindCount current.BindCount = cmd.BindCount
r := makeAddrBindReceipt(info.TargetAddr, a.fromaddr, &acctCopy, &acct) r := makeAddrBindReceipt(cmd.TargetAddr, a.fromaddr, &acctCopy, current)
return mergeReceipt(receipt, r), nil return mergeReceipt(receipt, r), nil
} }
//not found, 增加新绑定 //not found, 增加新绑定
receipt, err := a.coinsAccount.ExecFrozen(a.fromaddr, a.execaddr, info.BindCount*types.Coin) receipt, err := a.coinsAccount.ExecFrozen(a.fromaddr, a.execaddr, cmd.BindCount*types.Coin)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "bindOp frozen addr=%s,execaddr=%s,count=%d", a.fromaddr, a.execaddr, info.BindCount) return nil, errors.Wrapf(err, "bindOp frozen addr=%s,execaddr=%s,count=%d", a.fromaddr, a.execaddr, cmd.BindCount)
} }
//bind addr //bind addr
acct := &pt.ParaBindMinerInfo{ acct := &pt.ParaBindMinerInfo{
Addr: a.fromaddr, Addr: a.fromaddr,
BindStatus: opBind, BindAction: opBind,
BindCount: info.BindCount, BindCount: cmd.BindCount,
BlockTime: a.blocktime, BlockTime: a.blocktime,
TargetAddr: info.TargetAddr, BlockHeight: a.height,
TargetAddr: cmd.TargetAddr,
} }
rBind := makeAddrBindReceipt(info.TargetAddr, a.fromaddr, nil, acct) rBind := makeAddrBindReceipt(cmd.TargetAddr, a.fromaddr, nil, acct)
mergeReceipt(receipt, rBind) mergeReceipt(receipt, rBind)
//增加到列表中 //增加到列表中
rList, err := a.bind2Node(info.TargetAddr) rList, err := a.bind2Node(cmd.TargetAddr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -392,8 +381,8 @@ func (a *action) bindOp(info *pt.ParaBindMinerInfo) (*types.Receipt, error) { ...@@ -392,8 +381,8 @@ func (a *action) bindOp(info *pt.ParaBindMinerInfo) (*types.Receipt, error) {
} }
func (a *action) unBindOp(info *pt.ParaBindMinerInfo) (*types.Receipt, error) { func (a *action) unBindOp(cmd *pt.ParaBindMinerInfo) (*types.Receipt, error) {
acct, err := a.getBindAddrInfo(info.TargetAddr, a.fromaddr) acct, err := getBindAddrInfo(a.db, cmd.TargetAddr, a.fromaddr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -411,11 +400,11 @@ func (a *action) unBindOp(info *pt.ParaBindMinerInfo) (*types.Receipt, error) { ...@@ -411,11 +400,11 @@ func (a *action) unBindOp(info *pt.ParaBindMinerInfo) (*types.Receipt, error) {
} }
//删除 bind addr //删除 bind addr
rUnBind := makeAddrBindReceipt(info.TargetAddr, a.fromaddr, acct, nil) rUnBind := makeAddrBindReceipt(cmd.TargetAddr, a.fromaddr, acct, nil)
mergeReceipt(receipt, rUnBind) mergeReceipt(receipt, rUnBind)
//从列表删除 //从列表删除
rUnList, err := a.unbind2Node(info.TargetAddr) rUnList, err := a.unbind2Node(cmd.TargetAddr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -429,11 +418,16 @@ func (a *action) bindMiner(info *pt.ParaBindMinerInfo) (*types.Receipt, error) { ...@@ -429,11 +418,16 @@ func (a *action) bindMiner(info *pt.ParaBindMinerInfo) (*types.Receipt, error) {
return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner targetAddr should not be nil to addr %s", a.fromaddr) return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner targetAddr should not be nil to addr %s", a.fromaddr)
} }
if info.BindStatus != opBind && info.BindStatus != opUnBind { //只允许平行链操作
return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner status=%d not correct", info.BindStatus) if !types.IsParaExecName(string(a.tx.Execer)) {
return nil, errors.Wrapf(types.ErrInvalidParam, "exec=%s,should prefix with user.p.", string(a.tx.Execer))
}
if info.BindAction != opBind && info.BindAction != opUnBind {
return nil, errors.Wrapf(types.ErrInvalidParam, "bindMiner action=%d not correct", info.BindAction)
} }
if info.BindStatus == opBind { if info.BindAction == opBind {
return a.bindOp(info) return a.bindOp(info)
} }
return a.unBindOp(info) return a.unBindOp(info)
......
...@@ -161,10 +161,11 @@ message RespParacrossNodeGroups { ...@@ -161,10 +161,11 @@ message RespParacrossNodeGroups {
//para bind miner //para bind miner
message ParaBindMinerInfo{ message ParaBindMinerInfo{
string addr = 1; // miner addr string addr = 1; // miner addr
int32 bindStatus = 2; // 0: init, 1: bind, 2:unbind int32 bindAction = 2; // 1: bind, 2:unbind
int64 bindCount = 3; // bind coins count int64 bindCount = 3; // bind coins count
int64 blockTime = 4; // status bind block time string targetAddr = 4; // super node addr
string targetAddr = 5; // super node addr int64 blockTime = 5; // action bind block time
int64 blockHeight = 6; // action bind block height
} }
message ReceiptParaBindMinerInfo{ message ReceiptParaBindMinerInfo{
...@@ -183,6 +184,11 @@ message ReceiptParaNodeBindListUpdate{ ...@@ -183,6 +184,11 @@ message ReceiptParaNodeBindListUpdate{
ParaNodeBindList current = 2; ParaNodeBindList current = 2;
} }
message RespParaNodeBindList{
ParaNodeBindList list = 1;
repeated ParaBindMinerInfo details = 2;
}
message ParaBlock2MainMap { message ParaBlock2MainMap {
int64 height = 1; int64 height = 1;
string blockHash = 2; string blockHash = 2;
......
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