@ -703,13 +703,14 @@ func (c *Client) sequence(
newHeader * types . SignedHeader ,
newHeader * types . SignedHeader ,
newVals * types . ValidatorSet ,
newVals * types . ValidatorSet ,
now time . Time ) error {
now time . Time ) error {
// 1) Verify any intermediate headers.
// 1) Verify any intermediate headers.
var (
var (
interimHeader * types . SignedHeader
interimHeader * types . SignedHeader
interimNextVals * types . ValidatorSet
interimNextVals * types . ValidatorSet
err error
err error
)
)
for height := trustedHeader . Height + 1 ; height < newHeader . Height ; height ++ {
for height := trustedHeader . Height + 1 ; height <= newHeader . Height ; height ++ {
interimHeader , err = c . signedHeaderFromPrimary ( height )
interimHeader , err = c . signedHeaderFromPrimary ( height )
if err != nil {
if err != nil {
return errors . Wrapf ( err , "failed to obtain the header #%d" , height )
return errors . Wrapf ( err , "failed to obtain the header #%d" , height )
@ -734,16 +735,17 @@ func (c *Client) sequence(
if err != nil {
if err != nil {
return errors . Wrapf ( err , "failed to obtain the vals #%d" , height + 1 )
return errors . Wrapf ( err , "failed to obtain the vals #%d" , height + 1 )
}
}
}
err = c . updateTrustedHeaderAndNextVals ( interimHeader , interimNextVals )
if err != nil {
return errors . Wrapf ( err , "failed to update trusted state #%d" , height )
if ! bytes . Equal ( interimHeader . NextValidatorsHash , interimNextVals . Hash ( ) ) {
return errors . Errorf ( "expected next validator's hash %X, but got %X (height #%d)" ,
interimHeader . NextValidatorsHash ,
interimNextVals . Hash ( ) ,
interimHeader . Height )
}
}
}
trustedHeader , trustedNextVals = interimHeader , interimNextVals
trustedHeader , trustedNextVals = interimHeader , interimNextVals
}
}
// 2) Verify the new header.
return VerifyAdjacent ( c . chainID , c . latestTrustedHeader , newHeader , newVals , c . trustingPeriod , now )
return nil
}
}
// see VerifyHeader
// see VerifyHeader
@ -757,7 +759,7 @@ func (c *Client) bisection(
interimVals := newVals
interimVals := newVals
interimHeader := newHeader
interimHeader := newHeader
for trustedHeader . Height < newHeader . Height {
for {
c . logger . Debug ( "Verify newHeader against trustedHeader" ,
c . logger . Debug ( "Verify newHeader against trustedHeader" ,
"trustedHeight" , trustedHeader . Height ,
"trustedHeight" , trustedHeader . Height ,
"trustedHash" , hash2str ( trustedHeader . Hash ( ) ) ,
"trustedHash" , hash2str ( trustedHeader . Hash ( ) ) ,
@ -767,24 +769,22 @@ func (c *Client) bisection(
c . trustLevel )
c . trustLevel )
switch err . ( type ) {
switch err . ( type ) {
case nil :
case nil :
if interimHeader . Height == newHeader . Height {
return nil
}
// Update the lower bound to the previous upper bound
// Update the lower bound to the previous upper bound
trustedHeader = interimHeader
trustedNextVals , err = c . validatorSetFromPrimary ( interimHeader . Height + 1 )
interimNextVals , err := c . validatorSetFromPrimary ( interimHeader . Height + 1 )
if err != nil {
if err != nil {
return err
return err
}
}
if ! bytes . Equal ( trusted Header. NextValidatorsHash , trusted NextVals. Hash ( ) ) {
if ! bytes . Equal ( interim Header. NextValidatorsHash , interim NextVals. Hash ( ) ) {
return errors . Errorf ( "expected next validator's hash %X, but got %X (height #%d)" ,
return errors . Errorf ( "expected next validator's hash %X, but got %X (height #%d)" ,
trustedHeader . NextValidatorsHash ,
trustedNextVals . Hash ( ) ,
trustedHeader . Height )
}
err = c . updateTrustedHeaderAndNextVals ( trustedHeader , trustedNextVals )
if err != nil {
return err
interimHeader . NextValidatorsHash ,
interimNextVals . Hash ( ) ,
interimHeader . Height )
}
}
trustedHeader , trustedNextVals = interimHeader , interimNextVals
// Update the upper bound to the untrustedHeader
// Update the upper bound to the untrustedHeader
interimHeader , interimVals = newHeader , newVals
interimHeader , interimVals = newHeader , newVals
@ -799,8 +799,6 @@ func (c *Client) bisection(
return errors . Wrapf ( err , "failed to verify the header #%d" , newHeader . Height )
return errors . Wrapf ( err , "failed to verify the header #%d" , newHeader . Height )
}
}
}
}
return nil
}
}
// persist header and next validators to trustedStore.
// persist header and next validators to trustedStore.
@ -841,6 +839,10 @@ func (c *Client) backwards(trustedHeader *types.SignedHeader, newHeader *types.S
err error
err error
)
)
if HeaderExpired ( newHeader , c . trustingPeriod , now ) {
return ErrOldHeaderExpired { newHeader . Time . Add ( c . trustingPeriod ) , now }
}
for trustedHeader . Height > newHeader . Height {
for trustedHeader . Height > newHeader . Height {
interimHeader , err = c . signedHeaderFromPrimary ( trustedHeader . Height - 1 )
interimHeader , err = c . signedHeaderFromPrimary ( trustedHeader . Height - 1 )
if err != nil {
if err != nil {
@ -857,10 +859,6 @@ func (c *Client) backwards(trustedHeader *types.SignedHeader, newHeader *types.S
trustedHeader . Time )
trustedHeader . Time )
}
}
if HeaderExpired ( interimHeader , c . trustingPeriod , now ) {
return ErrOldHeaderExpired { interimHeader . Time . Add ( c . trustingPeriod ) , now }
}
if ! bytes . Equal ( interimHeader . Hash ( ) , trustedHeader . LastBlockID . Hash ) {
if ! bytes . Equal ( interimHeader . Hash ( ) , trustedHeader . LastBlockID . Hash ) {
return errors . Errorf ( "older header hash %X does not match trusted header's last block %X" ,
return errors . Errorf ( "older header hash %X does not match trusted header's last block %X" ,
interimHeader . Hash ( ) ,
interimHeader . Hash ( ) ,