mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 02:10:46 +00:00
Implement api eth.getCandidateStatus
This commit is contained in:
parent
56e1251a94
commit
a479343cc7
4 changed files with 323 additions and 53 deletions
|
|
@ -44,10 +44,17 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
"github.com/syndtr/goleveldb/leveldb/util"
|
"github.com/syndtr/goleveldb/leveldb/util"
|
||||||
|
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
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.
|
// 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.
|
// BlockNumber returns the block number of the chain head.
|
||||||
func (s *PublicBlockChainAPI) GetRewardByHash(hash common.Hash) map[string]interface{} {
|
func (s *PublicBlockChainAPI) GetRewardByHash(hash common.Hash) map[string]interface{} {
|
||||||
if c, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok {
|
return s.b.GetRewardByHash(hash)
|
||||||
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
|
||||||
|
|
@ -614,6 +615,175 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
|
||||||
return res[:], state.Error()
|
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.
|
// CallArgs represents the arguments for a call.
|
||||||
type CallArgs struct {
|
type CallArgs struct {
|
||||||
From common.Address `json:"from"`
|
From common.Address `json:"from"`
|
||||||
|
|
@ -860,46 +1030,55 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
|
||||||
uncleHashes[i] = uncle.Hash()
|
uncleHashes[i] = uncle.Hash()
|
||||||
}
|
}
|
||||||
fields["uncles"] = uncleHashes
|
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.
|
// Get signers for block.
|
||||||
client, err := s.b.GetIPCClient()
|
client, err := s.b.GetIPCClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Fail to connect IPC client for block status", "error", err)
|
log.Error("Fail to connect IPC client for block status", "error", err)
|
||||||
|
return []common.Address{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var signers []common.Address
|
var signers []common.Address
|
||||||
var filterSigners []common.Address
|
var filterSigners []common.Address
|
||||||
finality := int32(0)
|
|
||||||
if b.Number().Int64() > 0 {
|
if b.Number().Int64() > 0 {
|
||||||
addrBlockSigner := common.HexToAddress(common.BlockSigners)
|
curBlockNumber := b.Number().Uint64()
|
||||||
signers, err = contracts.GetSignersFromContract(addrBlockSigner, client, b.Hash())
|
prevBlockNumber := curBlockNumber + (common.MergeSignRange - (curBlockNumber % common.MergeSignRange))
|
||||||
if err != nil {
|
latestBlockNumber := s.b.CurrentBlock().Number().Uint64()
|
||||||
log.Error("Fail to get signers from block signer SC.", "error", err)
|
if prevBlockNumber >= latestBlockNumber || !s.b.ChainConfig().IsTIP2019(b.Number()) {
|
||||||
|
prevBlockNumber = curBlockNumber
|
||||||
}
|
}
|
||||||
// Get block epoc latest.
|
if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok {
|
||||||
if s.b.ChainConfig().XDPoS != nil {
|
prevBlock, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(prevBlockNumber))
|
||||||
engine := s.b.GetEngine()
|
if err != nil {
|
||||||
lastCheckpointNumber := rpc.BlockNumber(b.Number().Uint64() - (b.Number().Uint64() % s.b.ChainConfig().XDPoS.Epoch))
|
log.Error("Fail to get previous block", "error", err)
|
||||||
prevCheckpointBlock, _ := s.b.BlockByNumber(ctx, lastCheckpointNumber)
|
return []common.Address{}, err
|
||||||
if prevCheckpointBlock != nil {
|
}
|
||||||
masternodes := engine.(*XDPoS.XDPoS).GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), b.Number().Uint64(), s.b.ChainConfig().XDPoS.Epoch)
|
addrBlockSigner := common.HexToAddress(common.BlockSigners)
|
||||||
countFinality := 0
|
signers, err = contracts.GetSignersByExecutingEVM(addrBlockSigner, client, prevBlock.Hash())
|
||||||
for _, masternode := range masternodes {
|
if err != nil {
|
||||||
for _, signer := range signers {
|
log.Error("Fail to get signers from block signer SC.", "error", err)
|
||||||
if signer == masternode {
|
return []common.Address{}, err
|
||||||
countFinality++
|
}
|
||||||
filterSigners = append(filterSigners, masternode)
|
validator, _ := engine.RecoverValidator(b.Header())
|
||||||
break
|
creator, _ := engine.RecoverSigner(b.Header())
|
||||||
}
|
signers = append(signers, validator)
|
||||||
|
signers = append(signers, creator)
|
||||||
|
for _, masternode := range masternodes {
|
||||||
|
for _, signer := range signers {
|
||||||
|
if signer == masternode {
|
||||||
|
filterSigners = append(filterSigners, masternode)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finality = int32(countFinality * 100 / len(masternodes))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Error("Undefined XDPoS consensus engine")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fields["signers"] = filterSigners
|
return filterSigners, nil
|
||||||
fields["finality"] = finality
|
|
||||||
|
|
||||||
return fields, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
||||||
|
|
@ -1532,4 +1711,4 @@ func (s *PublicNetAPI) PeerCount() hexutil.Uint {
|
||||||
// Version returns the current ethereum protocol version.
|
// Version returns the current ethereum protocol version.
|
||||||
func (s *PublicNetAPI) Version() string {
|
func (s *PublicNetAPI) Version() string {
|
||||||
return fmt.Sprintf("%d", s.networkVersion)
|
return fmt.Sprintf("%d", s.networkVersion)
|
||||||
}
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -3715,6 +3715,13 @@ var inputBlockNumberFormatter = function (blockNumber) {
|
||||||
return utils.toHex(blockNumber);
|
return utils.toHex(blockNumber);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var inputEpochNumberFormatter = function (epochNumber) {
|
||||||
|
if (epochNumber === undefined || epochNumber === "latest") {
|
||||||
|
return "latest";
|
||||||
|
}
|
||||||
|
return utils.toHex(epochNumber);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats the input of a transaction and converts all values to HEX
|
* Formats the input of a transaction and converts all values to HEX
|
||||||
*
|
*
|
||||||
|
|
@ -3840,6 +3847,22 @@ var outputBlockFormatter = function(block) {
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Formats the output of a blockSigner list
|
||||||
|
*
|
||||||
|
* @method outputBlockFormatter
|
||||||
|
* @param {Object} blockSigners
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
var outputBlockSignersFormatter = function(blockSigners) {
|
||||||
|
if (utils.isArray(blockSigners)) {
|
||||||
|
blockSigners.forEach(function(item){
|
||||||
|
if(!utils.isString(item))
|
||||||
|
return formatOutputAddress(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return blockSigners;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats the output of a log
|
* Formats the output of a log
|
||||||
|
|
@ -3950,6 +3973,7 @@ var outputSyncingFormatter = function(result) {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,
|
inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,
|
||||||
inputBlockNumberFormatter: inputBlockNumberFormatter,
|
inputBlockNumberFormatter: inputBlockNumberFormatter,
|
||||||
|
inputEpochNumberFormatter: inputEpochNumberFormatter,
|
||||||
inputCallFormatter: inputCallFormatter,
|
inputCallFormatter: inputCallFormatter,
|
||||||
inputTransactionFormatter: inputTransactionFormatter,
|
inputTransactionFormatter: inputTransactionFormatter,
|
||||||
inputAddressFormatter: inputAddressFormatter,
|
inputAddressFormatter: inputAddressFormatter,
|
||||||
|
|
@ -3958,6 +3982,7 @@ module.exports = {
|
||||||
outputTransactionFormatter: outputTransactionFormatter,
|
outputTransactionFormatter: outputTransactionFormatter,
|
||||||
outputTransactionReceiptFormatter: outputTransactionReceiptFormatter,
|
outputTransactionReceiptFormatter: outputTransactionReceiptFormatter,
|
||||||
outputBlockFormatter: outputBlockFormatter,
|
outputBlockFormatter: outputBlockFormatter,
|
||||||
|
outputBlockSignersFormatter: outputBlockSignersFormatter,
|
||||||
outputLogFormatter: outputLogFormatter,
|
outputLogFormatter: outputLogFormatter,
|
||||||
outputPostFormatter: outputPostFormatter,
|
outputPostFormatter: outputPostFormatter,
|
||||||
outputSyncingFormatter: outputSyncingFormatter
|
outputSyncingFormatter: outputSyncingFormatter
|
||||||
|
|
@ -5210,6 +5235,14 @@ var blockCall = function (args) {
|
||||||
return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? "eth_getBlockByHash" : "eth_getBlockByNumber";
|
return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? "eth_getBlockByHash" : "eth_getBlockByNumber";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var blockSignersCall = function (args) {
|
||||||
|
return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? "eth_getBlockSignersByHash" : "eth_getBlockSignersByNumber";
|
||||||
|
};
|
||||||
|
|
||||||
|
var blockFinalityCall = function (args) {
|
||||||
|
return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? "eth_getBlockFinalityByHash" : "eth_getBlockFinalityByNumber";
|
||||||
|
};
|
||||||
|
|
||||||
var transactionFromBlockCall = function (args) {
|
var transactionFromBlockCall = function (args) {
|
||||||
return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';
|
return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';
|
||||||
};
|
};
|
||||||
|
|
@ -5297,6 +5330,22 @@ var methods = function () {
|
||||||
outputFormatter: formatters.outputBlockFormatter
|
outputFormatter: formatters.outputBlockFormatter
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var getBlockSigners = new Method({
|
||||||
|
name: 'getBlockSigners',
|
||||||
|
call: blockSignersCall,
|
||||||
|
params: 1,
|
||||||
|
inputFormatter: [formatters.inputBlockNumberFormatter],
|
||||||
|
outputFormatter: formatters.outputBlockSignersFormatter
|
||||||
|
});
|
||||||
|
|
||||||
|
var getBlockFinality = new Method({
|
||||||
|
name: 'getBlockFinality',
|
||||||
|
call: blockFinalityCall,
|
||||||
|
params: 1,
|
||||||
|
inputFormatter: [formatters.inputBlockNumberFormatter],
|
||||||
|
outputFormatter: formatters.formatOutputInt
|
||||||
|
});
|
||||||
|
|
||||||
var getUncle = new Method({
|
var getUncle = new Method({
|
||||||
name: 'getUncle',
|
name: 'getUncle',
|
||||||
call: uncleCall,
|
call: uncleCall,
|
||||||
|
|
@ -5431,11 +5480,20 @@ var methods = function () {
|
||||||
params: 0
|
params: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var getCandidateStatus = new Method({
|
||||||
|
name: 'getCandidateStatus',
|
||||||
|
call: 'eth_getCandidateStatus',
|
||||||
|
params: 2,
|
||||||
|
inputFormatter: [formatters.inputAddressFormatter, formatters.inputEpochNumberFormatter]
|
||||||
|
});
|
||||||
return [
|
return [
|
||||||
getBalance,
|
getBalance,
|
||||||
getStorageAt,
|
getStorageAt,
|
||||||
getCode,
|
getCode,
|
||||||
getBlock,
|
getBlock,
|
||||||
|
getBlockSigners,
|
||||||
|
getBlockFinality,
|
||||||
|
getCandidateStatus,
|
||||||
getUncle,
|
getUncle,
|
||||||
getCompilers,
|
getCompilers,
|
||||||
getBlockTransactionCount,
|
getBlockTransactionCount,
|
||||||
|
|
|
||||||
39
rpc/types.go
39
rpc/types.go
|
|
@ -117,11 +117,13 @@ type ServerCodec interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockNumber int64
|
type BlockNumber int64
|
||||||
|
type EpochNumber int64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PendingBlockNumber = BlockNumber(-2)
|
PendingBlockNumber = BlockNumber(-2)
|
||||||
LatestBlockNumber = BlockNumber(-1)
|
LatestBlockNumber = BlockNumber(-1)
|
||||||
EarliestBlockNumber = BlockNumber(0)
|
EarliestBlockNumber = BlockNumber(0)
|
||||||
|
LatestEpochNumber = EpochNumber(-1)
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
|
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
|
||||||
|
|
@ -131,11 +133,7 @@ const (
|
||||||
// - an invalid block number error when the given argument isn't a known strings
|
// - an invalid block number error when the given argument isn't a known strings
|
||||||
// - an out of range error when the given block number is either too little or too large
|
// - an out of range error when the given block number is either too little or too large
|
||||||
func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
||||||
input := strings.TrimSpace(string(data))
|
input := trimData(data)
|
||||||
if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
|
|
||||||
input = input[1 : len(input)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
switch input {
|
switch input {
|
||||||
case "earliest":
|
case "earliest":
|
||||||
*bn = EarliestBlockNumber
|
*bn = EarliestBlockNumber
|
||||||
|
|
@ -163,3 +161,34 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
||||||
func (bn BlockNumber) Int64() int64 {
|
func (bn BlockNumber) Int64() int64 {
|
||||||
return (int64)(bn)
|
return (int64)(bn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *EpochNumber) UnmarshalJSON(data []byte) error {
|
||||||
|
input := trimData(data)
|
||||||
|
if input == "latest" {
|
||||||
|
*e = LatestEpochNumber
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
eNum, err := hexutil.DecodeUint64(input)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if eNum > math.MaxInt64 {
|
||||||
|
return fmt.Errorf("EpochNumber too high")
|
||||||
|
}
|
||||||
|
|
||||||
|
*e = EpochNumber(eNum)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EpochNumber) Int64() int64 {
|
||||||
|
return (int64)(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimData(data []byte) string {
|
||||||
|
input := strings.TrimSpace(string(data))
|
||||||
|
if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
|
||||||
|
input = input[1 : len(input)-1]
|
||||||
|
}
|
||||||
|
return input
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue