From fd50d90b7033fb720b86c3498f5f09f675ce0fdc Mon Sep 17 00:00:00 2001 From: Sam Kleinman Date: Tue, 8 Feb 2022 12:26:24 -0500 Subject: [PATCH] light: remove legacy timeout scheme (#7776) --- internal/statesync/stateprovider.go | 36 +++++++++++++++++++---------- light/client.go | 26 +++++---------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/internal/statesync/stateprovider.go b/internal/statesync/stateprovider.go index dc54ee3e2..d7ee77fd2 100644 --- a/internal/statesync/stateprovider.go +++ b/internal/statesync/stateprovider.go @@ -87,6 +87,12 @@ func NewRPCStateProvider( }, nil } +func (s *stateProviderRPC) verifyLightBlockAtHeight(ctx context.Context, height uint64, ts time.Time) (*types.LightBlock, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + return s.lc.VerifyLightBlockAtHeight(ctx, int64(height), ts) +} + // AppHash implements part of StateProvider. It calls the application to verify the // light blocks at heights h+1 and h+2 and, if verification succeeds, reports the app // hash for the block at height h+1 which correlates to the state at height h. @@ -95,7 +101,7 @@ func (s *stateProviderRPC) AppHash(ctx context.Context, height uint64) ([]byte, defer s.Unlock() // We have to fetch the next height, which contains the app hash for the previous height. - header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + header, err := s.verifyLightBlockAtHeight(ctx, height+1, time.Now()) if err != nil { return nil, err } @@ -103,7 +109,7 @@ func (s *stateProviderRPC) AppHash(ctx context.Context, height uint64) ([]byte, // We also try to fetch the blocks at H+2, since we need these // when building the state while restoring the snapshot. This avoids the race // condition where we try to restore a snapshot before H+2 exists. - _, err = s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + _, err = s.verifyLightBlockAtHeight(ctx, height+2, time.Now()) if err != nil { return nil, err } @@ -114,7 +120,7 @@ func (s *stateProviderRPC) AppHash(ctx context.Context, height uint64) ([]byte, func (s *stateProviderRPC) Commit(ctx context.Context, height uint64) (*types.Commit, error) { s.Lock() defer s.Unlock() - header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + header, err := s.verifyLightBlockAtHeight(ctx, height, time.Now()) if err != nil { return nil, err } @@ -142,15 +148,15 @@ func (s *stateProviderRPC) State(ctx context.Context, height uint64) (sm.State, // // We need to fetch the NextValidators from height+2 because if the application changed // the validator set at the snapshot height then this only takes effect at height+2. - lastLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + lastLightBlock, err := s.verifyLightBlockAtHeight(ctx, height, time.Now()) if err != nil { return sm.State{}, err } - currentLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + currentLightBlock, err := s.verifyLightBlockAtHeight(ctx, height+1, time.Now()) if err != nil { return sm.State{}, err } - nextLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + nextLightBlock, err := s.verifyLightBlockAtHeight(ctx, height+2, time.Now()) if err != nil { return sm.State{}, err } @@ -235,13 +241,19 @@ func NewP2PStateProvider( }, nil } +func (s *stateProviderP2P) verifyLightBlockAtHeight(ctx context.Context, height uint64, ts time.Time) (*types.LightBlock, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + return s.lc.VerifyLightBlockAtHeight(ctx, int64(height), ts) +} + // AppHash implements StateProvider. func (s *stateProviderP2P) AppHash(ctx context.Context, height uint64) ([]byte, error) { s.Lock() defer s.Unlock() // We have to fetch the next height, which contains the app hash for the previous height. - header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + header, err := s.verifyLightBlockAtHeight(ctx, height+1, time.Now()) if err != nil { return nil, err } @@ -249,7 +261,7 @@ func (s *stateProviderP2P) AppHash(ctx context.Context, height uint64) ([]byte, // We also try to fetch the blocks at H+2, since we need these // when building the state while restoring the snapshot. This avoids the race // condition where we try to restore a snapshot before H+2 exists. - _, err = s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + _, err = s.verifyLightBlockAtHeight(ctx, height+2, time.Now()) if err != nil { return nil, err } @@ -260,7 +272,7 @@ func (s *stateProviderP2P) AppHash(ctx context.Context, height uint64) ([]byte, func (s *stateProviderP2P) Commit(ctx context.Context, height uint64) (*types.Commit, error) { s.Lock() defer s.Unlock() - header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + header, err := s.verifyLightBlockAtHeight(ctx, height, time.Now()) if err != nil { return nil, err } @@ -288,15 +300,15 @@ func (s *stateProviderP2P) State(ctx context.Context, height uint64) (sm.State, // // We need to fetch the NextValidators from height+2 because if the application changed // the validator set at the snapshot height then this only takes effect at height+2. - lastLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + lastLightBlock, err := s.verifyLightBlockAtHeight(ctx, height, time.Now()) if err != nil { return sm.State{}, err } - currentLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + currentLightBlock, err := s.verifyLightBlockAtHeight(ctx, height+1, time.Now()) if err != nil { return sm.State{}, err } - nextLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + nextLightBlock, err := s.verifyLightBlockAtHeight(ctx, height+2, time.Now()) if err != nil { return sm.State{}, err } diff --git a/light/client.go b/light/client.go index 443b4d822..2b84805b0 100644 --- a/light/client.go +++ b/light/client.go @@ -52,8 +52,6 @@ const ( // 10s is sufficient for most networks. defaultMaxBlockLag = 10 * time.Second - - defaultProviderTimeout = 10 * time.Second ) // Option sets a parameter for the light client. @@ -113,12 +111,6 @@ func MaxBlockLag(d time.Duration) Option { return func(c *Client) { c.maxBlockLag = d } } -// Provider timeout is the maximum time that the light client will wait for a -// provider to respond with a light block. -func ProviderTimeout(d time.Duration) Option { - return func(c *Client) { c.providerTimeout = d } -} - // Client represents a light client, connected to a single chain, which gets // light blocks from a primary provider, verifies them either sequentially or by // skipping some and stores them in a trusted store (usually, a local FS). @@ -131,7 +123,6 @@ type Client struct { trustLevel tmmath.Fraction maxClockDrift time.Duration maxBlockLag time.Duration - providerTimeout time.Duration // Mutex for locking during changes of the light clients providers providerMutex sync.Mutex @@ -203,7 +194,6 @@ func NewClient( trustLevel: DefaultTrustLevel, maxClockDrift: defaultMaxClockDrift, maxBlockLag: defaultMaxBlockLag, - providerTimeout: defaultProviderTimeout, pruningSize: defaultPruningSize, logger: log.NewNopLogger(), } @@ -696,9 +686,7 @@ func (c *Client) verifySkipping( if depth == len(blockCache)-1 { // schedule what the next height we need to fetch is pivotHeight := c.schedule(verifiedBlock.Height, blockCache[depth].Height) - subCtx, cancel := context.WithTimeout(ctx, c.providerTimeout) - defer cancel() - interimBlock, providerErr := c.getLightBlock(subCtx, source, pivotHeight) + interimBlock, providerErr := c.getLightBlock(ctx, source, pivotHeight) if providerErr != nil { return nil, ErrVerificationFailed{From: verifiedBlock.Height, To: pivotHeight, Reason: providerErr} } @@ -963,10 +951,8 @@ func (c *Client) lightBlockFromPrimary(ctx context.Context, height int64) (*type } func (c *Client) getLightBlock(ctx context.Context, p provider.Provider, height int64) (*types.LightBlock, error) { - subCtx, cancel := context.WithTimeout(ctx, c.providerTimeout) - defer cancel() - l, err := p.LightBlock(subCtx, height) - if err == context.DeadlineExceeded || ctx.Err() != nil { + l, err := p.LightBlock(ctx, height) + if ctx.Err() != nil { return nil, provider.ErrNoResponse } return l, err @@ -1015,15 +1001,15 @@ func (c *Client) findNewPrimary(ctx context.Context, height int64, remove bool) wg sync.WaitGroup ) - // send out a light block request to all witnesses - subctx, cancel := context.WithTimeout(ctx, c.providerTimeout) + ctx, cancel := context.WithCancel(ctx) defer cancel() + // send out a light block request to all witnesses for index := range c.witnesses { wg.Add(1) go func(witnessIndex int, witnessResponsesC chan witnessResponse) { defer wg.Done() - lb, err := c.witnesses[witnessIndex].LightBlock(subctx, height) + lb, err := c.witnesses[witnessIndex].LightBlock(ctx, height) select { case witnessResponsesC <- witnessResponse{lb, witnessIndex, err}: case <-ctx.Done():