github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+incompatible/consensus/istanbul/backend/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 backend
    18  
    19  import (
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/consensus"
    22  	"github.com/ethereum/go-ethereum/core/types"
    23  	"github.com/ethereum/go-ethereum/rpc"
    24  )
    25  
    26  // API is a user facing RPC API to dump Istanbul state
    27  type API struct {
    28  	chain    consensus.ChainReader
    29  	istanbul *backend
    30  }
    31  
    32  // GetSnapshot retrieves the state snapshot at a given block.
    33  func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
    34  	// Retrieve the requested block number (or current if none requested)
    35  	var header *types.Header
    36  	if number == nil || *number == rpc.LatestBlockNumber {
    37  		header = api.chain.CurrentHeader()
    38  	} else {
    39  		header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
    40  	}
    41  	// Ensure we have an actually valid block and return its snapshot
    42  	if header == nil {
    43  		return nil, errUnknownBlock
    44  	}
    45  	return api.istanbul.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    46  }
    47  
    48  // GetSnapshotAtHash retrieves the state snapshot at a given block.
    49  func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
    50  	header := api.chain.GetHeaderByHash(hash)
    51  	if header == nil {
    52  		return nil, errUnknownBlock
    53  	}
    54  	return api.istanbul.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    55  }
    56  
    57  // GetValidators retrieves the list of authorized validators at the specified block.
    58  func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) {
    59  	// Retrieve the requested block number (or current if none requested)
    60  	var header *types.Header
    61  	if number == nil || *number == rpc.LatestBlockNumber {
    62  		header = api.chain.CurrentHeader()
    63  	} else {
    64  		header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
    65  	}
    66  	// Ensure we have an actually valid block and return the validators from its snapshot
    67  	if header == nil {
    68  		return nil, errUnknownBlock
    69  	}
    70  	snap, err := api.istanbul.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	return snap.validators(), nil
    75  }
    76  
    77  // GetValidatorsAtHash retrieves the state snapshot at a given block.
    78  func (api *API) GetValidatorsAtHash(hash common.Hash) ([]common.Address, error) {
    79  	header := api.chain.GetHeaderByHash(hash)
    80  	if header == nil {
    81  		return nil, errUnknownBlock
    82  	}
    83  	snap, err := api.istanbul.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	return snap.validators(), nil
    88  }
    89  
    90  // Candidates returns the current candidates the node tries to uphold and vote on.
    91  func (api *API) Candidates() map[common.Address]bool {
    92  	api.istanbul.candidatesLock.RLock()
    93  	defer api.istanbul.candidatesLock.RUnlock()
    94  
    95  	proposals := make(map[common.Address]bool)
    96  	for address, auth := range api.istanbul.candidates {
    97  		proposals[address] = auth
    98  	}
    99  	return proposals
   100  }
   101  
   102  // Propose injects a new authorization candidate that the validator will attempt to
   103  // push through.
   104  func (api *API) Propose(address common.Address, auth bool) {
   105  	api.istanbul.candidatesLock.Lock()
   106  	defer api.istanbul.candidatesLock.Unlock()
   107  
   108  	api.istanbul.candidates[address] = auth
   109  }
   110  
   111  // Discard drops a currently running candidate, stopping the validator from casting
   112  // further votes (either for or against).
   113  func (api *API) Discard(address common.Address) {
   114  	api.istanbul.candidatesLock.Lock()
   115  	defer api.istanbul.candidatesLock.Unlock()
   116  
   117  	delete(api.istanbul.candidates, address)
   118  }