github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/casper/apply_block.go (about)

     1  package casper
     2  
     3  import (
     4  	"fmt"
     5  
     6  	log "github.com/sirupsen/logrus"
     7  
     8  	"github.com/bytom/bytom/config"
     9  	"github.com/bytom/bytom/consensus"
    10  	"github.com/bytom/bytom/errors"
    11  	"github.com/bytom/bytom/protocol/bc"
    12  	"github.com/bytom/bytom/protocol/bc/types"
    13  	"github.com/bytom/bytom/protocol/state"
    14  )
    15  
    16  // ApplyBlock used to receive a new block from upper layer, it provides idempotence
    17  // and parse the vote and mortgage from the transactions, then save to the checkpoint
    18  // the tree of checkpoint will grow with the arrival of new blocks
    19  // it will return verification when an epoch is reached and the current node is the validator, otherwise return nil
    20  // the chain module must broadcast the verification
    21  func (c *Casper) ApplyBlock(block *types.Block) (bc.Hash, error) {
    22  	if block.Height%consensus.ActiveNetParams.BlocksOfEpoch == 1 {
    23  		c.newEpochCh <- block.PreviousBlockHash
    24  	}
    25  
    26  	c.mu.Lock()
    27  	defer c.mu.Unlock()
    28  	if node := c.tree.nodeByHash(block.Hash()); node != nil {
    29  		return c.bestChain(), nil
    30  	}
    31  
    32  	target, err := c.applyBlockToCheckpoint(block)
    33  	if err != nil {
    34  		return bc.Hash{}, errors.Wrap(err, "apply block to checkpoint")
    35  	}
    36  
    37  	if err := c.applyMyVerification(target, block); err != nil {
    38  		return bc.Hash{}, err
    39  	}
    40  
    41  	affectedCheckpoints, err := c.applySupLinks(target, block.SupLinks)
    42  	if err != nil {
    43  		return bc.Hash{}, err
    44  	}
    45  
    46  	return c.bestChain(), c.saveCheckpoints(affectedCheckpoints)
    47  }
    48  
    49  func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
    50  	node, err := c.checkpointNodeByHash(block.PreviousBlockHash)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	if block.Height%consensus.ActiveNetParams.BlocksOfEpoch == 1 {
    56  		node = node.newChild()
    57  	}
    58  	return node.Checkpoint, node.Increase(block)
    59  }
    60  
    61  func (c *Casper) checkpointNodeByHash(hash bc.Hash) (*treeNode, error) {
    62  	if node := c.tree.nodeByHash(hash); node != nil {
    63  		return node, nil
    64  	}
    65  
    66  	block, err := c.store.GetBlock(&hash)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	if block.Height%consensus.ActiveNetParams.BlocksOfEpoch == 0 {
    72  		return nil, errors.New("checkpointNodeByHash fail on previous round checkpoint")
    73  	}
    74  
    75  	node, err := c.checkpointNodeByHash(block.PreviousBlockHash)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	if block.Height%consensus.ActiveNetParams.BlocksOfEpoch == 1 {
    81  		node = node.newChild()
    82  	}
    83  	return node, node.Increase(block)
    84  }
    85  
    86  // applySupLinks copy the block's supLink to the checkpoint
    87  func (c *Casper) applySupLinks(target *state.Checkpoint, supLinks []*types.SupLink) ([]*state.Checkpoint, error) {
    88  	affectedCheckpoints := []*state.Checkpoint{target}
    89  	if target.Status == state.Growing {
    90  		return nil, nil
    91  	}
    92  
    93  	for _, supLink := range supLinks {
    94  		validVerifications, err := c.validVerificationsFromSupLink(target, supLink)
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  
    99  		checkpoints, err := c.addVerificationToCheckpoint(target, validVerifications...)
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  
   104  		affectedCheckpoints = append(affectedCheckpoints, checkpoints...)
   105  	}
   106  	return affectedCheckpoints, nil
   107  }
   108  
   109  func (c *Casper) applyMyVerification(target *state.Checkpoint, block *types.Block) error {
   110  	v := c.myVerification(target)
   111  	if v == nil {
   112  		return nil
   113  	}
   114  
   115  	if err := c.msgQueue.Post(v.toValidCasperSignMsg()); err != nil {
   116  		return err
   117  	}
   118  
   119  	block.SupLinks.AddSupLink(v.SourceHeight, v.SourceHash, v.Signature, v.order)
   120  	return nil
   121  }
   122  
   123  func (c *Casper) myVerification(target *state.Checkpoint) *verification {
   124  	if target.Status == state.Growing {
   125  		return nil
   126  	}
   127  
   128  	source := lastJustifiedCheckpoint(target)
   129  	if source == nil {
   130  		log.WithField("module", logModule).Warn("myVerification fail on find last justified")
   131  		return nil
   132  	}
   133  
   134  	prvKey := config.CommonConfig.PrivateKey()
   135  	v, err := convertVerification(source, target, &ValidCasperSignMsg{PubKey: prvKey.XPub().String()})
   136  	if err != nil {
   137  		return nil
   138  	}
   139  
   140  	if target.ContainsVerification(v.order, nil) {
   141  		log.WithField("module", logModule).Warn("myVerification fail on find same height sign")
   142  		return nil
   143  	}
   144  
   145  	if err := v.Sign(*prvKey); err != nil {
   146  		log.WithField("module", logModule).Error("myVerification fail on sign msg")
   147  		return nil
   148  	}
   149  
   150  	if err := c.verifyVerification(v); err != nil {
   151  		log.WithField("module", logModule).Warn("myVerification fail on find nest sign")
   152  		return nil
   153  	}
   154  
   155  	return v
   156  }
   157  
   158  func (c *Casper) saveCheckpoints(checkpoints []*state.Checkpoint) error {
   159  	checkpointSet := make(map[bc.Hash]*state.Checkpoint)
   160  	for _, c := range checkpoints {
   161  		checkpointSet[c.Hash] = c
   162  	}
   163  
   164  	var result []*state.Checkpoint
   165  	for _, c := range checkpointSet {
   166  		result = append(result, c)
   167  	}
   168  
   169  	return c.store.SaveCheckpoints(result)
   170  }
   171  
   172  func lastJustifiedCheckpoint(branch *state.Checkpoint) *state.Checkpoint {
   173  	for parent := branch.Parent; parent != nil; parent = parent.Parent {
   174  		if parent.Status == state.Justified {
   175  			return parent
   176  		}
   177  	}
   178  	return nil
   179  }
   180  
   181  func (c *Casper) validVerificationsFromSupLink(target *state.Checkpoint, supLink *types.SupLink) ([]*verification, error) {
   182  	source, err := c.store.GetCheckpoint(&supLink.SourceHash)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	if source.Height != supLink.SourceHeight {
   188  		return nil, fmt.Errorf("suplink has incorrect source height")
   189  	}
   190  
   191  	var result []*verification
   192  	for _, v := range supLinkToVerifications(source, target, supLink) {
   193  		if c.verifyVerification(v) == nil {
   194  			result = append(result, v)
   195  		}
   196  	}
   197  	return result, nil
   198  }