Commit db10be7e authored by madengji's avatar madengji Committed by vipwzw

add bind miner query by miner

parent 93df499c
......@@ -26,7 +26,7 @@ const (
maxRcvTxCount = 100 //channel buffer, max 100 nodes, 1 height tx or 1 txgroup per node
leaderSyncInt = 15 //15s heartbeat sync interval
defLeaderSwitchInt = 100 //每隔100个共识高度切换一次leader,大约6小时(按50个空块间隔计算)
delaySubP2pTopic = 30 //30s to sub p2p topic
delaySubP2pTopic = 10 //30s to sub p2p topic
paraBlsSignTopic = "PARA-BLS-SIGN-TOPIC"
)
......
......@@ -581,19 +581,20 @@ func getNodeBindListCmd() *cobra.Command {
func addNodeBindCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("node", "n", "", "super node addr to bind miner")
cmd.MarkFlagRequired("node")
cmd.Flags().StringP("miner", "m", "", "bind miner addr")
}
func nodeBindInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
addr, _ := cmd.Flags().GetString("node")
node, _ := cmd.Flags().GetString("node")
miner, _ := cmd.Flags().GetString("miner")
var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX
params.FuncName = "GetNodeBindMinerList"
params.Payload = types.MustPBToJSON(&types.ReqString{Data: addr})
params.Payload = types.MustPBToJSON(&pt.ParaNodeBindOne{SuperNode: node, Miner: miner})
var res pt.RespParaNodeBindList
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
......
......@@ -192,6 +192,6 @@ func calcParaBindMinerAddr(node, bind string) []byte {
return []byte(fmt.Sprintf(paraBindMinderAddr+"%s-%s", node, bind))
}
func calcParaBindMinerNode(node string) []byte {
return []byte(paraBindMinderNode + node)
func calcParaBindMinerNode() []byte {
return []byte(paraBindMinderNode)
}
......@@ -534,29 +534,63 @@ func (p *Paracross) Query_GetHeight(req *types.ReqString) (*pt.ParacrossConsensu
return nil, types.ErrDecode
}
func getMinerListResp(db dbm.KV, list *pt.ParaNodeBindList) (types.Message, error) {
var resp pt.RespParaNodeBindList
resp.List = list
for _, n := range list.Miners {
info, err := getBindAddrInfo(db, n.SuperNode, n.Miner)
if err != nil {
clog.Error("Query_GetNodeBindMinerList get addr", "err", err, "node", n.SuperNode, "addr", n.Miner)
return nil, errors.Cause(err)
}
resp.Details = append(resp.Details, info)
}
return &resp, nil
}
// 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 {
func (p *Paracross) Query_GetNodeBindMinerList(in *pt.ParaNodeBindOne) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
list, err := getBindNodeInfo(p.GetStateDB(), in.Data)
list, err := getBindNodeInfo(p.GetStateDB())
if err != nil {
clog.Error("Query_GetNodeBindMinerList get node", "err", err, "req", in.Data)
clog.Error("Query_GetNodeBindMinerList get node", "err", err)
return nil, errors.Cause(err)
}
var resp pt.RespParaNodeBindList
resp.List = list
var newList pt.ParaNodeBindList
//按node query
if len(in.SuperNode) != 0 && len(in.Miner) == 0 {
for _, n := range list.Miners {
if n.SuperNode == in.SuperNode {
newList.Miners = append(newList.Miners, n)
}
}
return getMinerListResp(p.GetStateDB(), &newList)
}
for _, addr := range list.Miners {
info, err := getBindAddrInfo(p.GetStateDB(), in.Data, addr)
if err != nil {
clog.Error("Query_GetNodeBindMinerList get addr", "err", err, "node", in.Data, "addr", addr)
return nil, errors.Cause(err)
//按miner query
if len(in.SuperNode) == 0 && len(in.Miner) != 0 {
for _, n := range list.Miners {
if n.Miner == in.Miner {
newList.Miners = append(newList.Miners, n)
}
}
resp.Details = append(resp.Details, info)
return getMinerListResp(p.GetStateDB(), &newList)
}
//按唯一绑定查询
if len(in.SuperNode) != 0 && len(in.Miner) != 0 {
for _, n := range list.Miners {
if n.SuperNode == in.SuperNode && n.Miner == in.Miner {
newList.Miners = append(newList.Miners, n)
}
}
return getMinerListResp(p.GetStateDB(), &newList)
}
return &resp, nil
//获取所有
return getMinerListResp(p.GetStateDB(), list)
}
......@@ -8,6 +8,7 @@ import (
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/golang/protobuf/proto"
)
const (
......@@ -15,36 +16,28 @@ const (
opUnBind = 2
)
//根据挖矿节点地址 获取委托挖矿地址
func (a *action) getBindAddrs(nodes []string, statusHeight int64) []*pt.ParaNodeBindList {
var lists []*pt.ParaNodeBindList
for _, m := range nodes {
list, err := getBindNodeInfo(a.db, m)
if isNotFound(errors.Cause(err)) {
continue
}
if err != nil {
clog.Error("paracross getBindAddrs err", "height", statusHeight, "node", m)
continue
}
lists = append(lists, list)
//根据挖矿共识节点地址 过滤整体共识节点映射列表, 获取委托挖矿地址
func (a *action) getBindAddrs(nodes []string, statusHeight int64) (*pt.ParaNodeBindList, error) {
nodesMap := make(map[string]bool)
for _, n := range nodes {
nodesMap[n] = true
}
return lists
}
func isBindAddrFound(bindAddrs []*pt.ParaNodeBindList) bool {
if len(bindAddrs) <= 0 {
return false
var newLists pt.ParaNodeBindList
list, err := getBindNodeInfo(a.db)
if err != nil {
clog.Error("paracross getBindAddrs err", "height", statusHeight)
return nil, err
}
for _, addr := range bindAddrs {
if len(addr.Miners) > 0 {
return true
//这样检索是按照list的映射顺序,不是按照nodes的顺序(需要循环嵌套)
for _, m := range list.Miners {
if nodesMap[m.SuperNode] {
newLists.Miners = append(newLists.Miners, m)
}
}
return false
return &newLists, nil
}
func (a *action) rewardSuperNode(coinReward int64, miners []string, statusHeight int64) (*types.Receipt, int64, error) {
......@@ -70,21 +63,19 @@ func (a *action) rewardSuperNode(coinReward int64, miners []string, statusHeight
}
//奖励委托挖矿账户
func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindList, statusHeight int64) (*types.Receipt, int64, error) {
func (a *action) rewardBindAddr(coinReward int64, bindList *pt.ParaNodeBindList, statusHeight int64) (*types.Receipt, int64, error) {
if coinReward <= 0 {
return nil, 0, nil
}
//有可能一个bindAddr 在多个node绑定,这里会累计上去
var bindAddrList []*pt.ParaBindMinerInfo
for _, node := range bindList {
for _, miner := range node.Miners {
info, err := getBindAddrInfo(a.db, node.SuperNode, miner)
if err != nil {
return nil, 0, err
}
bindAddrList = append(bindAddrList, info)
for _, node := range bindList.Miners {
info, err := getBindAddrInfo(a.db, node.SuperNode, node.Miner)
if err != nil {
return nil, 0, err
}
bindAddrList = append(bindAddrList, info)
}
var totalCoins int64
......@@ -127,18 +118,21 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe
}
//超级节点地址
minerAddrs := getMiners(stat.Details, nodeStatus.BlockHash)
nodeAddrs := getSuperNodes(stat.Details, nodeStatus.BlockHash)
//委托地址
bindAddrs := a.getBindAddrs(minerAddrs, nodeStatus.Height)
bindAddrs, err := a.getBindAddrs(nodeAddrs, nodeStatus.Height)
if err != nil {
return nil, err
}
//奖励超级节点
minderRewards := coinReward
//如果有委托挖矿地址,则超级节点分baseReward部分,否则全部
if isBindAddrFound(bindAddrs) {
if len(bindAddrs.Miners) > 0 {
minderRewards = coinBaseReward
}
receipt := &types.Receipt{Ty: types.ExecOk}
r, change, err := a.rewardSuperNode(minderRewards, minerAddrs, nodeStatus.Height)
r, change, err := a.rewardSuperNode(minderRewards, nodeAddrs, nodeStatus.Height)
if err != nil {
return nil, err
}
......@@ -167,8 +161,8 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe
return receipt, nil
}
// getMiners 获取提交共识消息的矿工地址
func getMiners(detail *pt.ParacrossStatusDetails, blockHash []byte) []string {
// getSuperNodes 获取提交共识消息的矿工地址
func getSuperNodes(detail *pt.ParacrossStatusDetails, blockHash []byte) []string {
addrs := make([]string, 0)
for i, hash := range detail.BlockHash {
if bytes.Equal(hash, blockHash) {
......@@ -210,8 +204,8 @@ func makeAddrBindReceipt(node, addr string, prev, current *pt.ParaBindMinerInfo)
}
}
func makeNodeBindReceipt(addr string, prev, current *pt.ParaNodeBindList) *types.Receipt {
key := calcParaBindMinerNode(addr)
func makeNodeBindReceipt(prev, current *pt.ParaNodeBindList) *types.Receipt {
key := calcParaBindMinerNode()
log := &pt.ReceiptParaNodeBindListUpdate{
Prev: prev,
Current: current,
......@@ -233,51 +227,50 @@ func makeNodeBindReceipt(addr string, prev, current *pt.ParaNodeBindList) *types
//绑定到超级节点
func (a *action) bind2Node(node string) (*types.Receipt, error) {
info, err := getBindNodeInfo(a.db, node)
if err != nil && !isNotFound(errors.Cause(err)) {
list, err := getBindNodeInfo(a.db)
if err != nil {
return nil, errors.Wrap(err, "bind2Node")
}
//found
if info != nil {
listCopy := *info
info.Miners = append(info.Miners, a.fromaddr)
return makeNodeBindReceipt(node, &listCopy, info), nil
}
//unfound
var list pt.ParaNodeBindList
list.SuperNode = node
list.Miners = append(list.Miners, a.fromaddr)
return makeNodeBindReceipt(node, nil, &list), nil
old := proto.Clone(list).(*pt.ParaNodeBindList)
list.Miners = append(list.Miners, &pt.ParaNodeBindOne{SuperNode: node, Miner: a.fromaddr})
return makeNodeBindReceipt(old, list), nil
}
//从超级节点解绑
func (a *action) unbind2Node(node string) (*types.Receipt, error) {
list, err := getBindNodeInfo(a.db, node)
list, err := getBindNodeInfo(a.db)
if err != nil {
return nil, errors.Wrap(err, "unbind2Node")
}
newList := &pt.ParaNodeBindList{SuperNode: list.SuperNode}
newList := &pt.ParaNodeBindList{}
old := proto.Clone(list).(*pt.ParaNodeBindList)
for _, m := range list.Miners {
if m != a.fromaddr {
if m.SuperNode != node && m.Miner != a.fromaddr {
newList.Miners = append(newList.Miners, m)
}
}
return makeNodeBindReceipt(node, list, newList), nil
return makeNodeBindReceipt(old, newList), nil
}
func getBindNodeInfo(db dbm.KV, node string) (*pt.ParaNodeBindList, error) {
key := calcParaBindMinerNode(node)
func getBindNodeInfo(db dbm.KV) (*pt.ParaNodeBindList, error) {
var list pt.ParaNodeBindList
key := calcParaBindMinerNode()
data, err := db.Get(key)
if isNotFound(err) {
return &list, nil
}
if err != nil {
return nil, errors.Wrapf(err, "get key failed node=%s", node)
return nil, errors.Wrapf(err, "get key failed")
}
var list pt.ParaNodeBindList
err = types.Decode(data, &list)
if err != nil {
return nil, errors.Wrapf(err, "decode failed node=%s", node)
return nil, errors.Wrapf(err, "decode failed")
}
return &list, nil
}
......
# 平行链共识节点挖矿奖励规则
>平行链共识节点是参与平行链共识安全的节点,发送共识交易,同时享受平行链挖矿奖励
## 共识节点资格
1. 共识节点需要加入共识节点账户组才具有发送共识交易的资格,不然即使发送也不会被接受
1. 新的共识节点需要共识节点账户组成员超过2/3投票通过才可以加入共识节点账户组
## 共识节点挖矿奖励
1. 共识节点根据本地计算的区块哈希发送共识交易参与共识,共识达成后促使达成共识的节点享受挖矿奖励
1. 比如共识账户组有4个挖矿账户A,B,C,D,其中A,B,C,D都依次发送共识交易,基于超过2/3的规则,在C的共识交易收到后即达成共识,那么奖励将分给A,B,C,而D是在达成共识后发送的,不享受挖矿奖励
## 奖励规则和金额
>奖励规则和金额可配置
```
[mver.consensus.paracross]
#超级节点挖矿奖励
coinReward=18
#发展基金奖励
coinDevFund=12
#如果超级节点上绑定了委托账户,则奖励超级节点coinBaseReward,其余部分(coinReward-coinBaseReward)按权重分给委托账户
coinBaseReward=3
#委托账户最少解绑定时间(按小时)
unBindTime=24
```
1. 每个区块产生的挖矿总奖励如配置项是coinDevFund+coinReward=30,共识达成后,发展基金账户分走12,剩余的18个coin平均分给达成共识的节点
1. 如果有绑定挖矿的账户绑定了共识节点进行挖矿,则共识节点平分基础的coinBaseReward,剩余部分(coinReward-coinBaseReward)按绑定挖矿锁定币的权重数量分给绑定挖矿的节点。
## 绑定挖矿命令
1. 生成 绑定/解绑定 挖矿 的交易(未签名)
```
{
"method" : "Chain33.CreateTransaction",
"params" : [
{
"execer" : "{user.p.para}.paracross",
"actionName" : "ParaBindMiner",
"payload" : {
       "bindAction":"1"
"bindCoins" : 5,
"targetNode" : "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4",
}
}
],
}
```
**参数说明:**
|参数|类型|说明|
|----|----|----|
|method|string|Chain33.CreateTransaction|
|execer|string|必须是平行链的执行器user.p.para.paracross,title:user.p.para.按需调整|
|actionName|string|ParaBindMiner|
|bindAction|string|绑定:1,解绑定:2|
|bindCoins|int|绑定挖矿冻结币的份额,需冻结平行链原生代币,解绑定不需要此配置|
|targetNode|string|绑定目标共识节点,需要是共识账户组的成员|
......@@ -83,14 +83,14 @@ func (suite *RewardTestSuite) TestRewardBindAddr() {
key = calcParaBindMinerAddr(node, addr2)
suite.stateDB.Set(key, data)
list := &pt.ParaNodeBindList{
SuperNode: node,
Miners: []string{addr, addr2},
}
node1 := &pt.ParaNodeBindOne{SuperNode: node, Miner: addr}
node2 := &pt.ParaNodeBindOne{SuperNode: node, Miner: addr2}
lists := []*pt.ParaNodeBindList{list}
list := &pt.ParaNodeBindList{}
list.Miners = append(list.Miners, node1)
list.Miners = append(list.Miners, node2)
recp, change, err := suite.action.rewardBindAddr(50000005, lists, 1)
recp, change, err := suite.action.rewardBindAddr(50000005, list, 1)
suite.Nil(err)
suite.Equal(int64(5), change)
suite.Equal(int32(types.ExecOk), recp.Ty)
......
......@@ -180,9 +180,13 @@ message ReceiptParaBindMinerInfo{
ParaBindMinerInfo current = 3;
}
message ParaNodeBindList{
message ParaNodeBindOne{
string superNode = 1;
repeated string miners = 2;
string miner = 2;
}
message ParaNodeBindList{
repeated ParaNodeBindOne miners = 1;
}
message ReceiptParaNodeBindListUpdate{
......
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