Merge pull request from GHSA-f3w5-v9xx-rp8p

* add time warping lunatic attack test

* create too high and connecton refused errors and add to the light client provider

* add height check to provider

* introduce block lag

* add detection logic for processing forward lunatic attack

* add node-side verification logic

* clean up tests and formatting

* update adr's

* update testing

* fix fetching the latest block

* format

* update changelog

* implement suggestions

* modify ADR's

* format

* clean up node evidence verification
This commit is contained in:
Callum Waters
2021-04-08 08:10:03 -07:00
committed by GitHub
parent 0f41f7465c
commit b272746444
16 changed files with 631 additions and 133 deletions
+24 -3
View File
@@ -35,6 +35,9 @@ const (
// - http://vancouver-webpages.com/time/web.html
// - https://blog.codinghorror.com/keeping-time-on-the-pc/
defaultMaxClockDrift = 10 * time.Second
// 10s is sufficient for most networks.
defaultMaxBlockLag = 10 * time.Second
)
// Option sets a parameter for the light client.
@@ -92,13 +95,27 @@ func Logger(l log.Logger) Option {
}
// MaxClockDrift defines how much new header's time can drift into
// the future. Default: 10s.
// the future relative to the light clients local time. Default: 10s.
func MaxClockDrift(d time.Duration) Option {
return func(c *Client) {
c.maxClockDrift = d
}
}
// MaxBlockLag represents the maximum time difference between the realtime
// that a block is received and the timestamp of that block.
// One can approximate it to the maximum block production time
//
// As an example, say the light client received block B at a time
// 12:05 (this is the real time) and the time on the block
// was 12:00. Then the lag here is 5 minutes.
// Default: 10s
func MaxBlockLag(d time.Duration) Option {
return func(c *Client) {
c.maxBlockLag = 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).
@@ -110,6 +127,7 @@ type Client struct {
verificationMode mode
trustLevel tmmath.Fraction
maxClockDrift time.Duration
maxBlockLag time.Duration
// Mutex for locking during changes of the light clients providers
providerMutex tmsync.Mutex
@@ -197,6 +215,7 @@ func NewClientFromTrustedStore(
verificationMode: skipping,
trustLevel: DefaultTrustLevel,
maxClockDrift: defaultMaxClockDrift,
maxBlockLag: defaultMaxBlockLag,
primary: primary,
witnesses: witnesses,
trustedStore: trustedStore,
@@ -952,13 +971,15 @@ func (c *Client) lightBlockFromPrimary(ctx context.Context, height int64) (*type
case provider.ErrNoResponse, provider.ErrLightBlockNotFound:
// we find a new witness to replace the primary
c.logger.Debug("error from light block request from primary, replacing...", "error", err, "primary", c.primary)
c.logger.Debug("error from light block request from primary, replacing...",
"error", err, "height", height, "primary", c.primary)
return c.findNewPrimary(ctx, height, false)
default:
// The light client has most likely received either provider.ErrUnreliableProvider or provider.ErrBadLightBlock
// These errors mean that the light client should drop the primary and try with another provider instead
c.logger.Error("error from light block request from primary, removing...", "error", err, "primary", c.primary)
c.logger.Error("error from light block request from primary, removing...",
"error", err, "height", height, "primary", c.primary)
return c.findNewPrimary(ctx, height, true)
}
}