6 "github.com/sirupsen/logrus"
8 "github.com/bytom/bytom/config"
9 "github.com/bytom/bytom/errors"
10 "github.com/bytom/bytom/math/checked"
11 "github.com/bytom/bytom/protocol/bc"
12 "github.com/bytom/bytom/protocol/bc/types"
13 "github.com/bytom/bytom/protocol/state"
16 type applyBlockReply struct {
17 verification *Verification
21 // ApplyBlock used to receive a new block from upper layer, it provides idempotence
22 // and parse the vote and mortgage from the transactions, then save to the checkpoint
23 // the tree of checkpoint will grow with the arrival of new blocks
24 // it will return verification when an epoch is reached and the current node is the validator, otherwise return nil
25 // the chain module must broadcast the verification
26 func (c *Casper) ApplyBlock(block *types.Block) (*applyBlockReply, error) {
27 if block.Height%state.BlocksOfEpoch == 1 {
28 c.newEpochCh <- block.PreviousBlockHash
34 if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
35 return &applyBlockReply{bestHash: c.bestChain()}, nil
38 target, err := c.applyBlockToCheckpoint(block)
40 return nil, errors.Wrap(err, "apply block to checkpoint")
43 if err := applyTransactions(target, block.Transactions); err != nil {
47 validators, err := c.Validators(&target.Hash)
52 verification, err := c.applyMyVerification(target, block, validators)
57 affectedCheckpoints, err := c.applySupLinks(target, block.SupLinks, validators)
62 return &applyBlockReply{verification: verification, bestHash: c.bestChain()}, c.saveCheckpoints(affectedCheckpoints)
65 func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
66 node, err := c.checkpointNodeByHash(block.PreviousBlockHash)
71 checkpoint := node.checkpoint
72 if mod := block.Height % state.BlocksOfEpoch; mod == 1 {
74 checkpoint = &state.Checkpoint{
75 ParentHash: parent.Hash,
77 Status: state.Growing,
78 Votes: make(map[string]uint64),
79 Guaranties: make(map[string]uint64),
82 for pubKey, num := range parent.Votes {
83 checkpoint.Votes[pubKey] = num
85 for pubKey, num := range parent.Guaranties {
86 checkpoint.Guaranties[pubKey] = num
88 node.addChild(&treeNode{checkpoint: checkpoint})
90 checkpoint.Status = state.Unjustified
93 checkpoint.Height = block.Height
94 checkpoint.Hash = block.Hash()
95 checkpoint.Timestamp = block.Timestamp
96 return checkpoint, nil
99 func (c *Casper) checkpointNodeByHash(blockHash bc.Hash) (*treeNode, error) {
100 node, err := c.tree.nodeByHash(blockHash)
102 logrus.WithField("err", err).Error("fail find checkpoint, start to reorganize checkpoint")
104 return c.replayCheckpoint(blockHash)
110 func (c *Casper) replayCheckpoint(hash bc.Hash) (*treeNode, error) {
112 var attachBlocks []*types.Block
114 prevBlock, err := c.store.GetBlock(&prevHash)
119 if prevBlock.Height%state.BlocksOfEpoch == 0 {
123 attachBlocks = append([]*types.Block{prevBlock}, attachBlocks...)
124 prevHash = prevBlock.PreviousBlockHash
127 parent, err := c.tree.nodeByHash(prevHash)
133 checkpoint: &state.Checkpoint{
134 ParentHash: parent.checkpoint.Hash,
135 Parent: parent.checkpoint,
136 Status: state.Growing,
137 Votes: make(map[string]uint64),
138 Guaranties: make(map[string]uint64),
142 parent.addChild(node)
143 for _, attachBlock := range attachBlocks {
144 if err := applyTransactions(node.checkpoint, attachBlock.Transactions); err != nil {
148 node.checkpoint.Hash = attachBlock.Hash()
149 node.checkpoint.Height = attachBlock.Height
150 node.checkpoint.Timestamp = attachBlock.Timestamp
155 func applyTransactions(target *state.Checkpoint, transactions []*types.Tx) error {for _, tx := range transactions {
156 for _, input := range tx.Inputs {
157 if vetoInput, ok := input.TypedInput.(*types.VetoInput); ok {
158 if err := processVeto(vetoInput, target); err != nil {
163 if isGuarantyProgram(input.ControlProgram()) {
164 if err := processWithdrawal(decodeGuarantyArgs(input.ControlProgram()), target); err != nil {
170 for _, output := range tx.Outputs {
171 if _, ok := output.TypedOutput.(*types.VoteOutput); ok {
172 if err := processVote(output, target); err != nil {
177 if isGuarantyProgram(output.ControlProgram) {
178 if err := processGuaranty(decodeGuarantyArgs(output.ControlProgram), target); err != nil {
187 // applySupLinks copy the block's supLink to the checkpoint
188 func (c *Casper) applySupLinks(target *state.Checkpoint, supLinks []*types.SupLink, validators map[string]*state.Validator) ([]*state.Checkpoint, error) {
189 affectedCheckpoints := []*state.Checkpoint{target}
190 if target.Height%state.BlocksOfEpoch != 0 {
194 for _, supLink := range supLinks {
195 var validVerifications []*Verification
196 for _, v := range supLinkToVerifications(supLink, validators, target.Hash, target.Height) {
197 if validate(v) == nil && c.verifyVerification(v, validators[v.PubKey].Order, true) == nil {
198 validVerifications = append(validVerifications, v)
202 checkpoints, err := c.addVerificationToCheckpoint(target, validators, validVerifications...)
207 affectedCheckpoints = append(affectedCheckpoints, checkpoints...)
209 return affectedCheckpoints, nil
212 func (c *Casper) applyMyVerification(target *state.Checkpoint, block *types.Block, validators map[string]*state.Validator) (*Verification, error) {
213 v, err := c.myVerification(target, validators)
222 signature, err := hex.DecodeString(v.Signature)
227 block.SupLinks.AddSupLink(v.SourceHeight, v.SourceHash, signature, validators[v.PubKey].Order)
228 return v, c.store.SaveBlockHeader(&block.BlockHeader)
231 func (c *Casper) myVerification(target *state.Checkpoint, validators map[string]*state.Validator) (*Verification, error) {
232 if target.Height%state.BlocksOfEpoch != 0 {
236 pubKey := config.CommonConfig.PrivateKey().XPub().String()
237 if _, ok := validators[pubKey]; !ok {
241 validatorOrder := validators[pubKey].Order
242 if target.ContainsVerification(validatorOrder, nil) {
246 if source := c.lastJustifiedCheckpoint(target); source != nil {
248 SourceHash: source.Hash,
249 TargetHash: target.Hash,
250 SourceHeight: source.Height,
251 TargetHeight: target.Height,
255 prvKey := config.CommonConfig.PrivateKey()
256 if err := v.Sign(*prvKey); err != nil {
260 if err := c.verifyVerification(v, validatorOrder, false); err != nil {
269 type guarantyArgs struct {
274 func isGuarantyProgram(program []byte) bool {
278 func decodeGuarantyArgs(program []byte) *guarantyArgs {
282 func processWithdrawal(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
283 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
284 guarantyNum := checkpoint.Guaranties[pubKey]
285 guarantyNum, ok := checked.SubUint64(guarantyNum, guarantyArgs.Amount)
287 return checked.ErrOverflow
290 checkpoint.Guaranties[pubKey] = guarantyNum
291 // TODO delete the evil validator when receive the confiscate transaction
295 func processGuaranty(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
296 if guarantyArgs.Amount < minGuaranty {
297 return errGuarantyLessThanMinimum
300 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
301 guarantyNum := checkpoint.Guaranties[pubKey]
302 guarantyNum, ok := checked.AddUint64(guarantyNum, guarantyArgs.Amount)
304 return checked.ErrOverflow
307 checkpoint.Guaranties[pubKey] = guarantyNum
311 func processVeto(input *types.VetoInput, checkpoint *state.Checkpoint) error {
312 pubKey := hex.EncodeToString(input.Vote)
313 voteNum := checkpoint.Votes[pubKey]
314 voteNum, ok := checked.SubUint64(voteNum, input.Amount)
316 return checked.ErrOverflow
319 checkpoint.Votes[pubKey] = voteNum
323 func processVote(output *types.TxOutput, checkpoint *state.Checkpoint) error {
324 voteOutput := output.TypedOutput.(*types.VoteOutput)
325 pubKey := hex.EncodeToString(voteOutput.Vote)
326 if checkpoint.Guaranties[pubKey] < minGuaranty {
327 return errVoteToNonValidator
330 voteNum := checkpoint.Votes[pubKey]
331 voteNum, ok := checked.AddUint64(voteNum, output.Amount)
333 return checked.ErrOverflow
336 checkpoint.Votes[pubKey] = voteNum
340 func (c *Casper) lastJustifiedCheckpoint(branch *state.Checkpoint) *state.Checkpoint {
341 parent := branch.Parent
343 switch parent.Status {
344 case state.Finalized:
346 case state.Justified:
349 parent = parent.Parent
354 func (c *Casper) saveCheckpoints(checkpoints []*state.Checkpoint) error {
355 checkpointSet := make(map[bc.Hash]*state.Checkpoint)
356 for _, c := range checkpoints {
357 checkpointSet[c.Hash] = c
360 var result []*state.Checkpoint
361 for _, c := range checkpointSet {
362 result = append(result, c)
365 return c.store.SaveCheckpoints(result)
368 func supLinkToVerifications(supLink *types.SupLink, validators map[string]*state.Validator, targetHash bc.Hash, targetHeight uint64) []*Verification {
369 validatorList := make([]*state.Validator, len(validators))
370 for _, validator := range validators {
371 validatorList[validator.Order] = validator
374 var result []*Verification
375 for i := 0; i < len(validators); i++ {
376 signature := supLink.Signatures[i]
377 if len(signature) == 0 {
381 result = append(result, &Verification{
382 SourceHash: supLink.SourceHash,
383 TargetHash: targetHash,
384 SourceHeight: supLink.SourceHeight,
385 TargetHeight: targetHeight,
386 Signature: hex.EncodeToString(signature),
387 PubKey: validatorList[i].PubKey,