github.com/ebakus/go-ebakus@v1.0.5-0.20200520105415-dbccef9ec421/consensus/dpos/api.go (about)

     1  // Copyright 2019 The ebakus/go-ebakus Authors
     2  // This file is part of the ebakus/go-ebakus library.
     3  //
     4  // The ebakus/go-ebakus 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 ebakus/go-ebakus 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 ebakus/go-ebakus library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package dpos
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"github.com/ebakus/go-ebakus/common"
    24  	"github.com/ebakus/go-ebakus/consensus"
    25  	"github.com/ebakus/go-ebakus/core/rawdb"
    26  	"github.com/ebakus/go-ebakus/core/types"
    27  	"github.com/ebakus/go-ebakus/core/vm"
    28  	"github.com/ebakus/go-ebakus/rpc"
    29  )
    30  
    31  // API is a user facing RPC API to allow controlling the voting
    32  // mechanisms of the delegeted proof-of-stake scheme.
    33  type API struct {
    34  	chain consensus.ChainReader
    35  	dpos  *DPOS
    36  }
    37  
    38  func (api *API) rpcOutputWitnesses(wits *vm.WitnessArray) []interface{} {
    39  	dels := make([]interface{}, len(*wits))
    40  
    41  	for i, wit := range *wits {
    42  		d := map[string]interface{}{
    43  			"address": wit.Id,
    44  			"stake":   wit.Stake,
    45  		}
    46  		dels[i] = d
    47  	}
    48  
    49  	return dels
    50  }
    51  
    52  // GetDelegates retrieves the list of delegates at the specified block.
    53  func (api *API) GetDelegates(ctx context.Context, number rpc.BlockNumber) ([]interface{}, error) {
    54  	var header *types.Header
    55  	if number == rpc.LatestBlockNumber {
    56  		header = api.chain.CurrentHeader()
    57  	} else {
    58  		header = api.chain.GetHeaderByNumber(uint64(number))
    59  	}
    60  
    61  	if header == nil {
    62  		return nil, consensus.ErrFutureBlock
    63  	}
    64  
    65  	ebakusSnapshotID := rawdb.ReadSnapshot(api.dpos.db, header.Hash(), header.Number.Uint64())
    66  	ebakusState := api.dpos.ebakusDb.Snapshot(*ebakusSnapshotID)
    67  	defer ebakusState.Release()
    68  
    69  	delegates := GetDelegates(header, ebakusState, api.dpos.config.DelegateCount, api.dpos.config.BonusDelegateCount, api.dpos.config.TurnBlockCount)
    70  
    71  	return api.rpcOutputWitnesses(&delegates), nil
    72  }
    73  
    74  // GetDelegate get delegate.
    75  func (api *API) GetDelegate(ctx context.Context, address common.Address, number rpc.BlockNumber) (map[string]interface{}, error) {
    76  	var header *types.Header
    77  	if number == rpc.LatestBlockNumber {
    78  		header = api.chain.CurrentHeader()
    79  	} else {
    80  		header = api.chain.GetHeaderByNumber(uint64(number))
    81  	}
    82  
    83  	if header == nil {
    84  		return nil, consensus.ErrFutureBlock
    85  	}
    86  
    87  	ebakusSnapshotID := rawdb.ReadSnapshot(api.dpos.db, header.Hash(), header.Number.Uint64())
    88  	ebakusState := api.dpos.ebakusDb.Snapshot(*ebakusSnapshotID)
    89  	defer ebakusState.Release()
    90  
    91  	var witness vm.Witness
    92  
    93  	where := []byte("Id LIKE ")
    94  	whereClause, err := ebakusState.WhereParser(append(where, address.Bytes()...))
    95  	if err != nil {
    96  		return nil, fmt.Errorf("Ebakusdb query error")
    97  	}
    98  
    99  	iter, err := ebakusState.Select(vm.WitnessesTable, whereClause)
   100  	if err != nil {
   101  		return nil, fmt.Errorf("Ebakusdb query error")
   102  	}
   103  
   104  	if iter.Next(&witness) == false {
   105  		return nil, fmt.Errorf("Address is not a delegate")
   106  	}
   107  
   108  	out := map[string]interface{}{
   109  		"address": witness.Id,
   110  		"stake":   witness.Stake,
   111  		"elected": (witness.Flags & vm.ElectEnabledFlag) == 1,
   112  	}
   113  
   114  	return out, nil
   115  }
   116  
   117  func (api *API) GetBlockDensity(ctx context.Context, number rpc.BlockNumber, lookbackTime uint64) (map[string]interface{}, error) {
   118  	return api.dpos.getBlockDensity(api.chain, number, lookbackTime)
   119  }