if options.Height: 1. ahead of trustedLightBlock.Height => fetch light blocks (same height as trustedLightBlock) from primary provider and check it's hash matches the trustedLightBlock's hash (if not, remove trustedLightBlock and all the light blocks before) 2. equals trustedLightBlock.Height => c
(ctx context.Context, options TrustOptions)
| 301 | // The intuition here is the user is always right. I.e. if she decides to reset |
| 302 | // the light client with an older header, there must be a reason for it. |
| 303 | func (c *Client) checkTrustedHeaderUsingOptions(ctx context.Context, options TrustOptions) error { |
| 304 | var primaryHash []byte |
| 305 | switch { |
| 306 | case options.Height > c.latestTrustedBlock.Height: |
| 307 | h, err := c.lightBlockFromPrimary(ctx, c.latestTrustedBlock.Height) |
| 308 | if err != nil { |
| 309 | return err |
| 310 | } |
| 311 | primaryHash = h.Hash() |
| 312 | case options.Height == c.latestTrustedBlock.Height: |
| 313 | primaryHash = options.Hash |
| 314 | case options.Height < c.latestTrustedBlock.Height: |
| 315 | c.logger.Info("Client initialized with old header (trusted is more recent)", |
| 316 | "old", options.Height, |
| 317 | "trustedHeight", c.latestTrustedBlock.Height, |
| 318 | "trustedHash", c.latestTrustedBlock.Hash()) |
| 319 | |
| 320 | action := fmt.Sprintf( |
| 321 | "Rollback to %d (%X)? Note this will remove newer light blocks up to %d (%X)", |
| 322 | options.Height, options.Hash, |
| 323 | c.latestTrustedBlock.Height, c.latestTrustedBlock.Hash()) |
| 324 | if c.confirmationFn(action) { |
| 325 | // remove all the headers (options.Height, trustedHeader.Height] |
| 326 | err := c.cleanupAfter(options.Height) |
| 327 | if err != nil { |
| 328 | return fmt.Errorf("cleanupAfter(%d): %w", options.Height, err) |
| 329 | } |
| 330 | |
| 331 | c.logger.Info("Rolled back to older header (newer headers were removed)", |
| 332 | "old", options.Height) |
| 333 | } else { |
| 334 | return nil |
| 335 | } |
| 336 | |
| 337 | primaryHash = options.Hash |
| 338 | } |
| 339 | |
| 340 | if !bytes.Equal(primaryHash, c.latestTrustedBlock.Hash()) { |
| 341 | c.logger.Info("Prev. trusted header's hash (h1) doesn't match hash from primary provider (h2)", |
| 342 | "h1", c.latestTrustedBlock.Hash(), "h2", primaryHash) |
| 343 | |
| 344 | action := fmt.Sprintf( |
| 345 | "Prev. trusted header's hash %X doesn't match hash %X from primary provider. Remove all the stored light blocks?", |
| 346 | c.latestTrustedBlock.Hash(), primaryHash) |
| 347 | if c.confirmationFn(action) { |
| 348 | err := c.Cleanup() |
| 349 | if err != nil { |
| 350 | return fmt.Errorf("failed to cleanup: %w", err) |
| 351 | } |
| 352 | } else { |
| 353 | return errors.New("refused to remove the stored light blocks despite hashes mismatch") |
| 354 | } |
| 355 | } |
| 356 | |
| 357 | return nil |
| 358 | } |
| 359 | |
| 360 | // initializeWithTrustOptions fetches the weakly-trusted light block from |
no test coverage detected