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 }