Skip to content

Commit

Permalink
Merge pull request ethereum#367 from nguyenbatam/create_new_api_get_r…
Browse files Browse the repository at this point in the history
…eward

create new api get rewards
  • Loading branch information
ngtuna authored Dec 28, 2018
2 parents 8acdc87 + 1baaa30 commit b681865
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 17 deletions.
1 change: 1 addition & 0 deletions cmd/tomo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ var (
//utils.ExtraDataFlag,
configFileFlag,
utils.AnnounceTxsFlag,
utils.StoreRewardFlag,
}

rpcFlags = []cli.Flag{
Expand Down
11 changes: 10 additions & 1 deletion cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ var (
Name: "announce-txs",
Usage: "Always commit transactions",
}
StoreRewardFlag = cli.BoolFlag{
Name: "store-reward",
Usage: "Store reward to file",
}
DataDirFlag = DirectoryFlag{
Name: "datadir",
Usage: "Data directory for the databases and keystore",
Expand Down Expand Up @@ -1082,7 +1086,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
// TODO(fjl): force-enable this in --dev mode
cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
}

if ctx.GlobalIsSet(StoreRewardFlag.Name) {
cfg.StoreRewardFolder = filepath.Join(stack.DataDir(), "tomo", "rewards")
if _, err := os.Stat(cfg.StoreRewardFolder); os.IsNotExist(err) {
os.Mkdir(cfg.StoreRewardFolder, os.ModePerm)
}
}
// Override any default configs for hard coded networks.
switch {
case ctx.GlobalBool(TestnetFlag.Name):
Expand Down
21 changes: 19 additions & 2 deletions consensus/posv/posv.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,14 @@ type Posv struct {
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
validatorSignatures *lru.ARCCache // Signatures of recent blocks to speed up mining
verifiedHeaders *lru.ARCCache
rewards *lru.ARCCache
proposals map[common.Address]bool // Current list of proposals we are pushing

signer common.Address // Ethereum address of the signing key
signFn clique.SignerFn // Signer function to authorize hashes with
lock sync.RWMutex // Protects the signer fields

HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{})
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
HookVerifyMNs func(header *types.Header, signers []common.Address) error
Expand All @@ -240,13 +241,15 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv {
signatures, _ := lru.NewARC(inmemorySnapshots)
validatorSignatures, _ := lru.NewARC(inmemorySnapshots)
verifiedHeaders, _ := lru.NewARC(inmemorySnapshots)
rewards, _ := lru.NewARC(inmemorySnapshots)
return &Posv{
config: &conf,
db: db,
recents: recents,
signatures: signatures,
verifiedHeaders: verifiedHeaders,
validatorSignatures: validatorSignatures,
rewards: rewards,
proposals: make(map[common.Address]bool),
}
}
Expand Down Expand Up @@ -847,9 +850,11 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state
rCheckpoint := chain.Config().Posv.RewardCheckpoint

if c.HookReward != nil && number%rCheckpoint == 0 {
if err := c.HookReward(chain, state, header); err != nil {
err, rewardResults := c.HookReward(chain, state, header)
if err != nil {
return nil, err
}
c.rewards.Add(header.Hash(), rewardResults)
}

// the state remains as is and uncles are dropped
Expand Down Expand Up @@ -1079,3 +1084,15 @@ func Hop(len, pre, cur int) int {
return len - 1
}
}

func (c *Posv) GetRewards(hash common.Hash) map[string]interface{} {
rewards, ok := c.rewards.Get(hash)
if !ok {
return nil
}
return rewards.(map[string]interface{})
}

func (c *Posv) InsertRewards(hash common.Hash, rewards map[string]interface{}) {
c.rewards.Add(hash, rewards)
}
6 changes: 3 additions & 3 deletions contracts/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,17 +387,17 @@ func GetCandidatesOwnerBySigner(validator *contractValidator.TomoValidator, sign
}

// Calculate reward for holders.
func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) error {
func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) {
rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator)
if err != nil {
return err
return err, nil
}
if len(rewards) > 0 {
for holder, reward := range rewards {
state.AddBalance(holder, reward)
}
}
return nil
return nil, rewards
}

// Get reward balance rates for master node, founder and holders.
Expand Down
13 changes: 10 additions & 3 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,10 @@ type BlockChain struct {
validator Validator // block and state validator interface
vmConfig vm.Config

badBlocks *lru.Cache // Bad block cache
IPCEndpoint string
Client *ethclient.Client // Global ipc client instance.
badBlocks *lru.Cache // Bad block cache
IPCEndpoint string
Client *ethclient.Client // Global ipc client instance.
HookWriteRewards func(header *types.Header)
}

// NewBlockChain returns a fully initialised block chain using information
Expand Down Expand Up @@ -1222,6 +1223,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
}
}
}
if bc.HookWriteRewards != nil {
bc.HookWriteRewards(block.Header())
}
}
// Append a single chain head event if we've progressed the chain
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
Expand Down Expand Up @@ -1428,6 +1432,9 @@ func (bc *BlockChain) insertBlock(block *types.Block) ([]interface{}, []*types.L
events = append(events, ChainHeadEvent{block})
log.Debug("New ChainHeadEvent from fetcher ", "number", block.NumberU64(), "hash", block.Hash())
}
if bc.HookWriteRewards != nil {
bc.HookWriteRewards(block.Header())
}
return events, coalescedLogs, nil
}

Expand Down
11 changes: 11 additions & 0 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package eth

