create new api get reward

This commit is contained in:
parmarrushabh 2018-11-19 11:21:42 +05:30
parent bd61027260
commit 51c88fe8ce
11 changed files with 102 additions and 13 deletions

View file

@ -122,6 +122,7 @@ var (
//utils.ExtraDataFlag, //utils.ExtraDataFlag,
configFileFlag, configFileFlag,
utils.AnnounceTxsFlag, utils.AnnounceTxsFlag,
utils.StoreRewardFlag,
} }
rpcFlags = []cli.Flag{ rpcFlags = []cli.Flag{

View file

@ -115,6 +115,10 @@ var (
Name: "announce-txs", Name: "announce-txs",
Usage: "Always commit transactions", Usage: "Always commit transactions",
} }
StoreRewardFlag = cli.BoolFlag{
Name: "store-reward",
Usage: "Store reward to file",
}
DataDirFlag = DirectoryFlag{ DataDirFlag = DirectoryFlag{
Name: "datadir", Name: "datadir",
Usage: "Data directory for the databases and keystore", Usage: "Data directory for the databases and keystore",
@ -1081,6 +1085,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
} }
if ctx.GlobalIsSet(StoreRewardFlag.Name) {
cfg.StoreRewardFolder = filepath.Join(stack.DataDir(), "XDC", "rewards")
if _, err := os.Stat(cfg.StoreRewardFolder); os.IsNotExist(err) {
os.Mkdir(cfg.StoreRewardFolder, os.ModePerm)
}
}
// Override any default configs for hard coded networks. // Override any default configs for hard coded networks.
switch { switch {
case ctx.GlobalBool(TestnetFlag.Name): case ctx.GlobalBool(TestnetFlag.Name):

View file

@ -372,17 +372,17 @@ func GetCandidatesOwnerBySigner(validator *contractValidator.XDCValidator, signe
} }
// Calculate reward for holders. // Calculate reward for holders.
func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.XDCValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) error { func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.XDCValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) {
rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator) rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator)
if err != nil { if err != nil {
return err return err, nil
} }
if len(rewards) > 0 { if len(rewards) > 0 {
for holder, reward := range rewards { for holder, reward := range rewards {
state.AddBalance(holder, reward) state.AddBalance(holder, reward)
} }
} }
return nil return nil, rewards
} }
// Get reward balance rates for master node, founder and holders. // Get reward balance rates for master node, founder and holders.

View file

@ -141,9 +141,10 @@ type BlockChain struct {
validator Validator // block and state validator interface validator Validator // block and state validator interface
vmConfig vm.Config vmConfig vm.Config
badBlocks *lru.Cache // Bad block cache badBlocks *lru.Cache // Bad block cache
IPCEndpoint string IPCEndpoint string
Client *ethclient.Client // Global ipc client instance. Client *ethclient.Client // Global ipc client instance.
HookWriteRewards func(header *types.Header)
} }
// NewBlockChain returns a fully initialised block chain using information // NewBlockChain returns a fully initialised block chain using information
@ -1223,6 +1224,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 // Append a single chain head event if we've progressed the chain
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() { if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
@ -1429,6 +1433,9 @@ func (bc *BlockChain) insertBlock(block *types.Block) ([]interface{}, []*types.L
events = append(events, ChainHeadEvent{block}) events = append(events, ChainHeadEvent{block})
log.Debug("New ChainHeadEvent from fetcher ", "number", block.NumberU64(), "hash", block.Hash()) log.Debug("New ChainHeadEvent from fetcher ", "number", block.NumberU64(), "hash", block.Hash())
} }
if bc.HookWriteRewards != nil {
bc.HookWriteRewards(block.Header())
}
return events, coalescedLogs, nil return events, coalescedLogs, nil
} }

View file

