light: run detector for sequentially validating light client (#5538)

Closes #5445
This commit is contained in:
Anton Kaliaev
2020-11-02 12:42:03 +04:00
committed by GitHub
parent 8e6194626e
commit 627f7b5989
4 changed files with 94 additions and 76 deletions
+19 -8
View File
@@ -123,7 +123,7 @@ type Client struct {
providerMutex tmsync.Mutex
// Primary provider of new headers.
primary provider.Provider
// See Witnesses option
// Providers used to "witness" new headers.
witnesses []provider.Provider
// Where trusted light blocks are stored.
@@ -218,7 +218,7 @@ func NewClientFromTrustedStore(
}
// Validate the number of witnesses.
if len(c.witnesses) < 1 && c.verificationMode == skipping {
if len(c.witnesses) < 1 {
return nil, errNoWitnesses{}
}
@@ -363,10 +363,8 @@ func (c *Client) initializeWithTrustOptions(ctx context.Context, options TrustOp
}
// 3) Cross-verify with witnesses to ensure everybody has the same state.
if len(c.witnesses) > 0 {
if err := c.compareFirstHeaderWithWitnesses(ctx, l.SignedHeader); err != nil {
return err
}
if err := c.compareFirstHeaderWithWitnesses(ctx, l.SignedHeader); err != nil {
return err
}
// 4) Persist both of them and continue.
@@ -443,7 +441,7 @@ func (c *Client) Update(ctx context.Context, now time.Time) (*types.LightBlock,
}
// VerifyLightBlockAtHeight fetches the light block at the given height
// and calls verifyLightBlock. It returns the block immediately if it exists in
// and verifies it. It returns the block immediately if it exists in
// the trustedStore (no verification is needed).
//
// height must be > 0.
@@ -600,6 +598,7 @@ func (c *Client) verifySequential(
verifiedBlock = trustedBlock
interimBlock *types.LightBlock
err error
trace = []*types.LightBlock{trustedBlock}
)
for height := trustedBlock.Height + 1; height <= newLightBlock.Height; height++ {
@@ -669,9 +668,17 @@ func (c *Client) verifySequential(
// 3) Update verifiedBlock
verifiedBlock = interimBlock
// 4) Add verifiedBlock to trace
trace = append(trace, verifiedBlock)
}
return nil
// Compare header with the witnesses to ensure it's not a fork.
// More witnesses we have, more chance to notice one.
//
// CORRECTNESS ASSUMPTION: there's at least 1 correct full node
// (primary or one of the witnesses).
return c.detectDivergence(ctx, trace, now)
}
// see VerifyHeader
@@ -995,6 +1002,10 @@ func (c *Client) compareFirstHeaderWithWitnesses(ctx context.Context, h *types.S
compareCtx, cancel := context.WithCancel(ctx)
defer cancel()
if len(c.witnesses) < 1 {
return errNoWitnesses{}
}
errc := make(chan error, len(c.witnesses))
for i, witness := range c.witnesses {
go c.compareNewHeaderWithWitness(compareCtx, errc, h, witness, i)