light: minor fixes / standardising errors (#5716)

## Description

I'm just doing a self audit of the light client. There's a few things I've changed

- Validate trust level in `VerifyNonAdjacent` function
- Make errNoWitnesses public (it's something people running software on top of a light client should be able to parse)
- Remove `ChainID` check of witnesses on start up. We do this already when we compare the first header with witnesses
- Remove `ChainID()` from provider interface

Closes: #4538
This commit is contained in:
Callum Waters
2020-12-01 13:53:53 +01:00
committed by GitHub
parent b1bbd37519
commit f368b91caf
9 changed files with 47 additions and 62 deletions

View File

@@ -219,15 +219,7 @@ func NewClientFromTrustedStore(
// Validate the number of witnesses.
if len(c.witnesses) < 1 {
return nil, errNoWitnesses{}
}
// Verify witnesses are all on the same chain.
for i, w := range witnesses {
if w.ChainID() != chainID {
return nil, fmt.Errorf("witness #%d: %v is on another chain %s, expected %s",
i, w, w.ChainID(), chainID)
}
return nil, ErrNoWitnesses
}
// Validate trust level.
@@ -455,7 +447,7 @@ func (c *Client) VerifyLightBlockAtHeight(ctx context.Context, height int64, now
return nil, errors.New("negative or zero height")
}
// Check if the light block already verified.
// Check if the light block is already verified.
h, err := c.TrustedLightBlock(height)
if err == nil {
c.logger.Info("Header has already been verified", "height", height, "hash", hash2str(h.Hash()))
@@ -634,7 +626,7 @@ func (c *Client) verifySequential(
// If some intermediate header is invalid, replace the primary and try
// again.
c.logger.Error("primary sent invalid header -> replacing", "err", err)
c.logger.Error("primary sent invalid header -> replacing", "err", err, "primary", c.primary)
replaceErr := c.replacePrimaryProvider()
if replaceErr != nil {
c.logger.Error("Can't replace primary", "err", replaceErr)
@@ -768,7 +760,7 @@ func (c *Client) verifySkippingAgainstPrimary(
// If some intermediate header is invalid, replace the primary and try
// again.
c.logger.Error("primary sent invalid header -> replacing", "err", err)
c.logger.Error("primary sent invalid header -> replacing", "err", err, "primary", c.primary)
replaceErr := c.replacePrimaryProvider()
if replaceErr != nil {
c.logger.Error("Can't replace primary", "err", replaceErr)
@@ -853,7 +845,7 @@ func (c *Client) Witnesses() []provider.Provider {
// Cleanup removes all the data (headers and validator sets) stored. Note: the
// client must be stopped at this point.
func (c *Client) Cleanup() error {
c.logger.Info("Removing all the data")
c.logger.Info("Removing all light blocks")
c.latestTrustedBlock = nil
return c.trustedStore.Prune(0)
}
@@ -932,7 +924,7 @@ func (c *Client) backwards(
"newHeight", interimHeader.Height,
"newHash", hash2str(interimHeader.Hash()))
if err := VerifyBackwards(interimHeader, verifiedHeader); err != nil {
c.logger.Error("primary sent invalid header -> replacing", "err", err)
c.logger.Error("primary sent invalid header -> replacing", "err", err, "primary", c.primary)
if replaceErr := c.replacePrimaryProvider(); replaceErr != nil {
c.logger.Error("Can't replace primary", "err", replaceErr)
// return original error
@@ -968,7 +960,7 @@ func (c *Client) replacePrimaryProvider() error {
defer c.providerMutex.Unlock()
if len(c.witnesses) <= 1 {
return errNoWitnesses{}
return ErrNoWitnesses
}
c.primary = c.witnesses[0]
c.witnesses = c.witnesses[1:]
@@ -985,7 +977,7 @@ func (c *Client) lightBlockFromPrimary(ctx context.Context, height int64) (*type
l, err := c.primary.LightBlock(ctx, height)
c.providerMutex.Unlock()
if err != nil {
c.logger.Debug("Error on light block request from primary", "error", err)
c.logger.Debug("Error on light block request from primary", "error", err, "primary", c.primary)
replaceErr := c.replacePrimaryProvider()
if replaceErr != nil {
return nil, fmt.Errorf("%v. Tried to replace primary but: %w", err.Error(), replaceErr)
@@ -1003,7 +995,7 @@ func (c *Client) compareFirstHeaderWithWitnesses(ctx context.Context, h *types.S
defer cancel()
if len(c.witnesses) < 1 {
return errNoWitnesses{}
return ErrNoWitnesses
}
errc := make(chan error, len(c.witnesses))