Files
tendermint/pkg/light/light.go
2021-08-24 13:25:49 +02:00

115 lines
2.8 KiB
Go

package light
import (
"bytes"
"errors"
"fmt"
"github.com/tendermint/tendermint/pkg/consensus"
"github.com/tendermint/tendermint/pkg/metadata"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)
// LightBlock is a SignedHeader and a ValidatorSet.
// It is the basis of the light client
type LightBlock struct {
*metadata.SignedHeader `json:"signed_header"`
ValidatorSet *consensus.ValidatorSet `json:"validator_set"`
}
// ValidateBasic checks that the data is correct and consistent
//
// This does no verification of the signatures
func (lb LightBlock) ValidateBasic(chainID string) error {
if lb.SignedHeader == nil {
return errors.New("missing signed header")
}
if lb.ValidatorSet == nil {
return errors.New("missing validator set")
}
if err := lb.SignedHeader.ValidateBasic(chainID); err != nil {
return fmt.Errorf("invalid signed header: %w", err)
}
if err := lb.ValidatorSet.ValidateBasic(); err != nil {
return fmt.Errorf("invalid validator set: %w", err)
}
// make sure the validator set is consistent with the header
if valSetHash := lb.ValidatorSet.Hash(); !bytes.Equal(lb.SignedHeader.ValidatorsHash, valSetHash) {
return fmt.Errorf("expected validator hash of header to match validator set hash (%X != %X)",
lb.SignedHeader.ValidatorsHash, valSetHash,
)
}
return nil
}
// String returns a string representation of the LightBlock
func (lb LightBlock) String() string {
return lb.StringIndented("")
}
// StringIndented returns an indented string representation of the LightBlock
//
// SignedHeader
// ValidatorSet
func (lb LightBlock) StringIndented(indent string) string {
return fmt.Sprintf(`LightBlock{
%s %v
%s %v
%s}`,
indent, lb.SignedHeader.StringIndented(indent+" "),
indent, lb.ValidatorSet.StringIndented(indent+" "),
indent)
}
// ToProto converts the LightBlock to protobuf
func (lb *LightBlock) ToProto() (*tmproto.LightBlock, error) {
if lb == nil {
return nil, nil
}
lbp := new(tmproto.LightBlock)
var err error
if lb.SignedHeader != nil {
lbp.SignedHeader = lb.SignedHeader.ToProto()
}
if lb.ValidatorSet != nil {
lbp.ValidatorSet, err = lb.ValidatorSet.ToProto()
if err != nil {
return nil, err
}
}
return lbp, nil
}
// LightBlockFromProto converts from protobuf back into the Lightblock.
// An error is returned if either the validator set or signed header are invalid
func LightBlockFromProto(pb *tmproto.LightBlock) (*LightBlock, error) {
if pb == nil {
return nil, errors.New("nil light block")
}
lb := new(LightBlock)
if pb.SignedHeader != nil {
sh, err := metadata.SignedHeaderFromProto(pb.SignedHeader)
if err != nil {
return nil, err
}
lb.SignedHeader = sh
}
if pb.ValidatorSet != nil {
vals, err := consensus.ValidatorSetFromProto(pb.ValidatorSet)
if err != nil {
return nil, err
}
lb.ValidatorSet = vals
}
return lb, nil
}