add FilterThresholdEpoch configuration setting for defining a static starting epoch above which the node will return filtered logs

This commit is contained in:
i-norden 2023-10-19 13:31:49 -05:00
parent 14a7ae339f
commit a8829a049e
4 changed files with 72 additions and 17 deletions

View File

@ -383,6 +383,21 @@ this time become eligible for automatic deletion.`,
Comment: `MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
the entire chain)`,
},
{
Name: "FilterThresholdSet",
Type: "bool",
Comment: `FilterThresholdSet signals whether a FilterThresholdEpoch is set. If it is it will be used instead of
MaxFilterHeightRange to define the supported range.`,
},
{
Name: "FilterThresholdEpoch",
Type: "uint64",
Comment: `FilterThresholdEpoch specifies an epoch above which the node will support returning filtered logs.
This is useful for setting a static start epoch for support, rather than a static window size with a start epoch
that shifts as the chain progresses.`,
},
{
Name: "DatabasePath",

View File

@ -717,6 +717,16 @@ type Events struct {
// the entire chain)
MaxFilterHeightRange uint64
// FilterThresholdSet signals whether a FilterThresholdEpoch is set. If it is it will be used instead of
// MaxFilterHeightRange to define the supported range.
FilterThresholdSet bool
// FilterThresholdEpoch specifies an epoch above which the node will support returning filtered logs.
// This is useful for setting a static start epoch for support, rather than a static window size with a start epoch
// that shifts as the chain progresses.
FilterThresholdEpoch uint64
// DatabasePath is the full path to a sqlite database that will be used to index actor events to
// support the historic filter APIs. If the database does not exist it will be created. The directory containing
// the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as

View File

@ -143,6 +143,8 @@ type EthEvent struct {
FilterStore filter.FilterStore
SubManager *EthSubscriptionManager
MaxFilterHeightRange abi.ChainEpoch
FilterThresholdSet bool
FilterThresholdEpoch abi.ChainEpoch
SubscribtionCtx context.Context
}
@ -1292,27 +1294,53 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype
}
// Validate height ranges are within limits set by node operator
if minHeight == -1 && maxHeight > 0 {
// Here the client is looking for events between the head and some future height
ts := e.Chain.GetHeaviestTipSet()
if maxHeight-ts.Height() > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: to block is too far in the future (maximum: %d)", e.MaxFilterHeightRange)
}
} else if minHeight >= 0 && maxHeight == -1 {
// Here the client is looking for events between some time in the past and the current head
ts := e.Chain.GetHeaviestTipSet()
if ts.Height()-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (maximum: %d)", e.MaxFilterHeightRange)
if e.FilterThresholdSet {
if minHeight == -1 && maxHeight > 0 {
// Here the client is looking for events between the head and some future height
ts := e.Chain.GetHeaviestTipSet()
if maxHeight < ts.Height() {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, ts.Height())
}
if ts.Height() < e.FilterThresholdEpoch {
return nil, xerrors.Errorf("invalid epoch range: from block (%d) is below the set FilterThresholdEpoch (%d)", ts.Height(), e.FilterThresholdEpoch)
}
} else if minHeight >= 0 && maxHeight == -1 {
// Here the client is looking for events between some time in the past and the current head
if minHeight < e.FilterThresholdEpoch {
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (minimum from epoch: %d)", e.FilterThresholdEpoch)
}
} else if minHeight >= 0 && maxHeight >= 0 {
if minHeight > maxHeight {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, minHeight)
} else if minHeight < e.FilterThresholdEpoch {
return nil, xerrors.Errorf("invalid epoch range: from block (%d) is below the set FilterThresholdEpoch (%d)", minHeight, e.FilterThresholdEpoch)
}
}
} else {
if minHeight == -1 && maxHeight > 0 {
// Here the client is looking for events between the head and some future height
ts := e.Chain.GetHeaviestTipSet()
if maxHeight < ts.Height() {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, ts.Height())
}
if maxHeight-ts.Height() > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: to block is too far in the future (maximum: %d)", e.MaxFilterHeightRange)
}
} else if minHeight >= 0 && maxHeight == -1 {
// Here the client is looking for events between some time in the past and the current head
ts := e.Chain.GetHeaviestTipSet()
if ts.Height()-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (maximum: %d)", e.MaxFilterHeightRange)
}
} else if minHeight >= 0 && maxHeight >= 0 {
if minHeight > maxHeight {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", minHeight, maxHeight)
} else if maxHeight-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: range between to and from blocks is too large (maximum: %d)", e.MaxFilterHeightRange)
} else if minHeight >= 0 && maxHeight >= 0 {
if minHeight > maxHeight {
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", maxHeight, minHeight)
} else if maxHeight-minHeight > e.MaxFilterHeightRange {
return nil, xerrors.Errorf("invalid epoch range: range between to and from blocks is too large (maximum: %d)", e.MaxFilterHeightRange)
}
}
}
}
// Convert all addresses to filecoin f4 addresses

View File

@ -40,6 +40,8 @@ func EthEventAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo
ee := &full.EthEvent{
Chain: cs,
MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange),
FilterThresholdSet: cfg.Events.FilterThresholdSet,
FilterThresholdEpoch: abi.ChainEpoch(cfg.Events.FilterThresholdEpoch),
SubscribtionCtx: ctx,
}