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 }