import (
"context"
"github.com/ethereum/go-ethereum/consensus/posv"
"math/big"

"github.com/ethereum/go-ethereum/accounts"
Expand Down Expand Up @@ -233,3 +234,13 @@ func (b *EthApiBackend) GetIPCClient() (*ethclient.Client, error) {
func (b *EthApiBackend) GetEngine() consensus.Engine {
return b.eth.engine
}

func (s *EthApiBackend) GetRewardByHash(hash common.Hash) map[string]interface{} {
if c, ok := s.eth.Engine().(*posv.Posv); ok {
rewards := c.GetRewards(hash)
if rewards != nil {
return rewards
}
}
return make(map[string]interface{})
}
43 changes: 37 additions & 6 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
package eth

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"math/big"
"path/filepath"
"runtime"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -286,17 +289,19 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}

// Hook calculates reward for masternodes
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) {
client, err := eth.blockchain.GetClient()
if err != nil {
log.Error("Fail to connect IPC client for blockSigner", "error", err)
return err, nil
}
number := header.Number.Uint64()
rCheckpoint := chain.Config().Posv.RewardCheckpoint
foudationWalletAddr := chain.Config().Posv.FoudationWalletAddr
if foudationWalletAddr == (common.Address{}) {
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr)
}
rewards := make(map[string]interface{})
if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) {
start := time.Now()
// Get signers in blockSigner smartcontract.
Expand All @@ -309,30 +314,36 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
if err != nil {
log.Error("Fail to get signers for reward checkpoint", "error", err)
return err, nil
}
rewards["signers"] = signers
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
if err != nil {
log.Error("Fail to calculate reward for signers", "error", err)
return err, nil
}
// Get validator.
validator, err := contract.NewTomoValidator(common.HexToAddress(common.MasternodeVotingSMC), client)
if err != nil {
log.Error("Fail get instance of Tomo Validator", "error", err)

return err
return err, nil
}
// Add reward for coin holders.
voterResults := make(map[common.Address]interface{})
if len(signers) > 0 {
for signer, calcReward := range rewardSigners {
err := contracts.CalculateRewardForHolders(foudationWalletAddr, validator, state, signer, calcReward)
err, rewards := contracts.CalculateRewardForHolders(foudationWalletAddr, validator, state, signer, calcReward)
if err != nil {
log.Error("Fail to calculate reward for holders.", "error", err)
return err, nil
}
voterResults[signer] = rewards
}
}
rewards["rewards"] = voterResults
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
}
return nil
return nil, rewards
}

// Hook verifies masternodes set
Expand Down Expand Up @@ -363,8 +374,28 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
return false
}
eth.blockchain.HookWriteRewards = func(header *types.Header) {
if len(config.StoreRewardFolder) > 0 {
rewards := c.GetRewards(header.Hash())
if rewards == nil {
rewards = c.GetRewards(header.HashNoValidator())
if rewards != nil {
c.InsertRewards(header.Hash(), rewards)
}
}
if rewards == nil {
return
}
data, err := json.Marshal(rewards)
if err == nil {
err = ioutil.WriteFile(filepath.Join(config.StoreRewardFolder, header.Number.String()+"."+header.Hash().Hex()), data, 0644)
}
if err != nil {
log.Error("Error when save reward info ", "number", header.Number, "hash", header.Hash().Hex(), "err", err)
}
}
}
}

return eth, nil
}

Expand Down
2 changes: 2 additions & 0 deletions eth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ type Config struct {

// Miscellaneous options
DocRoot string `toml:"-"`

StoreRewardFolder string
}

type configMarshaling struct {
Expand Down
11 changes: 11 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,17 @@ func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
return header.Number
}

// BlockNumber returns the block number of the chain head.
func (s *PublicBlockChainAPI) GetRewardByHash(hash common.Hash) map[string]interface{} {
if c, ok := s.b.GetEngine().(*posv.Posv); ok {
rewards := c.GetRewards(hash)
if rewards != nil {
return rewards
}
}
return make(map[string]interface{})
}

// GetBalance returns the amount of wei for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.
Expand Down
1 change: 1 addition & 0 deletions internal/ethapi/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type Backend interface {
CurrentBlock() *types.Block
GetIPCClient() (*ethclient.Client, error)
GetEngine() consensus.Engine
GetRewardByHash(hash common.Hash) map[string]interface{}
}

func GetAPIs(apiBackend Backend) []rpc.API {
Expand Down
5 changes: 5 additions & 0 deletions internal/web3ext/web3ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,11 @@ web3._extend({
call: 'eth_getRawTransactionByHash',
params: 1
}),
new web3._extend.Method({
name: 'getRewardByHash',
call: 'eth_getRewardByHash',
params: 1
}),
new web3._extend.Method({
name: 'getRawTransactionFromBlock',
call: function(args) {
Expand Down
10 changes: 10 additions & 0 deletions les/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package les

import (
"context"
"github.com/ethereum/go-ethereum/consensus/posv"
"math/big"

"github.com/ethereum/go-ethereum/accounts"
Expand Down Expand Up @@ -200,3 +201,12 @@ func (b *LesApiBackend) GetIPCClient() (*ethclient.Client, error) {
func (b *LesApiBackend) GetEngine() consensus.Engine {
return b.eth.engine
}
func (s *LesApiBackend) GetRewardByHash(hash common.Hash) map[string]interface{} {
if c, ok := s.eth.Engine().(*posv.Posv); ok {
rewards := c.GetRewards(hash)
if rewards != nil {
return rewards
}
}
return make(map[string]interface{})
}
4 changes: 2 additions & 2 deletions params/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (

const (
VersionMajor = 1 // Major version component of the current release
VersionMinor = 1 // Minor version component of the current release
VersionPatch = 3 // Patch version component of the current release
VersionMinor = 2 // Minor version component of the current release
VersionPatch = 0 // Patch version component of the current release
VersionMeta = "stable" // Version metadata to append to the version string
)

Expand Down

0 comments on commit b681865

Please sign in to comment.