package apiv1
import (
"context"
"fmt"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/consensus/reward"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
internal_common "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
[rpc][availability][apr] Richer validator information, implement APR, unify EPoS computation, remove fall 2019 tech debt (#2484)
* [rpc][validator] Extend hmy blockchain validator information
* [availability] Optimize bump count
* [staking][validator][rpc] Remove validator stats rpc, fold into validator information, make existing pattern default behavior
* [slash] Reimplement SetDifference
* [reward][engine][network] Remove bad API from fall, begin setup for Per validator awards
* [header] Custom Marshal header for downstream, remove dev code
* [effective][committee] Factor out EPoS round of computation thereby unification in codebase of EPoS
* [unit-test] Fix semantically wrong validator unit tests, punt on maxBLS key wrt tx-pool test
* [reward] Use excellent singleflight package for caching lookup of subcommittees
* [apr][reward] Begin APR package itself, iterate on iterface signatures
* [reward] Handle possible error from singleflight
* [rpc][validator][reward] Adjust RPC committees, singleflight on votingPower, foldStats into Validator Information
* [apr] Stub out computation of APR
* [effective][committee] Upgrade SlotPurchase with named fields, provide marshal
* [effective] Update Tests
* [blockchain] TODO Remove the validators no longer in committee
* [validator][effective] More expressive string representation of eligibilty, ValidatorRPC explicit say if in committee now
* [rpc] Median-stake more semantic meaningful
* [validator] Iterate on semantic meaning of JSON representation
* [offchain] Make validator stats return explicit error
* [availability] Small typo
* [rpc] Quick visual hack until fix delete out kicked out validators
* [offchain] Delete validator from offchain that lost their slot
* [apr] Forgot to update interface signature
* [apr] Mul instead of Div
* [protocol][validator] Fold block reward accum per vaidator into validator-wrapper, off-chain => on-chain
* [votepower] Refactor votepower Roster, simplify aggregation of network wide rosters
* [votepower][shard] Adjust roster, optimize usage of BLSPublicKey as key, use MarshalText trick
* [shard] Granular errors
* [votepower][validator] Unify votepower data structure with off-chain usage
* [votepower][consensus][validator] Further simplify and unify votepower with off-chain, validator stats
* [votepower] Use RJs naming convention group,overall
* [votepower] Remove Println, do keep enforcing order
* [effective][reward] Expand semantics of eligibility as it was overloaded and confusing, evict old voting power computations
* [apr] Adjust json field name
* [votepower] Only aggregate on external validator
* [votepower] Mistake on aggregation, custom presentation network-wide
* [rpc][validator][availability] Remove parameter, take into account empty snapshot
* [apr] Use snapshots from two, one epochs ago. Still have question on header
* [apr] Use GetHeaderByNumber for the header needed for time stamp
* [chain] Evict > 3 epoch old voting power
* [blockchain] Leave Delete Validator snapshot as TODO
* [validator][rpc][effective] Undo changes to Protocol field, use virtual construct at RPC layer for meaning
* [project] Address PR comments
* [committee][rpc] Move +1 to computation of epos round rather than hack mutation
* [reward] Remove entire unnecessary loop, hook on AddReward. Remove unnecessary new big int
* [votepower][rpc][validator] Stick with numeric.Dec for token involved with computation, expose accumulate block-reward in RPC
* [effective][committee] Track the candidates for the EPoS auction, RPC median-stake benefits
* [node] Add hack way to get real error reason of why cannot load shardchain
* [consensus] Expand log on current issue on nil block
* [apr] Do the actual call to compute for validator's APR
* [committee] Wrap SlotOrder with validator address, manifests in median-stake RPC
* [apr] Incorrect error handle order
* [quorum] Remove incorrect compare on bls Key, (typo), remove redundant error check
* [shard] Add log if stakedSlots is 0
* [apr] More sanity check on div by zero, more lenient on error when dont have historical data yet
* [committee] Remove + 1 on seat count
* [apr] Use int64() directly
* [apr] Log when odd empty nil header
* [apr] Do not crash on empty header, figure out later
5 years ago
"github.com/harmony-one/harmony/shard/committee"
"github.com/harmony-one/harmony/staking/network"
staking "github.com/harmony-one/harmony/staking/types"
"github.com/pkg/errors"
)
const (
defaultGasPrice = denominations . Nano
defaultFromAddress = "0x0000000000000000000000000000000000000000"
defaultBlocksPeriod = 15000
validatorsPageSize = 100
initSupply = int64 ( 12600000000 )
)
// PublicBlockChainAPI provides an API to access the Harmony blockchain.
// It offers only methods that operate on public data that is freely available to anyone.
type PublicBlockChainAPI struct {
b Backend
}
// NewPublicBlockChainAPI creates a new Harmony blockchain API.
func NewPublicBlockChainAPI ( b Backend ) * PublicBlockChainAPI {
return & PublicBlockChainAPI { b }
}
// BlockArgs is struct to include optional block formatting params.
type BlockArgs struct {
WithSigners bool ` json:"withSigners" `
InclTx bool ` json:"inclTx" `
FullTx bool ` json:"fullTx" `
Signers [ ] string ` json:"signers" `
InclStaking bool ` json:"inclStaking" `
}
func ( s * PublicBlockChainAPI ) isBeaconShard ( ) error {
if s . b . GetShardID ( ) != shard . BeaconChainShardID {
return ErrNotBeaconShard
}
return nil
}
func ( s * PublicBlockChainAPI ) isBlockGreaterThanLatest ( blockNum rpc . BlockNumber ) error {
// rpc.BlockNumber is int64 (latest = -1. pending = -2) and currentBlockNum is uint64.
// Most straightfoward to make sure to return nil error for latest and pending block num
// since they are never greater than latest
if blockNum != rpc . PendingBlockNumber &&
blockNum != rpc . LatestBlockNumber &&
uint64 ( blockNum ) > s . b . CurrentBlock ( ) . NumberU64 ( ) {
return ErrRequestedBlockTooHigh
}
return nil
}
// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func ( s * PublicBlockChainAPI ) GetBlockByNumber ( ctx context . Context , blockNr rpc . BlockNumber , fullTx bool ) ( map [ string ] interface { } , error ) {
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return nil , err
}
block , err := s . b . BlockByNumber ( ctx , blockNr )
if block != nil {
blockArgs := BlockArgs { WithSigners : false , InclTx : true , FullTx : fullTx , InclStaking : true }
response , err := RPCMarshalBlock ( block , blockArgs )
if err == nil && blockNr == rpc . PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _ , field := range [ ] string { "hash" , "nonce" , "miner" } {
response [ field ] = nil
}
}
return response , err
}
return nil , err
}
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
// detail, otherwise only the transaction hash is returned.
func ( s * PublicBlockChainAPI ) GetBlockByHash ( ctx context . Context , blockHash common . Hash , fullTx bool ) ( map [ string ] interface { } , error ) {
block , err := s . b . GetBlock ( ctx , blockHash )
if block != nil {
blockArgs := BlockArgs { WithSigners : false , InclTx : true , FullTx : fullTx , InclStaking : true }
return RPCMarshalBlock ( block , blockArgs )
}
return nil , err
}
// GetBlockByNumberNew returns the requested block. When blockNr is -1 the chain head is returned. When fullTx in blockArgs is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned. When withSigners in BlocksArgs is true
// it shows block signers for this block in list of one addresses.
func ( s * PublicBlockChainAPI ) GetBlockByNumberNew ( ctx context . Context , blockNr rpc . BlockNumber , blockArgs BlockArgs ) ( map [ string ] interface { } , error ) {
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return nil , err
}
block , err := s . b . BlockByNumber ( ctx , blockNr )
blockArgs . InclTx = true
if blockArgs . WithSigners {
blockArgs . Signers , err = s . GetBlockSigners ( ctx , blockNr )
if err != nil {
return nil , err
}
}
if block != nil {
response , err := RPCMarshalBlock ( block , blockArgs )
if err == nil && blockNr == rpc . PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _ , field := range [ ] string { "hash" , "nonce" , "miner" } {
response [ field ] = nil
}
}
return response , err
}
return nil , err
}
// GetBlockByHashNew returns the requested block. When fullTx in blockArgs is true all transactions in the block are returned in full
// detail, otherwise only the transaction hash is returned. When withSigners in BlocksArgs is true
// it shows block signers for this block in list of one addresses.
func ( s * PublicBlockChainAPI ) GetBlockByHashNew ( ctx context . Context , blockHash common . Hash , blockArgs BlockArgs ) ( map [ string ] interface { } , error ) {
block , err := s . b . GetBlock ( ctx , blockHash )
blockArgs . InclTx = true
if blockArgs . WithSigners {
blockArgs . Signers , err = s . GetBlockSigners ( ctx , rpc . BlockNumber ( block . NumberU64 ( ) ) )
if err != nil {
return nil , err
}
}
if block != nil {
return RPCMarshalBlock ( block , blockArgs )
}
return nil , err
}
// GetBlocks method returns blocks in range blockStart, blockEnd just like GetBlockByNumber but all at once.
func ( s * PublicBlockChainAPI ) GetBlocks ( ctx context . Context , blockStart rpc . BlockNumber , blockEnd rpc . BlockNumber , blockArgs BlockArgs ) ( [ ] map [ string ] interface { } , error ) {
result := make ( [ ] map [ string ] interface { } , 0 )
for i := blockStart ; i <= blockEnd ; i ++ {
block , err := s . b . BlockByNumber ( ctx , i )
blockArgs . InclTx = true
if blockArgs . WithSigners {
blockArgs . Signers , err = s . GetBlockSigners ( ctx , rpc . BlockNumber ( i ) )
if err != nil {
return nil , err
}
}
if block != nil {
rpcBlock , err := RPCMarshalBlock ( block , blockArgs )
if err == nil && i == rpc . PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _ , field := range [ ] string { "hash" , "nonce" , "miner" } {
rpcBlock [ field ] = nil
}
}
result = append ( result , rpcBlock )
}
}
return result , nil
}
// GetValidators returns validators list for a particular epoch.
func ( s * PublicBlockChainAPI ) GetValidators ( ctx context . Context , epoch int64 ) ( map [ string ] interface { } , error ) {
committee , err := s . b . GetValidators ( big . NewInt ( epoch ) )
if err != nil {
return nil , err
}
balanceQueryBlock := shard . Schedule . EpochLastBlock ( uint64 ( epoch ) )
if balanceQueryBlock > s . b . CurrentBlock ( ) . NumberU64 ( ) {
balanceQueryBlock = s . b . CurrentBlock ( ) . NumberU64 ( )
}
validators := make ( [ ] map [ string ] interface { } , 0 )
for _ , validator := range committee . Slots {
oneAddress , err := internal_common . AddressToBech32 ( validator . EcdsaAddress )
if err != nil {
return nil , err
}
validatorBalance , err := s . getBalanceByBlockNumber ( ctx , oneAddress , rpc . BlockNumber ( balanceQueryBlock ) )
if err != nil {
return nil , err
}
validatorsFields := map [ string ] interface { } {
"address" : oneAddress ,
"balance" : ( * hexutil . Big ) ( validatorBalance ) ,
}
validators = append ( validators , validatorsFields )
}
result := map [ string ] interface { } {
"shardID" : committee . ShardID ,
"validators" : validators ,
}
return result , nil
}
// GetValidatorKeys returns list of bls public keys in the committee for a particular epoch.
func ( s * PublicBlockChainAPI ) GetValidatorKeys ( ctx context . Context , epoch int64 ) ( [ ] string , error ) {
committee , err := s . b . GetValidators ( big . NewInt ( epoch ) )
if err != nil {
return nil , err
}
validators := make ( [ ] string , len ( committee . Slots ) )
for i , v := range committee . Slots {
validators [ i ] = v . BLSPublicKey . Hex ( )
}
return validators , nil
}
// IsLastBlock checks if block is last epoch block.
func ( s * PublicBlockChainAPI ) IsLastBlock ( blockNum uint64 ) ( bool , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return false , err
}
return shard . Schedule . IsLastBlock ( blockNum ) , nil
}
// EpochLastBlock returns epoch last block.
func ( s * PublicBlockChainAPI ) EpochLastBlock ( epoch uint64 ) ( uint64 , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return 0 , err
}
return shard . Schedule . EpochLastBlock ( epoch ) , nil
}
// GetBlockSigners returns signers for a particular block.
func ( s * PublicBlockChainAPI ) GetBlockSigners ( ctx context . Context , blockNr rpc . BlockNumber ) ( [ ] string , error ) {
if uint64 ( blockNr ) == 0 {
return [ ] string { } , nil
}
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return nil , err
}
slots , mask , err := s . b . GetBlockSigners ( ctx , blockNr )
if err != nil {
return nil , err
}
signers := [ ] string { }
for _ , validator := range slots {
oneAddress , err := internal_common . AddressToBech32 ( validator . EcdsaAddress )
if err != nil {
return nil , err
}
blsPublicKey := new ( bls . PublicKey )
validator . BLSPublicKey . ToLibBLSPublicKey ( blsPublicKey )
if ok , err := mask . KeyEnabled ( blsPublicKey ) ; err == nil && ok {
signers = append ( signers , oneAddress )
}
}
return signers , nil
}
// GetBlockSignerKeys returns bls public keys that signed the block.
func ( s * PublicBlockChainAPI ) GetBlockSignerKeys ( ctx context . Context , blockNr rpc . BlockNumber ) ( [ ] string , error ) {
if uint64 ( blockNr ) == 0 {
return [ ] string { } , nil
}
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return nil , err
}
slots , mask , err := s . b . GetBlockSigners ( ctx , blockNr )
if err != nil {
return nil , err
}
signers := [ ] string { }
for _ , validator := range slots {
blsPublicKey := new ( bls . PublicKey )
validator . BLSPublicKey . ToLibBLSPublicKey ( blsPublicKey )
if ok , err := mask . KeyEnabled ( blsPublicKey ) ; err == nil && ok {
signers = append ( signers , validator . BLSPublicKey . Hex ( ) )
}
}
return signers , nil
}
// IsBlockSigner returns true if validator with address signed blockNr block.
func ( s * PublicBlockChainAPI ) IsBlockSigner ( ctx context . Context , blockNr rpc . BlockNumber , address string ) ( bool , error ) {
if uint64 ( blockNr ) == 0 {
return false , nil
}
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return false , err
}
slots , mask , err := s . b . GetBlockSigners ( ctx , blockNr )
if err != nil {
return false , err
}
for _ , validator := range slots {
oneAddress , err := internal_common . AddressToBech32 ( validator . EcdsaAddress )
if err != nil {
return false , err
}
if oneAddress != address {
continue
}
blsPublicKey := new ( bls . PublicKey )
validator . BLSPublicKey . ToLibBLSPublicKey ( blsPublicKey )
if ok , err := mask . KeyEnabled ( blsPublicKey ) ; err == nil && ok {
return true , nil
}
}
return false , nil
}
// GetSignedBlocks returns how many blocks a particular validator signed for last defaultBlocksPeriod (3 hours ~ 1500 blocks).
func ( s * PublicBlockChainAPI ) GetSignedBlocks ( ctx context . Context , address string ) hexutil . Uint64 {
totalSigned := uint64 ( 0 )
lastBlock := uint64 ( 0 )
blockHeight := uint64 ( s . BlockNumber ( ) )
if blockHeight >= defaultBlocksPeriod {
lastBlock = blockHeight - defaultBlocksPeriod + 1
}
for i := lastBlock ; i <= blockHeight ; i ++ {
signed , err := s . IsBlockSigner ( ctx , rpc . BlockNumber ( i ) , address )
if err == nil && signed {
totalSigned ++
}
}
return hexutil . Uint64 ( totalSigned )
}
// GetEpoch returns current epoch.
func ( s * PublicBlockChainAPI ) GetEpoch ( ctx context . Context ) hexutil . Uint64 {
return hexutil . Uint64 ( s . LatestHeader ( ctx ) . Epoch )
}
// GetLeader returns current shard leader.
func ( s * PublicBlockChainAPI ) GetLeader ( ctx context . Context ) string {
return s . LatestHeader ( ctx ) . Leader
}
// GetValidatorSelfDelegation returns validator stake.
func ( s * PublicBlockChainAPI ) GetValidatorSelfDelegation ( ctx context . Context , address string ) ( hexutil . Uint64 , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return hexutil . Uint64 ( 0 ) , err
}
return hexutil . Uint64 ( s . b . GetValidatorSelfDelegation ( internal_common . ParseAddr ( address ) ) . Uint64 ( ) ) , nil
}
// GetValidatorTotalDelegation returns total balace stacking for validator with delegation.
func ( s * PublicBlockChainAPI ) GetValidatorTotalDelegation ( ctx context . Context , address string ) ( hexutil . Uint64 , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return hexutil . Uint64 ( 0 ) , err
}
delegations := s . b . GetDelegationsByValidator ( internal_common . ParseAddr ( address ) )
totalStake := big . NewInt ( 0 )
for _ , delegation := range delegations {
totalStake . Add ( totalStake , delegation . Amount )
}
// TODO: return more than uint64
return hexutil . Uint64 ( totalStake . Uint64 ( ) ) , nil
}
// GetShardingStructure returns an array of sharding structures.
func ( s * PublicBlockChainAPI ) GetShardingStructure ( ctx context . Context ) ( [ ] map [ string ] interface { } , error ) {
// Get header and number of shards.
epoch := s . GetEpoch ( ctx )
numShard := shard . Schedule . InstanceForEpoch ( big . NewInt ( int64 ( epoch ) ) ) . NumShards ( )
// Return shareding structure for each case.
return shard . Schedule . GetShardingStructure ( int ( numShard ) , int ( s . b . GetShardID ( ) ) ) , nil
}
// GetShardID returns shard ID of the requested node.
func ( s * PublicBlockChainAPI ) GetShardID ( ctx context . Context ) ( int , error ) {
return int ( s . b . GetShardID ( ) ) , nil
}
// GetCode returns the code stored at the given address in the state for the given block number.
func ( s * PublicBlockChainAPI ) GetCode ( ctx context . Context , addr string , blockNr rpc . BlockNumber ) ( hexutil . Bytes , error ) {
address := internal_common . ParseAddr ( addr )
state , _ , err := s . b . StateAndHeaderByNumber ( ctx , blockNr )
if state == nil || err != nil {
return nil , err
}
code := state . GetCode ( address )
return code , state . Error ( )
}
// GetStorageAt returns the storage from the state at the given address, key and
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// numbers are also allowed.
func ( s * PublicBlockChainAPI ) GetStorageAt ( ctx context . Context , addr string , key string , blockNr rpc . BlockNumber ) ( hexutil . Bytes , error ) {
address := internal_common . ParseAddr ( addr )
state , _ , err := s . b . StateAndHeaderByNumber ( ctx , blockNr )
if state == nil || err != nil {
return nil , err
}
res := state . GetState ( address , common . HexToHash ( key ) )
return res [ : ] , state . Error ( )
}
func ( s * PublicBlockChainAPI ) getBalanceByBlockNumber ( ctx context . Context , address string , blockNr rpc . BlockNumber ) ( * hexutil . Big , error ) {
addr := internal_common . ParseAddr ( address )
balance , err := s . b . GetBalance ( ctx , addr , blockNr )
if balance == nil {
return nil , err
}
return ( * hexutil . Big ) ( balance ) , err
}
// GetBalanceByBlockNumber returns balance by block number.
func ( s * PublicBlockChainAPI ) GetBalanceByBlockNumber ( ctx context . Context , address string , blockNr rpc . BlockNumber ) ( * hexutil . Big , error ) {
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return nil , err
}
return s . getBalanceByBlockNumber ( ctx , address , blockNr )
}
// GetAccountNonce returns the nonce value of the given address for the given block number
func ( s * PublicBlockChainAPI ) GetAccountNonce ( ctx context . Context , address string , blockNr rpc . BlockNumber ) ( uint64 , error ) {
addr := internal_common . ParseAddr ( address )
return s . b . GetAccountNonce ( ctx , addr , rpc . BlockNumber ( blockNr ) )
}
// GetBalance returns the amount of Atto for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.
func ( s * PublicBlockChainAPI ) GetBalance ( ctx context . Context , address string , blockNr rpc . BlockNumber ) ( * hexutil . Big , error ) {
return s . getBalanceByBlockNumber ( ctx , address , rpc . BlockNumber ( blockNr ) )
}
// BlockNumber returns the block number of the chain head.
func ( s * PublicBlockChainAPI ) BlockNumber ( ) hexutil . Uint64 {
header , _ := s . b . HeaderByNumber ( context . Background ( ) , rpc . LatestBlockNumber ) // latest header should always be available
if header == nil {
return 0
}
return hexutil . Uint64 ( header . Number ( ) . Uint64 ( ) )
}
// ResendCx requests that the egress receipt for the given cross-shard
// transaction be sent to the destination shard for credit. This is used for
// unblocking a half-complete cross-shard transaction whose fund has been
// withdrawn already from the source shard but not credited yet in the
// destination account due to transient failures.
func ( s * PublicBlockChainAPI ) ResendCx ( ctx context . Context , txID common . Hash ) ( bool , error ) {
_ , success := s . b . ResendCx ( ctx , txID )
return success , nil
}
// Call executes the given transaction on the state for the given block number.
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
func ( s * PublicBlockChainAPI ) Call ( ctx context . Context , args CallArgs , blockNr rpc . BlockNumber ) ( hexutil . Bytes , error ) {
result , _ , _ , err := doCall ( ctx , s . b , args , blockNr , vm . Config { } , 5 * time . Second , s . b . RPCGasCap ( ) )
return ( hexutil . Bytes ) ( result ) , err
}
func doCall ( ctx context . Context , b Backend , args CallArgs , blockNr rpc . BlockNumber , vmCfg vm . Config , timeout time . Duration , globalGasCap * big . Int ) ( [ ] byte , uint64 , bool , error ) {
defer func ( start time . Time ) {
utils . Logger ( ) . Debug ( ) .
Dur ( "runtime" , time . Since ( start ) ) .
Msg ( "Executing EVM call finished" )
} ( time . Now ( ) )
state , header , err := b . StateAndHeaderByNumber ( ctx , blockNr )
if state == nil || err != nil {
return nil , 0 , false , err
}
// Set sender address or use a default if none specified
var addr common . Address
if args . From == nil {
// TODO(ricl): this logic was borrowed from [go-ethereum](https://github.com/ethereum/go-ethereum/blob/f578d41ee6b3087f8021fd561a0b5665aea3dba6/internal/ethapi/api.go#L738)
// [question](https://ethereum.stackexchange.com/questions/72979/why-does-the-docall-function-use-the-first-account-by-default)
// Might need to reconsider the logic
// if wallets := b.AccountManager().Wallets(); len(wallets) > 0 {
// if accounts := wallets[0].Accounts(); len(accounts) > 0 {
// addr = accounts[0].Address
// }
// }
// The logic in ethereum is to pick a random address managed under the account manager.
// Currently Harmony no longers support the account manager.
// Any address does not affect the logic of this call.
addr = common . HexToAddress ( defaultFromAddress )
} else {
addr = * args . From
}
// Set default gas & gas price if none were set
gas := uint64 ( math . MaxUint64 / 2 )
if args . Gas != nil {
gas = uint64 ( * args . Gas )
}
if globalGasCap != nil && globalGasCap . Uint64 ( ) < gas {
utils . Logger ( ) . Warn ( ) .
Uint64 ( "requested" , gas ) .
Uint64 ( "cap" , globalGasCap . Uint64 ( ) ) .
Msg ( "Caller gas above allowance, capping" )
gas = globalGasCap . Uint64 ( )
}
gasPrice := new ( big . Int ) . SetUint64 ( defaultGasPrice )
if args . GasPrice != nil {
gasPrice = args . GasPrice . ToInt ( )
}
value := new ( big . Int )
if args . Value != nil {
value = args . Value . ToInt ( )
}
var data [ ] byte
if args . Data != nil {
data = [ ] byte ( * args . Data )
}
// Create new call message
msg := types . NewMessage ( addr , args . To , 0 , value , gas , gasPrice , data , false )
// Setup context so it may be cancelled the call has completed
// or, in case of unmetered gas, setup a context with a timeout.
var cancel context . CancelFunc
if timeout > 0 {
ctx , cancel = context . WithTimeout ( ctx , timeout )
} else {
ctx , cancel = context . WithCancel ( ctx )
}
// Make sure the context is cancelled when the call has completed
// this makes sure resources are cleaned up.
defer cancel ( )
// Get a new instance of the EVM.
evm , vmError , err := b . GetEVM ( ctx , msg , state , header )
if err != nil {
return nil , 0 , false , err
}
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
go func ( ) {
<- ctx . Done ( )
evm . Cancel ( )
} ( )
// Setup the gas pool (also for unmetered requests)
// and apply the message.
gp := new ( core . GasPool ) . AddGas ( math . MaxUint64 )
res , gas , failed , err := core . ApplyMessage ( evm , msg , gp )
if err := vmError ( ) ; err != nil {
return nil , 0 , false , err
}
// If the timer caused an abort, return an appropriate error message
if evm . Cancelled ( ) {
return nil , 0 , false , fmt . Errorf ( "execution aborted (timeout = %v)" , timeout )
}
return res , gas , failed , err
}
// LatestHeader returns the latest header information
func ( s * PublicBlockChainAPI ) LatestHeader ( ctx context . Context ) * HeaderInformation {
header , _ := s . b . HeaderByNumber ( context . Background ( ) , rpc . LatestBlockNumber ) // latest header should always be available
return newHeaderInformation ( header )
}
// GetHeaderByNumber returns block header at given number
func ( s * PublicBlockChainAPI ) GetHeaderByNumber ( ctx context . Context , blockNum rpc . BlockNumber ) ( * HeaderInformation , error ) {
if err := s . isBlockGreaterThanLatest ( blockNum ) ; err != nil {
return nil , err
}
header , err := s . b . HeaderByNumber ( context . Background ( ) , blockNum )
if err != nil {
return nil , err
}
return newHeaderInformation ( header ) , nil
}
// GetTotalStaking returns total staking by validators, only meant to be called on beaconchain
// explorer node
func ( s * PublicBlockChainAPI ) GetTotalStaking ( ) ( * big . Int , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
return s . b . GetTotalStakingSnapshot ( ) , nil
}
// GetMedianRawStakeSnapshot returns the raw median stake, only meant to be called on beaconchain
// explorer node
[rpc][availability][apr] Richer validator information, implement APR, unify EPoS computation, remove fall 2019 tech debt (#2484)
* [rpc][validator] Extend hmy blockchain validator information
* [availability] Optimize bump count
* [staking][validator][rpc] Remove validator stats rpc, fold into validator information, make existing pattern default behavior
* [slash] Reimplement SetDifference
* [reward][engine][network] Remove bad API from fall, begin setup for Per validator awards
* [header] Custom Marshal header for downstream, remove dev code
* [effective][committee] Factor out EPoS round of computation thereby unification in codebase of EPoS
* [unit-test] Fix semantically wrong validator unit tests, punt on maxBLS key wrt tx-pool test
* [reward] Use excellent singleflight package for caching lookup of subcommittees
* [apr][reward] Begin APR package itself, iterate on iterface signatures
* [reward] Handle possible error from singleflight
* [rpc][validator][reward] Adjust RPC committees, singleflight on votingPower, foldStats into Validator Information
* [apr] Stub out computation of APR
* [effective][committee] Upgrade SlotPurchase with named fields, provide marshal
* [effective] Update Tests
* [blockchain] TODO Remove the validators no longer in committee
* [validator][effective] More expressive string representation of eligibilty, ValidatorRPC explicit say if in committee now
* [rpc] Median-stake more semantic meaningful
* [validator] Iterate on semantic meaning of JSON representation
* [offchain] Make validator stats return explicit error
* [availability] Small typo
* [rpc] Quick visual hack until fix delete out kicked out validators
* [offchain] Delete validator from offchain that lost their slot
* [apr] Forgot to update interface signature
* [apr] Mul instead of Div
* [protocol][validator] Fold block reward accum per vaidator into validator-wrapper, off-chain => on-chain
* [votepower] Refactor votepower Roster, simplify aggregation of network wide rosters
* [votepower][shard] Adjust roster, optimize usage of BLSPublicKey as key, use MarshalText trick
* [shard] Granular errors
* [votepower][validator] Unify votepower data structure with off-chain usage
* [votepower][consensus][validator] Further simplify and unify votepower with off-chain, validator stats
* [votepower] Use RJs naming convention group,overall
* [votepower] Remove Println, do keep enforcing order
* [effective][reward] Expand semantics of eligibility as it was overloaded and confusing, evict old voting power computations
* [apr] Adjust json field name
* [votepower] Only aggregate on external validator
* [votepower] Mistake on aggregation, custom presentation network-wide
* [rpc][validator][availability] Remove parameter, take into account empty snapshot
* [apr] Use snapshots from two, one epochs ago. Still have question on header
* [apr] Use GetHeaderByNumber for the header needed for time stamp
* [chain] Evict > 3 epoch old voting power
* [blockchain] Leave Delete Validator snapshot as TODO
* [validator][rpc][effective] Undo changes to Protocol field, use virtual construct at RPC layer for meaning
* [project] Address PR comments
* [committee][rpc] Move +1 to computation of epos round rather than hack mutation
* [reward] Remove entire unnecessary loop, hook on AddReward. Remove unnecessary new big int
* [votepower][rpc][validator] Stick with numeric.Dec for token involved with computation, expose accumulate block-reward in RPC
* [effective][committee] Track the candidates for the EPoS auction, RPC median-stake benefits
* [node] Add hack way to get real error reason of why cannot load shardchain
* [consensus] Expand log on current issue on nil block
* [apr] Do the actual call to compute for validator's APR
* [committee] Wrap SlotOrder with validator address, manifests in median-stake RPC
* [apr] Incorrect error handle order
* [quorum] Remove incorrect compare on bls Key, (typo), remove redundant error check
* [shard] Add log if stakedSlots is 0
* [apr] More sanity check on div by zero, more lenient on error when dont have historical data yet
* [committee] Remove + 1 on seat count
* [apr] Use int64() directly
* [apr] Log when odd empty nil header
* [apr] Do not crash on empty header, figure out later
5 years ago
func ( s * PublicBlockChainAPI ) GetMedianRawStakeSnapshot ( ) (
* committee . CompletedEPoSRound , error ,
) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
return s . b . GetMedianRawStakeSnapshot ( )
}
// GetLatestChainHeaders ..
func ( s * PublicBlockChainAPI ) GetLatestChainHeaders ( ) * block . HeaderPair {
return s . b . GetLatestChainHeaders ( )
}
// GetAllValidatorAddresses returns all validator addresses.
func ( s * PublicBlockChainAPI ) GetAllValidatorAddresses ( ) ( [ ] string , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
addresses := [ ] string { }
for _ , addr := range s . b . GetAllValidatorAddresses ( ) {
oneAddr , _ := internal_common . AddressToBech32 ( addr )
addresses = append ( addresses , oneAddr )
}
return addresses , nil
}
// GetElectedValidatorAddresses returns elected validator addresses.
func ( s * PublicBlockChainAPI ) GetElectedValidatorAddresses ( ) ( [ ] string , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
addresses := [ ] string { }
for _ , addr := range s . b . GetElectedValidatorAddresses ( ) {
oneAddr , _ := internal_common . AddressToBech32 ( addr )
addresses = append ( addresses , oneAddr )
}
return addresses , nil
}
// GetValidatorInformation returns information about a validator.
func ( s * PublicBlockChainAPI ) GetValidatorInformation (
ctx context . Context , address string ,
) ( * staking . ValidatorRPCEnhanced , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
block , err := s . b . BlockByNumber ( ctx , rpc . BlockNumber ( rpc . LatestBlockNumber ) )
if err != nil {
return nil , errors . Wrapf ( err , "could not retrieve the latest block information" )
}
[rpc][availability][apr] Richer validator information, implement APR, unify EPoS computation, remove fall 2019 tech debt (#2484)
* [rpc][validator] Extend hmy blockchain validator information
* [availability] Optimize bump count
* [staking][validator][rpc] Remove validator stats rpc, fold into validator information, make existing pattern default behavior
* [slash] Reimplement SetDifference
* [reward][engine][network] Remove bad API from fall, begin setup for Per validator awards
* [header] Custom Marshal header for downstream, remove dev code
* [effective][committee] Factor out EPoS round of computation thereby unification in codebase of EPoS
* [unit-test] Fix semantically wrong validator unit tests, punt on maxBLS key wrt tx-pool test
* [reward] Use excellent singleflight package for caching lookup of subcommittees
* [apr][reward] Begin APR package itself, iterate on iterface signatures
* [reward] Handle possible error from singleflight
* [rpc][validator][reward] Adjust RPC committees, singleflight on votingPower, foldStats into Validator Information
* [apr] Stub out computation of APR
* [effective][committee] Upgrade SlotPurchase with named fields, provide marshal
* [effective] Update Tests
* [blockchain] TODO Remove the validators no longer in committee
* [validator][effective] More expressive string representation of eligibilty, ValidatorRPC explicit say if in committee now
* [rpc] Median-stake more semantic meaningful
* [validator] Iterate on semantic meaning of JSON representation
* [offchain] Make validator stats return explicit error
* [availability] Small typo
* [rpc] Quick visual hack until fix delete out kicked out validators
* [offchain] Delete validator from offchain that lost their slot
* [apr] Forgot to update interface signature
* [apr] Mul instead of Div
* [protocol][validator] Fold block reward accum per vaidator into validator-wrapper, off-chain => on-chain
* [votepower] Refactor votepower Roster, simplify aggregation of network wide rosters
* [votepower][shard] Adjust roster, optimize usage of BLSPublicKey as key, use MarshalText trick
* [shard] Granular errors
* [votepower][validator] Unify votepower data structure with off-chain usage
* [votepower][consensus][validator] Further simplify and unify votepower with off-chain, validator stats
* [votepower] Use RJs naming convention group,overall
* [votepower] Remove Println, do keep enforcing order
* [effective][reward] Expand semantics of eligibility as it was overloaded and confusing, evict old voting power computations
* [apr] Adjust json field name
* [votepower] Only aggregate on external validator
* [votepower] Mistake on aggregation, custom presentation network-wide
* [rpc][validator][availability] Remove parameter, take into account empty snapshot
* [apr] Use snapshots from two, one epochs ago. Still have question on header
* [apr] Use GetHeaderByNumber for the header needed for time stamp
* [chain] Evict > 3 epoch old voting power
* [blockchain] Leave Delete Validator snapshot as TODO
* [validator][rpc][effective] Undo changes to Protocol field, use virtual construct at RPC layer for meaning
* [project] Address PR comments
* [committee][rpc] Move +1 to computation of epos round rather than hack mutation
* [reward] Remove entire unnecessary loop, hook on AddReward. Remove unnecessary new big int
* [votepower][rpc][validator] Stick with numeric.Dec for token involved with computation, expose accumulate block-reward in RPC
* [effective][committee] Track the candidates for the EPoS auction, RPC median-stake benefits
* [node] Add hack way to get real error reason of why cannot load shardchain
* [consensus] Expand log on current issue on nil block
* [apr] Do the actual call to compute for validator's APR
* [committee] Wrap SlotOrder with validator address, manifests in median-stake RPC
* [apr] Incorrect error handle order
* [quorum] Remove incorrect compare on bls Key, (typo), remove redundant error check
* [shard] Add log if stakedSlots is 0
* [apr] More sanity check on div by zero, more lenient on error when dont have historical data yet
* [committee] Remove + 1 on seat count
* [apr] Use int64() directly
* [apr] Log when odd empty nil header
* [apr] Do not crash on empty header, figure out later
5 years ago
return s . b . GetValidatorInformation (
internal_common . ParseAddr ( address ) , block ,
[rpc][availability][apr] Richer validator information, implement APR, unify EPoS computation, remove fall 2019 tech debt (#2484)
* [rpc][validator] Extend hmy blockchain validator information
* [availability] Optimize bump count
* [staking][validator][rpc] Remove validator stats rpc, fold into validator information, make existing pattern default behavior
* [slash] Reimplement SetDifference
* [reward][engine][network] Remove bad API from fall, begin setup for Per validator awards
* [header] Custom Marshal header for downstream, remove dev code
* [effective][committee] Factor out EPoS round of computation thereby unification in codebase of EPoS
* [unit-test] Fix semantically wrong validator unit tests, punt on maxBLS key wrt tx-pool test
* [reward] Use excellent singleflight package for caching lookup of subcommittees
* [apr][reward] Begin APR package itself, iterate on iterface signatures
* [reward] Handle possible error from singleflight
* [rpc][validator][reward] Adjust RPC committees, singleflight on votingPower, foldStats into Validator Information
* [apr] Stub out computation of APR
* [effective][committee] Upgrade SlotPurchase with named fields, provide marshal
* [effective] Update Tests
* [blockchain] TODO Remove the validators no longer in committee
* [validator][effective] More expressive string representation of eligibilty, ValidatorRPC explicit say if in committee now
* [rpc] Median-stake more semantic meaningful
* [validator] Iterate on semantic meaning of JSON representation
* [offchain] Make validator stats return explicit error
* [availability] Small typo
* [rpc] Quick visual hack until fix delete out kicked out validators
* [offchain] Delete validator from offchain that lost their slot
* [apr] Forgot to update interface signature
* [apr] Mul instead of Div
* [protocol][validator] Fold block reward accum per vaidator into validator-wrapper, off-chain => on-chain
* [votepower] Refactor votepower Roster, simplify aggregation of network wide rosters
* [votepower][shard] Adjust roster, optimize usage of BLSPublicKey as key, use MarshalText trick
* [shard] Granular errors
* [votepower][validator] Unify votepower data structure with off-chain usage
* [votepower][consensus][validator] Further simplify and unify votepower with off-chain, validator stats
* [votepower] Use RJs naming convention group,overall
* [votepower] Remove Println, do keep enforcing order
* [effective][reward] Expand semantics of eligibility as it was overloaded and confusing, evict old voting power computations
* [apr] Adjust json field name
* [votepower] Only aggregate on external validator
* [votepower] Mistake on aggregation, custom presentation network-wide
* [rpc][validator][availability] Remove parameter, take into account empty snapshot
* [apr] Use snapshots from two, one epochs ago. Still have question on header
* [apr] Use GetHeaderByNumber for the header needed for time stamp
* [chain] Evict > 3 epoch old voting power
* [blockchain] Leave Delete Validator snapshot as TODO
* [validator][rpc][effective] Undo changes to Protocol field, use virtual construct at RPC layer for meaning
* [project] Address PR comments
* [committee][rpc] Move +1 to computation of epos round rather than hack mutation
* [reward] Remove entire unnecessary loop, hook on AddReward. Remove unnecessary new big int
* [votepower][rpc][validator] Stick with numeric.Dec for token involved with computation, expose accumulate block-reward in RPC
* [effective][committee] Track the candidates for the EPoS auction, RPC median-stake benefits
* [node] Add hack way to get real error reason of why cannot load shardchain
* [consensus] Expand log on current issue on nil block
* [apr] Do the actual call to compute for validator's APR
* [committee] Wrap SlotOrder with validator address, manifests in median-stake RPC
* [apr] Incorrect error handle order
* [quorum] Remove incorrect compare on bls Key, (typo), remove redundant error check
* [shard] Add log if stakedSlots is 0
* [apr] More sanity check on div by zero, more lenient on error when dont have historical data yet
* [committee] Remove + 1 on seat count
* [apr] Use int64() directly
* [apr] Log when odd empty nil header
* [apr] Do not crash on empty header, figure out later
5 years ago
)
}
// GetValidatorInformationByBlockNumber returns information about a validator.
func ( s * PublicBlockChainAPI ) GetValidatorInformationByBlockNumber (
ctx context . Context , address string , blockNr rpc . BlockNumber ,
) ( * staking . ValidatorRPCEnhanced , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return nil , err
}
block , err := s . b . BlockByNumber ( ctx , rpc . BlockNumber ( blockNr ) )
if err != nil {
return nil , errors . Wrapf ( err , "could not retrieve the block information for block number: %d" , blockNr )
}
return s . b . GetValidatorInformation (
internal_common . ParseAddr ( address ) , block ,
)
}
func ( s * PublicBlockChainAPI ) getAllValidatorInformation (
ctx context . Context , page int , blockNr rpc . BlockNumber ,
) ( [ ] * staking . ValidatorRPCEnhanced , error ) {
if page < - 1 {
return nil , errors . Errorf ( "page given %d cannot be less than -1" , page )
}
addresses := s . b . GetAllValidatorAddresses ( )
if page != - 1 && len ( addresses ) <= page * validatorsPageSize {
return make ( [ ] * staking . ValidatorRPCEnhanced , 0 ) , nil
}
validatorsNum := len ( addresses )
start := 0
if page != - 1 {
validatorsNum = validatorsPageSize
start = page * validatorsPageSize
if len ( addresses ) - start < validatorsPageSize {
validatorsNum = len ( addresses ) - start
}
}
validators := [ ] * staking . ValidatorRPCEnhanced { }
block , err := s . b . BlockByNumber ( ctx , rpc . BlockNumber ( blockNr ) )
if err != nil {
return nil , errors . Wrapf ( err , "could not retrieve the block information for block number: %d" , blockNr )
}
for i := start ; i < start + validatorsNum ; i ++ {
information , err := s . b . GetValidatorInformation ( addresses [ i ] , block )
if err == nil {
validators = append ( validators , information )
}
}
return validators , nil
}
// GetAllValidatorInformation returns information about all validators.
// If page is -1, return all instead of `validatorsPageSize` elements.
func ( s * PublicBlockChainAPI ) GetAllValidatorInformation (
ctx context . Context , page int ,
) ( [ ] * staking . ValidatorRPCEnhanced , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
blockNr := s . b . CurrentBlock ( ) . NumberU64 ( )
// delete cache for previous block
prevKey := fmt . Sprintf ( "all-info-%d" , blockNr - 1 )
s . b . SingleFlightForgetKey ( prevKey )
key := fmt . Sprintf ( "all-info-%d" , blockNr )
res , err := s . b . SingleFlightRequest (
key ,
func ( ) ( interface { } , error ) {
return s . getAllValidatorInformation ( ctx , page , rpc . LatestBlockNumber )
} ,
)
if err != nil {
return nil , err
}
return res . ( [ ] * staking . ValidatorRPCEnhanced ) , nil
}
// GetAllValidatorInformationByBlockNumber returns information about all validators.
// If page is -1, return all instead of `validatorsPageSize` elements.
func ( s * PublicBlockChainAPI ) GetAllValidatorInformationByBlockNumber (
ctx context . Context , page int , blockNr rpc . BlockNumber ,
) ( [ ] * staking . ValidatorRPCEnhanced , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
if err := s . isBlockGreaterThanLatest ( blockNr ) ; err != nil {
return nil , err
}
return s . getAllValidatorInformation ( ctx , page , blockNr )
}
// GetAllDelegationInformation returns delegation information about `validatorsPageSize` validators,
// starting at `page*validatorsPageSize`.
// If page is -1, return all instead of `validatorsPageSize` elements.
func ( s * PublicBlockChainAPI ) GetAllDelegationInformation ( ctx context . Context , page int ) ( [ ] [ ] * RPCDelegation , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
if page < - 1 {
return make ( [ ] [ ] * RPCDelegation , 0 ) , nil
}
addresses := s . b . GetAllValidatorAddresses ( )
if page != - 1 && len ( addresses ) <= page * validatorsPageSize {
return make ( [ ] [ ] * RPCDelegation , 0 ) , nil
}
validatorsNum := len ( addresses )
start := 0
if page != - 1 {
validatorsNum = validatorsPageSize
start = page * validatorsPageSize
if len ( addresses ) - start < validatorsPageSize {
validatorsNum = len ( addresses ) - start
}
}
validators := make ( [ ] [ ] * RPCDelegation , validatorsNum )
var err error
for i := start ; i < start + validatorsNum ; i ++ {
validators [ i - start ] , err = s . GetDelegationsByValidator ( ctx , addresses [ i ] . String ( ) )
if err != nil {
return nil , err
}
}
return validators , nil
}
// GetDelegationsByDelegator returns list of delegations for a delegator address.
func ( s * PublicBlockChainAPI ) GetDelegationsByDelegator ( ctx context . Context , address string ) ( [ ] * RPCDelegation , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
delegatorAddress := internal_common . ParseAddr ( address )
validators , delegations := s . b . GetDelegationsByDelegator ( delegatorAddress )
result := [ ] * RPCDelegation { }
for i := range delegations {
delegation := delegations [ i ]
undelegations := make ( [ ] RPCUndelegation , len ( delegation . Undelegations ) )
for j := range delegation . Undelegations {
undelegations = append ( undelegations , RPCUndelegation {
delegation . Undelegations [ j ] . Amount ,
delegation . Undelegations [ j ] . Epoch ,
} )
}
valAddr , _ := internal_common . AddressToBech32 ( validators [ i ] )
delAddr , _ := internal_common . AddressToBech32 ( delegatorAddress )
result = append ( result , & RPCDelegation {
valAddr ,
delAddr ,
delegation . Amount ,
delegation . Reward ,
undelegations ,
} )
}
return result , nil
}
// GetDelegationsByDelegatorByBlockNumber returns list of delegations for a delegator address at given block number
func ( s * PublicBlockChainAPI ) GetDelegationsByDelegatorByBlockNumber (
ctx context . Context , address string , blockNum rpc . BlockNumber ,
) ( [ ] * RPCDelegation , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
if err := s . isBlockGreaterThanLatest ( blockNum ) ; err != nil {
return nil , err
}
delegatorAddress := internal_common . ParseAddr ( address )
block , err := s . b . BlockByNumber ( ctx , rpc . BlockNumber ( blockNum ) )
if err != nil {
return nil , errors . Wrapf ( err , "could not retrieve the block information for block number: %d" , blockNum )
}
validators , delegations := s . b . GetDelegationsByDelegatorByBlock ( delegatorAddress , block )
result := make ( [ ] * RPCDelegation , len ( delegations ) )
for i := range delegations {
delegation := delegations [ i ]
undelegations := make ( [ ] RPCUndelegation , len ( delegation . Undelegations ) )
for j := range delegation . Undelegations {
undelegations [ j ] = RPCUndelegation {
delegation . Undelegations [ j ] . Amount ,
delegation . Undelegations [ j ] . Epoch ,
}
}
valAddr , _ := internal_common . AddressToBech32 ( validators [ i ] )
delAddr , _ := internal_common . AddressToBech32 ( delegatorAddress )
result [ i ] = & RPCDelegation {
valAddr ,
delAddr ,
delegation . Amount ,
delegation . Reward ,
undelegations ,
}
}
return result , nil
}
// GetDelegationsByValidator returns list of delegations for a validator address.
func ( s * PublicBlockChainAPI ) GetDelegationsByValidator ( ctx context . Context , address string ) ( [ ] * RPCDelegation , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
validatorAddress := internal_common . ParseAddr ( address )
delegations := s . b . GetDelegationsByValidator ( validatorAddress )
result := make ( [ ] * RPCDelegation , 0 )
for _ , delegation := range delegations {
undelegations := [ ] RPCUndelegation { }
for j := range delegation . Undelegations {
undelegations = append ( undelegations , RPCUndelegation {
delegation . Undelegations [ j ] . Amount ,
delegation . Undelegations [ j ] . Epoch ,
} )
}
valAddr , _ := internal_common . AddressToBech32 ( validatorAddress )
delAddr , _ := internal_common . AddressToBech32 ( delegation . DelegatorAddress )
result = append ( result , & RPCDelegation {
valAddr ,
delAddr ,
delegation . Amount ,
delegation . Reward ,
undelegations ,
} )
}
return result , nil
}
// GetDelegationByDelegatorAndValidator returns a delegation for delegator and validator.
func ( s * PublicBlockChainAPI ) GetDelegationByDelegatorAndValidator ( ctx context . Context , address string , validator string ) ( * RPCDelegation , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
delegatorAddress := internal_common . ParseAddr ( address )
validatorAddress := internal_common . ParseAddr ( validator )
validators , delegations := s . b . GetDelegationsByDelegator ( delegatorAddress )
for i := range delegations {
if validators [ i ] != validatorAddress {
continue
}
delegation := delegations [ i ]
undelegations := [ ] RPCUndelegation { }
for j := range delegation . Undelegations {
undelegations = append ( undelegations , RPCUndelegation {
delegation . Undelegations [ j ] . Amount ,
delegation . Undelegations [ j ] . Epoch ,
} )
}
valAddr , _ := internal_common . AddressToBech32 ( validatorAddress )
delAddr , _ := internal_common . AddressToBech32 ( delegatorAddress )
return & RPCDelegation {
valAddr ,
delAddr ,
delegation . Amount ,
delegation . Reward ,
undelegations ,
} , nil
}
return nil , nil
}
// doEstimateGas ..
func doEstimateGas ( ctx context . Context , b Backend , args CallArgs , gasCap * big . Int ) ( hexutil . Uint64 , error ) {
// Binary search the gas requirement, as it may be higher than the amount used
var (
lo = params . TxGas - 1
hi uint64
cap uint64
)
blockNum := rpc . LatestBlockNumber
if args . Gas != nil && uint64 ( * args . Gas ) >= params . TxGas {
hi = uint64 ( * args . Gas )
} else {
// Retrieve the block to act as the gas ceiling
block , err := b . BlockByNumber ( ctx , blockNum )
if err != nil {
return 0 , err
}
hi = block . GasLimit ( )
}
if gasCap != nil && hi > gasCap . Uint64 ( ) {
// log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap)
hi = gasCap . Uint64 ( )
}
cap = hi
// Use zero-address if none other is available
if args . From == nil {
args . From = & common . Address { }
}
// Create a helper to check if a gas allowance results in an executable transaction
executable := func ( gas uint64 ) bool {
args . Gas = ( * hexutil . Uint64 ) ( & gas )
_ , _ , failed , err := doCall ( ctx , b , args , blockNum , vm . Config { } , 0 , big . NewInt ( int64 ( cap ) ) )
if err != nil || failed {
return false
}
return true
}
// Execute the binary search and hone in on an executable gas limit
for lo + 1 < hi {
mid := ( hi + lo ) / 2
if ! executable ( mid ) {
lo = mid
} else {
hi = mid
}
}
// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
if ! executable ( hi ) {
return 0 , fmt . Errorf ( "gas required exceeds allowance (%d) or always failing transaction" , cap )
}
}
return hexutil . Uint64 ( hi ) , nil
}
// EstimateGas returns an estimate of the amount of gas needed to execute the
// given transaction against the current pending block.
func ( s * PublicBlockChainAPI ) EstimateGas ( ctx context . Context , args CallArgs ) ( hexutil . Uint64 , error ) {
return doEstimateGas ( ctx , s . b , args , nil )
}
// GetCurrentUtilityMetrics ..
func ( s * PublicBlockChainAPI ) GetCurrentUtilityMetrics ( ) ( * network . UtilityMetric , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
return s . b . GetCurrentUtilityMetrics ( )
}
// GetSuperCommittees ..
func ( s * PublicBlockChainAPI ) GetSuperCommittees ( ) ( * quorum . Transition , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
return s . b . GetSuperCommittees ( )
}
// GetCurrentBadBlocks ..
func ( s * PublicBlockChainAPI ) GetCurrentBadBlocks ( ) [ ] core . BadBlock {
return s . b . GetCurrentBadBlocks ( )
}
// GetTotalSupply ..
func ( s * PublicBlockChainAPI ) GetTotalSupply ( ) ( numeric . Dec , error ) {
return numeric . NewDec ( initSupply ) , nil
}
// GetCirculatingSupply ..
func ( s * PublicBlockChainAPI ) GetCirculatingSupply ( ) ( numeric . Dec , error ) {
timestamp := time . Now ( )
return numeric . NewDec ( initSupply ) . Mul ( reward . PercentageForTimeStamp ( timestamp . Unix ( ) ) ) , nil
}
// GetStakingNetworkInfo ..
[rpc][availability][apr] Richer validator information, implement APR, unify EPoS computation, remove fall 2019 tech debt (#2484)
* [rpc][validator] Extend hmy blockchain validator information
* [availability] Optimize bump count
* [staking][validator][rpc] Remove validator stats rpc, fold into validator information, make existing pattern default behavior
* [slash] Reimplement SetDifference
* [reward][engine][network] Remove bad API from fall, begin setup for Per validator awards
* [header] Custom Marshal header for downstream, remove dev code
* [effective][committee] Factor out EPoS round of computation thereby unification in codebase of EPoS
* [unit-test] Fix semantically wrong validator unit tests, punt on maxBLS key wrt tx-pool test
* [reward] Use excellent singleflight package for caching lookup of subcommittees
* [apr][reward] Begin APR package itself, iterate on iterface signatures
* [reward] Handle possible error from singleflight
* [rpc][validator][reward] Adjust RPC committees, singleflight on votingPower, foldStats into Validator Information
* [apr] Stub out computation of APR
* [effective][committee] Upgrade SlotPurchase with named fields, provide marshal
* [effective] Update Tests
* [blockchain] TODO Remove the validators no longer in committee
* [validator][effective] More expressive string representation of eligibilty, ValidatorRPC explicit say if in committee now
* [rpc] Median-stake more semantic meaningful
* [validator] Iterate on semantic meaning of JSON representation
* [offchain] Make validator stats return explicit error
* [availability] Small typo
* [rpc] Quick visual hack until fix delete out kicked out validators
* [offchain] Delete validator from offchain that lost their slot
* [apr] Forgot to update interface signature
* [apr] Mul instead of Div
* [protocol][validator] Fold block reward accum per vaidator into validator-wrapper, off-chain => on-chain
* [votepower] Refactor votepower Roster, simplify aggregation of network wide rosters
* [votepower][shard] Adjust roster, optimize usage of BLSPublicKey as key, use MarshalText trick
* [shard] Granular errors
* [votepower][validator] Unify votepower data structure with off-chain usage
* [votepower][consensus][validator] Further simplify and unify votepower with off-chain, validator stats
* [votepower] Use RJs naming convention group,overall
* [votepower] Remove Println, do keep enforcing order
* [effective][reward] Expand semantics of eligibility as it was overloaded and confusing, evict old voting power computations
* [apr] Adjust json field name
* [votepower] Only aggregate on external validator
* [votepower] Mistake on aggregation, custom presentation network-wide
* [rpc][validator][availability] Remove parameter, take into account empty snapshot
* [apr] Use snapshots from two, one epochs ago. Still have question on header
* [apr] Use GetHeaderByNumber for the header needed for time stamp
* [chain] Evict > 3 epoch old voting power
* [blockchain] Leave Delete Validator snapshot as TODO
* [validator][rpc][effective] Undo changes to Protocol field, use virtual construct at RPC layer for meaning
* [project] Address PR comments
* [committee][rpc] Move +1 to computation of epos round rather than hack mutation
* [reward] Remove entire unnecessary loop, hook on AddReward. Remove unnecessary new big int
* [votepower][rpc][validator] Stick with numeric.Dec for token involved with computation, expose accumulate block-reward in RPC
* [effective][committee] Track the candidates for the EPoS auction, RPC median-stake benefits
* [node] Add hack way to get real error reason of why cannot load shardchain
* [consensus] Expand log on current issue on nil block
* [apr] Do the actual call to compute for validator's APR
* [committee] Wrap SlotOrder with validator address, manifests in median-stake RPC
* [apr] Incorrect error handle order
* [quorum] Remove incorrect compare on bls Key, (typo), remove redundant error check
* [shard] Add log if stakedSlots is 0
* [apr] More sanity check on div by zero, more lenient on error when dont have historical data yet
* [committee] Remove + 1 on seat count
* [apr] Use int64() directly
* [apr] Log when odd empty nil header
* [apr] Do not crash on empty header, figure out later
5 years ago
func ( s * PublicBlockChainAPI ) GetStakingNetworkInfo (
ctx context . Context ,
) ( * StakingNetworkInfo , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
totalStaking , _ := s . GetTotalStaking ( )
[rpc][availability][apr] Richer validator information, implement APR, unify EPoS computation, remove fall 2019 tech debt (#2484)
* [rpc][validator] Extend hmy blockchain validator information
* [availability] Optimize bump count
* [staking][validator][rpc] Remove validator stats rpc, fold into validator information, make existing pattern default behavior
* [slash] Reimplement SetDifference
* [reward][engine][network] Remove bad API from fall, begin setup for Per validator awards
* [header] Custom Marshal header for downstream, remove dev code
* [effective][committee] Factor out EPoS round of computation thereby unification in codebase of EPoS
* [unit-test] Fix semantically wrong validator unit tests, punt on maxBLS key wrt tx-pool test
* [reward] Use excellent singleflight package for caching lookup of subcommittees
* [apr][reward] Begin APR package itself, iterate on iterface signatures
* [reward] Handle possible error from singleflight
* [rpc][validator][reward] Adjust RPC committees, singleflight on votingPower, foldStats into Validator Information
* [apr] Stub out computation of APR
* [effective][committee] Upgrade SlotPurchase with named fields, provide marshal
* [effective] Update Tests
* [blockchain] TODO Remove the validators no longer in committee
* [validator][effective] More expressive string representation of eligibilty, ValidatorRPC explicit say if in committee now
* [rpc] Median-stake more semantic meaningful
* [validator] Iterate on semantic meaning of JSON representation
* [offchain] Make validator stats return explicit error
* [availability] Small typo
* [rpc] Quick visual hack until fix delete out kicked out validators
* [offchain] Delete validator from offchain that lost their slot
* [apr] Forgot to update interface signature
* [apr] Mul instead of Div
* [protocol][validator] Fold block reward accum per vaidator into validator-wrapper, off-chain => on-chain
* [votepower] Refactor votepower Roster, simplify aggregation of network wide rosters
* [votepower][shard] Adjust roster, optimize usage of BLSPublicKey as key, use MarshalText trick
* [shard] Granular errors
* [votepower][validator] Unify votepower data structure with off-chain usage
* [votepower][consensus][validator] Further simplify and unify votepower with off-chain, validator stats
* [votepower] Use RJs naming convention group,overall
* [votepower] Remove Println, do keep enforcing order
* [effective][reward] Expand semantics of eligibility as it was overloaded and confusing, evict old voting power computations
* [apr] Adjust json field name
* [votepower] Only aggregate on external validator
* [votepower] Mistake on aggregation, custom presentation network-wide
* [rpc][validator][availability] Remove parameter, take into account empty snapshot
* [apr] Use snapshots from two, one epochs ago. Still have question on header
* [apr] Use GetHeaderByNumber for the header needed for time stamp
* [chain] Evict > 3 epoch old voting power
* [blockchain] Leave Delete Validator snapshot as TODO
* [validator][rpc][effective] Undo changes to Protocol field, use virtual construct at RPC layer for meaning
* [project] Address PR comments
* [committee][rpc] Move +1 to computation of epos round rather than hack mutation
* [reward] Remove entire unnecessary loop, hook on AddReward. Remove unnecessary new big int
* [votepower][rpc][validator] Stick with numeric.Dec for token involved with computation, expose accumulate block-reward in RPC
* [effective][committee] Track the candidates for the EPoS auction, RPC median-stake benefits
* [node] Add hack way to get real error reason of why cannot load shardchain
* [consensus] Expand log on current issue on nil block
* [apr] Do the actual call to compute for validator's APR
* [committee] Wrap SlotOrder with validator address, manifests in median-stake RPC
* [apr] Incorrect error handle order
* [quorum] Remove incorrect compare on bls Key, (typo), remove redundant error check
* [shard] Add log if stakedSlots is 0
* [apr] More sanity check on div by zero, more lenient on error when dont have historical data yet
* [committee] Remove + 1 on seat count
* [apr] Use int64() directly
* [apr] Log when odd empty nil header
* [apr] Do not crash on empty header, figure out later
5 years ago
round , _ := s . GetMedianRawStakeSnapshot ( )
epoch := s . LatestHeader ( ctx ) . Epoch
epochLastBlock , _ := s . EpochLastBlock ( epoch )
totalSupply , _ := s . GetTotalSupply ( )
circulatingSupply , _ := s . GetCirculatingSupply ( )
return & StakingNetworkInfo {
TotalSupply : totalSupply ,
CirculatingSupply : circulatingSupply ,
EpochLastBlock : epochLastBlock ,
TotalStaking : totalStaking ,
[rpc][availability][apr] Richer validator information, implement APR, unify EPoS computation, remove fall 2019 tech debt (#2484)
* [rpc][validator] Extend hmy blockchain validator information
* [availability] Optimize bump count
* [staking][validator][rpc] Remove validator stats rpc, fold into validator information, make existing pattern default behavior
* [slash] Reimplement SetDifference
* [reward][engine][network] Remove bad API from fall, begin setup for Per validator awards
* [header] Custom Marshal header for downstream, remove dev code
* [effective][committee] Factor out EPoS round of computation thereby unification in codebase of EPoS
* [unit-test] Fix semantically wrong validator unit tests, punt on maxBLS key wrt tx-pool test
* [reward] Use excellent singleflight package for caching lookup of subcommittees
* [apr][reward] Begin APR package itself, iterate on iterface signatures
* [reward] Handle possible error from singleflight
* [rpc][validator][reward] Adjust RPC committees, singleflight on votingPower, foldStats into Validator Information
* [apr] Stub out computation of APR
* [effective][committee] Upgrade SlotPurchase with named fields, provide marshal
* [effective] Update Tests
* [blockchain] TODO Remove the validators no longer in committee
* [validator][effective] More expressive string representation of eligibilty, ValidatorRPC explicit say if in committee now
* [rpc] Median-stake more semantic meaningful
* [validator] Iterate on semantic meaning of JSON representation
* [offchain] Make validator stats return explicit error
* [availability] Small typo
* [rpc] Quick visual hack until fix delete out kicked out validators
* [offchain] Delete validator from offchain that lost their slot
* [apr] Forgot to update interface signature
* [apr] Mul instead of Div
* [protocol][validator] Fold block reward accum per vaidator into validator-wrapper, off-chain => on-chain
* [votepower] Refactor votepower Roster, simplify aggregation of network wide rosters
* [votepower][shard] Adjust roster, optimize usage of BLSPublicKey as key, use MarshalText trick
* [shard] Granular errors
* [votepower][validator] Unify votepower data structure with off-chain usage
* [votepower][consensus][validator] Further simplify and unify votepower with off-chain, validator stats
* [votepower] Use RJs naming convention group,overall
* [votepower] Remove Println, do keep enforcing order
* [effective][reward] Expand semantics of eligibility as it was overloaded and confusing, evict old voting power computations
* [apr] Adjust json field name
* [votepower] Only aggregate on external validator
* [votepower] Mistake on aggregation, custom presentation network-wide
* [rpc][validator][availability] Remove parameter, take into account empty snapshot
* [apr] Use snapshots from two, one epochs ago. Still have question on header
* [apr] Use GetHeaderByNumber for the header needed for time stamp
* [chain] Evict > 3 epoch old voting power
* [blockchain] Leave Delete Validator snapshot as TODO
* [validator][rpc][effective] Undo changes to Protocol field, use virtual construct at RPC layer for meaning
* [project] Address PR comments
* [committee][rpc] Move +1 to computation of epos round rather than hack mutation
* [reward] Remove entire unnecessary loop, hook on AddReward. Remove unnecessary new big int
* [votepower][rpc][validator] Stick with numeric.Dec for token involved with computation, expose accumulate block-reward in RPC
* [effective][committee] Track the candidates for the EPoS auction, RPC median-stake benefits
* [node] Add hack way to get real error reason of why cannot load shardchain
* [consensus] Expand log on current issue on nil block
* [apr] Do the actual call to compute for validator's APR
* [committee] Wrap SlotOrder with validator address, manifests in median-stake RPC
* [apr] Incorrect error handle order
* [quorum] Remove incorrect compare on bls Key, (typo), remove redundant error check
* [shard] Add log if stakedSlots is 0
* [apr] More sanity check on div by zero, more lenient on error when dont have historical data yet
* [committee] Remove + 1 on seat count
* [apr] Use int64() directly
* [apr] Log when odd empty nil header
* [apr] Do not crash on empty header, figure out later
5 years ago
MedianRawStake : round . MedianStake ,
} , nil
}
// GetLastCrossLinks ..
func ( s * PublicBlockChainAPI ) GetLastCrossLinks ( ) ( [ ] * types . CrossLink , error ) {
if err := s . isBeaconShard ( ) ; err != nil {
return nil , err
}
return s . b . GetLastCrossLinks ( )
}