4 "github.com/sirupsen/logrus"
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"
11 "github.com/bytom/bytom/protocol/state"
14 type ApplyBlockReply struct {
15 Verification *Verification
19 // ApplyBlock used to receive a new block from upper layer, it provides idempotence
20 // and parse the vote and mortgage from the transactions, then save to the checkpoint
21 // the tree of checkpoint will grow with the arrival of new blocks
22 // it will return verification when an epoch is reached and the current node is the validator, otherwise return nil
23 // the chain module must broadcast the verification
24 func (c *Casper) ApplyBlock(block *types.Block) (*ApplyBlockReply, error) {
25 if block.Height%consensus.ActiveNetParams.BlocksOfEpoch == 1 {
26 c.newEpochCh <- block.PreviousBlockHash
31 if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
32 return &ApplyBlockReply{BestHash: c.bestChain()}, nil
35 target, err := c.applyBlockToCheckpoint(block)
37 return nil, errors.Wrap(err, "apply block to checkpoint")
40 validators, err := c.Validators(&target.Hash)
45 verification, err := c.applyMyVerification(target, block, validators)
50 affectedCheckpoints, err := c.applySupLinks(target, block.SupLinks, validators)
55 return &ApplyBlockReply{Verification: verification, BestHash: c.bestChain()}, c.saveCheckpoints(affectedCheckpoints)
58 func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
59 node, err := c.checkpointNodeByHash(block.PreviousBlockHash)
64 checkpoint := node.Checkpoint
65 if mod := block.Height % consensus.ActiveNetParams.BlocksOfEpoch; mod == 1 {
67 checkpoint = state.NewCheckpoint(parent)
68 node.addChild(&treeNode{Checkpoint: checkpoint})
71 return checkpoint, checkpoint.Increase(block)
74 func (c *Casper) checkpointNodeByHash(blockHash bc.Hash) (*treeNode, error) {
75 node, err := c.tree.nodeByHash(blockHash)
77 logrus.WithFields(logrus.Fields{"err": err, "module": logModule}).Error("fail find checkpoint, start to reorganize checkpoint")
78 return c.replayCheckpoint(blockHash)
84 func (c *Casper) replayCheckpoint(hash bc.Hash) (*treeNode, error) {
86 var attachBlocks []*types.Block
88 prevBlock, err := c.store.GetBlock(&prevHash)
93 if prevBlock.Height%consensus.ActiveNetParams.BlocksOfEpoch == 0 {
97 attachBlocks = append([]*types.Block{prevBlock}, attachBlocks...)
98 prevHash = prevBlock.PreviousBlockHash
101 parent, err := c.tree.nodeByHash(prevHash)
106 node := &treeNode{Checkpoint: state.NewCheckpoint(parent.Checkpoint)}
107 parent.addChild(node)
108 for _, attachBlock := range attachBlocks {
109 if err := node.Increase(attachBlock); err != nil {
116 // applySupLinks copy the block's supLink to the checkpoint
117 func (c *Casper) applySupLinks(target *state.Checkpoint, supLinks []*types.SupLink, validators map[string]*state.Validator) ([]*state.Checkpoint, error) {
118 affectedCheckpoints := []*state.Checkpoint{target}
119 if target.Height%consensus.ActiveNetParams.BlocksOfEpoch != 0 {
120 return affectedCheckpoints, nil
123 for _, supLink := range supLinks {
124 var validVerifications []*Verification
125 for _, v := range supLinkToVerifications(supLink, validators, target.Hash, target.Height) {
126 if validate(v) == nil && c.verifyVerification(v, validators[v.PubKey].Order) == nil {
127 validVerifications = append(validVerifications, v)
131 checkpoints, err := c.addVerificationToCheckpoint(target, validators, validVerifications...)
136 affectedCheckpoints = append(affectedCheckpoints, checkpoints...)
138 return affectedCheckpoints, nil
141 func (c *Casper) applyMyVerification(target *state.Checkpoint, block *types.Block, validators map[string]*state.Validator) (*Verification, error) {
142 v, err := c.myVerification(target, validators)
151 block.SupLinks.AddSupLink(v.SourceHeight, v.SourceHash, v.Signature, validators[v.PubKey].Order)
152 return v, c.store.SaveBlockHeader(&block.BlockHeader)
155 func (c *Casper) myVerification(target *state.Checkpoint, validators map[string]*state.Validator) (*Verification, error) {
156 if target.Height%consensus.ActiveNetParams.BlocksOfEpoch != 0 {
160 pubKey := config.CommonConfig.PrivateKey().XPub().String()
161 if _, ok := validators[pubKey]; !ok {
165 validatorOrder := validators[pubKey].Order
166 if target.ContainsVerification(validatorOrder, nil) {
170 if source := c.lastJustifiedCheckpoint(target); source != nil {
172 SourceHash: source.Hash,
173 TargetHash: target.Hash,
174 SourceHeight: source.Height,
175 TargetHeight: target.Height,
179 prvKey := config.CommonConfig.PrivateKey()
180 if err := v.Sign(*prvKey); err != nil {
184 if err := c.verifyVerification(v, validatorOrder); err != nil {
193 func (c *Casper) lastJustifiedCheckpoint(branch *state.Checkpoint) *state.Checkpoint {
194 parent := branch.Parent
196 switch parent.Status {
197 case state.Finalized:
199 case state.Justified:
202 parent = parent.Parent
207 func (c *Casper) saveCheckpoints(checkpoints []*state.Checkpoint) error {
208 checkpointSet := make(map[bc.Hash]*state.Checkpoint)
209 for _, c := range checkpoints {
210 checkpointSet[c.Hash] = c
213 var result []*state.Checkpoint
214 for _, c := range checkpointSet {
215 result = append(result, c)
218 return c.store.SaveCheckpoints(result)
221 func supLinkToVerifications(supLink *types.SupLink, validators map[string]*state.Validator, targetHash bc.Hash, targetHeight uint64) []*Verification {
222 validatorList := make([]*state.Validator, len(validators))
223 for _, validator := range validators {
224 validatorList[validator.Order] = validator
227 var result []*Verification
228 for i := 0; i < len(validators); i++ {
229 signature := supLink.Signatures[i]
230 if len(signature) == 0 {
234 result = append(result, &Verification{
235 SourceHash: supLink.SourceHash,
236 TargetHash: targetHash,
237 SourceHeight: supLink.SourceHeight,
238 TargetHeight: targetHeight,
239 Signature: signature,
240 PubKey: validatorList[i].PubKey,