diff --git a/offchainreporting2/reportingplugin/median/median.go b/offchainreporting2/reportingplugin/median/median.go index d4c3310d..5f689720 100644 --- a/offchainreporting2/reportingplugin/median/median.go +++ b/offchainreporting2/reportingplugin/median/median.go @@ -112,6 +112,17 @@ type OffchainConfig struct { // Be careful setting this. It can cause increased transaction load and // costs. TransmitDespiteContractReadError bool + // If AcceptAfterFullTransmissionScheduleElapsed is true, a report will + // be accepted by ShouldAcceptFinalizedReport if the full transmission + // schedule has elapsed since the last accepted report. This is useful + // to prevent missed heartbeats on chains where sometimes *all* nodes + // are unable to successfully land a transaction, because otherwise the + // "pending report check" will keep blocking later non-deviating + // reports from being accepted. + // This flag defaults to false. The corresponding flag on + // NumericalMedianFactory has the same effect; if either flag is true, + // the condition applies. + AcceptAfterFullTransmissionScheduleElapsed bool } func DecodeOffchainConfig(b []byte) (OffchainConfig, error) { @@ -132,6 +143,7 @@ func DecodeOffchainConfig(b []byte) (OffchainConfig, error) { configProto.GetAlphaAcceptPpb(), time.Duration(configProto.GetDeltaCNanoseconds()), configProto.GetTransmitDespiteContractReadError(), + configProto.GetAcceptAfterFullTransmissionScheduleElapsed(), }, nil } @@ -148,6 +160,7 @@ func (c OffchainConfig) Encode() []byte { c.AlphaAcceptPPB, uint64(c.DeltaC), c.TransmitDespiteContractReadError, + c.AcceptAfterFullTransmissionScheduleElapsed, } result, err := proto.Marshal(&configProto) if err != nil { @@ -286,10 +299,16 @@ type NumericalMedianFactory struct { // function DefaultDeviationFunc. All oracles in the OCR protocol instance // must run with the same deviation function. DeviationFunc DeviationFunc + // The corresponding flag on OffchainConfig has the same effect; + // if either flag is true, the condition applies. See the + // comment on OffchainConfig.AcceptAfterFullTransmissionScheduleElapsed + // for details on what this does. + // It's preferable to configure this flag via OffchainConfig, but in cases + // where that is not feasible, you may set it here instead. + AcceptAfterFullTransmissionScheduleElapsed bool } func (fac NumericalMedianFactory) NewReportingPlugin(ctx context.Context, configuration types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { - offchainConfig, err := DecodeOffchainConfig(configuration.OffchainConfig) if err != nil { return nil, types.ReportingPluginInfo{}, err @@ -324,6 +343,7 @@ func (fac NumericalMedianFactory) NewReportingPlugin(ctx context.Context, config "onchainConfig": onchainConfig, "includeGasPriceSubunitsInObservation": fac.IncludeGasPriceSubunitsInObservation, "hasCustomDeviationFunc": fac.DeviationFunc != nil, + "acceptAfterFullTransmissionScheduleElapsed": fac.AcceptAfterFullTransmissionScheduleElapsed, }) return &numericalMedian{ @@ -337,11 +357,14 @@ func (fac NumericalMedianFactory) NewReportingPlugin(ctx context.Context, config logger, fac.ReportCodec, deviationFunc, + fac.AcceptAfterFullTransmissionScheduleElapsed || offchainConfig.AcceptAfterFullTransmissionScheduleElapsed, configuration.ConfigDigest, configuration.F, + configuration.DurationAllTransmissionStages, epochRound{}, new(big.Int), + time.Now(), maxReportLength, }, types.ReportingPluginInfo{ "NumericalMedian", @@ -376,22 +399,25 @@ func DefaultDeviationFunc(_ context.Context, thresholdPPB uint64, old *big.Int, var _ types.ReportingPlugin = (*numericalMedian)(nil) type numericalMedian struct { - offchainConfig OffchainConfig - onchainConfig OnchainConfig - contractTransmitter MedianContract - dataSource DataSource - juelsPerFeeCoinDataSource DataSource - gasPriceSubunitsDataSource DataSource - includeGasPriceSubunitsInObservation bool - logger loghelper.LoggerWithContext - reportCodec ReportCodec - deviationFunc DeviationFunc - - configDigest types.ConfigDigest - f int - latestAcceptedEpochRound epochRound - latestAcceptedMedian *big.Int - maxReportLength int + offchainConfig OffchainConfig + onchainConfig OnchainConfig + contractTransmitter MedianContract + dataSource DataSource + juelsPerFeeCoinDataSource DataSource + gasPriceSubunitsDataSource DataSource + includeGasPriceSubunitsInObservation bool + logger loghelper.LoggerWithContext + reportCodec ReportCodec + deviationFunc DeviationFunc + acceptAfterFullTransmissionScheduleElapsed bool + + configDigest types.ConfigDigest + f int + durationAllTransmissionStages time.Duration + latestAcceptedEpochRound epochRound + latestAcceptedMedian *big.Int + latestAcceptedTime time.Time + maxReportLength int } func (nm *numericalMedian) Query(ctx context.Context, repts types.ReportTimestamp) (types.Query, error) { @@ -754,25 +780,30 @@ func (nm *numericalMedian) ShouldAcceptFinalizedReport(ctx context.Context, rept nothingPending = !contractLatestTransmissionDetailsOrNil.EpochRound.Less(nm.latestAcceptedEpochRound) } - result := medianContractReadErrorAcceptOverride || (contractConfigDigestMatches && reportFresh && (deviates || nothingPending)) + fullTransmissionScheduleElapsedSinceLastAccepted := time.Since(nm.latestAcceptedTime) > nm.durationAllTransmissionStages + + result := medianContractReadErrorAcceptOverride || (contractConfigDigestMatches && reportFresh && (deviates || nothingPending || (nm.acceptAfterFullTransmissionScheduleElapsed && fullTransmissionScheduleElapsedSinceLastAccepted))) nm.logger.Debug("ShouldAcceptFinalizedReport() = result", commontypes.LogFields{ - "contractLatestTransmissionDetailsOrNil": contractLatestTransmissionDetailsOrNil, - "reportEpochRound": reportEpochRound, - "latestAcceptedEpochRound": nm.latestAcceptedEpochRound, - "alphaAcceptInfinite": nm.offchainConfig.AlphaAcceptInfinite, - "alphaAcceptPPB": nm.offchainConfig.AlphaAcceptPPB, - "medianContractReadErrorAcceptOverride": medianContractReadErrorAcceptOverride, - "contractConfigDigestMatches": contractConfigDigestMatches, - "reportFresh": reportFresh, - "nothingPending": nothingPending, - "deviates": deviates, - "result": result, + "contractLatestTransmissionDetailsOrNil": contractLatestTransmissionDetailsOrNil, + "reportEpochRound": reportEpochRound, + "latestAcceptedEpochRound": nm.latestAcceptedEpochRound, + "alphaAcceptInfinite": nm.offchainConfig.AlphaAcceptInfinite, + "alphaAcceptPPB": nm.offchainConfig.AlphaAcceptPPB, + "medianContractReadErrorAcceptOverride": medianContractReadErrorAcceptOverride, + "contractConfigDigestMatches": contractConfigDigestMatches, + "reportFresh": reportFresh, + "nothingPending": nothingPending, + "acceptAfterFullTransmissionScheduleElapsed": nm.acceptAfterFullTransmissionScheduleElapsed, + "fullTransmissionScheduleElapsedSinceLastAccepted": fullTransmissionScheduleElapsedSinceLastAccepted, + "deviates": deviates, + "result": result, }) if result { nm.latestAcceptedEpochRound = reportEpochRound nm.latestAcceptedMedian = reportMedian + nm.latestAcceptedTime = time.Now() } return result, nil diff --git a/offchainreporting2/reportingplugin/median/offchainreporting2_median_config.pb.go b/offchainreporting2/reportingplugin/median/offchainreporting2_median_config.pb.go index 1c13b2f6..a4025fa4 100644 --- a/offchainreporting2/reportingplugin/median/offchainreporting2_median_config.pb.go +++ b/offchainreporting2/reportingplugin/median/offchainreporting2_median_config.pb.go @@ -25,12 +25,13 @@ type NumericalMedianConfigProto struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AlphaReportInfinite bool `protobuf:"varint,1,opt,name=alpha_report_infinite,json=alphaReportInfinite,proto3" json:"alpha_report_infinite,omitempty"` - AlphaReportPpb uint64 `protobuf:"varint,2,opt,name=alpha_report_ppb,json=alphaReportPpb,proto3" json:"alpha_report_ppb,omitempty"` - AlphaAcceptInfinite bool `protobuf:"varint,3,opt,name=alpha_accept_infinite,json=alphaAcceptInfinite,proto3" json:"alpha_accept_infinite,omitempty"` - AlphaAcceptPpb uint64 `protobuf:"varint,4,opt,name=alpha_accept_ppb,json=alphaAcceptPpb,proto3" json:"alpha_accept_ppb,omitempty"` - DeltaCNanoseconds uint64 `protobuf:"varint,5,opt,name=delta_c_nanoseconds,json=deltaCNanoseconds,proto3" json:"delta_c_nanoseconds,omitempty"` - TransmitDespiteContractReadError bool `protobuf:"varint,6,opt,name=transmit_despite_contract_read_error,json=transmitDespiteContractReadError,proto3" json:"transmit_despite_contract_read_error,omitempty"` + AlphaReportInfinite bool `protobuf:"varint,1,opt,name=alpha_report_infinite,json=alphaReportInfinite,proto3" json:"alpha_report_infinite,omitempty"` + AlphaReportPpb uint64 `protobuf:"varint,2,opt,name=alpha_report_ppb,json=alphaReportPpb,proto3" json:"alpha_report_ppb,omitempty"` + AlphaAcceptInfinite bool `protobuf:"varint,3,opt,name=alpha_accept_infinite,json=alphaAcceptInfinite,proto3" json:"alpha_accept_infinite,omitempty"` + AlphaAcceptPpb uint64 `protobuf:"varint,4,opt,name=alpha_accept_ppb,json=alphaAcceptPpb,proto3" json:"alpha_accept_ppb,omitempty"` + DeltaCNanoseconds uint64 `protobuf:"varint,5,opt,name=delta_c_nanoseconds,json=deltaCNanoseconds,proto3" json:"delta_c_nanoseconds,omitempty"` + TransmitDespiteContractReadError bool `protobuf:"varint,6,opt,name=transmit_despite_contract_read_error,json=transmitDespiteContractReadError,proto3" json:"transmit_despite_contract_read_error,omitempty"` + AcceptAfterFullTransmissionScheduleElapsed bool `protobuf:"varint,7,opt,name=accept_after_full_transmission_schedule_elapsed,json=acceptAfterFullTransmissionScheduleElapsed,proto3" json:"accept_after_full_transmission_schedule_elapsed,omitempty"` } func (x *NumericalMedianConfigProto) Reset() { @@ -107,13 +108,20 @@ func (x *NumericalMedianConfigProto) GetTransmitDespiteContractReadError() bool return false } +func (x *NumericalMedianConfigProto) GetAcceptAfterFullTransmissionScheduleElapsed() bool { + if x != nil { + return x.AcceptAfterFullTransmissionScheduleElapsed + } + return false +} + var File_offchainreporting2_median_config_proto protoreflect.FileDescriptor var file_offchainreporting2_median_config_proto_rawDesc = []byte{ 0x0a, 0x26, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x32, 0x5f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x32, 0x22, 0xd8, 0x02, 0x0a, + 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x32, 0x22, 0xbd, 0x03, 0x0a, 0x1a, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x69, @@ -135,8 +143,14 @@ var file_offchainreporting2_median_config_proto_rawDesc = []byte{ 0x72, 0x61, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x44, 0x65, 0x73, 0x70, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, - 0x61, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x6d, 0x65, 0x64, - 0x69, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x63, 0x0a, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, + 0x6c, 0x65, 0x5f, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x2a, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x46, 0x75, 0x6c, + 0x6c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x45, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x42, 0x0a, 0x5a, 0x08, + 0x2e, 0x3b, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/offchainreporting2plus/confighelper/confighelper.go b/offchainreporting2plus/confighelper/confighelper.go index 36da13e3..b4224303 100644 --- a/offchainreporting2plus/confighelper/confighelper.go +++ b/offchainreporting2plus/confighelper/confighelper.go @@ -143,6 +143,7 @@ func ContractSetConfigArgsForEthereumIntegrationTest( alphaPPB, 0, false, + false, }.Encode(), util.PointerTo(50 * time.Millisecond), 50 * time.Millisecond, diff --git a/offchainreporting2plus/internal/config/ocr2config/public_config.go b/offchainreporting2plus/internal/config/ocr2config/public_config.go index 350a0fd1..4bb5aa74 100644 --- a/offchainreporting2plus/internal/config/ocr2config/public_config.go +++ b/offchainreporting2plus/internal/config/ocr2config/public_config.go @@ -52,7 +52,8 @@ type PublicConfig struct { // attempt to transmit (if in their view the first and second stage didn't // succeed). // - // sum(S) should equal n. + // It is recommended to have sum(S) >= n to ensure all oracles are + // included as transmitters. S []int // Identities (i.e. public keys) of the oracles participating in this // protocol instance. @@ -92,6 +93,30 @@ func (c *PublicConfig) N() int { return len(c.OracleIdentities) } +// DurationAllTransmissionStages returns how long it takes until +// all transmission stages have elapsed, i.e. by what time the final +// transmitting oracle will have had one DeltaStage to transmit. +// Recall that the OCR2 transmission schedule is described by N, S, and DeltaStage. +func (c *PublicConfig) DurationAllTransmissionStages() time.Duration { + if c.N() == 0 { + return 0 + } + + coveredOracles := 0 + lastNonZeroStageCount := 0 + for stageIdx, stageSize := range c.S { + if stageSize > 0 { + lastNonZeroStageCount = stageIdx + 1 + } + coveredOracles += stageSize + if coveredOracles >= c.N() { + return time.Duration(stageIdx+1) * c.DeltaStage + } + } + + return time.Duration(lastNonZeroStageCount) * c.DeltaStage +} + func (c *PublicConfig) CheckParameterBounds() error { if c.F < 0 || c.F > math.MaxUint8 { return errors.Errorf("number of potentially faulty oracles must fit in 8 bits.") diff --git a/offchainreporting2plus/internal/config/ocr3_1config/public_config.go b/offchainreporting2plus/internal/config/ocr3_1config/public_config.go index 8cc62eb3..307b02f4 100644 --- a/offchainreporting2plus/internal/config/ocr3_1config/public_config.go +++ b/offchainreporting2plus/internal/config/ocr3_1config/public_config.go @@ -157,7 +157,8 @@ type PublicConfig struct { // attempt to transmit (if in their view the first and second stage didn't // succeed). // - // sum(S) should equal n. + // It is recommended to have sum(S) >= n to ensure all oracles are + // included as transmitters. S []int // Identities (i.e. public keys) of the oracles participating in this // protocol instance. diff --git a/offchainreporting2plus/internal/config/ocr3_1config/shared_config.go b/offchainreporting2plus/internal/config/ocr3_1config/shared_config.go index 62644c24..efc30702 100644 --- a/offchainreporting2plus/internal/config/ocr3_1config/shared_config.go +++ b/offchainreporting2plus/internal/config/ocr3_1config/shared_config.go @@ -1,7 +1,6 @@ package ocr3_1config import ( - "bytes" "crypto/hmac" "crypto/rand" "crypto/sha256" @@ -48,7 +47,7 @@ func SharedConfigFromContractConfig[RI any]( skipInsaneForProductionChecks bool, change types.ContractConfig, offchainKeyring types.OffchainKeyring, - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], peerID string, transmitAccount types.Account, ) (SharedConfig, commontypes.OracleID, error) { @@ -59,38 +58,38 @@ func SharedConfigFromContractConfig[RI any]( oracleID := commontypes.OracleID(math.MaxUint8) { - onchainPublicKey := onchainKeyring.PublicKey() offchainPublicKey := offchainKeyring.OffchainPublicKey() var found bool for i, identity := range publicConfig.OracleIdentities { - if bytes.Equal(identity.OnchainPublicKey, onchainPublicKey) { - if identity.OffchainPublicKey != offchainPublicKey { - return SharedConfig{}, 0, errors.Errorf( - "OnchainPublicKey %x in publicConfig matches "+ - "mine, but OffchainPublicKey does not: %v (config) vs %v (mine)", - onchainPublicKey, identity.OffchainPublicKey, offchainPublicKey) - } - if identity.PeerID != peerID { - return SharedConfig{}, 0, errors.Errorf( - "OnchainPublicKey %x in publicConfig matches "+ - "mine, but PeerID does not: %v (config) vs %v (mine)", - onchainPublicKey, identity.PeerID, peerID) - } - if identity.TransmitAccount != transmitAccount { - return SharedConfig{}, 0, errors.Errorf( - "OnchainPublicKey %x in publicConfig matches "+ - "mine, but TransmitAccount does not: %v (config) vs %v (mine)", - onchainPublicKey, identity.TransmitAccount, transmitAccount) - } - oracleID = commontypes.OracleID(i) - found = true + if identity.OffchainPublicKey != offchainPublicKey { + continue } + if !onchainKeyring.Has(identity.OnchainPublicKey) { + return SharedConfig{}, 0, errors.Errorf( + "OffchainPublicKey %v in publicConfig matches "+ + "mine, but OnchainPublicKey %x does not match keyring %s", + offchainPublicKey, identity.OnchainPublicKey, onchainKeyring.DebugIdentifier()) + } + if identity.PeerID != peerID { + return SharedConfig{}, 0, errors.Errorf( + "OffchainPublicKey %v in publicConfig matches "+ + "mine, but PeerID does not: %v (config) vs %v (mine)", + offchainPublicKey, identity.PeerID, peerID) + } + if identity.TransmitAccount != transmitAccount { + return SharedConfig{}, 0, errors.Errorf( + "OffchainPublicKey %v in publicConfig matches "+ + "mine, but TransmitAccount does not: %v (config) vs %v (mine)", + offchainPublicKey, identity.TransmitAccount, transmitAccount) + } + oracleID = commontypes.OracleID(i) + found = true } if !found { return SharedConfig{}, 0, - fmt.Errorf("could not find my OnchainPublicKey %x in publicConfig", onchainPublicKey) + fmt.Errorf("could not find matching OffchainPublicKey in publicConfig for %v", offchainPublicKey) } } diff --git a/offchainreporting2plus/internal/config/ocr3config/public_config.go b/offchainreporting2plus/internal/config/ocr3config/public_config.go index 2785dd3f..15ddc0d1 100644 --- a/offchainreporting2plus/internal/config/ocr3config/public_config.go +++ b/offchainreporting2plus/internal/config/ocr3config/public_config.go @@ -64,7 +64,8 @@ type PublicConfig struct { // attempt to transmit (if in their view the first and second stage didn't // succeed). // - // sum(S) should equal n. + // It is recommended to have sum(S) >= n to ensure all oracles are + // included as transmitters. S []int // Identities (i.e. public keys) of the oracles participating in this // protocol instance. diff --git a/offchainreporting2plus/internal/config/ocr3config/shared_config.go b/offchainreporting2plus/internal/config/ocr3config/shared_config.go index 283424fb..b6194ea9 100644 --- a/offchainreporting2plus/internal/config/ocr3config/shared_config.go +++ b/offchainreporting2plus/internal/config/ocr3config/shared_config.go @@ -1,7 +1,6 @@ package ocr3config import ( - "bytes" "crypto/hmac" "crypto/rand" "crypto/sha256" @@ -48,7 +47,7 @@ func SharedConfigFromContractConfig[RI any]( skipResourceExhaustionChecks bool, change types.ContractConfig, offchainKeyring types.OffchainKeyring, - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], peerID string, transmitAccount types.Account, ) (SharedConfig, commontypes.OracleID, error) { @@ -59,38 +58,38 @@ func SharedConfigFromContractConfig[RI any]( oracleID := commontypes.OracleID(math.MaxUint8) { - onchainPublicKey := onchainKeyring.PublicKey() offchainPublicKey := offchainKeyring.OffchainPublicKey() var found bool for i, identity := range publicConfig.OracleIdentities { - if bytes.Equal(identity.OnchainPublicKey, onchainPublicKey) { - if identity.OffchainPublicKey != offchainPublicKey { - return SharedConfig{}, 0, errors.Errorf( - "OnchainPublicKey %x in publicConfig matches "+ - "mine, but OffchainPublicKey does not: %v (config) vs %v (mine)", - onchainPublicKey, identity.OffchainPublicKey, offchainPublicKey) - } - if identity.PeerID != peerID { - return SharedConfig{}, 0, errors.Errorf( - "OnchainPublicKey %x in publicConfig matches "+ - "mine, but PeerID does not: %v (config) vs %v (mine)", - onchainPublicKey, identity.PeerID, peerID) - } - if identity.TransmitAccount != transmitAccount { - return SharedConfig{}, 0, errors.Errorf( - "OnchainPublicKey %x in publicConfig matches "+ - "mine, but TransmitAccount does not: %v (config) vs %v (mine)", - onchainPublicKey, identity.TransmitAccount, transmitAccount) - } - oracleID = commontypes.OracleID(i) - found = true + if identity.OffchainPublicKey != offchainPublicKey { + continue } + if !onchainKeyring.Has(identity.OnchainPublicKey) { + return SharedConfig{}, 0, errors.Errorf( + "OffchainPublicKey %v in publicConfig matches "+ + "mine, but OnchainPublicKey %x does not match keyring %s", + offchainPublicKey, identity.OnchainPublicKey, onchainKeyring.DebugIdentifier()) + } + if identity.PeerID != peerID { + return SharedConfig{}, 0, errors.Errorf( + "OffchainPublicKey %v in publicConfig matches "+ + "mine, but PeerID does not: %v (config) vs %v (mine)", + offchainPublicKey, identity.PeerID, peerID) + } + if identity.TransmitAccount != transmitAccount { + return SharedConfig{}, 0, errors.Errorf( + "OffchainPublicKey %v in publicConfig matches "+ + "mine, but TransmitAccount does not: %v (config) vs %v (mine)", + offchainPublicKey, identity.TransmitAccount, transmitAccount) + } + oracleID = commontypes.OracleID(i) + found = true } if !found { return SharedConfig{}, 0, - fmt.Errorf("could not find my OnchainPublicKey %x in publicConfig", onchainPublicKey) + fmt.Errorf("could not find matching OffchainPublicKey in publicConfig for %v", offchainPublicKey) } } diff --git a/offchainreporting2plus/internal/managed/managed_mercury_oracle.go b/offchainreporting2plus/internal/managed/managed_mercury_oracle.go index 08e68e96..d24ba782 100644 --- a/offchainreporting2plus/internal/managed/managed_mercury_oracle.go +++ b/offchainreporting2plus/internal/managed/managed_mercury_oracle.go @@ -2,8 +2,8 @@ package managed import ( "context" - "errors" "fmt" + "github.com/smartcontractkit/libocr/offchainreporting2plus/internal/common" "github.com/prometheus/client_golang/prometheus" @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/internal/ocr3/protocol" "github.com/smartcontractkit/libocr/offchainreporting2plus/internal/ocr3/serialization" "github.com/smartcontractkit/libocr/offchainreporting2plus/internal/shim" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3shims" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/libocr/subprocesses" @@ -70,7 +71,7 @@ func RunManagedMercuryOracle( return fmt.Errorf("ManagedMercuryOracle: error getting FromAccount: %w", err), true } - ocr3OnchainKeyring := mercuryshim.NewMercuryOCR3OnchainKeyring(onchainKeyring) + ocr3OnchainKeyring := ocr3shims.OnchainKeyringAsOnchainKeyring2[mercuryshim.MercuryReportInfo](mercuryshim.NewMercuryOCR3OnchainKeyring(onchainKeyring)) sharedConfig, oid, err := ocr3config.SharedConfigFromContractConfig[mercuryshim.MercuryReportInfo]( skipResourceExhaustionChecks, @@ -139,7 +140,7 @@ func RunManagedMercuryOracle( metricsRegistererWrapper, ) - if err := validateMercuryPluginLimits(mercuryPluginInfo.Limits); err != nil { + if err := mercuryPluginInfo.Validate(); err != nil { logger.Error("ManagedMercuryOracle: invalid MercuryPluginInfo", commontypes.LogFields{ "error": err, "mercuryPluginInfo": mercuryPluginInfo, @@ -147,7 +148,8 @@ func RunManagedMercuryOracle( return fmt.Errorf("ManagedMercuryOracle: invalid MercuryPluginInfo"), false } - reportingPluginLimits := mercuryshim.ReportingPluginLimits(mercuryPluginInfo.Limits) + reportingPluginInfo := mercuryshim.ReportingPluginInfo(mercuryPluginInfo) + reportingPluginLimits := reportingPluginInfo.Limits lims, err := limits.OCR3Limits(sharedConfig.PublicConfig, reportingPluginLimits, ocr3OnchainKeyring.MaxSignatureLength()) if err != nil { @@ -230,6 +232,7 @@ func RunManagedMercuryOracle( offchainKeyring, ocr3OnchainKeyring, shim.LimitCheckOCR3ReportingPlugin[mercuryshim.MercuryReportInfo]{reportingPlugin, reportingPluginLimits}, + reportingPluginInfo, shim.NewOCR3TelemetrySender(chTelemetrySend, childLogger, localConfig.EnableTransmissionTelemetry), ) @@ -241,14 +244,3 @@ func RunManagedMercuryOracle( defaultRetryParams(), ) } - -func validateMercuryPluginLimits(limits ocr3types.MercuryPluginLimits) error { - var err error - if !(0 <= limits.MaxObservationLength && limits.MaxObservationLength <= ocr3types.MaxMaxMercuryObservationLength) { - err = errors.Join(err, fmt.Errorf("MaxObservationLength (%v) out of range. Should be between 0 and %v", limits.MaxObservationLength, ocr3types.MaxMaxMercuryObservationLength)) - } - if !(0 <= limits.MaxReportLength && limits.MaxReportLength <= ocr3types.MaxMaxMercuryReportLength) { - err = errors.Join(err, fmt.Errorf("MaxReportLength (%v) out of range. Should be between 0 and %v", limits.MaxReportLength, ocr3types.MaxMaxMercuryReportLength)) - } - return err -} diff --git a/offchainreporting2plus/internal/managed/managed_ocr2_oracle.go b/offchainreporting2plus/internal/managed/managed_ocr2_oracle.go index 7aa41758..589e681f 100644 --- a/offchainreporting2plus/internal/managed/managed_ocr2_oracle.go +++ b/offchainreporting2plus/internal/managed/managed_ocr2_oracle.go @@ -135,6 +135,7 @@ func RunManagedOCR2Oracle( sharedConfig.MaxDurationReport, sharedConfig.MaxDurationShouldAcceptFinalizedReport, sharedConfig.MaxDurationShouldTransmitAcceptedReport, + sharedConfig.DurationAllTransmissionStages(), }) ins.Stop() diff --git a/offchainreporting2plus/internal/managed/managed_ocr3_1_oracle.go b/offchainreporting2plus/internal/managed/managed_ocr3_1_oracle.go index 28fb93f4..a4cc93ba 100644 --- a/offchainreporting2plus/internal/managed/managed_ocr3_1_oracle.go +++ b/offchainreporting2plus/internal/managed/managed_ocr3_1_oracle.go @@ -43,7 +43,7 @@ func RunManagedOCR3_1Oracle[RI any]( messageNetEndpointFactory types.BinaryNetworkEndpoint2Factory, offchainConfigDigester types.OffchainConfigDigester, offchainKeyring types.OffchainKeyring, - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPluginFactory ocr3_1types.ReportingPluginFactory[RI], ) { subs := subprocesses.Subprocesses{} @@ -151,7 +151,7 @@ func RunManagedOCR3_1Oracle[RI any]( reportingPluginInfo = rpi } - if err := validateOCR3_1ReportingPluginLimits(reportingPluginInfo.Limits); err != nil { + if err := reportingPluginInfo.Validate(); err != nil { logger.Error("ManagedOCR3_1Oracle: invalid ReportingPluginInfo", commontypes.LogFields{ "error": err, "reportingPluginInfo": reportingPluginInfo, @@ -275,7 +275,7 @@ func RunManagedOCR3_1Oracle[RI any]( &shim.SerializingOCR3_1Database{database}, oid, semanticOCR3_1KeyValueDatabase, - reportingPluginInfo.Limits, + reportingPluginInfo, localConfig, childLogger, registerer, @@ -283,7 +283,7 @@ func RunManagedOCR3_1Oracle[RI any]( offchainKeyring, onchainKeyring, shim.LimitCheckOCR3_1ReportingPlugin[RI]{reportingPlugin, reportingPluginInfo.Limits}, - shim.NewOCR3_1TelemetrySender(chTelemetrySend, childLogger), + shim.NewOCR3_1TelemetrySender(chTelemetrySend, childLogger, localConfig.EnableTransmissionTelemetry), ) return nil, false @@ -295,36 +295,6 @@ func RunManagedOCR3_1Oracle[RI any]( ) } -func validateOCR3_1ReportingPluginLimits(limits ocr3_1types.ReportingPluginLimits) error { - var err error - if !(0 <= limits.MaxQueryBytes && limits.MaxQueryBytes <= ocr3_1types.MaxMaxQueryBytes) { - err = errors.Join(err, fmt.Errorf("MaxQueryBytes (%v) out of range. Should be between 0 and %v", limits.MaxQueryBytes, ocr3_1types.MaxMaxQueryBytes)) - } - if !(0 <= limits.MaxObservationBytes && limits.MaxObservationBytes <= ocr3_1types.MaxMaxObservationBytes) { - err = errors.Join(err, fmt.Errorf("MaxObservationBytes (%v) out of range. Should be between 0 and %v", limits.MaxObservationBytes, ocr3_1types.MaxMaxObservationBytes)) - } - if !(0 <= limits.MaxReportBytes && limits.MaxReportBytes <= ocr3_1types.MaxMaxReportBytes) { - err = errors.Join(err, fmt.Errorf("MaxReportBytes (%v) out of range. Should be between 0 and %v", limits.MaxReportBytes, ocr3_1types.MaxMaxReportBytes)) - } - if !(0 <= limits.MaxReportsPlusPrecursorBytes && limits.MaxReportsPlusPrecursorBytes <= ocr3_1types.MaxMaxReportsPlusPrecursorBytes) { - err = errors.Join(err, fmt.Errorf("MaxReportsPlusPrecursorBytes (%v) out of range. Should be between 0 and %v", limits.MaxReportsPlusPrecursorBytes, ocr3_1types.MaxMaxReportsPlusPrecursorBytes)) - } - if !(0 <= limits.MaxReportCount && limits.MaxReportCount <= ocr3_1types.MaxMaxReportCount) { - err = errors.Join(err, fmt.Errorf("MaxReportCount (%v) out of range. Should be between 0 and %v", limits.MaxReportCount, ocr3_1types.MaxMaxReportCount)) - } - - if !(0 <= limits.MaxKeyValueModifiedKeys && limits.MaxKeyValueModifiedKeys <= ocr3_1types.MaxMaxKeyValueModifiedKeys) { - err = errors.Join(err, fmt.Errorf("MaxKeyValueModifiedKeys (%v) out of range. Should be between 0 and %v", limits.MaxKeyValueModifiedKeys, ocr3_1types.MaxMaxKeyValueModifiedKeys)) - } - if !(0 <= limits.MaxKeyValueModifiedKeysPlusValuesBytes && limits.MaxKeyValueModifiedKeysPlusValuesBytes <= ocr3_1types.MaxMaxKeyValueModifiedKeysPlusValuesBytes) { - err = errors.Join(err, fmt.Errorf("MaxKeyValueModifiedKeysPlusValuesBytes (%v) out of range. Should be between 0 and %v", limits.MaxKeyValueModifiedKeysPlusValuesBytes, ocr3_1types.MaxMaxKeyValueModifiedKeysPlusValuesBytes)) - } - if !(0 <= limits.MaxBlobPayloadBytes && limits.MaxBlobPayloadBytes <= ocr3_1types.MaxMaxBlobPayloadBytes) { - err = errors.Join(err, fmt.Errorf("MaxBlobPayloadBytes (%v) out of range. Should be between 0 and %v", limits.MaxBlobPayloadBytes, ocr3_1types.MaxMaxBlobPayloadBytes)) - } - return err -} - func tryCopyFromPrevInstance( ctx context.Context, publicConfig ocr3_1config.PublicConfig, diff --git a/offchainreporting2plus/internal/managed/managed_ocr3_oracle.go b/offchainreporting2plus/internal/managed/managed_ocr3_oracle.go index 2f0040e6..1d1d3aa9 100644 --- a/offchainreporting2plus/internal/managed/managed_ocr3_oracle.go +++ b/offchainreporting2plus/internal/managed/managed_ocr3_oracle.go @@ -2,8 +2,8 @@ package managed import ( "context" - "errors" "fmt" + "github.com/smartcontractkit/libocr/offchainreporting2plus/internal/common" "github.com/prometheus/client_golang/prometheus" @@ -39,7 +39,7 @@ func RunManagedOCR3Oracle[RI any]( netEndpointFactory types.BinaryNetworkEndpointFactory, offchainConfigDigester types.OffchainConfigDigester, offchainKeyring types.OffchainKeyring, - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPluginFactory ocr3types.ReportingPluginFactory[RI], ) { subs := subprocesses.Subprocesses{} @@ -139,12 +139,12 @@ func RunManagedOCR3Oracle[RI any]( "ManagedOCR3Oracle: error during reportingPlugin.Close()", ) - if err := validateOCR3ReportingPluginLimits(reportingPluginInfo.Limits); err != nil { + if err := reportingPluginInfo.Validate(); err != nil { logger.Error("ManagedOCR3Oracle: invalid ReportingPluginInfo", commontypes.LogFields{ "error": err, "reportingPluginInfo": reportingPluginInfo, }) - return fmt.Errorf("ManagedOCR3Oracle: invalid MercuryPluginInfo"), false + return fmt.Errorf("ManagedOCR3Oracle: invalid ReportingPluginInfo"), false } maxSigLen := onchainKeyring.MaxSignatureLength() @@ -209,6 +209,7 @@ func RunManagedOCR3Oracle[RI any]( offchainKeyring, onchainKeyring, shim.LimitCheckOCR3ReportingPlugin[RI]{reportingPlugin, reportingPluginInfo.Limits}, + reportingPluginInfo, shim.NewOCR3TelemetrySender(chTelemetrySend, childLogger, localConfig.EnableTransmissionTelemetry), ) @@ -220,23 +221,3 @@ func RunManagedOCR3Oracle[RI any]( defaultRetryParams(), ) } - -func validateOCR3ReportingPluginLimits(limits ocr3types.ReportingPluginLimits) error { - var err error - if !(0 <= limits.MaxQueryLength && limits.MaxQueryLength <= ocr3types.MaxMaxQueryLength) { - err = errors.Join(err, fmt.Errorf("MaxQueryLength (%v) out of range. Should be between 0 and %v", limits.MaxQueryLength, ocr3types.MaxMaxQueryLength)) - } - if !(0 <= limits.MaxObservationLength && limits.MaxObservationLength <= ocr3types.MaxMaxObservationLength) { - err = errors.Join(err, fmt.Errorf("MaxObservationLength (%v) out of range. Should be between 0 and %v", limits.MaxObservationLength, ocr3types.MaxMaxObservationLength)) - } - if !(0 <= limits.MaxOutcomeLength && limits.MaxOutcomeLength <= ocr3types.MaxMaxOutcomeLength) { - err = errors.Join(err, fmt.Errorf("MaxOutcomeLength (%v) out of range. Should be between 0 and %v", limits.MaxOutcomeLength, ocr3types.MaxMaxOutcomeLength)) - } - if !(0 <= limits.MaxReportLength && limits.MaxReportLength <= ocr3types.MaxMaxReportLength) { - err = errors.Join(err, fmt.Errorf("MaxReportLength (%v) out of range. Should be between 0 and %v", limits.MaxReportLength, ocr3types.MaxMaxReportLength)) - } - if !(0 <= limits.MaxReportCount && limits.MaxReportCount <= ocr3types.MaxMaxReportCount) { - err = errors.Join(err, fmt.Errorf("MaxReportCount (%v) out of range. Should be between 0 and %v", limits.MaxReportCount, ocr3types.MaxMaxReportCount)) - } - return err -} diff --git a/offchainreporting2plus/internal/mercuryshim/mercuryshims.go b/offchainreporting2plus/internal/mercuryshim/mercuryshims.go index de08dc98..478c064a 100644 --- a/offchainreporting2plus/internal/mercuryshim/mercuryshims.go +++ b/offchainreporting2plus/internal/mercuryshim/mercuryshims.go @@ -109,13 +109,16 @@ func ocr3MaxOutcomeLength(maxReportLength int) int { return outcomeSerializationOverhead + maxReportLength + maxReportLength/2 } -func ReportingPluginLimits(mercuryPluginLimits ocr3types.MercuryPluginLimits) ocr3types.ReportingPluginLimits { - return ocr3types.ReportingPluginLimits{ - 0, - mercuryPluginLimits.MaxObservationLength, - ocr3MaxOutcomeLength(mercuryPluginLimits.MaxReportLength), - mercuryPluginLimits.MaxReportLength, - 1, +func ReportingPluginInfo(mercuryPluginInfo ocr3types.MercuryPluginInfo) ocr3types.ReportingPluginInfo { + return ocr3types.ReportingPluginInfo{ + mercuryPluginInfo.Name, + ocr3types.ReportingPluginLimits{ + 0, + mercuryPluginInfo.Limits.MaxObservationLength, + ocr3MaxOutcomeLength(mercuryPluginInfo.Limits.MaxReportLength), + mercuryPluginInfo.Limits.MaxReportLength, + 1, + }, } } diff --git a/offchainreporting2plus/internal/ocr3/protocol/oracle.go b/offchainreporting2plus/internal/ocr3/protocol/oracle.go index 83fe68b0..e6cc7f85 100644 --- a/offchainreporting2plus/internal/ocr3/protocol/oracle.go +++ b/offchainreporting2plus/internal/ocr3/protocol/oracle.go @@ -31,8 +31,9 @@ func RunOracle[RI any]( metricsRegisterer prometheus.Registerer, netEndpoint NetworkEndpoint[RI], offchainKeyring types.OffchainKeyring, - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPlugin ocr3types.ReportingPlugin[RI], + reportingPluginInfo ocr3types.ReportingPluginInfo, telemetrySender TelemetrySender, ) { o := oracleState[RI]{ @@ -49,6 +50,7 @@ func RunOracle[RI any]( offchainKeyring: offchainKeyring, onchainKeyring: onchainKeyring, reportingPlugin: reportingPlugin, + reportingPluginInfo: reportingPluginInfo, telemetrySender: telemetrySender, } o.run() @@ -66,8 +68,9 @@ type oracleState[RI any] struct { metricsRegisterer prometheus.Registerer netEndpoint NetworkEndpoint[RI] offchainKeyring types.OffchainKeyring - onchainKeyring ocr3types.OnchainKeyring[RI] + onchainKeyring ocr3types.OnchainKeyring2[RI] reportingPlugin ocr3types.ReportingPlugin[RI] + reportingPluginInfo ocr3types.ReportingPluginInfo telemetrySender TelemetrySender chNetToPacemaker chan<- MessageToPacemakerWithSender[RI] @@ -130,8 +133,9 @@ type oracleState[RI any] struct { // This enables us to wait for their completion before exiting. func (o *oracleState[RI]) run() { o.logger.Info("Oracle: running", commontypes.LogFields{ - "localConfig": fmt.Sprintf("%+v", o.localConfig), - "publicConfig": fmt.Sprintf("%+v", o.config.PublicConfig), + "localConfig": fmt.Sprintf("%+v", o.localConfig), + "publicConfig": fmt.Sprintf("%+v", o.config.PublicConfig), + "reportingPluginInfo": fmt.Sprintf("%+v", o.reportingPluginInfo), }) chNetToPacemaker := make(chan MessageToPacemakerWithSender[RI]) diff --git a/offchainreporting2plus/internal/ocr3/protocol/pacemaker.go b/offchainreporting2plus/internal/ocr3/protocol/pacemaker.go index 85a3b311..bdbc1e85 100644 --- a/offchainreporting2plus/internal/ocr3/protocol/pacemaker.go +++ b/offchainreporting2plus/internal/ocr3/protocol/pacemaker.go @@ -311,7 +311,7 @@ func (pace *pacemakerState[RI]) messageNewEpochWish(msg MessageNewEpochWish[RI], } pace.metrics.epoch.Set(float64(pace.e)) pace.metrics.leader.Set(float64(pace.l)) - pace.telemetrySender.EpochStarted(pace.config.ConfigDigest, uint32(pace.e), pace.l) + pace.telemetrySender.EpochStarted(pace.config.ConfigDigest, pace.e, pace.l) pace.tProgress = time.After(pace.config.DeltaProgress) // restart timer T_{progress} pace.notifyOutcomeGenerationOfNewEpoch = true // invoke event newEpochStart(e, l) diff --git a/offchainreporting2plus/internal/ocr3/protocol/report_attestation.go b/offchainreporting2plus/internal/ocr3/protocol/report_attestation.go index b15a53da..3c9b2bf6 100644 --- a/offchainreporting2plus/internal/ocr3/protocol/report_attestation.go +++ b/offchainreporting2plus/internal/ocr3/protocol/report_attestation.go @@ -30,7 +30,7 @@ func RunReportAttestation[RI any]( contractTransmitter ocr3types.ContractTransmitter[RI], logger loghelper.LoggerWithContext, netSender NetworkSender[RI], - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPlugin ocr3types.ReportingPlugin[RI], ) { sched := scheduler.NewScheduler[EventMissingOutcome[RI]]() @@ -60,7 +60,7 @@ type reportAttestationState[RI any] struct { contractTransmitter ocr3types.ContractTransmitter[RI] logger loghelper.LoggerWithContext netSender NetworkSender[RI] - onchainKeyring ocr3types.OnchainKeyring[RI] + onchainKeyring ocr3types.OnchainKeyring2[RI] reportingPlugin ocr3types.ReportingPlugin[RI] scheduler *scheduler.Scheduler[EventMissingOutcome[RI]] @@ -670,7 +670,7 @@ func newReportAttestationState[RI any]( contractTransmitter ocr3types.ContractTransmitter[RI], logger loghelper.LoggerWithContext, netSender NetworkSender[RI], - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPlugin ocr3types.ReportingPlugin[RI], sched *scheduler.Scheduler[EventMissingOutcome[RI]], ) *reportAttestationState[RI] { diff --git a/offchainreporting2plus/internal/ocr3/protocol/telemetry.go b/offchainreporting2plus/internal/ocr3/protocol/telemetry.go index 5cb46c9f..8c7154fd 100644 --- a/offchainreporting2plus/internal/ocr3/protocol/telemetry.go +++ b/offchainreporting2plus/internal/ocr3/protocol/telemetry.go @@ -10,7 +10,7 @@ import ( type TelemetrySender interface { EpochStarted( configDigest types.ConfigDigest, - epoch uint32, + epoch uint64, leader commontypes.OracleID, ) diff --git a/offchainreporting2plus/internal/ocr3/serialization/offchainreporting3_telemetry.pb.go b/offchainreporting2plus/internal/ocr3/serialization/offchainreporting3_telemetry.pb.go index e983bf8f..75aa9bb5 100644 --- a/offchainreporting2plus/internal/ocr3/serialization/offchainreporting3_telemetry.pb.go +++ b/offchainreporting2plus/internal/ocr3/serialization/offchainreporting3_telemetry.pb.go @@ -629,7 +629,6 @@ type TelemetryTransmissionScheduleComputed struct { unknownFields protoimpl.UnknownFields ConfigDigest []byte `protobuf:"bytes,1,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"` - Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` SeqNr uint64 `protobuf:"varint,3,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"` Index uint64 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` UnixTimeNanoseconds uint64 `protobuf:"varint,5,opt,name=unix_time_nanoseconds,json=unixTimeNanoseconds,proto3" json:"unix_time_nanoseconds,omitempty"` @@ -677,13 +676,6 @@ func (x *TelemetryTransmissionScheduleComputed) GetConfigDigest() []byte { return nil } -func (x *TelemetryTransmissionScheduleComputed) GetEpoch() uint64 { - if x != nil { - return x.Epoch - } - return 0 -} - func (x *TelemetryTransmissionScheduleComputed) GetSeqNr() uint64 { if x != nil { return x.SeqNr @@ -732,7 +724,6 @@ type TelemetryTransmissionShouldAcceptAttestedReportComputed struct { unknownFields protoimpl.UnknownFields ConfigDigest []byte `protobuf:"bytes,1,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"` - Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` SeqNr uint64 `protobuf:"varint,3,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"` Index uint64 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` Result bool `protobuf:"varint,5,opt,name=result,proto3" json:"result,omitempty"` @@ -778,13 +769,6 @@ func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetConfigDiges return nil } -func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetEpoch() uint64 { - if x != nil { - return x.Epoch - } - return 0 -} - func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetSeqNr() uint64 { if x != nil { return x.SeqNr @@ -819,7 +803,6 @@ type TelemetryTransmissionShouldTransmitAcceptedReportComputed struct { unknownFields protoimpl.UnknownFields ConfigDigest []byte `protobuf:"bytes,1,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"` - Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` SeqNr uint64 `protobuf:"varint,3,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"` Index uint64 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` Result bool `protobuf:"varint,5,opt,name=result,proto3" json:"result,omitempty"` @@ -865,13 +848,6 @@ func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetConfigDig return nil } -func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetEpoch() uint64 { - if x != nil { - return x.Epoch - } - return 0 -} - func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetSeqNr() uint64 { if x != nil { return x.SeqNr @@ -1104,64 +1080,61 @@ var file_offchainreporting3_telemetry_proto_rawDesc = []byte{ 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x22, - 0xf7, 0x03, 0x0a, 0x25, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, + 0xe7, 0x03, 0x0a, 0x25, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x12, 0x32, 0x0a, 0x15, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, - 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x13, 0x75, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0xac, 0x01, 0x0a, 0x23, 0x73, 0x63, 0x68, 0x65, 0x64, - 0x75, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x07, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x5e, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x2e, - 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6e, - 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x50, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, - 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x50, 0x65, - 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x1a, 0x52, 0x0a, 0x24, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, - 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x73, 0x50, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc9, 0x01, 0x0a, 0x37, 0x54, 0x65, + 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x15, + 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x32, 0x0a, 0x15, 0x75, + 0x6e, 0x69, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x78, + 0x54, 0x69, 0x6d, 0x65, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, + 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x12, 0xac, 0x01, 0x0a, 0x23, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x64, 0x65, + 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, + 0x70, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x5e, + 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, + 0x6e, 0x67, 0x33, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, + 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x73, 0x50, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1f, + 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6e, + 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x50, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x1a, + 0x52, 0x0a, 0x24, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, + 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x50, 0x65, 0x72, 0x4e, 0x6f, + 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xb9, 0x01, 0x0a, 0x37, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x22, 0xcb, 0x01, 0x0a, 0x39, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, + 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, + 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x4a, + 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xbb, 0x01, 0x0a, 0x39, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x15, - 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x02, 0x6f, 0x6b, 0x22, 0x6a, 0x0a, 0x15, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, + 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, + 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, + 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x6f, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x4a, 0x04, 0x08, + 0x02, 0x10, 0x03, 0x22, 0x6a, 0x0a, 0x15, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, diff --git a/offchainreporting2plus/internal/ocr3_1/protocol/oracle.go b/offchainreporting2plus/internal/ocr3_1/protocol/oracle.go index 72da6327..2020d413 100644 --- a/offchainreporting2plus/internal/ocr3_1/protocol/oracle.go +++ b/offchainreporting2plus/internal/ocr3_1/protocol/oracle.go @@ -30,13 +30,13 @@ func RunOracle[RI any]( database Database, id commontypes.OracleID, kvDb KeyValueDatabase, - limits ocr3_1types.ReportingPluginLimits, + reportingPluginInfo ocr3_1types.ReportingPluginInfo1, localConfig types.LocalConfig, logger loghelper.LoggerWithContext, metricsRegisterer prometheus.Registerer, netEndpoint NetworkEndpoint[RI], offchainKeyring types.OffchainKeyring, - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPlugin ocr3_1types.ReportingPlugin[RI], telemetrySender TelemetrySender, ) { @@ -49,7 +49,7 @@ func RunOracle[RI any]( database: database, id: id, kvDb: kvDb, - limits: limits, + reportingPluginInfo: reportingPluginInfo, localConfig: localConfig, logger: logger, metricsRegisterer: metricsRegisterer, @@ -71,13 +71,13 @@ type oracleState[RI any] struct { database Database id commontypes.OracleID kvDb KeyValueDatabase - limits ocr3_1types.ReportingPluginLimits + reportingPluginInfo ocr3_1types.ReportingPluginInfo1 localConfig types.LocalConfig logger loghelper.LoggerWithContext metricsRegisterer prometheus.Registerer netEndpoint NetworkEndpoint[RI] offchainKeyring types.OffchainKeyring - onchainKeyring ocr3types.OnchainKeyring[RI] + onchainKeyring ocr3types.OnchainKeyring2[RI] reportingPlugin ocr3_1types.ReportingPlugin[RI] telemetrySender TelemetrySender @@ -146,8 +146,9 @@ type oracleState[RI any] struct { // This enables us to wait for their completion before exiting. func (o *oracleState[RI]) run() { o.logger.Info("Oracle: running", commontypes.LogFields{ - "localConfig": fmt.Sprintf("%+v", o.localConfig), - "publicConfig": fmt.Sprintf("%+v", o.config.PublicConfig), + "localConfig": fmt.Sprintf("%+v", o.localConfig), + "publicConfig": fmt.Sprintf("%+v", o.config.PublicConfig), + "reportingPluginInfo": fmt.Sprintf("%+v", o.reportingPluginInfo), }) chNetToPacemaker := make(chan MessageToPacemakerWithSender[RI]) @@ -297,6 +298,7 @@ func (o *oracleState[RI]) run() { o.localConfig, o.logger, o.reportingPlugin, + o.telemetrySender, ) }) @@ -313,7 +315,7 @@ func (o *oracleState[RI]) run() { o.config, o.kvDb, o.id, - o.limits, + o.reportingPluginInfo.Limits, o.localConfig, o.logger, o.metricsRegisterer, diff --git a/offchainreporting2plus/internal/ocr3_1/protocol/pacemaker.go b/offchainreporting2plus/internal/ocr3_1/protocol/pacemaker.go index f80ad8a9..57eadf0f 100644 --- a/offchainreporting2plus/internal/ocr3_1/protocol/pacemaker.go +++ b/offchainreporting2plus/internal/ocr3_1/protocol/pacemaker.go @@ -309,6 +309,7 @@ func (pace *pacemakerState[RI]) messageNewEpochWish(msg MessageNewEpochWish[RI], } pace.metrics.epoch.Set(float64(pace.e)) pace.metrics.leader.Set(float64(pace.l)) + pace.telemetrySender.EpochStarted(pace.config.ConfigDigest, pace.e, pace.l) pace.tProgress = time.After(pace.config.DeltaProgress) // restart timer T_{progress} pace.notifyOutcomeGenerationOfNewEpoch = true // invoke event newEpochStart(e, l) diff --git a/offchainreporting2plus/internal/ocr3_1/protocol/report_attestation.go b/offchainreporting2plus/internal/ocr3_1/protocol/report_attestation.go index 6f35c4c4..de6ff31b 100644 --- a/offchainreporting2plus/internal/ocr3_1/protocol/report_attestation.go +++ b/offchainreporting2plus/internal/ocr3_1/protocol/report_attestation.go @@ -34,7 +34,7 @@ func RunReportAttestation[RI any]( kvDb KeyValueDatabase, logger loghelper.LoggerWithContext, netSender NetworkSender[RI], - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPlugin ocr3_1types.ReportingPlugin[RI], ) { sched := scheduler.NewScheduler[EventMissingReportsPlusPrecursor[RI]]() @@ -70,7 +70,7 @@ type reportAttestationState[RI any] struct { kvDb KeyValueDatabase logger loghelper.LoggerWithContext netSender NetworkSender[RI] - onchainKeyring ocr3types.OnchainKeyring[RI] + onchainKeyring ocr3types.OnchainKeyring2[RI] reportingPlugin ocr3_1types.ReportingPlugin[RI] scheduler *scheduler.Scheduler[EventMissingReportsPlusPrecursor[RI]] @@ -885,7 +885,7 @@ func newReportAttestationState[RI any]( kvDb KeyValueDatabase, logger loghelper.LoggerWithContext, netSender NetworkSender[RI], - onchainKeyring ocr3types.OnchainKeyring[RI], + onchainKeyring ocr3types.OnchainKeyring2[RI], reportingPlugin ocr3_1types.ReportingPlugin[RI], sched *scheduler.Scheduler[EventMissingReportsPlusPrecursor[RI]], ) *reportAttestationState[RI] { diff --git a/offchainreporting2plus/internal/ocr3_1/protocol/telemetry.go b/offchainreporting2plus/internal/ocr3_1/protocol/telemetry.go index d38f6a4e..8c7154fd 100644 --- a/offchainreporting2plus/internal/ocr3_1/protocol/telemetry.go +++ b/offchainreporting2plus/internal/ocr3_1/protocol/telemetry.go @@ -1,11 +1,19 @@ package protocol import ( + "time" + "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ) type TelemetrySender interface { + EpochStarted( + configDigest types.ConfigDigest, + epoch uint64, + leader commontypes.OracleID, + ) + RoundStarted( configDigest types.ConfigDigest, epoch uint64, @@ -13,4 +21,30 @@ type TelemetrySender interface { round uint64, leader commontypes.OracleID, ) + + TransmissionScheduleComputed( + configDigest types.ConfigDigest, + seqNr uint64, + index int, + now time.Time, + isOverride bool, + schedule map[commontypes.OracleID]time.Duration, + ok bool, + ) + + TransmissionShouldAcceptAttestedReportComputed( + configDigest types.ConfigDigest, + seqNr uint64, + index int, + result bool, + ok bool, + ) + + TransmissionShouldTransmitAcceptedReportComputed( + configDigest types.ConfigDigest, + seqNr uint64, + index int, + result bool, + ok bool, + ) } diff --git a/offchainreporting2plus/internal/ocr3_1/protocol/transmission.go b/offchainreporting2plus/internal/ocr3_1/protocol/transmission.go index 068e3bd5..efe81461 100644 --- a/offchainreporting2plus/internal/ocr3_1/protocol/transmission.go +++ b/offchainreporting2plus/internal/ocr3_1/protocol/transmission.go @@ -5,7 +5,6 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/binary" - "slices" "time" "github.com/smartcontractkit/libocr/offchainreporting2plus/internal/common" @@ -33,6 +32,7 @@ func RunTransmission[RI any]( localConfig types.LocalConfig, logger loghelper.LoggerWithContext, reportingPlugin ocr3_1types.ReportingPlugin[RI], + telemetrySender TelemetrySender, ) { sched := scheduler.NewScheduler[EventAttestedReport[RI]]() defer sched.Close() @@ -48,6 +48,7 @@ func RunTransmission[RI any]( localConfig, logger.MakeUpdated(commontypes.LogFields{"proto": "transmission"}), reportingPlugin, + telemetrySender, sched, } @@ -65,6 +66,7 @@ type transmissionState[RI any] struct { localConfig types.LocalConfig logger loghelper.LoggerWithContext reportingPlugin ocr3_1types.ReportingPlugin[RI] + telemetrySender TelemetrySender scheduler *scheduler.Scheduler[EventAttestedReport[RI]] } @@ -104,18 +106,27 @@ func (t *transmissionState[RI]) eventAttestedReport(ev EventAttestedReport[RI]) } func (t *transmissionState[RI]) backgroundEventAttestedReport(ctx context.Context, start time.Time, ev EventAttestedReport[RI]) { - var delay time.Duration - { - delayMaybe := t.transmitDelay(ev.SeqNr, ev.Index, ev.TransmissionScheduleOverride) - if delayMaybe == nil { - t.logger.Debug("dropping EventAttestedReport because we're not included in transmission schedule", commontypes.LogFields{ - "seqNr": ev.SeqNr, - "index": ev.Index, - "transmissionScheduleOverride": ev.TransmissionScheduleOverride != nil, - }) - return - } - delay = *delayMaybe + delays, ok := t.transmitDelays(ev.SeqNr, ev.Index, ev.TransmissionScheduleOverride) + t.telemetrySender.TransmissionScheduleComputed( + t.config.ConfigDigest, + ev.SeqNr, + ev.Index, + start, + ev.TransmissionScheduleOverride != nil, + delays, + ok, + ) + if !ok { + return + } + delay, ok := delays[t.id] + if !ok { + t.logger.Debug("dropping EventAttestedReport because we're not included in transmission schedule", commontypes.LogFields{ + "seqNr": ev.SeqNr, + "index": ev.Index, + "transmissionScheduleOverride": ev.TransmissionScheduleOverride != nil, + }) + return } shouldAccept, ok := common.CallPlugin[bool]( @@ -135,6 +146,7 @@ func (t *transmissionState[RI]) backgroundEventAttestedReport(ctx context.Contex ) }, ) + t.telemetrySender.TransmissionShouldAcceptAttestedReportComputed(t.config.ConfigDigest, ev.SeqNr, ev.Index, shouldAccept, ok) if !ok { return } @@ -180,6 +192,7 @@ func (t *transmissionState[RI]) backgroundScheduled(ctx context.Context, ev Even ) }, ) + t.telemetrySender.TransmissionShouldTransmitAcceptedReportComputed(t.config.ConfigDigest, ev.SeqNr, ev.Index, shouldTransmit, ok) if !ok { return } @@ -249,42 +262,85 @@ func (t *transmissionState[RI]) transmitPermutationKey(seqNr uint64, index int) return key } -func (t *transmissionState[RI]) transmitDelayFromOverride(seqNr uint64, index int, transmissionScheduleOverride ocr3types.TransmissionSchedule) *time.Duration { +func (t *transmissionState[RI]) transmitDelaysFromOverride(seqNr uint64, index int, transmissionScheduleOverride ocr3types.TransmissionSchedule) (delays map[commontypes.OracleID]time.Duration, ok bool) { if len(transmissionScheduleOverride.TransmissionDelays) != len(transmissionScheduleOverride.Transmitters) { - t.logger.Error("invalid TransmissionScheduleOverride, cannot compute delay", commontypes.LogFields{ + t.logger.Error("invalid TransmissionScheduleOverride, cannot compute delay, lengths do not match", commontypes.LogFields{ "seqNr": seqNr, "index": index, "transmissionScheduleOverride": transmissionScheduleOverride, }) - return nil + return nil, false + } + + for _, oid := range transmissionScheduleOverride.Transmitters { + if !(0 <= int(oid) && int(oid) < t.config.N()) { + t.logger.Error("invalid TransmissionScheduleOverride, cannot compute delay, oracle id out of bounds", commontypes.LogFields{ + "seqNr": seqNr, + "index": index, + "transmissionScheduleOverride": transmissionScheduleOverride, + }) + return nil, false + } } - oracleIndex := slices.Index(transmissionScheduleOverride.Transmitters, t.id) - if oracleIndex < 0 { - return nil + // Permutation from index of oracle in transmissionScheduleOverride.Transmitters to transmission order index. + pi := permutation.Permutation(len(transmissionScheduleOverride.Transmitters), t.transmitPermutationKey(seqNr, index)) + + result := make(map[commontypes.OracleID]time.Duration, len(transmissionScheduleOverride.Transmitters)) + + for transmitterIndex, oid := range transmissionScheduleOverride.Transmitters { + if _, ok := result[oid]; ok { + t.logger.Error("invalid TransmissionScheduleOverride, cannot compute delay, duplicate oracle id", commontypes.LogFields{ + "seqNr": seqNr, + "index": index, + "transmissionScheduleOverride": transmissionScheduleOverride, + }) + return nil, false + } + result[oid] = transmissionScheduleOverride.TransmissionDelays[pi[transmitterIndex]] } - pi := permutation.Permutation(len(transmissionScheduleOverride.TransmissionDelays), t.transmitPermutationKey(seqNr, index)) - delay := transmissionScheduleOverride.TransmissionDelays[pi[oracleIndex]] - return &delay + + return result, true } -func (t *transmissionState[RI]) transmitDelayDefault(seqNr uint64, index int) *time.Duration { - pi := permutation.Permutation(t.config.N(), t.transmitPermutationKey(seqNr, index)) - sum := 0 - for i, s := range t.config.S { - sum += s - if pi[t.id] < sum { - result := time.Duration(i) * t.config.DeltaStage - return &result +func (t *transmissionState[RI]) transmitDelaysDefault(seqNr uint64, index int) map[commontypes.OracleID]time.Duration { + // Permutation from transmission order index to oracle id + piInv := make([]int, t.config.N()) + { + // Permutation from oracle id to transmission order index. The + // permutations are structured in this "inverted" way for historical + // compatibility + pi := permutation.Permutation(t.config.N(), t.transmitPermutationKey(seqNr, index)) + for i := range pi { + piInv[pi[i]] = i + } + } + + result := make(map[commontypes.OracleID]time.Duration, t.config.N()) + + accumulatedStageSize := 0 + for stageIdx, stageSize := range t.config.S { + // i is the index of the oracle sorted by transmission order + for i := accumulatedStageSize; i < accumulatedStageSize+stageSize; i++ { + if i >= len(piInv) { + // Index is larger than index of the last oracle. This happens + // when sum(S) > N. + break + } + oracleId := commontypes.OracleID(piInv[i]) + result[oracleId] = time.Duration(stageIdx) * t.config.DeltaStage } + + accumulatedStageSize += stageSize } - return nil + + return result } -func (t *transmissionState[RI]) transmitDelay(seqNr uint64, index int, transmissionScheduleOverride *ocr3types.TransmissionSchedule) *time.Duration { +func (t *transmissionState[RI]) transmitDelays(seqNr uint64, index int, transmissionScheduleOverride *ocr3types.TransmissionSchedule) (delays map[commontypes.OracleID]time.Duration, ok bool) { if transmissionScheduleOverride != nil { - return t.transmitDelayFromOverride(seqNr, index, *transmissionScheduleOverride) + return t.transmitDelaysFromOverride(seqNr, index, *transmissionScheduleOverride) } else { - return t.transmitDelayDefault(seqNr, index) + return t.transmitDelaysDefault(seqNr, index), true } } diff --git a/offchainreporting2plus/internal/ocr3_1/serialization/offchainreporting3_1_telemetry.pb.go b/offchainreporting2plus/internal/ocr3_1/serialization/offchainreporting3_1_telemetry.pb.go index f75a802b..13b3a980 100644 --- a/offchainreporting2plus/internal/ocr3_1/serialization/offchainreporting3_1_telemetry.pb.go +++ b/offchainreporting2plus/internal/ocr3_1/serialization/offchainreporting3_1_telemetry.pb.go @@ -32,6 +32,10 @@ type TelemetryWrapper struct { // *TelemetryWrapper_MessageSent // *TelemetryWrapper_AssertionViolation // *TelemetryWrapper_RoundStarted + // *TelemetryWrapper_TransmissionScheduleComputed + // *TelemetryWrapper_TransmissionShouldAcceptAttestedReportComputed + // *TelemetryWrapper_TransmissionShouldTransmitAcceptedReportComputed + // *TelemetryWrapper_EpochStarted Wrapped isTelemetryWrapper_Wrapped `protobuf_oneof:"wrapped"` UnixTimeNanoseconds int64 `protobuf:"varint,26,opt,name=unix_time_nanoseconds,json=unixTimeNanoseconds,proto3" json:"unix_time_nanoseconds,omitempty"` } @@ -110,6 +114,34 @@ func (x *TelemetryWrapper) GetRoundStarted() *TelemetryRoundStarted { return nil } +func (x *TelemetryWrapper) GetTransmissionScheduleComputed() *TelemetryTransmissionScheduleComputed { + if x, ok := x.GetWrapped().(*TelemetryWrapper_TransmissionScheduleComputed); ok { + return x.TransmissionScheduleComputed + } + return nil +} + +func (x *TelemetryWrapper) GetTransmissionShouldAcceptAttestedReportComputed() *TelemetryTransmissionShouldAcceptAttestedReportComputed { + if x, ok := x.GetWrapped().(*TelemetryWrapper_TransmissionShouldAcceptAttestedReportComputed); ok { + return x.TransmissionShouldAcceptAttestedReportComputed + } + return nil +} + +func (x *TelemetryWrapper) GetTransmissionShouldTransmitAcceptedReportComputed() *TelemetryTransmissionShouldTransmitAcceptedReportComputed { + if x, ok := x.GetWrapped().(*TelemetryWrapper_TransmissionShouldTransmitAcceptedReportComputed); ok { + return x.TransmissionShouldTransmitAcceptedReportComputed + } + return nil +} + +func (x *TelemetryWrapper) GetEpochStarted() *TelemetryEpochStarted { + if x, ok := x.GetWrapped().(*TelemetryWrapper_EpochStarted); ok { + return x.EpochStarted + } + return nil +} + func (x *TelemetryWrapper) GetUnixTimeNanoseconds() int64 { if x != nil { return x.UnixTimeNanoseconds @@ -141,6 +173,22 @@ type TelemetryWrapper_RoundStarted struct { RoundStarted *TelemetryRoundStarted `protobuf:"bytes,25,opt,name=round_started,json=roundStarted,proto3,oneof"` } +type TelemetryWrapper_TransmissionScheduleComputed struct { + TransmissionScheduleComputed *TelemetryTransmissionScheduleComputed `protobuf:"bytes,27,opt,name=transmission_schedule_computed,json=transmissionScheduleComputed,proto3,oneof"` +} + +type TelemetryWrapper_TransmissionShouldAcceptAttestedReportComputed struct { + TransmissionShouldAcceptAttestedReportComputed *TelemetryTransmissionShouldAcceptAttestedReportComputed `protobuf:"bytes,28,opt,name=transmission_should_accept_attested_report_computed,json=transmissionShouldAcceptAttestedReportComputed,proto3,oneof"` +} + +type TelemetryWrapper_TransmissionShouldTransmitAcceptedReportComputed struct { + TransmissionShouldTransmitAcceptedReportComputed *TelemetryTransmissionShouldTransmitAcceptedReportComputed `protobuf:"bytes,29,opt,name=transmission_should_transmit_accepted_report_computed,json=transmissionShouldTransmitAcceptedReportComputed,proto3,oneof"` +} + +type TelemetryWrapper_EpochStarted struct { + EpochStarted *TelemetryEpochStarted `protobuf:"bytes,30,opt,name=epoch_started,json=epochStarted,proto3,oneof"` +} + func (*TelemetryWrapper_MessageReceived) isTelemetryWrapper_Wrapped() {} func (*TelemetryWrapper_MessageBroadcast) isTelemetryWrapper_Wrapped() {} @@ -151,6 +199,16 @@ func (*TelemetryWrapper_AssertionViolation) isTelemetryWrapper_Wrapped() {} func (*TelemetryWrapper_RoundStarted) isTelemetryWrapper_Wrapped() {} +func (*TelemetryWrapper_TransmissionScheduleComputed) isTelemetryWrapper_Wrapped() {} + +func (*TelemetryWrapper_TransmissionShouldAcceptAttestedReportComputed) isTelemetryWrapper_Wrapped() { +} + +func (*TelemetryWrapper_TransmissionShouldTransmitAcceptedReportComputed) isTelemetryWrapper_Wrapped() { +} + +func (*TelemetryWrapper_EpochStarted) isTelemetryWrapper_Wrapped() {} + type TelemetryMessageReceived struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -589,6 +647,338 @@ func (x *TelemetryRoundStarted) GetSeqNr() uint64 { return 0 } +type TelemetryTransmissionScheduleComputed struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConfigDigest []byte `protobuf:"bytes,1,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"` + Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` + SeqNr uint64 `protobuf:"varint,3,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"` + Index uint64 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` + UnixTimeNanoseconds uint64 `protobuf:"varint,5,opt,name=unix_time_nanoseconds,json=unixTimeNanoseconds,proto3" json:"unix_time_nanoseconds,omitempty"` + IsOverride bool `protobuf:"varint,6,opt,name=is_override,json=isOverride,proto3" json:"is_override,omitempty"` + ScheduleDelayNanosecondsPerNode map[uint64]uint64 `protobuf:"bytes,7,rep,name=schedule_delay_nanoseconds_per_node,json=scheduleDelayNanosecondsPerNode,proto3" json:"schedule_delay_nanoseconds_per_node,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + Ok bool `protobuf:"varint,8,opt,name=ok,proto3" json:"ok,omitempty"` // Was the schedule computed successfully? +} + +func (x *TelemetryTransmissionScheduleComputed) Reset() { + *x = TelemetryTransmissionScheduleComputed{} + if protoimpl.UnsafeEnabled { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryTransmissionScheduleComputed) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryTransmissionScheduleComputed) ProtoMessage() {} + +func (x *TelemetryTransmissionScheduleComputed) ProtoReflect() protoreflect.Message { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryTransmissionScheduleComputed.ProtoReflect.Descriptor instead. +func (*TelemetryTransmissionScheduleComputed) Descriptor() ([]byte, []int) { + return file_offchainreporting3_1_telemetry_proto_rawDescGZIP(), []int{7} +} + +func (x *TelemetryTransmissionScheduleComputed) GetConfigDigest() []byte { + if x != nil { + return x.ConfigDigest + } + return nil +} + +func (x *TelemetryTransmissionScheduleComputed) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + +func (x *TelemetryTransmissionScheduleComputed) GetSeqNr() uint64 { + if x != nil { + return x.SeqNr + } + return 0 +} + +func (x *TelemetryTransmissionScheduleComputed) GetIndex() uint64 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *TelemetryTransmissionScheduleComputed) GetUnixTimeNanoseconds() uint64 { + if x != nil { + return x.UnixTimeNanoseconds + } + return 0 +} + +func (x *TelemetryTransmissionScheduleComputed) GetIsOverride() bool { + if x != nil { + return x.IsOverride + } + return false +} + +func (x *TelemetryTransmissionScheduleComputed) GetScheduleDelayNanosecondsPerNode() map[uint64]uint64 { + if x != nil { + return x.ScheduleDelayNanosecondsPerNode + } + return nil +} + +func (x *TelemetryTransmissionScheduleComputed) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +type TelemetryTransmissionShouldAcceptAttestedReportComputed struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConfigDigest []byte `protobuf:"bytes,1,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"` + Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` + SeqNr uint64 `protobuf:"varint,3,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"` + Index uint64 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` + Result bool `protobuf:"varint,5,opt,name=result,proto3" json:"result,omitempty"` + Ok bool `protobuf:"varint,6,opt,name=ok,proto3" json:"ok,omitempty"` // Did the ReportingPlugin method return successfully? +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) Reset() { + *x = TelemetryTransmissionShouldAcceptAttestedReportComputed{} + if protoimpl.UnsafeEnabled { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryTransmissionShouldAcceptAttestedReportComputed) ProtoMessage() {} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) ProtoReflect() protoreflect.Message { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryTransmissionShouldAcceptAttestedReportComputed.ProtoReflect.Descriptor instead. +func (*TelemetryTransmissionShouldAcceptAttestedReportComputed) Descriptor() ([]byte, []int) { + return file_offchainreporting3_1_telemetry_proto_rawDescGZIP(), []int{8} +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetConfigDigest() []byte { + if x != nil { + return x.ConfigDigest + } + return nil +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetSeqNr() uint64 { + if x != nil { + return x.SeqNr + } + return 0 +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetIndex() uint64 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetResult() bool { + if x != nil { + return x.Result + } + return false +} + +func (x *TelemetryTransmissionShouldAcceptAttestedReportComputed) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +type TelemetryTransmissionShouldTransmitAcceptedReportComputed struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConfigDigest []byte `protobuf:"bytes,1,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"` + SeqNr uint64 `protobuf:"varint,3,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"` + Index uint64 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` + Result bool `protobuf:"varint,5,opt,name=result,proto3" json:"result,omitempty"` + Ok bool `protobuf:"varint,6,opt,name=ok,proto3" json:"ok,omitempty"` // Did the ReportingPlugin method return successfully? +} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) Reset() { + *x = TelemetryTransmissionShouldTransmitAcceptedReportComputed{} + if protoimpl.UnsafeEnabled { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryTransmissionShouldTransmitAcceptedReportComputed) ProtoMessage() {} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) ProtoReflect() protoreflect.Message { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryTransmissionShouldTransmitAcceptedReportComputed.ProtoReflect.Descriptor instead. +func (*TelemetryTransmissionShouldTransmitAcceptedReportComputed) Descriptor() ([]byte, []int) { + return file_offchainreporting3_1_telemetry_proto_rawDescGZIP(), []int{9} +} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetConfigDigest() []byte { + if x != nil { + return x.ConfigDigest + } + return nil +} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetSeqNr() uint64 { + if x != nil { + return x.SeqNr + } + return 0 +} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetIndex() uint64 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetResult() bool { + if x != nil { + return x.Result + } + return false +} + +func (x *TelemetryTransmissionShouldTransmitAcceptedReportComputed) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +type TelemetryEpochStarted struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConfigDigest []byte `protobuf:"bytes,1,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"` + Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` + Leader uint64 `protobuf:"varint,3,opt,name=leader,proto3" json:"leader,omitempty"` +} + +func (x *TelemetryEpochStarted) Reset() { + *x = TelemetryEpochStarted{} + if protoimpl.UnsafeEnabled { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryEpochStarted) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryEpochStarted) ProtoMessage() {} + +func (x *TelemetryEpochStarted) ProtoReflect() protoreflect.Message { + mi := &file_offchainreporting3_1_telemetry_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryEpochStarted.ProtoReflect.Descriptor instead. +func (*TelemetryEpochStarted) Descriptor() ([]byte, []int) { + return file_offchainreporting3_1_telemetry_proto_rawDescGZIP(), []int{10} +} + +func (x *TelemetryEpochStarted) GetConfigDigest() []byte { + if x != nil { + return x.ConfigDigest + } + return nil +} + +func (x *TelemetryEpochStarted) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + +func (x *TelemetryEpochStarted) GetLeader() uint64 { + if x != nil { + return x.Leader + } + return 0 +} + var File_offchainreporting3_1_telemetry_proto protoreflect.FileDescriptor var file_offchainreporting3_1_telemetry_proto_rawDesc = []byte{ @@ -598,7 +988,7 @@ var file_offchainreporting3_1_telemetry_proto_rawDesc = []byte{ 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x1a, 0x23, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x9f, 0x04, 0x0a, 0x10, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x57, + 0x6f, 0x22, 0xfd, 0x08, 0x0a, 0x10, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, @@ -627,80 +1017,181 @@ var file_offchainreporting3_1_telemetry_proto_rawDesc = []byte{ 0x0b, 0x32, 0x2b, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x48, 0x00, - 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x32, - 0x0a, 0x15, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x75, - 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x04, 0x08, - 0x01, 0x10, 0x15, 0x22, 0xab, 0x01, 0x0a, 0x18, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, - 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, - 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x22, 0x94, 0x01, 0x0a, 0x19, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, + 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x83, + 0x01, 0x0a, 0x1e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, + 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x1c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x64, 0x12, 0xbc, 0x01, 0x0a, 0x33, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x61, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x18, 0x1c, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x4d, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, + 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, + 0x64, 0x48, 0x00, 0x52, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x65, 0x64, 0x12, 0xc2, 0x01, 0x0a, 0x35, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x6d, 0x69, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x18, 0x1d, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x4f, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x41, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x30, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, + 0x69, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x12, 0x52, 0x0a, 0x0d, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, + 0x45, 0x70, 0x6f, 0x63, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0c, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, + 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x75, 0x6e, 0x69, + 0x78, 0x54, 0x69, 0x6d, 0x65, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, + 0x42, 0x09, 0x0a, 0x07, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x04, 0x08, 0x01, 0x10, + 0x15, 0x22, 0xab, 0x01, 0x0a, 0x18, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x23, + 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x57, + 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x65, 0x6e, + 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, + 0x94, 0x01, 0x0a, 0x19, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x23, 0x0a, + 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, + 0x73, 0x74, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x57, 0x72, + 0x61, 0x70, 0x70, 0x65, 0x72, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, + 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, + 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0xab, 0x01, 0x0a, 0x14, 0x54, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x74, 0x72, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1a, 0x0a, 0x08, - 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, - 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0xab, 0x01, 0x0a, 0x14, 0x54, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x6e, - 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1a, - 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, - 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, - 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0xae, 0x01, 0x0a, 0x1b, 0x54, 0x65, 0x6c, 0x65, 0x6d, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x22, 0xae, 0x01, 0x0a, 0x1b, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x69, 0x6f, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x7c, 0x0a, 0x15, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, + 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x69, 0x6f, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x7c, 0x0a, 0x15, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x56, - 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x14, - 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0xf2, 0x01, 0x0a, 0x2f, 0x54, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x74, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x69, - 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6d, - 0x73, 0x67, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x13, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x64, 0x5f, 0x6d, 0x73, 0x67, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x13, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, - 0x73, 0x67, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0xab, 0x01, 0x0a, - 0x15, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, - 0x69, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x3b, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, + 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x14, 0x69, 0x6e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, + 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0xf2, 0x01, 0x0a, 0x2f, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x69, 0x6f, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x32, + 0x0a, 0x15, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6d, 0x73, 0x67, + 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x73, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x5f, 0x6d, 0x73, 0x67, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x13, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, 0x73, 0x67, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1a, + 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0xab, 0x01, 0x0a, 0x15, 0x54, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, + 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, + 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, + 0x65, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x22, 0xf9, 0x03, 0x0a, 0x25, 0x54, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, + 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x15, 0x0a, + 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, + 0x65, 0x71, 0x4e, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x32, 0x0a, 0x15, 0x75, 0x6e, + 0x69, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x78, 0x54, + 0x69, 0x6d, 0x65, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, + 0xae, 0x01, 0x0a, 0x23, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, + 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x70, + 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x60, 0x2e, + 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, + 0x67, 0x33, 0x5f, 0x31, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, + 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, + 0x75, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x50, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x1f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4e, 0x61, + 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x50, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, + 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, + 0x1a, 0x52, 0x0a, 0x24, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x61, + 0x79, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x50, 0x65, 0x72, 0x4e, + 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc9, 0x01, 0x0a, 0x37, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, + 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x65, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, + 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, + 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x15, 0x0a, 0x06, 0x73, + 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, + 0x4e, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, + 0x22, 0xbb, 0x01, 0x0a, 0x39, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x12, 0x23, + 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x6a, + 0x0a, 0x15, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x45, 0x70, 0x6f, 0x63, 0x68, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x3b, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } @@ -717,32 +1208,42 @@ func file_offchainreporting3_1_telemetry_proto_rawDescGZIP() []byte { return file_offchainreporting3_1_telemetry_proto_rawDescData } -var file_offchainreporting3_1_telemetry_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_offchainreporting3_1_telemetry_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_offchainreporting3_1_telemetry_proto_goTypes = []interface{}{ - (*TelemetryWrapper)(nil), // 0: offchainreporting3_1.TelemetryWrapper - (*TelemetryMessageReceived)(nil), // 1: offchainreporting3_1.TelemetryMessageReceived - (*TelemetryMessageBroadcast)(nil), // 2: offchainreporting3_1.TelemetryMessageBroadcast - (*TelemetryMessageSent)(nil), // 3: offchainreporting3_1.TelemetryMessageSent - (*TelemetryAssertionViolation)(nil), // 4: offchainreporting3_1.TelemetryAssertionViolation - (*TelemetryAssertionViolationInvalidSerialization)(nil), // 5: offchainreporting3_1.TelemetryAssertionViolationInvalidSerialization - (*TelemetryRoundStarted)(nil), // 6: offchainreporting3_1.TelemetryRoundStarted - (*MessageWrapper)(nil), // 7: offchainreporting3_1.MessageWrapper + (*TelemetryWrapper)(nil), // 0: offchainreporting3_1.TelemetryWrapper + (*TelemetryMessageReceived)(nil), // 1: offchainreporting3_1.TelemetryMessageReceived + (*TelemetryMessageBroadcast)(nil), // 2: offchainreporting3_1.TelemetryMessageBroadcast + (*TelemetryMessageSent)(nil), // 3: offchainreporting3_1.TelemetryMessageSent + (*TelemetryAssertionViolation)(nil), // 4: offchainreporting3_1.TelemetryAssertionViolation + (*TelemetryAssertionViolationInvalidSerialization)(nil), // 5: offchainreporting3_1.TelemetryAssertionViolationInvalidSerialization + (*TelemetryRoundStarted)(nil), // 6: offchainreporting3_1.TelemetryRoundStarted + (*TelemetryTransmissionScheduleComputed)(nil), // 7: offchainreporting3_1.TelemetryTransmissionScheduleComputed + (*TelemetryTransmissionShouldAcceptAttestedReportComputed)(nil), // 8: offchainreporting3_1.TelemetryTransmissionShouldAcceptAttestedReportComputed + (*TelemetryTransmissionShouldTransmitAcceptedReportComputed)(nil), // 9: offchainreporting3_1.TelemetryTransmissionShouldTransmitAcceptedReportComputed + (*TelemetryEpochStarted)(nil), // 10: offchainreporting3_1.TelemetryEpochStarted + nil, // 11: offchainreporting3_1.TelemetryTransmissionScheduleComputed.ScheduleDelayNanosecondsPerNodeEntry + (*MessageWrapper)(nil), // 12: offchainreporting3_1.MessageWrapper } var file_offchainreporting3_1_telemetry_proto_depIdxs = []int32{ - 1, // 0: offchainreporting3_1.TelemetryWrapper.message_received:type_name -> offchainreporting3_1.TelemetryMessageReceived - 2, // 1: offchainreporting3_1.TelemetryWrapper.message_broadcast:type_name -> offchainreporting3_1.TelemetryMessageBroadcast - 3, // 2: offchainreporting3_1.TelemetryWrapper.message_sent:type_name -> offchainreporting3_1.TelemetryMessageSent - 4, // 3: offchainreporting3_1.TelemetryWrapper.assertion_violation:type_name -> offchainreporting3_1.TelemetryAssertionViolation - 6, // 4: offchainreporting3_1.TelemetryWrapper.round_started:type_name -> offchainreporting3_1.TelemetryRoundStarted - 7, // 5: offchainreporting3_1.TelemetryMessageReceived.msg:type_name -> offchainreporting3_1.MessageWrapper - 7, // 6: offchainreporting3_1.TelemetryMessageBroadcast.msg:type_name -> offchainreporting3_1.MessageWrapper - 7, // 7: offchainreporting3_1.TelemetryMessageSent.msg:type_name -> offchainreporting3_1.MessageWrapper - 5, // 8: offchainreporting3_1.TelemetryAssertionViolation.invalid_serialization:type_name -> offchainreporting3_1.TelemetryAssertionViolationInvalidSerialization - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 1, // 0: offchainreporting3_1.TelemetryWrapper.message_received:type_name -> offchainreporting3_1.TelemetryMessageReceived + 2, // 1: offchainreporting3_1.TelemetryWrapper.message_broadcast:type_name -> offchainreporting3_1.TelemetryMessageBroadcast + 3, // 2: offchainreporting3_1.TelemetryWrapper.message_sent:type_name -> offchainreporting3_1.TelemetryMessageSent + 4, // 3: offchainreporting3_1.TelemetryWrapper.assertion_violation:type_name -> offchainreporting3_1.TelemetryAssertionViolation + 6, // 4: offchainreporting3_1.TelemetryWrapper.round_started:type_name -> offchainreporting3_1.TelemetryRoundStarted + 7, // 5: offchainreporting3_1.TelemetryWrapper.transmission_schedule_computed:type_name -> offchainreporting3_1.TelemetryTransmissionScheduleComputed + 8, // 6: offchainreporting3_1.TelemetryWrapper.transmission_should_accept_attested_report_computed:type_name -> offchainreporting3_1.TelemetryTransmissionShouldAcceptAttestedReportComputed + 9, // 7: offchainreporting3_1.TelemetryWrapper.transmission_should_transmit_accepted_report_computed:type_name -> offchainreporting3_1.TelemetryTransmissionShouldTransmitAcceptedReportComputed + 10, // 8: offchainreporting3_1.TelemetryWrapper.epoch_started:type_name -> offchainreporting3_1.TelemetryEpochStarted + 12, // 9: offchainreporting3_1.TelemetryMessageReceived.msg:type_name -> offchainreporting3_1.MessageWrapper + 12, // 10: offchainreporting3_1.TelemetryMessageBroadcast.msg:type_name -> offchainreporting3_1.MessageWrapper + 12, // 11: offchainreporting3_1.TelemetryMessageSent.msg:type_name -> offchainreporting3_1.MessageWrapper + 5, // 12: offchainreporting3_1.TelemetryAssertionViolation.invalid_serialization:type_name -> offchainreporting3_1.TelemetryAssertionViolationInvalidSerialization + 11, // 13: offchainreporting3_1.TelemetryTransmissionScheduleComputed.schedule_delay_nanoseconds_per_node:type_name -> offchainreporting3_1.TelemetryTransmissionScheduleComputed.ScheduleDelayNanosecondsPerNodeEntry + 14, // [14:14] is the sub-list for method output_type + 14, // [14:14] is the sub-list for method input_type + 14, // [14:14] is the sub-list for extension type_name + 14, // [14:14] is the sub-list for extension extendee + 0, // [0:14] is the sub-list for field type_name } func init() { file_offchainreporting3_1_telemetry_proto_init() } @@ -836,6 +1337,54 @@ func file_offchainreporting3_1_telemetry_proto_init() { return nil } } + file_offchainreporting3_1_telemetry_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryTransmissionScheduleComputed); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_offchainreporting3_1_telemetry_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryTransmissionShouldAcceptAttestedReportComputed); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_offchainreporting3_1_telemetry_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryTransmissionShouldTransmitAcceptedReportComputed); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_offchainreporting3_1_telemetry_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryEpochStarted); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_offchainreporting3_1_telemetry_proto_msgTypes[0].OneofWrappers = []interface{}{ (*TelemetryWrapper_MessageReceived)(nil), @@ -843,6 +1392,10 @@ func file_offchainreporting3_1_telemetry_proto_init() { (*TelemetryWrapper_MessageSent)(nil), (*TelemetryWrapper_AssertionViolation)(nil), (*TelemetryWrapper_RoundStarted)(nil), + (*TelemetryWrapper_TransmissionScheduleComputed)(nil), + (*TelemetryWrapper_TransmissionShouldAcceptAttestedReportComputed)(nil), + (*TelemetryWrapper_TransmissionShouldTransmitAcceptedReportComputed)(nil), + (*TelemetryWrapper_EpochStarted)(nil), } file_offchainreporting3_1_telemetry_proto_msgTypes[4].OneofWrappers = []interface{}{ (*TelemetryAssertionViolation_InvalidSerialization)(nil), @@ -853,7 +1406,7 @@ func file_offchainreporting3_1_telemetry_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_offchainreporting3_1_telemetry_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, diff --git a/offchainreporting2plus/internal/shim/ocr3_1_telemetry_sender.go b/offchainreporting2plus/internal/shim/ocr3_1_telemetry_sender.go index 740a7bc9..8aa6a689 100644 --- a/offchainreporting2plus/internal/shim/ocr3_1_telemetry_sender.go +++ b/offchainreporting2plus/internal/shim/ocr3_1_telemetry_sender.go @@ -10,32 +10,49 @@ import ( ) type OCR3_1TelemetrySender struct { - chTelemetry chan<- *serialization.TelemetryWrapper - logger commontypes.Logger - taper loghelper.LogarithmicTaper + chTelemetry chan<- *serialization.TelemetryWrapper + logger commontypes.Logger + taper loghelper.LogarithmicTaper + enableTransmissionTelemetry bool } -func NewOCR3_1TelemetrySender(chTelemetry chan<- *serialization.TelemetryWrapper, logger commontypes.Logger) *OCR3_1TelemetrySender { - return &OCR3_1TelemetrySender{chTelemetry, logger, loghelper.LogarithmicTaper{}} +func NewOCR3_1TelemetrySender(chTelemetry chan<- *serialization.TelemetryWrapper, logger commontypes.Logger, enableTransmissionTelemetry bool) *OCR3_1TelemetrySender { + return &OCR3_1TelemetrySender{chTelemetry, logger, loghelper.LogarithmicTaper{}, enableTransmissionTelemetry} } func (ts *OCR3_1TelemetrySender) send(t *serialization.TelemetryWrapper) { select { case ts.chTelemetry <- t: ts.taper.Reset(func(oldCount uint64) { - ts.logger.Info("NewOCR3_1TelemetrySender: stopped dropping telemetry", commontypes.LogFields{ + ts.logger.Info("OCR3_1TelemetrySender: stopped dropping telemetry", commontypes.LogFields{ "droppedCount": oldCount, }) }) default: ts.taper.Trigger(func(newCount uint64) { - ts.logger.Warn("NewOCR3_1TelemetrySender: dropping telemetry", commontypes.LogFields{ + ts.logger.Warn("OCR3_1TelemetrySender: dropping telemetry", commontypes.LogFields{ "droppedCount": newCount, }) }) } } +func (ts *OCR3_1TelemetrySender) EpochStarted( + configDigest types.ConfigDigest, + epoch uint64, + leader commontypes.OracleID, +) { + t := time.Now().UnixNano() + ts.send(&serialization.TelemetryWrapper{ + Wrapped: &serialization.TelemetryWrapper_EpochStarted{&serialization.TelemetryEpochStarted{ + ConfigDigest: configDigest[:], + Epoch: epoch, + Leader: uint64(leader), + }}, + UnixTimeNanoseconds: t, + }) +} + func (ts *OCR3_1TelemetrySender) RoundStarted( configDigest types.ConfigDigest, epoch uint64, @@ -56,3 +73,80 @@ func (ts *OCR3_1TelemetrySender) RoundStarted( UnixTimeNanoseconds: t, }) } + +func (ts *OCR3_1TelemetrySender) TransmissionScheduleComputed( + configDigest types.ConfigDigest, + seqNr uint64, + index int, + now time.Time, + isOverride bool, + schedule map[commontypes.OracleID]time.Duration, + ok bool, +) { + if !ts.enableTransmissionTelemetry { + return + } + scheduleDelayNanosecondsPerNode := make(map[uint64]uint64, len(schedule)) + for oracle, delay := range schedule { + scheduleDelayNanosecondsPerNode[uint64(oracle)] = uint64(delay.Nanoseconds()) + } + t := time.Now().UnixNano() + ts.send(&serialization.TelemetryWrapper{ + Wrapped: &serialization.TelemetryWrapper_TransmissionScheduleComputed{&serialization.TelemetryTransmissionScheduleComputed{ + ConfigDigest: configDigest[:], + SeqNr: seqNr, + Index: uint64(index), + UnixTimeNanoseconds: uint64(now.UnixNano()), + IsOverride: isOverride, + ScheduleDelayNanosecondsPerNode: scheduleDelayNanosecondsPerNode, + Ok: ok, + }}, + UnixTimeNanoseconds: t, + }) +} + +func (ts *OCR3_1TelemetrySender) TransmissionShouldAcceptAttestedReportComputed( + configDigest types.ConfigDigest, + seqNr uint64, + index int, + result bool, + ok bool, +) { + if !ts.enableTransmissionTelemetry { + return + } + t := time.Now().UnixNano() + ts.send(&serialization.TelemetryWrapper{ + Wrapped: &serialization.TelemetryWrapper_TransmissionShouldAcceptAttestedReportComputed{&serialization.TelemetryTransmissionShouldAcceptAttestedReportComputed{ + ConfigDigest: configDigest[:], + SeqNr: seqNr, + Index: uint64(index), + Result: result, + Ok: ok, + }}, + UnixTimeNanoseconds: t, + }) +} + +func (ts *OCR3_1TelemetrySender) TransmissionShouldTransmitAcceptedReportComputed( + configDigest types.ConfigDigest, + seqNr uint64, + index int, + result bool, + ok bool, +) { + if !ts.enableTransmissionTelemetry { + return + } + t := time.Now().UnixNano() + ts.send(&serialization.TelemetryWrapper{ + Wrapped: &serialization.TelemetryWrapper_TransmissionShouldTransmitAcceptedReportComputed{&serialization.TelemetryTransmissionShouldTransmitAcceptedReportComputed{ + ConfigDigest: configDigest[:], + SeqNr: seqNr, + Index: uint64(index), + Result: result, + Ok: ok, + }}, + UnixTimeNanoseconds: t, + }) +} diff --git a/offchainreporting2plus/internal/shim/ocr3_telemetry_sender.go b/offchainreporting2plus/internal/shim/ocr3_telemetry_sender.go index 7d92fe65..210dd5d1 100644 --- a/offchainreporting2plus/internal/shim/ocr3_telemetry_sender.go +++ b/offchainreporting2plus/internal/shim/ocr3_telemetry_sender.go @@ -39,14 +39,14 @@ func (ts *OCR3TelemetrySender) send(t *serialization.TelemetryWrapper) { func (ts *OCR3TelemetrySender) EpochStarted( configDigest types.ConfigDigest, - epoch uint32, + epoch uint64, leader commontypes.OracleID, ) { t := time.Now().UnixNano() ts.send(&serialization.TelemetryWrapper{ Wrapped: &serialization.TelemetryWrapper_EpochStarted{&serialization.TelemetryEpochStarted{ ConfigDigest: configDigest[:], - Epoch: uint64(epoch), + Epoch: epoch, Leader: uint64(leader), }}, UnixTimeNanoseconds: t, diff --git a/offchainreporting2plus/keyvaluedatabase/pebble_key_value_database.go b/offchainreporting2plus/keyvaluedatabase/pebble_key_value_database.go index ba90e654..e0cf27fd 100644 --- a/offchainreporting2plus/keyvaluedatabase/pebble_key_value_database.go +++ b/offchainreporting2plus/keyvaluedatabase/pebble_key_value_database.go @@ -90,6 +90,12 @@ func (p *pebbleKeyValueDatabase) NewReadTransaction() (ocr3_1types.KeyValueDatab }, nil } +// Deprecated: Metrics is only used for internal benchmarking and should not be +// used externally. It may be removed or changed without notice in the future. +func (p *pebbleKeyValueDatabase) Metrics() (*pebble.Metrics, error) { + return p.db.Metrics(), nil +} + // The resulting transaction is NOT thread-safe. func (p *pebbleKeyValueDatabase) NewReadWriteTransaction() (ocr3_1types.KeyValueDatabaseReadWriteTransaction, error) { diff --git a/offchainreporting2plus/ocr3_1types/plugin.go b/offchainreporting2plus/ocr3_1types/plugin.go index 7ca1958e..0eb73d7c 100644 --- a/offchainreporting2plus/ocr3_1types/plugin.go +++ b/offchainreporting2plus/ocr3_1types/plugin.go @@ -2,6 +2,8 @@ package ocr3_1types import ( "context" + "errors" + "fmt" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -429,6 +431,27 @@ type ReportingPluginLimits struct { MaxPerOracleUnexpiredBlobCount int } +// Validate checks that all fields are within their allowed ranges. +// It returns a joined error listing every out-of-range field, or nil if valid. +func (l ReportingPluginLimits) Validate() error { + var err error + check := func(name string, val, max int) { + if !(0 <= val && val <= max) { + err = errors.Join(err, fmt.Errorf("%s (%v) out of range. Should be between 0 and %v", name, val, max)) + } + } + check("MaxQueryBytes", l.MaxQueryBytes, MaxMaxQueryBytes) + check("MaxObservationBytes", l.MaxObservationBytes, MaxMaxObservationBytes) + check("MaxReportBytes", l.MaxReportBytes, MaxMaxReportBytes) + check("MaxReportsPlusPrecursorBytes", l.MaxReportsPlusPrecursorBytes, MaxMaxReportsPlusPrecursorBytes) + check("MaxReportCount", l.MaxReportCount, MaxMaxReportCount) + + check("MaxKeyValueModifiedKeys", l.MaxKeyValueModifiedKeys, MaxMaxKeyValueModifiedKeys) + check("MaxKeyValueModifiedKeysPlusValuesBytes", l.MaxKeyValueModifiedKeysPlusValuesBytes, MaxMaxKeyValueModifiedKeysPlusValuesBytes) + check("MaxBlobPayloadBytes", l.MaxBlobPayloadBytes, MaxMaxBlobPayloadBytes) + return err +} + //go-sumtype:decl ReportingPluginInfo type ReportingPluginInfo interface { @@ -442,6 +465,13 @@ type ReportingPluginInfo1 struct { Limits ReportingPluginLimits } +func (i ReportingPluginInfo1) Validate() error { + if err := i.Limits.Validate(); err != nil { + return fmt.Errorf("Limits are invalid: %w", err) + } + return nil +} + var _ ReportingPluginInfo = ReportingPluginInfo1{} func (ReportingPluginInfo1) isReportingPluginInfo() {} diff --git a/offchainreporting2plus/ocr3shims/onchain_keyring.go b/offchainreporting2plus/ocr3shims/onchain_keyring.go new file mode 100644 index 00000000..35c7586a --- /dev/null +++ b/offchainreporting2plus/ocr3shims/onchain_keyring.go @@ -0,0 +1,30 @@ +package ocr3shims + +import ( + "bytes" + "fmt" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +type onchainKeyring2Shim[RI any] struct { + ocr3types.OnchainKeyring[RI] +} + +func (k *onchainKeyring2Shim[RI]) Has(onchainPublicKey types.OnchainPublicKey) bool { + return bytes.Equal(k.OnchainKeyring.PublicKey(), onchainPublicKey) +} + +func (k *onchainKeyring2Shim[RI]) DebugIdentifier() string { + return fmt.Sprintf("%x", k.OnchainKeyring.PublicKey()) +} + +// OnchainKeyringAsOnchainKeyring2 wraps an [ocr3types.OnchainKeyring] and returns an [ocr3types.OnchainKeyring2]. +// If k already implements OnchainKeyring2, it is returned as-is. +func OnchainKeyringAsOnchainKeyring2[RI any](k ocr3types.OnchainKeyring[RI]) ocr3types.OnchainKeyring2[RI] { + if c, ok := any(k).(ocr3types.OnchainKeyring2[RI]); ok { + return c + } + return &onchainKeyring2Shim[RI]{k} +} diff --git a/offchainreporting2plus/ocr3types/mercury_plugin.go b/offchainreporting2plus/ocr3types/mercury_plugin.go index d52bd424..29797707 100644 --- a/offchainreporting2plus/ocr3types/mercury_plugin.go +++ b/offchainreporting2plus/ocr3types/mercury_plugin.go @@ -2,6 +2,8 @@ package ocr3types import ( "context" + "errors" + "fmt" "time" "github.com/smartcontractkit/libocr/commontypes" @@ -164,3 +166,22 @@ type MercuryPluginInfo struct { Limits MercuryPluginLimits } + +func (l MercuryPluginLimits) Validate() error { + var err error + check := func(name string, val, max int) { + if !(0 <= val && val <= max) { + err = errors.Join(err, fmt.Errorf("%s (%v) out of range. Should be between 0 and %v", name, val, max)) + } + } + check("MaxObservationLength", l.MaxObservationLength, MaxMaxMercuryObservationLength) + check("MaxReportLength", l.MaxReportLength, MaxMaxMercuryReportLength) + return err +} + +func (i MercuryPluginInfo) Validate() error { + if err := i.Limits.Validate(); err != nil { + return fmt.Errorf("Limits are invalid: %w", err) + } + return nil +} diff --git a/offchainreporting2plus/ocr3types/plugin.go b/offchainreporting2plus/ocr3types/plugin.go index 1236adb4..96f6a86c 100644 --- a/offchainreporting2plus/ocr3types/plugin.go +++ b/offchainreporting2plus/ocr3types/plugin.go @@ -2,6 +2,8 @@ package ocr3types import ( "context" + "errors" + "fmt" "time" "github.com/smartcontractkit/libocr/commontypes" @@ -312,3 +314,27 @@ type ReportingPluginInfo struct { Limits ReportingPluginLimits } + +// Validate checks that all fields are within their allowed ranges. +// It returns a joined error listing every out-of-range field, or nil if valid. +func (l ReportingPluginLimits) Validate() error { + var err error + check := func(name string, val, max int) { + if !(0 <= val && val <= max) { + err = errors.Join(err, fmt.Errorf("%s (%v) out of range. Should be between 0 and %v", name, val, max)) + } + } + check("MaxQueryLength", l.MaxQueryLength, MaxMaxQueryLength) + check("MaxObservationLength", l.MaxObservationLength, MaxMaxObservationLength) + check("MaxOutcomeLength", l.MaxOutcomeLength, MaxMaxOutcomeLength) + check("MaxReportLength", l.MaxReportLength, MaxMaxReportLength) + check("MaxReportCount", l.MaxReportCount, MaxMaxReportCount) + return err +} + +func (i ReportingPluginInfo) Validate() error { + if err := i.Limits.Validate(); err != nil { + return fmt.Errorf("Limits are invalid: %w", err) + } + return nil +} diff --git a/offchainreporting2plus/ocr3types/types.go b/offchainreporting2plus/ocr3types/types.go index b9de2003..92ce4fa2 100644 --- a/offchainreporting2plus/ocr3types/types.go +++ b/offchainreporting2plus/ocr3types/types.go @@ -40,10 +40,10 @@ type OnchainKeyring[RI any] interface { // PublicKey returns the public key of the keypair used by Sign. PublicKey() types.OnchainPublicKey - // Sign returns a signature over Report. - Sign(types.ConfigDigest, uint64, ReportWithInfo[RI]) (signature []byte, err error) + // Sign returns a signature over ConfigDigest, seqNr, and ReportWithInfo. + Sign(_ types.ConfigDigest, seqNr uint64, _ ReportWithInfo[RI]) (signature []byte, err error) - // Verify verifies a signature over ReportContext and Report allegedly + // Verify verifies a signature over ConfigDigest, SeqNr, and ReportWithInfo allegedly // created from OnchainPublicKey. // // Implementations of this function must gracefully handle malformed or @@ -53,3 +53,36 @@ type OnchainKeyring[RI any] interface { // Maximum length of a signature MaxSignatureLength() int } + +// OnchainKeyring2 is an updated version of [OnchainKeyring] that can +// support sets of public keys (as e.g. used in CRE). Unlike OnchainKeyring, +// it does not expose a PublicKey() method. Identity matching is done via Has(). +// +// Package ocr3shims provides a helper to turn an [OnchainKeyring] into an +// [OnchainKeyring2]. +// +// All its functions should be thread-safe. +type OnchainKeyring2[RI any] interface { + // Sign returns a signature over ConfigDigest, seqNr, and ReportWithInfo. + Sign(_ types.ConfigDigest, seqNr uint64, _ ReportWithInfo[RI]) (signature []byte, err error) + + // Verify verifies a signature over ConfigDigest, SeqNr, and ReportWithInfo allegedly + // created from OnchainPublicKey. + // + // Implementations of this function must gracefully handle malformed or + // adversarially crafted inputs. + Verify(_ types.OnchainPublicKey, _ types.ConfigDigest, seqNr uint64, _ ReportWithInfo[RI], signature []byte) bool + + // Has returns true if the keyring supports signing for the given OnchainPublicKey. + // Implementations that are backed by a set of keys should return true iff the + // set of keys represented by the argument is a subset of the supported keys. + Has(types.OnchainPublicKey) bool + + // Maximum length of a signature + MaxSignatureLength() int + + // DebugIdentifier returns a human-readable string identifying this keyring, + // for use in log/error messages. Not used for any cryptographic or + // protocol-level purpose. + DebugIdentifier() string +} diff --git a/offchainreporting2plus/ocrintegrationtesthelpers/in_memory_key_value_database.go b/offchainreporting2plus/ocrintegrationtesthelpers/in_memory_key_value_database.go new file mode 100644 index 00000000..f69ec557 --- /dev/null +++ b/offchainreporting2plus/ocrintegrationtesthelpers/in_memory_key_value_database.go @@ -0,0 +1,416 @@ +package ocrintegrationtesthelpers + +import ( + "bytes" + "context" + "fmt" + "sync" + + "github.com/google/btree" + "github.com/smartcontractkit/libocr/internal/util" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3_1types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/libocr/subprocesses" +) + +var ( + errKeyValueDatabaseClosed = fmt.Errorf("key value database closed") + errTransactionCommittedOrDiscarded = fmt.Errorf("transaction committed or discarded") + errKeyValueDatabaseAlreadyOpen = fmt.Errorf("key value database already open") +) + +type item struct { + key []byte + value []byte +} + +func (i item) Less(than item) bool { + return bytes.Compare(i.key, than.key) < 0 +} + +// StatelessInMemoryKeyValueDatabaseFactory is a stateless factory for testing. +// Each call to NewKeyValueDatabase returns a fresh, empty database. +// NewKeyValueDatabaseIfExists always returns ErrKeyValueDatabaseDoesNotExist. +// No exclusive access is enforced: multiple concurrent calls to +// NewKeyValueDatabase with the same configDigest will each succeed and return +// independent databases. Use [StatefulInMemoryKeyValueDatabaseFactory] if you +// need a NewKeyValueDatabase* call to return a database with contents written +// before a previous Close call. +type StatelessInMemoryKeyValueDatabaseFactory struct{} + +var _ ocr3_1types.KeyValueDatabaseFactory = StatelessInMemoryKeyValueDatabaseFactory{} + +func NewStatelessInMemoryKeyValueDatabaseFactory() StatelessInMemoryKeyValueDatabaseFactory { + return StatelessInMemoryKeyValueDatabaseFactory{} +} + +func (StatelessInMemoryKeyValueDatabaseFactory) NewKeyValueDatabase(types.ConfigDigest) (ocr3_1types.KeyValueDatabase, error) { + return NewInMemoryKeyValueDatabase(), nil +} + +func (StatelessInMemoryKeyValueDatabaseFactory) NewKeyValueDatabaseIfExists(types.ConfigDigest) (ocr3_1types.KeyValueDatabase, error) { + return nil, ocr3_1types.ErrKeyValueDatabaseDoesNotExist +} + +// StatefulInMemoryKeyValueDatabaseFactory is a factory for testing that retains +// database contents in memory (not on disk) for the lifetime of the factory. +// After calling db.Close(), a subsequent NewKeyValueDatabase or +// NewKeyValueDatabaseIfExists call for the same configDigest returns a database +// with the contents written before Close. Enforces exclusive access: +// NewKeyValueDatabase* returns an error if a database for that configDigest has +// been opened but not yet closed. Use [ForgetKeyValueDatabaseForTests] to make +// the factory forget about a configDigest (akin to deleting the database from +// the filesystem for a disk-based implementation). +type StatefulInMemoryKeyValueDatabaseFactory struct { + mu sync.Mutex + dbs map[types.ConfigDigest]*InMemoryKeyValueDatabase +} + +var _ ocr3_1types.KeyValueDatabaseFactory = &StatefulInMemoryKeyValueDatabaseFactory{} + +func NewStatefulInMemoryKeyValueDatabaseFactory() *StatefulInMemoryKeyValueDatabaseFactory { + return &StatefulInMemoryKeyValueDatabaseFactory{ + sync.Mutex{}, + make(map[types.ConfigDigest]*InMemoryKeyValueDatabase), + } +} + +func (f *StatefulInMemoryKeyValueDatabaseFactory) NewKeyValueDatabase(configDigest types.ConfigDigest) (ocr3_1types.KeyValueDatabase, error) { + return f.newKeyValueDatabase(configDigest, true) +} + +func (f *StatefulInMemoryKeyValueDatabaseFactory) NewKeyValueDatabaseIfExists(configDigest types.ConfigDigest) (ocr3_1types.KeyValueDatabase, error) { + return f.newKeyValueDatabase(configDigest, false) +} + +// ForgetKeyValueDatabaseForTests makes the factory forget about a configDigest. +// The next NewKeyValueDatabase call for this configDigest will create a fresh +// database; NewKeyValueDatabaseIfExists will return ErrKeyValueDatabaseDoesNotExist. +// Any currently open database for this configDigest is unaffected and continues +// to work, but the exclusivity guarantee is lost: the database opened before +// ForgetKeyValueDatabaseForTests and the database opened after can be open +// simultaneously. +func (f *StatefulInMemoryKeyValueDatabaseFactory) ForgetKeyValueDatabaseForTests(configDigest types.ConfigDigest) { + f.mu.Lock() + defer f.mu.Unlock() + delete(f.dbs, configDigest) +} + +func (f *StatefulInMemoryKeyValueDatabaseFactory) newKeyValueDatabase(configDigest types.ConfigDigest, createIfNotExists bool) (ocr3_1types.KeyValueDatabase, error) { + f.mu.Lock() + defer f.mu.Unlock() + + existingDb, exists := f.dbs[configDigest] + if exists { + existingDb.mu.Lock() + if !existingDb.closed { + existingDb.mu.Unlock() + return nil, errKeyValueDatabaseAlreadyOpen + } + // Closed - transplant tree to new database + tree := existingDb.tree + existingDb.mu.Unlock() + + newDb := newInMemoryKeyValueDatabaseWithTree(tree) + f.dbs[configDigest] = newDb + return newDb, nil + } + + if !createIfNotExists { + return nil, ocr3_1types.ErrKeyValueDatabaseDoesNotExist + } + + newDb := NewInMemoryKeyValueDatabase() + f.dbs[configDigest] = newDb + return newDb, nil +} + +type InMemoryKeyValueDatabase struct { + ctx context.Context + cancel context.CancelFunc + subs subprocesses.Subprocesses + + rwSerializationLock sync.Mutex + + mu sync.Mutex + tree *btree.BTreeG[item] + closed bool +} + +var _ ocr3_1types.KeyValueDatabase = &InMemoryKeyValueDatabase{} + +// NewInMemoryKeyValueDatabase creates a standalone in-memory database without +// factory tracking. Use NewInMemoryKeyValueDatabaseFactory for exclusive access +// and persistence semantics. +func NewInMemoryKeyValueDatabase() *InMemoryKeyValueDatabase { + return newInMemoryKeyValueDatabaseWithTree(btree.NewG(32, func(a, b item) bool { + return a.Less(b) + })) +} + +func newInMemoryKeyValueDatabaseWithTree(tree *btree.BTreeG[item]) *InMemoryKeyValueDatabase { + ctx, cancel := context.WithCancel(context.Background()) + return &InMemoryKeyValueDatabase{ + ctx, + cancel, + subprocesses.Subprocesses{}, + sync.Mutex{}, + sync.Mutex{}, + tree, + false, + } +} + +func (db *InMemoryKeyValueDatabase) Close() error { + db.mu.Lock() + defer db.mu.Unlock() + if db.closed { + return errKeyValueDatabaseClosed + } + + db.closed = true + db.cancel() + db.subs.Wait() + return nil +} + +func (db *InMemoryKeyValueDatabase) NewReadTransaction() (ocr3_1types.KeyValueDatabaseReadTransaction, error) { + db.mu.Lock() + defer db.mu.Unlock() + if db.closed { + return nil, errKeyValueDatabaseClosed + } + + ctx, cancel := context.WithCancel(db.ctx) + return &inMemoryReadWriteTransaction{ + ctx, + cancel, + db, + sync.Mutex{}, + db.tree.Clone(), + true, + }, nil +} + +func (db *InMemoryKeyValueDatabase) NewReadWriteTransaction() (ocr3_1types.KeyValueDatabaseReadWriteTransaction, error) { + db.rwSerializationLock.Lock() + + db.mu.Lock() + defer db.mu.Unlock() + if db.closed { + db.rwSerializationLock.Unlock() + return nil, errKeyValueDatabaseClosed + } + + ctx, cancel := context.WithCancel(db.ctx) + updatedTree := db.tree.Clone() + return &inMemoryReadWriteTransaction{ + ctx, + cancel, + db, + sync.Mutex{}, + updatedTree, + false, + }, nil +} + +func (db *InMemoryKeyValueDatabase) commit(updatedTree *btree.BTreeG[item]) error { + db.mu.Lock() + defer db.mu.Unlock() + if db.closed { + return errKeyValueDatabaseClosed + } + db.tree = updatedTree + return nil +} + +type inMemoryReadWriteTransaction struct { + ctx context.Context + cancel context.CancelFunc + + db *InMemoryKeyValueDatabase + + mu sync.Mutex + updatedTree *btree.BTreeG[item] + readOnly bool +} + +func (tx *inMemoryReadWriteTransaction) Range(loKey []byte, hiKeyExcl []byte) ocr3_1types.KeyValueDatabaseIterator { + loKey = bytes.Clone(loKey) + hiKeyExcl = bytes.Clone(hiKeyExcl) + + tx.mu.Lock() + defer tx.mu.Unlock() + if tx.updatedTree == nil { + return &inMemoryRangeIterator{ + errTransactionCommittedOrDiscarded, + nil, + nil, + nil, + nil, + } + } + + ctx, cancel := context.WithCancel(tx.ctx) + ch := make(chan item) + // Btree is not safe to share across goroutines with concurrent writes. We + // intentionally do not clone because as per the + // ocr3_1types.KeyValueDatabaseIterator interface, users must not write or + // delete keys while an iterator is opened. We want this to cause a nil + // dereference, panic, or other problematic behavior, so that we'll know we + // misuse the interface in protocol code. + tree := tx.updatedTree + + iter := &inMemoryRangeIterator{ + nil, + cancel, + ch, + tx, + nil, + } + + tx.db.subs.Go(func() { + defer close(ch) + tree.AscendGreaterOrEqual(item{loKey, nil}, func(i item) bool { + if len(hiKeyExcl) > 0 && bytes.Compare(i.key, hiKeyExcl) >= 0 { + return false + } + select { + case ch <- i: + return true + case <-ctx.Done(): + return false + } + }) + }) + + return iter +} + +type inMemoryRangeIterator struct { + err error + cancel context.CancelFunc + ch chan item + tx *inMemoryReadWriteTransaction + + currentKey []byte +} + +var _ ocr3_1types.KeyValueDatabaseIterator = &inMemoryRangeIterator{} + +func (i *inMemoryRangeIterator) Close() error { + if i.cancel != nil { + i.cancel() + } + return nil +} + +func (i *inMemoryRangeIterator) Next() bool { + if i.err != nil { + return false + } + + nextItem, ok := <-i.ch + if !ok { + return false + } + + i.currentKey = nextItem.key + return true +} + +func (i *inMemoryRangeIterator) Key() []byte { + return bytes.Clone(i.currentKey) +} + +func (i *inMemoryRangeIterator) Value() ([]byte, error) { + return i.tx.Read(i.currentKey) +} + +func (i *inMemoryRangeIterator) Err() error { + return i.err +} + +var _ ocr3_1types.KeyValueDatabaseReadWriteTransaction = &inMemoryReadWriteTransaction{} +var _ ocr3_1types.KeyValueDatabaseReadTransaction = &inMemoryReadWriteTransaction{} + +func (tx *inMemoryReadWriteTransaction) Commit() error { + tx.mu.Lock() + defer tx.mu.Unlock() + if tx.readOnly { + return fmt.Errorf("read only transaction cannot be committed") + } + if tx.updatedTree == nil { + return errTransactionCommittedOrDiscarded + } + defer tx.db.rwSerializationLock.Unlock() + + if err := tx.db.commit(tx.updatedTree); err != nil { + return err + } + + tx.updatedTree = nil + tx.cancel() + return nil +} + +func (tx *inMemoryReadWriteTransaction) Delete(key []byte) error { + tx.mu.Lock() + defer tx.mu.Unlock() + if tx.readOnly { + return fmt.Errorf("read only transaction cannot delete") + } + if tx.updatedTree == nil { + return errTransactionCommittedOrDiscarded + } + + tx.updatedTree.Delete(item{key, nil}) + return nil +} + +func (tx *inMemoryReadWriteTransaction) Write(key []byte, value []byte) error { + // protect against later modification + key = bytes.Clone(key) + value = bytes.Clone(value) + value = util.NilCoalesceSlice(value) + + tx.mu.Lock() + defer tx.mu.Unlock() + if tx.readOnly { + return fmt.Errorf("read only transaction cannot write") + } + if tx.updatedTree == nil { + return errTransactionCommittedOrDiscarded + } + + tx.updatedTree.ReplaceOrInsert(item{key, value}) + return nil +} + +func (tx *inMemoryReadWriteTransaction) Discard() { + tx.mu.Lock() + defer tx.mu.Unlock() + if tx.updatedTree == nil { + return + } + + tx.updatedTree = nil + tx.cancel() + if !tx.readOnly { + tx.db.rwSerializationLock.Unlock() + } +} + +func (tx *inMemoryReadWriteTransaction) Read(key []byte) ([]byte, error) { + tx.mu.Lock() + defer tx.mu.Unlock() + if tx.updatedTree == nil { + return nil, errTransactionCommittedOrDiscarded + } + + if v, ok := tx.updatedTree.Get(item{key, nil}); ok { + // protect against later modification + return bytes.Clone(v.value), nil + } + return nil, nil +} diff --git a/offchainreporting2plus/ocrintegrationtesthelpers/mock_contract_config_tracker.go b/offchainreporting2plus/ocrintegrationtesthelpers/mock_contract_config_tracker.go new file mode 100644 index 00000000..15c373f6 --- /dev/null +++ b/offchainreporting2plus/ocrintegrationtesthelpers/mock_contract_config_tracker.go @@ -0,0 +1,81 @@ +package ocrintegrationtesthelpers + +import ( + "context" + "fmt" + "sync" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/internal/config" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +type MockContractConfigTracker struct { + offchainConfigDigester types.OffchainConfigDigester + + mu sync.RWMutex + configs []types.ContractConfig +} + +var _ types.ContractConfigTracker = &MockContractConfigTracker{} + +// NewMockContractConfigTracker returns a tracker that simulates on-chain config +// history without a chain: LatestBlockHeight is the number of configs set via +// SetConfig, and LatestConfigDetails returns changedInBlock as the index of the +// latest config (0 when there are no configs set, 1 when one config is set, +// etc.) LatestBlockHeight is always +1 to the index/changedInBlock of the +// latest config. +// +// Requires ContractConfigConfirmations == 1 or SkipContractConfigConfirmations +// in [types.LocalConfig]. +// +// Developers must invoke SetConfig at least once to set a meaningful config, +// otherwise oracles using this tracker will not be able to start. +func NewMockContractConfigTracker(offchainConfigDigester types.OffchainConfigDigester) *MockContractConfigTracker { + configs := []types.ContractConfig{{}} + return &MockContractConfigTracker{offchainConfigDigester, sync.RWMutex{}, configs} +} + +func (c *MockContractConfigTracker) SetConfig(identities []config.OracleIdentity, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) error { + signers := make([]types.OnchainPublicKey, len(identities)) + transmitters := make([]types.Account, len(identities)) + for i, id := range identities { + signers[i] = id.OnchainPublicKey + transmitters[i] = id.TransmitAccount + } + + c.mu.Lock() + defer c.mu.Unlock() + config := types.ContractConfig{types.ConfigDigest{}, uint64(len(c.configs)), signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig} + configDigest, err := c.offchainConfigDigester.ConfigDigest(context.TODO(), config) + if err != nil { + return fmt.Errorf("error computing config digest: %w", err) + } + config.ConfigDigest = configDigest + c.configs = append(c.configs, config) + return nil +} + +func (c *MockContractConfigTracker) Notify() <-chan struct{} { + return nil +} + +func (c *MockContractConfigTracker) LatestConfigDetails(ctx context.Context) (uint64, types.ConfigDigest, error) { + c.mu.RLock() + defer c.mu.RUnlock() + return uint64(len(c.configs) - 1), c.configs[len(c.configs)-1].ConfigDigest, nil +} + +func (c *MockContractConfigTracker) LatestConfig(ctx context.Context, changedInBlock uint64) (types.ContractConfig, error) { + c.mu.RLock() + defer c.mu.RUnlock() + if !(0 < changedInBlock && changedInBlock < uint64(len(c.configs))) { + return types.ContractConfig{}, fmt.Errorf("changedInBlock %d is out of range (0, %d)", changedInBlock, len(c.configs)) + } + return c.configs[changedInBlock], nil +} + +func (c *MockContractConfigTracker) LatestBlockHeight(ctx context.Context) (uint64, error) { + c.mu.RLock() + defer c.mu.RUnlock() + return uint64(len(c.configs)), nil +} diff --git a/offchainreporting2plus/oracle.go b/offchainreporting2plus/oracle.go index 9c318bda..f05b0014 100644 --- a/offchainreporting2plus/oracle.go +++ b/offchainreporting2plus/oracle.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3_1types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3shims" "github.com/prometheus/client_golang/prometheus" "github.com/smartcontractkit/libocr/commontypes" @@ -16,6 +17,8 @@ import ( "github.com/smartcontractkit/libocr/subprocesses" ) +//go-sumtype:decl OracleArgs + type OracleArgs interface { oracleArgsMarker() localConfig() types.LocalConfig @@ -226,6 +229,49 @@ func (args OCR3OracleArgs[RI]) localConfig() types.LocalConfig { return args.Loc func (args OCR3OracleArgs[RI]) runManaged(ctx context.Context) { logger := loghelper.MakeRootLoggerWithContext(args.Logger) + managed.RunManagedOCR3Oracle( + ctx, + + args.V2Bootstrappers, + args.ContractConfigTracker, + args.ContractTransmitter, + args.Database, + args.LocalConfig, + logger, + args.MetricsRegisterer, + args.MonitoringEndpoint, + args.BinaryNetworkEndpointFactory, + args.OffchainConfigDigester, + args.OffchainKeyring, + ocr3shims.OnchainKeyringAsOnchainKeyring2(args.OnchainKeyring), + args.ReportingPluginFactory, + ) +} + +// OCR3OracleArgs2 is like OCR3OracleArgs but accepts an OnchainKeyring2. +type OCR3OracleArgs2[RI any] struct { + BinaryNetworkEndpointFactory types.BinaryNetworkEndpointFactory + V2Bootstrappers []commontypes.BootstrapperLocator + ContractConfigTracker types.ContractConfigTracker + ContractTransmitter ocr3types.ContractTransmitter[RI] + Database ocr3types.Database + LocalConfig types.LocalConfig + Logger commontypes.Logger + MetricsRegisterer prometheus.Registerer + MonitoringEndpoint commontypes.MonitoringEndpoint + OffchainConfigDigester types.OffchainConfigDigester + OffchainKeyring types.OffchainKeyring + OnchainKeyring ocr3types.OnchainKeyring2[RI] + ReportingPluginFactory ocr3types.ReportingPluginFactory[RI] +} + +func (OCR3OracleArgs2[RI]) oracleArgsMarker() {} + +func (args OCR3OracleArgs2[RI]) localConfig() types.LocalConfig { return args.LocalConfig } + +func (args OCR3OracleArgs2[RI]) runManaged(ctx context.Context) { + logger := loghelper.MakeRootLoggerWithContext(args.Logger) + managed.RunManagedOCR3Oracle( ctx, @@ -302,6 +348,51 @@ func (args OCR3_1OracleArgs[RI]) localConfig() types.LocalConfig { return args.L func (args OCR3_1OracleArgs[RI]) runManaged(ctx context.Context) { logger := loghelper.MakeRootLoggerWithContext(args.Logger) + managed.RunManagedOCR3_1Oracle( + ctx, + + args.V2Bootstrappers, + args.ContractConfigTracker, + args.ContractTransmitter, + args.Database, + args.KeyValueDatabaseFactory, + args.LocalConfig, + logger, + args.MetricsRegisterer, + args.MonitoringEndpoint, + args.BinaryNetworkEndpointFactory, + args.OffchainConfigDigester, + args.OffchainKeyring, + ocr3shims.OnchainKeyringAsOnchainKeyring2(args.OnchainKeyring), + args.ReportingPluginFactory, + ) +} + +// OCR3_1OracleArgs2 is like OCR3_1OracleArgs but accepts an OnchainKeyring2. +type OCR3_1OracleArgs2[RI any] struct { + BinaryNetworkEndpointFactory types.BinaryNetworkEndpoint2Factory + V2Bootstrappers []commontypes.BootstrapperLocator + ContractConfigTracker types.ContractConfigTracker + ContractTransmitter ocr3types.ContractTransmitter[RI] + Database ocr3_1types.Database + KeyValueDatabaseFactory ocr3_1types.KeyValueDatabaseFactory + LocalConfig types.LocalConfig + Logger commontypes.Logger + MetricsRegisterer prometheus.Registerer + MonitoringEndpoint commontypes.MonitoringEndpoint + OffchainConfigDigester types.OffchainConfigDigester + OffchainKeyring types.OffchainKeyring + OnchainKeyring ocr3types.OnchainKeyring2[RI] + ReportingPluginFactory ocr3_1types.ReportingPluginFactory[RI] +} + +func (OCR3_1OracleArgs2[RI]) oracleArgsMarker() {} + +func (args OCR3_1OracleArgs2[RI]) localConfig() types.LocalConfig { return args.LocalConfig } + +func (args OCR3_1OracleArgs2[RI]) runManaged(ctx context.Context) { + logger := loghelper.MakeRootLoggerWithContext(args.Logger) + managed.RunManagedOCR3_1Oracle( ctx, diff --git a/offchainreporting2plus/types/types.go b/offchainreporting2plus/types/types.go index 859c8785..2b9ccff6 100644 --- a/offchainreporting2plus/types/types.go +++ b/offchainreporting2plus/types/types.go @@ -155,6 +155,10 @@ type ReportingPluginConfig struct { MaxDurationReport time.Duration MaxDurationShouldAcceptFinalizedReport time.Duration MaxDurationShouldTransmitAcceptedReport time.Duration + + // The duration until all transmitters had at least one stage to transmit. + // Computed based on the schedule and the actual number of oracles. + DurationAllTransmissionStages time.Duration } // A ReportingPlugin allows plugging custom logic into the OCR protocol. The OCR @@ -377,10 +381,13 @@ type ContractConfigTracker interface { Notify() <-chan struct{} // LatestConfigDetails returns information about the latest configuration, - // but not the configuration itself. + // but not the configuration itself. When no configuration has been set, + // should return (0, ConfigDigest{}, nil). LatestConfigDetails(ctx context.Context) (changedInBlock uint64, configDigest ConfigDigest, err error) - // LatestConfig returns the latest configuration. + // LatestConfig returns the latest configuration. If no configuration has + // been set inside the block specified by changedInBlock, should return an + // error. LatestConfig(ctx context.Context, changedInBlock uint64) (ContractConfig, error) // LatestBlockHeight returns the height of the most recent block in the chain.