4 "github.com/vapor/consensus"
5 "github.com/vapor/errors"
6 "github.com/vapor/protocol/bc"
7 "github.com/vapor/protocol/bc/types"
8 "github.com/vapor/protocol/state"
12 errNotFoundConsensusNode = errors.New("can not found consensus node")
13 errNotFoundBlockNode = errors.New("can not find block node")
16 func (c *Chain) getConsensusNode(prevBlockHash *bc.Hash, pubkey string) (*state.ConsensusNode, error) {
17 consensusNodeMap, err := c.getConsensusNodes(prevBlockHash)
22 node, exist := consensusNodeMap[pubkey]
24 return nil, errNotFoundConsensusNode
29 // GetBlocker return blocker by specified timestamp
30 func (c *Chain) GetBlocker(prevBlockHash *bc.Hash, timeStamp uint64) (string, error) {
31 consensusNodeMap, err := c.getConsensusNodes(prevBlockHash)
36 prevVoteRoundLastBlock, err := c.getPrevRoundLastBlock(prevBlockHash)
41 startTimestamp := prevVoteRoundLastBlock.Timestamp + consensus.BlockTimeInterval
42 order := getBlockerOrder(startTimestamp, timeStamp, uint64(len(consensusNodeMap)))
43 for xPub, consensusNode := range consensusNodeMap {
44 if consensusNode.Order == order {
50 return "", errors.New("can not find blocker by given timestamp")
53 func getBlockerOrder(startTimestamp, blockTimestamp, numOfConsensusNode uint64) uint64 {
54 // One round of product block time for all consensus nodes
55 roundBlockTime := consensus.BlockNumEachNode * numOfConsensusNode * consensus.BlockTimeInterval
56 // The start time of the last round of product block
57 lastRoundStartTime := startTimestamp + (blockTimestamp-startTimestamp)/roundBlockTime*roundBlockTime
59 return (blockTimestamp - lastRoundStartTime) / (consensus.BlockNumEachNode * consensus.BlockTimeInterval)
62 func (c *Chain) getPrevRoundLastBlock(prevBlockHash *bc.Hash) (*types.BlockHeader, error) {
63 blockHeader, err := c.store.GetBlockHeader(prevBlockHash)
65 return nil, errNotFoundBlockNode
68 for blockHeader.Height%consensus.RoundVoteBlockNums != 0 {
69 blockHeader, err = c.store.GetBlockHeader(&blockHeader.PreviousBlockHash)
74 return blockHeader, nil
77 func (c *Chain) getConsensusNodes(prevBlockHash *bc.Hash) (map[string]*state.ConsensusNode, error) {
78 prevBlockHeader, err := c.store.GetBlockHeader(prevBlockHash)
80 return nil, errNotFoundBlockNode
83 bestBlockHeader := c.bestBlockHeader
84 preSeq := state.CalcVoteSeq(prevBlockHeader.Height+1) - 1
85 if bestSeq := state.CalcVoteSeq(bestBlockHeader.Height); preSeq > bestSeq {
89 lastBlockHeader, err := c.getPrevRoundLastBlock(prevBlockHash)
94 voteResult, err := c.getVoteResult(preSeq, lastBlockHeader)
99 return voteResult.ConsensusNodes()
102 func (c *Chain) getBestVoteResult() (*state.VoteResult, error) {
103 bestBlockHeader := c.bestBlockHeader
104 seq := state.CalcVoteSeq(bestBlockHeader.Height)
105 return c.getVoteResult(seq, bestBlockHeader)
108 // getVoteResult return the vote result
109 // seq represent the sequence of vote
110 // blockHeader represent the chain in which the result of the vote is located
111 // Voting results need to be adjusted according to the chain
112 func (c *Chain) getVoteResult(seq uint64, blockHeader *types.BlockHeader) (*state.VoteResult, error) {
113 voteResult, err := c.store.GetVoteResult(seq)
118 if err := c.reorganizeVoteResult(voteResult, blockHeader); err != nil {
122 return voteResult, nil
125 func (c *Chain) reorganizeVoteResult(voteResult *state.VoteResult, blockHeader *types.BlockHeader) error {
126 mainChainBlockHeader, err := c.store.GetBlockHeader(&voteResult.BlockHash)
131 attachBlockHeaders, detachBlockHeaders, err := c.calcReorganizeChain(blockHeader, mainChainBlockHeader)
136 for _, bh := range detachBlockHeaders {
137 blockHash := bh.Hash()
138 block, err := c.store.GetBlock(&blockHash)
143 if err := voteResult.DetachBlock(block); err != nil {
148 for _, bh := range attachBlockHeaders {
149 blockHash := bh.Hash()
150 block, err := c.store.GetBlock(&blockHash)
155 if err := voteResult.ApplyBlock(block); err != nil {