github.com/aswedchain/aswed@v1.0.1/consensus/congress/api.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package congress
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/aswedchain/aswed/common"
    23  	"github.com/aswedchain/aswed/consensus"
    24  	"github.com/aswedchain/aswed/core/types"
    25  	"github.com/aswedchain/aswed/rpc"
    26  )
    27  
    28  // API is a user facing RPC API to allow controlling the validator and voting
    29  // mechanisms of the proof-of-authority scheme.
    30  type API struct {
    31  	chain    consensus.ChainHeaderReader
    32  	congress *Congress
    33  }
    34  
    35  // GetSnapshot retrieves the state snapshot at a given block.
    36  func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
    37  	// Retrieve the requested block number (or current if none requested)
    38  	var header *types.Header
    39  	if number == nil || *number == rpc.LatestBlockNumber {
    40  		header = api.chain.CurrentHeader()
    41  	} else {
    42  		header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
    43  	}
    44  	// Ensure we have an actually valid block and return its snapshot
    45  	if header == nil {
    46  		return nil, errUnknownBlock
    47  	}
    48  	return api.congress.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    49  }
    50  
    51  // GetSnapshotAtHash retrieves the state snapshot at a given block.
    52  func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
    53  	header := api.chain.GetHeaderByHash(hash)
    54  	if header == nil {
    55  		return nil, errUnknownBlock
    56  	}
    57  	return api.congress.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    58  }
    59  
    60  // GetValidators retrieves the list of authorized validators at the specified block.
    61  func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) {
    62  	// Retrieve the requested block number (or current if none requested)
    63  	var header *types.Header
    64  	if number == nil || *number == rpc.LatestBlockNumber {
    65  		header = api.chain.CurrentHeader()
    66  	} else {
    67  		header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
    68  	}
    69  	// Ensure we have an actually valid block and return the validators from its snapshot
    70  	if header == nil {
    71  		return nil, errUnknownBlock
    72  	}
    73  	snap, err := api.congress.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return snap.validators(), nil
    78  }
    79  
    80  // GetValidatorsAtHash retrieves the list of authorized validators at the specified block.
    81  func (api *API) GetValidatorsAtHash(hash common.Hash) ([]common.Address, error) {
    82  	header := api.chain.GetHeaderByHash(hash)
    83  	if header == nil {
    84  		return nil, errUnknownBlock
    85  	}
    86  	snap, err := api.congress.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	return snap.validators(), nil
    91  }
    92  
    93  type status struct {
    94  	InturnPercent float64                `json:"inturnPercent"`
    95  	SigningStatus map[common.Address]int `json:"sealerActivity"`
    96  	NumBlocks     uint64                 `json:"numBlocks"`
    97  }
    98  
    99  // Status returns the status of the last N blocks,
   100  // - the number of active validators,
   101  // - the number of validators,
   102  // - the percentage of in-turn blocks
   103  func (api *API) Status() (*status, error) {
   104  	var (
   105  		numBlocks = uint64(64)
   106  		header    = api.chain.CurrentHeader()
   107  		diff      = uint64(0)
   108  		optimals  = 0
   109  	)
   110  	snap, err := api.congress.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	var (
   115  		validators = snap.validators()
   116  		end        = header.Number.Uint64()
   117  		start      = end - numBlocks
   118  	)
   119  	if numBlocks > end {
   120  		start = 1
   121  		numBlocks = end - start
   122  	}
   123  	signStatus := make(map[common.Address]int)
   124  	for _, s := range validators {
   125  		signStatus[s] = 0
   126  	}
   127  	for n := start; n < end; n++ {
   128  		h := api.chain.GetHeaderByNumber(n)
   129  		if h == nil {
   130  			return nil, fmt.Errorf("missing block %d", n)
   131  		}
   132  		if h.Difficulty.Cmp(diffInTurn) == 0 {
   133  			optimals++
   134  		}
   135  		diff += h.Difficulty.Uint64()
   136  		sealer, err := api.congress.Author(h)
   137  		if err != nil {
   138  			return nil, err
   139  		}
   140  		signStatus[sealer]++
   141  	}
   142  	return &status{
   143  		InturnPercent: float64(100*optimals) / float64(numBlocks),
   144  		SigningStatus: signStatus,
   145  		NumBlocks:     numBlocks,
   146  	}, nil
   147  }