mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-05 04:55:18 +00:00
light: ensure required header fields are present for verification (#5677)
This commit is contained in:
@@ -29,6 +29,7 @@ var (
|
||||
//
|
||||
// maxClockDrift defines how much untrustedHeader.Time can drift into the
|
||||
// future.
|
||||
// trustedHeader must have a ChainID, Height and Time
|
||||
func VerifyNonAdjacent(
|
||||
trustedHeader *types.SignedHeader, // height=X
|
||||
trustedVals *types.ValidatorSet, // height=X or height=X+1
|
||||
@@ -39,6 +40,8 @@ func VerifyNonAdjacent(
|
||||
maxClockDrift time.Duration,
|
||||
trustLevel tmmath.Fraction) error {
|
||||
|
||||
checkRequiredHeaderFields(trustedHeader)
|
||||
|
||||
if untrustedHeader.Height == trustedHeader.Height+1 {
|
||||
return errors.New("headers must be non adjacent in height")
|
||||
}
|
||||
@@ -90,6 +93,7 @@ func VerifyNonAdjacent(
|
||||
//
|
||||
// maxClockDrift defines how much untrustedHeader.Time can drift into the
|
||||
// future.
|
||||
// trustedHeader must have a ChainID, Height, Time and NextValidatorsHash
|
||||
func VerifyAdjacent(
|
||||
trustedHeader *types.SignedHeader, // height=X
|
||||
untrustedHeader *types.SignedHeader, // height=X+1
|
||||
@@ -98,6 +102,12 @@ func VerifyAdjacent(
|
||||
now time.Time,
|
||||
maxClockDrift time.Duration) error {
|
||||
|
||||
checkRequiredHeaderFields(trustedHeader)
|
||||
|
||||
if len(trustedHeader.NextValidatorsHash) == 0 {
|
||||
panic("next validators hash in trusted header is empty")
|
||||
}
|
||||
|
||||
if untrustedHeader.Height != trustedHeader.Height+1 {
|
||||
return errors.New("headers must be adjacent in height")
|
||||
}
|
||||
@@ -150,47 +160,6 @@ func Verify(
|
||||
return VerifyAdjacent(trustedHeader, untrustedHeader, untrustedVals, trustingPeriod, now, maxClockDrift)
|
||||
}
|
||||
|
||||
func verifyNewHeaderAndVals(
|
||||
untrustedHeader *types.SignedHeader,
|
||||
untrustedVals *types.ValidatorSet,
|
||||
trustedHeader *types.SignedHeader,
|
||||
now time.Time,
|
||||
maxClockDrift time.Duration) error {
|
||||
|
||||
if err := untrustedHeader.ValidateBasic(trustedHeader.ChainID); err != nil {
|
||||
return fmt.Errorf("untrustedHeader.ValidateBasic failed: %w", err)
|
||||
}
|
||||
|
||||
if untrustedHeader.Height <= trustedHeader.Height {
|
||||
return fmt.Errorf("expected new header height %d to be greater than one of old header %d",
|
||||
untrustedHeader.Height,
|
||||
trustedHeader.Height)
|
||||
}
|
||||
|
||||
if !untrustedHeader.Time.After(trustedHeader.Time) {
|
||||
return fmt.Errorf("expected new header time %v to be after old header time %v",
|
||||
untrustedHeader.Time,
|
||||
trustedHeader.Time)
|
||||
}
|
||||
|
||||
if !untrustedHeader.Time.Before(now.Add(maxClockDrift)) {
|
||||
return fmt.Errorf("new header has a time from the future %v (now: %v; max clock drift: %v)",
|
||||
untrustedHeader.Time,
|
||||
now,
|
||||
maxClockDrift)
|
||||
}
|
||||
|
||||
if !bytes.Equal(untrustedHeader.ValidatorsHash, untrustedVals.Hash()) {
|
||||
return fmt.Errorf("expected new header validators (%X) to match those that were supplied (%X) at height %d",
|
||||
untrustedHeader.ValidatorsHash,
|
||||
untrustedVals.Hash(),
|
||||
untrustedHeader.Height,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateTrustLevel checks that trustLevel is within the allowed range [1/3,
|
||||
// 1]. If not, it returns an error. 1/3 is the minimum amount of trust needed
|
||||
// which does not break the security model.
|
||||
@@ -243,3 +212,59 @@ func VerifyBackwards(untrustedHeader, trustedHeader *types.Header) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyNewHeaderAndVals(
|
||||
untrustedHeader *types.SignedHeader,
|
||||
untrustedVals *types.ValidatorSet,
|
||||
trustedHeader *types.SignedHeader,
|
||||
now time.Time,
|
||||
maxClockDrift time.Duration) error {
|
||||
|
||||
if err := untrustedHeader.ValidateBasic(trustedHeader.ChainID); err != nil {
|
||||
return fmt.Errorf("untrustedHeader.ValidateBasic failed: %w", err)
|
||||
}
|
||||
|
||||
if untrustedHeader.Height <= trustedHeader.Height {
|
||||
return fmt.Errorf("expected new header height %d to be greater than one of old header %d",
|
||||
untrustedHeader.Height,
|
||||
trustedHeader.Height)
|
||||
}
|
||||
|
||||
if !untrustedHeader.Time.After(trustedHeader.Time) {
|
||||
return fmt.Errorf("expected new header time %v to be after old header time %v",
|
||||
untrustedHeader.Time,
|
||||
trustedHeader.Time)
|
||||
}
|
||||
|
||||
if !untrustedHeader.Time.Before(now.Add(maxClockDrift)) {
|
||||
return fmt.Errorf("new header has a time from the future %v (now: %v; max clock drift: %v)",
|
||||
untrustedHeader.Time,
|
||||
now,
|
||||
maxClockDrift)
|
||||
}
|
||||
|
||||
if !bytes.Equal(untrustedHeader.ValidatorsHash, untrustedVals.Hash()) {
|
||||
return fmt.Errorf("expected new header validators (%X) to match those that were supplied (%X) at height %d",
|
||||
untrustedHeader.ValidatorsHash,
|
||||
untrustedVals.Hash(),
|
||||
untrustedHeader.Height,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkRequiredHeaderFields(h *types.SignedHeader) {
|
||||
if h.Height == 0 {
|
||||
panic("height in trusted header must be set (non zero")
|
||||
}
|
||||
|
||||
zeroTime := time.Time{}
|
||||
if h.Time == zeroTime {
|
||||
panic("time in trusted header must be set")
|
||||
}
|
||||
|
||||
if h.ChainID == "" {
|
||||
panic("chain ID in trusted header must be set")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user