github.com/fiagdao/tendermint@v0.32.11-0.20220824195748-2087fcc480c1/lite2/client.go (about)

     1  package lite
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math/rand"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/tendermint/tendermint/libs/log"
    13  	tmmath "github.com/tendermint/tendermint/libs/math"
    14  	"github.com/tendermint/tendermint/lite2/provider"
    15  	"github.com/tendermint/tendermint/lite2/store"
    16  	"github.com/tendermint/tendermint/types"
    17  )
    18  
    19  type mode byte
    20  
    21  const (
    22  	sequential mode = iota + 1
    23  	skipping
    24  
    25  	defaultPruningSize      = 1000
    26  	defaultMaxRetryAttempts = 10
    27  	// For bisection, when using the cache of headers from the previous batch,
    28  	// they will always be at a height greater than 1/2 (normal bisection) so to
    29  	// find something in between the range, 9/16 is used.
    30  	bisectionNumerator   = 9
    31  	bisectionDenominator = 16
    32  
    33  	// 10s should cover most of the clients.
    34  	// References:
    35  	// - http://vancouver-webpages.com/time/web.html
    36  	// - https://blog.codinghorror.com/keeping-time-on-the-pc/
    37  	defaultMaxClockDrift = 10 * time.Second
    38  )
    39  
    40  // Option sets a parameter for the light client.
    41  type Option func(*Client)
    42  
    43  // SequentialVerification option configures the light client to sequentially
    44  // check the headers (every header, in ascending height order). Note this is
    45  // much slower than SkippingVerification, albeit more secure.
    46  func SequentialVerification() Option {
    47  	return func(c *Client) {
    48  		c.verificationMode = sequential
    49  	}
    50  }
    51  
    52  // SkippingVerification option configures the light client to skip headers as
    53  // long as {trustLevel} of the old validator set signed the new header. The
    54  // bisection algorithm from the specification is used for finding the minimal
    55  // "trust path".
    56  //
    57  // trustLevel - fraction of the old validator set (in terms of voting power),
    58  // which must sign the new header in order for us to trust it. NOTE this only
    59  // applies to non-adjacent headers. For adjacent headers, sequential
    60  // verification is used.
    61  func SkippingVerification(trustLevel tmmath.Fraction) Option {
    62  	return func(c *Client) {
    63  		c.verificationMode = skipping
    64  		c.trustLevel = trustLevel
    65  	}
    66  }
    67  
    68  // PruningSize option sets the maximum amount of headers & validator set pairs
    69  // that the light client stores. When Prune() is run, all headers (along with
    70  // the associated validator sets) that are earlier than the h amount of headers
    71  // will be removed from the store. Default: 1000. A pruning size of 0 will not
    72  // prune the lite client at all.
    73  func PruningSize(h uint16) Option {
    74  	return func(c *Client) {
    75  		c.pruningSize = h
    76  	}
    77  }
    78  
    79  // ConfirmationFunction option can be used to prompt to confirm an action. For
    80  // example, remove newer headers if the light client is being reset with an
    81  // older header. No confirmation is required by default!
    82  func ConfirmationFunction(fn func(action string) bool) Option {
    83  	return func(c *Client) {
    84  		c.confirmationFn = fn
    85  	}
    86  }
    87  
    88  // Logger option can be used to set a logger for the client.
    89  func Logger(l log.Logger) Option {
    90  	return func(c *Client) {
    91  		c.logger = l
    92  	}
    93  }
    94  
    95  // MaxRetryAttempts option can be used to set max attempts before replacing
    96  // primary with a witness.
    97  func MaxRetryAttempts(max uint16) Option {
    98  	return func(c *Client) {
    99  		c.maxRetryAttempts = max
   100  	}
   101  }
   102  
   103  // MaxClockDrift defines how much new (untrusted) header's Time can drift into
   104  // the future. Default: 10s.
   105  func MaxClockDrift(d time.Duration) Option {
   106  	return func(c *Client) {
   107  		c.maxClockDrift = d
   108  	}
   109  }
   110  
   111  // Client represents a light client, connected to a single chain, which gets
   112  // headers from a primary provider, verifies them either sequentially or by
   113  // skipping some and stores them in a trusted store (usually, a local FS).
   114  //
   115  // Default verification: SkippingVerification(DefaultTrustLevel)
   116  type Client struct {
   117  	chainID          string
   118  	trustingPeriod   time.Duration // see TrustOptions.Period
   119  	verificationMode mode
   120  	trustLevel       tmmath.Fraction
   121  	maxRetryAttempts uint16 // see MaxRetryAttempts option
   122  	maxClockDrift    time.Duration
   123  
   124  	// Mutex for locking during changes of the lite clients providers
   125  	providerMutex sync.Mutex
   126  	// Primary provider of new headers.
   127  	primary provider.Provider
   128  	// See Witnesses option
   129  	witnesses []provider.Provider
   130  
   131  	// Where trusted headers are stored.
   132  	trustedStore store.Store
   133  	// Highest trusted header from the store (height=H).
   134  	latestTrustedHeader *types.SignedHeader
   135  	// Highest validator set from the store (height=H).
   136  	latestTrustedVals *types.ValidatorSet
   137  
   138  	// See RemoveNoLongerTrustedHeadersPeriod option
   139  	pruningSize uint16
   140  	// See ConfirmationFunction option
   141  	confirmationFn func(action string) bool
   142  
   143  	quit chan struct{}
   144  
   145  	logger log.Logger
   146  }
   147  
   148  // NewClient returns a new light client. It returns an error if it fails to
   149  // obtain the header & vals from the primary or they are invalid (e.g. trust
   150  // hash does not match with the one from the header).
   151  //
   152  // Witnesses are providers, which will be used for cross-checking the primary
   153  // provider. At least one witness must be given. A witness can become a primary
   154  // iff the current primary is unavailable.
   155  //
   156  // See all Option(s) for the additional configuration.
   157  func NewClient(
   158  	chainID string,
   159  	trustOptions TrustOptions,
   160  	primary provider.Provider,
   161  	witnesses []provider.Provider,
   162  	trustedStore store.Store,
   163  	options ...Option) (*Client, error) {
   164  
   165  	if err := trustOptions.ValidateBasic(); err != nil {
   166  		return nil, fmt.Errorf("invalid TrustOptions: %w", err)
   167  	}
   168  
   169  	c, err := NewClientFromTrustedStore(chainID, trustOptions.Period, primary, witnesses, trustedStore, options...)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  
   174  	if c.latestTrustedHeader != nil {
   175  		c.logger.Info("Checking trusted header using options")
   176  		if err := c.checkTrustedHeaderUsingOptions(trustOptions); err != nil {
   177  			return nil, err
   178  		}
   179  	}
   180  
   181  	if c.latestTrustedHeader == nil || c.latestTrustedHeader.Height < trustOptions.Height {
   182  		c.logger.Info("Downloading trusted header using options")
   183  		if err := c.initializeWithTrustOptions(trustOptions); err != nil {
   184  			return nil, err
   185  		}
   186  	}
   187  
   188  	return c, err
   189  }
   190  
   191  // NewClientFromTrustedStore initializes existing client from the trusted store.
   192  //
   193  // See NewClient
   194  func NewClientFromTrustedStore(
   195  	chainID string,
   196  	trustingPeriod time.Duration,
   197  	primary provider.Provider,
   198  	witnesses []provider.Provider,
   199  	trustedStore store.Store,
   200  	options ...Option) (*Client, error) {
   201  
   202  	c := &Client{
   203  		chainID:          chainID,
   204  		trustingPeriod:   trustingPeriod,
   205  		verificationMode: skipping,
   206  		trustLevel:       DefaultTrustLevel,
   207  		maxRetryAttempts: defaultMaxRetryAttempts,
   208  		maxClockDrift:    defaultMaxClockDrift,
   209  		primary:          primary,
   210  		witnesses:        witnesses,
   211  		trustedStore:     trustedStore,
   212  		pruningSize:      defaultPruningSize,
   213  		confirmationFn:   func(action string) bool { return true },
   214  		quit:             make(chan struct{}),
   215  		logger:           log.NewNopLogger(),
   216  	}
   217  
   218  	for _, o := range options {
   219  		o(c)
   220  	}
   221  
   222  	// Validate the number of witnesses.
   223  	if len(c.witnesses) < 1 {
   224  		return nil, errNoWitnesses{}
   225  	}
   226  
   227  	// Verify witnesses are all on the same chain.
   228  	for i, w := range witnesses {
   229  		if w.ChainID() != chainID {
   230  			return nil, fmt.Errorf("witness #%d: %v is on another chain %s, expected %s",
   231  				i, w, w.ChainID(), chainID)
   232  		}
   233  	}
   234  
   235  	// Validate trust level.
   236  	if err := ValidateTrustLevel(c.trustLevel); err != nil {
   237  		return nil, err
   238  	}
   239  
   240  	if err := c.restoreTrustedHeaderAndVals(); err != nil {
   241  		return nil, err
   242  	}
   243  
   244  	return c, nil
   245  }
   246  
   247  // restoreTrustedHeaderAndVals loads trustedHeader and trustedVals from
   248  // trustedStore.
   249  func (c *Client) restoreTrustedHeaderAndVals() error {
   250  	lastHeight, err := c.trustedStore.LastSignedHeaderHeight()
   251  	if err != nil {
   252  		return fmt.Errorf("can't get last trusted header height: %w", err)
   253  	}
   254  
   255  	if lastHeight > 0 {
   256  		trustedHeader, err := c.trustedStore.SignedHeader(lastHeight)
   257  		if err != nil {
   258  			return fmt.Errorf("can't get last trusted header: %w", err)
   259  		}
   260  
   261  		trustedVals, err := c.trustedStore.ValidatorSet(lastHeight)
   262  		if err != nil {
   263  			return fmt.Errorf("can't get last trusted validators: %w", err)
   264  		}
   265  
   266  		c.latestTrustedHeader = trustedHeader
   267  		c.latestTrustedVals = trustedVals
   268  
   269  		c.logger.Info("Restored trusted header and vals", "height", lastHeight)
   270  	}
   271  
   272  	return nil
   273  }
   274  
   275  // if options.Height:
   276  //
   277  //     1) ahead of trustedHeader.Height => fetch header (same height as
   278  //     trustedHeader) from primary provider and check it's hash matches the
   279  //     trustedHeader's hash (if not, remove trustedHeader and all the headers
   280  //     before)
   281  //
   282  //     2) equals trustedHeader.Height => check options.Hash matches the
   283  //     trustedHeader's hash (if not, remove trustedHeader and all the headers
   284  //     before)
   285  //
   286  //     3) behind trustedHeader.Height => remove all the headers between
   287  //     options.Height and trustedHeader.Height, update trustedHeader, then
   288  //     check options.Hash matches the trustedHeader's hash (if not, remove
   289  //     trustedHeader and all the headers before)
   290  //
   291  // The intuition here is the user is always right. I.e. if she decides to reset
   292  // the light client with an older header, there must be a reason for it.
   293  func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error {
   294  	var primaryHash []byte
   295  	switch {
   296  	case options.Height > c.latestTrustedHeader.Height:
   297  		h, err := c.signedHeaderFromPrimary(c.latestTrustedHeader.Height)
   298  		if err != nil {
   299  			return err
   300  		}
   301  		primaryHash = h.Hash()
   302  	case options.Height == c.latestTrustedHeader.Height:
   303  		primaryHash = options.Hash
   304  	case options.Height < c.latestTrustedHeader.Height:
   305  		c.logger.Info("Client initialized with old header (trusted is more recent)",
   306  			"old", options.Height,
   307  			"trustedHeight", c.latestTrustedHeader.Height,
   308  			"trustedHash", hash2str(c.latestTrustedHeader.Hash()))
   309  
   310  		action := fmt.Sprintf(
   311  			"Rollback to %d (%X)? Note this will remove newer headers up to %d (%X)",
   312  			options.Height, options.Hash,
   313  			c.latestTrustedHeader.Height, c.latestTrustedHeader.Hash())
   314  		if c.confirmationFn(action) {
   315  			// remove all the headers (options.Height, trustedHeader.Height]
   316  			err := c.cleanupAfter(options.Height)
   317  			if err != nil {
   318  				return fmt.Errorf("cleanupAfter(%d): %w", options.Height, err)
   319  			}
   320  
   321  			c.logger.Info("Rolled back to older header (newer headers were removed)",
   322  				"old", options.Height)
   323  		} else {
   324  			return nil
   325  		}
   326  
   327  		primaryHash = options.Hash
   328  	}
   329  
   330  	if !bytes.Equal(primaryHash, c.latestTrustedHeader.Hash()) {
   331  		c.logger.Info("Prev. trusted header's hash (h1) doesn't match hash from primary provider (h2)",
   332  			"h1", hash2str(c.latestTrustedHeader.Hash()), "h2", hash2str(primaryHash))
   333  
   334  		action := fmt.Sprintf(
   335  			"Prev. trusted header's hash %X doesn't match hash %X from primary provider. Remove all the stored headers?",
   336  			c.latestTrustedHeader.Hash(), primaryHash)
   337  		if c.confirmationFn(action) {
   338  			err := c.Cleanup()
   339  			if err != nil {
   340  				return fmt.Errorf("failed to cleanup: %w", err)
   341  			}
   342  		} else {
   343  			return errors.New("refused to remove the stored headers despite hashes mismatch")
   344  		}
   345  	}
   346  
   347  	return nil
   348  }
   349  
   350  // initializeWithTrustOptions fetches the weakly-trusted header and vals from
   351  // primary provider. The header is cross-checked with witnesses for additional
   352  // security.
   353  func (c *Client) initializeWithTrustOptions(options TrustOptions) error {
   354  	// 1) Fetch and verify the header.
   355  	h, err := c.signedHeaderFromPrimary(options.Height)
   356  	if err != nil {
   357  		return err
   358  	}
   359  
   360  	// NOTE: - Verify func will check if it's expired or not.
   361  	//       - h.Time is not being checked against time.Now() because we don't
   362  	//         want to add yet another argument to NewClient* functions.
   363  	if err := h.ValidateBasic(c.chainID); err != nil {
   364  		return err
   365  	}
   366  
   367  	if !bytes.Equal(h.Hash(), options.Hash) {
   368  		return fmt.Errorf("expected header's hash %X, but got %X", options.Hash, h.Hash())
   369  	}
   370  
   371  	err = c.compareNewHeaderWithWitnesses(h)
   372  	if err != nil {
   373  		return err
   374  	}
   375  
   376  	// 2) Fetch and verify the vals.
   377  	vals, err := c.validatorSetFromPrimary(options.Height)
   378  	if err != nil {
   379  		return err
   380  	}
   381  
   382  	if !bytes.Equal(h.ValidatorsHash, vals.Hash()) {
   383  		return fmt.Errorf("expected header's validators (%X) to match those that were supplied (%X)",
   384  			h.ValidatorsHash,
   385  			vals.Hash(),
   386  		)
   387  	}
   388  
   389  	// Ensure that +2/3 of validators signed correctly.
   390  	err = vals.VerifyCommitLight(c.chainID, h.Commit.BlockID, h.Height, h.Commit)
   391  	if err != nil {
   392  		return fmt.Errorf("invalid commit: %w", err)
   393  	}
   394  
   395  	// 3) Persist both of them and continue.
   396  	return c.updateTrustedHeaderAndVals(h, vals)
   397  }
   398  
   399  // TrustedHeader returns a trusted header at the given height (0 - the latest).
   400  //
   401  // Headers along with validator sets, which can't be trusted anymore, are
   402  // removed once a day (can be changed with RemoveNoLongerTrustedHeadersPeriod
   403  // option).
   404  // .
   405  // height must be >= 0.
   406  //
   407  // It returns an error if:
   408  //  - there are some issues with the trusted store, although that should not
   409  //  happen normally;
   410  //  - negative height is passed;
   411  //  - header has not been verified yet and is therefore not in the store
   412  //
   413  // Safe for concurrent use by multiple goroutines.
   414  func (c *Client) TrustedHeader(height int64) (*types.SignedHeader, error) {
   415  	height, err := c.compareWithLatestHeight(height)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  	return c.trustedStore.SignedHeader(height)
   420  }
   421  
   422  // TrustedValidatorSet returns a trusted validator set at the given height (0 -
   423  // latest). The second return parameter is the height used (useful if 0 was
   424  // passed; otherwise can be ignored).
   425  //
   426  // height must be >= 0.
   427  //
   428  // Headers along with validator sets are
   429  // removed once a day (can be changed with RemoveNoLongerTrustedHeadersPeriod
   430  // option).
   431  //
   432  // Function returns an error if:
   433  //  - there are some issues with the trusted store, although that should not
   434  //  happen normally;
   435  //  - negative height is passed;
   436  //  - header signed by that validator set has not been verified yet
   437  //
   438  // Safe for concurrent use by multiple goroutines.
   439  func (c *Client) TrustedValidatorSet(height int64) (valSet *types.ValidatorSet, heightUsed int64, err error) {
   440  	heightUsed, err = c.compareWithLatestHeight(height)
   441  	if err != nil {
   442  		return nil, heightUsed, err
   443  	}
   444  	valSet, err = c.trustedStore.ValidatorSet(heightUsed)
   445  	if err != nil {
   446  		return nil, heightUsed, err
   447  	}
   448  	return valSet, heightUsed, err
   449  }
   450  
   451  func (c *Client) compareWithLatestHeight(height int64) (int64, error) {
   452  	latestHeight, err := c.LastTrustedHeight()
   453  	if err != nil {
   454  		return 0, fmt.Errorf("can't get last trusted height: %w", err)
   455  	}
   456  	if latestHeight == -1 {
   457  		return 0, errors.New("no headers exist")
   458  	}
   459  
   460  	switch {
   461  	case height > latestHeight:
   462  		return 0, fmt.Errorf("unverified header/valset requested (latest: %d)", latestHeight)
   463  	case height == 0:
   464  		return latestHeight, nil
   465  	case height < 0:
   466  		return 0, errors.New("negative height")
   467  	}
   468  
   469  	return height, nil
   470  }
   471  
   472  // VerifyHeaderAtHeight fetches header and validators at the given height
   473  // and calls VerifyHeader. It returns header immediately if such exists in
   474  // trustedStore (no verification is needed).
   475  //
   476  // height must be > 0.
   477  //
   478  // It returns provider.ErrSignedHeaderNotFound if header is not found by
   479  // primary.
   480  func (c *Client) VerifyHeaderAtHeight(height int64, now time.Time) (*types.SignedHeader, error) {
   481  	if height <= 0 {
   482  		return nil, errors.New("negative or zero height")
   483  	}
   484  
   485  	// Check if header already verified.
   486  	h, err := c.TrustedHeader(height)
   487  	if err == nil {
   488  		c.logger.Info("Header has already been verified", "height", height, "hash", hash2str(h.Hash()))
   489  		// Return already trusted header
   490  		return h, nil
   491  	}
   492  
   493  	// Request the header and the vals.
   494  	newHeader, newVals, err := c.fetchHeaderAndValsAtHeight(height)
   495  	if err != nil {
   496  		return nil, err
   497  	}
   498  
   499  	return newHeader, c.verifyHeader(newHeader, newVals, now)
   500  }
   501  
   502  // VerifyHeader verifies new header against the trusted state. It returns
   503  // immediately if newHeader exists in trustedStore (no verification is
   504  // needed). Else it performs one of the two types of verification:
   505  //
   506  // SequentialVerification: verifies that 2/3 of the trusted validator set has
   507  // signed the new header. If the headers are not adjacent, **all** intermediate
   508  // headers will be requested. Intermediate headers are not saved to database.
   509  //
   510  // SkippingVerification(trustLevel): verifies that {trustLevel} of the trusted
   511  // validator set has signed the new header. If it's not the case and the
   512  // headers are not adjacent, bisection is performed and necessary (not all)
   513  // intermediate headers will be requested. See the specification for details.
   514  // Intermediate headers are not saved to database.
   515  // https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md
   516  //
   517  // If the header, which is older than the currently trusted header, is
   518  // requested and the light client does not have it, VerifyHeader will perform:
   519  //		a) bisection verification if nearest trusted header is found & not expired
   520  //		b) backwards verification in all other cases
   521  //
   522  // It returns ErrOldHeaderExpired if the latest trusted header expired.
   523  //
   524  // If the primary provides an invalid header (ErrInvalidHeader), it is rejected
   525  // and replaced by another provider until all are exhausted.
   526  //
   527  // If, at any moment, SignedHeader or ValidatorSet are not found by the primary
   528  // provider, provider.ErrSignedHeaderNotFound /
   529  // provider.ErrValidatorSetNotFound error is returned.
   530  func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.ValidatorSet, now time.Time) error {
   531  	if newHeader.Height <= 0 {
   532  		return errors.New("negative or zero height")
   533  	}
   534  
   535  	// Check if newHeader already verified.
   536  	h, err := c.TrustedHeader(newHeader.Height)
   537  	if err == nil {
   538  		// Make sure it's the same header.
   539  		if !bytes.Equal(h.Hash(), newHeader.Hash()) {
   540  			return fmt.Errorf("existing trusted header %X does not match newHeader %X", h.Hash(), newHeader.Hash())
   541  		}
   542  		c.logger.Info("Header has already been verified",
   543  			"height", newHeader.Height, "hash", hash2str(newHeader.Hash()))
   544  		return nil
   545  	}
   546  
   547  	return c.verifyHeader(newHeader, newVals, now)
   548  }
   549  
   550  func (c *Client) verifyHeader(newHeader *types.SignedHeader, newVals *types.ValidatorSet, now time.Time) error {
   551  	c.logger.Info("VerifyHeader", "height", newHeader.Height, "hash", hash2str(newHeader.Hash()),
   552  		"vals", hash2str(newVals.Hash()))
   553  
   554  	var err error
   555  
   556  	// 1) If going forward, perform either bisection or sequential verification.
   557  	if newHeader.Height >= c.latestTrustedHeader.Height {
   558  		switch c.verificationMode {
   559  		case sequential:
   560  			err = c.sequence(c.latestTrustedHeader, newHeader, newVals, now)
   561  		case skipping:
   562  			err = c.bisection(c.latestTrustedHeader, c.latestTrustedVals, newHeader, newVals, now)
   563  		default:
   564  			panic(fmt.Sprintf("Unknown verification mode: %b", c.verificationMode))
   565  		}
   566  	} else {
   567  		// 2) If verifying before the first trusted header, perform backwards
   568  		// verification.
   569  		var (
   570  			closestHeader     *types.SignedHeader
   571  			firstHeaderHeight int64
   572  		)
   573  		firstHeaderHeight, err = c.FirstTrustedHeight()
   574  		if err != nil {
   575  			return fmt.Errorf("can't get first header height: %w", err)
   576  		}
   577  		if newHeader.Height < firstHeaderHeight {
   578  			closestHeader, err = c.TrustedHeader(firstHeaderHeight)
   579  			if err != nil {
   580  				return fmt.Errorf("can't get first signed header: %w", err)
   581  			}
   582  			if HeaderExpired(closestHeader, c.trustingPeriod, now) {
   583  				closestHeader = c.latestTrustedHeader
   584  			}
   585  			err = c.backwards(closestHeader, newHeader, now)
   586  		} else {
   587  			// 3) OR if between trusted headers where the nearest has not expired,
   588  			// perform bisection verification, else backwards.
   589  			closestHeader, err = c.trustedStore.SignedHeaderBefore(newHeader.Height)
   590  			if err != nil {
   591  				return fmt.Errorf("can't get signed header before height %d: %w", newHeader.Height, err)
   592  			}
   593  			var closestValidatorSet *types.ValidatorSet
   594  			if c.verificationMode == sequential || HeaderExpired(closestHeader, c.trustingPeriod, now) {
   595  				err = c.backwards(c.latestTrustedHeader, newHeader, now)
   596  			} else {
   597  				closestValidatorSet, _, err = c.TrustedValidatorSet(closestHeader.Height)
   598  				if err != nil {
   599  					return fmt.Errorf("can't get validator set at height %d: %w", closestHeader.Height, err)
   600  				}
   601  				err = c.bisection(closestHeader, closestValidatorSet, newHeader, newVals, now)
   602  			}
   603  		}
   604  	}
   605  	if err != nil {
   606  		c.logger.Error("Can't verify", "err", err)
   607  		return err
   608  	}
   609  	// 4) Compare header with other witnesses
   610  	if err := c.compareNewHeaderWithWitnesses(newHeader); err != nil {
   611  		c.logger.Error("Error when comparing new header with witnesses", "err", err)
   612  		return err
   613  	}
   614  
   615  	// 5) Once verified, save and return
   616  	return c.updateTrustedHeaderAndVals(newHeader, newVals)
   617  }
   618  
   619  // see VerifyHeader
   620  func (c *Client) sequence(
   621  	initiallyTrustedHeader *types.SignedHeader,
   622  	newHeader *types.SignedHeader,
   623  	newVals *types.ValidatorSet,
   624  	now time.Time) error {
   625  
   626  	var (
   627  		trustedHeader = initiallyTrustedHeader
   628  
   629  		interimHeader *types.SignedHeader
   630  		interimVals   *types.ValidatorSet
   631  
   632  		err error
   633  	)
   634  
   635  	for height := initiallyTrustedHeader.Height + 1; height <= newHeader.Height; height++ {
   636  		// 1) Fetch interim headers and vals if needed.
   637  		if height == newHeader.Height { // last header
   638  			interimHeader, interimVals = newHeader, newVals
   639  		} else { // intermediate headers
   640  			interimHeader, interimVals, err = c.fetchHeaderAndValsAtHeight(height)
   641  			if err != nil {
   642  				return err
   643  			}
   644  		}
   645  
   646  		// 2) Verify them
   647  		c.logger.Debug("Verify newHeader against trustedHeader",
   648  			"trustedHeight", trustedHeader.Height,
   649  			"trustedHash", hash2str(trustedHeader.Hash()),
   650  			"newHeight", interimHeader.Height,
   651  			"newHash", hash2str(interimHeader.Hash()))
   652  
   653  		err = VerifyAdjacent(c.chainID, trustedHeader, interimHeader, interimVals,
   654  			c.trustingPeriod, now, c.maxClockDrift)
   655  		if err != nil {
   656  			err = fmt.Errorf("verify adjacent from #%d to #%d failed: %w",
   657  				trustedHeader.Height, interimHeader.Height, err)
   658  
   659  			switch errors.Unwrap(err).(type) {
   660  			case ErrInvalidHeader:
   661  				c.logger.Error("primary sent invalid header -> replacing", "err", err)
   662  				replaceErr := c.replacePrimaryProvider()
   663  				if replaceErr != nil {
   664  					c.logger.Error("Can't replace primary", "err", replaceErr)
   665  					return err // return original error
   666  				}
   667  				// attempt to verify header again
   668  				height--
   669  				continue
   670  			default:
   671  				return err
   672  			}
   673  		}
   674  
   675  		// 3) Update trustedHeader
   676  		trustedHeader = interimHeader
   677  	}
   678  
   679  	return nil
   680  }
   681  
   682  // see VerifyHeader
   683  // Bisection finds the middle header between a trusted and new header, reiterating the action until it
   684  // verifies a header. A cache of headers requested by the primary is kept such that when a
   685  // verification is made, and the light client tries again to verify the new header in the middle,
   686  // the light client does not need to ask for all the same headers again.
   687  func (c *Client) bisection(
   688  	initiallyTrustedHeader *types.SignedHeader,
   689  	initiallyTrustedVals *types.ValidatorSet,
   690  	newHeader *types.SignedHeader,
   691  	newVals *types.ValidatorSet,
   692  	now time.Time) error {
   693  
   694  	type headerSet struct {
   695  		sh     *types.SignedHeader
   696  		valSet *types.ValidatorSet
   697  	}
   698  
   699  	var (
   700  		headerCache = []headerSet{{newHeader, newVals}}
   701  		depth       = 0
   702  
   703  		trustedHeader = initiallyTrustedHeader
   704  		trustedVals   = initiallyTrustedVals
   705  	)
   706  
   707  	for {
   708  		c.logger.Debug("Verify newHeader against trustedHeader",
   709  			"trustedHeight", trustedHeader.Height,
   710  			"trustedHash", hash2str(trustedHeader.Hash()),
   711  			"newHeight", headerCache[depth].sh.Height,
   712  			"newHash", hash2str(headerCache[depth].sh.Hash()))
   713  
   714  		err := Verify(c.chainID, trustedHeader, trustedVals, headerCache[depth].sh, headerCache[depth].valSet,
   715  			c.trustingPeriod, now, c.maxClockDrift, c.trustLevel)
   716  		switch err.(type) {
   717  		case nil:
   718  			// Have we verified the last header
   719  			if depth == 0 {
   720  				return nil
   721  			}
   722  			// If not, update the lower bound to the previous upper bound
   723  			trustedHeader, trustedVals = headerCache[depth].sh, headerCache[depth].valSet
   724  			// Remove the untrusted header at the lower bound in the header cache - it's no longer useful
   725  			headerCache = headerCache[:depth]
   726  			// Reset the cache depth so that we start from the upper bound again
   727  			depth = 0
   728  
   729  		case ErrNewValSetCantBeTrusted:
   730  			// do add another header to the end of the cache
   731  			if depth == len(headerCache)-1 {
   732  				pivotHeight := trustedHeader.Height + (headerCache[depth].sh.Height-trustedHeader.
   733  					Height)*bisectionNumerator/bisectionDenominator
   734  				interimHeader, interimVals, err := c.fetchHeaderAndValsAtHeight(pivotHeight)
   735  				if err != nil {
   736  					return err
   737  				}
   738  				headerCache = append(headerCache, headerSet{interimHeader, interimVals})
   739  			}
   740  			depth++
   741  
   742  		case ErrInvalidHeader:
   743  			c.logger.Error("primary sent invalid header -> replacing", "err", err)
   744  			replaceErr := c.replacePrimaryProvider()
   745  			if replaceErr != nil {
   746  				c.logger.Error("Can't replace primary", "err", replaceErr)
   747  				// return original error
   748  				return fmt.Errorf("verify non adjacent from #%d to #%d failed: %w",
   749  					trustedHeader.Height, headerCache[depth].sh.Height, err)
   750  			}
   751  			// attempt to verify the header again
   752  			continue
   753  
   754  		default:
   755  			return fmt.Errorf("verify non adjacent from #%d to #%d failed: %w",
   756  				trustedHeader.Height, headerCache[depth].sh.Height, err)
   757  		}
   758  	}
   759  }
   760  
   761  // LastTrustedHeight returns a last trusted height. -1 and nil are returned if
   762  // there are no trusted headers.
   763  //
   764  // Safe for concurrent use by multiple goroutines.
   765  func (c *Client) LastTrustedHeight() (int64, error) {
   766  	return c.trustedStore.LastSignedHeaderHeight()
   767  }
   768  
   769  // FirstTrustedHeight returns a first trusted height. -1 and nil are returned if
   770  // there are no trusted headers.
   771  //
   772  // Safe for concurrent use by multiple goroutines.
   773  func (c *Client) FirstTrustedHeight() (int64, error) {
   774  	return c.trustedStore.FirstSignedHeaderHeight()
   775  }
   776  
   777  // ChainID returns the chain ID the light client was configured with.
   778  //
   779  // Safe for concurrent use by multiple goroutines.
   780  func (c *Client) ChainID() string {
   781  	return c.chainID
   782  }
   783  
   784  // Primary returns the primary provider.
   785  //
   786  // NOTE: provider may be not safe for concurrent access.
   787  func (c *Client) Primary() provider.Provider {
   788  	c.providerMutex.Lock()
   789  	defer c.providerMutex.Unlock()
   790  	return c.primary
   791  }
   792  
   793  // Witnesses returns the witness providers.
   794  //
   795  // NOTE: providers may be not safe for concurrent access.
   796  func (c *Client) Witnesses() []provider.Provider {
   797  	c.providerMutex.Lock()
   798  	defer c.providerMutex.Unlock()
   799  	return c.witnesses
   800  }
   801  
   802  // Cleanup removes all the data (headers and validator sets) stored. Note: the
   803  // client must be stopped at this point.
   804  func (c *Client) Cleanup() error {
   805  	c.logger.Info("Removing all the data")
   806  	c.latestTrustedHeader = nil
   807  	c.latestTrustedVals = nil
   808  	return c.trustedStore.Prune(0)
   809  }
   810  
   811  // cleanupAfter deletes all headers & validator sets after +height+. It also
   812  // resets latestTrustedHeader to the latest header.
   813  func (c *Client) cleanupAfter(height int64) error {
   814  	prevHeight := c.latestTrustedHeader.Height
   815  
   816  	for {
   817  		h, err := c.trustedStore.SignedHeaderBefore(prevHeight)
   818  		if err == store.ErrSignedHeaderNotFound || (h != nil && h.Height <= height) {
   819  			break
   820  		} else if err != nil {
   821  			return fmt.Errorf("failed to get header before %d: %w", prevHeight, err)
   822  		}
   823  
   824  		err = c.trustedStore.DeleteSignedHeaderAndValidatorSet(h.Height)
   825  		if err != nil {
   826  			c.logger.Error("can't remove a trusted header & validator set", "err", err,
   827  				"height", h.Height)
   828  		}
   829  
   830  		prevHeight = h.Height
   831  	}
   832  
   833  	c.latestTrustedHeader = nil
   834  	c.latestTrustedVals = nil
   835  	err := c.restoreTrustedHeaderAndVals()
   836  	if err != nil {
   837  		return err
   838  	}
   839  
   840  	return nil
   841  }
   842  
   843  func (c *Client) updateTrustedHeaderAndVals(h *types.SignedHeader, vals *types.ValidatorSet) error {
   844  	if !bytes.Equal(h.ValidatorsHash, vals.Hash()) {
   845  		return fmt.Errorf("expected validator's hash %X, but got %X", h.ValidatorsHash, vals.Hash())
   846  	}
   847  
   848  	if err := c.trustedStore.SaveSignedHeaderAndValidatorSet(h, vals); err != nil {
   849  		return fmt.Errorf("failed to save trusted header: %w", err)
   850  	}
   851  
   852  	if c.pruningSize > 0 {
   853  		if err := c.trustedStore.Prune(c.pruningSize); err != nil {
   854  			return fmt.Errorf("prune: %w", err)
   855  		}
   856  	}
   857  
   858  	if c.latestTrustedHeader == nil || h.Height > c.latestTrustedHeader.Height {
   859  		c.latestTrustedHeader = h
   860  		c.latestTrustedVals = vals
   861  	}
   862  
   863  	return nil
   864  }
   865  
   866  // fetch header and validators for the given height (0 - latest) from primary
   867  // provider.
   868  func (c *Client) fetchHeaderAndValsAtHeight(height int64) (*types.SignedHeader, *types.ValidatorSet, error) {
   869  	h, err := c.signedHeaderFromPrimary(height)
   870  	if err != nil {
   871  		return nil, nil, fmt.Errorf("failed to obtain the header #%d: %w", height, err)
   872  	}
   873  	vals, err := c.validatorSetFromPrimary(height)
   874  	if err != nil {
   875  		return nil, nil, fmt.Errorf("failed to obtain the vals #%d: %w", height, err)
   876  	}
   877  	return h, vals, nil
   878  }
   879  
   880  // backwards verification (see VerifyHeaderBackwards func in the spec) verifies
   881  // headers before a trusted header. If a sent header is invalid the primary is
   882  // replaced with another provider and the operation is repeated.
   883  func (c *Client) backwards(
   884  	initiallyTrustedHeader *types.SignedHeader,
   885  	newHeader *types.SignedHeader,
   886  	now time.Time) error {
   887  
   888  	if HeaderExpired(initiallyTrustedHeader, c.trustingPeriod, now) {
   889  		c.logger.Error("Header Expired")
   890  		return ErrOldHeaderExpired{initiallyTrustedHeader.Time.Add(c.trustingPeriod), now}
   891  	}
   892  
   893  	var (
   894  		trustedHeader = initiallyTrustedHeader
   895  		interimHeader *types.SignedHeader
   896  		err           error
   897  	)
   898  
   899  	for trustedHeader.Height > newHeader.Height {
   900  		interimHeader, err = c.signedHeaderFromPrimary(trustedHeader.Height - 1)
   901  		if err != nil {
   902  			return fmt.Errorf("failed to obtain the header at height #%d: %w", trustedHeader.Height-1, err)
   903  		}
   904  		c.logger.Debug("Verify newHeader against trustedHeader",
   905  			"trustedHeight", trustedHeader.Height,
   906  			"trustedHash", hash2str(trustedHeader.Hash()),
   907  			"newHeight", interimHeader.Height,
   908  			"newHash", hash2str(interimHeader.Hash()))
   909  		if err := VerifyBackwards(c.chainID, interimHeader, trustedHeader); err != nil {
   910  			c.logger.Error("primary sent invalid header -> replacing", "err", err)
   911  			if replaceErr := c.replacePrimaryProvider(); replaceErr != nil {
   912  				c.logger.Error("Can't replace primary", "err", replaceErr)
   913  				// return original error
   914  				return fmt.Errorf("verify backwards from %d to %d failed: %w",
   915  					trustedHeader.Height, interimHeader.Height, err)
   916  			}
   917  		}
   918  
   919  		trustedHeader = interimHeader
   920  	}
   921  
   922  	// Initially trusted header might have expired at this point.
   923  	if HeaderExpired(initiallyTrustedHeader, c.trustingPeriod, now) {
   924  		return ErrOldHeaderExpired{initiallyTrustedHeader.Time.Add(c.trustingPeriod), now}
   925  	}
   926  
   927  	return nil
   928  }
   929  
   930  // compare header with all witnesses provided.
   931  func (c *Client) compareNewHeaderWithWitnesses(h *types.SignedHeader) error {
   932  	c.providerMutex.Lock()
   933  	defer c.providerMutex.Unlock()
   934  
   935  	// 1. Make sure AT LEAST ONE witness returns the same header.
   936  	headerMatched := false
   937  	witnessesToRemove := make([]int, 0)
   938  	for attempt := uint16(1); attempt <= c.maxRetryAttempts; attempt++ {
   939  		if len(c.witnesses) == 0 {
   940  			return errNoWitnesses{}
   941  		}
   942  
   943  		for i, witness := range c.witnesses {
   944  			altH, err := witness.SignedHeader(h.Height)
   945  			if err != nil {
   946  				c.logger.Error("Failed to get a header from witness", "height", h.Height, "witness", witness)
   947  				continue
   948  			}
   949  
   950  			if err = altH.ValidateBasic(c.chainID); err != nil {
   951  				c.logger.Error("Witness sent us incorrect header", "err", err, "witness", witness)
   952  				witnessesToRemove = append(witnessesToRemove, i)
   953  				continue
   954  			}
   955  
   956  			if !bytes.Equal(h.Hash(), altH.Hash()) {
   957  				if err = c.latestTrustedVals.VerifyCommitLightTrusting(c.chainID, altH.Commit.BlockID,
   958  					altH.Height, altH.Commit, c.trustLevel); err != nil {
   959  					c.logger.Error("Witness sent us incorrect header", "err", err, "witness", witness)
   960  					witnessesToRemove = append(witnessesToRemove, i)
   961  					continue
   962  				}
   963  
   964  				// TODO: send the diverged headers to primary && all witnesses
   965  
   966  				return fmt.Errorf(
   967  					"header hash %X does not match one %X from the witness %v",
   968  					h.Hash(), altH.Hash(), witness)
   969  			}
   970  
   971  			headerMatched = true
   972  		}
   973  
   974  		for _, idx := range witnessesToRemove {
   975  			c.removeWitness(idx)
   976  		}
   977  		witnessesToRemove = make([]int, 0)
   978  
   979  		if headerMatched {
   980  			return nil
   981  		}
   982  
   983  		// 2. Otherwise, sleep
   984  		time.Sleep(backoffTimeout(attempt))
   985  	}
   986  
   987  	return errors.New("awaiting response from all witnesses exceeded dropout time")
   988  }
   989  
   990  // NOTE: requires a providerMutex locked.
   991  func (c *Client) removeWitness(idx int) {
   992  	switch len(c.witnesses) {
   993  	case 0:
   994  		panic(fmt.Sprintf("wanted to remove %d element from empty witnesses slice", idx))
   995  	case 1:
   996  		c.witnesses = make([]provider.Provider, 0)
   997  	default:
   998  		c.witnesses[idx] = c.witnesses[len(c.witnesses)-1]
   999  		c.witnesses = c.witnesses[:len(c.witnesses)-1]
  1000  	}
  1001  }
  1002  
  1003  // Update attempts to advance the state by downloading the latest header and
  1004  // comparing it with the existing one. It returns a new header on a successful
  1005  // update. Otherwise, it returns nil (plus an error, if any).
  1006  func (c *Client) Update(now time.Time) (*types.SignedHeader, error) {
  1007  	lastTrustedHeight, err := c.LastTrustedHeight()
  1008  	if err != nil {
  1009  		return nil, fmt.Errorf("can't get last trusted height: %w", err)
  1010  	}
  1011  
  1012  	if lastTrustedHeight == -1 {
  1013  		// no headers yet => wait
  1014  		return nil, nil
  1015  	}
  1016  
  1017  	latestHeader, latestVals, err := c.fetchHeaderAndValsAtHeight(0)
  1018  	if err != nil {
  1019  		return nil, err
  1020  	}
  1021  
  1022  	if latestHeader.Height > lastTrustedHeight {
  1023  		err = c.VerifyHeader(latestHeader, latestVals, now)
  1024  		if err != nil {
  1025  			return nil, err
  1026  		}
  1027  		c.logger.Info("Advanced to new state", "height", latestHeader.Height, "hash", hash2str(latestHeader.Hash()))
  1028  		return latestHeader, nil
  1029  	}
  1030  
  1031  	return nil, nil
  1032  }
  1033  
  1034  // replaceProvider takes the first alternative provider and promotes it as the
  1035  // primary provider.
  1036  func (c *Client) replacePrimaryProvider() error {
  1037  	c.providerMutex.Lock()
  1038  	defer c.providerMutex.Unlock()
  1039  
  1040  	if len(c.witnesses) <= 1 {
  1041  		return errNoWitnesses{}
  1042  	}
  1043  	c.primary = c.witnesses[0]
  1044  	c.witnesses = c.witnesses[1:]
  1045  	c.logger.Info("New primary", "p", c.primary)
  1046  
  1047  	return nil
  1048  }
  1049  
  1050  // signedHeaderFromPrimary retrieves the SignedHeader from the primary provider
  1051  // at the specified height. Handles dropout by the primary provider by swapping
  1052  // with an alternative provider.
  1053  func (c *Client) signedHeaderFromPrimary(height int64) (*types.SignedHeader, error) {
  1054  	for attempt := uint16(1); attempt <= c.maxRetryAttempts; attempt++ {
  1055  		c.providerMutex.Lock()
  1056  		h, err := c.primary.SignedHeader(height)
  1057  		c.providerMutex.Unlock()
  1058  		if err == nil {
  1059  			// sanity check
  1060  			if height > 0 && h.Height != height {
  1061  				return nil, fmt.Errorf("expected %d height, got %d", height, h.Height)
  1062  			}
  1063  			return h, nil
  1064  		}
  1065  		if err == provider.ErrSignedHeaderNotFound {
  1066  			return nil, err
  1067  		}
  1068  		c.logger.Error("Failed to get signed header from primary", "attempt", attempt, "err", err)
  1069  		time.Sleep(backoffTimeout(attempt))
  1070  	}
  1071  
  1072  	c.logger.Info("Primary is unavailable. Replacing with the first witness")
  1073  	err := c.replacePrimaryProvider()
  1074  	if err != nil {
  1075  		return nil, err
  1076  	}
  1077  
  1078  	return c.signedHeaderFromPrimary(height)
  1079  }
  1080  
  1081  // validatorSetFromPrimary retrieves the ValidatorSet from the primary provider
  1082  // at the specified height. Handles dropout by the primary provider after 5
  1083  // attempts by replacing it with an alternative provider.
  1084  func (c *Client) validatorSetFromPrimary(height int64) (*types.ValidatorSet, error) {
  1085  	for attempt := uint16(1); attempt <= c.maxRetryAttempts; attempt++ {
  1086  		c.providerMutex.Lock()
  1087  		vals, err := c.primary.ValidatorSet(height)
  1088  		c.providerMutex.Unlock()
  1089  		if err == nil || err == provider.ErrValidatorSetNotFound {
  1090  			return vals, err
  1091  		}
  1092  		c.logger.Error("Failed to get validator set from primary", "attempt", attempt, "err", err)
  1093  		time.Sleep(backoffTimeout(attempt))
  1094  	}
  1095  
  1096  	c.logger.Info("Primary is unavailable. Replacing with the first witness")
  1097  	err := c.replacePrimaryProvider()
  1098  	if err != nil {
  1099  		return nil, err
  1100  	}
  1101  
  1102  	return c.validatorSetFromPrimary(height)
  1103  }
  1104  
  1105  // exponential backoff (with jitter)
  1106  //		0.5s -> 2s -> 4.5s -> 8s -> 12.5 with 1s variation
  1107  func backoffTimeout(attempt uint16) time.Duration {
  1108  	return time.Duration(500*attempt*attempt)*time.Millisecond + time.Duration(rand.Intn(1000))*time.Millisecond
  1109  }
  1110  
  1111  func hash2str(hash []byte) string {
  1112  	return fmt.Sprintf("%X", hash)
  1113  }