llo

package
v0.0.0-...-a5a1065 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2024 License: MIT Imports: 20 Imported by: 3

Documentation

Index

Constants

View Source
const (
	MAX_OBSERVATION_REMOVE_CHANNEL_IDS_LENGTH      = 5
	MAX_OBSERVATION_ADD_CHANNEL_DEFINITIONS_LENGTH = 5
	MAX_OBSERVATION_STREAM_VALUES_LENGTH           = 1_000
)

Additional limits so we can more effectively bound the size of observations

View Source
const (
	LifeCycleStageStaging    llotypes.LifeCycleStage = "staging"
	LifeCycleStageProduction llotypes.LifeCycleStage = "production"
	LifeCycleStageRetired    llotypes.LifeCycleStage = "retired"
)

Protocol instances start in either the staging or production stage. They may later be retired and "hand over" their work to another protocol instance that will move from the staging to the production stage.

View Source
const MAX_OUTCOME_CHANNEL_DEFINITIONS_LENGTH = 500

Variables

View Source
var File_llo_offchain_config_proto protoreflect.FileDescriptor

Functions

This section is empty.

Types

type ChannelDefinitionWithID

type ChannelDefinitionWithID struct {
	llotypes.ChannelDefinition
	ChannelID llotypes.ChannelID
}

type ChannelHash

type ChannelHash [32]byte

func MakeChannelHash

func MakeChannelHash(cd ChannelDefinitionWithID) ChannelHash

MakeChannelHash is used for mapping ChannelDefinitionWithIDs

type DataSource

type DataSource interface {
	// For each known streamID, Observe should return a non-nil entry in
	// StreamValues. Observe should ignore unknown streamIDs.
	Observe(ctx context.Context, streamIDs map[llotypes.StreamID]struct{}) (StreamValues, error)
}

type JSONOnchainConfigCodec

type JSONOnchainConfigCodec struct{}

TODO: Replace this with protobuf, if it is actually used for something

func (*JSONOnchainConfigCodec) Decode

func (*JSONOnchainConfigCodec) Encode

type JSONReportCodec

type JSONReportCodec struct{}

func (JSONReportCodec) Decode

func (cdc JSONReportCodec) Decode(b []byte) (r Report, err error)

func (JSONReportCodec) Encode

func (cdc JSONReportCodec) Encode(r Report) ([]byte, error)

type LLOOffchainConfigProto

type LLOOffchainConfigProto struct {
	PredecessorConfigDigest []byte `protobuf:"bytes,1,opt,name=predecessorConfigDigest,proto3" json:"predecessorConfigDigest,omitempty"`
	// contains filtered or unexported fields
}

func (*LLOOffchainConfigProto) Descriptor deprecated

func (*LLOOffchainConfigProto) Descriptor() ([]byte, []int)

Deprecated: Use LLOOffchainConfigProto.ProtoReflect.Descriptor instead.

func (*LLOOffchainConfigProto) GetPredecessorConfigDigest

func (x *LLOOffchainConfigProto) GetPredecessorConfigDigest() []byte

func (*LLOOffchainConfigProto) ProtoMessage

func (*LLOOffchainConfigProto) ProtoMessage()

func (*LLOOffchainConfigProto) ProtoReflect

func (x *LLOOffchainConfigProto) ProtoReflect() protoreflect.Message

func (*LLOOffchainConfigProto) Reset

func (x *LLOOffchainConfigProto) Reset()

func (*LLOOffchainConfigProto) String

func (x *LLOOffchainConfigProto) String() string

type LLOPlugin

type LLOPlugin struct {
	PredecessorConfigDigest          *types.ConfigDigest
	ConfigDigest                     types.ConfigDigest
	PredecessorRetirementReportCache PredecessorRetirementReportCache
	ShouldRetireCache                ShouldRetireCache
	ChannelDefinitionCache           llotypes.ChannelDefinitionCache
	DataSource                       DataSource
	Logger                           logger.Logger
	F                                int
	Codecs                           map[llotypes.ReportFormat]ReportCodec
}

func (*LLOPlugin) Close

func (p *LLOPlugin) Close() error

func (*LLOPlugin) Observation

func (p *LLOPlugin) 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 (*LLOPlugin) ObservationQuorum

