diff --git a/commit/chainfee/processor.go b/commit/chainfee/processor.go index 3d613977..c37afc0b 100644 --- a/commit/chainfee/processor.go +++ b/commit/chainfee/processor.go @@ -5,6 +5,7 @@ import ( "fmt" mapset "github.com/deckarep/golang-set/v2" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/internal/plugincommon" @@ -30,6 +31,7 @@ func (w *Processor) Observation( } func (w *Processor) Outcome( + ctx context.Context, prevOutcome Outcome, query Query, aos []plugincommon.AttributedObservation[Observation], diff --git a/commit/factory.go b/commit/factory.go index 0c0ce8f8..e8295dde 100644 --- a/commit/factory.go +++ b/commit/factory.go @@ -84,7 +84,7 @@ func NewPluginFactory( } } -func (p *PluginFactory) NewReportingPlugin(config ocr3types.ReportingPluginConfig, +func (p *PluginFactory) NewReportingPlugin(ctx context.Context, config ocr3types.ReportingPluginConfig, ) (ocr3types.ReportingPlugin[[]byte], ocr3types.ReportingPluginInfo, error) { offchainConfig, err := pluginconfig.DecodeCommitOffchainConfig(config.OffchainConfig) if err != nil { @@ -134,34 +134,37 @@ func (p *PluginFactory) NewReportingPlugin(config ocr3types.ReportingPluginConfi p.ocrConfig.Config.ChainSelector, p.ocrConfig.Config.OfframpAddress, ) - return NewPlugin( - context.Background(), - config.OracleID, - oracleIDToP2PID, - pluginconfig.CommitPluginConfig{ - DestChain: p.ocrConfig.Config.ChainSelector, - NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, - MaxReportTransmissionCheckAttempts: maxReportTransmissionCheckAttempts, - OffchainConfig: offchainConfig, - }, - ccipReader, - onChainTokenPricesReader, - p.commitCodec, - p.msgHasher, - p.lggr, - p.homeChainReader, - config, - rmn.Config{}, // todo - ), ocr3types.ReportingPluginInfo{ - Name: "CCIPRoleCommit", - Limits: ocr3types.ReportingPluginLimits{ - MaxQueryLength: maxQueryLength, - MaxObservationLength: 20_000, // 20kB - MaxOutcomeLength: 10_000, // 10kB - MaxReportLength: 10_000, // 10kB - MaxReportCount: 10, - }, - }, nil + plugin := NewPlugin( + config.OracleID, + oracleIDToP2PID, + pluginconfig.CommitPluginConfig{ + DestChain: p.ocrConfig.Config.ChainSelector, + NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, + MaxReportTransmissionCheckAttempts: maxReportTransmissionCheckAttempts, + OffchainConfig: offchainConfig, + }, + ccipReader, + onChainTokenPricesReader, + p.commitCodec, + p.msgHasher, + p.lggr, + p.homeChainReader, + config, + rmn.Config{}, // todo + ) + if err = plugin.Start(ctx); err != nil { + return nil, ocr3types.ReportingPluginInfo{}, fmt.Errorf("failed to start plugin: %w", err) + } + return plugin, ocr3types.ReportingPluginInfo{ + Name: "CCIPRoleCommit", + Limits: ocr3types.ReportingPluginLimits{ + MaxQueryLength: maxQueryLength, + MaxObservationLength: 20_000, // 20kB + MaxOutcomeLength: 10_000, // 10kB + MaxReportLength: 10_000, // 10kB + MaxReportCount: 10, + }, + }, nil } func (p PluginFactory) Name() string { diff --git a/commit/merkleroot/observation.go b/commit/merkleroot/observation.go index cb10625b..f1b2b0f2 100644 --- a/commit/merkleroot/observation.go +++ b/commit/merkleroot/observation.go @@ -9,11 +9,13 @@ import ( "time" mapset "github.com/deckarep/golang-set/v2" + "golang.org/x/sync/errgroup" + chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/libocr/quorumhelper" "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -28,9 +30,12 @@ import ( readerpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" ) -func (w *Processor) ObservationQuorum(_ ocr3types.OutcomeContext, _ types.Query) (ocr3types.Quorum, error) { +func (w *Processor) ObservationQuorum( + _ context.Context, _ ocr3types.OutcomeContext, _ types.Query, aos []types.AttributedObservation, +) (bool, error) { // Across all chains we require at least 2F+1 observations. - return ocr3types.QuorumTwoFPlusOne, nil + return quorumhelper.ObservationCountReachesObservationQuorum( + quorumhelper.QuorumTwoFPlusOne, w.reportingCfg.N, w.reportingCfg.F, aos), nil } func (w *Processor) Observation( diff --git a/commit/merkleroot/outcome.go b/commit/merkleroot/outcome.go index e8602ac6..67e93e99 100644 --- a/commit/merkleroot/outcome.go +++ b/commit/merkleroot/outcome.go @@ -1,6 +1,7 @@ package merkleroot import ( + "context" "fmt" "sort" "time" @@ -20,6 +21,7 @@ import ( // - builds a report // - checks for the transmission of a previous report func (w *Processor) Outcome( + ctx context.Context, prevOutcome Outcome, query Query, aos []plugincommon.AttributedObservation[Observation], diff --git a/commit/plugin.go b/commit/plugin.go index 2e46288d..f7c0ec56 100644 --- a/commit/plugin.go +++ b/commit/plugin.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/libocr/quorumhelper" libocrtypes "github.com/smartcontractkit/libocr/ragep2p/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -46,7 +47,6 @@ type Plugin struct { } func NewPlugin( - _ context.Context, nodeID commontypes.OracleID, oracleIDToP2pID map[commontypes.OracleID]libocrtypes.PeerID, cfg pluginconfig.CommitPluginConfig, @@ -70,9 +70,6 @@ func NewPlugin( syncTimeout(cfg.SyncTimeout), syncFrequency(cfg.SyncFrequency), ) - if err := readerSyncer.Start(context.Background()); err != nil { - lggr.Errorw("error starting background reader syncer", "err", err) - } chainSupport := plugincommon.NewCCIPChainSupport( lggr, @@ -148,9 +145,12 @@ func (p *Plugin) Query(ctx context.Context, outCtx ocr3types.OutcomeContext) (ty return q.Encode() } -func (p *Plugin) ObservationQuorum(_ ocr3types.OutcomeContext, _ types.Query) (ocr3types.Quorum, error) { +func (p *Plugin) ObservationQuorum( + ctx context.Context, _ ocr3types.OutcomeContext, _ types.Query, aos []types.AttributedObservation, +) (bool, error) { // Across all chains we require at least 2F+1 observations. - return ocr3types.QuorumTwoFPlusOne, nil + return quorumhelper.ObservationCountReachesObservationQuorum( + quorumhelper.QuorumFPlusOne, p.reportingCfg.N, p.reportingCfg.F, aos), nil } func (p *Plugin) Observation( @@ -201,7 +201,7 @@ func (p *Plugin) ObserveFChain() map[cciptypes.ChainSelector]int { // - builds a report // - checks for the transmission of a previous report func (p *Plugin) Outcome( - outCtx ocr3types.OutcomeContext, q types.Query, aos []types.AttributedObservation, + ctx context.Context, outCtx ocr3types.OutcomeContext, q types.Query, aos []types.AttributedObservation, ) (ocr3types.Outcome, error) { prevOutcome := p.decodeOutcome(outCtx.PreviousOutcome) @@ -243,6 +243,7 @@ func (p *Plugin) Outcome( } merkleRootOutcome, err := p.merkleRootProcessor.Outcome( + ctx, prevOutcome.MerkleRootOutcome, decodedQ.MerkleRootQuery, merkleObservations, @@ -252,6 +253,7 @@ func (p *Plugin) Outcome( } tokenPriceOutcome, err := p.tokenPriceProcessor.Outcome( + ctx, prevOutcome.TokenPriceOutcome, decodedQ.TokenPriceQuery, tokensObservations, @@ -261,6 +263,7 @@ func (p *Plugin) Outcome( } chainFeeOutcome, err := p.chainFeeProcessor.Outcome( + ctx, prevOutcome.ChainFeeOutcome, decodedQ.ChainFeeQuery, feeObservations, @@ -276,6 +279,13 @@ func (p *Plugin) Outcome( }.Encode() } +func (p *Plugin) Start(ctx context.Context) error { + if err := p.readerSyncer.Start(ctx); err != nil { + return fmt.Errorf("error starting background reader syncer: %w", err) + } + return nil +} + func (p *Plugin) Close() error { timeout := 10 * time.Second ctx, cf := context.WithTimeout(context.Background(), timeout) diff --git a/commit/plugin_e2e_test.go b/commit/plugin_e2e_test.go index 58379c6b..1a45071a 100644 --- a/commit/plugin_e2e_test.go +++ b/commit/plugin_e2e_test.go @@ -337,7 +337,6 @@ func setupNode( } p := NewPlugin( - ctx, nodeID, oracleIDToP2pID, pluginCfg, @@ -350,6 +349,7 @@ func setupNode( reportingCfg, rmn.Config{}, ) + require.NoError(t, p.Start(ctx)) return nodeSetup{ node: p, diff --git a/commit/report.go b/commit/report.go index 9596a7f4..9fb3218a 100644 --- a/commit/report.go +++ b/commit/report.go @@ -12,7 +12,9 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" ) -func (p *Plugin) Reports(seqNr uint64, outcomeBytes ocr3types.Outcome) ([]ocr3types.ReportWithInfo[[]byte], error) { +func (p *Plugin) Reports( + ctx context.Context, seqNr uint64, outcomeBytes ocr3types.Outcome, +) ([]ocr3types.ReportPlus[[]byte], error) { outcome, err := DecodeOutcome(outcomeBytes) if err != nil { // TODO: metrics @@ -22,7 +24,7 @@ func (p *Plugin) Reports(seqNr uint64, outcomeBytes ocr3types.Outcome) ([]ocr3ty // Until we start adding tokens and gas to the report, we don't need to report anything if outcome.MerkleRootOutcome.OutcomeType != merkleroot.ReportGenerated { - return []ocr3types.ReportWithInfo[[]byte]{}, nil + return []ocr3types.ReportPlus[[]byte]{}, nil } rep := cciptypes.CommitPluginReport{ @@ -34,12 +36,15 @@ func (p *Plugin) Reports(seqNr uint64, outcomeBytes ocr3types.Outcome) ([]ocr3ty RMNSignatures: outcome.MerkleRootOutcome.RMNReportSignatures, } - encodedReport, err := p.reportCodec.Encode(context.Background(), rep) + encodedReport, err := p.reportCodec.Encode(ctx, rep) if err != nil { return nil, fmt.Errorf("encode commit plugin report: %w", err) } - return []ocr3types.ReportWithInfo[[]byte]{{Report: encodedReport, Info: nil}}, nil + return []ocr3types.ReportPlus[[]byte]{ + {ReportWithInfo: ocr3types.ReportWithInfo[[]byte]{ + Report: encodedReport, Info: nil}}, + }, nil } func (p *Plugin) ShouldAcceptAttestedReport( diff --git a/commit/tokenprice/outcome_test.go b/commit/tokenprice/outcome_test.go index bacc3582..cfb00f0a 100644 --- a/commit/tokenprice/outcome_test.go +++ b/commit/tokenprice/outcome_test.go @@ -4,17 +4,18 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-ccip/internal/plugincommon" "github.com/smartcontractkit/chainlink-ccip/internal/plugintypes" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/stretchr/testify/assert" ) var ts = time.Now().UTC() @@ -139,6 +140,7 @@ func TestSelectTokensForUpdate(t *testing.T) { // Test Plugin Outcome method returns the correct token prices func TestOutcome(t *testing.T) { + ctx := tests.Context(t) lggr := logger.Test(t) p := &processor{ lggr: lggr, @@ -149,7 +151,7 @@ func TestOutcome(t *testing.T) { bigF: 1, } - outcome, err := p.Outcome(Outcome{}, Query{}, []plugincommon.AttributedObservation[Observation]{ + outcome, err := p.Outcome(ctx, Outcome{}, Query{}, []plugincommon.AttributedObservation[Observation]{ {OracleID: 1, Observation: obs}, {OracleID: 2, Observation: obs}, {OracleID: 3, Observation: obs}, diff --git a/commit/tokenprice/processor.go b/commit/tokenprice/processor.go index e343b5c2..77eecd6d 100644 --- a/commit/tokenprice/processor.go +++ b/commit/tokenprice/processor.go @@ -7,15 +7,15 @@ import ( mapset "github.com/deckarep/golang-set/v2" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-ccip/internal/plugincommon" "github.com/smartcontractkit/chainlink-ccip/internal/reader" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" ) type processor struct { @@ -82,6 +82,7 @@ func (p *processor) ValidateObservation( } func (p *processor) Outcome( + ctx context.Context, _ Outcome, _ Query, aos []plugincommon.AttributedObservation[Observation], diff --git a/commit/validate_observation.go b/commit/validate_observation.go index 6b2859a8..fddae895 100644 --- a/commit/validate_observation.go +++ b/commit/validate_observation.go @@ -1,6 +1,7 @@ package commit import ( + "context" "fmt" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" @@ -11,6 +12,7 @@ import ( // ValidateObservation validates an observation to ensure it is well-formed func (p *Plugin) ValidateObservation( + _ context.Context, outCtx ocr3types.OutcomeContext, q types.Query, ao types.AttributedObservation, diff --git a/execute/factory.go b/execute/factory.go index 0bebcf8c..72bb5f99 100644 --- a/execute/factory.go +++ b/execute/factory.go @@ -7,13 +7,14 @@ import ( "google.golang.org/grpc" + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types/core" - "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" "github.com/smartcontractkit/chainlink-ccip/execute/internal/gas" "github.com/smartcontractkit/chainlink-ccip/execute/tokendata" @@ -86,7 +87,7 @@ func NewPluginFactory( } func (p PluginFactory) NewReportingPlugin( - config ocr3types.ReportingPluginConfig, + ctx context.Context, config ocr3types.ReportingPluginConfig, ) (ocr3types.ReportingPlugin[[]byte], ocr3types.ReportingPluginInfo, error) { offchainConfig, err := pluginconfig.DecodeExecuteOffchainConfig(config.OffchainConfig) if err != nil { @@ -116,31 +117,35 @@ func (p PluginFactory) NewReportingPlugin( p.ocrConfig.Config.OfframpAddress, ) - return NewPlugin( - config, - pluginconfig.ExecutePluginConfig{ - DestChain: p.ocrConfig.Config.ChainSelector, - OffchainConfig: offchainConfig, - }, - oracleIDToP2PID, - ccipReader, - p.execCodec, - p.msgHasher, - p.homeChainReader, - p.tokenDataObserver, - p.estimateProvider, - p.lggr, - ), ocr3types.ReportingPluginInfo{ - Name: "CCIPRoleExecute", - Limits: ocr3types.ReportingPluginLimits{ - // No query for this execute implementation. - MaxQueryLength: 0, - MaxObservationLength: 20_000, // 20kB - MaxOutcomeLength: 20_000, // 20kB - MaxReportLength: maxReportSizeBytes, // 250kB - MaxReportCount: 10, - }, - }, nil + plugin := NewPlugin( + config, + pluginconfig.ExecutePluginConfig{ + DestChain: p.ocrConfig.Config.ChainSelector, + OffchainConfig: offchainConfig, + }, + oracleIDToP2PID, + ccipReader, + p.execCodec, + p.msgHasher, + p.homeChainReader, + p.tokenDataObserver, + p.estimateProvider, + p.lggr, + ) + if err = plugin.Start(ctx); err != nil { + return nil, ocr3types.ReportingPluginInfo{}, fmt.Errorf("failed to start plugin: %w", err) + } + return plugin, ocr3types.ReportingPluginInfo{ + Name: "CCIPRoleExecute", + Limits: ocr3types.ReportingPluginLimits{ + // No query for this execute implementation. + MaxQueryLength: 0, + MaxObservationLength: 20_000, // 20kB + MaxOutcomeLength: 20_000, // 20kB + MaxReportLength: maxReportSizeBytes, // 250kB + MaxReportCount: 10, + }, + }, nil } func (p PluginFactory) Name() string { diff --git a/execute/plugin.go b/execute/plugin.go index 0bb2b92a..e17662bc 100644 --- a/execute/plugin.go +++ b/execute/plugin.go @@ -7,6 +7,7 @@ import ( "time" mapset "github.com/deckarep/golang-set/v2" + "github.com/smartcontractkit/libocr/quorumhelper" "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -66,9 +67,6 @@ func NewPlugin( syncTimeout(cfg.SyncTimeout), syncFrequency(cfg.SyncFrequency), ) - if err := readerSyncer.Start(context.Background()); err != nil { - lggr.Errorw("error starting background reader syncer", "err", err) - } return &Plugin{ reportingCfg: reportingCfg, @@ -85,6 +83,29 @@ func NewPlugin( } } +func (p *Plugin) Start(ctx context.Context) error { + if err := p.readerSyncer.Start(ctx); err != nil { + return fmt.Errorf("error starting background reader syncer: %w", err) + } + return nil +} + +func (p *Plugin) Close() error { + timeout := 10 * time.Second // todo: cfg + ctx, cf := context.WithTimeout(context.Background(), timeout) + defer cf() + + if err := p.readerSyncer.Close(); err != nil { + p.lggr.Warnw("error closing reader syncer", "err", err) + } + + if err := p.ccipReader.Close(ctx); err != nil { + return fmt.Errorf("close ccip reader: %w", err) + } + + return nil +} + func (p *Plugin) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (types.Query, error) { return types.Query{}, nil } @@ -287,7 +308,7 @@ func (p *Plugin) Observation( } func (p *Plugin) ValidateObservation( - outctx ocr3types.OutcomeContext, query types.Query, ao types.AttributedObservation, + ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, ao types.AttributedObservation, ) error { decodedObservation, err := exectypes.DecodeObservation(ao.Observation) if err != nil { @@ -311,9 +332,12 @@ func (p *Plugin) ValidateObservation( return nil } -func (p *Plugin) ObservationQuorum(outctx ocr3types.OutcomeContext, query types.Query) (ocr3types.Quorum, error) { +func (p *Plugin) ObservationQuorum( + _ context.Context, outctx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation, +) (bool, error) { // TODO: should we use f+1 (or less) instead of 2f+1 because it is not needed for security? - return ocr3types.QuorumFPlusOne, nil + return quorumhelper.ObservationCountReachesObservationQuorum( + quorumhelper.QuorumFPlusOne, p.reportingCfg.N, p.reportingCfg.F, aos), nil } // selectReport takes a list of reports in execution order and selects the first reports that fit within the @@ -361,7 +385,7 @@ func selectReport( // formed report that will be encoded for final transmission in the reporting phase. // nolint:gocyclo // todo func (p *Plugin) Outcome( - outctx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation, + ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation, ) (ocr3types.Outcome, error) { var previousOutcome exectypes.Outcome if outctx.PreviousOutcome != nil { @@ -462,7 +486,9 @@ func (p *Plugin) Outcome( return outcome.Encode() } -func (p *Plugin) Reports(seqNr uint64, outcome ocr3types.Outcome) ([]ocr3types.ReportWithInfo[[]byte], error) { +func (p *Plugin) Reports( + ctx context.Context, seqNr uint64, outcome ocr3types.Outcome, +) ([]ocr3types.ReportPlus[[]byte], error) { if outcome == nil { p.lggr.Warn("no outcome, skipping report generation") return nil, nil @@ -474,15 +500,17 @@ func (p *Plugin) Reports(seqNr uint64, outcome ocr3types.Outcome) ([]ocr3types.R } // TODO: this function should be pure, a context should not be needed. - encoded, err := p.reportCodec.Encode(context.Background(), decodedOutcome.Report) + encoded, err := p.reportCodec.Encode(ctx, decodedOutcome.Report) if err != nil { return nil, fmt.Errorf("unable to encode report: %w", err) } - report := []ocr3types.ReportWithInfo[[]byte]{{ - Report: encoded, - Info: nil, - }} + report := []ocr3types.ReportPlus[[]byte]{ + {ReportWithInfo: ocr3types.ReportWithInfo[[]byte]{ + Report: encoded, + Info: nil, + }}, + } return report, nil } @@ -536,22 +564,6 @@ func (p *Plugin) ShouldTransmitAcceptedReport( return true, nil } -func (p *Plugin) Close() error { - timeout := 10 * time.Second // todo: cfg - ctx, cf := context.WithTimeout(context.Background(), timeout) - defer cf() - - if err := p.readerSyncer.Close(); err != nil { - p.lggr.Warnw("error closing reader syncer", "err", err) - } - - if err := p.ccipReader.Close(ctx); err != nil { - return fmt.Errorf("close ccip reader: %w", err) - } - - return nil -} - func (p *Plugin) supportedChains(id commontypes.OracleID) (mapset.Set[cciptypes.ChainSelector], error) { p2pID, exists := p.oracleIDToP2pID[id] if !exists { diff --git a/execute/plugin_e2e_test.go b/execute/plugin_e2e_test.go index 93960f46..a559f15d 100644 --- a/execute/plugin_e2e_test.go +++ b/execute/plugin_e2e_test.go @@ -254,8 +254,8 @@ func setupSimpleTest( } func newNode( - _ context.Context, - _ *testing.T, + ctx context.Context, + t *testing.T, lggr logger.Logger, cfg pluginconfig.ExecutePluginConfig, msgHasher cciptypes.MessageHasher, @@ -284,6 +284,9 @@ func newNode( tokenDataObserver, evm.EstimateProvider{}, lggr) + if err := node1.Start(ctx); err != nil { + t.Fatalf("failed to start plugin: %v", err) + } return nodeSetup{ node: node1, diff --git a/execute/plugin_test.go b/execute/plugin_test.go index f876ffc7..7ea1fd78 100644 --- a/execute/plugin_test.go +++ b/execute/plugin_test.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-ccip/execute/exectypes" "github.com/smartcontractkit/chainlink-ccip/internal/libs/slicelib" @@ -183,15 +184,22 @@ func TestPlugin_Query(t *testing.T) { } func TestPlugin_ObservationQuorum(t *testing.T) { - p := &Plugin{} - got, err := p.ObservationQuorum(ocr3types.OutcomeContext{}, nil) + ctx := tests.Context(t) + p := &Plugin{ + reportingCfg: ocr3types.ReportingPluginConfig{F: 1}, + } + got, err := p.ObservationQuorum(ctx, ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{ + {Observation: []byte{}}, + {Observation: []byte{}}, + }) require.NoError(t, err) - assert.Equal(t, ocr3types.QuorumFPlusOne, got) + assert.Equal(t, true, got) } func TestPlugin_ValidateObservation_NonDecodable(t *testing.T) { + ctx := tests.Context(t) p := &Plugin{} - err := p.ValidateObservation(ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ + err := p.ValidateObservation(ctx, ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ Observation: []byte("not a valid observation"), }) require.Error(t, err) @@ -199,8 +207,9 @@ func TestPlugin_ValidateObservation_NonDecodable(t *testing.T) { } func TestPlugin_ValidateObservation_SupportedChainsError(t *testing.T) { + ctx := tests.Context(t) p := &Plugin{} - err := p.ValidateObservation(ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ + err := p.ValidateObservation(ctx, ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ Observation: []byte(`{"oracleID": "0xdeadbeef"}`), }) require.Error(t, err) @@ -208,6 +217,7 @@ func TestPlugin_ValidateObservation_SupportedChainsError(t *testing.T) { } func TestPlugin_ValidateObservation_IneligibleObserver(t *testing.T) { + ctx := tests.Context(t) lggr := logger.Test(t) mockHomeChain := reader_mock.NewMockHomeChain(t) @@ -233,7 +243,7 @@ func TestPlugin_ValidateObservation_IneligibleObserver(t *testing.T) { }, nil, nil) encoded, err := observation.Encode() require.NoError(t, err) - err = p.ValidateObservation(ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ + err = p.ValidateObservation(ctx, ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ Observation: encoded, }) require.Error(t, err) @@ -241,6 +251,7 @@ func TestPlugin_ValidateObservation_IneligibleObserver(t *testing.T) { } func TestPlugin_ValidateObservation_ValidateObservedSeqNum_Error(t *testing.T) { + ctx := tests.Context(t) lggr := logger.Test(t) mockHomeChain := reader_mock.NewMockHomeChain(t) @@ -265,7 +276,7 @@ func TestPlugin_ValidateObservation_ValidateObservedSeqNum_Error(t *testing.T) { observation := exectypes.NewObservation(commitReports, nil, nil, nil) encoded, err := observation.Encode() require.NoError(t, err) - err = p.ValidateObservation(ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ + err = p.ValidateObservation(ctx, ocr3types.OutcomeContext{}, types.Query{}, types.AttributedObservation{ Observation: encoded, }) require.Error(t, err) @@ -299,10 +310,11 @@ func TestPlugin_Observation_EligibilityCheckFailure(t *testing.T) { } func TestPlugin_Outcome_BadObservationEncoding(t *testing.T) { + ctx := tests.Context(t) homeChain := reader_mock.NewMockHomeChain(t) homeChain.EXPECT().GetFChain().Return(nil, nil) p := &Plugin{lggr: logger.Test(t), homeChain: homeChain} - _, err := p.Outcome(ocr3types.OutcomeContext{}, nil, + _, err := p.Outcome(ctx, ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{ { Observation: []byte("not a valid observation"), @@ -314,6 +326,7 @@ func TestPlugin_Outcome_BadObservationEncoding(t *testing.T) { } func TestPlugin_Outcome_BelowF(t *testing.T) { + ctx := tests.Context(t) homeChain := reader_mock.NewMockHomeChain(t) homeChain.EXPECT().GetFChain().Return(nil, nil) p := &Plugin{ @@ -323,13 +336,14 @@ func TestPlugin_Outcome_BelowF(t *testing.T) { }, lggr: logger.Test(t), } - _, err := p.Outcome(ocr3types.OutcomeContext{}, nil, + _, err := p.Outcome(ctx, ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{}) require.Error(t, err) assert.Contains(t, err.Error(), "below F threshold") } func TestPlugin_Outcome_HomeChainError(t *testing.T) { + ctx := tests.Context(t) homeChain := reader_mock.NewMockHomeChain(t) homeChain.On("GetFChain", mock.Anything).Return(nil, fmt.Errorf("test error")) @@ -337,12 +351,13 @@ func TestPlugin_Outcome_HomeChainError(t *testing.T) { homeChain: homeChain, lggr: logger.Test(t), } - _, err := p.Outcome(ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{}) + _, err := p.Outcome(ctx, ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{}) require.Error(t, err) assert.Contains(t, err.Error(), "unable to get FChain: test error") } func TestPlugin_Outcome_CommitReportsMergeError(t *testing.T) { + ctx := tests.Context(t) homeChain := reader_mock.NewMockHomeChain(t) fChainMap := map[cciptypes.ChainSelector]int{ 10: 20, @@ -359,7 +374,7 @@ func TestPlugin_Outcome_CommitReportsMergeError(t *testing.T) { } observation, err := exectypes.NewObservation(commitReports, nil, nil, nil).Encode() require.NoError(t, err) - _, err = p.Outcome(ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{ + _, err = p.Outcome(ctx, ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{ { Observation: observation, }, @@ -369,6 +384,7 @@ func TestPlugin_Outcome_CommitReportsMergeError(t *testing.T) { } func TestPlugin_Outcome_MessagesMergeError(t *testing.T) { + ctx := tests.Context(t) homeChain := reader_mock.NewMockHomeChain(t) fChainMap := map[cciptypes.ChainSelector]int{ 10: 20, @@ -392,7 +408,7 @@ func TestPlugin_Outcome_MessagesMergeError(t *testing.T) { } observation, err := exectypes.NewObservation(nil, messages, nil, nil).Encode() require.NoError(t, err) - _, err = p.Outcome(ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{ + _, err = p.Outcome(ctx, ocr3types.OutcomeContext{}, nil, []types.AttributedObservation{ { Observation: observation, }, @@ -402,13 +418,15 @@ func TestPlugin_Outcome_MessagesMergeError(t *testing.T) { } func TestPlugin_Reports_UnableToParse(t *testing.T) { + ctx := tests.Context(t) p := &Plugin{} - _, err := p.Reports(0, ocr3types.Outcome("not a valid observation")) + _, err := p.Reports(ctx, 0, ocr3types.Outcome("not a valid observation")) require.Error(t, err) assert.Contains(t, err.Error(), "unable to decode outcome") } func TestPlugin_Reports_UnableToEncode(t *testing.T) { + ctx := tests.Context(t) codec := codec_mocks.NewMockExecutePluginCodec(t) codec.On("Encode", mock.Anything, mock.Anything). Return(nil, fmt.Errorf("test error")) @@ -416,7 +434,7 @@ func TestPlugin_Reports_UnableToEncode(t *testing.T) { report, err := exectypes.NewOutcome(exectypes.Unknown, nil, cciptypes.ExecutePluginReport{}).Encode() require.NoError(t, err) - _, err = p.Reports(0, report) + _, err = p.Reports(ctx, 0, report) require.Error(t, err) assert.Contains(t, err.Error(), "unable to encode report: test error") } diff --git a/go.mod b/go.mod index 73609d12..e1583af1 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.22.5 require ( github.com/deckarep/golang-set/v2 v2.6.0 github.com/smartcontractkit/chain-selectors v1.0.23 - github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919092417-53e784c2e420 - github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 + github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919134624-1a9bd2ac4b18 + github.com/smartcontractkit/libocr v0.0.0-20240830084433-f4f9f401c0ac github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.27.0 diff --git a/go.sum b/go.sum index 992bddc6..1d9f61b7 100644 --- a/go.sum +++ b/go.sum @@ -59,10 +59,10 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919092417-53e784c2e420 h1:+xNnYYgkxzKUIkLCOfzfAKUxeLLtuxlalDI70kNJ8No= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919092417-53e784c2e420/go.mod h1:zm+l8gN4LQS1+YvwQDhRz/njirVeWGNiDJKIhCGwaoQ= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919134624-1a9bd2ac4b18 h1:GDNj7L8Bkp3RjXttjKaKcS3NCMutVmyGL/Bf5OMIRd0= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919134624-1a9bd2ac4b18/go.mod h1:llM0s/N/PAE3LOaZ6kiC7nzw9/0KPJoiziGgLraOoS0= +github.com/smartcontractkit/libocr v0.0.0-20240830084433-f4f9f401c0ac h1:jo3kFDcpF4/hfBLNMhLL7bvjdnJkEaUhbxXIFiC9lVs= +github.com/smartcontractkit/libocr v0.0.0-20240830084433-f4f9f401c0ac/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/internal/libs/testhelpers/ocr3runner.go b/internal/libs/testhelpers/ocr3runner.go index 160b5caa..3a1d722f 100644 --- a/internal/libs/testhelpers/ocr3runner.go +++ b/internal/libs/testhelpers/ocr3runner.go @@ -72,7 +72,7 @@ func (r *OCR3Runner[RI]) RunRound(ctx context.Context) (result RoundResult[RI], } attrObs := types.AttributedObservation{Observation: obs, Observer: r.nodeIDs[i]} - err = leaderNode.ValidateObservation(outcomeCtx, q, attrObs) + err = leaderNode.ValidateObservation(ctx, outcomeCtx, q, attrObs) if err != nil { return RoundResult[RI]{}, fmt.Errorf("%w: %w", err, ErrValidateObservation) } @@ -82,7 +82,7 @@ func (r *OCR3Runner[RI]) RunRound(ctx context.Context) (result RoundResult[RI], outcomes := make([]ocr3types.Outcome, len(r.nodes)) for i, n := range r.nodes { - outcome, err2 := n.Outcome(outcomeCtx, q, attributedObservations) + outcome, err2 := n.Outcome(ctx, outcomeCtx, q, attributedObservations) if err2 != nil { return RoundResult[RI]{}, fmt.Errorf("%w: %w", err2, ErrOutcome) } @@ -100,14 +100,14 @@ func (r *OCR3Runner[RI]) RunRound(ctx context.Context) (result RoundResult[RI], r.previousOutcome = outcomes[0] - allReports := make([][]ocr3types.ReportWithInfo[RI], len(r.nodes)) + allReports := make([][]ocr3types.ReportPlus[RI], len(r.nodes)) for i, n := range r.nodes { - reportsWithInfo, err2 := n.Reports(seqNr, outcomes[0]) + reportsPlus, err2 := n.Reports(ctx, seqNr, outcomes[0]) if err2 != nil { return RoundResult[RI]{}, fmt.Errorf("%w: %w", err2, ErrReports) } - allReports[i] = reportsWithInfo + allReports[i] = reportsPlus } // check that all the reports are the same. @@ -122,7 +122,7 @@ func (r *OCR3Runner[RI]) RunRound(ctx context.Context) (result RoundResult[RI], for _, report := range allReports[0] { allShouldAccept := make([]bool, len(r.nodes)) for i, n := range r.nodes { - shouldAccept, err2 := n.ShouldAcceptAttestedReport(ctx, seqNr, report) + shouldAccept, err2 := n.ShouldAcceptAttestedReport(ctx, seqNr, report.ReportWithInfo) if err2 != nil { return RoundResult[RI]{}, fmt.Errorf("%w: %w", err2, ErrShouldAcceptAttestedReport) } @@ -134,13 +134,13 @@ func (r *OCR3Runner[RI]) RunRound(ctx context.Context) (result RoundResult[RI], } if !allShouldAccept[0] { - notAccepted = append(notAccepted, report) + notAccepted = append(notAccepted, report.ReportWithInfo) continue } allShouldTransmit := make([]bool, len(r.nodes)) for i, n := range r.nodes { - shouldTransmit, err2 := n.ShouldTransmitAcceptedReport(ctx, seqNr, report) + shouldTransmit, err2 := n.ShouldTransmitAcceptedReport(ctx, seqNr, report.ReportWithInfo) if err2 != nil { return RoundResult[RI]{}, fmt.Errorf("%w: %w", err2, ErrShouldTransmitAcceptedReport) } @@ -152,11 +152,11 @@ func (r *OCR3Runner[RI]) RunRound(ctx context.Context) (result RoundResult[RI], } if !allShouldTransmit[0] { - notTransmitted = append(notTransmitted, report) + notTransmitted = append(notTransmitted, report.ReportWithInfo) continue } - transmitted = append(transmitted, report) + transmitted = append(transmitted, report.ReportWithInfo) } return RoundResult[RI]{ @@ -200,11 +200,11 @@ func countUniqueOutcomes(outcomes []ocr3types.Outcome) int { return slicelib.CountUnique(flattenedHashes) } -func countUniqueReports[RI any](reports []ocr3types.ReportWithInfo[RI]) int { +func countUniqueReports[RI any](reports []ocr3types.ReportPlus[RI]) int { flattenedHashes := make([]string, 0, len(reports)) for _, report := range reports { h := sha256.New() - h.Write(report.Report) + h.Write(report.ReportWithInfo.Report) flattenedHashes = append(flattenedHashes, hex.EncodeToString(h.Sum(nil))) } return slicelib.CountUnique(flattenedHashes) diff --git a/internal/plugincommon/ccipreader.go b/internal/plugincommon/ccipreader.go index 7d20f006..a946b51a 100644 --- a/internal/plugincommon/ccipreader.go +++ b/internal/plugincommon/ccipreader.go @@ -49,12 +49,12 @@ func NewBackgroundReaderSyncer( } } -func (b *BackgroundReaderSyncer) Start(ctx context.Context) error { +func (b *BackgroundReaderSyncer) Start(_ context.Context) error { if b.bgSyncCtx != nil { return fmt.Errorf("background syncer already started") } - b.bgSyncCtx, b.bgSyncCf = context.WithCancel(ctx) + b.bgSyncCtx, b.bgSyncCf = context.WithCancel(context.Background()) b.bgSyncWG = &sync.WaitGroup{} b.bgSyncWG.Add(1) b.bgSyncTicker = time.NewTicker(b.syncFrequency) diff --git a/internal/plugincommon/plugin_processor.go b/internal/plugincommon/plugin_processor.go index 7527e66d..5de6b76b 100644 --- a/internal/plugincommon/plugin_processor.go +++ b/internal/plugincommon/plugin_processor.go @@ -36,9 +36,9 @@ type AttributedObservation[ObservationType any] struct { // Notice all interface functions are using prevOutcome instead of outCtx. // We're interested in the prevOutcome, and it makes it easier to have all decoding on the top level (OCR plugin), // otherwise there might be cyclic dependencies or just complicating the code more. -type PluginProcessor[QueryType any, ObservationType any, OutcomeType any] interface { - Query(ctx context.Context, prevOutcome OutcomeType) (QueryType, error) - Observation(ctx context.Context, prevOutcome OutcomeType, query QueryType) (ObservationType, error) - ValidateObservation(prevOutcome OutcomeType, query QueryType, ao AttributedObservation[ObservationType]) error - Outcome(prevOutcome OutcomeType, query QueryType, aos []AttributedObservation[ObservationType]) (OutcomeType, error) +type PluginProcessor[Query any, Observation any, Outcome any] interface { + Query(ctx context.Context, prev Outcome) (Query, error) + Observation(ctx context.Context, prev Outcome, query Query) (Observation, error) + ValidateObservation(prev Outcome, query Query, ao AttributedObservation[Observation]) error + Outcome(ctx context.Context, prev Outcome, query Query, aos []AttributedObservation[Observation]) (Outcome, error) } diff --git a/mocks/internal_/plugincommon/plugin_processor.go b/mocks/internal_/plugincommon/plugin_processor.go index 69c2ac73..66beb85b 100644 --- a/mocks/internal_/plugincommon/plugin_processor.go +++ b/mocks/internal_/plugincommon/plugin_processor.go @@ -10,39 +10,39 @@ import ( ) // MockPluginProcessor is an autogenerated mock type for the PluginProcessor type -type MockPluginProcessor[QueryType interface{}, ObservationType interface{}, OutcomeType interface{}] struct { +type MockPluginProcessor[Query interface{}, Observation interface{}, Outcome interface{}] struct { mock.Mock } -type MockPluginProcessor_Expecter[QueryType interface{}, ObservationType interface{}, OutcomeType interface{}] struct { +type MockPluginProcessor_Expecter[Query interface{}, Observation interface{}, Outcome interface{}] struct { mock *mock.Mock } -func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) EXPECT() *MockPluginProcessor_Expecter[QueryType, ObservationType, OutcomeType] { - return &MockPluginProcessor_Expecter[QueryType, ObservationType, OutcomeType]{mock: &_m.Mock} +func (_m *MockPluginProcessor[Query, Observation, Outcome]) EXPECT() *MockPluginProcessor_Expecter[Query, Observation, Outcome] { + return &MockPluginProcessor_Expecter[Query, Observation, Outcome]{mock: &_m.Mock} } -// Observation provides a mock function with given fields: ctx, prevOutcome, query -func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) Observation(ctx context.Context, prevOutcome OutcomeType, query QueryType) (ObservationType, error) { - ret := _m.Called(ctx, prevOutcome, query) +// Observation provides a mock function with given fields: ctx, prev, query +func (_m *MockPluginProcessor[Query, Observation, Outcome]) Observation(ctx context.Context, prev Outcome, query Query) (Observation, error) { + ret := _m.Called(ctx, prev, query) if len(ret) == 0 { panic("no return value specified for Observation") } - var r0 ObservationType + var r0 Observation var r1 error - if rf, ok := ret.Get(0).(func(context.Context, OutcomeType, QueryType) (ObservationType, error)); ok { - return rf(ctx, prevOutcome, query) + if rf, ok := ret.Get(0).(func(context.Context, Outcome, Query) (Observation, error)); ok { + return rf(ctx, prev, query) } - if rf, ok := ret.Get(0).(func(context.Context, OutcomeType, QueryType) ObservationType); ok { - r0 = rf(ctx, prevOutcome, query) + if rf, ok := ret.Get(0).(func(context.Context, Outcome, Query) Observation); ok { + r0 = rf(ctx, prev, query) } else { - r0 = ret.Get(0).(ObservationType) + r0 = ret.Get(0).(Observation) } - if rf, ok := ret.Get(1).(func(context.Context, OutcomeType, QueryType) error); ok { - r1 = rf(ctx, prevOutcome, query) + if rf, ok := ret.Get(1).(func(context.Context, Outcome, Query) error); ok { + r1 = rf(ctx, prev, query) } else { r1 = ret.Error(1) } @@ -51,56 +51,56 @@ func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) Observat } // MockPluginProcessor_Observation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Observation' -type MockPluginProcessor_Observation_Call[QueryType interface{}, ObservationType interface{}, OutcomeType interface{}] struct { +type MockPluginProcessor_Observation_Call[Query interface{}, Observation interface{}, Outcome interface{}] struct { *mock.Call } // Observation is a helper method to define mock.On call // - ctx context.Context -// - prevOutcome OutcomeType -// - query QueryType -func (_e *MockPluginProcessor_Expecter[QueryType, ObservationType, OutcomeType]) Observation(ctx interface{}, prevOutcome interface{}, query interface{}) *MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType] { - return &MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType]{Call: _e.mock.On("Observation", ctx, prevOutcome, query)} +// - prev Outcome +// - query Query +func (_e *MockPluginProcessor_Expecter[Query, Observation, Outcome]) Observation(ctx interface{}, prev interface{}, query interface{}) *MockPluginProcessor_Observation_Call[Query, Observation, Outcome] { + return &MockPluginProcessor_Observation_Call[Query, Observation, Outcome]{Call: _e.mock.On("Observation", ctx, prev, query)} } -func (_c *MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType]) Run(run func(ctx context.Context, prevOutcome OutcomeType, query QueryType)) *MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Observation_Call[Query, Observation, Outcome]) Run(run func(ctx context.Context, prev Outcome, query Query)) *MockPluginProcessor_Observation_Call[Query, Observation, Outcome] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(OutcomeType), args[2].(QueryType)) + run(args[0].(context.Context), args[1].(Outcome), args[2].(Query)) }) return _c } -func (_c *MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType]) Return(_a0 ObservationType, _a1 error) *MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Observation_Call[Query, Observation, Outcome]) Return(_a0 Observation, _a1 error) *MockPluginProcessor_Observation_Call[Query, Observation, Outcome] { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType]) RunAndReturn(run func(context.Context, OutcomeType, QueryType) (ObservationType, error)) *MockPluginProcessor_Observation_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Observation_Call[Query, Observation, Outcome]) RunAndReturn(run func(context.Context, Outcome, Query) (Observation, error)) *MockPluginProcessor_Observation_Call[Query, Observation, Outcome] { _c.Call.Return(run) return _c } -// Outcome provides a mock function with given fields: prevOutcome, query, aos -func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) Outcome(prevOutcome OutcomeType, query QueryType, aos []plugincommon.AttributedObservation[ObservationType]) (OutcomeType, error) { - ret := _m.Called(prevOutcome, query, aos) +// Outcome provides a mock function with given fields: ctx, prev, query, aos +func (_m *MockPluginProcessor[Query, Observation, Outcome]) Outcome(ctx context.Context, prev Outcome, query Query, aos []plugincommon.AttributedObservation[Observation]) (Outcome, error) { + ret := _m.Called(ctx, prev, query, aos) if len(ret) == 0 { panic("no return value specified for Outcome") } - var r0 OutcomeType + var r0 Outcome var r1 error - if rf, ok := ret.Get(0).(func(OutcomeType, QueryType, []plugincommon.AttributedObservation[ObservationType]) (OutcomeType, error)); ok { - return rf(prevOutcome, query, aos) + if rf, ok := ret.Get(0).(func(context.Context, Outcome, Query, []plugincommon.AttributedObservation[Observation]) (Outcome, error)); ok { + return rf(ctx, prev, query, aos) } - if rf, ok := ret.Get(0).(func(OutcomeType, QueryType, []plugincommon.AttributedObservation[ObservationType]) OutcomeType); ok { - r0 = rf(prevOutcome, query, aos) + if rf, ok := ret.Get(0).(func(context.Context, Outcome, Query, []plugincommon.AttributedObservation[Observation]) Outcome); ok { + r0 = rf(ctx, prev, query, aos) } else { - r0 = ret.Get(0).(OutcomeType) + r0 = ret.Get(0).(Outcome) } - if rf, ok := ret.Get(1).(func(OutcomeType, QueryType, []plugincommon.AttributedObservation[ObservationType]) error); ok { - r1 = rf(prevOutcome, query, aos) + if rf, ok := ret.Get(1).(func(context.Context, Outcome, Query, []plugincommon.AttributedObservation[Observation]) error); ok { + r1 = rf(ctx, prev, query, aos) } else { r1 = ret.Error(1) } @@ -109,56 +109,57 @@ func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) Outcome( } // MockPluginProcessor_Outcome_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Outcome' -type MockPluginProcessor_Outcome_Call[QueryType interface{}, ObservationType interface{}, OutcomeType interface{}] struct { +type MockPluginProcessor_Outcome_Call[Query interface{}, Observation interface{}, Outcome interface{}] struct { *mock.Call } // Outcome is a helper method to define mock.On call -// - prevOutcome OutcomeType -// - query QueryType -// - aos []plugincommon.AttributedObservation[ObservationType] -func (_e *MockPluginProcessor_Expecter[QueryType, ObservationType, OutcomeType]) Outcome(prevOutcome interface{}, query interface{}, aos interface{}) *MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType] { - return &MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType]{Call: _e.mock.On("Outcome", prevOutcome, query, aos)} +// - ctx context.Context +// - prev Outcome +// - query Query +// - aos []plugincommon.AttributedObservation[Observation] +func (_e *MockPluginProcessor_Expecter[Query, Observation, Outcome]) Outcome(ctx interface{}, prev interface{}, query interface{}, aos interface{}) *MockPluginProcessor_Outcome_Call[Query, Observation, Outcome] { + return &MockPluginProcessor_Outcome_Call[Query, Observation, Outcome]{Call: _e.mock.On("Outcome", ctx, prev, query, aos)} } -func (_c *MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType]) Run(run func(prevOutcome OutcomeType, query QueryType, aos []plugincommon.AttributedObservation[ObservationType])) *MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Outcome_Call[Query, Observation, Outcome]) Run(run func(ctx context.Context, prev Outcome, query Query, aos []plugincommon.AttributedObservation[Observation])) *MockPluginProcessor_Outcome_Call[Query, Observation, Outcome] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(OutcomeType), args[1].(QueryType), args[2].([]plugincommon.AttributedObservation[ObservationType])) + run(args[0].(context.Context), args[1].(Outcome), args[2].(Query), args[3].([]plugincommon.AttributedObservation[Observation])) }) return _c } -func (_c *MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType]) Return(_a0 OutcomeType, _a1 error) *MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Outcome_Call[Query, Observation, Outcome]) Return(_a0 Outcome, _a1 error) *MockPluginProcessor_Outcome_Call[Query, Observation, Outcome] { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType]) RunAndReturn(run func(OutcomeType, QueryType, []plugincommon.AttributedObservation[ObservationType]) (OutcomeType, error)) *MockPluginProcessor_Outcome_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Outcome_Call[Query, Observation, Outcome]) RunAndReturn(run func(context.Context, Outcome, Query, []plugincommon.AttributedObservation[Observation]) (Outcome, error)) *MockPluginProcessor_Outcome_Call[Query, Observation, Outcome] { _c.Call.Return(run) return _c } -// Query provides a mock function with given fields: ctx, prevOutcome -func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) Query(ctx context.Context, prevOutcome OutcomeType) (QueryType, error) { - ret := _m.Called(ctx, prevOutcome) +// Query provides a mock function with given fields: ctx, prev +func (_m *MockPluginProcessor[Query, Observation, Outcome]) Query(ctx context.Context, prev Outcome) (Query, error) { + ret := _m.Called(ctx, prev) if len(ret) == 0 { panic("no return value specified for Query") } - var r0 QueryType + var r0 Query var r1 error - if rf, ok := ret.Get(0).(func(context.Context, OutcomeType) (QueryType, error)); ok { - return rf(ctx, prevOutcome) + if rf, ok := ret.Get(0).(func(context.Context, Outcome) (Query, error)); ok { + return rf(ctx, prev) } - if rf, ok := ret.Get(0).(func(context.Context, OutcomeType) QueryType); ok { - r0 = rf(ctx, prevOutcome) + if rf, ok := ret.Get(0).(func(context.Context, Outcome) Query); ok { + r0 = rf(ctx, prev) } else { - r0 = ret.Get(0).(QueryType) + r0 = ret.Get(0).(Query) } - if rf, ok := ret.Get(1).(func(context.Context, OutcomeType) error); ok { - r1 = rf(ctx, prevOutcome) + if rf, ok := ret.Get(1).(func(context.Context, Outcome) error); ok { + r1 = rf(ctx, prev) } else { r1 = ret.Error(1) } @@ -167,45 +168,45 @@ func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) Query(ct } // MockPluginProcessor_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' -type MockPluginProcessor_Query_Call[QueryType interface{}, ObservationType interface{}, OutcomeType interface{}] struct { +type MockPluginProcessor_Query_Call[Query interface{}, Observation interface{}, Outcome interface{}] struct { *mock.Call } // Query is a helper method to define mock.On call // - ctx context.Context -// - prevOutcome OutcomeType -func (_e *MockPluginProcessor_Expecter[QueryType, ObservationType, OutcomeType]) Query(ctx interface{}, prevOutcome interface{}) *MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType] { - return &MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType]{Call: _e.mock.On("Query", ctx, prevOutcome)} +// - prev Outcome +func (_e *MockPluginProcessor_Expecter[Query, Observation, Outcome]) Query(ctx interface{}, prev interface{}) *MockPluginProcessor_Query_Call[Query, Observation, Outcome] { + return &MockPluginProcessor_Query_Call[Query, Observation, Outcome]{Call: _e.mock.On("Query", ctx, prev)} } -func (_c *MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType]) Run(run func(ctx context.Context, prevOutcome OutcomeType)) *MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Query_Call[Query, Observation, Outcome]) Run(run func(ctx context.Context, prev Outcome)) *MockPluginProcessor_Query_Call[Query, Observation, Outcome] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(OutcomeType)) + run(args[0].(context.Context), args[1].(Outcome)) }) return _c } -func (_c *MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType]) Return(_a0 QueryType, _a1 error) *MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Query_Call[Query, Observation, Outcome]) Return(_a0 Query, _a1 error) *MockPluginProcessor_Query_Call[Query, Observation, Outcome] { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType]) RunAndReturn(run func(context.Context, OutcomeType) (QueryType, error)) *MockPluginProcessor_Query_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_Query_Call[Query, Observation, Outcome]) RunAndReturn(run func(context.Context, Outcome) (Query, error)) *MockPluginProcessor_Query_Call[Query, Observation, Outcome] { _c.Call.Return(run) return _c } -// ValidateObservation provides a mock function with given fields: prevOutcome, query, ao -func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) ValidateObservation(prevOutcome OutcomeType, query QueryType, ao plugincommon.AttributedObservation[ObservationType]) error { - ret := _m.Called(prevOutcome, query, ao) +// ValidateObservation provides a mock function with given fields: prev, query, ao +func (_m *MockPluginProcessor[Query, Observation, Outcome]) ValidateObservation(prev Outcome, query Query, ao plugincommon.AttributedObservation[Observation]) error { + ret := _m.Called(prev, query, ao) if len(ret) == 0 { panic("no return value specified for ValidateObservation") } var r0 error - if rf, ok := ret.Get(0).(func(OutcomeType, QueryType, plugincommon.AttributedObservation[ObservationType]) error); ok { - r0 = rf(prevOutcome, query, ao) + if rf, ok := ret.Get(0).(func(Outcome, Query, plugincommon.AttributedObservation[Observation]) error); ok { + r0 = rf(prev, query, ao) } else { r0 = ret.Error(0) } @@ -214,42 +215,42 @@ func (_m *MockPluginProcessor[QueryType, ObservationType, OutcomeType]) Validate } // MockPluginProcessor_ValidateObservation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidateObservation' -type MockPluginProcessor_ValidateObservation_Call[QueryType interface{}, ObservationType interface{}, OutcomeType interface{}] struct { +type MockPluginProcessor_ValidateObservation_Call[Query interface{}, Observation interface{}, Outcome interface{}] struct { *mock.Call } // ValidateObservation is a helper method to define mock.On call -// - prevOutcome OutcomeType -// - query QueryType -// - ao plugincommon.AttributedObservation[ObservationType] -func (_e *MockPluginProcessor_Expecter[QueryType, ObservationType, OutcomeType]) ValidateObservation(prevOutcome interface{}, query interface{}, ao interface{}) *MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType] { - return &MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType]{Call: _e.mock.On("ValidateObservation", prevOutcome, query, ao)} +// - prev Outcome +// - query Query +// - ao plugincommon.AttributedObservation[Observation] +func (_e *MockPluginProcessor_Expecter[Query, Observation, Outcome]) ValidateObservation(prev interface{}, query interface{}, ao interface{}) *MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome] { + return &MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome]{Call: _e.mock.On("ValidateObservation", prev, query, ao)} } -func (_c *MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType]) Run(run func(prevOutcome OutcomeType, query QueryType, ao plugincommon.AttributedObservation[ObservationType])) *MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome]) Run(run func(prev Outcome, query Query, ao plugincommon.AttributedObservation[Observation])) *MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(OutcomeType), args[1].(QueryType), args[2].(plugincommon.AttributedObservation[ObservationType])) + run(args[0].(Outcome), args[1].(Query), args[2].(plugincommon.AttributedObservation[Observation])) }) return _c } -func (_c *MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType]) Return(_a0 error) *MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome]) Return(_a0 error) *MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome] { _c.Call.Return(_a0) return _c } -func (_c *MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType]) RunAndReturn(run func(OutcomeType, QueryType, plugincommon.AttributedObservation[ObservationType]) error) *MockPluginProcessor_ValidateObservation_Call[QueryType, ObservationType, OutcomeType] { +func (_c *MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome]) RunAndReturn(run func(Outcome, Query, plugincommon.AttributedObservation[Observation]) error) *MockPluginProcessor_ValidateObservation_Call[Query, Observation, Outcome] { _c.Call.Return(run) return _c } // NewMockPluginProcessor creates a new instance of MockPluginProcessor. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. -func NewMockPluginProcessor[QueryType interface{}, ObservationType interface{}, OutcomeType interface{}](t interface { +func NewMockPluginProcessor[Query interface{}, Observation interface{}, Outcome interface{}](t interface { mock.TestingT Cleanup(func()) -}) *MockPluginProcessor[QueryType, ObservationType, OutcomeType] { - mock := &MockPluginProcessor[QueryType, ObservationType, OutcomeType]{} +}) *MockPluginProcessor[Query, Observation, Outcome] { + mock := &MockPluginProcessor[Query, Observation, Outcome]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) })