github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/consensus/dpos/api.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package dpos
    18  
    19  import (
    20  	"fmt"
    21  	"github.com/DxChainNetwork/dxc/common"
    22  	"github.com/DxChainNetwork/dxc/common/hexutil"
    23  	"github.com/DxChainNetwork/dxc/consensus"
    24  	"github.com/DxChainNetwork/dxc/consensus/dpos/systemcontract"
    25  	"github.com/DxChainNetwork/dxc/core/state"
    26  	"github.com/DxChainNetwork/dxc/core/types"
    27  	"github.com/DxChainNetwork/dxc/rpc"
    28  	"math/big"
    29  )
    30  
    31  // API is a user facing RPC API to allow controlling the validator and voting
    32  // mechanisms of the proof-of-authority scheme.
    33  type API struct {
    34  	chain consensus.ChainHeaderReader
    35  	dpos  *Dpos
    36  }
    37  
    38  type ProposalInfo struct {
    39  	Id          string
    40  	Proposer    common.Address
    41  	PType       uint8
    42  	Deposit     *big.Int
    43  	Rate        uint8
    44  	Details     string
    45  	Name        string
    46  	InitBlock   *big.Int
    47  	Guarantee   common.Address
    48  	UpdateBlock *big.Int
    49  	Status      uint8
    50  }
    51  
    52  func (api *API) GetHeaderAndState(number *rpc.BlockNumber) (*types.Header, *state.StateDB, error) {
    53  	var header *types.Header
    54  	if number == nil || *number == rpc.LatestBlockNumber {
    55  		header = api.chain.CurrentHeader()
    56  	} else {
    57  		header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
    58  	}
    59  	if header == nil {
    60  		return nil, nil, errUnknownBlock
    61  	}
    62  	statedb, err := api.dpos.stateFn(header.Root)
    63  	return header, statedb, err
    64  }
    65  
    66  // GetSnapshot retrieves the state snapshot at a given block.
    67  func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
    68  	// Retrieve the requested block number (or current if none requested)
    69  	var header *types.Header
    70  	if number == nil || *number == rpc.LatestBlockNumber {
    71  		header = api.chain.CurrentHeader()
    72  	} else {
    73  		header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
    74  	}
    75  	// Ensure we have an actually valid block and return its snapshot
    76  	if header == nil {
    77  		return nil, errUnknownBlock
    78  	}
    79  	return api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    80  }
    81  
    82  // GetSnapshotAtHash retrieves the state snapshot at a given block.
    83  func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
    84  	header := api.chain.GetHeaderByHash(hash)
    85  	if header == nil {
    86  		return nil, errUnknownBlock
    87  	}
    88  	return api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    89  }
    90  
    91  // GetValidators retrieves the list of authorized validators at the specified block.
    92  func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) {
    93  	// Retrieve the requested block number (or current if none requested)
    94  	var header *types.Header
    95  	if number == nil || *number == rpc.LatestBlockNumber {
    96  		header = api.chain.CurrentHeader()
    97  	} else {
    98  		header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
    99  	}
   100  	// Ensure we have an actually valid block and return the validators from its snapshot
   101  	if header == nil {
   102  		return nil, errUnknownBlock
   103  	}
   104  	snap, err := api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	return snap.validators(), nil
   109  }
   110  
   111  // GetValidatorsAtHash retrieves the list of authorized validators at the specified block.
   112  func (api *API) GetValidatorsAtHash(hash common.Hash) ([]common.Address, error) {
   113  	header := api.chain.GetHeaderByHash(hash)
   114  	if header == nil {
   115  		return nil, errUnknownBlock
   116  	}
   117  	snap, err := api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	return snap.validators(), nil
   122  }
   123  
   124  func (api *API) GetBaseInfos(number *rpc.BlockNumber) (map[string]interface{}, error) {
   125  	base := systemcontract.NewBase()
   126  	header, statedb, err := api.GetHeaderAndState(number)
   127  	if err != nil {
   128  		return map[string]interface{}{}, err
   129  	}
   130  	infos, err := base.GetBaseInfos(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   131  	if err != nil {
   132  		return map[string]interface{}{}, err
   133  	}
   134  	return infos, nil
   135  }
   136  
   137  // GetValidator return the validator of address
   138  func (api *API) GetValidator(addr common.Address, number *rpc.BlockNumber) (*systemcontract.Validator, error) {
   139  	validators := systemcontract.NewValidators()
   140  	header, statedb, err := api.GetHeaderAndState(number)
   141  	if err != nil {
   142  		return &systemcontract.Validator{}, err
   143  	}
   144  	val, err := validators.GetValidator(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   145  	if err != nil {
   146  		return &systemcontract.Validator{}, err
   147  	}
   148  	return val, nil
   149  }
   150  
   151  // GetTotalDeposit return total deposit
   152  func (api *API) GetTotalDeposit(number *rpc.BlockNumber) (*big.Int, error) {
   153  	validators := systemcontract.NewValidators()
   154  	header, statedb, err := api.GetHeaderAndState(number)
   155  	if err != nil {
   156  		return big.NewInt(0), err
   157  	}
   158  	deposit, err := validators.TotalDeposit(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   159  	if err != nil {
   160  		return big.NewInt(0), err
   161  	}
   162  	return deposit, nil
   163  }
   164  
   165  // GetTotalVotes return total votes
   166  func (api *API) GetTotalVotes(number *rpc.BlockNumber) (*big.Int, error) {
   167  	nodeVotes := systemcontract.NewNodeVotes()
   168  	header, statedb, err := api.GetHeaderAndState(number)
   169  	if err != nil {
   170  		return big.NewInt(0), err
   171  	}
   172  	totalVotes, err := nodeVotes.TotalVotes(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   173  	if err != nil {
   174  		return big.NewInt(0), err
   175  	}
   176  	return totalVotes, nil
   177  }
   178  
   179  // GetCurrentEpochValidators return current epoch validators
   180  func (api *API) GetCurrentEpochValidators(number *rpc.BlockNumber) ([]common.Address, error) {
   181  	validators := systemcontract.NewValidators()
   182  	header, statedb, err := api.GetHeaderAndState(number)
   183  	if err != nil {
   184  		return []common.Address{}, err
   185  	}
   186  	curValidators, err := validators.GetCurrentEpochValidators(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   187  	if err != nil {
   188  		return []common.Address{}, err
   189  	}
   190  	return curValidators, nil
   191  }
   192  
   193  // GetEffictiveValidators return all effictive validators
   194  func (api *API) GetEffictiveValidators(number *rpc.BlockNumber) ([]common.Address, error) {
   195  	validators := systemcontract.NewValidators()
   196  	header, statedb, err := api.GetHeaderAndState(number)
   197  	if err != nil {
   198  		return []common.Address{}, err
   199  	}
   200  
   201  	size := big.NewInt(50)
   202  	var allValidators []common.Address
   203  
   204  	count, err := validators.EffictiveValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   205  	if err != nil {
   206  		return []common.Address{}, err
   207  	}
   208  
   209  	if count.Cmp(size) <= 0 {
   210  		page := big.NewInt(1)
   211  		allValidators, err = validators.GetEffictiveValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size)
   212  		if err != nil {
   213  			return []common.Address{}, err
   214  		}
   215  	} else {
   216  		var res big.Int
   217  		div := res.Div(count, size)
   218  		div = res.Add(div, big.NewInt(1))
   219  		for i := int64(1); i <= div.Int64(); i++ {
   220  			voters, err := validators.GetEffictiveValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size)
   221  			if err != nil {
   222  				return []common.Address{}, err
   223  			}
   224  			allValidators = append(allValidators, voters...)
   225  		}
   226  	}
   227  
   228  	return allValidators, nil
   229  }
   230  
   231  // GetInvalidValidators return all invalid validators
   232  func (api *API) GetInvalidValidators(number *rpc.BlockNumber) ([]common.Address, error) {
   233  	validators := systemcontract.NewValidators()
   234  	header, statedb, err := api.GetHeaderAndState(number)
   235  	if err != nil {
   236  		return []common.Address{}, err
   237  	}
   238  
   239  	size := big.NewInt(50)
   240  	var invalidValidators []common.Address
   241  
   242  	count, err := validators.InvalidValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   243  	if err != nil {
   244  		return []common.Address{}, err
   245  	}
   246  
   247  	if count.Cmp(size) <= 0 {
   248  		page := big.NewInt(1)
   249  		invalidValidators, err = validators.GetInvalidValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size)
   250  		if err != nil {
   251  			return []common.Address{}, err
   252  		}
   253  	} else {
   254  		var res big.Int
   255  		div := res.Div(count, size)
   256  		div = res.Add(div, big.NewInt(1))
   257  		for i := int64(1); i <= div.Int64(); i++ {
   258  			voters, err := validators.GetInvalidValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size)
   259  			if err != nil {
   260  				return []common.Address{}, err
   261  			}
   262  			invalidValidators = append(invalidValidators, voters...)
   263  		}
   264  	}
   265  
   266  	return invalidValidators, nil
   267  }
   268  
   269  // GetCancelQueueValidators return all canceling queue validators
   270  func (api *API) GetCancelQueueValidators(number *rpc.BlockNumber) ([]common.Address, error) {
   271  	validators := systemcontract.NewValidators()
   272  	header, statedb, err := api.GetHeaderAndState(number)
   273  	if err != nil {
   274  		return []common.Address{}, err
   275  	}
   276  	cancelingValidators, err := validators.GetCancelQueueValidators(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   277  	if err != nil {
   278  		return []common.Address{}, err
   279  	}
   280  	return cancelingValidators, nil
   281  }
   282  
   283  // GetValidatorVoters return the address voter
   284  func (api *API) GetValidatorVoters(addr common.Address, number *rpc.BlockNumber) ([]common.Address, error) {
   285  	validators := systemcontract.NewValidators()
   286  	header, statedb, err := api.GetHeaderAndState(number)
   287  	if err != nil {
   288  		return []common.Address{}, err
   289  	}
   290  
   291  	size := big.NewInt(50)
   292  	var allVoters []common.Address
   293  
   294  	count, err := validators.ValidatorVotersLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   295  	if err != nil {
   296  		return []common.Address{}, err
   297  	}
   298  
   299  	if count.Cmp(size) <= 0 {
   300  		page := big.NewInt(1)
   301  		allVoters, err = validators.GetValidatorVoters(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, page, size)
   302  		if err != nil {
   303  			return []common.Address{}, err
   304  		}
   305  	} else {
   306  		var res big.Int
   307  		div := res.Div(count, size)
   308  		div = res.Add(div, big.NewInt(1))
   309  		for i := int64(1); i <= div.Int64(); i++ {
   310  			voters, err := validators.GetValidatorVoters(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, big.NewInt(i), size)
   311  			if err != nil {
   312  				return []common.Address{}, err
   313  			}
   314  			allVoters = append(allVoters, voters...)
   315  		}
   316  	}
   317  
   318  	return allVoters, nil
   319  }
   320  
   321  // EffictiveValsLength return effictive validators length
   322  func (api *API) EffictiveValsLength(number *rpc.BlockNumber) (*big.Int, error) {
   323  	validators := systemcontract.NewValidators()
   324  	header, statedb, err := api.GetHeaderAndState(number)
   325  	if err != nil {
   326  		return big.NewInt(0), err
   327  	}
   328  	count, err := validators.EffictiveValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   329  	if err != nil {
   330  		return big.NewInt(0), err
   331  	}
   332  	return count, nil
   333  }
   334  
   335  // InvalidValsLength return invalid validators length
   336  func (api *API) InvalidValsLength(number *rpc.BlockNumber) (*big.Int, error) {
   337  	validators := systemcontract.NewValidators()
   338  	header, statedb, err := api.GetHeaderAndState(number)
   339  	if err != nil {
   340  		return big.NewInt(0), err
   341  	}
   342  	count, err := validators.InvalidValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   343  	if err != nil {
   344  		return big.NewInt(0), err
   345  	}
   346  	return count, nil
   347  }
   348  
   349  // CancelQueueValidatorsLength return cancel queue validators length
   350  func (api *API) CancelQueueValidatorsLength(number *rpc.BlockNumber) (*big.Int, error) {
   351  	validators := systemcontract.NewValidators()
   352  	header, statedb, err := api.GetHeaderAndState(number)
   353  	if err != nil {
   354  		return big.NewInt(0), err
   355  	}
   356  	count, err := validators.CancelQueueValidatorsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   357  	if err != nil {
   358  		return big.NewInt(0), err
   359  	}
   360  	return count, nil
   361  }
   362  
   363  // ValidatorVotersLength return the validator voters length
   364  func (api *API) ValidatorVotersLength(addr common.Address, number *rpc.BlockNumber) (*big.Int, error) {
   365  	validators := systemcontract.NewValidators()
   366  	header, statedb, err := api.GetHeaderAndState(number)
   367  	if err != nil {
   368  		return big.NewInt(0), err
   369  	}
   370  	count, err := validators.ValidatorVotersLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   371  	if err != nil {
   372  		return big.NewInt(0), err
   373  	}
   374  	return count, nil
   375  }
   376  
   377  // IsEffictiveValidator return the address is validator
   378  func (api *API) IsEffictiveValidator(addr common.Address, number *rpc.BlockNumber) (bool, error) {
   379  	validators := systemcontract.NewValidators()
   380  	header, statedb, err := api.GetHeaderAndState(number)
   381  	if err != nil {
   382  		return false, err
   383  	}
   384  	val, err := validators.IsEffictiveValidator(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   385  	if err != nil {
   386  		return false, err
   387  	}
   388  	return val, nil
   389  }
   390  
   391  // Proposals
   392  
   393  // GetAddressProposalSets return the address proposal id
   394  func (api *API) GetAddressProposalSets(addr common.Address, number *rpc.BlockNumber) ([]string, error) {
   395  	proposals := systemcontract.NewProposals()
   396  	header, statedb, err := api.GetHeaderAndState(number)
   397  	if err != nil {
   398  		return []string{}, err
   399  	}
   400  	count, err := proposals.AddressProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   401  	if err != nil {
   402  		return []string{}, err
   403  	}
   404  
   405  	size := big.NewInt(50)
   406  	var allSets [][4]byte
   407  
   408  	if count.Cmp(size) <= 0 {
   409  		page := big.NewInt(1)
   410  		allSets, err = proposals.AddressProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, page, size)
   411  		if err != nil {
   412  			return []string{}, err
   413  		}
   414  	} else {
   415  		var res big.Int
   416  		div := res.Div(count, size)
   417  		div = res.Add(div, big.NewInt(1))
   418  		for i := int64(1); i <= div.Int64(); i++ {
   419  			proposalIds, err := proposals.AddressProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, big.NewInt(i), size)
   420  			if err != nil {
   421  				return []string{}, err
   422  			}
   423  			allSets = append(allSets, proposalIds...)
   424  		}
   425  	}
   426  
   427  	newProposalIds := []string{}
   428  	for i := 0; i < len(allSets); i++ {
   429  		id := hexutil.Encode(allSets[i][0:len(allSets[i])])
   430  		newProposalIds = append(newProposalIds, id)
   431  	}
   432  	return newProposalIds, nil
   433  }
   434  
   435  // GetAllProposalSets return all proposals id
   436  func (api *API) GetAllProposalSets(number *rpc.BlockNumber) ([]string, error) {
   437  	proposals := systemcontract.NewProposals()
   438  	header, statedb, err := api.GetHeaderAndState(number)
   439  	if err != nil {
   440  		return []string{}, err
   441  	}
   442  
   443  	count, err := proposals.ProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   444  	if err != nil {
   445  		return []string{}, err
   446  	}
   447  
   448  	size := big.NewInt(50)
   449  	var allSets [][4]byte
   450  
   451  	if count.Cmp(size) <= 0 {
   452  		page := big.NewInt(1)
   453  		allSets, err = proposals.AllProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size)
   454  		if err != nil {
   455  			return []string{}, err
   456  		}
   457  	} else {
   458  		var res big.Int
   459  		div := res.Div(count, size)
   460  		div = res.Add(div, big.NewInt(1))
   461  		for i := int64(1); i <= div.Int64(); i++ {
   462  			proposalIds, err := proposals.AllProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size)
   463  			if err != nil {
   464  				return []string{}, err
   465  			}
   466  			allSets = append(allSets, proposalIds...)
   467  		}
   468  	}
   469  
   470  	newProposalIds := []string{}
   471  	for i := 0; i < len(allSets); i++ {
   472  		id := hexutil.Encode(allSets[i][0:len(allSets[i])])
   473  		newProposalIds = append(newProposalIds, id)
   474  	}
   475  	return newProposalIds, nil
   476  
   477  }
   478  
   479  // GetAllProposals return all proposals
   480  func (api *API) GetAllProposals(number *rpc.BlockNumber) ([]ProposalInfo, error) {
   481  	proposals := systemcontract.NewProposals()
   482  	header, statedb, err := api.GetHeaderAndState(number)
   483  	if err != nil {
   484  		return []ProposalInfo{}, err
   485  	}
   486  
   487  	count, err := proposals.ProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   488  	if err != nil {
   489  		return []ProposalInfo{}, err
   490  	}
   491  
   492  	size := big.NewInt(50)
   493  	var allProposals []systemcontract.ProposalInfo
   494  
   495  	if count.Cmp(size) <= 0 {
   496  		page := big.NewInt(1)
   497  		allProposals, err = proposals.AllProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size)
   498  		if err != nil {
   499  			return []ProposalInfo{}, err
   500  		}
   501  	} else {
   502  		var res big.Int
   503  		div := res.Div(count, size)
   504  		div = res.Add(div, big.NewInt(1))
   505  		for i := int64(1); i <= div.Int64(); i++ {
   506  			proposals, err := proposals.AllProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size)
   507  			if err != nil {
   508  				return []ProposalInfo{}, err
   509  			}
   510  			allProposals = append(allProposals, proposals...)
   511  		}
   512  	}
   513  
   514  	newProposals := []ProposalInfo{}
   515  	for i := 0; i < len(allProposals); i++ {
   516  		detail := ProposalInfo{
   517  			Id:          hexutil.Encode(allProposals[i].Id[0:len(allProposals[i].Id)]),
   518  			Proposer:    allProposals[i].Proposer,
   519  			UpdateBlock: allProposals[i].UpdateBlock,
   520  			PType:       allProposals[i].PType,
   521  			Guarantee:   allProposals[i].Guarantee,
   522  			Deposit:     allProposals[i].Deposit,
   523  			Details:     allProposals[i].Details,
   524  			Name:        allProposals[i].Name,
   525  			InitBlock:   allProposals[i].InitBlock,
   526  			Rate:        allProposals[i].Rate,
   527  			Status:      allProposals[i].Status,
   528  		}
   529  		newProposals = append(newProposals, detail)
   530  	}
   531  	return newProposals, nil
   532  
   533  }
   534  
   535  // GetProposal return the proposal of id
   536  func (api *API) GetProposal(id string, number *rpc.BlockNumber) (*ProposalInfo, error) {
   537  	proposals := systemcontract.NewProposals()
   538  	header, statedb, err := api.GetHeaderAndState(number)
   539  	if err != nil {
   540  		return &ProposalInfo{}, err
   541  	}
   542  	proposalInfo, err := proposals.GetProposal(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, id)
   543  	if err != nil {
   544  		return &ProposalInfo{}, err
   545  	}
   546  	detail := &ProposalInfo{
   547  		Id:          hexutil.Encode(proposalInfo.Id[0:len(proposalInfo.Id)]),
   548  		Proposer:    proposalInfo.Proposer,
   549  		UpdateBlock: proposalInfo.UpdateBlock,
   550  		PType:       proposalInfo.PType,
   551  		Guarantee:   proposalInfo.Guarantee,
   552  		Deposit:     proposalInfo.Deposit,
   553  		Details:     proposalInfo.Details,
   554  		Name:        proposalInfo.Name,
   555  		InitBlock:   proposalInfo.InitBlock,
   556  		Rate:        proposalInfo.Rate,
   557  		Status:      proposalInfo.Status,
   558  	}
   559  	return detail, nil
   560  }
   561  
   562  // GetAddressProposals return the address proposals
   563  func (api *API) GetAddressProposals(addr common.Address, number *rpc.BlockNumber) ([]ProposalInfo, error) {
   564  	proposals := systemcontract.NewProposals()
   565  	header, statedb, err := api.GetHeaderAndState(number)
   566  	if err != nil {
   567  		return []ProposalInfo{}, err
   568  	}
   569  
   570  	var allProposals []systemcontract.ProposalInfo
   571  	size := big.NewInt(50)
   572  
   573  	count, err := proposals.AddressProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   574  	if err != nil {
   575  		return []ProposalInfo{}, err
   576  	}
   577  
   578  	if count.Cmp(size) <= 0 {
   579  		page := big.NewInt(1)
   580  		allProposals, err = proposals.AddressProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, page, size)
   581  		if err != nil {
   582  			return []ProposalInfo{}, err
   583  		}
   584  	} else {
   585  		var res big.Int
   586  		div := res.Div(count, size)
   587  		div = res.Add(div, big.NewInt(1))
   588  		for i := int64(1); i <= div.Int64(); i++ {
   589  			proposalIds, err := proposals.AddressProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, big.NewInt(i), size)
   590  			if err != nil {
   591  				return []ProposalInfo{}, err
   592  			}
   593  			allProposals = append(allProposals, proposalIds...)
   594  		}
   595  	}
   596  
   597  	var newProposals []ProposalInfo
   598  	for i := 0; i < len(allProposals); i++ {
   599  		detail := ProposalInfo{
   600  			Id:          hexutil.Encode(allProposals[i].Id[0:len(allProposals[i].Id)]),
   601  			Proposer:    allProposals[i].Proposer,
   602  			UpdateBlock: allProposals[i].UpdateBlock,
   603  			PType:       allProposals[i].PType,
   604  			Guarantee:   allProposals[i].Guarantee,
   605  			Deposit:     allProposals[i].Deposit,
   606  			Details:     allProposals[i].Details,
   607  			Name:        allProposals[i].Name,
   608  			InitBlock:   allProposals[i].InitBlock,
   609  			Rate:        allProposals[i].Rate,
   610  			Status:      allProposals[i].Status,
   611  		}
   612  		newProposals = append(newProposals, detail)
   613  	}
   614  	return newProposals, nil
   615  }
   616  
   617  // GetProposalCount return all proposal count
   618  func (api *API) GetProposalCount(number *rpc.BlockNumber) (*big.Int, error) {
   619  	proposals := systemcontract.NewProposals()
   620  	header, statedb, err := api.GetHeaderAndState(number)
   621  	if err != nil {
   622  		return big.NewInt(0), err
   623  	}
   624  	count, err := proposals.ProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig)
   625  	if err != nil {
   626  		return big.NewInt(0), err
   627  	}
   628  	return count, nil
   629  }
   630  
   631  // GetAddressProposalCount return the address proposal count
   632  func (api *API) GetAddressProposalCount(addr common.Address, number *rpc.BlockNumber) (*big.Int, error) {
   633  	proposals := systemcontract.NewProposals()
   634  	header, statedb, err := api.GetHeaderAndState(number)
   635  	if err != nil {
   636  		return big.NewInt(0), err
   637  	}
   638  	count, err := proposals.AddressProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   639  	if err != nil {
   640  		return big.NewInt(0), err
   641  	}
   642  	return count, nil
   643  }
   644  
   645  // NodeVotes
   646  
   647  // PendingVoteReward return the voter vote the validator rewards
   648  func (api *API) PendingVoteReward(val common.Address, voter common.Address, number *rpc.BlockNumber) (*big.Int, error) {
   649  	nodeVotes := systemcontract.NewNodeVotes()
   650  	header, statedb, err := api.GetHeaderAndState(number)
   651  	if err != nil {
   652  		return big.NewInt(0), err
   653  	}
   654  	value, err := nodeVotes.PendingVoteReward(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, val, voter)
   655  	if err != nil {
   656  		return big.NewInt(0), err
   657  	}
   658  	return value, nil
   659  }
   660  
   661  // PendingVoteRedeem return the voter redeem validators voters
   662  func (api *API) PendingVoteRedeem(val common.Address, voter common.Address, number *rpc.BlockNumber) (*big.Int, error) {
   663  	nodeVotes := systemcontract.NewNodeVotes()
   664  	header, statedb, err := api.GetHeaderAndState(number)
   665  	if err != nil {
   666  		return big.NewInt(0), err
   667  	}
   668  	value, err := nodeVotes.PendingVoteRedeem(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, val, voter)
   669  	if err != nil {
   670  		return big.NewInt(0), err
   671  	}
   672  	return value, nil
   673  }
   674  
   675  // VoteListLength return the voter vote list length
   676  func (api *API) VoteListLength(addr common.Address, number *rpc.BlockNumber) (*big.Int, error) {
   677  	nodeVotes := systemcontract.NewNodeVotes()
   678  	header, statedb, err := api.GetHeaderAndState(number)
   679  	if err != nil {
   680  		return big.NewInt(0), err
   681  	}
   682  	count, err := nodeVotes.VoteListLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   683  	if err != nil {
   684  		return big.NewInt(0), err
   685  	}
   686  	return count, nil
   687  }
   688  
   689  // VotesRewardRedeemInfo votesRewardRedeemInfo
   690  func (api *API) VotesRewardRedeemInfo(val common.Address, voter common.Address, number *rpc.BlockNumber) (*systemcontract.VotesRewardRedeemInfo, error) {
   691  	nodeVotes := systemcontract.NewNodeVotes()
   692  	header, statedb, err := api.GetHeaderAndState(number)
   693  	if err != nil {
   694  		return &systemcontract.VotesRewardRedeemInfo{}, err
   695  	}
   696  
   697  	info, err := nodeVotes.VotesRewardRedeemInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, val, voter)
   698  	if err != nil {
   699  		return &systemcontract.VotesRewardRedeemInfo{}, err
   700  	}
   701  	return info, nil
   702  }
   703  
   704  // VotesRewardRedeemInfos nodevotes.VotesRewardRedeemInfos
   705  func (api *API) VotesRewardRedeemInfos(voter common.Address, number *rpc.BlockNumber) ([]systemcontract.VotesRewardRedeemInfo, error) {
   706  	nodeVotes := systemcontract.NewNodeVotes()
   707  	header, statedb, err := api.GetHeaderAndState(number)
   708  	if err != nil {
   709  		return []systemcontract.VotesRewardRedeemInfo{}, err
   710  	}
   711  
   712  	size := big.NewInt(50)
   713  	var allInfos []systemcontract.VotesRewardRedeemInfo
   714  
   715  	count, err := nodeVotes.VoteListLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, voter)
   716  	if err != nil {
   717  		return []systemcontract.VotesRewardRedeemInfo{}, err
   718  	}
   719  
   720  	if count.Cmp(size) <= 0 {
   721  		page := big.NewInt(1)
   722  		allInfos, err = nodeVotes.VotesRewardRedeemInfoWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, voter, page, size)
   723  		if err != nil {
   724  			return []systemcontract.VotesRewardRedeemInfo{}, err
   725  		}
   726  	} else {
   727  		var res big.Int
   728  		div := res.Div(count, size)
   729  		div = res.Add(div, big.NewInt(1))
   730  		for i := int64(1); i <= div.Int64(); i++ {
   731  			infos, err := nodeVotes.VotesRewardRedeemInfoWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, voter, big.NewInt(i), size)
   732  			if err != nil {
   733  				return []systemcontract.VotesRewardRedeemInfo{}, err
   734  			}
   735  			allInfos = append(allInfos, infos...)
   736  		}
   737  		return allInfos, nil
   738  	}
   739  
   740  	return allInfos, nil
   741  }
   742  
   743  // systemRewards
   744  
   745  type SysRewardsInfo struct {
   746  	Epochs            []*big.Int
   747  	ValidatorRewards  []*big.Int
   748  	DelegatorsRewards []*big.Int
   749  	Rates             []uint
   750  	PendingReward     *big.Int
   751  	FrozenReward      *big.Int
   752  	RewardPerVote     *big.Int
   753  }
   754  
   755  // EpochInfo return the epoch info
   756  func (api *API) EpochInfo(epoch *big.Int, number *rpc.BlockNumber) (*systemcontract.EpochInfo, error) {
   757  	systemRewards := systemcontract.NewSystemRewards()
   758  	header, statedb, err := api.GetHeaderAndState(number)
   759  	if err != nil {
   760  		return &systemcontract.EpochInfo{}, err
   761  	}
   762  	epochInfo, err := systemRewards.GetEpochInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, epoch)
   763  	if err != nil {
   764  		return &systemcontract.EpochInfo{}, err
   765  	}
   766  	return epochInfo, nil
   767  }
   768  
   769  // KickoutInfo return kickout addresses in epoch
   770  func (api *API) KickoutInfo(epoch *big.Int, number *rpc.BlockNumber) ([]common.Address, error) {
   771  	systemRewards := systemcontract.NewSystemRewards()
   772  	header, statedb, err := api.GetHeaderAndState(number)
   773  	if err != nil {
   774  		return []common.Address{}, err
   775  	}
   776  	vals, err := systemRewards.KickoutInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, epoch)
   777  	if err != nil {
   778  		return []common.Address{}, err
   779  	}
   780  	return vals, nil
   781  }
   782  
   783  // ValidatorRewardsInfo return the sys reward info
   784  func (api *API) ValidatorRewardsInfo(addr common.Address, number *rpc.BlockNumber) (*SysRewardsInfo, error) {
   785  	systemRewards := systemcontract.NewSystemRewards()
   786  	header, statedb, err := api.GetHeaderAndState(number)
   787  	if err != nil {
   788  		return &SysRewardsInfo{}, err
   789  	}
   790  	rewardInfo, err := systemRewards.ValidatorRewardsInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   791  	if err != nil {
   792  		return &SysRewardsInfo{}, err
   793  	}
   794  	newInfo := SysRewardsInfo{
   795  		Epochs:            rewardInfo.Epochs,
   796  		ValidatorRewards:  rewardInfo.ValidatorRewards,
   797  		DelegatorsRewards: rewardInfo.DelegatorsRewards,
   798  		PendingReward:     rewardInfo.PendingReward,
   799  		FrozenReward:      rewardInfo.FrozenReward,
   800  		RewardPerVote:     rewardInfo.RewardPerVote,
   801  	}
   802  
   803  	for i := 0; i < len(rewardInfo.Rates); i++ {
   804  		newInfo.Rates = append(newInfo.Rates, uint(rewardInfo.Rates[i]))
   805  	}
   806  
   807  	return &newInfo, nil
   808  }
   809  
   810  // ValidatorRewardInfoByEpoch return the address and the epoch reward info
   811  func (api *API) ValidatorRewardInfoByEpoch(addr common.Address, epoch *big.Int, number *rpc.BlockNumber) (*systemcontract.Reward, error) {
   812  	systemRewards := systemcontract.NewSystemRewards()
   813  	header, statedb, err := api.GetHeaderAndState(number)
   814  	if err != nil {
   815  		return &systemcontract.Reward{}, err
   816  	}
   817  	rewards, err := systemRewards.GetValRewardInfoByEpoch(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, epoch)
   818  	if err != nil {
   819  		return &systemcontract.Reward{}, err
   820  	}
   821  	return rewards, nil
   822  }
   823  
   824  // PendingValidatorReward return the address reward
   825  func (api *API) PendingValidatorReward(addr common.Address, number *rpc.BlockNumber) (map[string]*big.Int, error) {
   826  	systemRewards := systemcontract.NewSystemRewards()
   827  	header, statedb, err := api.GetHeaderAndState(number)
   828  	if err != nil {
   829  		return map[string]*big.Int{}, err
   830  	}
   831  	avaliable, frozen, err := systemRewards.PendingValidatorReward(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr)
   832  	if err != nil {
   833  		return map[string]*big.Int{}, err
   834  	}
   835  	result := make(map[string]*big.Int)
   836  	result["avaliable"] = avaliable
   837  	result["frozen"] = frozen
   838  	return result, nil
   839  }
   840  
   841  // PunishInfo punishInfo function of systemRewards contract
   842  func (api *API) PunishInfo(addr common.Address, epoch *big.Int, number *rpc.BlockNumber) (*systemcontract.Punish, error) {
   843  	systemRewards := systemcontract.NewSystemRewards()
   844  	header, statedb, err := api.GetHeaderAndState(number)
   845  	if err != nil {
   846  		return &systemcontract.Punish{}, err
   847  	}
   848  	punish, err := systemRewards.PunishInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, epoch)
   849  	if err != nil {
   850  		return &systemcontract.Punish{}, err
   851  	}
   852  
   853  	return punish, nil
   854  }
   855  
   856  type status struct {
   857  	InturnPercent float64                `json:"inturnPercent"`
   858  	SigningStatus map[common.Address]int `json:"sealerActivity"`
   859  	NumBlocks     uint64                 `json:"numBlocks"`
   860  }
   861  
   862  // Status returns the status of the last N blocks,
   863  // - the number of active validators,
   864  // - the number of validators,
   865  // - the percentage of in-turn blocks
   866  func (api *API) Status() (*status, error) {
   867  	var (
   868  		numBlocks = uint64(64)
   869  		header    = api.chain.CurrentHeader()
   870  		diff      = uint64(0)
   871  		optimals  = 0
   872  	)
   873  	snap, err := api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
   874  	if err != nil {
   875  		return nil, err
   876  	}
   877  	var (
   878  		validators = snap.validators()
   879  		end        = header.Number.Uint64()
   880  		start      = end - numBlocks
   881  	)
   882  	if numBlocks > end {
   883  		start = 1
   884  		numBlocks = end - start
   885  	}
   886  	signStatus := make(map[common.Address]int)
   887  	for _, s := range validators {
   888  		signStatus[s] = 0
   889  	}
   890  	for n := start; n < end; n++ {
   891  		h := api.chain.GetHeaderByNumber(n)
   892  		if h == nil {
   893  			return nil, fmt.Errorf("missing block %d", n)
   894  		}
   895  		if h.Difficulty.Cmp(diffInTurn) == 0 {
   896  			optimals++
   897  		}
   898  		diff += h.Difficulty.Uint64()
   899  		sealer, err := api.dpos.Author(h)
   900  		if err != nil {
   901  			return nil, err
   902  		}
   903  		signStatus[sealer]++
   904  	}
   905  	return &status{
   906  		InturnPercent: float64(100*optimals) / float64(numBlocks),
   907  		SigningStatus: signStatus,
   908  		NumBlocks:     numBlocks,
   909  	}, nil
   910  }