7 "github.com/bytom/bytom/errors"
8 "github.com/bytom/bytom/math/checked"
9 "github.com/bytom/bytom/protocol"
10 "github.com/bytom/bytom/protocol/bc"
11 "github.com/bytom/bytom/protocol/bc/types"
12 "github.com/bytom/bytom/protocol/state"
16 errVerifySignature = errors.New("signature of verification message is invalid")
17 errPubKeyIsNotValidator = errors.New("pub key is not in validators of target checkpoint")
18 errVoteToGrowingCheckpoint = errors.New("validator publish vote to growing checkpoint")
19 errSameHeightInVerification = errors.New("validator publish two distinct votes for the same target height")
20 errSpanHeightInVerification = errors.New("validator publish vote within the span of its other votes")
21 errVoteToNonValidator = errors.New("pubKey of vote is not validator")
22 errGuarantyLessThanMinimum = errors.New("guaranty less than minimum")
23 errOverflow = errors.New("arithmetic overflow/underflow")
26 const minGuaranty = 1E14
28 // Casper is BFT based proof of stack consensus algorithm, it provides safety and liveness in theory,
29 // it's design mainly refers to https://github.com/ethereum/research/blob/master/papers/casper-basics/casper_basics.pdf
33 rollbackNotifyCh chan bc.Hash
36 // pubKey -> conflicting verifications
37 evilValidators map[string][]*Verification
40 // Best chain return the chain containing the justified checkpoint of the largest height
41 func (c *Casper) BestChain() (uint64, bc.Hash) {
45 // root is init justified
46 root := c.tree.checkpoint
47 bestHeight, bestHash, _ := chainOfMaxJustifiedHeight(c.tree, root.Height)
48 return bestHeight, bestHash
51 // Validators return the validators by specified block hash
52 // 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
53 func (c *Casper) Validators(blockHash *bc.Hash) ([]*state.Validator, error) {
54 hash, err := c.prevCheckpointHash(blockHash)
62 checkpoint, err := c.store.GetCheckpoint(hash)
67 return checkpoint.Validators(), nil
70 // AuthVerification verify whether the Verification is legal.
71 // the status of source checkpoint must justified, and an individual validator ν must not publish two distinct Verification
72 // ⟨ν,s1,t1,h(s1),h(t1)⟩ and ⟨ν,s2,t2,h(s2),h(t2)⟩, such that either:
73 // h(t1) = h(t2) OR h(s1) < h(s2) < h(t2) < h(t1)
74 func (c *Casper) AuthVerification(v *Verification) error {
75 if err := v.VerifySignature(); err != nil {
82 target, err := c.store.GetCheckpoint(&v.TargetHash)
87 // root of tree is the last finalized checkpoint
88 if target.Height < c.tree.checkpoint.Height {
89 // discard the verification message which height of target less than height of last finalized checkpoint
90 // is for simplify check the vote within the span of its other votes
94 source, err := c.store.GetCheckpoint(&v.SourceHash)
96 // the synchronization block is later than the arrival of the verification message
100 if source.Status == state.Growing || target.Status == state.Growing {
101 return errVoteToGrowingCheckpoint
104 if !target.ContainsValidator(v.PubKey) {
105 return errPubKeyIsNotValidator
108 if err := c.verifyVerification(v); err != nil {
112 supLink := target.AddSupLink(v.SourceHeight, v.SourceHash, v.PubKey, v.Signature)
113 if source.Status == state.Justified && supLink.Confirmed() {
114 c.setJustified(target)
116 if target.PrevHash == source.Hash {
117 if err := c.setFinalized(source); err != nil {
122 return c.store.SaveCheckpoints(source, target)
125 func (c *Casper) setJustified(checkpoint *state.Checkpoint) {
126 _, oldBestHash := c.BestChain()
127 checkpoint.Status = state.Justified
128 if _, bestHash := c.BestChain(); bestHash != oldBestHash {
129 c.rollbackNotifyCh <- bestHash
133 func (c *Casper) setFinalized(checkpoint *state.Checkpoint) error {
134 checkpoint.Status = state.Finalized
135 newRoot, err := c.tree.nodeByHash(checkpoint.Hash)
144 // EvilValidator represent a validator who broadcast two distinct verification that violate the commandment
145 type EvilValidator struct {
151 // EvilValidators return all evil validators
152 func (c *Casper) EvilValidators() []*EvilValidator {
156 var validators []*EvilValidator
157 for pubKey, verifications := range c.evilValidators {
158 validators = append(validators, &EvilValidator{
160 V1: verifications[0],
161 V2: verifications[1],
167 // ApplyBlock used to receive a new block from upper layer, it provides idempotence
168 // and parse the vote and mortgage from the transactions, then save to the checkpoint
169 // the tree of checkpoint will grow with the arrival of new blocks
170 func (c *Casper) ApplyBlock(block *types.Block) error {
174 if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
179 checkpoint, err := c.applyBlockToCheckpoint(block)
181 return errors.Wrap(err, "apply block to checkpoint")
184 for _, tx := range block.Transactions {
185 for _, input := range tx.Inputs {
186 if vetoInput, ok := input.TypedInput.(*types.VetoInput); ok {
187 if err := processVeto(vetoInput, checkpoint); err != nil {
192 if isGuarantyProgram(input.ControlProgram()) {
193 if err := processWithdrawal(decodeGuarantyArgs(input.ControlProgram()), checkpoint); err != nil {
199 for _, output := range tx.Outputs {
200 if _, ok := output.TypedOutput.(*types.VoteOutput); ok {
201 if err := processVote(output, checkpoint); err != nil {
206 if isGuarantyProgram(output.ControlProgram) {
207 if err := processGuaranty(decodeGuarantyArgs(output.ControlProgram), checkpoint); err != nil {
213 return c.store.SaveCheckpoints(checkpoint)
216 type guarantyArgs struct {
221 func isGuarantyProgram(program []byte) bool {
225 func decodeGuarantyArgs(program []byte) *guarantyArgs {
229 func processWithdrawal(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
230 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
231 guarantyNum := checkpoint.Guaranties[pubKey]
232 guarantyNum, ok := checked.SubUint64(guarantyNum, guarantyArgs.Amount)
237 checkpoint.Guaranties[pubKey] = guarantyNum
238 // TODO delete the evil validator when receive the confiscate transaction
242 func processGuaranty(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
243 if guarantyArgs.Amount < minGuaranty {
244 return errGuarantyLessThanMinimum
247 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
248 guarantyNum := checkpoint.Guaranties[pubKey]
249 guarantyNum, ok := checked.AddUint64(guarantyNum, guarantyArgs.Amount)
254 checkpoint.Guaranties[pubKey] = guarantyNum
258 func processVeto(input *types.VetoInput, checkpoint *state.Checkpoint) error {
259 pubKey := hex.EncodeToString(input.Vote)
260 voteNum := checkpoint.Votes[pubKey]
261 voteNum, ok := checked.SubUint64(voteNum, input.Amount)
266 checkpoint.Votes[pubKey] = voteNum
270 func processVote(output *types.TxOutput, checkpoint *state.Checkpoint) error {
271 voteOutput := output.TypedOutput.(*types.VoteOutput)
272 pubKey := hex.EncodeToString(voteOutput.Vote)
273 if checkpoint.Guaranties[pubKey] < minGuaranty {
274 return errVoteToNonValidator
277 voteNum := checkpoint.Votes[pubKey]
278 voteNum, ok := checked.AddUint64(voteNum, output.Amount)
283 checkpoint.Votes[pubKey] = voteNum
287 func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
288 node, err := c.tree.nodeByHash(block.PreviousBlockHash)
293 checkpoint := node.checkpoint
294 if mod := block.Height % state.BlocksOfEpoch; mod == 1 {
296 checkpoint = &state.Checkpoint{
297 PrevHash: parent.Hash,
298 StartTimestamp: block.Timestamp,
299 Status: state.Growing,
300 Votes: make(map[string]uint64),
301 Guaranties: make(map[string]uint64),
303 node.children = append(node.children, &treeNode{checkpoint: checkpoint})
305 checkpoint.Status = state.Unverified
308 checkpoint.Height = block.Height
309 checkpoint.Hash = block.Hash()
310 return checkpoint, nil
313 func (c *Casper) verifyVerification(v *Verification) error {
314 if err := c.verifySameHeight(v); err != nil {
318 return c.verifySpanHeight(v)
321 // a validator must not publish two distinct votes for the same target height
322 func (c *Casper) verifySameHeight(v *Verification) error {
323 checkpoints, err := c.store.GetCheckpointsByHeight(v.TargetHeight)
328 for _, checkpoint := range checkpoints {
329 for _, supLink := range checkpoint.SupLinks {
330 if signature, ok := supLink.Signatures[v.PubKey]; ok {
331 c.evilValidators[v.PubKey] = []*Verification{v, makeVerification(supLink, checkpoint, signature, v.PubKey)}
332 return errSameHeightInVerification
339 // a validator must not vote within the span of its other votes.
340 func (c *Casper) verifySpanHeight(v *Verification) error {
341 if c.tree.findOnlyOne(func(checkpoint *state.Checkpoint) bool {
342 if checkpoint.Height == v.TargetHeight {
346 for _, supLink := range checkpoint.SupLinks {
347 if signature, ok := supLink.Signatures[v.PubKey]; ok {
348 if (checkpoint.Height < v.TargetHeight && supLink.SourceHeight > v.SourceHeight) ||
349 (checkpoint.Height > v.TargetHeight && supLink.SourceHeight < v.SourceHeight) {
350 c.evilValidators[v.PubKey] = []*Verification{v, makeVerification(supLink, checkpoint, signature, v.PubKey)}
357 return errSpanHeightInVerification
362 func makeVerification(supLink *state.SupLink, checkpoint *state.Checkpoint, signature, pubKey string) *Verification {
363 return &Verification{
364 SourceHash: supLink.SourceHash,
365 TargetHash: checkpoint.Hash,
366 SourceHeight: supLink.SourceHeight,
367 TargetHeight: checkpoint.Height,
368 Signature: signature,
373 // justifiedHeight is the max justified height of checkpoint from node to root
374 func chainOfMaxJustifiedHeight(node *treeNode, justifiedHeight uint64) (uint64, bc.Hash, uint64) {
375 checkpoint := node.checkpoint
376 if checkpoint.Status == state.Justified {
377 justifiedHeight = checkpoint.Height
380 bestHeight, bestHash, maxJustifiedHeight := checkpoint.Height, checkpoint.Hash, justifiedHeight
381 for _, child := range node.children {
382 if height, hash, justified := chainOfMaxJustifiedHeight(child, justifiedHeight); justified >= maxJustifiedHeight {
383 bestHeight, bestHash, maxJustifiedHeight = height, hash, justified
386 return bestHeight, bestHash, maxJustifiedHeight
389 func (c *Casper) prevCheckpointHash(blockHash *bc.Hash) (*bc.Hash, error) {
391 block, err := c.store.GetBlockHeader(blockHash)
396 height := block.Height - 1
397 blockHash = &block.PreviousBlockHash
398 if height%state.BlocksOfEpoch == 0 {
399 return blockHash, nil