Skip to content

Commit

Permalink
Merge pull request expanse-org#33 from dinhln89/master
Browse files Browse the repository at this point in the history
Initialize reward mechanism for masternodes
  • Loading branch information
ngtuna committed Jun 7, 2018
2 parents f7e72f2 + 659eb52 commit ef06236
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 9 deletions.
4 changes: 4 additions & 0 deletions cmd/puppeth/wizard_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func (w *wizard) makeGenesis() {
copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:])
}

fmt.Println()
fmt.Println("How many blocks per checkpoint? (default = 990)")
genesis.Config.Clique.RewardCheckpoint = uint64(w.readDefaultInt(990))

default:
log.Crit("Invalid consensus engine choice", "choice", choice)
}
Expand Down
69 changes: 63 additions & 6 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"sync"
"time"

"encoding/json"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand All @@ -39,7 +40,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
lru "github.com/hashicorp/golang-lru"
"github.com/hashicorp/golang-lru"
)

const (
Expand Down Expand Up @@ -385,14 +386,19 @@ func position(list []common.Address, x common.Address) int {
}

func YourTurn(snap *Snapshot, header *types.Header, cur common.Address) (bool, error) {
if header.Number.Uint64() == 0 {
// Not check signer for genesis block.
return true, nil
}

pre, err := ecrecover(header, snap.sigcache)
if err != nil {
return false, err
}
preIndex := position(snap.signers(), pre)
curIndex := position(snap.signers(), cur)
log.Info("Debugging info", "number of masternodes", len(snap.signers()), "previous", pre, "position", preIndex, "current", cur, "position", curIndex)
return (preIndex+1)%len(snap.signers()) == curIndex || pre.String() == genesisCoinBase, nil
return (preIndex+1)%len(snap.signers()) == curIndex, nil
}

// snapshot retrieves the authorization snapshot at a given point in time.
Expand Down Expand Up @@ -600,10 +606,9 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro
func (c *Clique) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
// set block reward
// FIXME: unit Ether could be too plump
chainReward := new(big.Int).SetUint64(chain.Config().Clique.Reward * params.Ether)

reward := new(big.Int).Set(chainReward)
state.AddBalance(header.Coinbase, reward)
if err := c.accumulateRewards(chain, state, header); err != nil {
return nil, err
}

// No block rewards in PoA, so the state remains as is and uncles are dropped
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
Expand Down Expand Up @@ -718,3 +723,55 @@ func (c *Clique) APIs(chain consensus.ChainReader) []rpc.API {
Public: false,
}}
}

func (c *Clique) accumulateRewards(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {
type rewardLog struct {
Sign uint64 `json:"sign"`
Reward float64 `json:"reward"`
}

number := header.Number.Uint64()
rCheckpoint := chain.Config().Clique.RewardCheckpoint

if number > 0 && rCheckpoint > 0 && number%rCheckpoint == 0 {
// Not reward for singer of genesis block and only calculate reward at checkpoint block.
parentHeader := chain.GetHeaderByHash(header.ParentHash)
startBlockNumber := number - rCheckpoint + 1
endBlockNumber := parentHeader.Number.Uint64()
signers := make(map[common.Address]*rewardLog)
totalSigner := uint64(0)

for i := startBlockNumber; i <= endBlockNumber; i++ {
blockHeader := chain.GetHeaderByNumber(i)
if signer, err := ecrecover(blockHeader, c.signatures); err != nil {
return err
} else {
_, exist := signers[signer]
if exist {
signers[signer].Sign++
} else {
signers[signer] = &rewardLog{1, 0}
}
totalSigner++
}
}

chainReward := new(big.Int).SetUint64(chain.Config().Clique.Reward * params.Ether)
// Update balance reward.
calcReward := new(big.Int)
for signer, rLog := range signers {
calcReward.Mul(chainReward, new(big.Int).SetUint64(rLog.Sign))
calcReward.Div(calcReward, new(big.Int).SetUint64(totalSigner))
rLog.Reward = float64(calcReward.Int64())

state.AddBalance(signer, calcReward)
}
jsonSigners, err := json.Marshal(signers)
if err != nil {
return err
}
log.Info("TOMO - Calculate reward at checkpoint", "startBlock", startBlockNumber, "endBlock", endBlockNumber, "signers", string(jsonSigners), "totalSigner", totalSigner, "totalReward", chainReward)
}

return nil
}
7 changes: 4 additions & 3 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,10 @@ func (c *EthashConfig) String() string {

// CliqueConfig is the consensus engine configs for proof-of-authority based sealing.
type CliqueConfig struct {
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint
Reward uint64 `json:"reward"` // Block reward - unit Ether
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint
Reward uint64 `json:"reward"` // Block reward - unit Ether
RewardCheckpoint uint64 `json:"rewardCheckpoint"` // Checkpoint block for calculate rewards.
}

// String implements the stringer interface, returning the consensus engine details.
Expand Down

0 comments on commit ef06236

Please sign in to comment.