Minor Changes added

This commit is contained in:
AnilChinchawale 2019-03-12 15:57:12 +05:30
parent 6d1685646f
commit 22732d57fb
4 changed files with 319 additions and 39 deletions

View file

@ -44,10 +44,17 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/util"
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
)
const (
defaultGasPrice = 50 * params.Shannon
defaultGasPrice = 50 * params.Shannon
// statuses of candidates
statusMasternode = "MASTERNODE"
statusSlashed = "SLASHED"
statusProposed = "PROPOSED"
)
// PublicEthereumAPI provides an API to access Ethereum related information.
@ -494,13 +501,7 @@ func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
// 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{})
return s.b.GetRewardByHash(hash)
}
// GetBalance returns the amount of wei for the given address in the state of the
@ -614,6 +615,175 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
return res[:], state.Error()
}
func (s *PublicBlockChainAPI) GetBlockSignersByHash(ctx context.Context, blockHash common.Hash) ([]common.Address, error) {
block, err := s.b.GetBlock(ctx, blockHash)
if err != nil || block == nil {
return []common.Address{}, err
}
masternodes, err := s.GetMasternodes(ctx, block)
if err != nil || len(masternodes) == 0 {
log.Error("Failed to get masternodes", "err", err, "len(masternodes)", len(masternodes))
return []common.Address{}, err
}
return s.rpcOutputBlockSigners(block, ctx, masternodes)
}
func (s *PublicBlockChainAPI) GetBlockSignersByNumber(ctx context.Context, blockNumber rpc.BlockNumber) ([]common.Address, error) {
block, err := s.b.BlockByNumber(ctx, blockNumber)
if err != nil || block == nil {
return []common.Address{}, err
}
masternodes, err := s.GetMasternodes(ctx, block)
if err != nil || len(masternodes) == 0 {
log.Error("Failed to get masternodes", "err", err, "len(masternodes)", len(masternodes))
return []common.Address{}, err
}
return s.rpcOutputBlockSigners(block, ctx, masternodes)
}
func (s *PublicBlockChainAPI) GetBlockFinalityByHash(ctx context.Context, blockHash common.Hash) (int32, error) {
block, err := s.b.GetBlock(ctx, blockHash)
if err != nil || block == nil {
return int32(0), err
}
masternodes, err := s.GetMasternodes(ctx, block)
if err != nil || len(masternodes) == 0 {
log.Error("Failed to get masternodes", "err", err, "len(masternodes)", len(masternodes))
return int32(0), err
}
blockSigners, err := s.rpcOutputBlockSigners(block, ctx, masternodes)
if err != nil {
return int32(0), err
}
return int32(100 * len(blockSigners) / len(masternodes)), err
}
func (s *PublicBlockChainAPI) GetBlockFinalityByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (int32, error) {
block, err := s.b.BlockByNumber(ctx, blockNumber)
if err != nil || block == nil {
return int32(0), err
}
masternodes, err := s.GetMasternodes(ctx, block)
if err != nil || len(masternodes) == 0 {
log.Error("Failed to get masternodes", "err", err, "len(masternodes)", len(masternodes))
return int32(0), err
}
blockSigners, err := s.rpcOutputBlockSigners(block, ctx, masternodes)
if err != nil {
return int32(0), err
}
return int32(100 * len(blockSigners) / len(masternodes)), err
}
// GetMasternodes returns masternodes set at the starting block of epoch of the given block
func (s *PublicBlockChainAPI) GetMasternodes(ctx context.Context, b *types.Block) ([]common.Address, error) {
var masternodes []common.Address
if b.Number().Int64() >= 0 {
curBlockNumber := b.Number().Uint64()
prevBlockNumber := curBlockNumber + (common.MergeSignRange - (curBlockNumber % common.MergeSignRange))
latestBlockNumber := s.b.CurrentBlock().Number().Uint64()
if prevBlockNumber >= latestBlockNumber || !s.b.ChainConfig().IsTIP2019(b.Number()) {
prevBlockNumber = curBlockNumber
}
if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok {
// Get block epoc latest.
lastCheckpointNumber := prevBlockNumber - (prevBlockNumber % s.b.ChainConfig().XDPoS.Epoch)
prevCheckpointBlock, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(lastCheckpointNumber))
if prevCheckpointBlock != nil {
masternodes = engine.GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), curBlockNumber, s.b.ChainConfig().XDPoS.Epoch)
}
} else {
log.Error("Undefined XDPoS consensus engine")
}
}
return masternodes, nil
}
// GetCandidateStatus returns status of the given candidate at a specified epochNumber
func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAddress common.Address, epochNumber rpc.EpochNumber) (string, error) {
var (
block *types.Block
masternodes, penaltyList, candidates, proposedList []common.Address
penalties []byte
err error
)
block = s.b.CurrentBlock()
epoch := s.b.ChainConfig().XDPoS.Epoch
// TODO: we currently support the latest epoch only
//if epochNumber == rpc.LatestEpochNumber {
// block = s.b.CurrentBlock()
//} else {
// checkpointNumber := rpc.BlockNumber((uint64(epochNumber) - 1) * epoch)
// if checkpointNumber < 0 {
// checkpointNumber = 0
// }
// block, err = s.b.BlockByNumber(ctx, checkpointNumber)
// if err != nil || block == nil {
// return "", err
// }
//}
blockNum := block.Number().Uint64()
masternodes, err = s.GetMasternodes(ctx, block)
if err != nil || len(masternodes) == 0 {
log.Error("Failed to get masternodes", "err", err, "len(masternodes)", len(masternodes))
return "", err
}
for _, masternode := range masternodes {
if coinbaseAddress == masternode {
return statusMasternode, nil
}
}
// look up recent checkpoint headers to get penalty list
for i := 0; i <= common.LimitPenaltyEpoch; i++ {
if blockNum > uint64(i) * epoch {
blockCheckpointNumber := rpc.BlockNumber(blockNum - (blockNum % epoch) - (uint64(i) * epoch))
blockCheckpoint, err := s.b.BlockByNumber(ctx, blockCheckpointNumber)
if err != nil {
log.Error("Failed to get block by number", "num", blockCheckpointNumber, "err", err)
continue
}
penalties = append(penalties, blockCheckpoint.Penalties()...)
}
}
if len(penalties) > 0 {
penaltyList = common.ExtractAddressFromBytes(penalties)
for _, pen := range penaltyList {
if coinbaseAddress == pen {
return statusSlashed, nil
}
}
}
// read smart contract to get candidate list
client, err := s.b.GetIPCClient()
if err != nil {
return "", err
}
addr := common.HexToAddress(common.MasternodeVotingSMC)
validator, err := contractValidator.NewXDCValidator(addr, client)
if err != nil {
return "", err
}
opts := new(bind.CallOpts)
candidates, err = validator.GetCandidates(opts)
if err != nil {
return "", err
}
// exclude masternodes
proposedList = common.RemoveItemFromArray(candidates, masternodes)
// exclude penalties
proposedList = common.RemoveItemFromArray(proposedList, penaltyList)
for _, proposed := range proposedList {
if coinbaseAddress == proposed {
return statusProposed, nil
}
}
return "", nil
}
// CallArgs represents the arguments for a call.
type CallArgs struct {
From common.Address `json:"from"`
@ -860,28 +1030,46 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
uncleHashes[i] = uncle.Hash()
}
fields["uncles"] = uncleHashes
return fields, nil
}
func (s *PublicBlockChainAPI) rpcOutputBlockSigners(b *types.Block, ctx context.Context, masternodes []common.Address) ([]common.Address, error) {
// Get signers for block.
client, err := s.b.GetIPCClient()
if err != nil {
log.Error("Fail to connect IPC client for block status", "error", err)
return []common.Address{}, err
}
var signers []common.Address
var filterSigners []common.Address
finality := int32(0)
if b.Number().Int64() > 0 {
addrBlockSigner := common.HexToAddress(common.BlockSigners)
signers, err = contracts.GetSignersFromContract(addrBlockSigner, client, b.Hash())
if err != nil {
log.Error("Fail to get signers from block signer SC.", "error", err)
blockNumber := b.Number().Uint64()
signedBlockNumber := blockNumber + (common.MergeSignRange - (blockNumber % common.MergeSignRange))
latestBlockNumber := s.b.CurrentBlock().Number()
if signedBlockNumber >= latestBlockNumber.Uint64() || !s.b.ChainConfig().IsTIP2019(b.Number()) {
signedBlockNumber = blockNumber
}
// Get block epoc latest.
if s.b.ChainConfig().XDPoS != nil {
engine := s.b.GetEngine()
lastCheckpointNumber := rpc.BlockNumber(b.Number().Uint64() - (b.Number().Uint64() % s.b.ChainConfig().XDPoS.Epoch))
prevCheckpointBlock, _ := s.b.BlockByNumber(ctx, lastCheckpointNumber)
if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok {
// Get block epoc latest.
lastCheckpointNumber := signedBlockNumber - (signedBlockNumber % s.b.ChainConfig().XDPoS.Epoch)
prevCheckpointBlock, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(lastCheckpointNumber))
if prevCheckpointBlock != nil {
masternodes := engine.(*XDPoS.XDPoS).GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), b.Number().Uint64(), s.b.ChainConfig().XDPoS.Epoch)
masternodes := engine.GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), blockNumber, s.b.ChainConfig().XDPoS.Epoch)
signedBlock, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(signedBlockNumber))
if s.b.ChainConfig().IsTIPSigning(latestBlockNumber) {
signers, err = GetSignersFromBlocks(s.b, signedBlock.NumberU64(), signedBlock.Hash(), masternodes)
} else {
signers, err = contracts.GetSignersByExecutingEVM(common.HexToAddress(common.BlockSigners), client, signedBlock.Hash())
}
if err != nil {
log.Error("Fail to get signers from block signer SC.", "error", err)
return nil, err
}
validator, _ := engine.RecoverValidator(b.Header())
creator, _ := engine.RecoverSigner(b.Header())
signers = append(signers, validator)
signers = append(signers, creator)
countFinality := 0
for _, masternode := range masternodes {
for _, signer := range signers {
@ -892,14 +1080,12 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
}
}
}
finality = int32(countFinality * 100 / len(masternodes))
}
} else {
log.Error("Undefined XDPoS consensus engine")
}
}
fields["signers"] = filterSigners
fields["finality"] = finality
return fields, nil
return filterSigners, nil
}
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
@ -1533,3 +1719,52 @@ func (s *PublicNetAPI) PeerCount() hexutil.Uint {
func (s *PublicNetAPI) Version() string {
return fmt.Sprintf("%d", s.networkVersion)
}
func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash, masternodes []common.Address) ([]common.Address, error) {
var addrs []common.Address
mapMN := map[common.Address]bool{}
for _, node := range masternodes {
mapMN[node] = true
}
if engine, ok := b.GetEngine().(*XDPoS.XDPoS); ok {
limitNumber := blockNumber - blockNumber%b.ChainConfig().XDPoS.Epoch + 2*b.ChainConfig().XDPoS.Epoch - 1
currentNumber := b.CurrentBlock().NumberU64()
if limitNumber > currentNumber {
limitNumber = currentNumber
}
for i := blockNumber + 1; i <= limitNumber; i++ {
header, err := b.HeaderByNumber(nil, rpc.BlockNumber(i))
if err != nil {
return addrs, err
}
signData, ok := engine.BlockSigners.Get(header.Hash())
var signTxs []*types.Transaction = nil
if !ok {
blockData, err := b.BlockByNumber(nil, rpc.BlockNumber(i))
if err != nil {
return addrs, err
}
signTxs = []*types.Transaction{}
for _, tx := range blockData.Transactions() {
if tx.IsSigningTransaction() {
signTxs = append(signTxs, tx)
}
}
} else {
signTxs = signData.([]*types.Transaction)
}
for _, signtx := range signTxs {
blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:])
from := *signtx.From()
if blkHash == blockHash && mapMN[from] {
addrs = append(addrs, from)
delete(mapMN, from)
}
}
if len(mapMN) == 0 {
break
}
}
}
return addrs, nil
}

