package lite
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
lerr "github.com/tendermint/tendermint/lite/errors"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
var _ Verifier = (*BaseVerifier)(nil)
|
|
|
|
// BaseVerifier lets us check the validity of SignedHeaders at height or
|
|
// later, requiring sufficient votes (> 2/3) from the given valset.
|
|
// To verify blocks produced by a blockchain with mutable validator sets,
|
|
// use the DynamicVerifier.
|
|
// TODO: Handle unbonding time.
|
|
type BaseVerifier struct {
|
|
chainID string
|
|
height int64
|
|
valset *types.ValidatorSet
|
|
}
|
|
|
|
// NewBaseVerifier returns a new Verifier initialized with a validator set at
|
|
// some height.
|
|
func NewBaseVerifier(chainID string, height int64, valset *types.ValidatorSet) *BaseVerifier {
|
|
if valset.IsNilOrEmpty() {
|
|
panic("NewBaseVerifier requires a valid valset")
|
|
}
|
|
return &BaseVerifier{
|
|
chainID: chainID,
|
|
height: height,
|
|
valset: valset,
|
|
}
|
|
}
|
|
|
|
// Implements Verifier.
|
|
func (bv *BaseVerifier) ChainID() string {
|
|
return bv.chainID
|
|
}
|
|
|
|
// Implements Verifier.
|
|
func (bv *BaseVerifier) Verify(signedHeader types.SignedHeader) error {
|
|
|
|
// We can't verify commits for a different chain.
|
|
if signedHeader.ChainID != bv.chainID {
|
|
return errors.Errorf("BaseVerifier chainID is %v, cannot verify chainID %v",
|
|
bv.chainID, signedHeader.ChainID)
|
|
}
|
|
|
|
// We can't verify commits older than bv.height.
|
|
if signedHeader.Height < bv.height {
|
|
return errors.Errorf("BaseVerifier height is %v, cannot verify height %v",
|
|
bv.height, signedHeader.Height)
|
|
}
|
|
|
|
// We can't verify with the wrong validator set.
|
|
if !bytes.Equal(signedHeader.ValidatorsHash,
|
|
bv.valset.Hash()) {
|
|
return lerr.ErrUnexpectedValidators(signedHeader.ValidatorsHash, bv.valset.Hash())
|
|
}
|
|
|
|
// Do basic sanity checks.
|
|
err := signedHeader.ValidateBasic(bv.chainID)
|
|
if err != nil {
|
|
return errors.Wrap(err, "in verify")
|
|
}
|
|
|
|
// Check commit signatures.
|
|
err = bv.valset.VerifyCommit(
|
|
bv.chainID, signedHeader.Commit.BlockID,
|
|
signedHeader.Height, signedHeader.Commit)
|
|
if err != nil {
|
|
return errors.Wrap(err, "in verify")
|
|
}
|
|
|
|
return nil
|
|
}
|