@ -18,6 +18,7 @@ package eth
import ( import (
"context" "context"
"github.com/ethereum/go-ethereum/consensus/XDPoS"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
@ -233,3 +234,13 @@ func (b *EthApiBackend) GetIPCClient() (*ethclient.Client, error) {
func (b *EthApiBackend) GetEngine() consensus.Engine { func (b *EthApiBackend) GetEngine() consensus.Engine {
return b.eth.engine return b.eth.engine
} }
func (s *EthApiBackend) GetRewardByHash(hash common.Hash) map[string]interface{} {
if c, ok := s.eth.Engine().(*XDPoS.XDPoS); ok {
rewards := c.GetRewards(hash)
if rewards != nil {
return rewards
}
}
return make(map[string]interface{})
}

View file

@ -19,9 +19,12 @@
package eth package eth
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"math/big" "math/big"
"path/filepath"
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -287,10 +290,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
} }
// Hook calculates reward for masternodes // 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() client, err := eth.blockchain.GetClient()
if err != nil { if err != nil {
log.Error("Fail to connect IPC client for blockSigner", "error", err) log.Error("Fail to connect IPC client for blockSigner", "error", err)
return err, nil
} }
number := header.Number.Uint64() number := header.Number.Uint64()
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
@ -298,6 +302,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if foudationWalletAddr == (common.Address{}) { if foudationWalletAddr == (common.Address{}) {
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr) log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr)
} }
rewards := make(map[string]interface{})
if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) { if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) {
start := time.Now() start := time.Now()
// Get signers in blockSigner smartcontract. // Get signers in blockSigner smartcontract.
@ -310,30 +315,36 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner) signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
if err != nil { if err != nil {
log.Error("Fail to get signers for reward checkpoint", "error", err) log.Error("Fail to get signers for reward checkpoint", "error", err)
return err, nil
} }
rewards["signers"] = signers
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner) rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
if err != nil { if err != nil {
log.Error("Fail to calculate reward for signers", "error", err) log.Error("Fail to calculate reward for signers", "error", err)
return err, nil
} }
// Get validator. // Get validator.
validator, err := contract.NewXDCValidator(common.HexToAddress(common.MasternodeVotingSMC), client) validator, err := contract.NewXDCValidator(common.HexToAddress(common.MasternodeVotingSMC), client)
if err != nil { if err != nil {
log.Error("Fail get instance of XDC Validator", "error", err) log.Error("Fail get instance of XDC Validator", "error", err)
return err, nil
return err
} }
// Add reward for coin holders. // Add reward for coin holders.
voterResults := make(map[common.Address]interface{})
if len(signers) > 0 { if len(signers) > 0 {
for signer, calcReward := range rewardSigners { 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 { if err != nil {
log.Error("Fail to calculate reward for holders.", "error", err) 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))) log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
} }
return nil return nil, rewards
} }
// Hook verifies masternodes set // Hook verifies masternodes set
@ -364,8 +375,28 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
} }
return false 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 return eth, nil
} }

View file

@ -112,6 +112,8 @@ type Config struct {
// Miscellaneous options // Miscellaneous options
DocRoot string `toml:"-"` DocRoot string `toml:"-"`
StoreRewardFolder string
} }
type configMarshaling struct { type configMarshaling struct {

View file

@ -492,6 +492,17 @@ func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
return header.Number 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().(*XDPoS.XDPoS); 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 // 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 // given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed. // block numbers are also allowed.

View file

@ -73,6 +73,7 @@ type Backend interface {
CurrentBlock() *types.Block CurrentBlock() *types.Block
GetIPCClient() (*ethclient.Client, error) GetIPCClient() (*ethclient.Client, error)
GetEngine() consensus.Engine GetEngine() consensus.Engine
GetRewardByHash(hash common.Hash) map[string]interface{}
} }
func GetAPIs(apiBackend Backend) []rpc.API { func GetAPIs(apiBackend Backend) []rpc.API {

View file

@ -461,6 +461,11 @@ web3._extend({
call: 'eth_getRawTransactionByHash', call: 'eth_getRawTransactionByHash',
params: 1 params: 1
}), }),
new web3._extend.Method({
name: 'getRewardByHash',
call: 'eth_getRewardByHash',
params: 1
}),
new web3._extend.Method({ new web3._extend.Method({
name: 'getRawTransactionFromBlock', name: 'getRawTransactionFromBlock',
call: function(args) { call: function(args) {

View file

@ -18,6 +18,7 @@ package les
import ( import (
"context" "context"
"github.com/ethereum/go-ethereum/consensus/XDPoS"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
@ -200,3 +201,12 @@ func (b *LesApiBackend) GetIPCClient() (*ethclient.Client, error) {
func (b *LesApiBackend) GetEngine() consensus.Engine { func (b *LesApiBackend) GetEngine() consensus.Engine {
return b.eth.engine return b.eth.engine
} }
func (s *LesApiBackend) GetRewardByHash(hash common.Hash) map[string]interface{} {
if c, ok := s.eth.Engine().(*XDPoS.XDPoS); ok {
rewards := c.GetRewards(hash)
if rewards != nil {
return rewards
}
}
return make(map[string]interface{})
}