6 "github.com/bytom/bytom/config"
7 "github.com/bytom/bytom/consensus"
8 "github.com/bytom/bytom/errors"
9 "github.com/bytom/bytom/protocol/bc"
10 "github.com/bytom/bytom/protocol/bc/types"
13 // CheckpointStatus represent current status of checkpoint
14 type CheckpointStatus uint8
17 // Growing means that the checkpoint has not ended the current epoch
18 Growing CheckpointStatus = iota
20 // Unjustified means thant the checkpoint has ended the current epoch, but not been justified
23 // Justified if checkpoint is the root, or there exists a super link c′ → c where c′ is justified
26 // Finalized if checkpoint c is justified and there is a sup link c→c′ where c′is a direct child of c
30 var errIncreaseCheckpoint = errors.New("invalid block for increase checkpoint")
32 // SupLink is an ordered pair of checkpoints (a, b), also written a → b,
33 // such that at least 2/3 of validators have published votes with source a and target b.
37 Signatures [consensus.MaxNumOfValidators]string
40 // IsMajority if at least 2/3 of validators have published votes with sup link
41 func (s *SupLink) IsMajority(numOfValidators int) bool {
43 for _, signature := range s.Signatures {
48 return numOfSignatures > numOfValidators*2/3
51 // Checkpoint represent the block/hash under consideration for finality for a given epoch.
52 // This block is the last block of the previous epoch. Rather than dealing with every block,
53 // Casper only considers checkpoints for finalization. When a checkpoint is explicitly finalized,
54 // all ancestor blocks of the checkpoint are implicitly finalized.
55 type Checkpoint struct {
59 // only save in the memory, not be persisted
60 Parent *Checkpoint `json:"-"`
62 SupLinks []*SupLink `json:"-"`
63 Status CheckpointStatus
65 Rewards map[string]uint64 // controlProgram -> num of reward
66 Votes map[string]uint64 // pubKey -> num of vote
68 MergeCheckpoint func(bc.Hash) `json:"-"`
71 // NewCheckpoint create a new checkpoint instance
72 func NewCheckpoint(parent *Checkpoint) *Checkpoint {
73 checkpoint := &Checkpoint{
74 ParentHash: parent.Hash,
77 Rewards: make(map[string]uint64),
78 Votes: make(map[string]uint64),
81 for pubKey, num := range parent.Votes {
82 checkpoint.Votes[pubKey] = num
87 // AddVerification add a valid verification to checkpoint's supLink
88 func (c *Checkpoint) AddVerification(sourceHash bc.Hash, sourceHeight uint64, validatorOrder int, signature string) *SupLink {
89 for _, supLink := range c.SupLinks {
90 if supLink.SourceHash == sourceHash {
91 supLink.Signatures[validatorOrder] = signature
96 SourceHeight: sourceHeight,
97 SourceHash: sourceHash,
99 supLink.Signatures[validatorOrder] = signature
100 c.SupLinks = append(c.SupLinks, supLink)
104 // ContainsVerification return whether the specified validator has add verification to current checkpoint
105 // sourceHash not as filter if is nil,
106 func (c *Checkpoint) ContainsVerification(validatorOrder int, sourceHash *bc.Hash) bool {
107 for _, supLink := range c.SupLinks {
108 if (sourceHash == nil || supLink.SourceHash == *sourceHash) && supLink.Signatures[validatorOrder] != "" {
115 // Increase will increase the height of checkpoint
116 func (c *Checkpoint) Increase(block *types.Block) error {
120 prevHash = c.ParentHash
123 if block.PreviousBlockHash != prevHash {
124 return errIncreaseCheckpoint
127 c.Hash = block.Hash()
128 c.Height = block.Height
129 c.Timestamp = block.Timestamp
130 c.MergeCheckpoint(c.Hash)
134 // Validator represent the participants of the PoS network
135 // Responsible for block generation and verification
136 type Validator struct {
142 // Validators return next epoch of validators, if the status of checkpoint is growing, return empty
143 func (c *Checkpoint) Validators() map[string]*Validator {
144 var validators []*Validator
145 if c.Status == Growing {
149 for pubKey, voteNum := range c.Votes {
150 if voteNum >= consensus.ActiveNetParams.MinValidatorVoteNum {
151 validators = append(validators, &Validator{
153 Vote: c.Votes[pubKey],
158 if len(validators) == 0 {
159 return federationValidators()
162 sort.Slice(validators, func(i, j int) bool {
163 numI := validators[i].Vote
164 numJ := validators[j].Vote
168 return validators[i].PubKey > validators[j].PubKey
171 result := make(map[string]*Validator)
172 for i := 0; i < len(validators) && i < consensus.MaxNumOfValidators; i++ {
173 validator := validators[i]
175 result[validator.PubKey] = validator
180 func federationValidators() map[string]*Validator {
181 validators := map[string]*Validator{}
182 for i, xPub := range config.CommonConfig.Federation.Xpubs {
183 validators[xPub.String()] = &Validator{PubKey: xPub.String(), Order: i}