diff --git a/pkg/capabilities/consensus/ocr3/types/ocr3_types.proto b/pkg/capabilities/consensus/ocr3/types/ocr3_types.proto index a3cb2a9ffe..f1e331200c 100644 --- a/pkg/capabilities/consensus/ocr3/types/ocr3_types.proto +++ b/pkg/capabilities/consensus/ocr3/types/ocr3_types.proto @@ -6,6 +6,7 @@ package ocr3_types; import "values/v1/values.proto"; import "google/protobuf/timestamp.proto"; +import "capabilities/consensus/ocr3/datafeeds/data_feeds_types.proto"; // per-workflow aggregation outcome message AggregationOutcome { @@ -16,6 +17,11 @@ message AggregationOutcome { google.protobuf.Timestamp timestamp = 5; // current time of the node string encoderName = 6; // optional dynamic encoder override values.v1.Map encoderConfig = 7; // optional dynamic encoder config + oneof typed_metadata { + datafeeds_types.DataFeedsOutcomeMetadata data_feeds_metadata = 8; + datafeeds_types.LLOOutcomeMetadata llo_metadata = 9; + values.v1.Map reduce_metadata = 10; + } } message Query { @@ -37,18 +43,14 @@ message Id { message Observation { Id id = 1; - // list of observations defined in inputs.observations values.v1.List observations = 4; string overriddenEncoderName = 5; values.v1.Map overriddenEncoderConfig = 6; } message Observations { - // batched observations for multiple workflow execution IDs repeated Observation observations = 1; - // the workflow IDs that are registered in the node repeated string registeredWorkflowIds = 2; - // the node's current current time google.protobuf.Timestamp timestamp = 3; } diff --git a/pkg/capabilities/consensus/ocr3/types/typed_metadata.go b/pkg/capabilities/consensus/ocr3/types/typed_metadata.go new file mode 100644 index 0000000000..03cd68ad63 --- /dev/null +++ b/pkg/capabilities/consensus/ocr3/types/typed_metadata.go @@ -0,0 +1,72 @@ +package types + +/* +import ( + "google.golang.org/protobuf/proto" + + datafeeds "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/datafeeds" + "github.com/smartcontractkit/chainlink-protos/cre/go/values" +) + +type MetadataType int + +const ( + MetadataTypeUnknown MetadataType = iota + MetadataTypeDataFeeds + MetadataTypeLLO + MetadataTypeReduce +) + +func PopulateTypedMetadata(outcome *AggregationOutcome, mdType MetadataType) { + if outcome == nil || len(outcome.Metadata) == 0 { + return + } + + switch mdType { + case MetadataTypeDataFeeds: + var md datafeeds.DataFeedsOutcomeMetadata + if err := proto.Unmarshal(outcome.Metadata, &md); err == nil { + outcome.TypedMetadata = &AggregationOutcome_DataFeedsMetadata{ + DataFeedsMetadata: &md, + } + } + case MetadataTypeLLO: + var md datafeeds.LLOOutcomeMetadata + if err := proto.Unmarshal(outcome.Metadata, &md); err == nil { + outcome.TypedMetadata = &AggregationOutcome_LloMetadata{ + LloMetadata: &md, + } + } + case MetadataTypeReduce: + pb := &values.Map{} + if err := proto.Unmarshal(outcome.Metadata, pb); err == nil { + outcome.TypedMetadata = &AggregationOutcome_ReduceMetadata{ + ReduceMetadata: pb, + } + } + } +} + +func ExtractTypedMetadata(outcome *AggregationOutcome) (proto.Message, MetadataType) { + if outcome == nil { + return nil, MetadataTypeUnknown + } + + switch tm := outcome.TypedMetadata.(type) { + case *AggregationOutcome_DataFeedsMetadata: + if tm.DataFeedsMetadata != nil { + return tm.DataFeedsMetadata, MetadataTypeDataFeeds + } + case *AggregationOutcome_LloMetadata: + if tm.LloMetadata != nil { + return tm.LloMetadata, MetadataTypeLLO + } + case *AggregationOutcome_ReduceMetadata: + if tm.ReduceMetadata != nil { + return tm.ReduceMetadata, MetadataTypeReduce + } + } + + return nil, MetadataTypeUnknown +} +*/ diff --git a/pkg/capabilities/pb/capabilities.proto b/pkg/capabilities/pb/capabilities.proto index b14897247e..b4868d33b7 100644 --- a/pkg/capabilities/pb/capabilities.proto +++ b/pkg/capabilities/pb/capabilities.proto @@ -10,6 +10,10 @@ import "google/protobuf/any.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; +import "capabilities/blockchain/evm/v1alpha/client.proto"; +import "capabilities/blockchain/solana/v1alpha/client.proto"; +import "capabilities/actions/vault/messages.proto"; + service BaseCapability { rpc Info (google.protobuf.Empty) returns (CapabilityInfoReply) {} } @@ -58,42 +62,48 @@ message RequestMetadata { message CapabilityRequest { RequestMetadata metadata = 1; - // Used for DAG SDK values.v1.Map config = 2; - // Used for DAG SDK values.v1.Map inputs = 3; - // Used for no DAG SDK google.protobuf.Any payload = 4; - // Used for no DAG SDK google.protobuf.Any configPayload = 5; - // Used for no DAG SDK string method = 6; string capabilityId = 7; + + oneof typed_payload { + capabilities.blockchain.evm.v1alpha.WriteReportRequest evm_write_report_request = 8; + capabilities.blockchain.solana.v1alpha.WriteReportRequest solana_write_report_request = 10; + vault.GetSecretsRequest vault_get_secrets_request = 11; + } } message TriggerRegistrationRequest { string triggerId = 1; RequestMetadata metadata = 2; - // Used for DAG SDK values.v1.Map config = 3; - // Used for no DAG SDK google.protobuf.Any payload = 4; - // Used for no DAG SDK string method = 5; + + oneof typed_payload { + capabilities.blockchain.evm.v1alpha.WriteReportRequest evm_write_report_request = 6; + capabilities.blockchain.solana.v1alpha.WriteReportRequest solana_write_report_request = 7; + } } message TriggerEvent { - reserved 5; // Previously used for v1.OCRTriggerEvent + reserved 5; string triggerType = 1; string id = 2; - // Used for DAG SDK values.v1.Map outputs = 4; - // used for no DAG SDK google.protobuf.Any payload = 6; + + oneof typed_payload { + capabilities.blockchain.evm.v1alpha.WriteReportRequest evm_write_report_request = 7; + capabilities.blockchain.solana.v1alpha.WriteReportRequest solana_write_report_request = 8; + } } message TriggerResponse { @@ -109,7 +119,7 @@ message TriggerResponseMessage { } message AckEventRequest { - string trigger_id = 1; // triggerID is unique per workflow as it contains the workflowID + string trigger_id = 1; string event_id = 2; string method = 3; } @@ -122,27 +132,21 @@ service TriggerExecutable { } message CapabilityResponse { - // Used for DAG SDK values.v1.Map value = 1; string error = 2; ResponseMetadata metadata = 3; - // Used for no DAG SDK google.protobuf.Any payload = 4; optional OCRAttestation ocr_attestation = 5; + + oneof typed_payload { + capabilities.blockchain.evm.v1alpha.WriteReportRequest evm_write_report_request = 6; + capabilities.blockchain.solana.v1alpha.WriteReportRequest solana_write_report_request = 7; + vault.GetSecretsResponse vault_get_secrets_response = 8; + } } message ResponseMetadata { - // MeteringReportNodeDetail is repeated here due to - // the identical response aggregation strategy at the Don2Don layer. - // We expect identical responses from capabilities, but not identical - // metering reports. Since we pass the CapabilityResponse through the - // protocol layer to the engine, this field needs to be repeated to - // eventually hold all the reports from each capability response node. - // - // If you are working with this in a capability, you should not emit - // more than one metering report per node. repeated metering.MeteringReportNodeDetail metering = 1; - // capdon_n represents the total number of nodes in a capability don. uint32 capdon_n = 2; } @@ -209,6 +213,6 @@ service Settings { } message SettingsUpdate { - string settings = 1; // default format TOML - string hash = 2; // default sha256 + string settings = 1; + string hash = 2; } diff --git a/pkg/capabilities/pb/typed_payload.go b/pkg/capabilities/pb/typed_payload.go new file mode 100644 index 0000000000..4b353bdfe0 --- /dev/null +++ b/pkg/capabilities/pb/typed_payload.go @@ -0,0 +1,99 @@ +package pb + +/* +import ( + "google.golang.org/protobuf/types/known/anypb" + + evmcappb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/chain-capabilities/evm" + solcappb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/chain-capabilities/solana" + vault "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" +) + +func PopulateTypedPayload(req *CapabilityRequest) { + if req == nil || req.Payload == nil { + return + } + + if req.TypedPayload != nil { + return + } + + switch req.Payload.GetTypeUrl() { + case "type.googleapis.com/capabilities.blockchain.evm.v1alpha.WriteReportRequest": + var msg evmcappb.WriteReportRequest + if err := req.Payload.UnmarshalTo(&msg); err == nil { + req.TypedPayload = &CapabilityRequest_EvmWriteReportRequest{ + EvmWriteReportRequest: &msg, + } + } + case "type.googleapis.com/capabilities.blockchain.solana.v1alpha.WriteReportRequest": + var msg solcappb.WriteReportRequest + if err := req.Payload.UnmarshalTo(&msg); err == nil { + req.TypedPayload = &CapabilityRequest_SolanaWriteReportRequest{ + SolanaWriteReportRequest: &msg, + } + } + case "type.googleapis.com/vault.GetSecretsRequest": + var msg vault.GetSecretsRequest + if err := req.Payload.UnmarshalTo(&msg); err == nil { + req.TypedPayload = &CapabilityRequest_VaultGetSecretsRequest{ + VaultGetSecretsRequest: &msg, + } + } + } +} + +func ExtractTypedPayload(req *CapabilityRequest) { + if req == nil { + return + } + + switch tp := req.TypedPayload.(type) { + case *CapabilityRequest_EvmWriteReportRequest: + if tp.EvmWriteReportRequest != nil && req.Payload == nil { + req.Payload, _ = anypb.New(tp.EvmWriteReportRequest) + } + case *CapabilityRequest_SolanaWriteReportRequest: + if tp.SolanaWriteReportRequest != nil && req.Payload == nil { + req.Payload, _ = anypb.New(tp.SolanaWriteReportRequest) + } + case *CapabilityRequest_VaultGetSecretsRequest: + if tp.VaultGetSecretsRequest != nil && req.Payload == nil { + req.Payload, _ = anypb.New(tp.VaultGetSecretsRequest) + } + } +} + +func PopulateTypedResponsePayload(resp *CapabilityResponse) { + if resp == nil || resp.Payload == nil { + return + } + + if resp.TypedPayload != nil { + return + } + + switch resp.Payload.GetTypeUrl() { + case "type.googleapis.com/vault.GetSecretsResponse": + var msg vault.GetSecretsResponse + if err := resp.Payload.UnmarshalTo(&msg); err == nil { + resp.TypedPayload = &CapabilityResponse_VaultGetSecretsResponse{ + VaultGetSecretsResponse: &msg, + } + } + } +} + +func ExtractTypedResponsePayload(resp *CapabilityResponse) { + if resp == nil { + return + } + + switch tp := resp.TypedPayload.(type) { + case *CapabilityResponse_VaultGetSecretsResponse: + if tp.VaultGetSecretsResponse != nil && resp.Payload == nil { + resp.Payload, _ = anypb.New(tp.VaultGetSecretsResponse) + } + } +} +*/