6 log "github.com/sirupsen/logrus"
8 "github.com/bytom/bytom/common"
9 "github.com/bytom/bytom/errors"
10 "github.com/bytom/bytom/protocol/bc"
11 "github.com/bytom/bytom/protocol/state"
15 errPubKeyIsNotValidator = errors.New("pub key is not in validators of target checkpoint")
16 errVoteToGrowingCheckpoint = errors.New("validator publish vote to growing checkpoint")
17 errVoteToSameCheckpoint = errors.New("source height and target height in verification is equals")
18 errSameHeightInVerification = errors.New("validator publish two distinct votes for the same target height")
19 errSpanHeightInVerification = errors.New("validator publish vote within the span of its other votes")
20 errVoteToNonValidator = errors.New("pubKey of vote is not validator")
21 errGuarantyLessThanMinimum = errors.New("guaranty less than minimum")
22 errOverflow = errors.New("arithmetic overflow/underflow")
25 const minGuaranty = 1E14
27 // Casper is BFT based proof of stack consensus algorithm, it provides safety and liveness in theory,
28 // it's design mainly refers to https://github.com/ethereum/research/blob/master/papers/casper-basics/casper_basics.pdf
32 rollbackNotifyCh chan bc.Hash
33 newEpochCh chan bc.Hash
35 // pubKey -> conflicting verifications
36 evilValidators map[string][]*Verification
37 // block hash -> previous checkpoint hash
38 prevCheckpointCache *common.Cache
39 // block hash + pubKey -> verification
40 verificationCache *common.Cache
43 // NewCasper create a new instance of Casper
44 // argument checkpoints load the checkpoints from leveldb
45 // the first element of checkpoints must genesis checkpoint or the last finalized checkpoint in order to reduce memory space
46 // the others must be successors of first one
47 func NewCasper(store Store, checkpoints []*state.Checkpoint, rollbackNotifyCh chan bc.Hash) *Casper {
48 if checkpoints[0].Height != 0 && checkpoints[0].Status != state.Finalized {
49 log.Panic("first element of checkpoints must genesis or in finalized status")
53 tree: makeTree(checkpoints[0], checkpoints[1:]),
54 rollbackNotifyCh: rollbackNotifyCh,
55 newEpochCh: make(chan bc.Hash),
57 evilValidators: make(map[string][]*Verification),
58 prevCheckpointCache: common.NewCache(1024),
59 verificationCache: common.NewCache(1024),
61 go casper.authVerificationLoop()
65 // Best chain return the chain containing the justified checkpoint of the largest height
66 func (c *Casper) BestChain() (uint64, bc.Hash) {
73 func (c *Casper) bestChain() (uint64, bc.Hash) {
74 // root is init justified
75 root := c.tree.checkpoint
76 bestHeight, bestHash, _ := chainOfMaxJustifiedHeight(c.tree, root.Height)
77 return bestHeight, bestHash
80 // LastFinalized return the block height and block hash which is finalized ast last
81 func (c *Casper) LastFinalized() (uint64, bc.Hash) {
85 root := c.tree.checkpoint
86 return root.Height, root.Hash
89 // Validators return the validators by specified block hash
90 // e.g. if the block num of epoch is 100, and the block height corresponding to the block hash is 130, then will return the voting results of height in 0~100
91 func (c *Casper) Validators(blockHash *bc.Hash) (map[string]*state.Validator, error) {
92 checkpoint, err := c.prevCheckpoint(blockHash)
97 return checkpoint.Validators(), nil
100 func (c *Casper) prevCheckpoint(blockHash *bc.Hash) (*state.Checkpoint, error) {
101 hash, err := c.prevCheckpointHash(blockHash)
106 return c.store.GetCheckpoint(hash)
109 func (c *Casper) prevCheckpointByPrevHash(prevBlockHash *bc.Hash) (*state.Checkpoint, error) {
110 hash, err := c.prevCheckpointHashByPrevHash(prevBlockHash)
115 return c.store.GetCheckpoint(hash)
118 // EvilValidator represent a validator who broadcast two distinct verification that violate the commandment
119 type EvilValidator struct {
125 // EvilValidators return all evil validators
126 func (c *Casper) EvilValidators() []*EvilValidator {
130 var validators []*EvilValidator
131 for pubKey, verifications := range c.evilValidators {
132 validators = append(validators, &EvilValidator{
134 V1: verifications[0],
135 V2: verifications[1],
141 // justifiedHeight is the max justified height of checkpoint from node to root
142 func chainOfMaxJustifiedHeight(node *treeNode, justifiedHeight uint64) (uint64, bc.Hash, uint64) {
143 checkpoint := node.checkpoint
144 if checkpoint.Status == state.Justified {
145 justifiedHeight = checkpoint.Height
148 bestHeight, bestHash, maxJustifiedHeight := checkpoint.Height, checkpoint.Hash, justifiedHeight
149 for _, child := range node.children {
150 if height, hash, justified := chainOfMaxJustifiedHeight(child, justifiedHeight); justified >= maxJustifiedHeight {
151 bestHeight, bestHash, maxJustifiedHeight = height, hash, justified
154 return bestHeight, bestHash, maxJustifiedHeight
157 func (c *Casper) prevCheckpointHash(blockHash *bc.Hash) (*bc.Hash, error) {
158 if data, ok := c.prevCheckpointCache.Get(*blockHash); ok {
159 return data.(*bc.Hash), nil
162 block, err := c.store.GetBlockHeader(blockHash)
167 result, err := c.prevCheckpointHashByPrevHash(&block.PreviousBlockHash)
172 c.prevCheckpointCache.Add(*blockHash, result)
176 func (c *Casper) prevCheckpointHashByPrevHash(prevBlockHash *bc.Hash) (*bc.Hash, error) {
177 prevHash := prevBlockHash
179 prevBlock, err := c.store.GetBlockHeader(prevHash)
184 if prevBlock.Height%state.BlocksOfEpoch == 0 {
185 c.prevCheckpointCache.Add(*prevBlockHash, prevHash)
189 if data, ok := c.prevCheckpointCache.Get(*prevHash); ok {
190 c.prevCheckpointCache.Add(*prevBlockHash, data)
191 return data.(*bc.Hash), nil
194 prevHash = &prevBlock.PreviousBlockHash