OSDN Git Service

add get-consensus-nodes api (#159)
[bytom/vapor.git] / protocol / state / vote_result.go
index acbd58f..c9059b2 100644 (file)
@@ -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"
@@ -28,18 +29,30 @@ func (c byVote) Less(i, j int) bool {
 }
 func (c byVote) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
 
+// seq 0 is the genesis block
+// seq 1 is the the block height 1, to block height RoundVoteBlockNums
+// seq 2 is the block height RoundVoteBlockNums + 1 to block height 2 * RoundVoteBlockNums
+// consensus node of the current round is the final result of previous round
+func CalcVoteSeq(blockHeight uint64) uint64 {
+       if blockHeight == 0 {
+               return 0
+       }
+       return (blockHeight-1)/consensus.RoundVoteBlockNums + 1
+}
+
 // VoteResult represents a snapshot of each round of DPOS voting
 // Seq indicates the sequence of current votes, which start from zero
 // NumOfVote indicates the number of votes each consensus node receives, the key of map represent public key
 // Finalized indicates whether this vote is finalized
 type VoteResult struct {
-       Seq           uint64
-       NumOfVote     map[string]uint64
-       LastBlockHash bc.Hash
+       Seq         uint64
+       NumOfVote   map[string]uint64
+       BlockHash   bc.Hash
+       BlockHeight uint64
 }
 
 func (v *VoteResult) ApplyBlock(block *types.Block) error {
-       if v.LastBlockHash != block.PreviousBlockHash {
+       if v.BlockHash != block.PreviousBlockHash {
                return errors.New("block parent hash is not equals last block hash of vote result")
        }
 
@@ -74,7 +87,9 @@ func (v *VoteResult) ApplyBlock(block *types.Block) error {
                }
        }
 
-       v.LastBlockHash = block.Hash()
+       v.BlockHash = block.Hash()
+       v.BlockHeight = block.Height
+       v.Seq = CalcVoteSeq(block.Height)
        return nil
 }
 
@@ -98,15 +113,28 @@ 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 {
-       if v.LastBlockHash != block.Hash() {
+       if v.BlockHash != block.Hash() {
                return errors.New("block hash is not equals last block hash of vote result")
        }
 
-       for _, tx := range block.Transactions {
+       for i := len(block.Transactions) - 1; i >= 0; i-- {
+               tx := block.Transactions[i]
                for _, input := range tx.Inputs {
                        unVoteInput, ok := input.TypedInput.(*types.UnvoteInput)
                        if !ok {
@@ -137,6 +165,26 @@ func (v *VoteResult) DetachBlock(block *types.Block) error {
                }
        }
 
-       v.LastBlockHash = block.PreviousBlockHash
+       v.BlockHash = block.PreviousBlockHash
+       v.BlockHeight = block.Height - 1
+       v.Seq = CalcVoteSeq(block.Height - 1)
        return nil
 }
+
+func (v *VoteResult) Fork() *VoteResult {
+       f := &VoteResult{
+               Seq:         v.Seq,
+               NumOfVote:   map[string]uint64{},
+               BlockHash:   v.BlockHash,
+               BlockHeight: v.BlockHeight,
+       }
+
+       for key, value := range v.NumOfVote {
+               f.NumOfVote[key] = value
+       }
+       return f
+}
+
+func (v *VoteResult) IsFinalize() bool {
+       return v.BlockHeight%consensus.RoundVoteBlockNums == 0
+}