Browse Source

Network setting (classic|mordor)

master
yuriy0803 5 years ago
parent
commit
8770a21668
  1. 1
      configs/api.json
  2. 2
      main.go
  3. 197
      payouts/unlocker.go
  4. 1
      proxy/config.go
  5. 15
      proxy/miner.go

1
configs/api.json

@ -3,6 +3,7 @@
"coin": "etc", "coin": "etc",
"name": "main", "name": "main",
"pplns": 9000, "pplns": 9000,
"network": "classic",
"proxy": { "proxy": {
"enabled": false, "enabled": false,
"listen": "0.0.0.0:8888", "listen": "0.0.0.0:8888",

2
main.go

@ -33,7 +33,7 @@ func startApi() {
} }
func startBlockUnlocker() { func startBlockUnlocker() {
u := payouts.NewBlockUnlocker(&cfg.BlockUnlocker, backend) u := payouts.NewBlockUnlocker(&cfg.BlockUnlocker, backend, &cfg.Network)
u.Start() u.Start()
} }

197
payouts/unlocker.go

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"math/big" "math/big"
"os"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -17,29 +17,28 @@ import (
) )
type UnlockerConfig struct { type UnlockerConfig struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
PoolFee float64 `json:"poolFee"` PoolFee float64 `json:"poolFee"`
PoolFeeAddress string `json:"poolFeeAddress"` PoolFeeAddress string `json:"poolFeeAddress"`
Donate bool `json:"donate"` Donate bool `json:"donate"`
Depth int64 `json:"depth"` Depth int64 `json:"depth"`
ImmatureDepth int64 `json:"immatureDepth"` ImmatureDepth int64 `json:"immatureDepth"`
KeepTxFees bool `json:"keepTxFees"` KeepTxFees bool `json:"keepTxFees"`
Interval string `json:"interval"` Interval string `json:"interval"`
Daemon string `json:"daemon"` Daemon string `json:"daemon"`
Timeout string `json:"timeout"` Timeout string `json:"timeout"`
Classic bool `json:"classic"` Ecip1017FBlock int64 `json:"ecip1017FBlock"`
Ecip1017EraRounds *big.Int `json:"ecip1017EraRounds"`
} }
const minDepth = 16 const minDepth = 16
const byzantiumHardForkHeight = 4370000
var homesteadReward = math.MustParseBig256("5000000000000000000") var disinflationRateQuotient = big.NewInt(4) // Disinflation rate quotient for ECIP1017
var byzantiumReward = math.MustParseBig256("3200000000000000000") var disinflationRateDivisor = big.NewInt(5) // Disinflation rate divisor for ECIP1017
var classicReward = math.MustParseBig256("3200000000000000000") var big32 = big.NewInt(32)
var big8 = big.NewInt(8)
// Donate 10% from pool fees to developers var homesteadReward = math.MustParseBig256("3200000000000000000")
const donationFee = 10
const donationAccount = "0xd92fa5a9732a0aec36dc8d5a6a1305dc2d3e09e6"
type BlockUnlocker struct { type BlockUnlocker struct {
config *UnlockerConfig config *UnlockerConfig
@ -49,7 +48,17 @@ type BlockUnlocker struct {
lastFail error lastFail error
} }
func NewBlockUnlocker(cfg *UnlockerConfig, backend *storage.RedisClient) *BlockUnlocker { func NewBlockUnlocker(cfg *UnlockerConfig, backend *storage.RedisClient, network *string) *BlockUnlocker {
if *network == "classic" {
cfg.Ecip1017FBlock = 5000000
cfg.Ecip1017EraRounds = big.NewInt(5000000)
} else if *network == "mordor" {
cfg.Ecip1017FBlock = 0
cfg.Ecip1017EraRounds = big.NewInt(2000000)
} else {
log.Fatalln("Invalid network set", network)
}
if len(cfg.PoolFeeAddress) != 0 && !util.IsValidHexAddress(cfg.PoolFeeAddress) { if len(cfg.PoolFeeAddress) != 0 && !util.IsValidHexAddress(cfg.PoolFeeAddress) {
log.Fatalln("Invalid poolFeeAddress", cfg.PoolFeeAddress) log.Fatalln("Invalid poolFeeAddress", cfg.PoolFeeAddress)
} }
@ -112,6 +121,11 @@ func (u *BlockUnlocker) unlockCandidates(candidates []*storage.BlockData) (*Unlo
/* Search for a normal block with wrong height here by traversing 16 blocks back and forward. /* Search for a normal block with wrong height here by traversing 16 blocks back and forward.
* Also we are searching for a block that can include this one as uncle. * Also we are searching for a block that can include this one as uncle.
*/ */
if candidate.Height < minDepth {
orphan = false
// avoid scanning the first 16 blocks
continue
}
for i := int64(minDepth * -1); i < minDepth; i++ { for i := int64(minDepth * -1); i < minDepth; i++ {
height := candidate.Height + i height := candidate.Height + i
@ -120,6 +134,7 @@ func (u *BlockUnlocker) unlockCandidates(candidates []*storage.BlockData) (*Unlo
} }
block, err := u.rpc.GetBlockByHeight(height) block, err := u.rpc.GetBlockByHeight(height)
if err != nil { if err != nil {
log.Printf("Error while retrieving block %v from node: %v", height, err) log.Printf("Error while retrieving block %v from node: %v", height, err)
return nil, err return nil, err
@ -162,7 +177,7 @@ func (u *BlockUnlocker) unlockCandidates(candidates []*storage.BlockData) (*Unlo
orphan = false orphan = false
result.uncles++ result.uncles++
err := handleUncle(height, uncle, candidate, u.config.Classic) err := handleUncle(height, uncle, candidate, u.config)
if err != nil { if err != nil {
u.halt = true u.halt = true
u.lastFail = err u.lastFail = err
@ -212,7 +227,13 @@ func (u *BlockUnlocker) handleBlock(block *rpc.GetBlockReply, candidate *storage
return err return err
} }
candidate.Height = correctHeight candidate.Height = correctHeight
reward := getConstReward(candidate.Height, u.config.Classic) era := GetBlockEra(big.NewInt(candidate.Height), u.config.Ecip1017EraRounds)
reward := getConstReward(era)
// Add reward for including uncles
uncleReward := getRewardForUncle(reward)
rewardForUncles := big.NewInt(0).Mul(uncleReward, big.NewInt(int64(len(block.Uncles))))
reward.Add(reward, rewardForUncles)
// Add TX fees // Add TX fees
extraTxReward, err := u.getExtraRewardForTx(block) extraTxReward, err := u.getExtraRewardForTx(block)
@ -225,23 +246,19 @@ func (u *BlockUnlocker) handleBlock(block *rpc.GetBlockReply, candidate *storage
reward.Add(reward, extraTxReward) reward.Add(reward, extraTxReward)
} }
// Add reward for including uncles
uncleReward := getRewardForUncle(candidate.Height, u.config.Classic)
rewardForUncles := big.NewInt(0).Mul(uncleReward, big.NewInt(int64(len(block.Uncles))))
reward.Add(reward, rewardForUncles)
candidate.Orphan = false candidate.Orphan = false
candidate.Hash = block.Hash candidate.Hash = block.Hash
candidate.Reward = reward candidate.Reward = reward
return nil return nil
} }
func handleUncle(height int64, uncle *rpc.GetBlockReply, candidate *storage.BlockData, isClassic bool) error { func handleUncle(height int64, uncle *rpc.GetBlockReply, candidate *storage.BlockData, cfg *UnlockerConfig) error {
uncleHeight, err := strconv.ParseInt(strings.Replace(uncle.Number, "0x", "", -1), 16, 64) uncleHeight, err := strconv.ParseInt(strings.Replace(uncle.Number, "0x", "", -1), 16, 64)
if err != nil { if err != nil {
return err return err
} }
reward := getUncleReward(uncleHeight, height, isClassic) era := GetBlockEra(big.NewInt(height), cfg.Ecip1017EraRounds)
reward := getUncleReward(new(big.Int).SetInt64(uncleHeight), new(big.Int).SetInt64(height), era, getConstReward(era))
candidate.Height = height candidate.Height = height
candidate.UncleHeight = uncleHeight candidate.UncleHeight = uncleHeight
candidate.Orphan = false candidate.Orphan = false
@ -253,7 +270,6 @@ func handleUncle(height int64, uncle *rpc.GetBlockReply, candidate *storage.Bloc
func (u *BlockUnlocker) unlockPendingBlocks() { func (u *BlockUnlocker) unlockPendingBlocks() {
if u.halt { if u.halt {
log.Println("Unlocking suspended due to last critical error:", u.lastFail) log.Println("Unlocking suspended due to last critical error:", u.lastFail)
os.Exit(1)
return return
} }
@ -309,7 +325,7 @@ func (u *BlockUnlocker) unlockPendingBlocks() {
totalPoolProfit := new(big.Rat) totalPoolProfit := new(big.Rat)
for _, block := range result.maturedBlocks { for _, block := range result.maturedBlocks {
revenue, minersProfit, poolProfit, roundRewards, percents, err := u.calculateRewards(block) revenue, minersProfit, poolProfit, roundRewards, err := u.calculateRewards(block)
if err != nil { if err != nil {
u.halt = true u.halt = true
u.lastFail = err u.lastFail = err
@ -337,11 +353,6 @@ func (u *BlockUnlocker) unlockPendingBlocks() {
entries := []string{logEntry} entries := []string{logEntry}
for login, reward := range roundRewards { for login, reward := range roundRewards {
entries = append(entries, fmt.Sprintf("\tREWARD %v: %v: %v Shannon", block.RoundKey(), login, reward)) entries = append(entries, fmt.Sprintf("\tREWARD %v: %v: %v Shannon", block.RoundKey(), login, reward))
per := new(big.Rat)
if val, ok := percents[login]; ok {
per = val
}
u.backend.WriteReward(login, reward, per, true, block)
} }
log.Println(strings.Join(entries, "\n")) log.Println(strings.Join(entries, "\n"))
} }
@ -413,7 +424,7 @@ func (u *BlockUnlocker) unlockAndCreditMiners() {
totalPoolProfit := new(big.Rat) totalPoolProfit := new(big.Rat)
for _, block := range result.maturedBlocks { for _, block := range result.maturedBlocks {
revenue, minersProfit, poolProfit, roundRewards, percents, err := u.calculateRewards(block) revenue, minersProfit, poolProfit, roundRewards, err := u.calculateRewards(block)
if err != nil { if err != nil {
u.halt = true u.halt = true
u.lastFail = err u.lastFail = err
@ -441,11 +452,6 @@ func (u *BlockUnlocker) unlockAndCreditMiners() {
entries := []string{logEntry} entries := []string{logEntry}
for login, reward := range roundRewards { for login, reward := range roundRewards {
entries = append(entries, fmt.Sprintf("\tREWARD %v: %v: %v Shannon", block.RoundKey(), login, reward)) entries = append(entries, fmt.Sprintf("\tREWARD %v: %v: %v Shannon", block.RoundKey(), login, reward))
per := new(big.Rat)
if val, ok := percents[login]; ok {
per = val
}
u.backend.WriteReward(login, reward, per, false, block)
} }
log.Println(strings.Join(entries, "\n")) log.Println(strings.Join(entries, "\n"))
} }
@ -458,21 +464,16 @@ func (u *BlockUnlocker) unlockAndCreditMiners() {
) )
} }
func (u *BlockUnlocker) calculateRewards(block *storage.BlockData) (*big.Rat, *big.Rat, *big.Rat, map[string]int64, map[string]*big.Rat, error) { func (u *BlockUnlocker) calculateRewards(block *storage.BlockData) (*big.Rat, *big.Rat, *big.Rat, map[string]int64, error) {
revenue := new(big.Rat).SetInt(block.Reward) revenue := new(big.Rat).SetInt(block.Reward)
minersProfit, poolProfit := chargeFee(revenue, u.config.PoolFee) minersProfit, poolProfit := chargeFee(revenue, u.config.PoolFee)
shares, err := u.backend.GetRoundShares(block.RoundHeight, block.Nonce) shares, err := u.backend.GetRoundShares(block.RoundHeight, block.Nonce)
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, err return nil, nil, nil, nil, err
}
totalShares := int64(0)
for _, val := range shares {
totalShares += val
} }
rewards, percents := calculateRewardsForShares(shares, totalShares, minersProfit) rewards := calculateRewardsForShares(shares, block.TotalShares, minersProfit)
if block.ExtraReward != nil { if block.ExtraReward != nil {
extraReward := new(big.Rat).SetInt(block.ExtraReward) extraReward := new(big.Rat).SetInt(block.ExtraReward)
@ -480,31 +481,23 @@ func (u *BlockUnlocker) calculateRewards(block *storage.BlockData) (*big.Rat, *b
revenue.Add(revenue, extraReward) revenue.Add(revenue, extraReward)
} }
if u.config.Donate {
var donation = new(big.Rat)
poolProfit, donation = chargeFee(poolProfit, donationFee)
login := strings.ToLower(donationAccount)
rewards[login] += weiToShannonInt64(donation)
}
if len(u.config.PoolFeeAddress) != 0 { if len(u.config.PoolFeeAddress) != 0 {
address := strings.ToLower(u.config.PoolFeeAddress) address := strings.ToLower(u.config.PoolFeeAddress)
rewards[address] += weiToShannonInt64(poolProfit) rewards[address] += weiToShannonInt64(poolProfit)
} }
return revenue, minersProfit, poolProfit, rewards, percents, nil return revenue, minersProfit, poolProfit, rewards, nil
} }
func calculateRewardsForShares(shares map[string]int64, total int64, reward *big.Rat) (map[string]int64, map[string]*big.Rat) { func calculateRewardsForShares(shares map[string]int64, total int64, reward *big.Rat) map[string]int64 {
rewards := make(map[string]int64) rewards := make(map[string]int64)
percents := make(map[string]*big.Rat)
for login, n := range shares { for login, n := range shares {
percents[login] = big.NewRat(n, total) percent := big.NewRat(n, total)
workerReward := new(big.Rat).Mul(reward, percents[login]) workerReward := new(big.Rat).Mul(reward, percent)
rewards[login] += weiToShannonInt64(workerReward) rewards[login] += weiToShannonInt64(workerReward)
} }
return rewards, percents return rewards
} }
// Returns new value after fee deduction and fee value. // Returns new value after fee deduction and fee value.
@ -521,35 +514,67 @@ func weiToShannonInt64(wei *big.Rat) int64 {
return value return value
} }
func getConstReward(height int64, isClassic bool) *big.Int { // GetRewardByEra gets a block reward at disinflation rate.
if !isClassic { // Constants MaxBlockReward, DisinflationRateQuotient, and DisinflationRateDivisor assumed.
if height >= byzantiumHardForkHeight { func GetBlockWinnerRewardByEra(era *big.Int, blockReward *big.Int) *big.Int {
return new(big.Int).Set(byzantiumReward) if era.Cmp(big.NewInt(0)) == 0 {
} return new(big.Int).Set(blockReward)
return new(big.Int).Set(homesteadReward) }
} else {
return new(big.Int).Set(classicReward) // MaxBlockReward _r_ * (4/5)**era == MaxBlockReward * (4**era) / (5**era)
// since (q/d)**n == q**n / d**n
// qed
var q, d, r *big.Int = new(big.Int), new(big.Int), new(big.Int)
q.Exp(disinflationRateQuotient, era, nil)
d.Exp(disinflationRateDivisor, era, nil)
r.Mul(blockReward, q)
r.Div(r, d)
return r
}
// GetBlockEra gets which "Era" a given block is within, given an era length (ecip-1017 has era=5,000,000 blocks)
// Returns a zero-index era number, so "Era 1": 0, "Era 2": 1, "Era 3": 2 ...
func GetBlockEra(blockNum, eraLength *big.Int) *big.Int {
// If genesis block or impossible negative-numbered block, return zero-val.
if blockNum.Sign() < 1 {
return new(big.Int)
} }
remainder := big.NewInt(0).Mod(big.NewInt(0).Sub(blockNum, big.NewInt(1)), eraLength)
base := big.NewInt(0).Sub(blockNum, remainder)
d := big.NewInt(0).Div(base, eraLength)
dremainder := big.NewInt(0).Mod(d, big.NewInt(1))
return new(big.Int).Sub(d, dremainder)
} }
func getRewardForUncle(height int64, isClassic bool) *big.Int { func getConstReward(era *big.Int) *big.Int {
reward := getConstReward(height, isClassic) var blockReward = homesteadReward
return new(big.Int).Div(reward, new(big.Int).SetInt64(32)) wr := GetBlockWinnerRewardByEra(era, blockReward)
return wr
} }
func getUncleReward(uHeight, height int64, isClassic bool) *big.Int { func getRewardForUncle(blockReward *big.Int) *big.Int {
if !isClassic { return new(big.Int).Div(blockReward, big32) //return new(big.Int).Div(reward, new(big.Int).SetInt64(32))
reward := getConstReward(height, isClassic) }
k := height - uHeight
reward.Mul(big.NewInt(8-k), reward) func getUncleReward(uHeight *big.Int, height *big.Int, era *big.Int, reward *big.Int) *big.Int {
reward.Div(reward, big.NewInt(8)) // Era 1 (index 0):
return reward // An extra reward to the winning miner for including uncles as part of the block, in the form of an extra 1/32 (0.15625ETC) per uncle included, up to a maximum of two (2) uncles.
} else { if era.Cmp(big.NewInt(0)) == 0 {
reward := getConstReward(height, isClassic) r := new(big.Int)
reward.Mul(reward, big.NewInt(3125)) r.Add(uHeight, big8) // 2,534,998 + 8 = 2,535,006
reward.Div(reward, big.NewInt(100000)) r.Sub(r, height) // 2,535,006 - 2,534,999 = 7
return reward r.Mul(r, reward) // 7 * 5e+18 = 35e+18
r.Div(r, big8) // 35e+18 / 8 = 7/8 * 5e+18
return r
} }
return getRewardForUncle(reward)
} }
func (u *BlockUnlocker) getExtraRewardForTx(block *rpc.GetBlockReply) (*big.Int, error) { func (u *BlockUnlocker) getExtraRewardForTx(block *rpc.GetBlockReply) (*big.Int, error) {

1
proxy/config.go

@ -17,6 +17,7 @@ type Config struct {
Threads int `json:"threads"` Threads int `json:"threads"`
Coin string `json:"coin"` Coin string `json:"coin"`
Network string `json:"network"`
Pplns int64 `json:"pplns"` Pplns int64 `json:"pplns"`
Redis storage.Config `json:"redis"` Redis storage.Config `json:"redis"`

15
proxy/miner.go

@ -11,11 +11,22 @@ import (
) )
var ecip1099FBlockClassic uint64 = 11700000 // classic mainnet var ecip1099FBlockClassic uint64 = 11700000 // classic mainnet
var ecip1099FBlockMordor uint64 = 2520000 // mordor testnet var ecip1099FBlockMordor uint64 = 2520000 // mordor
var hasher = etchash.New(&ecip1099FBlockClassic) var hasher *etchash.Etchash = nil
func (s *ProxyServer) processShare(login, id, ip string, t *BlockTemplate, params []string) (bool, bool) { func (s *ProxyServer) processShare(login, id, ip string, t *BlockTemplate, params []string) (bool, bool) {
if hasher == nil {
if s.config.Network == "classic" {
hasher = etchash.New(&ecip1099FBlockClassic)
} else if s.config.Network == "mordor" {
hasher = etchash.New(&ecip1099FBlockMordor)
} else {
// unknown network
log.Printf("Unknown network configuration %s", s.config.Network)
return false, false
}
}
// Now, the function received some work with login id and worker name and all information, ready to be processed // Now, the function received some work with login id and worker name and all information, ready to be processed
// and checked if it is a valid work or not, and if it is a block or not and write to db accordingly // and checked if it is a valid work or not, and if it is a block or not and write to db accordingly
nonceHex := params[0] nonceHex := params[0]

Loading…
Cancel
Save