From 0bd22d212b767702bd1c99edb05d5f3a57cb572c Mon Sep 17 00:00:00 2001 From: muscle_boy Date: Wed, 12 Jun 2019 16:38:28 +0800 Subject: [PATCH] add get-consensus-nodes api (#159) * add get-consensus-nodes api * add get vote result api * bug fix * remove is consensus node * bug fix * remove is consensus * add sort for get vote result api * rename --- api/api.go | 2 ++ api/bbft.go | 47 ++++++++++++++++++++++++++++++++++++++ protocol/bbft.go | 8 ++++++- protocol/consensus_node_manager.go | 47 +++++++++++++++++--------------------- protocol/state/vote_result.go | 15 +++++++++++- wallet/indexer.go | 8 +++---- 6 files changed, 95 insertions(+), 32 deletions(-) create mode 100644 api/bbft.go diff --git a/api/api.go b/api/api.go index 074e0380..88f43e59 100644 --- a/api/api.go +++ b/api/api.go @@ -301,6 +301,8 @@ func (a *API) buildHandler() { m.Handle("/get-merkle-proof", jsonHandler(a.getMerkleProof)) + m.Handle("/get-vote-result", jsonHandler(a.getVoteResult)) + m.HandleFunc("/websocket-subscribe", a.websocketHandler) handler := walletHandler(m, walletEnable) diff --git a/api/bbft.go b/api/bbft.go new file mode 100644 index 00000000..83cad1e7 --- /dev/null +++ b/api/bbft.go @@ -0,0 +1,47 @@ +package api + +import ( + "sort" + + chainjson "github.com/vapor/encoding/json" +) + +type voteInfo struct { + Vote string `json:"vote"` + VoteNum uint64 `json:"vote_number"` +} + +type voteInfoSlice []*voteInfo +func (v voteInfoSlice) Len() int { return len(v) } +func (v voteInfoSlice) Less(i, j int) bool { return v[i].VoteNum > v[j].VoteNum } +func (v voteInfoSlice) Swap(i, j int) { v[i], v[j] = v[j], v[i] } + +func (a *API) getVoteResult(req struct { + BlockHash chainjson.HexBytes `json:"block_hash"` + BlockHeight uint64 `json:"block_height"` +}) Response { + blockHash := hexBytesToHash(req.BlockHash) + if len(req.BlockHash) != 32 { + blockHeader, err := a.chain.GetHeaderByHeight(req.BlockHeight) + if err != nil { + return NewErrorResponse(err) + } + + blockHash = blockHeader.Hash() + } + + voteResult, err := a.chain.GetVoteResultByHash(&blockHash) + if err != nil { + return NewErrorResponse(err) + } + + voteInfos := []*voteInfo{} + for pubKey, voteNum := range voteResult.NumOfVote { + voteInfos = append(voteInfos, &voteInfo{ + Vote: pubKey, + VoteNum: voteNum, + }) + } + sort.Sort(voteInfoSlice(voteInfos)) + return NewSuccessResponse(voteInfos) +} diff --git a/protocol/bbft.go b/protocol/bbft.go index a0e133b0..798f62da 100644 --- a/protocol/bbft.go +++ b/protocol/bbft.go @@ -45,7 +45,13 @@ func (c *Chain) isIrreversible(blockNode *state.BlockNode) bool { return signCount > len(consensusNodes)*2/3 } -// NextLeaderTime returns the start time of the specified public key as the next leader node +// GetVoteResultByHash return vote result by block hash +func (c *Chain) GetVoteResultByHash(blockHash *bc.Hash) (*state.VoteResult, error) { + blockNode := c.index.GetNode(blockHash) + return c.consensusNodeManager.getVoteResult(state.CalcVoteSeq(blockNode.Height), blockNode) +} + +// IsBlocker returns whether the consensus node is a blocker at the specified time func (c *Chain) IsBlocker(prevBlockHash *bc.Hash, pubkey string, timeStamp uint64) (bool, error) { return c.consensusNodeManager.isBlocker(prevBlockHash, pubkey, timeStamp) } diff --git a/protocol/consensus_node_manager.go b/protocol/consensus_node_manager.go index 136fb6ae..3b5f9edb 100644 --- a/protocol/consensus_node_manager.go +++ b/protocol/consensus_node_manager.go @@ -1,7 +1,6 @@ package protocol import ( - "github.com/vapor/config" "github.com/vapor/consensus" "github.com/vapor/errors" "github.com/vapor/protocol/bc" @@ -92,34 +91,30 @@ func (c *consensusNodeManager) getConsensusNodes(prevBlockHash *bc.Hash) (map[st preSeq = bestSeq } - voteResult, err := c.store.GetVoteResult(preSeq) - if err != nil { - return nil, err - } - lastBlockNode, err := c.getPrevRoundLastBlock(prevBlockHash) if err != nil { return nil, err } - if err := c.reorganizeVoteResult(voteResult, lastBlockNode); err != nil { - return nil, err - } - - result, err := voteResult.ConsensusNodes() + voteResult, err := c.getVoteResult(preSeq, lastBlockNode) if err != nil { return nil, err } - if len(result) != 0 { - return result, nil - } - return federationNodes(), nil + return voteResult.ConsensusNodes() } func (c *consensusNodeManager) getBestVoteResult() (*state.VoteResult, error) { blockNode := c.blockIndex.BestNode() seq := state.CalcVoteSeq(blockNode.Height) + return c.getVoteResult(seq, blockNode) +} + +// getVoteResult return the vote result +// seq represent the sequence of vote +// blockNode represent the chain in which the result of the vote is located +// Voting results need to be adjusted according to the chain +func (c *consensusNodeManager) getVoteResult(seq uint64, blockNode *state.BlockNode) (*state.VoteResult, error) { voteResult, err := c.store.GetVoteResult(seq) if err != nil { return nil, err @@ -136,12 +131,20 @@ func (c *consensusNodeManager) reorganizeVoteResult(voteResult *state.VoteResult mainChainNode := c.blockIndex.GetNode(&voteResult.BlockHash) var attachNodes []*state.BlockNode var detachNodes []*state.BlockNode - for forkChainNode := node; mainChainNode != forkChainNode; forkChainNode = forkChainNode.Parent { - if forkChainNode.Height == mainChainNode.Height { + for forkChainNode := node; mainChainNode != forkChainNode; { + var forChainRollback, mainChainRollBack bool + if forChainRollback = forkChainNode.Height >= mainChainNode.Height; forChainRollback { + attachNodes = append([]*state.BlockNode{forkChainNode}, attachNodes...) + } + if mainChainRollBack = forkChainNode.Height <= mainChainNode.Height; mainChainRollBack { detachNodes = append(detachNodes, mainChainNode) + } + if forChainRollback { + forkChainNode = forkChainNode.Parent + } + if mainChainRollBack { mainChainNode = mainChainNode.Parent } - attachNodes = append([]*state.BlockNode{forkChainNode}, attachNodes...) } for _, node := range detachNodes { @@ -167,11 +170,3 @@ func (c *consensusNodeManager) reorganizeVoteResult(voteResult *state.VoteResult } return nil } - -func federationNodes() map[string]*state.ConsensusNode { - voteResult := map[string]*state.ConsensusNode{} - for i, xpub := range config.CommonConfig.Federation.Xpubs { - voteResult[xpub.String()] = &state.ConsensusNode{XPub: xpub, VoteNum: 0, Order: uint64(i)} - } - return voteResult -} diff --git a/protocol/state/vote_result.go b/protocol/state/vote_result.go index e241bcff..c9059b2c 100644 --- a/protocol/state/vote_result.go +++ b/protocol/state/vote_result.go @@ -5,6 +5,7 @@ import ( "sort" "github.com/vapor/consensus" + "github.com/vapor/config" "github.com/vapor/crypto/ed25519/chainkd" "github.com/vapor/errors" "github.com/vapor/math/checked" @@ -112,7 +113,19 @@ func (v *VoteResult) ConsensusNodes() (map[string]*ConsensusNode, error) { nodes[i].Order = uint64(i) result[nodes[i].XPub.String()] = nodes[i] } - return result, nil + + if len(result) != 0 { + return result, nil + } + return federationNodes(), nil +} + +func federationNodes() map[string]*ConsensusNode { + voteResult := map[string]*ConsensusNode{} + for i, xpub := range config.CommonConfig.Federation.Xpubs { + voteResult[xpub.String()] = &ConsensusNode{XPub: xpub, VoteNum: 0, Order: uint64(i)} + } + return voteResult } func (v *VoteResult) DetachBlock(block *types.Block) error { diff --git a/wallet/indexer.go b/wallet/indexer.go index 47a8f47c..bc61dc33 100644 --- a/wallet/indexer.go +++ b/wallet/indexer.go @@ -383,14 +383,14 @@ func (w *Wallet) GetAccountVotes(accountID string, id string) ([]AccountVotes, e type voteDetail struct { Vote string `json:"vote"` - VoteAmount uint64 `json:"vote_amount"` + VoteNumber uint64 `json:"vote_number"` } // AccountVotes account vote type AccountVotes struct { AccountID string `json:"account_id"` Alias string `json:"account_alias"` - TotalVoteAmount uint64 `json:"total_vote_amount"` + TotalVoteNumber uint64 `json:"total_vote_number"` VoteDetails []voteDetail `json:"vote_details"` } @@ -429,7 +429,7 @@ func (w *Wallet) indexVotes(accountUTXOs []*account.UTXO) ([]AccountVotes, error for _, xpub := range sortedXpub { voteDetails = append(voteDetails, voteDetail{ Vote: xpub, - VoteAmount: accVote[id][xpub], + VoteNumber: accVote[id][xpub], }) voteTotal += accVote[id][xpub] } @@ -438,7 +438,7 @@ func (w *Wallet) indexVotes(accountUTXOs []*account.UTXO) ([]AccountVotes, error Alias: alias, AccountID: id, VoteDetails: voteDetails, - TotalVoteAmount: voteTotal, + TotalVoteNumber: voteTotal, }) } -- 2.11.0