func (p *LLOPlugin) ObservationQuorum(outctx ocr3types.OutcomeContext, query types.Query) (ocr3types.Quorum, 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 (*LLOPlugin) Outcome

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 (*LLOPlugin) Query

func (p *LLOPlugin) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (types.Query, error)

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 (*LLOPlugin) Reports

func (p *LLOPlugin) Reports(seqNr uint64, rawOutcome ocr3types.Outcome) ([]ocr3types.ReportWithInfo[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 (*LLOPlugin) ShouldAcceptAttestedReport

func (p *LLOPlugin) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error)

func (*LLOPlugin) ShouldTransmitAcceptedReport

func (p *LLOPlugin) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error)

func (*LLOPlugin) ValidateObservation

func (p *LLOPlugin) ValidateObservation(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 ObsResult

type ObsResult[T any] struct {
	Val   T
	Valid bool
}

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
	UnixTimestampNanoseconds int64
	// Votes to remove/add channels. Subject to MAX_OBSERVATION_*_LENGTH limits
	RemoveChannelIDs      map[llotypes.ChannelID]struct{}
	AddChannelDefinitions llotypes.ChannelDefinitions
	// Observed (numeric) stream values. Subject to
	// MAX_OBSERVATION_STREAM_VALUES_LENGTH limit
	StreamValues StreamValues
}

type OffchainConfig

type OffchainConfig struct {
	// We use the offchainconfig of the plugin to tell the plugin the
	// configdigest of its predecessor protocol instance.
	//
	// NOTE: Set here:
	// https://github.com/smartcontractkit/mercury-v1-sketch/blob/f52c0f823788f86c1aeaa9ba1eee32a85b981535/onchain/src/ConfigurationStore.sol#L13
	// TODO: This needs to be implemented alongside staging/production
	// switchover support: https://smartcontract-it.atlassian.net/browse/MERC-3386
	PredecessorConfigDigest *types.ConfigDigest
}

func DecodeOffchainConfig

func DecodeOffchainConfig(b []byte) (o OffchainConfig, err error)

func (OffchainConfig) Encode

func (c OffchainConfig) Encode() ([]byte, error)

type OnchainConfig

type OnchainConfig struct{}

type OnchainConfigCodec

type OnchainConfigCodec interface {
	Encode(OnchainConfig) ([]byte, error)
	Decode([]byte) (OnchainConfig, error)
}

type Outcome

type Outcome struct {
	// LifeCycleStage the protocol is in
	LifeCycleStage llotypes.LifeCycleStage
	// ObservationsTimestampNanoseconds is the median timestamp from the
	// latest set of observations
	ObservationsTimestampNanoseconds int64
	// ChannelDefinitions defines the set & structure of channels for which we
	// generate reports
	ChannelDefinitions llotypes.ChannelDefinitions
	// Latest ValidAfterSeconds value for each channel, reports for each channel
	// span from ValidAfterSeconds to ObservationTimestampSeconds
	ValidAfterSeconds map[llotypes.ChannelID]uint32
	// StreamMedians is the median observed value for each stream
	// QUESTION: Can we use arbitrary types here to allow for other types or
	// consensus methods?
	StreamMedians map[llotypes.StreamID]*big.Int
}

func (*Outcome) IsReportable

func (out *Outcome) IsReportable(channelID llotypes.ChannelID) error

Indicates whether a report can be generated for the given channel. Returns nil if channel is reportable

func (*Outcome) ObservationsTimestampSeconds

func (out *Outcome) ObservationsTimestampSeconds() (uint32, error)

The Outcome's ObservationsTimestamp rounded down to seconds precision

func (*Outcome) ReportableChannels

func (out *Outcome) ReportableChannels() []llotypes.ChannelID

List of reportable channels (according to IsReportable), sorted according to a canonical ordering

type PluginFactory

type PluginFactory struct {
	PredecessorRetirementReportCache PredecessorRetirementReportCache
	ShouldRetireCache                ShouldRetireCache
	ChannelDefinitionCache           llotypes.ChannelDefinitionCache
	DataSource                       DataSource
	Logger                           logger.Logger
	Codecs                           map[llotypes.ReportFormat]ReportCodec
}

type PredecessorRetirementReportCache

type PredecessorRetirementReportCache interface {
	AttestedRetirementReport(predecessorConfigDigest ocr2types.ConfigDigest) ([]byte, error)
	CheckAttestedRetirementReport(predecessorConfigDigest ocr2types.ConfigDigest, attestedRetirementReport []byte) (RetirementReport, error)
}

The predecessor protocol instance stores its attested retirement report in this cache (locally, offchain), so it can be fetched by the successor protocol instance.

PredecessorRetirementReportCache is populated by the old protocol instance writing to it and the new protocol instance reading from it.

The sketch envisions it being implemented as a single object that is shared between different protocol instances.

func NewPredecessorRetirementReportCache

func NewPredecessorRetirementReportCache() PredecessorRetirementReportCache

TODO: This ought to be DB-persisted https://smartcontract-it.atlassian.net/browse/MERC-3386

type Report

type Report struct {
	ConfigDigest types.ConfigDigest
	// Chain the report is destined for
	ChainSelector uint64
	// OCR sequence number of this report
	SeqNr uint64
	// Channel that is being reported on
	ChannelID llotypes.ChannelID
	// Report is valid for ValidAfterSeconds < block.time <= ValidUntilSeconds
	ValidAfterSeconds uint32
	ValidUntilSeconds uint32
	// Here we only encode big.Ints, but in principle there's nothing stopping
	// us from also supporting non-numeric data or smaller values etc...
	Values []*big.Int
	// The contract onchain will only validate non-specimen reports. A staging
	// protocol instance will generate specimen reports so we can validate it
	// works properly without any risk of misreports landing on chain.
	Specimen bool
}

type ReportCodec

type ReportCodec interface {
	Encode(Report) ([]byte, error)
	Decode([]byte) (Report, error)
}

type RetirementReport

type RetirementReport struct {
	// Carries validity time stamps between protocol instances to ensure there
	// are no gaps
	ValidAfterSeconds map[llotypes.ChannelID]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() (bool, error)
}

type StreamValues

type StreamValues map[llotypes.StreamID]ObsResult[*big.Int]

Values for a set of streams, e.g. "eth-usd", "link-usd", and "eur-chf" TODO: generalize from *big.Int to anything https://smartcontract-it.atlassian.net/browse/MERC-3525 TODO: Consider renaming to StreamDataPoints?

type Transmitter

type Transmitter interface {
	// NOTE: Mercury doesn't actually transmit on-chain, so there is no
	// "contract" involved with the transmitter.
	// - Transmit should be implemented and send to Mercury server
	// - FromAccount() should return CSA public key
	ocr3types.ContractTransmitter[llotypes.ReportInfo]
}

Jump to

Keyboard shortcuts

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