Documentation
¶
Overview ¶
Package llo: outcome_golden_cases.go defines golden outcome cases for outcome serialization tests.
Index ¶
- Constants
- func IsSecondsResolution(cd llocommon.ChannelDefinitionWithID, optsCache *llocommon.OptsCache) bool
- func MakeChannelHash(cd llocommon.ChannelDefinitionWithID) llocommon.ChannelHash
- func StreamAggregatesToProtoOutcome(in llocommon.StreamAggregates) (out []*llocommon.LLOStreamAggregate, err error)
- type Config
- type DSOpts
- type DataSource
- type GoldenOutcomeCase
- type Observation
- type ObservationCodec
- type Outcome
- func (out *Outcome) GenRetirementReport(protocolVersion uint32) llocommon.RetirementReport
- func (out *Outcome) IsReportable(channelID llotypes.ChannelID, protocolVersion uint32, minReportInterval uint64, ...) *UnreportableChannelError
- func (out *Outcome) ReportableChannels(protocolVersion uint32, defaultMinReportInterval uint64, ...) (reportable []llotypes.ChannelID, unreportable []*UnreportableChannelError)
- type OutcomeCodec
- type Plugin
- func (p *Plugin) Close() error
- func (p *Plugin) Observation(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query) (types.Observation, error)
- func (p *Plugin) ObservationQuorum(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, ...) (bool, error)
- func (p *Plugin) Outcome(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, ...) (ocr3types.Outcome, error)
- func (p *Plugin) ProcessCalculatedStreams(outcome *Outcome)
- func (p *Plugin) ProcessCalculatedStreamsDryRun(expression string) error
- func (p *Plugin) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (types.Query, error)
- func (p *Plugin) Reports(ctx context.Context, seqNr uint64, rawOutcome ocr3types.Outcome) ([]ocr3types.ReportPlus[llotypes.ReportInfo], error)
- func (p *Plugin) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error)
- func (p *Plugin) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error)
- func (p *Plugin) ValidateObservation(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, ...) error
- type PluginFactory
- type PluginFactoryParams
- type ShouldRetireCache
- type UnreportableChannelError
Constants ¶
const ( // NOTE: CAREFUL! If we ever accidentally exceed these e.g. // through too many channels/streams, the protocol will halt. MaxObservationLength = ocr3types.MaxMaxObservationLength MaxOutcomeLength = ocr3types.MaxMaxOutcomeLength MaxReportLength = ocr3types.MaxMaxReportLength )
OCR3.0 transport limits, reported in the v3.0 ReportingPluginInfo. The LLO-protocol limits (MaxReportCount, MaxObservation*Length, MaxStreamsPerChannel, MaxOutcomeChannelDefinitionsLength) are shared across plugin versions and live in the root llo package (limits.go).
Variables ¶
This section is empty.
Functions ¶
func IsSecondsResolution ¶
func IsSecondsResolution(cd llocommon.ChannelDefinitionWithID, optsCache *llocommon.OptsCache) bool
IsSecondsResolution returns whether the report format uses second-level resolution for the given opts. For ReportFormatEVMABIEncodeUnpacked, the cache must be populated (e.g. by Outcome's reset or Set during channel add/update) for correct resolution; no fallback to decoding opts is used — on cache miss it returns false.
func MakeChannelHash ¶
func MakeChannelHash(cd llocommon.ChannelDefinitionWithID) llocommon.ChannelHash
MakeChannelHash is used for mapping ChannelDefinitionWithIDs
func StreamAggregatesToProtoOutcome ¶
func StreamAggregatesToProtoOutcome(in llocommon.StreamAggregates) (out []*llocommon.LLOStreamAggregate, err error)
Types ¶
type Config ¶
type Config struct {
// Enables additional logging that might be expensive, e.g. logging entire
// channel definitions on every round or other very large structs
VerboseLogging bool
}
type DSOpts ¶
type DSOpts interface {
VerboseLogging() bool
SeqNr() uint64
OutCtx() ocr3types.OutcomeContext
ConfigDigest() ocr2types.ConfigDigest
ObservationTimestamp() time.Time
OutcomeCodec() OutcomeCodec
}
type DataSource ¶
type GoldenOutcomeCase ¶
GoldenOutcomeCase defines a single outcome serialization golden test case. Used by llo/tools/generate_golden to emit golden files and by outcome_codec_v1_test for comparison.
func GoldenOutcomeCases ¶
func GoldenOutcomeCases() []GoldenOutcomeCase
GoldenOutcomeCases returns the canonical set of outcome golden cases. "initial" and "from_full" are outcomes the plugin produces (Plugin.Outcome); "full" is a fixture used as previous outcome to produce "from_full".
type Observation ¶
type Observation struct {
// Attested (i.e. signed by f+1 oracles) retirement report from predecessor
// protocol instance
AttestedPredecessorRetirement []byte
// Should this protocol instance be retired?
ShouldRetire bool
// Timestamp from when observation is made
// Note that this is the timestamp immediately before we initiate any
// observations
UnixTimestampNanoseconds uint64
// Votes to remove/add channels. Subject to MAX_OBSERVATION_*_LENGTH limits
RemoveChannelIDs map[llotypes.ChannelID]struct{}
// Votes to add or replace channel definitions
UpdateChannelDefinitions llotypes.ChannelDefinitions
// Observed (numeric) stream values. Subject to
// MaxObservationStreamValuesLength limit
StreamValues llocommon.StreamValues
}
type ObservationCodec ¶
type ObservationCodec interface {
Encode(obs Observation) (types.Observation, error)
Decode(encoded types.Observation) (obs Observation, err error)
}
func NewProtoObservationCodec ¶
func NewProtoObservationCodec(lggr logger.Logger, enableCompression bool) (ObservationCodec, error)
type Outcome ¶
type Outcome struct {
// LifeCycleStage the protocol is in
LifeCycleStage llotypes.LifeCycleStage
// ObservationTimestampNanoseconds is the median timestamp from the
// latest set of observations
ObservationTimestampNanoseconds uint64
// ChannelDefinitions defines the set & structure of channels for which we
// generate reports
ChannelDefinitions llotypes.ChannelDefinitions
// Latest ValidAfterNanoseconds value for each channel, reports for each channel
// span from ValidAfterNanoseconds to ObservationTimestampNanoseconds
ValidAfterNanoseconds map[llotypes.ChannelID]uint64
// StreamAggregates contains stream IDs mapped to various aggregations.
// Usually you will only have one aggregation type per stream but since
// channels can define different aggregation methods, sometimes we will
// need multiple.
StreamAggregates llocommon.StreamAggregates
}
func (*Outcome) GenRetirementReport ¶
func (out *Outcome) GenRetirementReport(protocolVersion uint32) llocommon.RetirementReport
func (*Outcome) IsReportable ¶
func (out *Outcome) IsReportable(channelID llotypes.ChannelID, protocolVersion uint32, minReportInterval uint64, optsCache *llocommon.OptsCache) *UnreportableChannelError
IsReportable checks if a report can be generated for the given channel. Checks if channel is retired, tombstoned, has missing stream values (when DisableNilStreamValues is true), and if ValidAfterNanoseconds is set. Returns nil if channel is reportable. Time-resolution for overlap checks uses IsSecondsResolution, which tries the cache when available and falls back to decoding opts (e.g. after node restart).
Note: this is not a complete guarantee that a report will be successfully generated. Reports can still be silently dropped at the encoding step for other reasons (e.g. codec errors, bid/mid/ask validation failures). Those failure modes are not covered here and can still result in report gaps if DisableNilStreamValues is false or if the report codec fails to encode the report.
func (*Outcome) ReportableChannels ¶
func (out *Outcome) ReportableChannels(protocolVersion uint32, defaultMinReportInterval uint64, optsCache *llocommon.OptsCache) (reportable []llotypes.ChannelID, unreportable []*UnreportableChannelError)
ReportableChannels returns a sorted list of reportable channel IDs and errors for unreportable ones.
type OutcomeCodec ¶
type OutcomeCodec interface {
Encode(outcome Outcome) (ocr3types.Outcome, error)
Decode(encoded ocr3types.Outcome) (outcome Outcome, err error)
}
func GetOutcomeCodec ¶
func GetOutcomeCodec(c llocommon.OffchainConfig) OutcomeCodec
GetOutcomeCodec selects the outcome codec for the given offchain config's protocol version. It is a free function (rather than a method on the shared OffchainConfig type) because the outcome codecs are v3.0-specific.
type Plugin ¶
type Plugin struct {
Config Config
PredecessorConfigDigest *types.ConfigDigest
ConfigDigest types.ConfigDigest
PredecessorRetirementReportCache llocommon.PredecessorRetirementReportCache
ShouldRetireCache ShouldRetireCache
ChannelDefinitionCache llotypes.ChannelDefinitionCache
DataSource DataSource
Logger logger.Logger
N int
F int
ObservationCodec ObservationCodec
OutcomeCodec OutcomeCodec
RetirementReportCodec llocommon.RetirementReportCodec
ReportCodecs map[llotypes.ReportFormat]llocommon.ReportCodec
OutcomeTelemetryCh chan<- *llocommon.LLOOutcomeTelemetry
ReportTelemetryCh chan<- *llocommon.LLOReportTelemetry
DonID uint32
OptsCache *llocommon.OptsCache // must be non-nil; set by NewReportingPlugin or by tests that exercise Outcome/Reports
// From ReportingPluginConfig
MaxDurationObservation time.Duration
// From offchain config
ProtocolVersion uint32
DefaultMinReportIntervalNanoseconds uint64
}
func (*Plugin) Observation ¶
func (p *Plugin) Observation(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query) (types.Observation, error)
Observation gets an observation from the underlying data source. Returns a value or an error.
You may assume that the outctx.SeqNr is increasing monotonically (though *not* strictly) across the lifetime of a protocol instance and that outctx.previousOutcome contains the consensus outcome with sequence number (outctx.SeqNr-1).
Should return a serialized Observation struct.
func (*Plugin) ObservationQuorum ¶
func (p *Plugin) ObservationQuorum(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation) (bool, error)
ObservationQuorum returns the minimum number of valid (according to ValidateObservation) observations needed to construct an outcome.
This function should be pure. Don't do anything slow in here.
This is an advanced feature. The "default" approach (what OCR1 & OCR2 did) is to have an empty ValidateObservation function and return QuorumTwoFPlusOne from this function.
func (*Plugin) Outcome ¶
func (p *Plugin) Outcome(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation) (ocr3types.Outcome, error)
Generates an outcome for a seqNr, typically based on the previous outcome, the current query, and the current set of attributed observations.
This function should be pure. Don't do anything slow in here.
You may assume that the outctx.SeqNr is increasing monotonically (though *not* strictly) across the lifetime of a protocol instance and that outctx.previousOutcome contains the consensus outcome with sequence number (outctx.SeqNr-1).
libocr guarantees that this will always be called with at least 2f+1 AttributedObservations
func (*Plugin) ProcessCalculatedStreams ¶
ProcessCalculatedStreams evaluates calculated-stream expressions for the outcome's EVMABIEncodeUnpackedExpr channels, appending the calculated streams to their channel definitions and writing the evaluated values into the outcome's StreamAggregates.
func (*Plugin) ProcessCalculatedStreamsDryRun ¶
ProcessCalculatedStreamsDryRun validates an expression against synthetic inputs.
func (*Plugin) Query ¶
Query creates a Query that is sent from the leader to all follower nodes as part of the request for an observation. Be careful! A malicious leader could equivocate (i.e. send different queries to different followers.) Many applications will likely be better off always using an empty query if the oracles don't need to coordinate on what to observe (e.g. in case of a price feed) or the underlying data source offers an (eventually) consistent view to different oracles (e.g. in case of observing a blockchain).
You may assume that the outctx.SeqNr is increasing monotonically (though *not* strictly) across the lifetime of a protocol instance and that outctx.previousOutcome contains the consensus outcome with sequence number (outctx.SeqNr-1).
func (*Plugin) Reports ¶
func (p *Plugin) Reports(ctx context.Context, seqNr uint64, rawOutcome ocr3types.Outcome) ([]ocr3types.ReportPlus[llotypes.ReportInfo], error)
Generates a (possibly empty) list of reports from an outcome. Each report will be signed and possibly be transmitted to the contract. (Depending on ShouldAcceptAttestedReport & ShouldTransmitAcceptedReport)
This function should be pure. Don't do anything slow in here.
This is likely to change in the future. It will likely be returning a list of report batches, where each batch goes into its own Merkle tree.
You may assume that the outctx.SeqNr is increasing monotonically (though *not* strictly) across the lifetime of a protocol instance and that outctx.previousOutcome contains the consensus outcome with sequence number (outctx.SeqNr-1).
func (*Plugin) ShouldAcceptAttestedReport ¶
func (p *Plugin) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error)
func (*Plugin) ShouldTransmitAcceptedReport ¶
func (p *Plugin) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error)
func (*Plugin) ValidateObservation ¶
func (p *Plugin) ValidateObservation(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, ao types.AttributedObservation) error
Should return an error if an observation isn't well-formed. Non-well-formed observations will be discarded by the protocol. This is called for each observation, don't do anything slow in here.
You may assume that the outctx.SeqNr is increasing monotonically (though *not* strictly) across the lifetime of a protocol instance and that outctx.previousOutcome contains the consensus outcome with sequence number (outctx.SeqNr-1).
type PluginFactory ¶
type PluginFactory struct {
PluginFactoryParams
}
func NewPluginFactory ¶
func NewPluginFactory(p PluginFactoryParams) *PluginFactory
func (*PluginFactory) NewReportingPlugin ¶
func (f *PluginFactory) NewReportingPlugin(ctx context.Context, cfg ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[llotypes.ReportInfo], ocr3types.ReportingPluginInfo, error)
type PluginFactoryParams ¶
type PluginFactoryParams struct {
Config
llocommon.PredecessorRetirementReportCache
ShouldRetireCache
llocommon.RetirementReportCodec
llotypes.ChannelDefinitionCache
DataSource
logger.Logger
llocommon.OnchainConfigCodec
ReportCodecs map[llotypes.ReportFormat]llocommon.ReportCodec
// LLOOutcomeTelemetryCh if set will be used to send one telemetry struct per
// round in the Outcome stage
OutcomeTelemetryCh chan<- *llocommon.LLOOutcomeTelemetry
// ReportTelemetryCh if set will be used to send one telemetry struct per
// transmissible report in the Report stage
ReportTelemetryCh chan<- *llocommon.LLOReportTelemetry
// DonID is optional and used only for telemetry and logging
DonID uint32
}
type ShouldRetireCache ¶
type ShouldRetireCache interface {
// Should the protocol instance retire according to the configuration
// contract?
// See: https://github.com/smartcontractkit/mercury-v1-sketch/blob/main/onchain/src/ConfigurationStore.sol#L18
ShouldRetire(digest ocr2types.ConfigDigest) (bool, error)
}
type UnreportableChannelError ¶
type UnreportableChannelError struct {
Inner error `json:",omitempty"`
Reason string
ChannelID llotypes.ChannelID
}
func SelectBackfillCandidate ¶
func SelectBackfillCandidate(out *Outcome, backfillCID llotypes.ChannelID) (tsNanos uint64, rawTS uint64, opts llocommon.HistoryBackfillOpts, uerr *UnreportableChannelError)
SelectBackfillCandidate returns the next observation timestamp in nanoseconds, its raw key, and parsed opts, or an UnreportableChannelError. outcome.ValidAfterNanoseconds[backfillCID] is the progress watermark (last emitted backfill observation time, in nanoseconds). Min report interval and second-resolution overlap rules used for live channels do not apply to history_backfill.
func (*UnreportableChannelError) Error ¶
func (e *UnreportableChannelError) Error() string
func (*UnreportableChannelError) String ¶
func (e *UnreportableChannelError) String() string
func (*UnreportableChannelError) Unwrap ¶
func (e *UnreportableChannelError) Unwrap() error