View file

@ -18,8 +18,10 @@ package les
import (
"context"
"github.com/ethereum/go-ethereum/consensus/XDPoS"
"encoding/json"
"io/ioutil"
"math/big"
"path/filepath"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
@ -202,10 +204,24 @@ 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().(*XDPoS.XDPoS); ok {
rewards := c.GetRewards(hash)
if rewards != nil {
return rewards
header := s.eth.blockchain.GetHeaderByHash(hash)
if header != nil {
data, err := ioutil.ReadFile(filepath.Join(common.StoreRewardFolder, header.Number.String()+"."+header.Hash().Hex()))
if err == nil {
rewards := make(map[string]interface{})
err = json.Unmarshal(data, &rewards)
if err == nil {
return rewards
}
} else {
data, err = ioutil.ReadFile(filepath.Join(common.StoreRewardFolder, header.Number.String()+"."+header.HashNoValidator().Hex()))
if err == nil {
rewards := make(map[string]interface{})
err = json.Unmarshal(data, &rewards)
if err == nil {
return rewards
}
}
}
}
return make(map[string]interface{})

View file

@ -18,6 +18,7 @@ package miner
import (
"bytes"
"encoding/binary"
"fmt"
"math/big"
"os"
@ -410,8 +411,10 @@ func (self *worker) wait() {
}
}
// Send tx sign to smart contract blockSigners.
if err := contracts.CreateTransactionSign(self.config, self.eth.TxPool(), self.eth.AccountManager(), block, self.chainDb); err != nil {
log.Error("Fail to create tx sign for signer", "error", "err")
if block.NumberU64()%common.MergeSignRange == 0 || !self.config.IsTIP2019(block.Number()) {
if err := contracts.CreateTransactionSign(self.config, self.eth.TxPool(), self.eth.AccountManager(), block, self.chainDb); err != nil {
log.Error("Fail to create tx sign for signer", "error", "err")
}
}
}
}
@ -552,6 +555,7 @@ func (self *worker) commitNewWork() {
if atomic.LoadInt32(&self.mining) == 1 {
header.Coinbase = self.coinbase
}
if err := self.engine.Prepare(self.chain, header); err != nil {
log.Error("Failed to prepare header for new block", "err", err)
return
@ -580,12 +584,22 @@ func (self *worker) commitNewWork() {
if self.config.DAOForkSupport && self.config.DAOForkBlock != nil && self.config.DAOForkBlock.Cmp(header.Number) == 0 {
misc.ApplyDAOHardFork(work.state)
}
pending, err := self.eth.TxPool().Pending()
if err != nil {
log.Error("Failed to fetch pending transactions", "err", err)
return
if common.TIPSigning.Cmp(header.Number) == 0 {
work.state.DeleteAddress(common.HexToAddress(common.BlockSigners))
}
// won't grasp txs at checkpoint
var (
txs *types.TransactionsByPriceAndNonce
specialTxs types.Transactions
)
if self.config.XDPoS != nil && header.Number.Uint64()%self.config.XDPoS.Epoch != 0 {
pending, err := self.eth.TxPool().Pending()
if err != nil {
log.Error("Failed to fetch pending transactions", "err", err)
return
}
txs, specialTxs = types.NewTransactionsByPriceAndNonce(self.current.signer, pending, signers)
}
txs, specialTxs := types.NewTransactionsByPriceAndNonce(self.current.signer, pending, signers)
work.commitTransactions(self.mux, txs, specialTxs, self.chain, self.coinbase)
// compute uncles for the new block.
@ -618,7 +632,7 @@ func (self *worker) commitNewWork() {
return
}
if atomic.LoadInt32(&self.mining) == 1 {
log.Info("Committing new block", "number", work.Block.Number(), "txs", work.tcount, "special txs", len(specialTxs), "uncles", len(uncles), "elapsed", common.PrettyDuration(time.Since(tstart)))
log.Info("Committing new block", "number", work.Block.Number(), "txs", work.tcount, "special-txs", len(specialTxs), "uncles", len(uncles), "elapsed", common.PrettyDuration(time.Since(tstart)))
self.unconfirmed.Shift(work.Block.NumberU64() - 1)
self.lastParentBlockCommit = parent.Hash().Hex()
}
@ -661,6 +675,17 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
log.Trace("Ignoring reply protected special transaction", "hash", tx.Hash(), "eip155", env.config.EIP155Block)
continue
}
if tx.To().Hex() == common.BlockSigners {
if len(tx.Data()) < 68 {
log.Trace("Data special transaction invalid length", "hash", tx.Hash(), "data", len(tx.Data()))
continue
}
blkNumber := binary.BigEndian.Uint64(tx.Data()[8:40])
if blkNumber >= env.header.Number.Uint64() || blkNumber <= env.header.Number.Uint64()-env.config.XDPoS.Epoch*2 {
log.Trace("Data special transaction invalid number", "hash", tx.Hash(), "blkNumber", blkNumber, "miner", env.header.Number)
continue
}
}
// Start executing the transaction
env.state.Prepare(tx.Hash(), common.Hash{}, env.tcount)
nonce := env.state.GetNonce(from)
@ -694,6 +719,10 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
log.Trace("Not enough gas for further transactions", "gp", gp)
break
}
if txs == nil {
log.Info("this block has no transaction")
break
}
// Retrieve the next transaction and abort if all done
tx := txs.Peek()
if tx == nil {

View file

@ -190,14 +190,14 @@ func (s *Server) serveRequest(codec ServerCodec, singleShot bool, options CodecO
if singleShot {
if batch {
for _, req := range reqs {
if req.callb != nil && req.callb.method.Name == "SendTransaction" {
if req.callb != nil && req.callb.method.Name == "EnabledRPCSendTransaction" {
codec.Write(codec.CreateErrorResponse(&req.id, &invalidRequestError{message: "Only support send transaction with ipc"}))
return nil
}
}
s.execBatch(ctx, codec, reqs)
} else {
if reqs[0].callb != nil && reqs[0].callb.method.Name == "SendTransaction" {
if reqs[0].callb != nil && reqs[0].callb.method.Name == "EnabledRPCSendTransaction" {
codec.Write(codec.CreateErrorResponse(&reqs[0].id, &invalidRequestError{message: "Only support send transaction with ipc"}))
return nil
}