"sort"
"github.com/vapor/consensus"
+ "github.com/vapor/config"
"github.com/vapor/crypto/ed25519/chainkd"
"github.com/vapor/errors"
"github.com/vapor/math/checked"
}
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")
}
}
}
- v.LastBlockHash = block.Hash()
+ v.BlockHash = block.Hash()
+ v.BlockHeight = block.Height
+ v.Seq = CalcVoteSeq(block.Height)
return nil
}
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 {
}
}
- 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
+}