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

     1  package casper
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"errors"
     7  
     8  	"golang.org/x/crypto/sha3"
     9  
    10  	"github.com/bytom/bytom/consensus"
    11  	"github.com/bytom/bytom/crypto/ed25519/chainkd"
    12  	"github.com/bytom/bytom/protocol/bc"
    13  	"github.com/bytom/bytom/protocol/bc/types"
    14  	"github.com/bytom/bytom/protocol/state"
    15  )
    16  
    17  var errVerifySignature = errors.New("signature of verification message is invalid")
    18  
    19  type ValidCasperSignMsg struct {
    20  	SourceHash bc.Hash
    21  	TargetHash bc.Hash
    22  	Signature  []byte
    23  	PubKey     string
    24  }
    25  
    26  // verification represent a verification message for the block
    27  // source hash and target hash point to the checkpoint, and the source checkpoint is the target checkpoint's parent(not be directly)
    28  // the vector <sourceHash, targetHash, sourceHeight, targetHeight, pubKey> as the message of signature
    29  type verification struct {
    30  	SourceHash   bc.Hash
    31  	TargetHash   bc.Hash
    32  	SourceHeight uint64
    33  	TargetHeight uint64
    34  	Signature    []byte
    35  	PubKey       string
    36  	order        int
    37  }
    38  
    39  func convertVerification(source, target *state.Checkpoint, msg *ValidCasperSignMsg) (*verification, error) {
    40  	validators := target.Parent.EffectiveValidators()
    41  	if _, ok := validators[msg.PubKey]; !ok {
    42  		return nil, errPubKeyIsNotValidator
    43  	}
    44  
    45  	return &verification{
    46  		SourceHash:   source.Hash,
    47  		TargetHash:   target.Hash,
    48  		SourceHeight: source.Height,
    49  		TargetHeight: target.Height,
    50  		Signature:    msg.Signature,
    51  		PubKey:       msg.PubKey,
    52  		order:        validators[msg.PubKey].Order,
    53  	}, nil
    54  }
    55  
    56  func supLinkToVerifications(source, target *state.Checkpoint, supLink *types.SupLink) []*verification {
    57  	var result []*verification
    58  	for _, validator := range target.Parent.EffectiveValidators() {
    59  		if signature := supLink.Signatures[validator.Order]; len(signature) != 0 {
    60  			result = append(result, &verification{
    61  				SourceHash:   source.Hash,
    62  				TargetHash:   target.Hash,
    63  				SourceHeight: source.Height,
    64  				TargetHeight: target.Height,
    65  				Signature:    signature,
    66  				PubKey:       validator.PubKey,
    67  				order:        validator.Order,
    68  			})
    69  		}
    70  	}
    71  	return result
    72  }
    73  
    74  // Sign used to sign the verification by specified xPrv
    75  func (v *verification) Sign(xPrv chainkd.XPrv) error {
    76  	message, err := v.encodeMessage()
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	v.Signature = xPrv.Sign(message)
    82  	return nil
    83  }
    84  
    85  func (v *verification) toValidCasperSignMsg() ValidCasperSignMsg {
    86  	return ValidCasperSignMsg{
    87  		SourceHash: v.SourceHash,
    88  		TargetHash: v.TargetHash,
    89  		Signature:  v.Signature,
    90  		PubKey:     v.PubKey,
    91  	}
    92  }
    93  
    94  func (v *verification) valid() error {
    95  	blocksOfEpoch := consensus.ActiveNetParams.BlocksOfEpoch
    96  	if v.SourceHeight%blocksOfEpoch != 0 || v.TargetHeight%blocksOfEpoch != 0 {
    97  		return errVoteToGrowingCheckpoint
    98  	}
    99  
   100  	if v.SourceHeight >= v.TargetHeight {
   101  		return errVoteToSameCheckpoint
   102  	}
   103  
   104  	return v.verifySignature()
   105  }
   106  
   107  // verifySignature verify the signature of encode message of verification
   108  func (v *verification) verifySignature() error {
   109  	message, err := v.encodeMessage()
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	pubKey, err := hex.DecodeString(v.PubKey)
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	var xPub chainkd.XPub
   120  	copy(xPub[:], pubKey)
   121  	if !xPub.Verify(message, v.Signature) {
   122  		return errVerifySignature
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  // encodeMessage encode the verification for the validators to sign or verify
   129  func (v *verification) encodeMessage() ([]byte, error) {
   130  	buff := new(bytes.Buffer)
   131  	if _, err := v.SourceHash.WriteTo(buff); err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	if _, err := v.TargetHash.WriteTo(buff); err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	msg := sha3.Sum256(buff.Bytes())
   140  	return msg[:], nil
   141  }