llo

package
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package llo (import path .../llo/dev/v31) implements the LLO reporting plugin against libocr's OCR3.1 interface (offchainreporting2plus/ocr3_1types).

Experimental

This package lives under llo/dev and is experimental: OCR3.1 is not released, the state model is still moving, and the API carries no stability guarantee. See the llo/dev package documentation. It graduates to .../llo/v31 once the protocol version ships.

It is a dev-tree counterpart of the production OCR3.0 plugin at .../llo/v30, not a peer of it. Version-agnostic primitives (stream values, report codecs, aggregators, channel-definition helpers, opts cache, retirement types, lifecycle constants, limits and all generated protobuf types) live in the root llo package and are shared via a dot-import. This package is a self-contained plugin driver: it does not import v30.

State model

Unlike v30 (which threads the full outcome through OutcomeContext.PreviousOutcome), v31 stores state in the replicated KeyValueState. The in-round KeyValueStateReader only supports point Read(key); it has no range scan, so the set of live channels is tracked in an explicit index key. See kv.go for the key schema. All values written to the KV store MUST be serialized deterministically (protobuf with Deterministic:true, or fixed-width big-endian integers) because the store is replicated across oracles and any divergence halts the protocol.

Blobs

Observations carry per-stream values. When the serialized stream-value payload is large it is disseminated as a blob and referenced by handle in the observation, rather than sent inline. See observation.go.

Parity status (vs v30)

Implemented: lifecycle bootstrap/transitions (staging→production promotion, retirement), channel add/remove voting, stream aggregation (median/mode/quote via the shared aggregators), min-report-interval validAfter, precursor construction, report generation, blob-backed observations.

Seconds-resolution overlap prevention (for report formats that encode timestamps at second granularity) is implemented in resolution.go and applied in both the current-round (isReportable) and previous-round (prevReportable) reportability checks.

DisableNilStreamValues (a channel with any nil stream aggregate is unreportable), cross-round timestamped-aggregate carry-forward (t/ KV keys, newer-wins monotonicity), and best-effort outcome/report telemetry are also implemented. Reportability is persisted per channel each round (the r/ KV key) so the next round can advance validAfter faithfully without re-deriving it from aggregates that are not otherwise persisted.

Calculated streams (EVMABIEncodeUnpackedExpr channels) are supported via the expression engine in calculated.go, run at the end of StateTransition.

History-backfill channels are supported: backfill.go selects the next observation to emit (advancing a per-channel watermark stored in validAfter), reportability and validAfter advancement account for it, and Reports emits the backfill report encoded with the target channel's codec.

v31 now covers the full v30 reporting-plugin feature set. Consensus-affecting logic (state transition, aggregation, reportability, backfill, calculated streams) is ported from v30; the transport differs (KV state + blobs).

Missing: Blob success path isn't unit-tested: ocr3_1types.BlobHandle has no exported constructor, it's in an internal package, so a test can't fabricate a handle. Tests cover the offload decision + inline fallback; the full broadcast→fetch→merge round-trip needs libocr-provided doubles or an integration test.

Index

Constants

View Source
const DefaultBlobThreshold = 128 * 1024

DefaultBlobThreshold is the default serialized stream-value payload size in bytes above which an observation offloads its stream values to a blob.

View Source
const MaxMaxQueryBytesUnused = 0

MaxMaxQueryBytesUnused documents that LLO uses an empty query.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// VerboseLogging enables additional, potentially expensive logging.
	VerboseLogging bool
}

Config holds v31 plugin behavior toggles.

type DSOpts

type DSOpts = datasource.DSOpts

DSOpts and DataSource are the shared, version-agnostic data-source types. Kept as aliases here so existing llov31.DSOpts / llov31.DataSource references keep working. Lifecycle is carried directly via DSOpts.LifeCycleStage() (read from the KeyValueState at the Observe call site).

type DataSource

type DataSource = datasource.DataSource

type Observation

type Observation struct {
	AttestedPredecessorRetirement []byte
	ShouldRetire                  bool
	UnixTimestampNanoseconds      uint64
	RemoveChannelIDs              map[llotypes.ChannelID]struct{}
	UpdateChannelDefinitions      llotypes.ChannelDefinitions
	StreamValues                  protocol.StreamValues
}

