github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/backend/api.go (about) 1 package backend 2 3 import ( 4 "math/big" 5 "sort" 6 7 "github.com/quickchainproject/quickchain/common" 8 "github.com/quickchainproject/quickchain/consensus" 9 "github.com/quickchainproject/quickchain/core/types" 10 "github.com/quickchainproject/quickchain/rpc" 11 ) 12 13 // API is a user facing RPC API to dump BFT state 14 type API struct { 15 chain consensus.ChainReader 16 bft *backend 17 } 18 19 // GetSnapshot retrieves the state snapshot at a given block. 20 func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { 21 // Retrieve the requested block number (or current if none requested) 22 var header *types.Header 23 if number == nil || *number == rpc.LatestBlockNumber { 24 header = api.chain.CurrentHeader() 25 } else { 26 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 27 } 28 // Ensure we have an actually valid block and return its snapshot 29 if header == nil { 30 return nil, errUnknownBlock 31 } 32 return api.bft.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 33 } 34 35 // GetSnapshotAtHash retrieves the state snapshot at a given block. 36 func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { 37 header := api.chain.GetHeaderByHash(hash) 38 if header == nil { 39 return nil, errUnknownBlock 40 } 41 return api.bft.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 42 } 43 44 // GetValidators retrieves the list of authorized validators at the specified block. 45 func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) { 46 // Retrieve the requested block number (or current if none requested) 47 var header *types.Header 48 if number == nil || *number == rpc.LatestBlockNumber { 49 header = api.chain.CurrentHeader() 50 } else { 51 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 52 } 53 // Ensure we have an actually valid block and return the validators from its snapshot 54 if header == nil { 55 return nil, errUnknownBlock 56 } 57 snap, err := api.bft.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 58 if err != nil { 59 return nil, err 60 } 61 return snap.validators(), nil 62 } 63 64 // GetValidatorsAtHash retrieves the state snapshot at a given block. 65 func (api *API) GetValidatorsAtHash(hash common.Hash) ([]common.Address, error) { 66 header := api.chain.GetHeaderByHash(hash) 67 if header == nil { 68 return nil, errUnknownBlock 69 } 70 snap, err := api.bft.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 // Candidates returns the current candidates the node tries to uphold and vote on. 78 func (api *API) Candidates() map[common.Address]bool { 79 api.bft.candidatesLock.RLock() 80 defer api.bft.candidatesLock.RUnlock() 81 82 proposals := make(map[common.Address]bool) 83 for address, auth := range api.bft.candidates { 84 proposals[address] = auth 85 } 86 return proposals 87 } 88 89 // Propose injects a new authorization candidate that the validator will attempt to 90 // push through. 91 func (api *API) Propose(address common.Address, auth bool) { 92 api.bft.candidatesLock.Lock() 93 defer api.bft.candidatesLock.Unlock() 94 95 api.bft.candidates[address] = auth 96 } 97 98 // Discard drops a currently running candidate, stopping the validator from casting 99 // further votes (either for or against). 100 func (api *API) Discard(address common.Address) { 101 api.bft.candidatesLock.Lock() 102 defer api.bft.candidatesLock.Unlock() 103 104 delete(api.bft.candidates, address) 105 } 106 107 //copy from dpos.api 108 // GetDposValidators retrieves the list of the validators at specified block 109 func (api *API) GetDposValidators(number *rpc.BlockNumber) ([]common.Address, error) { 110 var header *types.Header 111 if number == nil || *number == rpc.LatestBlockNumber { 112 header = api.chain.CurrentHeader() 113 } else { 114 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 115 } 116 if header == nil { 117 return nil, errUnknownBlock 118 } 119 120 dposContext, err := types.NewDposContextFromProto(api.bft.db, header.DposContext) 121 if err != nil { 122 return nil, err 123 } 124 validators, err := dposContext.GetValidators() 125 if err != nil { 126 return nil, err 127 } 128 return validators, nil 129 } 130 131 // GetCandidates retrieves maxcnt result of the list of the candidates at specified block 132 func (api *API) GetDposCandidates(maxcnt, number *rpc.BlockNumber) ([]types.CandidateContext, error) { 133 var header *types.Header 134 if number == nil || *number == rpc.LatestBlockNumber { 135 header = api.chain.CurrentHeader() 136 } else { 137 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 138 } 139 if header == nil { 140 return nil, errUnknownBlock 141 } 142 143 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 144 if err != nil { 145 return nil, err 146 } 147 candidates, err := dposContext.GetCandidates() 148 if err != nil { 149 return nil, err 150 } 151 sort.Sort(types.SortCandidateContexts(candidates)) 152 if maxcnt == nil { 153 return candidates, nil 154 } 155 index := int(maxcnt.Int64()) 156 if int(maxcnt.Int64()) > len(candidates) { 157 index = len(candidates) 158 } 159 return candidates[:index], nil 160 } 161 162 // GetDposCandidates retrieves the list of the candidates at specified block 163 func (api *API) GetDposCandidate(addr common.Address, number *rpc.BlockNumber) (types.CandidateContext, error) { 164 var header *types.Header 165 var cc types.CandidateContext 166 if number == nil || *number == rpc.LatestBlockNumber { 167 header = api.chain.CurrentHeader() 168 } else { 169 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 170 } 171 if header == nil { 172 return cc, errUnknownBlock 173 } 174 175 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 176 if err != nil { 177 return cc, err 178 } 179 candidatecontext, err := dposContext.GetCandidateContext(addr) 180 if err != nil { 181 return cc, err 182 } 183 return candidatecontext, nil 184 } 185 186 func (api *API) GetSortableAddresses(number *rpc.BlockNumber) (types.SortableAddresses, error) { 187 var header *types.Header 188 if number == nil || *number == rpc.LatestBlockNumber { 189 header = api.chain.CurrentHeader() 190 } else { 191 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 192 } 193 if header == nil { 194 return nil, errUnknownBlock 195 } 196 197 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 198 if err != nil { 199 return nil, err 200 } 201 sa, err := dposContext.GetSortableAddresses() 202 if err != nil { 203 return nil, err 204 } 205 return sa, nil 206 } 207 208 // GetMintCnt retrieves the mint cnt of the validator at specified block 209 func (api *API) GetMintCnt(addr common.Address, number *rpc.BlockNumber) (int64, error) { 210 var header *types.Header 211 cnt := int64(0) 212 if number == nil || *number == rpc.LatestBlockNumber { 213 header = api.chain.CurrentHeader() 214 } else { 215 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 216 } 217 if header == nil { 218 return cnt, errUnknownBlock 219 } 220 221 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 222 if err != nil { 223 return cnt, err 224 } 225 cnt = dposContext.GetMintCnt(addr) 226 return cnt, nil 227 } 228 229 // GetMintCnt retrieves maxcnt result of the mint cnt of all validators at specified block 230 func (api *API) GetMintCnts(maxcnt, number *rpc.BlockNumber) ([]types.MintCntAddress, error) { 231 var header *types.Header 232 ma := make([]types.MintCntAddress, 0) 233 if number == nil || *number == rpc.LatestBlockNumber { 234 header = api.chain.CurrentHeader() 235 } else { 236 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 237 } 238 if header == nil { 239 return ma, errUnknownBlock 240 } 241 242 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 243 if err != nil { 244 return ma, err 245 } 246 ma, err = dposContext.GetMintCnts() 247 sort.Sort(types.SortableMintCntAddresses(ma)) 248 if maxcnt == nil { 249 return ma, err 250 } 251 index := int(maxcnt.Int64()) 252 if int(maxcnt.Int64()) > len(ma) { 253 index = len(ma) 254 } 255 return ma[:index], nil 256 } 257 258 // GetVote retrieves delegator to candidate at specified block 259 func (api *API) GetVote(addr common.Address, number *rpc.BlockNumber) (map[string]types.VoteContext, error) { 260 var header *types.Header 261 vote := make(map[string]types.VoteContext) 262 if number == nil || *number == rpc.LatestBlockNumber { 263 header = api.chain.CurrentHeader() 264 } else { 265 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 266 } 267 if header == nil { 268 return vote, errUnknownBlock 269 } 270 271 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 272 if err != nil { 273 return vote, err 274 } 275 return dposContext.GetVote(addr) 276 } 277 278 // GetVotes retrieves all delegator to their candidate at specified block 279 func (api *API) GetVotes(number *rpc.BlockNumber) (map[string]types.VoteContext, error) { 280 var header *types.Header 281 votes := make(map[string]types.VoteContext) 282 283 if number == nil || *number == rpc.LatestBlockNumber { 284 header = api.chain.CurrentHeader() 285 } else { 286 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 287 } 288 if header == nil { 289 return votes, errUnknownBlock 290 } 291 292 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 293 if err != nil { 294 return votes, err 295 } 296 return dposContext.GetVotes() 297 } 298 299 // GetCFDs retrieves all candidates from their delegates at specified block 300 func (api *API) GetCFDs(number *rpc.BlockNumber) (map[string]map[string]*big.Int, error) { 301 var header *types.Header 302 cfd := make(map[string]map[string]*big.Int) 303 304 if number == nil || *number == rpc.LatestBlockNumber { 305 header = api.chain.CurrentHeader() 306 } else { 307 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 308 } 309 if header == nil { 310 return cfd, errUnknownBlock 311 } 312 313 dposContext, err := types.NewDposContextFromProto(api.bft.DB(), header.DposContext) 314 if err != nil { 315 return cfd, err 316 } 317 return dposContext.GetCFDs() 318 }