diff --git a/deployment/go.mod b/deployment/go.mod index f40142f2232..06d7ad04918 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -9,7 +9,7 @@ replace github.com/smartcontractkit/chainlink/v2 => ../ // Using a separate inline `require` here to avoid surrounding line changes // creating potential merge conflicts. -require github.com/smartcontractkit/chainlink/v2 v2.0.0-20241212011003-de1a8f5e5b42 +require github.com/smartcontractkit/chainlink/v2 v2.0.0-20250113180450-c33ab50ac8c0 require ( github.com/Khan/genqlient v0.7.0 diff --git a/deployment/keystone/changeset/compatiblity.go b/deployment/keystone/changeset/compatiblity.go index 7f80b6ab53d..67b799a02ce 100644 --- a/deployment/keystone/changeset/compatiblity.go +++ b/deployment/keystone/changeset/compatiblity.go @@ -89,6 +89,8 @@ type ConfigureContractsResponse = internal.ConfigureContractsResponse // in is in a convenient form to handle the CLO representation of the nop data type DonCapabilities = internal.DonCapabilities +type DONCapabilityWithConfig = internal.DONCapabilityWithConfig + type DeployRequest = internal.DeployRequest type DeployResponse = internal.DeployResponse diff --git a/deployment/keystone/changeset/internal/deploy.go b/deployment/keystone/changeset/internal/deploy.go index e785b6dc161..8b67013aa15 100644 --- a/deployment/keystone/changeset/internal/deploy.go +++ b/deployment/keystone/changeset/internal/deploy.go @@ -15,25 +15,17 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "golang.org/x/exp/maps" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" - chainsel "github.com/smartcontractkit/chain-selectors" - capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" - "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "golang.org/x/exp/maps" + "google.golang.org/protobuf/proto" + "github.com/smartcontractkit/chainlink/deployment" capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" ) type ConfigureContractsRequest struct { @@ -142,7 +134,7 @@ type DonInfo struct { Name string F uint8 Nodes []deployment.Node - Capabilities []capabilities_registry.CapabilitiesRegistryCapability // every capability is hosted on each node + Capabilities []DONCapabilityWithConfig // every capability is hosted on each node } func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, error) { @@ -415,7 +407,7 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C type RegisterCapabilitiesRequest struct { Env *deployment.Environment RegistryChainSelector uint64 - DonToCapabilities map[string][]capabilities_registry.CapabilitiesRegistryCapability + DonToCapabilities map[string][]DONCapabilityWithConfig // if UseMCMS is true, a batch proposal is returned and no transaction is confirmed on chain. UseMCMS bool @@ -428,21 +420,26 @@ type RegisterCapabilitiesResponse struct { type RegisteredCapability struct { capabilities_registry.CapabilitiesRegistryCapability - ID [32]byte + ID [32]byte + Config *capabilitiespb.CapabilityConfig } -func FromCapabilitiesRegistryCapability(cap *capabilities_registry.CapabilitiesRegistryCapability, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { +func FromCapabilitiesRegistryCapability(capReg *capabilities_registry.CapabilitiesRegistryCapability, cfg *capabilitiespb.CapabilityConfig, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { registry, _, err := GetRegistryContract(&e, registryChainSelector) if err != nil { return nil, fmt.Errorf("failed to get registry: %w", err) } - id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, capReg.LabelledName, capReg.Version) if err != nil { - return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) + return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", capReg, err) + } + if cfg == nil { + return nil, fmt.Errorf("config is required for capability %v", capReg) } return &RegisteredCapability{ - CapabilitiesRegistryCapability: *cap, + CapabilitiesRegistryCapability: *capReg, ID: id, + Config: cfg, }, nil } @@ -468,29 +465,31 @@ func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) ( uniqueCaps := make(map[capabilities_registry.CapabilitiesRegistryCapability][32]byte) for don, caps := range req.DonToCapabilities { var registerCaps []RegisteredCapability - for _, cap := range caps { - id, ok := uniqueCaps[cap] + for i := range caps { + regCap := &caps[i] + id, ok := uniqueCaps[regCap.Capability] if !ok { var err error - id, err = registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + id, err = registry.GetHashedCapabilityId(&bind.CallOpts{}, regCap.Capability.LabelledName, regCap.Capability.Version) if err != nil { - return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) + return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", regCap, err) } - uniqueCaps[cap] = id + uniqueCaps[regCap.Capability] = id } registerCap := RegisteredCapability{ - CapabilitiesRegistryCapability: cap, ID: id, + Config: regCap.Config, + CapabilitiesRegistryCapability: regCap.Capability, } - lggr.Debugw("hashed capability id", "capability", cap, "id", id) + lggr.Debugw("hashed capability id", "capability", regCap, "id", id) registerCaps = append(registerCaps, registerCap) } resp.DonToCapabilities[don] = registerCaps } var capabilities []capabilities_registry.CapabilitiesRegistryCapability - for cap := range uniqueCaps { - capabilities = append(capabilities, cap) + for uniqueCap := range uniqueCaps { + capabilities = append(capabilities, uniqueCap) } if len(capabilities) == 0 { lggr.Warn("no new capabilities to register") @@ -615,41 +614,6 @@ func addNOPsMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, n }, nil } -func DefaultCapConfig(capType uint8, nNodes int) *capabilitiespb.CapabilityConfig { - switch capType { - // TODO: use the enum defined in ?? - case uint8(0): // trigger - return &capabilitiespb.CapabilityConfig{ - DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), - RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ - RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ - RegistrationRefresh: durationpb.New(20 * time.Second), - RegistrationExpiry: durationpb.New(60 * time.Second), - // F + 1; assuming n = 3f+1 - MinResponsesToAggregate: uint32(nNodes/3) + 1, - }, - }, - } - case uint8(2): // consensus - return &capabilitiespb.CapabilityConfig{ - DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), - } - case uint8(3): // target - return &capabilitiespb.CapabilityConfig{ - DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), - RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ - RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ - RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, // TODO: const defn in a common place - }, - }, - } - default: - return &capabilitiespb.CapabilityConfig{ - DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), - } - } -} - // register nodes type RegisterNodesRequest struct { Env *deployment.Environment @@ -916,26 +880,26 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes } lggr.Debugw("registering DON", "don", don.Name, "p2p sorted hash", p2pSortedHash) - - caps, ok := req.DonToCapabilities[don.Name] + regCaps, ok := req.DonToCapabilities[don.Name] if !ok { return nil, fmt.Errorf("capabilities not found for DON %s", don.Name) } wfSupported := false var cfgs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration - for _, cap := range caps { - if cap.CapabilityType == 2 { // OCR3 capability => WF supported + for _, regCap := range regCaps { + if regCap.CapabilityType == 2 { // OCR3 capability => WF supported wfSupported = true } - // TODO: accept configuration from external source for each (don,capability) - capCfg := DefaultCapConfig(cap.CapabilityType, len(p2pIds)) - cfgb, err := proto.Marshal(capCfg) - if err != nil { - return nil, fmt.Errorf("failed to marshal capability config for %v: %w", cap, err) + if regCap.Config == nil { + return nil, fmt.Errorf("config not found for capability %v", regCap) + } + cfgB, capErr := proto.Marshal(regCap.Config) + if capErr != nil { + return nil, fmt.Errorf("failed to marshal config for capability %v: %w", regCap, capErr) } cfgs = append(cfgs, capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - CapabilityId: cap.ID, - Config: cfgb, + CapabilityId: regCap.ID, + Config: cfgB, }) } diff --git a/deployment/keystone/changeset/internal/deploy_test.go b/deployment/keystone/changeset/internal/deploy_test.go index b8a98207ea0..c059cd5a981 100644 --- a/deployment/keystone/changeset/internal/deploy_test.go +++ b/deployment/keystone/changeset/internal/deploy_test.go @@ -4,13 +4,14 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - - "github.com/stretchr/testify/require" ) func Test_RegisterNOPS(t *testing.T) { diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/internal/test/utils.go index cc7e3b27160..290d0ee2196 100644 --- a/deployment/keystone/changeset/internal/test/utils.go +++ b/deployment/keystone/changeset/internal/test/utils.go @@ -5,10 +5,12 @@ import ( "fmt" "sort" "testing" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -16,7 +18,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -211,25 +212,26 @@ func (cc *CapabilityCache) Get(cap capabilities_registry.CapabilitiesRegistryCap // AddCapabilities adds the capabilities to the registry and returns the registered capabilities // if the capability is already registered, it will not be re-registered // if duplicate capabilities are passed, they will be deduped -func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capabilities []capabilities_registry.CapabilitiesRegistryCapability) []internal.RegisteredCapability { +func (cc *CapabilityCache) AddCapabilities(_ logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capabilities []capabilities_registry.CapabilitiesRegistryCapability) []internal.RegisteredCapability { t := cc.t var out []internal.RegisteredCapability // get the registered capabilities & dedup seen := make(map[capabilities_registry.CapabilitiesRegistryCapability]struct{}) var toRegister []capabilities_registry.CapabilitiesRegistryCapability - for _, cap := range capabilities { - id, cached := cc.nameToId[internal.CapabilityID(cap)] + for _, c := range capabilities { + id, cached := cc.nameToId[internal.CapabilityID(c)] if cached { out = append(out, internal.RegisteredCapability{ - CapabilitiesRegistryCapability: cap, + CapabilitiesRegistryCapability: c, ID: id, + Config: GetDefaultCapConfig(t, c), }) continue } // dedup - if _, exists := seen[cap]; !exists { - seen[cap] = struct{}{} - toRegister = append(toRegister, cap) + if _, exists := seen[c]; !exists { + seen[c] = struct{}{} + toRegister = append(toRegister, c) } } if len(toRegister) == 0 { @@ -251,6 +253,7 @@ func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment. out = append(out, internal.RegisteredCapability{ CapabilitiesRegistryCapability: capb, ID: id, + Config: GetDefaultCapConfig(t, capb), }) // cache the id cc.nameToId[internal.CapabilityID(capb)] = id @@ -294,3 +297,29 @@ func MustCapabilityId(t *testing.T, registry *capabilities_registry.Capabilities require.NoError(t, err) return id } + +func GetDefaultCapConfig(t *testing.T, capability capabilities_registry.CapabilitiesRegistryCapability) *capabilitiespb.CapabilityConfig { + t.Helper() + defaultCfg := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + } + switch capability.CapabilityType { + case uint8(0): // trigger + defaultCfg.RemoteConfig = &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(20 * time.Second), + RegistrationExpiry: durationpb.New(60 * time.Second), + MinResponsesToAggregate: uint32(10), + }, + } + case uint8(3): // target + defaultCfg.RemoteConfig = &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ + RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ + RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, + }, + } + case uint8(2): // consensus + default: + } + return defaultCfg +} diff --git a/deployment/keystone/changeset/internal/types.go b/deployment/keystone/changeset/internal/types.go index cffd69f85e6..c4e9deccdf9 100644 --- a/deployment/keystone/changeset/internal/types.go +++ b/deployment/keystone/changeset/internal/types.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/common" + capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" chainsel "github.com/smartcontractkit/chain-selectors" @@ -131,7 +132,12 @@ type DonCapabilities struct { Name string F uint8 Nops []NOP - Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each nop + Capabilities []DONCapabilityWithConfig // every capability is hosted on each nop +} + +type DONCapabilityWithConfig struct { + Capability kcr.CapabilitiesRegistryCapability + Config *capabilitiespb.CapabilityConfig } func (v DonCapabilities) Validate() error { @@ -195,8 +201,8 @@ func nopsToNodes(donInfos []DonInfo, dons []DonCapabilities, chainSelector uint6 } // mapDonsToCaps converts a list of DonCapabilities to a map of don name to capabilities -func mapDonsToCaps(dons []DonInfo) map[string][]kcr.CapabilitiesRegistryCapability { - out := make(map[string][]kcr.CapabilitiesRegistryCapability) +func mapDonsToCaps(dons []DonInfo) map[string][]DONCapabilityWithConfig { + out := make(map[string][]DONCapabilityWithConfig) for _, don := range dons { out[don.Name] = don.Capabilities } diff --git a/deployment/keystone/changeset/internal/update_don.go b/deployment/keystone/changeset/internal/update_don.go index aa3e203e5e4..b5006358f77 100644 --- a/deployment/keystone/changeset/internal/update_don.go +++ b/deployment/keystone/changeset/internal/update_don.go @@ -11,15 +11,14 @@ import ( "sort" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "google.golang.org/protobuf/proto" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + "github.com/smartcontractkit/chainlink/deployment" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) // CapabilityConfig is a struct that holds a capability and its configuration @@ -71,7 +70,7 @@ type UpdateDonResponse struct { Ops *timelock.BatchChainOperation } -func UpdateDon(lggr logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, error) { +func UpdateDon(_ logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, error) { if err := req.Validate(); err != nil { return nil, fmt.Errorf("failed to validate request: %w", err) } @@ -86,7 +85,7 @@ func UpdateDon(lggr logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, e if err != nil { return nil, fmt.Errorf("failed to lookup don by p2pIDs: %w", err) } - cfgs, err := computeConfigs(registry, req.CapabilityConfigs, don) + cfgs, err := computeConfigs(registry, req.CapabilityConfigs) if err != nil { return nil, fmt.Errorf("failed to compute configs: %w", err) } @@ -140,22 +139,18 @@ func BytesToPeerIDs(p2pIDs [][32]byte) []p2pkey.PeerID { return out } -func computeConfigs(registry *kcr.CapabilitiesRegistry, caps []CapabilityConfig, donInfo kcr.CapabilitiesRegistryDONInfo) ([]kcr.CapabilitiesRegistryCapabilityConfiguration, error) { - out := make([]kcr.CapabilitiesRegistryCapabilityConfiguration, len(caps)) - for i, cap := range caps { +func computeConfigs(registry *kcr.CapabilitiesRegistry, capCfgs []CapabilityConfig) ([]kcr.CapabilitiesRegistryCapabilityConfiguration, error) { + out := make([]kcr.CapabilitiesRegistryCapabilityConfiguration, len(capCfgs)) + for i, capCfg := range capCfgs { out[i] = kcr.CapabilitiesRegistryCapabilityConfiguration{} - id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.Capability.LabelledName, cap.Capability.Version) + id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, capCfg.Capability.LabelledName, capCfg.Capability.Version) if err != nil { return nil, fmt.Errorf("failed to get capability id: %w", err) } out[i].CapabilityId = id + out[i].Config = capCfg.Config if out[i].Config == nil { - c := DefaultCapConfig(cap.Capability.CapabilityType, int(donInfo.F)) - cb, err := proto.Marshal(c) - if err != nil { - return nil, fmt.Errorf("failed to marshal capability config for %v: %w", c, err) - } - out[i].Config = cb + return nil, fmt.Errorf("config is required for capability %s", capCfg.Capability.LabelledName) } } return out, nil diff --git a/deployment/keystone/changeset/internal/update_don_test.go b/deployment/keystone/changeset/internal/update_don_test.go index bf9ab96fecb..42b032d9433 100644 --- a/deployment/keystone/changeset/internal/update_don_test.go +++ b/deployment/keystone/changeset/internal/update_don_test.go @@ -13,8 +13,10 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" kscs "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" @@ -95,6 +97,13 @@ func TestUpdateDon(t *testing.T) { } ) + initialCapCfg := kstest.GetDefaultCapConfig(t, initialCap) + initialCapCfgB, err := proto.Marshal(initialCapCfg) + require.NoError(t, err) + capToAddCfg := kstest.GetDefaultCapConfig(t, capToAdd) + capToAddCfgB, err := proto.Marshal(capToAddCfg) + require.NoError(t, err) + lggr := logger.Test(t) t.Run("empty", func(t *testing.T) { @@ -103,7 +112,7 @@ func TestUpdateDon(t *testing.T) { { Name: "don 1", Nodes: []deployment.Node{node_1, node_2, node_3, node_4}, - Capabilities: []kcr.CapabilitiesRegistryCapability{initialCap}, + Capabilities: []internal.DONCapabilityWithConfig{{Capability: initialCap, Config: initialCapCfg}}, }, }, nops: []internal.NOP{ @@ -133,7 +142,7 @@ func TestUpdateDon(t *testing.T) { Chain: testCfg.Chain, P2PIDs: []p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()}, CapabilityConfigs: []internal.CapabilityConfig{ - {Capability: initialCap}, {Capability: capToAdd}, + {Capability: initialCap, Config: initialCapCfgB}, {Capability: capToAdd, Config: capToAddCfgB}, }, } want := &internal.UpdateDonResponse{ @@ -142,8 +151,8 @@ func TestUpdateDon(t *testing.T) { ConfigCount: 1, NodeP2PIds: internal.PeerIDsToBytes([]p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()}), CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, initialCap)}, - {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, capToAdd)}, + {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, initialCap), Config: initialCapCfgB}, + {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, capToAdd), Config: capToAddCfgB}, }, }, } @@ -286,7 +295,7 @@ func makeP2PToCapabilities(t *testing.T, dons []internal.DonInfo) map[p2pkey.Pee for _, cap := range don.Capabilities { p, err := kscs.NewP2PSignerEnc(&node, registryChain.Selector) require.NoError(t, err, "failed to make p2p signer enc from clo nod %s", node.NodeID) - p2pToCapabilities[p.P2PKey] = append(p2pToCapabilities[p.P2PKey], cap) + p2pToCapabilities[p.P2PKey] = append(p2pToCapabilities[p.P2PKey], cap.Capability) } } } @@ -312,9 +321,12 @@ func testDon(t *testing.T, don internal.DonInfo) kstest.Don { } var capabilityConfigs []internal.CapabilityConfig - for _, cap := range don.Capabilities { + for i := range don.Capabilities { + donCap := &don.Capabilities[i] + cfg, err := proto.Marshal(donCap.Config) + require.NoError(t, err) capabilityConfigs = append(capabilityConfigs, internal.CapabilityConfig{ - Capability: cap, + Capability: donCap.Capability, Config: cfg, }) } return kstest.Don{ diff --git a/deployment/keystone/changeset/internal/update_nodes_test.go b/deployment/keystone/changeset/internal/update_nodes_test.go index 1b532129e48..c564e87c2de 100644 --- a/deployment/keystone/changeset/internal/update_nodes_test.go +++ b/deployment/keystone/changeset/internal/update_nodes_test.go @@ -7,19 +7,22 @@ import ( "fmt" "sort" "testing" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/durationpb" + capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" - - "github.com/smartcontractkit/chainlink/deployment/environment/memory" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -448,6 +451,17 @@ func TestUpdateNodes(t *testing.T) { Version: "1.0.0", CapabilityType: 0, } + phonyCapCfg := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(20 * time.Second), + RegistrationExpiry: durationpb.New(60 * time.Second), + // F + 1; assuming n = 3f+1 + MinResponsesToAggregate: uint32(10), + }, + }, + } initMap := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) for p2pID := range tt.args.req.P2pToUpdates { initMap[p2pID] = []kcr.CapabilitiesRegistryCapability{phonyCap} @@ -472,7 +486,7 @@ func TestUpdateNodes(t *testing.T) { expectedUpdatedCaps[p2p] = expectedCaps } else { expectedUpdatedCaps[p2p] = []internal.RegisteredCapability{ - {CapabilitiesRegistryCapability: phonyCap, ID: id}, + {CapabilitiesRegistryCapability: phonyCap, ID: id, Config: phonyCapCfg}, } } } diff --git a/deployment/keystone/changeset/test/helpers.go b/deployment/keystone/changeset/test/helpers.go index 5ddaeda524e..c0b7d9a0d67 100644 --- a/deployment/keystone/changeset/test/helpers.go +++ b/deployment/keystone/changeset/test/helpers.go @@ -24,6 +24,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/environment/memory" kschangeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -150,6 +151,10 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, c.AssetDonConfig.N, 0, crConfig) require.Len(t, assetNodes, c.AssetDonConfig.N) + ocr3CapCfg := kstest.GetDefaultCapConfig(t, internal.OCR3Cap) + writerChainCapCfg := kstest.GetDefaultCapConfig(t, internal.WriteChainCap) + streamTriggerChainCapCfg := kstest.GetDefaultCapConfig(t, internal.StreamTriggerCap) + // TODO: partition nodes into multiple nops wfDon := internal.DonCapabilities{ @@ -160,7 +165,9 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { Nodes: maps.Keys(wfNodes), }, }, - Capabilities: []kcr.CapabilitiesRegistryCapability{internal.OCR3Cap}, + Capabilities: []internal.DONCapabilityWithConfig{ + {Capability: internal.OCR3Cap, Config: ocr3CapCfg}, + }, } cwDon := internal.DonCapabilities{ Name: internal.TargetDonName, @@ -170,7 +177,9 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { Nodes: maps.Keys(cwNodes), }, }, - Capabilities: []kcr.CapabilitiesRegistryCapability{internal.WriteChainCap}, + Capabilities: []internal.DONCapabilityWithConfig{ + {Capability: internal.WriteChainCap, Config: writerChainCapCfg}, + }, } assetDon := internal.DonCapabilities{ Name: internal.StreamDonName, @@ -180,7 +189,9 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { Nodes: maps.Keys(assetNodes), }, }, - Capabilities: []kcr.CapabilitiesRegistryCapability{internal.StreamTriggerCap}, + Capabilities: []internal.DONCapabilityWithConfig{ + {Capability: internal.StreamTriggerCap, Config: streamTriggerChainCapCfg}, + }, } allChains := make(map[uint64]deployment.Chain) @@ -372,8 +383,8 @@ func p2pIDs(t *testing.T, vals []string) [][32]byte { func expectedHashedCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, don internal.DonCapabilities) [][32]byte { out := make([][32]byte, len(don.Capabilities)) var err error - for i, cap := range don.Capabilities { - out[i], err = registry.GetHashedCapabilityId(nil, cap.LabelledName, cap.Version) + for i, capWithCfg := range don.Capabilities { + out[i], err = registry.GetHashedCapabilityId(nil, capWithCfg.Capability.LabelledName, capWithCfg.Capability.Version) require.NoError(t, err) } return out diff --git a/deployment/keystone/changeset/update_don_test.go b/deployment/keystone/changeset/update_don_test.go index 74e2609b0a1..3fadb7822e2 100644 --- a/deployment/keystone/changeset/update_don_test.go +++ b/deployment/keystone/changeset/update_don_test.go @@ -5,11 +5,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + internaltest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -29,6 +31,13 @@ func TestUpdateDon(t *testing.T) { } caps = []kcr.CapabilitiesRegistryCapability{capA, capB} ) + capACfg := internaltest.GetDefaultCapConfig(t, capA) + capACfgB, err := proto.Marshal(capACfg) + require.NoError(t, err) + capBCfg := internaltest.GetDefaultCapConfig(t, capB) + capBCfgB, err := proto.Marshal(capBCfg) + require.NoError(t, err) + t.Run("no mcms", func(t *testing.T) { te := test.SetupTestEnv(t, test.TestConfig{ WFDonConfig: test.DonConfig{N: 4}, @@ -54,10 +63,10 @@ func TestUpdateDon(t *testing.T) { P2PIDs: p2pIDs, CapabilityConfigs: []changeset.CapabilityConfig{ { - Capability: capA, + Capability: capA, Config: capACfgB, }, { - Capability: capB, + Capability: capB, Config: capBCfgB, }, }, } @@ -94,9 +103,11 @@ func TestUpdateDon(t *testing.T) { CapabilityConfigs: []changeset.CapabilityConfig{ { Capability: capA, + Config: capACfgB, }, { Capability: capB, + Config: capBCfgB, }, }, MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 02580d20de9..a4e072b8309 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -13,7 +13,7 @@ replace github.com/smartcontractkit/chainlink/deployment => ../deployment // creating potential merge conflicts. require ( github.com/smartcontractkit/chainlink/deployment v0.0.0-20241212011003-de1a8f5e5b42 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241212011003-de1a8f5e5b42 + github.com/smartcontractkit/chainlink/v2 v2.0.0-20250113180450-c33ab50ac8c0 ) require ( diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 5e4cbf4d820..3e3a191f36d 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ replace github.com/smartcontractkit/chainlink/integration-tests => ../ require ( github.com/smartcontractkit/chainlink/deployment v0.0.0-20241212011003-de1a8f5e5b42 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241212011003-de1a8f5e5b42 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241212011003-de1a8f5e5b42 + github.com/smartcontractkit/chainlink/v2 v2.0.0-20250113180450-c33ab50ac8c0 ) require (