Commit 41f6c73e authored by madengji's avatar madengji Committed by vipwzw

minerMode to str

parent 22f11ae2
......@@ -96,8 +96,8 @@ coinBaseReward=3
unBindTime=24
#支持挖矿奖励的1e8小数模式,比如18coin 需要配置成1800000000 以支持小数位后的配置,如果true,意味着已经打开即coinReward=1800000000
decimalMode=false
#挖矿模式, 0:普通挖矿,1:减半挖矿,2:自定义
minerMode=0
#挖矿模式, normal:缺省挖矿,其他自定义,注册名字需要和配置名字保持一致
minerMode="normal"
#挖矿减半周期,按高度减半
halvePeriod=1000
......
......@@ -97,9 +97,8 @@ func (a *action) isSelfConsensOn(miner *pt.ParacrossMinerAction) (bool, error) {
func (a *action) issueCoins(miner *pt.ParacrossMinerAction) (*types.Receipt, error) {
cfg := a.api.GetConfig()
mode := int(cfg.MGInt("mver.consensus.paracross.minerMode", a.height))
if minerrewards.MinerRewards[mode] == nil {
mode := cfg.MGStr("mver.consensus.paracross.minerMode", a.height)
if _, ok := minerrewards.MinerRewards[mode]; !ok {
panic("getTotalReward not be set depend on consensus.paracross.minerMode")
}
......
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package minerrewards
import (
"fmt"
"math"
"strconv"
"strings"
"github.com/33cn/chain33/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
)
const (
startN uint32 = 11
minerUnit int64 = 10000
//addr:quota的配置
// 18.75/100份额,由于浮点数的原因,都扩大100倍即1875/10000
addrStaffA = "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4:1875" //18.75quota 1875/10000
addrStaffB = "1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR:1875" //18.75 quota
addrBoss = "1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k:6250" //62.50 quota
)
var addrs = []string{addrStaffA, addrStaffB, addrBoss}
var addrsMap = make(map[string]int64)
type custom struct{}
func checkQuota() {
var sum int64
for _, a := range addrs {
val := strings.Split(a, ":")
v, err := strconv.Atoi(val[1])
if err != nil || v == 0 {
panic(fmt.Sprintf("minerCustom checkQuota err=%s,addr=%s", err, a))
}
addrsMap[val[0]] = int64(v)
sum += int64(v)
}
if sum > minerUnit {
panic(fmt.Sprintf("minerCustom checkQuota sum=%d beyond %d", sum, minerUnit))
}
}
func init() {
register(customMiner, &custom{})
checkQuota()
}
func (c *custom) GetConfigReward(cfg *types.Chain33Config, height int64) (int64, int64, int64) {
n := getCurrentN(height)
return calcCoins(n), 0, 0
}
func getNHeight(n uint32) int64 {
v := 1 << n
return 40960 * (int64(v) - 1)
}
//高度 4096*(2^n -1)+1 开始减半, n=1:1~4096, n=2:4096+1~12288
func getCurrentN(height int64) uint32 {
if height <= 0 {
panic("height should bigger than 0")
}
var totalCycle uint32 = 1 << 30
offsetHeight := getNHeight(6)
for n := uint32(0); n < totalCycle; n++ {
leftVal := getNHeight(n)
rightVal := getNHeight(n + 1)
if offsetHeight+height > leftVal && offsetHeight+height <= rightVal {
return n + 1
}
}
panic("not enought total cycle")
}
//客户原有链大约50s出一个块,一个块是32/16/8..coins, 我们平均5s一个块,需要/10
func calcCoins(n uint32) int64 {
if n <= startN {
return 1e7 * (1 << (startN - n))
}
v := 1 << (n - startN)
vf := 1e7 / v
return int64(math.Trunc(float64(vf)))
}
func (c *custom) RewardMiners(coinReward int64, miners []string, height int64) ([]*pt.ParaMinerReward, int64) {
//找零
var change int64
var rewards []*pt.ParaMinerReward
coins, _, _ := c.GetConfigReward(nil, height)
var sum int64
//get quto to miner
for _, m := range miners {
if v, ok := addrsMap[m]; ok {
amount := (v * coins) / minerUnit
sum += amount
r := &pt.ParaMinerReward{Addr: m, Amount: amount}
rewards = append(rewards, r)
}
}
//所有找零给addrC
change = coins - sum
if change > 0 {
val := strings.Split(addrBoss, ":")
r := &pt.ParaMinerReward{Addr: val[0], Amount: change}
rewards = append(rewards, r)
}
return rewards, 0
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package minerrewards
import (
"fmt"
"testing"
"github.com/bmizerany/assert"
_ "github.com/33cn/plugin/plugin/crypto/bls"
)
func TestGetNHeight(t *testing.T) {
h := getNHeight(1)
assert.Equal(t, int64(40960), h)
h = getNHeight(2)
assert.Equal(t, int64(122880), h)
h = getNHeight(6)
assert.Equal(t, int64(2580480), h)
h = getNHeight(7)
assert.Equal(t, int64(5201920), h)
for i := 1; i < 10; i++ {
fmt.Println("n=", i, "height=", getNHeight(uint32(i)))
}
}
func TestGetN(t *testing.T) {
n := getCurrentN(1)
assert.Equal(t, uint32(7), n)
n = getCurrentN(2621440)
assert.Equal(t, uint32(7), n)
n = getCurrentN(2621441)
assert.Equal(t, uint32(8), n)
n = getCurrentN(39321600)
assert.Equal(t, uint32(10), n)
n = getCurrentN(39321601)
assert.Equal(t, uint32(11), n)
}
func TestGetBlockNum(t *testing.T) {
offset := getNHeight(6)
for n := uint32(7); n < 50; n++ {
blocks := getNHeight(n) - offset
secs := blocks * 5
secsOfYear := int64(60 * 60 * 24 * 365)
year := secs / secsOfYear
fmt.Println("n=", n, "coins=", calcCoins(n), "height=", blocks, "year=", year)
}
}
func TestGetCoins(t *testing.T) {
c := calcCoins(7)
assert.Equal(t, int64(16*1e7), c)
c = calcCoins(6)
assert.Equal(t, int64(32*1e7), c)
c = calcCoins(13)
assert.Equal(t, int64(0.25*1e7), c)
//for i:=uint32(0);i<50;i++{
// coin := calcCoins(i)
// fmt.Println("n",i,"coins",coin)
//}
}
func getCustomRewardMinerRst(miners []string, height int64) (map[string]int64, int64) {
c := &custom{}
res, change := c.RewardMiners(0, miners, height)
check := make(map[string]int64)
for _, r := range res {
//fmt.Println("addr",r.Addr,"amount",r.Amount)
check[r.Addr] += r.Amount
}
return check, change
}
func TestCustomRewardMiner(t *testing.T) {
staffA := "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"
staffB := "1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR"
staffBoss := "1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k"
miners := []string{staffA, staffB, staffBoss}
offsetHeight := getNHeight(6)
//height=1
height := int64(1)
check, change := getCustomRewardMinerRst(miners, height)
assert.Equal(t, int64(3*1e7), check[staffA])
assert.Equal(t, int64(3*1e7), check[staffB])
assert.Equal(t, int64(10*1e7), check[staffBoss])
assert.Equal(t, int64(0), change)
//height=262144
var n uint32
n = 8
height = getNHeight(n)
coins := calcCoins(n)
fmt.Println("n=", n, "coins=", coins)
check, change = getCustomRewardMinerRst(miners, height-offsetHeight)
assert.Equal(t, int64(1.5*1e7), check[staffA])
assert.Equal(t, int64(1.5*1e7), check[staffB])
assert.Equal(t, int64(5*1e7), check[staffBoss])
assert.Equal(t, int64(0), change)
//
n = 17
height = getNHeight(n)
coins = calcCoins(n)
fmt.Println("n=", n, "coins=", coins)
check, change = getCustomRewardMinerRst(miners, height-offsetHeight)
assert.Equal(t, int64(29296), check[staffA])
assert.Equal(t, int64(29296), check[staffB])
assert.Equal(t, int64(97658), check[staffBoss])
assert.Equal(t, int64(0), change)
//
n = 18
height = getNHeight(n)
coins = calcCoins(n)
fmt.Println("n=", n, "coins=", coins)
check, change = getCustomRewardMinerRst(miners, height-offsetHeight)
assert.Equal(t, int64(14648), check[staffA])
assert.Equal(t, int64(14648), check[staffB])
assert.Equal(t, int64(48829), check[staffBoss])
assert.Equal(t, int64(0), change)
}
# 用户定制挖矿奖励方案
## 需求
1. 挖矿数量规则按2^(11-n)计算,随着n增大,奖励减半
1. 比如n=7,奖励是16coin
1. n=8,奖励是8coin
由于新的链5s出一个块,老的链是50s一个块,新的链每一个块的挖矿奖励是原来的1/10
1. n从1开始都有一个自己的高度范围,超出高度范围增1,高度范围算法是40960×(2^n - 1)
1. n=1,高度范围是1~40960, 其中40960*(2^1 -1)=40960就是这个范围的最大高度
1. n=2,高度范围是40961~286720
1. n=6,范围是1269761~2580480
1. n=7,范围是2580481~5201920
如果height=1269880 就可以推导出n来。
由于新的链n从7开始奖励,但是新的链的高度是0,新链的高度偏移是40960*(2^6 -1)
1. 奖励份额分配,三个账户A,B,C,其中A,B分18.75%份额,C分62.5%份额
......@@ -5,31 +5,13 @@ import (
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
)
type normal struct {
}
type normal struct{}
func init() {
register(normalMiner, &normal{})
}
func (n *normal) RewardMiners(coinReward int64, miners []string, height int64) ([]*pt.ParaMinerReward, int64) {
//找零
var change int64
var rewards []*pt.ParaMinerReward
//分配给矿工的平均奖励
minerUnit := coinReward / int64(len(miners))
if minerUnit > 0 {
for _, m := range miners {
r := &pt.ParaMinerReward{Addr: m, Amount: minerUnit}
rewards = append(rewards, r)
}
//如果不等分转到发展基金
change = coinReward % minerUnit
}
return rewards, change
register("normal", &normal{})
}
//获取配置的奖励数值
func (n *normal) GetConfigReward(cfg *types.Chain33Config, height int64) (int64, int64, int64) {
coinReward := cfg.MGInt("mver.consensus.paracross.coinReward", height)
fundReward := cfg.MGInt("mver.consensus.paracross.coinDevFund", height)
......@@ -52,3 +34,22 @@ func (n *normal) GetConfigReward(cfg *types.Chain33Config, height int64) (int64,
}
return coinReward, fundReward, coinBaseReward
}
//奖励矿工算法
func (n *normal) RewardMiners(cfg *types.Chain33Config, coinReward int64, miners []string, height int64) ([]*pt.ParaMinerReward, int64) {
//找零
var change int64
var rewards []*pt.ParaMinerReward
//分配给矿工的平均奖励
minerUnit := coinReward / int64(len(miners))
if minerUnit > 0 {
for _, m := range miners {
r := &pt.ParaMinerReward{Addr: m, Amount: minerUnit}
rewards = append(rewards, r)
}
//如果不等分转到发展基金
change = coinReward % minerUnit
}
return rewards, change
}
......@@ -9,20 +9,14 @@ import (
type RewardPolicy interface {
GetConfigReward(cfg *types.Chain33Config, height int64) (int64, int64, int64)
RewardMiners(coinReward int64, miners []string, height int64) ([]*pt.ParaMinerReward, int64)
RewardMiners(cfg *types.Chain33Config, coinReward int64, miners []string, height int64) ([]*pt.ParaMinerReward, int64)
}
const (
normalMiner = iota
halveMiner
customMiner
)
var MinerRewards = make(map[int]RewardPolicy)
var MinerRewards = make(map[string]RewardPolicy)
func register(ty int, policy RewardPolicy) {
func register(ty string, policy RewardPolicy) {
if _, ok := MinerRewards[ty]; ok {
panic(fmt.Sprintf("paracross minerreward ty=%d registered", ty))
panic(fmt.Sprintf("paracross minerreward ty=%s registered", ty))
}
MinerRewards[ty] = policy
}
......@@ -46,11 +46,9 @@ func (a *action) rewardSuperNode(coinReward int64, miners []string, statusHeight
cfg := a.api.GetConfig()
receipt := &types.Receipt{Ty: types.ExecOk}
mode := int(cfg.MGInt("mver.consensus.paracross.minerMode", a.height))
if minerrewards.MinerRewards[mode] == nil {
panic("getReward not be set depend on consensus.paracross.minerMode")
}
rewards, change := minerrewards.MinerRewards[mode].RewardMiners(coinReward, miners, statusHeight)
mode := cfg.MGStr("mver.consensus.paracross.minerMode", a.height)
rewards, change := minerrewards.MinerRewards[mode].RewardMiners(cfg, coinReward, miners, statusHeight)
resp, err := a.rewardDeposit(rewards, statusHeight)
if err != nil {
return nil, 0, err
......@@ -124,7 +122,10 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe
return nil, nil
}
mode := int(cfg.MGInt("mver.consensus.paracross.minerMode", a.height))
mode := cfg.MGStr("mver.consensus.paracross.minerMode", a.height)
if _, ok := minerrewards.MinerRewards[mode]; !ok {
panic("getReward not be set depend on consensus.paracross.minerMode")
}
coinReward, fundReward, coinBaseReward := minerrewards.MinerRewards[mode].GetConfigReward(cfg, nodeStatus.Height)
fundAddr := cfg.MGStr("mver.consensus.fundKeyAddr", nodeStatus.Height)
......
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