Observation is the decoded per-round observation. It mirrors the v30 Observation, but is disseminated using the v31 wire framing (which supports offloading the bulk stream-value payload to a blob).

type Plugin

type Plugin struct {
	Config                           Config
	PredecessorConfigDigest          *ocrtypes.ConfigDigest
	ConfigDigest                     ocrtypes.ConfigDigest
	PredecessorRetirementReportCache protocol.PredecessorRetirementReportCache
	ShouldRetireCache                ShouldRetireCache
	ChannelDefinitionCache           llotypes.ChannelDefinitionCache
	DataSource                       DataSource
	Logger                           logger.Logger
	N                                int
	F                                int
	RetirementReportCodec            protocol.RetirementReportCodec
	ReportCodecs                     map[llotypes.ReportFormat]protocol.ReportCodec
	DonID                            uint32
	OptsCache                        *protocol.OptsCache

	// Optional telemetry sinks; best-effort, non-blocking.
	OutcomeTelemetryCh chan<- *protocol.LLOOutcomeTelemetry
	ReportTelemetryCh  chan<- *protocol.LLOReportTelemetry

	MaxDurationObservation time.Duration

	// From offchain config
	ProtocolVersion                     uint32
	DefaultMinReportIntervalNanoseconds uint64

	// BlobThreshold is the serialized stream-value payload size (bytes) above
	// which observations offload stream values to a blob. 0 disables offloading.
	BlobThreshold int
}

Plugin is the OCR3.1 LLO reporting plugin.

func (*Plugin) Close

func (p *Plugin) Close() error

func (*Plugin) Committed

func (p *Plugin) Committed(ctx context.Context, seqNr uint64, _ ocr3_1types.KeyValueStateReader) error

Committed is a no-op: LLO has no on-commit side effects, and Committed is not guaranteed to be called for every seqNr. Outcome telemetry is emitted from StateTransition, so there is nothing to do here.

func (*Plugin) Observation

Observation reads current state from the KeyValueState, gathers stream observations, votes on channel changes, and returns a (possibly blob-backed) serialized observation.

func (*Plugin) ObservationQuorum

ObservationQuorum uses the standard 2f+1 quorum.

func (*Plugin) Query

Query is empty: LLO oracles do not coordinate on what to observe.

func (*Plugin) Reports

Reports generates the (possibly empty) list of reports from a precursor. It receives no KeyValueStateReader, so the precursor must be fully self-sufficient.

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) StateTransition

StateTransition mutates the replicated KeyValueState based on the round's observations and returns a self-sufficient precursor for Reports.

This is a faithful port of the core of the v30 Outcome computation, adapted to read/write per-channel keys in the KeyValueState instead of decoding and re-encoding a monolithic previous outcome.

func (*Plugin) ValidateObservation

ValidateObservation checks an observation is well-formed. Blob-referenced stream values are fetched so lengths can be validated.

type PluginFactoryParams

type PluginFactoryParams struct {
	Config
	protocol.PredecessorRetirementReportCache
	ShouldRetireCache
	protocol.RetirementReportCodec
	llotypes.ChannelDefinitionCache
	DataSource
	logger.Logger
	protocol.OnchainConfigCodec
	ReportCodecs map[llotypes.ReportFormat]protocol.ReportCodec
	// OutcomeTelemetryCh, if set, receives one telemetry struct per StateTransition.
	OutcomeTelemetryCh chan<- *protocol.LLOOutcomeTelemetry
	// ReportTelemetryCh, if set, receives one telemetry struct per emitted report.
	ReportTelemetryCh chan<- *protocol.LLOReportTelemetry
	// DonID is optional and used only for telemetry and logging.
	DonID uint32
	// BlobThreshold overrides DefaultBlobThreshold if non-zero. A negative value
	// disables blob offloading.
	BlobThreshold int
}

PluginFactoryParams bundles the dependencies needed to construct the v31 reporting plugin. It mirrors the v30 params, minus the outcome codec (state lives in the KeyValueState), and adds BlobThreshold.

type ShouldRetireCache

type ShouldRetireCache interface {
	ShouldRetire(digest ocrtypes.ConfigDigest) (bool, error)
}

ShouldRetireCache reads asynchronously from the onchain ConfigurationStore whether this protocol instance should retire.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL