github.com/project-88388/tendermint-v0.34.14-terra.2@v1.0.0/types/light.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 8 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 9 ) 10 11 // LightBlock is a SignedHeader and a ValidatorSet. 12 // It is the basis of the light client 13 type LightBlock struct { 14 *SignedHeader `json:"signed_header"` 15 ValidatorSet *ValidatorSet `json:"validator_set"` 16 } 17 18 // ValidateBasic checks that the data is correct and consistent 19 // 20 // This does no verification of the signatures 21 func (lb LightBlock) ValidateBasic(chainID string) error { 22 if lb.SignedHeader == nil { 23 return errors.New("missing signed header") 24 } 25 if lb.ValidatorSet == nil { 26 return errors.New("missing validator set") 27 } 28 29 if err := lb.SignedHeader.ValidateBasic(chainID); err != nil { 30 return fmt.Errorf("invalid signed header: %w", err) 31 } 32 if err := lb.ValidatorSet.ValidateBasic(); err != nil { 33 return fmt.Errorf("invalid validator set: %w", err) 34 } 35 36 // make sure the validator set is consistent with the header 37 if valSetHash := lb.ValidatorSet.Hash(); !bytes.Equal(lb.SignedHeader.ValidatorsHash, valSetHash) { 38 return fmt.Errorf("expected validator hash of header to match validator set hash (%X != %X)", 39 lb.SignedHeader.ValidatorsHash, valSetHash, 40 ) 41 } 42 43 return nil 44 } 45 46 // String returns a string representation of the LightBlock 47 func (lb LightBlock) String() string { 48 return lb.StringIndented("") 49 } 50 51 // StringIndented returns an indented string representation of the LightBlock 52 // 53 // SignedHeader 54 // ValidatorSet 55 func (lb LightBlock) StringIndented(indent string) string { 56 return fmt.Sprintf(`LightBlock{ 57 %s %v 58 %s %v 59 %s}`, 60 indent, lb.SignedHeader.StringIndented(indent+" "), 61 indent, lb.ValidatorSet.StringIndented(indent+" "), 62 indent) 63 } 64 65 // ToProto converts the LightBlock to protobuf 66 func (lb *LightBlock) ToProto() (*tmproto.LightBlock, error) { 67 if lb == nil { 68 return nil, nil 69 } 70 71 lbp := new(tmproto.LightBlock) 72 var err error 73 if lb.SignedHeader != nil { 74 lbp.SignedHeader = lb.SignedHeader.ToProto() 75 } 76 if lb.ValidatorSet != nil { 77 lbp.ValidatorSet, err = lb.ValidatorSet.ToProto() 78 if err != nil { 79 return nil, err 80 } 81 } 82 83 return lbp, nil 84 } 85 86 // LightBlockFromProto converts from protobuf back into the Lightblock. 87 // An error is returned if either the validator set or signed header are invalid 88 func LightBlockFromProto(pb *tmproto.LightBlock) (*LightBlock, error) { 89 if pb == nil { 90 return nil, errors.New("nil light block") 91 } 92 93 lb := new(LightBlock) 94 95 if pb.SignedHeader != nil { 96 sh, err := SignedHeaderFromProto(pb.SignedHeader) 97 if err != nil { 98 return nil, err 99 } 100 lb.SignedHeader = sh 101 } 102 103 if pb.ValidatorSet != nil { 104 vals, err := ValidatorSetFromProto(pb.ValidatorSet) 105 if err != nil { 106 return nil, err 107 } 108 lb.ValidatorSet = vals 109 } 110 111 return lb, nil 112 } 113 114 //----------------------------------------------------------------------------- 115 116 // SignedHeader is a header along with the commits that prove it. 117 type SignedHeader struct { 118 *Header `json:"header"` 119 120 Commit *Commit `json:"commit"` 121 } 122 123 // ValidateBasic does basic consistency checks and makes sure the header 124 // and commit are consistent. 125 // 126 // NOTE: This does not actually check the cryptographic signatures. Make sure 127 // to use a Verifier to validate the signatures actually provide a 128 // significantly strong proof for this header's validity. 129 func (sh SignedHeader) ValidateBasic(chainID string) error { 130 if sh.Header == nil { 131 return errors.New("missing header") 132 } 133 if sh.Commit == nil { 134 return errors.New("missing commit") 135 } 136 137 if err := sh.Header.ValidateBasic(); err != nil { 138 return fmt.Errorf("invalid header: %w", err) 139 } 140 if err := sh.Commit.ValidateBasic(); err != nil { 141 return fmt.Errorf("invalid commit: %w", err) 142 } 143 144 if sh.ChainID != chainID { 145 return fmt.Errorf("header belongs to another chain %q, not %q", sh.ChainID, chainID) 146 } 147 148 // Make sure the header is consistent with the commit. 149 if sh.Commit.Height != sh.Height { 150 return fmt.Errorf("header and commit height mismatch: %d vs %d", sh.Height, sh.Commit.Height) 151 } 152 if hhash, chash := sh.Header.Hash(), sh.Commit.BlockID.Hash; !bytes.Equal(hhash, chash) { 153 return fmt.Errorf("commit signs block %X, header is block %X", chash, hhash) 154 } 155 156 return nil 157 } 158 159 // String returns a string representation of SignedHeader. 160 func (sh SignedHeader) String() string { 161 return sh.StringIndented("") 162 } 163 164 // StringIndented returns an indented string representation of SignedHeader. 165 // 166 // Header 167 // Commit 168 func (sh SignedHeader) StringIndented(indent string) string { 169 return fmt.Sprintf(`SignedHeader{ 170 %s %v 171 %s %v 172 %s}`, 173 indent, sh.Header.StringIndented(indent+" "), 174 indent, sh.Commit.StringIndented(indent+" "), 175 indent) 176 } 177 178 // ToProto converts SignedHeader to protobuf 179 func (sh *SignedHeader) ToProto() *tmproto.SignedHeader { 180 if sh == nil { 181 return nil 182 } 183 184 psh := new(tmproto.SignedHeader) 185 if sh.Header != nil { 186 psh.Header = sh.Header.ToProto() 187 } 188 if sh.Commit != nil { 189 psh.Commit = sh.Commit.ToProto() 190 } 191 192 return psh 193 } 194 195 // FromProto sets a protobuf SignedHeader to the given pointer. 196 // It returns an error if the header or the commit is invalid. 197 func SignedHeaderFromProto(shp *tmproto.SignedHeader) (*SignedHeader, error) { 198 if shp == nil { 199 return nil, errors.New("nil SignedHeader") 200 } 201 202 sh := new(SignedHeader) 203 204 if shp.Header != nil { 205 h, err := HeaderFromProto(shp.Header) 206 if err != nil { 207 return nil, err 208 } 209 sh.Header = &h 210 } 211 212 if shp.Commit != nil { 213 c, err := CommitFromProto(shp.Commit) 214 if err != nil { 215 return nil, err 216 } 217 sh.Commit = c 218 } 219 220 return sh, nil 221 }