OSDN Git Service

54bae5c5a235f0d9b4fc8a39491ca768fe5a8483
[bytom/bytom.git] / protocol / verfication.go
1 package protocol
2
3 import (
4         "bytes"
5         "encoding/binary"
6         "encoding/hex"
7         "errors"
8
9         "github.com/bytom/bytom/crypto/ed25519/chainkd"
10         "github.com/bytom/bytom/crypto/sha3pool"
11         "github.com/bytom/bytom/protocol/bc"
12 )
13
14 var errVerifySignature = errors.New("signature of verification message is invalid")
15
16 // Verification represent a verification message for the block
17 // source hash and target hash point to the checkpoint, and the source checkpoint is the target checkpoint's parent(not be directly)
18 // the vector <sourceHash, targetHash, sourceHeight, targetHeight, pubKey> as the message of signature
19 type Verification struct {
20         SourceHash   bc.Hash
21         TargetHash   bc.Hash
22         SourceHeight uint64
23         TargetHeight uint64
24         Signature    string
25         PubKey       string
26 }
27
28 // Sign used to sign the verification by specified xPrv
29 func (v *Verification) Sign(xPrv chainkd.XPrv) error {
30         message, err := v.encodeMessage()
31         if err != nil {
32                 return err
33         }
34
35         v.Signature = hex.EncodeToString(xPrv.Sign(message))
36         return nil
37 }
38
39 // VerifySignature verify the signature of encode message of verification
40 func (v *Verification) VerifySignature() error {
41         pubKey, err := hex.DecodeString(v.PubKey)
42         if err != nil {
43                 return err
44         }
45
46         signature, err := hex.DecodeString(v.Signature)
47         if err != nil {
48                 return err
49         }
50
51         message, err := v.encodeMessage()
52         if err != nil {
53                 return err
54         }
55
56         var xPub chainkd.XPub
57         copy(xPub[:], pubKey)
58         if !xPub.Verify(message, signature) {
59                 return errVerifySignature
60         }
61
62         return nil
63 }
64
65 // encodeMessage encode the verification for the validators to sign or verify
66 func (v *Verification) encodeMessage() ([]byte, error) {
67         buff := new(bytes.Buffer)
68         if _, err := v.SourceHash.WriteTo(buff); err != nil {
69                 return nil, err
70         }
71
72         if _, err := v.TargetHash.WriteTo(buff); err != nil {
73                 return nil, err
74         }
75
76         uint64Buff := make([]byte, 8)
77
78         binary.LittleEndian.PutUint64(uint64Buff, v.SourceHeight)
79         if _, err := buff.Write(uint64Buff); err != nil {
80                 return nil, err
81         }
82
83         binary.LittleEndian.PutUint64(uint64Buff, v.TargetHeight)
84         if _, err := buff.Write(uint64Buff); err != nil {
85                 return nil, err
86         }
87
88         return sha3Hash(buff.Bytes())
89 }
90
91 func sha3Hash(message []byte) ([]byte, error) {
92         sha3 := sha3pool.Get256()
93         defer sha3pool.Put256(sha3)
94
95         if _, err := sha3.Write(message); err != nil {
96                 return nil, err
97         }
98
99         hash := &bc.Hash{}
100         if _, err := hash.ReadFrom(sha3); err != nil {
101                 return nil, err
102         }
103
104         return hash.Bytes(), nil
105 }