From 502c6570c4ac87de3385a7f48e0697bb2d987416 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:40:58 -0600 Subject: [PATCH 01/37] wip: refactor ocr3 config in local env --- .../operations/contracts/configure_ocr3_op.go | 33 ++++---- system-tests/lib/cre/contracts/contracts.go | 83 +++++++++++++------ 2 files changed, 73 insertions(+), 43 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/configure_ocr3_op.go b/deployment/keystone/changeset/operations/contracts/configure_ocr3_op.go index bb8ad8eff47..510b9fc4a21 100644 --- a/deployment/keystone/changeset/operations/contracts/configure_ocr3_op.go +++ b/deployment/keystone/changeset/operations/contracts/configure_ocr3_op.go @@ -28,7 +28,7 @@ type ConfigureOCR3OpDeps struct { type ConfigureOCR3OpInput struct { ContractAddress *common.Address RegistryChainSel uint64 - DONs []ConfigureKeystoneDON + DON ConfigureKeystoneDON Config *ocr3.OracleConfig DryRun bool @@ -52,25 +52,20 @@ var ConfigureOCR3Op = operations.NewOperation[ConfigureOCR3OpInput, ConfigureOCR return ConfigureOCR3OpOutput{}, errors.New("ContractAddress is required") } - var nodeIDs []string - for _, don := range input.DONs { - donConfig := internal.RegisteredDonConfig{ - NodeIDs: don.NodeIDs, - Name: don.Name, - RegistryChainSel: input.RegistryChainSel, - Registry: deps.Registry, - } - d, err := internal.NewRegisteredDon(*deps.Env, donConfig) - if err != nil { - return ConfigureOCR3OpOutput{}, fmt.Errorf("configure-ocr3-op failed: failed to create registered DON %s: %w", don.Name, err) - } + donConfig := internal.RegisteredDonConfig{ + NodeIDs: input.DON.NodeIDs, + Name: input.DON.Name, + RegistryChainSel: input.RegistryChainSel, + Registry: deps.Registry, + } + d, err := internal.NewRegisteredDon(*deps.Env, donConfig) + if err != nil { + return ConfigureOCR3OpOutput{}, fmt.Errorf("configure-ocr3-op failed: failed to create registered DON %s: %w", input.DON.Name, err) + } - // We double-check that the DON accepts workflows... - if d.Info.AcceptsWorkflows { - for _, node := range d.Nodes { - nodeIDs = append(nodeIDs, node.NodeID) - } - } + nodeIDs := make([]string, 0, len(d.Nodes)) + for _, node := range d.Nodes { + nodeIDs = append(nodeIDs, node.NodeID) } resp, err := changeset.ConfigureOCR3Contract(*deps.Env, changeset.ConfigureOCR3Config{ diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index 3467b22e050..2649af228cf 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -31,12 +31,28 @@ import ( crenode "github.com/smartcontractkit/chainlink/system-tests/lib/cre/don/node" ) +type ocrDonCfg struct { + transmissionSchedule []int +} + +type donConfig struct { + keystone_changeset.DonCapabilities + // transmissionSchedule is the transmission schedule for the DON, if applicable + *ocrDonCfg +} + +var ocrDons map[string]ocrDonCfg // map of DON name to ocrDon struct + func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfigFns []cre.CapabilityRegistryConfigFn) error { + lggr := input.CldEnv.Logger + if err := input.Validate(); err != nil { return errors.Wrap(err, "input validation failed") } donCapabilities := make([]keystone_changeset.DonCapabilities, 0, len(input.Topology.DonsMetadata)) + d2 := make(map[string]donConfig) // map of DON name to donConfig struct + //ocrDons = make(map[string]ocrDonCfg) for donIdx, donMetadata := range input.Topology.DonsMetadata { // if it's only a gateway DON, we don't want to register it with the Capabilities Registry @@ -53,12 +69,12 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi continue } - capabilitiesFn, configFnErr := configFn(donMetadata.Flags, input.NodeSets[donIdx]) - if configFnErr != nil { - return errors.Wrap(configFnErr, "failed to get capabilities from config function") + enabledCapabilities, err2 := configFn(donMetadata.Flags, input.NodeSets[donIdx]) + if err2 != nil { + return errors.Wrap(err2, "failed to get capabilities from config function") } - capabilities = append(capabilities, capabilitiesFn...) + capabilities = append(capabilities, enabledCapabilities...) } workerNodes, workerNodesErr := crenode.FindManyWithLabel(donMetadata.NodesMetadata, &cre.Label{ @@ -98,34 +114,30 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi } donName := donMetadata.Name + "-don" - donCapabilities = append(donCapabilities, keystone_changeset.DonCapabilities{ + c := keystone_changeset.DonCapabilities{ Name: donName, F: libc.MustSafeUint8(forwarderF), Nops: []keystone_changeset.NOP{nop}, Capabilities: capabilities, - }) - } - - var transmissionSchedule []int - - for _, metaDon := range input.Topology.DonsMetadata { - if flags.HasFlag(metaDon.Flags, cre.ConsensusCapability) || flags.HasFlag(metaDon.Flags, cre.ConsensusCapabilityV2) { - workerNodes, workerNodesErr := crenode.FindManyWithLabel(metaDon.NodesMetadata, &cre.Label{ - Key: crenode.NodeTypeKey, - Value: cre.WorkerNode, - }, crenode.EqualLabels) - - if workerNodesErr != nil { - return errors.Wrap(workerNodesErr, "failed to find worker nodes") - } + } + donCapabilities = append(donCapabilities, c) + + ocrCfg, err := newOCRCfg(donMetadata) + if errors.Is(err, unsupportedDONTypeErr) { + // we simply skip DONs that do not support OCR3 + lggr.Warnw("skipping transmission schedule determination for DON that does not support OCR3", "donName", donMetadata.Name) + } else if err != nil { + return errors.Wrap(err, "failed to determine transmission schedule") + } - // this schedule makes sure that all worker nodes are transmitting OCR3 reports - transmissionSchedule = []int{len(workerNodes)} - break + d2[donName] = donConfig{ + DonCapabilities: c, + ocrDonCfg: ocrCfg, } } - if len(transmissionSchedule) == 0 { + // this can probably be removed, maintaining for compatibility for now + if len(ocrDons) == 0 { return errors.New("no OCR3-capable DON found in the topology") } @@ -333,6 +345,29 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi return nil } +var unsupportedDONTypeErr = errors.New("unsupported DON type for transmission schedule determination") + +func newOCRCfg(donMetadata *cre.DonMetadata) (*ocrDonCfg, error) { + // determine transmission schedule for OCR3-capable DONs + // todo extend and abstract this logic when we have for non-workflow DONs + if flags.HasFlag(donMetadata.Flags, cre.ConsensusCapability) || flags.HasFlag(donMetadata.Flags, cre.ConsensusCapabilityV2) { + workerNodes, workerNodesErr := crenode.FindManyWithLabel(donMetadata.NodesMetadata, &cre.Label{ + Key: crenode.NodeTypeKey, + Value: cre.WorkerNode, + }, crenode.EqualLabels) + + if workerNodesErr != nil { + return nil, errors.Wrap(workerNodesErr, "failed to find worker nodes") + } + + return &ocrDonCfg{ + transmissionSchedule: []int{len(workerNodes)}, + }, nil + } + return nil, unsupportedDONTypeErr + +} + // values supplied by Alexandr Yepishev as the expected values for OCR3 config func DefaultOCR3Config(topology *cre.Topology) (*keystone_changeset.OracleConfig, error) { var transmissionSchedule []int From 8c2bd51dbcf0a1ff0a9af3d81126e1bd1829a144 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Fri, 29 Aug 2025 19:59:06 -0600 Subject: [PATCH 02/37] start refactoring the setup of contracts --- .../contracts/deploy_contracts_seq.go | 50 ++++++++++++++ .../contracts/deploy_forwarders_seq.go | 3 +- .../lib/cre/environment/environment.go | 66 +++++++++++++++---- 3 files changed, 105 insertions(+), 14 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index cf7450a0ec2..740c65b4991 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -10,6 +10,10 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/operations" ) +type DeployContractsSequenceDeps struct { + Env *deployment.Environment +} + type DeployKeystoneContractsSequenceDeps struct { Env *deployment.Environment } @@ -17,6 +21,17 @@ type DeployKeystoneContractsSequenceDeps struct { type EVMChainID uint64 type Selector uint64 +type DeployRegistryContractsSequenceInput struct { + RegistryChainSelector uint64 +} + +type DeployContractSequenceOutput struct { + // Not sure if we can serialize the address book without modifications, but whatever is returned needs to be serializable. + // This could also be the address datastore instead. + AddressBook deployment.AddressBook + Datastore datastore.DataStore // Keeping the address store for backward compatibility, as not everything has been migrated to address book +} + // inputs and outputs have to be serializable, and must not contain sensitive data type DeployKeystoneContractsSequenceInput struct { @@ -49,6 +64,41 @@ func updateAddresses(addr datastore.MutableAddressRefStore, as datastore.Address return sourceAB.Merge(ab) } +// DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). +var DeployRegistryContractsSequence = operations.NewSequence[DeployRegistryContractsSequenceInput, DeployContractSequenceOutput, DeployContractsSequenceDeps]( + "deploy-registry-contracts-seq", + semver.MustParse("1.0.0"), + "Deploy registry Contracts (Capabilities Registry, Workflow Registry)", + func(b operations.Bundle, deps DeployContractsSequenceDeps, input DeployRegistryContractsSequenceInput) (output DeployContractSequenceOutput, err error) { + ab := deployment.NewMemoryAddressBook() + as := datastore.NewMemoryDataStore() + + // Capabilities Registry contract + capabilitiesRegistryDeployReport, err := operations.ExecuteOperation(b, DeployCapabilityRegistryOp, DeployCapabilityRegistryOpDeps(deps), DeployCapabilityRegistryInput{ChainSelector: input.RegistryChainSelector}) + if err != nil { + return DeployContractSequenceOutput{}, err + } + err = updateAddresses(as.Addresses(), capabilitiesRegistryDeployReport.Output.Addresses, ab, capabilitiesRegistryDeployReport.Output.AddressBook) + if err != nil { + return DeployContractSequenceOutput{}, err + } + // Workflow Registry contract + workflowRegistryDeployReport, err := operations.ExecuteOperation(b, DeployWorkflowRegistryOp, DeployWorkflowRegistryOpDeps(deps), DeployWorkflowRegistryInput{ChainSelector: input.RegistryChainSelector}) + if err != nil { + return DeployContractSequenceOutput{}, err + } + err = updateAddresses(as.Addresses(), workflowRegistryDeployReport.Output.Addresses, ab, workflowRegistryDeployReport.Output.AddressBook) + if err != nil { + return DeployContractSequenceOutput{}, err + } + return DeployContractSequenceOutput{ + AddressBook: ab, + Datastore: as.Seal(), + }, nil + + }, +) + // DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). var DeployKeystoneContractsSequence = operations.NewSequence[DeployKeystoneContractsSequenceInput, DeployKeystoneContractsSequenceOutput, DeployKeystoneContractsSequenceDeps]( "deploy-keystone-contracts-seq", diff --git a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go index 7c6858e49ed..a9832ca04aa 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go @@ -22,6 +22,7 @@ type DeployKeystoneForwardersInput struct { type DeployKeystoneForwardersOutput struct { Addresses datastore.AddressRefStore AddressBook cldf.AddressBook // The address book containing the deployed Keystone Forwarders + Datastore datastore.DataStore } var DeployKeystoneForwardersSequence = operations.NewSequence[DeployKeystoneForwardersInput, DeployKeystoneForwardersOutput, DeployKeystoneForwardersSequenceDeps]( @@ -60,6 +61,6 @@ var DeployKeystoneForwardersSequence = operations.NewSequence[DeployKeystoneForw if err := contractErrGroup.Wait(); err != nil { return DeployKeystoneForwardersOutput{AddressBook: ab, Addresses: as.Addresses()}, fmt.Errorf("failed to deploy Keystone contracts: %w", err) } - return DeployKeystoneForwardersOutput{AddressBook: ab, Addresses: as.Addresses()}, nil + return DeployKeystoneForwardersOutput{AddressBook: ab, Addresses: as.Addresses(), Datastore: as.Seal()}, nil }, ) diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index bbe56c0a7ee..7aa30891dff 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -252,36 +252,72 @@ func SetupTestEnvironment( } } } - - // use CLD to deploy the necessary contracts + /* + // use CLD to deploy the necessary contracts + homeChainSelector := homeChainOutput.ChainSelector + deployKeystoneReport, err := operations.ExecuteSequence( + allChainsCLDEnvironment.OperationsBundle, + ks_contracts_op.DeployKeystoneContractsSequence, + ks_contracts_op.DeployKeystoneContractsSequenceDeps{ + Env: allChainsCLDEnvironment, + }, + ks_contracts_op.DeployKeystoneContractsSequenceInput{ + RegistryChainSelector: homeChainSelector, + ForwardersSelectors: evmForwardersSelectors, + DeployVaultOCR3: vaultOCR3AddrFlag, + DeployEVMOCR3: evmOCR3AddrFlag, + EVMChainIDs: chainsWithEVMCapability, + DeployConsensusOCR3: consensusV2AddrFlag, + }, + ) + */ homeChainSelector := homeChainOutput.ChainSelector - deployKeystoneReport, err := operations.ExecuteSequence( + registryContractsReport, err := operations.ExecuteSequence( allChainsCLDEnvironment.OperationsBundle, - ks_contracts_op.DeployKeystoneContractsSequence, - ks_contracts_op.DeployKeystoneContractsSequenceDeps{ + ks_contracts_op.DeployRegistryContractsSequence, + ks_contracts_op.DeployContractsSequenceDeps{ Env: allChainsCLDEnvironment, }, - ks_contracts_op.DeployKeystoneContractsSequenceInput{ + ks_contracts_op.DeployRegistryContractsSequenceInput{ RegistryChainSelector: homeChainSelector, - ForwardersSelectors: evmForwardersSelectors, - DeployVaultOCR3: vaultOCR3AddrFlag, - DeployEVMOCR3: evmOCR3AddrFlag, - EVMChainIDs: chainsWithEVMCapability, - DeployConsensusOCR3: consensusV2AddrFlag, }, ) if err != nil { return nil, pkgerrors.Wrap(err, "failed to deploy Keystone contracts") } - if err = allChainsCLDEnvironment.ExistingAddresses.Merge(deployKeystoneReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now + if err = allChainsCLDEnvironment.ExistingAddresses.Merge(registryContractsReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now return nil, pkgerrors.Wrap(err, "failed to merge address book with Keystone contracts addresses") } - if err = memoryDatastore.Merge(deployKeystoneReport.Output.Datastore); err != nil { + if err = memoryDatastore.Merge(registryContractsReport.Output.Datastore); err != nil { return nil, pkgerrors.Wrap(err, "failed to merge datastore with Keystone contracts addresses") } + // deploy evm forwarders + evmForwardersReport, err := operations.ExecuteSequence( + allChainsCLDEnvironment.OperationsBundle, + ks_contracts_op.DeployKeystoneForwardersSequence, + ks_contracts_op.DeployKeystoneForwardersSequenceDeps{ + Env: allChainsCLDEnvironment, + }, + ks_contracts_op.DeployKeystoneForwardersInput{ + Targets: evmForwardersSelectors, + }, + ) + if err != nil { + return nil, pkgerrors.Wrap(err, "failed to deploy evm forwarder") + } + + if err = allChainsCLDEnvironment.ExistingAddresses.Merge(evmForwardersReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now + return nil, pkgerrors.Wrap(err, "failed to merge address book with Keystone contracts addresses") + } + + if err = memoryDatastore.Merge(evmForwardersReport.Output.Datastore); err != nil { + return nil, pkgerrors.Wrap(err, "failed to merge datastore with Keystone contracts addresses") + } + + // deploy solana forwarders for _, sel := range solForwardersSelectors { out, err := operations.ExecuteSequence( allChainsCLDEnvironment.OperationsBundle, @@ -324,6 +360,10 @@ func SetupTestEnvironment( testLogger.Info().Msgf("Deployed Forwarder contract on Solana chain chain %d programID: %s state: %s", sel, out.Output.ProgramID.String(), out.Output.State.String()) } + + // deploy the various ocr contracts + // TODO move this deeper into the stack when we have all the p2p ids and can deploy and configure in one sequence + allChainsCLDEnvironment.DataStore = memoryDatastore.Seal() ocr3Addr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], "capability_ocr3") From 6bbccf8f30eb9e4599ed65eee598ccfa29c96902 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Fri, 29 Aug 2025 20:07:52 -0600 Subject: [PATCH 03/37] ocr3 deploy sequence --- .../contracts/deploy_contracts_seq.go | 14 +++--- .../operations/contracts/deploy_ocr3_op.go | 43 +++++++++++++++++++ .../lib/cre/environment/environment.go | 22 ++++++++++ 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index 740c65b4991..00e6ee06c7b 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -10,17 +10,13 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/operations" ) -type DeployContractsSequenceDeps struct { - Env *deployment.Environment -} +type EVMChainID uint64 +type Selector uint64 -type DeployKeystoneContractsSequenceDeps struct { +type DeployContractsSequenceDeps struct { Env *deployment.Environment } -type EVMChainID uint64 -type Selector uint64 - type DeployRegistryContractsSequenceInput struct { RegistryChainSelector uint64 } @@ -34,6 +30,10 @@ type DeployContractSequenceOutput struct { // inputs and outputs have to be serializable, and must not contain sensitive data +type DeployKeystoneContractsSequenceDeps struct { + Env *deployment.Environment +} + type DeployKeystoneContractsSequenceInput struct { RegistryChainSelector uint64 ForwardersSelectors []uint64 diff --git a/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go b/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go index 88d1c4f8f61..e669bfae2ce 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go @@ -6,6 +6,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" @@ -45,3 +46,45 @@ var DeployOCR3Op = operations.NewOperation[DeployOCR3OpInput, DeployOCR3OpOutput }, nil }, ) + +type DeployOCR3ContractSequenceDeps struct { + Env *deployment.Environment +} + +type DeployOCR3ContractSequenceInput struct { + RegistryChainSelector uint64 + Qualifier string // qualifier for the OCR3 contract deployment +} + +type DeployOCR3ContractSequenceOutput struct { + // Not sure if we can serialize the address book without modifications, but whatever is returned needs to be serializable. + // This could also be the address datastore instead. + AddressBook deployment.AddressBook + Datastore datastore.DataStore // Keeping the address store for backward compatibility, as not everything has been migrated to address book +} + +// DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). +var DeployOCR3ContractsSequence = operations.NewSequence[DeployOCR3ContractSequenceInput, DeployOCR3ContractSequenceOutput, DeployOCR3ContractSequenceDeps]( + "deploy-registry-contracts-seq", + semver.MustParse("1.0.0"), + "Deploy registry Contracts (Capabilities Registry, Workflow Registry)", + func(b operations.Bundle, deps DeployOCR3ContractSequenceDeps, input DeployOCR3ContractSequenceInput) (output DeployOCR3ContractSequenceOutput, err error) { + ab := deployment.NewMemoryAddressBook() + as := datastore.NewMemoryDataStore() + + // OCR3 Contract + ocr3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: input.Qualifier}) + if err != nil { + return DeployOCR3ContractSequenceOutput{}, err + } + err = updateAddresses(as.Addresses(), ocr3DeployReport.Output.Addresses, ab, ocr3DeployReport.Output.AddressBook) + if err != nil { + return DeployOCR3ContractSequenceOutput{}, err + } + return DeployOCR3ContractSequenceOutput{ + AddressBook: ab, + Datastore: as.Seal(), + }, nil + + }, +) diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 7aa30891dff..4e356fd66f5 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -363,6 +363,28 @@ func SetupTestEnvironment( // deploy the various ocr contracts // TODO move this deeper into the stack when we have all the p2p ids and can deploy and configure in one sequence + // deploy OCR3 contract + // we deploy OCR3 contract with a qualifier, so that we can distinguish it from other OCR3 contracts (Vault, EVM, ConsensusV2) + ocr3DeployReport, err := operations.ExecuteSequence( + allChainsCLDEnvironment.OperationsBundle, + ks_contracts_op.DeployOCR3ContractsSequence, + ks_contracts_op.DeployOCR3ContractSequenceDeps{ + Env: allChainsCLDEnvironment, + }, + ks_contracts_op.DeployOCR3ContractSequenceInput{ + RegistryChainSelector: homeChainSelector, + Qualifier: "capability_ocr3", + }, + ) + if err != nil { + return nil, pkgerrors.Wrap(err, "failed to deploy OCR3 contract") + } + if err = allChainsCLDEnvironment.ExistingAddresses.Merge(ocr3DeployReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now + return nil, pkgerrors.Wrap(err, "failed to merge address book with OCR3 contract address") + } + if err = memoryDatastore.Merge(ocr3DeployReport.Output.Datastore); err != nil { + return nil, pkgerrors.Wrap(err, "failed to merge datastore with OCR3 contract address") + } allChainsCLDEnvironment.DataStore = memoryDatastore.Seal() From ff25faee013b157ec9c4f7b9764a2afb70c1a938 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Fri, 29 Aug 2025 20:16:08 -0600 Subject: [PATCH 04/37] add deploy ocr wrapper func --- .../lib/cre/environment/environment.go | 67 ++++++++++++++----- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 4e356fd66f5..d733e886531 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -365,27 +365,36 @@ func SetupTestEnvironment( // TODO move this deeper into the stack when we have all the p2p ids and can deploy and configure in one sequence // deploy OCR3 contract // we deploy OCR3 contract with a qualifier, so that we can distinguish it from other OCR3 contracts (Vault, EVM, ConsensusV2) - ocr3DeployReport, err := operations.ExecuteSequence( - allChainsCLDEnvironment.OperationsBundle, - ks_contracts_op.DeployOCR3ContractsSequence, - ks_contracts_op.DeployOCR3ContractSequenceDeps{ - Env: allChainsCLDEnvironment, - }, - ks_contracts_op.DeployOCR3ContractSequenceInput{ - RegistryChainSelector: homeChainSelector, - Qualifier: "capability_ocr3", - }, - ) + _, err = deployOCR3Contract("capability_ocr3", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) if err != nil { - return nil, pkgerrors.Wrap(err, "failed to deploy OCR3 contract") + return nil, fmt.Errorf("failed to deploy OCR3 contract %w", err) } - if err = allChainsCLDEnvironment.ExistingAddresses.Merge(ocr3DeployReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now - return nil, pkgerrors.Wrap(err, "failed to merge address book with OCR3 contract address") + // deploy DONTime contract + _, err = deployOCR3Contract("DONTime", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) + if err != nil { + return nil, fmt.Errorf("failed to deploy DONTime contract %w", err) } - if err = memoryDatastore.Merge(ocr3DeployReport.Output.Datastore); err != nil { - return nil, pkgerrors.Wrap(err, "failed to merge datastore with OCR3 contract address") + if vaultOCR3AddrFlag { + _, err = deployOCR3Contract("capability_vault", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) + if err != nil { + return nil, fmt.Errorf("failed to deploy Vault OCR3 contract %w", err) + } + } + if evmOCR3AddrFlag { + for chainID, selector := range chainsWithEVMCapability { + qualifier := ks_contracts_op.GetCapabilityContractIdentifier(uint64(chainID)) + _, err = deployOCR3Contract(qualifier, uint64(selector), allChainsCLDEnvironment, memoryDatastore) + if err != nil { + return nil, fmt.Errorf("failed to deploy EVM OCR3 contract for chainID %d, selector %d: %w", chainID, selector, err) + } + } + } + if consensusV2AddrFlag { + _, err = deployOCR3Contract("capability_consensus", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) + if err != nil { + return nil, fmt.Errorf("failed to deploy Consensus V2 OCR3 contract %w", err) + } } - allChainsCLDEnvironment.DataStore = memoryDatastore.Seal() ocr3Addr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], "capability_ocr3") @@ -1003,3 +1012,27 @@ func getAllFilters(ctx context.Context, logger logger.Logger, chainID *big.Int, defer db.Close() return orm.LoadFilters(ctx) } + +func deployOCR3Contract(qualifier string, selector uint64, env *cldf.Environment, ds datastore.MutableDataStore) (*ks_contracts_op.DeployOCR3ContractSequenceOutput, error) { + ocr3DeployReport, err := operations.ExecuteSequence( + env.OperationsBundle, + ks_contracts_op.DeployOCR3ContractsSequence, + ks_contracts_op.DeployOCR3ContractSequenceDeps{ + Env: env, + }, + ks_contracts_op.DeployOCR3ContractSequenceInput{ + RegistryChainSelector: selector, + Qualifier: qualifier, + }, + ) + if err != nil { + return nil, fmt.Errorf("failed to deploy OCR3 contract '%s' on chain %d: %w", qualifier, selector, err) + } + if err = env.ExistingAddresses.Merge(ocr3DeployReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now + return nil, fmt.Errorf("failed to merge address book with OCR3 contract address for '%s' on chain %d: %w", qualifier, selector, err) + } + if err = ds.Merge(ocr3DeployReport.Output.Datastore); err != nil { + return nil, fmt.Errorf("failed to merge datastore with OCR3 contract address for '%s' on chain %d: %w", qualifier, selector, err) + } + return &ocr3DeployReport.Output, nil +} From 6dd7e712e78a411a9dd5b5187e77bd42c13b2b97 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Sat, 30 Aug 2025 07:45:48 -0600 Subject: [PATCH 05/37] datastore hints, comments, cleanup --- system-tests/lib/cre/contracts/contracts.go | 9 ++------- system-tests/lib/cre/don/config/definitions.go | 9 +++++++++ system-tests/lib/cre/environment/environment.go | 10 ---------- system-tests/lib/cre/types.go | 9 +++++++++ 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index 2649af228cf..f9b9d46efd8 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -41,8 +41,6 @@ type donConfig struct { *ocrDonCfg } -var ocrDons map[string]ocrDonCfg // map of DON name to ocrDon struct - func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfigFns []cre.CapabilityRegistryConfigFn) error { lggr := input.CldEnv.Logger @@ -136,11 +134,6 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi } } - // this can probably be removed, maintaining for compatibility for now - if len(ocrDons) == 0 { - return errors.New("no OCR3-capable DON found in the topology") - } - _, err := operations.ExecuteSequence( input.CldEnv.OperationsBundle, ks_contracts_op.ConfigureCapabilitiesRegistrySeq, @@ -419,6 +412,7 @@ func DefaultOCR3Config(topology *cre.Topology) (*keystone_changeset.OracleConfig return oracleConfig, nil } +// TODO: CRE-742 use datastore func FindAddressesForChain(addressBook cldf.AddressBook, chainSelector uint64, contractName string) (common.Address, error) { addresses, err := addressBook.AddressesForChain(chainSelector) if err != nil { @@ -436,6 +430,7 @@ func FindAddressesForChain(addressBook cldf.AddressBook, chainSelector uint64, c return common.Address{}, fmt.Errorf("failed to find %s address in the address book for chain %d", contractName, chainSelector) } +// TODO: CRE-742 use datastore func MustFindAddressesForChain(addressBook cldf.AddressBook, chainSelector uint64, contractName string) common.Address { addr, err := FindAddressesForChain(addressBook, chainSelector, contractName) if err != nil { diff --git a/system-tests/lib/cre/don/config/definitions.go b/system-tests/lib/cre/don/config/definitions.go index c47877d04b5..30a1f980281 100644 --- a/system-tests/lib/cre/don/config/definitions.go +++ b/system-tests/lib/cre/don/config/definitions.go @@ -44,6 +44,7 @@ const ( ` ) +// BootstrapEVM creates TOML-literal for the EVM section of the node configuration for a bootstrap node func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitiesRegistryAddress common.Address, chains []*WorkerEVMInput) string { evmChainsConfig := "" for _, chain := range chains { @@ -93,6 +94,7 @@ func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitie ) } +// BoostrapDon2DonPeering creates TOML-literal for the Capabilities Peering section of the node configuration for a bootstrap node func BoostrapDon2DonPeering(peeringData cre.CapabilitiesPeeringData) string { return fmt.Sprintf(` [Capabilities.Peering.V2] @@ -107,6 +109,8 @@ func BoostrapDon2DonPeering(peeringData cre.CapabilitiesPeeringData) string { ) } +// WorkerEVM is a configuration struct to represent dependencies that are required for +// a non-bootstrap node to support an given EVM chains and optionally write to them type WorkerEVMInput struct { Name string ChainID uint64 @@ -119,6 +123,8 @@ type WorkerEVMInput struct { WorkflowConfig map[string]any // Configuration for EVM.Workflow section } +// WorkerEVM creates TOML-literal for the EVM section of the node configuration for a non-bootstrap node +// TODO: decomposition into p2p, capabilities, evm, workflow, ... func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringData cre.OCRPeeringData, capabilitiesPeeringData cre.CapabilitiesPeeringData, capabilitiesRegistryAddress common.Address, homeChainID uint64, chains []*WorkerEVMInput) (string, error) { evmChainsConfig := "" for _, chain := range chains { @@ -206,6 +212,8 @@ func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringDa ), nil } +// WorkerSolana is a configuration struct to represent dependencies that are required for +// a non-bootstrap node to support a given Solana chains and optionally write to them type WorkerSolanaInput struct { Name string ChainID string @@ -218,6 +226,7 @@ type WorkerSolanaInput struct { WorkflowConfig map[string]any // Configuration for Solana.Workflow section } +// BootstrapSolana creates TOML-literal for the Solana section of the node configuration for a bootstrap node func BootstrapSolana(chains []*WorkerSolanaInput) string { var ret string for _, chain := range chains { diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index d733e886531..3d39fe0fa64 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -509,17 +509,7 @@ func SetupTestEnvironment( startTime = time.Now() fmt.Print(libformat.PurpleText("---> [BACKGROUND 1/3] Configuring Workflow Registry contract\n")) - allAddresses, addrErr := allChainsCLDEnvironment.ExistingAddresses.Addresses() //nolint:staticcheck // ignore SA1019 as ExistingAddresses is deprecated but still used - if addrErr != nil { - backgroundStagesCh <- backgroundStageResult{err: pkgerrors.Wrap(addrErr, "failed to get addresses from address book")} - return - } - chainsWithContracts := make(map[uint64]bool) - for chainSelector, addresses := range allAddresses { - chainsWithContracts[chainSelector] = len(addresses) > 0 - } - addresses, addrErr1 := allChainsCLDEnvironment.DataStore.Addresses().Fetch() if addrErr1 != nil { backgroundStagesCh <- backgroundStageResult{err: pkgerrors.Wrap(addrErr1, "failed to get addresses from datastore")} diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index efa85221e22..2d1a52e3fbc 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -464,6 +464,15 @@ func (g *GenerateConfigsInput) Validate() error { if addrErr != nil { return fmt.Errorf("failed to get addresses for chain %d: %w", g.HomeChainSelector, addrErr) } + _, dsErr := g.Datastore.Addresses().Fetch() + if dsErr != nil { + return fmt.Errorf("failed to get addresses from datastore: %w", dsErr) + } + h := g.Datastore.Addresses().Filter(datastore.AddressRefByChainSelector(g.HomeChainSelector)) + if len(h) == 0 { + return fmt.Errorf("no addresses found for home chain %d in datastore", g.HomeChainSelector) + } + // TODO check for required registry contracts by type and version return nil } From 6189553eb7a035f6e572bb057a2ec0dc2b27782b Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Sat, 30 Aug 2025 09:06:27 -0600 Subject: [PATCH 06/37] finish minimal refactor for multiple ocr3 support --- .../keystone/changeset/internal/types.go | 8 + .../changeset/operations/contracts/types.go | 2 +- system-tests/lib/cre/contracts/contracts.go | 197 +++++++++++------- .../lib/cre/environment/environment.go | 1 + system-tests/lib/cre/types.go | 11 +- 5 files changed, 141 insertions(+), 78 deletions(-) diff --git a/deployment/keystone/changeset/internal/types.go b/deployment/keystone/changeset/internal/types.go index 691164bd7e9..bf7caf10b8e 100644 --- a/deployment/keystone/changeset/internal/types.go +++ b/deployment/keystone/changeset/internal/types.go @@ -90,6 +90,14 @@ type DonCapabilities struct { Capabilities []DONCapabilityWithConfig // every capability is hosted on each nop } +func (v DonCapabilities) N() int { + out := 0 + for _, n := range v.Nops { + out += len(n.Nodes) + } + return out +} + type DONCapabilityWithConfig struct { Capability kcr.CapabilitiesRegistryCapability Config *capabilitiespb.CapabilityConfig diff --git a/deployment/keystone/changeset/operations/contracts/types.go b/deployment/keystone/changeset/operations/contracts/types.go index 1c317006d03..eee1570bb09 100644 --- a/deployment/keystone/changeset/operations/contracts/types.go +++ b/deployment/keystone/changeset/operations/contracts/types.go @@ -2,5 +2,5 @@ package contracts type ConfigureKeystoneDON struct { Name string - NodeIDs []string + NodeIDs []string // usually peer IDs } diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index f9b9d46efd8..dc11b16611d 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -31,26 +31,99 @@ import ( crenode "github.com/smartcontractkit/chainlink/system-tests/lib/cre/don/node" ) -type ocrDonCfg struct { - transmissionSchedule []int -} - type donConfig struct { keystone_changeset.DonCapabilities // transmissionSchedule is the transmission schedule for the DON, if applicable - *ocrDonCfg + // todo this should be a method rather than a field; can be computed flags + default ocr config. only need to compute the xmission schedule for OCR3-capable DONs + flags []cre.CapabilityFlag } -func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfigFns []cre.CapabilityRegistryConfigFn) error { - lggr := input.CldEnv.Logger +func (d *donConfig) resolveOcr3Config(c keystone_changeset.OracleConfig) *keystone_changeset.OracleConfig { + // compute the xmission schedule + s := []int{d.N()} + c.TransmissionSchedule = s + return &c +} + +func (d *donConfig) keystoneDonConfig() ks_contracts_op.ConfigureKeystoneDON { + don := ks_contracts_op.ConfigureKeystoneDON{ + Name: d.Name, + } + for _, nop := range d.Nops { + don.NodeIDs = append(don.NodeIDs, nop.Nodes...) + } + return don +} + +type dons struct { + c map[string]donConfig +} + +func (d *dons) GetByName(name string) (donConfig, error) { + c, ok := d.c[name] + if !ok { + return donConfig{}, fmt.Errorf("don with name %s not found", name) + } + return c, nil +} + +func (d *dons) ListByFlag(flag cre.CapabilityFlag) ([]donConfig, error) { + out := make([]donConfig, 0) + for _, don := range d.c { + if flags.HasFlag(don.flags, flag) { + out = append(out, don) + } + } + if len(out) == 0 { + return nil, fmt.Errorf("don with flag %s not found", flag) + } + return out, nil +} + +func (d *dons) ListByCapability(capName, capVersion string) ([]donConfig, error) { + out := make([]donConfig, 0) + for _, don := range d.c { + for _, cap := range don.Capabilities { + if cap.Capability.LabelledName == capName && cap.Capability.Version == capVersion { + out = append(out, don) + break + } + } + } + if len(out) == 0 { + return nil, fmt.Errorf("don with capability %s v%s not found", capName, capVersion) + } + return out, nil +} + +func (d *dons) shouldBeOneDon(flag cre.CapabilityFlag) (donConfig, error) { + dons, err := d.ListByFlag(flag) + if err != nil { + return donConfig{}, err + } + if len(dons) != 1 { + return donConfig{}, fmt.Errorf("expected exactly one DON with flag %s, found %d", flag, len(dons)) + } + return dons[0], nil +} +func (d *dons) allKeystoneDons() []ks_contracts_op.ConfigureKeystoneDON { + out := make([]ks_contracts_op.ConfigureKeystoneDON, 0, len(d.c)) + for _, don := range d.c { + out = append(out, don.keystoneDonConfig()) + } + return out +} + +func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfigFns []cre.CapabilityRegistryConfigFn) error { if err := input.Validate(); err != nil { return errors.Wrap(err, "input validation failed") } donCapabilities := make([]keystone_changeset.DonCapabilities, 0, len(input.Topology.DonsMetadata)) - d2 := make(map[string]donConfig) // map of DON name to donConfig struct - //ocrDons = make(map[string]ocrDonCfg) + dons := &dons{ + c: make(map[string]donConfig), + } for donIdx, donMetadata := range input.Topology.DonsMetadata { // if it's only a gateway DON, we don't want to register it with the Capabilities Registry @@ -94,15 +167,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi donPeerIDs[i] = p2pID } - // we only need to assign P2P IDs to NOPs, since `ConfigureInitialContractsChangeset` method - // will take care of creating DON to Nodes mapping - nop := keystone_changeset.NOP{ - Name: fmt.Sprintf("NOP for %s DON", donMetadata.Name), - Nodes: donPeerIDs, - } - forwarderF := (len(workerNodes) - 1) / 3 - if forwarderF == 0 { if flags.HasFlag(donMetadata.Flags, cre.ConsensusCapability) || flags.HasFlag(donMetadata.Flags, cre.ConsensusCapabilityV2) { return fmt.Errorf("incorrect number of worker nodes: %d. Resulting F must conform to formula: mod((N-1)/3) > 0", len(workerNodes)) @@ -111,6 +176,12 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi forwarderF = 1 } + // we only need to assign P2P IDs to NOPs, since `ConfigureInitialContractsChangeset` method + // will take care of creating DON to Nodes mapping + nop := keystone_changeset.NOP{ + Name: fmt.Sprintf("NOP for %s DON", donMetadata.Name), + Nodes: donPeerIDs, + } donName := donMetadata.Name + "-don" c := keystone_changeset.DonCapabilities{ Name: donName, @@ -120,20 +191,12 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi } donCapabilities = append(donCapabilities, c) - ocrCfg, err := newOCRCfg(donMetadata) - if errors.Is(err, unsupportedDONTypeErr) { - // we simply skip DONs that do not support OCR3 - lggr.Warnw("skipping transmission schedule determination for DON that does not support OCR3", "donName", donMetadata.Name) - } else if err != nil { - return errors.Wrap(err, "failed to determine transmission schedule") - } - - d2[donName] = donConfig{ + dons.c[donName] = donConfig{ DonCapabilities: c, - ocrDonCfg: ocrCfg, + flags: donMetadata.Flags, } } - + // get the values of _, err := operations.ExecuteSequence( input.CldEnv.OperationsBundle, ks_contracts_op.ConfigureCapabilitiesRegistrySeq, @@ -160,17 +223,6 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi return errors.Wrap(err, "failed to get capabilities registry contract") } - configDONs := make([]ks_contracts_op.ConfigureKeystoneDON, 0) - for _, donCap := range donCapabilities { - don := ks_contracts_op.ConfigureKeystoneDON{ - Name: donCap.Name, - } - for _, nop := range donCap.Nops { - don.NodeIDs = append(don.NodeIDs, nop.Nodes...) - } - configDONs = append(configDONs, don) - } - // remove chains that do not require any configurations ('read-only' chains that do not have forwarders deployed) allAddresses, addrErr := input.CldEnv.ExistingAddresses.Addresses() //nolint:staticcheck // ignore SA1019 as ExistingAddresses is deprecated but still used if addrErr != nil { @@ -194,7 +246,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi // configure Solana forwarder only if we have some if len(solChainsWithForwarder) > 0 { - for _, don := range configDONs { + for _, don := range dons.allKeystoneDons() { cs := commonchangeset.Configure(ks_solana.ConfigureForwarders{}, &ks_solana.ConfigureForwarderRequest{ WFDonName: don.Name, @@ -224,7 +276,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi }, ks_contracts_op.ConfigureForwardersSeqInput{ RegistryChainSel: input.ChainSelector, - DONs: configDONs, + DONs: dons.allKeystoneDons(), Chains: evmChainsWithForwarders, }, ) @@ -233,6 +285,10 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi } } + consensusV1DON, err := dons.shouldBeOneDon(cre.ConsensusCapability) + if err != nil { + return fmt.Errorf("failed to get consensus v1 DON: %w", err) + } _, err = operations.ExecuteOperation( input.CldEnv.OperationsBundle, ks_contracts_op.ConfigureOCR3Op, @@ -243,8 +299,8 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi ks_contracts_op.ConfigureOCR3OpInput{ ContractAddress: input.OCR3Address, RegistryChainSel: input.ChainSelector, - DONs: configDONs, - Config: &input.OCR3Config, + DON: consensusV1DON.keystoneDonConfig(), + Config: consensusV1DON.resolveOcr3Config(input.OCR3Config), DryRun: false, }, ) @@ -252,6 +308,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi return errors.Wrap(err, "failed to configure OCR3 contract") } + // don time happens to be the same as consensus v1 DON, but it doesn't have to be _, err = operations.ExecuteOperation( input.CldEnv.OperationsBundle, ks_contracts_op.ConfigureOCR3Op, @@ -262,8 +319,8 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi ks_contracts_op.ConfigureOCR3OpInput{ ContractAddress: input.DONTimeAddress, RegistryChainSel: input.ChainSelector, - DONs: configDONs, - Config: &input.DONTimeConfig, + DON: consensusV1DON.keystoneDonConfig(), + Config: consensusV1DON.resolveOcr3Config(input.DONTimeConfig), DryRun: false, }, ) @@ -272,6 +329,11 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi } if input.VaultOCR3Address.Cmp(common.Address{}) != 0 { + vaultDON, err := dons.shouldBeOneDon(cre.VaultCapability) + if err != nil { + return fmt.Errorf("failed to get vault DON: %w", err) + } + _, err = operations.ExecuteOperation( input.CldEnv.OperationsBundle, ks_contracts_op.ConfigureOCR3Op, @@ -282,8 +344,8 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi ks_contracts_op.ConfigureOCR3OpInput{ ContractAddress: input.VaultOCR3Address, RegistryChainSel: input.ChainSelector, - DONs: configDONs, - Config: &input.VaultOCR3Config, + DON: vaultDON.keystoneDonConfig(), + Config: vaultDON.resolveOcr3Config(input.VaultOCR3Config), DryRun: false, }, ) @@ -293,6 +355,12 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi } for chainSelector, evmOCR3Address := range *input.EVMOCR3Addresses { + // not sure how to map EVM chains to DONs, so for now we assume that there's only one DON that supports EVM chains + evmDON, err := dons.shouldBeOneDon(cre.ReadContractCapability) + if err != nil { + return fmt.Errorf("failed to get EVM DON: %w", err) + } + if evmOCR3Address.Cmp(common.Address{}) != 0 { _, err = operations.ExecuteOperation( input.CldEnv.OperationsBundle, @@ -304,8 +372,8 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi ks_contracts_op.ConfigureOCR3OpInput{ ContractAddress: &evmOCR3Address, RegistryChainSel: chainSelector, - DONs: configDONs, - Config: &input.EVMOCR3Config, + DON: evmDON.keystoneDonConfig(), + Config: evmDON.resolveOcr3Config(input.EVMOCR3Config), DryRun: false, }, ) @@ -316,6 +384,10 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi } if input.ConsensusV2OCR3Address.Cmp(common.Address{}) != 0 { + v2ConsensusDON, err := dons.shouldBeOneDon(cre.ConsensusCapabilityV2) + if err != nil { + return fmt.Errorf("failed to get consensus v2 DON: %w", err) + } _, err = operations.ExecuteOperation( input.CldEnv.OperationsBundle, ks_contracts_op.ConfigureOCR3Op, @@ -326,8 +398,8 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi ks_contracts_op.ConfigureOCR3OpInput{ ContractAddress: input.ConsensusV2OCR3Address, RegistryChainSel: input.ChainSelector, - DONs: configDONs, - Config: &input.ConsensusV2OCR3Config, + DON: v2ConsensusDON.keystoneDonConfig(), + Config: v2ConsensusDON.resolveOcr3Config(input.ConsensusV2OCR3Config), DryRun: false, }, ) @@ -338,29 +410,6 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi return nil } -var unsupportedDONTypeErr = errors.New("unsupported DON type for transmission schedule determination") - -func newOCRCfg(donMetadata *cre.DonMetadata) (*ocrDonCfg, error) { - // determine transmission schedule for OCR3-capable DONs - // todo extend and abstract this logic when we have for non-workflow DONs - if flags.HasFlag(donMetadata.Flags, cre.ConsensusCapability) || flags.HasFlag(donMetadata.Flags, cre.ConsensusCapabilityV2) { - workerNodes, workerNodesErr := crenode.FindManyWithLabel(donMetadata.NodesMetadata, &cre.Label{ - Key: crenode.NodeTypeKey, - Value: cre.WorkerNode, - }, crenode.EqualLabels) - - if workerNodesErr != nil { - return nil, errors.Wrap(workerNodesErr, "failed to find worker nodes") - } - - return &ocrDonCfg{ - transmissionSchedule: []int{len(workerNodes)}, - }, nil - } - return nil, unsupportedDONTypeErr - -} - // values supplied by Alexandr Yepishev as the expected values for OCR3 config func DefaultOCR3Config(topology *cre.Topology) (*keystone_changeset.OracleConfig, error) { var transmissionSchedule []int diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 3d39fe0fa64..c3cdf266ee1 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -365,6 +365,7 @@ func SetupTestEnvironment( // TODO move this deeper into the stack when we have all the p2p ids and can deploy and configure in one sequence // deploy OCR3 contract // we deploy OCR3 contract with a qualifier, so that we can distinguish it from other OCR3 contracts (Vault, EVM, ConsensusV2) + // TODO track the qualifiers in vars/consts rather than raw strings _, err = deployOCR3Contract("capability_ocr3", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) if err != nil { return nil, fmt.Errorf("failed to deploy OCR3 contract %w", err) diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index 2d1a52e3fbc..4abad72b526 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -348,7 +348,7 @@ type ConfigureKeystoneInput struct { NodeSets []*CapabilitiesAwareNodeSet OCR3Config keystone_changeset.OracleConfig - OCR3Address *common.Address + OCR3Address *common.Address // v1 consensus contract address DONTimeConfig keystone_changeset.OracleConfig DONTimeAddress *common.Address @@ -357,9 +357,9 @@ type ConfigureKeystoneInput struct { VaultOCR3Address *common.Address EVMOCR3Config keystone_changeset.OracleConfig - EVMOCR3Addresses *map[uint64]common.Address + EVMOCR3Addresses *map[uint64]common.Address // chain selector to address map - ConsensusV2OCR3Config keystone_changeset.OracleConfig + ConsensusV2OCR3Config keystone_changeset.OracleConfig // v2 consensus contract config ConsensusV2OCR3Address *common.Address CapabilitiesRegistryAddress *common.Address @@ -494,6 +494,11 @@ type DonMetadata struct { SupportedChains []uint64 `toml:"supported_chains" json:"supported_chains"` // chain IDs that the DON supports, empty means all chains } +func (m *DonMetadata) RequiresOCR() bool { + return slices.Contains(m.Flags, ConsensusCapability) || slices.Contains(m.Flags, ConsensusCapabilityV2) || + slices.Contains(m.Flags, VaultCapability) || slices.Contains(m.Flags, ReadContractCapability) +} + type Label struct { Key string `toml:"key" json:"key"` Value string `toml:"value" json:"value"` From a3662f498352da877276bc40101469281519eae2 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Sat, 30 Aug 2025 09:40:22 -0600 Subject: [PATCH 07/37] rm dead code --- .../contracts/deploy_contracts_seq.go | 131 +----------------- system-tests/lib/cre/contracts/contracts.go | 8 +- 2 files changed, 5 insertions(+), 134 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index 00e6ee06c7b..47ecde2ce28 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -13,6 +13,7 @@ import ( type EVMChainID uint64 type Selector uint64 +// inputs and outputs have to be serializable, and must not contain sensitive data type DeployContractsSequenceDeps struct { Env *deployment.Environment } @@ -20,7 +21,6 @@ type DeployContractsSequenceDeps struct { type DeployRegistryContractsSequenceInput struct { RegistryChainSelector uint64 } - type DeployContractSequenceOutput struct { // Not sure if we can serialize the address book without modifications, but whatever is returned needs to be serializable. // This could also be the address datastore instead. @@ -28,28 +28,6 @@ type DeployContractSequenceOutput struct { Datastore datastore.DataStore // Keeping the address store for backward compatibility, as not everything has been migrated to address book } -// inputs and outputs have to be serializable, and must not contain sensitive data - -type DeployKeystoneContractsSequenceDeps struct { - Env *deployment.Environment -} - -type DeployKeystoneContractsSequenceInput struct { - RegistryChainSelector uint64 - ForwardersSelectors []uint64 - DeployVaultOCR3 bool - DeployEVMOCR3 bool - EVMChainIDs map[EVMChainID]Selector - DeployConsensusOCR3 bool -} - -type DeployKeystoneContractsSequenceOutput struct { - // Not sure if we can serialize the address book without modifications, but whatever is returned needs to be serializable. - // This could also be the address datastore instead. - AddressBook deployment.AddressBook - Datastore datastore.DataStore // Keeping the address store for backward compatibility, as not everything has been migrated to address book -} - func updateAddresses(addr datastore.MutableAddressRefStore, as datastore.AddressRefStore, sourceAB deployment.AddressBook, ab deployment.AddressBook) error { addresses, err := as.Fetch() if err != nil { @@ -64,8 +42,9 @@ func updateAddresses(addr datastore.MutableAddressRefStore, as datastore.Address return sourceAB.Merge(ab) } -// DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). +// DeployRegistryContractsSequence is a sequence that deploys the the required registry contracts (Capabilities Registry, Workflow Registry). var DeployRegistryContractsSequence = operations.NewSequence[DeployRegistryContractsSequenceInput, DeployContractSequenceOutput, DeployContractsSequenceDeps]( + // do not add optional contracts here (ocr, forwarder...), as this sequence is used to deploy the registry contracts that other sequences depend on "deploy-registry-contracts-seq", semver.MustParse("1.0.0"), "Deploy registry Contracts (Capabilities Registry, Workflow Registry)", @@ -99,110 +78,6 @@ var DeployRegistryContractsSequence = operations.NewSequence[DeployRegistryContr }, ) -// DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). -var DeployKeystoneContractsSequence = operations.NewSequence[DeployKeystoneContractsSequenceInput, DeployKeystoneContractsSequenceOutput, DeployKeystoneContractsSequenceDeps]( - "deploy-keystone-contracts-seq", - semver.MustParse("1.0.0"), - "Deploy Keystone Contracts (BalanceReader, OCR3, DON Time, Vault-OCR3, EVM-OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder)", - func(b operations.Bundle, deps DeployKeystoneContractsSequenceDeps, input DeployKeystoneContractsSequenceInput) (output DeployKeystoneContractsSequenceOutput, err error) { - ab := deployment.NewMemoryAddressBook() - as := datastore.NewMemoryDataStore() - - // Capabilities Registry contract - capabilitiesRegistryDeployReport, err := operations.ExecuteOperation(b, DeployCapabilityRegistryOp, DeployCapabilityRegistryOpDeps(deps), DeployCapabilityRegistryInput{ChainSelector: input.RegistryChainSelector}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), capabilitiesRegistryDeployReport.Output.Addresses, ab, capabilitiesRegistryDeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - - // OCR3 Contract - ocr3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "capability_ocr3"}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), ocr3DeployReport.Output.Addresses, ab, ocr3DeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - - // Workflow Registry contract - workflowRegistryDeployReport, err := operations.ExecuteOperation(b, DeployWorkflowRegistryOp, DeployWorkflowRegistryOpDeps(deps), DeployWorkflowRegistryInput{ChainSelector: input.RegistryChainSelector}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), workflowRegistryDeployReport.Output.Addresses, ab, workflowRegistryDeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - - // Keystone Forwarder contract - keystoneForwarderDeployReport, err := operations.ExecuteSequence(b, DeployKeystoneForwardersSequence, DeployKeystoneForwardersSequenceDeps(deps), DeployKeystoneForwardersInput{Targets: input.ForwardersSelectors}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), keystoneForwarderDeployReport.Output.Addresses, ab, keystoneForwarderDeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - - // DON Time Contract - Copy of OCR3Capability - donTimeDeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "DONTime"}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), donTimeDeployReport.Output.Addresses, ab, donTimeDeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - - if input.DeployVaultOCR3 { - // Vault OCR3 Contract - vaultOCR3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "capability_vault"}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), vaultOCR3DeployReport.Output.Addresses, ab, vaultOCR3DeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - } - - if input.DeployEVMOCR3 { - for chainID, selector := range input.EVMChainIDs { - // EVM cap OCR3 Contract - qualifier := GetCapabilityContractIdentifier(uint64(chainID)) - evmOCR3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: uint64(selector), Qualifier: qualifier}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), evmOCR3DeployReport.Output.Addresses, ab, evmOCR3DeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - } - } - - if input.DeployConsensusOCR3 { - evmOCR3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "capability_consensus"}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), evmOCR3DeployReport.Output.Addresses, ab, evmOCR3DeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - } - - return DeployKeystoneContractsSequenceOutput{ - AddressBook: ab, - Datastore: as.Seal(), - }, nil - }, -) - func GetCapabilityContractIdentifier(chainID uint64) string { return fmt.Sprintf("capability_evm_%d", chainID) } diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index dc11b16611d..c0ed539c64b 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -33,15 +33,11 @@ import ( type donConfig struct { keystone_changeset.DonCapabilities - // transmissionSchedule is the transmission schedule for the DON, if applicable - // todo this should be a method rather than a field; can be computed flags + default ocr config. only need to compute the xmission schedule for OCR3-capable DONs flags []cre.CapabilityFlag } func (d *donConfig) resolveOcr3Config(c keystone_changeset.OracleConfig) *keystone_changeset.OracleConfig { - // compute the xmission schedule - s := []int{d.N()} - c.TransmissionSchedule = s + c.TransmissionSchedule = []int{d.N()} return &c } @@ -196,7 +192,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi flags: donMetadata.Flags, } } - // get the values of + _, err := operations.ExecuteSequence( input.CldEnv.OperationsBundle, ks_contracts_op.ConfigureCapabilitiesRegistrySeq, From 531592513710c5758762195efbaa0ca3946012c7 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Sat, 30 Aug 2025 14:17:59 -0600 Subject: [PATCH 08/37] cleanup; rm donCapabilities slice --- .../contracts/deploy_forwarders_seq _test.go | 2 +- .../contracts/deploy_forwarders_seq.go | 3 ++- .../operations/contracts/deploy_ocr3_op.go | 7 +++--- system-tests/lib/cre/contracts/contracts.go | 18 ++++++++++----- .../lib/cre/environment/environment.go | 22 +++---------------- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go index c3a9507ec85..699f57a2fc0 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go @@ -26,7 +26,7 @@ func Test_DeployForwardersSeq(t *testing.T) { registrySel := env.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chain_selectors.FamilyEVM))[0] otherChainSel := env.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chain_selectors.FamilyEVM))[1] b := optest.NewBundle(t) - deps := contracts.DeployKeystoneForwardersSequenceDeps{ + deps := contracts.DeployForwardersSequenceDeps{ Env: &env, } input := contracts.DeployKeystoneForwardersInput{ diff --git a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go index a9832ca04aa..683e5a76160 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq.go @@ -20,7 +20,8 @@ type DeployKeystoneForwardersInput struct { } type DeployKeystoneForwardersOutput struct { - Addresses datastore.AddressRefStore + Addresses datastore.AddressRefStore + // TODO: CRE-742 remove AddressBook AddressBook cldf.AddressBook // The address book containing the deployed Keystone Forwarders Datastore datastore.DataStore } diff --git a/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go b/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go index e669bfae2ce..59f2abac67f 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go @@ -57,10 +57,9 @@ type DeployOCR3ContractSequenceInput struct { } type DeployOCR3ContractSequenceOutput struct { - // Not sure if we can serialize the address book without modifications, but whatever is returned needs to be serializable. - // This could also be the address datastore instead. - AddressBook deployment.AddressBook - Datastore datastore.DataStore // Keeping the address store for backward compatibility, as not everything has been migrated to address book + // TODO: CRE-742 remove AddressBook + AddressBook deployment.AddressBook // Keeping the address store for backward compatibility, as not everything has been migrated to datastore + Datastore datastore.DataStore } // DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index c0ed539c64b..cf3d8ab5b07 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -103,7 +103,7 @@ func (d *dons) shouldBeOneDon(flag cre.CapabilityFlag) (donConfig, error) { return dons[0], nil } -func (d *dons) allKeystoneDons() []ks_contracts_op.ConfigureKeystoneDON { +func (d *dons) donNodesets() []ks_contracts_op.ConfigureKeystoneDON { out := make([]ks_contracts_op.ConfigureKeystoneDON, 0, len(d.c)) for _, don := range d.c { out = append(out, don.keystoneDonConfig()) @@ -111,12 +111,19 @@ func (d *dons) allKeystoneDons() []ks_contracts_op.ConfigureKeystoneDON { return out } +func (d *dons) allDonCapabilities() []keystone_changeset.DonCapabilities { + out := make([]keystone_changeset.DonCapabilities, 0, len(d.c)) + for _, don := range d.c { + out = append(out, don.DonCapabilities) + } + return out +} + func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfigFns []cre.CapabilityRegistryConfigFn) error { if err := input.Validate(); err != nil { return errors.Wrap(err, "input validation failed") } - donCapabilities := make([]keystone_changeset.DonCapabilities, 0, len(input.Topology.DonsMetadata)) dons := &dons{ c: make(map[string]donConfig), } @@ -185,7 +192,6 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi Nops: []keystone_changeset.NOP{nop}, Capabilities: capabilities, } - donCapabilities = append(donCapabilities, c) dons.c[donName] = donConfig{ DonCapabilities: c, @@ -198,7 +204,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi ks_contracts_op.ConfigureCapabilitiesRegistrySeq, ks_contracts_op.ConfigureCapabilitiesRegistrySeqDeps{ Env: input.CldEnv, - Dons: donCapabilities, + Dons: dons.allDonCapabilities(), }, ks_contracts_op.ConfigureCapabilitiesRegistrySeqInput{ RegistryChainSel: input.ChainSelector, @@ -242,7 +248,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi // configure Solana forwarder only if we have some if len(solChainsWithForwarder) > 0 { - for _, don := range dons.allKeystoneDons() { + for _, don := range dons.donNodesets() { cs := commonchangeset.Configure(ks_solana.ConfigureForwarders{}, &ks_solana.ConfigureForwarderRequest{ WFDonName: don.Name, @@ -272,7 +278,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi }, ks_contracts_op.ConfigureForwardersSeqInput{ RegistryChainSel: input.ChainSelector, - DONs: dons.allKeystoneDons(), + DONs: dons.donNodesets(), Chains: evmChainsWithForwarders, }, ) diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index c3cdf266ee1..88c0176fc3d 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -252,25 +252,8 @@ func SetupTestEnvironment( } } } - /* - // use CLD to deploy the necessary contracts - homeChainSelector := homeChainOutput.ChainSelector - deployKeystoneReport, err := operations.ExecuteSequence( - allChainsCLDEnvironment.OperationsBundle, - ks_contracts_op.DeployKeystoneContractsSequence, - ks_contracts_op.DeployKeystoneContractsSequenceDeps{ - Env: allChainsCLDEnvironment, - }, - ks_contracts_op.DeployKeystoneContractsSequenceInput{ - RegistryChainSelector: homeChainSelector, - ForwardersSelectors: evmForwardersSelectors, - DeployVaultOCR3: vaultOCR3AddrFlag, - DeployEVMOCR3: evmOCR3AddrFlag, - EVMChainIDs: chainsWithEVMCapability, - DeployConsensusOCR3: consensusV2AddrFlag, - }, - ) - */ + + // use CLD to deploy the registry contracts, which are required before constructing the node TOML configs homeChainSelector := homeChainOutput.ChainSelector registryContractsReport, err := operations.ExecuteSequence( allChainsCLDEnvironment.OperationsBundle, @@ -1019,6 +1002,7 @@ func deployOCR3Contract(qualifier string, selector uint64, env *cldf.Environment if err != nil { return nil, fmt.Errorf("failed to deploy OCR3 contract '%s' on chain %d: %w", qualifier, selector, err) } + // TODO: CRE-742 remove address book if err = env.ExistingAddresses.Merge(ocr3DeployReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now return nil, fmt.Errorf("failed to merge address book with OCR3 contract address for '%s' on chain %d: %w", qualifier, selector, err) } From 7b8214cc32d48fa7257bf68bba404ad56af40893 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Mon, 1 Sep 2025 07:06:24 -0600 Subject: [PATCH 09/37] review comments --- .../contracts/deploy_forwarders_seq _test.go | 3 +- .../operations/contracts/deploy_ocr3_op.go | 7 ++- .../changeset/operations/contracts/types.go | 2 +- system-tests/lib/cre/contracts/contracts.go | 4 +- .../lib/cre/environment/environment.go | 54 +++++++++---------- system-tests/lib/cre/types.go | 2 +- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go index 699f57a2fc0..b099f8ad724 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_forwarders_seq _test.go @@ -26,7 +26,7 @@ func Test_DeployForwardersSeq(t *testing.T) { registrySel := env.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chain_selectors.FamilyEVM))[0] otherChainSel := env.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chain_selectors.FamilyEVM))[1] b := optest.NewBundle(t) - deps := contracts.DeployForwardersSequenceDeps{ + deps := contracts.DeployKeystoneForwardersSequenceDeps{ Env: &env, } input := contracts.DeployKeystoneForwardersInput{ @@ -39,4 +39,5 @@ func Test_DeployForwardersSeq(t *testing.T) { addrRefs, err := got.Output.Addresses.Fetch() require.NoError(t, err) require.Len(t, addrRefs, len(input.Targets)) + require.NotEmpty(t, got.Output.Datastore) } diff --git a/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go b/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go index 59f2abac67f..870e88195c5 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_ocr3_op.go @@ -6,7 +6,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/smartcontractkit/chainlink-deployments-framework/datastore" - "github.com/smartcontractkit/chainlink-deployments-framework/deployment" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" @@ -48,7 +47,7 @@ var DeployOCR3Op = operations.NewOperation[DeployOCR3OpInput, DeployOCR3OpOutput ) type DeployOCR3ContractSequenceDeps struct { - Env *deployment.Environment + Env *cldf.Environment } type DeployOCR3ContractSequenceInput struct { @@ -58,7 +57,7 @@ type DeployOCR3ContractSequenceInput struct { type DeployOCR3ContractSequenceOutput struct { // TODO: CRE-742 remove AddressBook - AddressBook deployment.AddressBook // Keeping the address store for backward compatibility, as not everything has been migrated to datastore + AddressBook cldf.AddressBook // Keeping the address store for backward compatibility, as not everything has been migrated to datastore Datastore datastore.DataStore } @@ -68,7 +67,7 @@ var DeployOCR3ContractsSequence = operations.NewSequence[DeployOCR3ContractSeque semver.MustParse("1.0.0"), "Deploy registry Contracts (Capabilities Registry, Workflow Registry)", func(b operations.Bundle, deps DeployOCR3ContractSequenceDeps, input DeployOCR3ContractSequenceInput) (output DeployOCR3ContractSequenceOutput, err error) { - ab := deployment.NewMemoryAddressBook() + ab := cldf.NewMemoryAddressBook() as := datastore.NewMemoryDataStore() // OCR3 Contract diff --git a/deployment/keystone/changeset/operations/contracts/types.go b/deployment/keystone/changeset/operations/contracts/types.go index eee1570bb09..51805aacffa 100644 --- a/deployment/keystone/changeset/operations/contracts/types.go +++ b/deployment/keystone/changeset/operations/contracts/types.go @@ -2,5 +2,5 @@ package contracts type ConfigureKeystoneDON struct { Name string - NodeIDs []string // usually peer IDs + NodeIDs []string // jd node ids or peer IDs } diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index cf3d8ab5b07..e31e1caed71 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -80,7 +80,7 @@ func (d *dons) ListByCapability(capName, capVersion string) ([]donConfig, error) out := make([]donConfig, 0) for _, don := range d.c { for _, cap := range don.Capabilities { - if cap.Capability.LabelledName == capName && cap.Capability.Version == capVersion { + if strings.EqualFold(cap.Capability.LabelledName, capName) && strings.EqualFold(cap.Capability.Version, capVersion) { out = append(out, don) break } @@ -358,7 +358,7 @@ func ConfigureKeystone(input cre.ConfigureKeystoneInput, capabilityRegistryConfi for chainSelector, evmOCR3Address := range *input.EVMOCR3Addresses { // not sure how to map EVM chains to DONs, so for now we assume that there's only one DON that supports EVM chains - evmDON, err := dons.shouldBeOneDon(cre.ReadContractCapability) + evmDON, err := dons.shouldBeOneDon(cre.EVMCapability) if err != nil { return fmt.Errorf("failed to get EVM DON: %w", err) } diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 88c0176fc3d..647875cb947 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -255,7 +255,7 @@ func SetupTestEnvironment( // use CLD to deploy the registry contracts, which are required before constructing the node TOML configs homeChainSelector := homeChainOutput.ChainSelector - registryContractsReport, err := operations.ExecuteSequence( + registryContractsReport, seqErr := operations.ExecuteSequence( allChainsCLDEnvironment.OperationsBundle, ks_contracts_op.DeployRegistryContractsSequence, ks_contracts_op.DeployContractsSequenceDeps{ @@ -265,20 +265,20 @@ func SetupTestEnvironment( RegistryChainSelector: homeChainSelector, }, ) - if err != nil { - return nil, pkgerrors.Wrap(err, "failed to deploy Keystone contracts") + if seqErr != nil { + return nil, pkgerrors.Wrap(seqErr, "failed to deploy Keystone contracts") } - if err = allChainsCLDEnvironment.ExistingAddresses.Merge(registryContractsReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now + if err := allChainsCLDEnvironment.ExistingAddresses.Merge(registryContractsReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now return nil, pkgerrors.Wrap(err, "failed to merge address book with Keystone contracts addresses") } - if err = memoryDatastore.Merge(registryContractsReport.Output.Datastore); err != nil { + if err := memoryDatastore.Merge(registryContractsReport.Output.Datastore); err != nil { return nil, pkgerrors.Wrap(err, "failed to merge datastore with Keystone contracts addresses") } // deploy evm forwarders - evmForwardersReport, err := operations.ExecuteSequence( + evmForwardersReport, seqErr := operations.ExecuteSequence( allChainsCLDEnvironment.OperationsBundle, ks_contracts_op.DeployKeystoneForwardersSequence, ks_contracts_op.DeployKeystoneForwardersSequenceDeps{ @@ -288,16 +288,16 @@ func SetupTestEnvironment( Targets: evmForwardersSelectors, }, ) - if err != nil { - return nil, pkgerrors.Wrap(err, "failed to deploy evm forwarder") + if seqErr != nil { + return nil, pkgerrors.Wrap(seqErr, "failed to deploy evm forwarder") } - if err = allChainsCLDEnvironment.ExistingAddresses.Merge(evmForwardersReport.Output.AddressBook); err != nil { //nolint:staticcheck // won't migrate now - return nil, pkgerrors.Wrap(err, "failed to merge address book with Keystone contracts addresses") + if seqErr = allChainsCLDEnvironment.ExistingAddresses.Merge(evmForwardersReport.Output.AddressBook); seqErr != nil { //nolint:staticcheck // won't migrate now + return nil, pkgerrors.Wrap(seqErr, "failed to merge address book with Keystone contracts addresses") } - if err = memoryDatastore.Merge(evmForwardersReport.Output.Datastore); err != nil { - return nil, pkgerrors.Wrap(err, "failed to merge datastore with Keystone contracts addresses") + if seqErr = memoryDatastore.Merge(evmForwardersReport.Output.Datastore); seqErr != nil { + return nil, pkgerrors.Wrap(seqErr, "failed to merge datastore with Keystone contracts addresses") } // deploy solana forwarders @@ -349,34 +349,34 @@ func SetupTestEnvironment( // deploy OCR3 contract // we deploy OCR3 contract with a qualifier, so that we can distinguish it from other OCR3 contracts (Vault, EVM, ConsensusV2) // TODO track the qualifiers in vars/consts rather than raw strings - _, err = deployOCR3Contract("capability_ocr3", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if err != nil { - return nil, fmt.Errorf("failed to deploy OCR3 contract %w", err) + _, seqErr = deployOCR3Contract("capability_ocr3", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) + if seqErr != nil { + return nil, fmt.Errorf("failed to deploy OCR3 contract %w", seqErr) } // deploy DONTime contract - _, err = deployOCR3Contract("DONTime", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if err != nil { - return nil, fmt.Errorf("failed to deploy DONTime contract %w", err) + _, seqErr = deployOCR3Contract("DONTime", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) + if seqErr != nil { + return nil, fmt.Errorf("failed to deploy DONTime contract %w", seqErr) } if vaultOCR3AddrFlag { - _, err = deployOCR3Contract("capability_vault", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if err != nil { - return nil, fmt.Errorf("failed to deploy Vault OCR3 contract %w", err) + _, seqErr = deployOCR3Contract("capability_vault", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) + if seqErr != nil { + return nil, fmt.Errorf("failed to deploy Vault OCR3 contract %w", seqErr) } } if evmOCR3AddrFlag { for chainID, selector := range chainsWithEVMCapability { qualifier := ks_contracts_op.GetCapabilityContractIdentifier(uint64(chainID)) - _, err = deployOCR3Contract(qualifier, uint64(selector), allChainsCLDEnvironment, memoryDatastore) - if err != nil { - return nil, fmt.Errorf("failed to deploy EVM OCR3 contract for chainID %d, selector %d: %w", chainID, selector, err) + _, seqErr = deployOCR3Contract(qualifier, uint64(selector), allChainsCLDEnvironment, memoryDatastore) + if seqErr != nil { + return nil, fmt.Errorf("failed to deploy EVM OCR3 contract for chainID %d, selector %d: %w", chainID, selector, seqErr) } } } if consensusV2AddrFlag { - _, err = deployOCR3Contract("capability_consensus", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if err != nil { - return nil, fmt.Errorf("failed to deploy Consensus V2 OCR3 contract %w", err) + _, seqErr = deployOCR3Contract("capability_consensus", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) + if seqErr != nil { + return nil, fmt.Errorf("failed to deploy Consensus V2 OCR3 contract %w", seqErr) } } allChainsCLDEnvironment.DataStore = memoryDatastore.Seal() diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index 4abad72b526..6ef83add1e4 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -496,7 +496,7 @@ type DonMetadata struct { func (m *DonMetadata) RequiresOCR() bool { return slices.Contains(m.Flags, ConsensusCapability) || slices.Contains(m.Flags, ConsensusCapabilityV2) || - slices.Contains(m.Flags, VaultCapability) || slices.Contains(m.Flags, ReadContractCapability) + slices.Contains(m.Flags, VaultCapability) || slices.Contains(m.Flags, EVMCapability) } type Label struct { From 8b3902d7bf5c2a02edc59b9059b42f7821764677 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Mon, 1 Sep 2025 17:13:42 +0200 Subject: [PATCH 10/37] use 4 nodes for capability DON, so they can run OCR. Fix internal hostname generation for capabilities DON --- .../configs/workflow-gateway-capabilities-don.toml | 2 +- system-tests/lib/cre/don/jobs/ocr/ocr.go | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml b/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml index acf51ea4be8..044b7a21d3d 100644 --- a/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml +++ b/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml @@ -84,7 +84,7 @@ """ [[nodesets]] - nodes = 2 + nodes = 4 name = "capabilities" don_types = ["capabilities"] override_mode = "all" diff --git a/system-tests/lib/cre/don/jobs/ocr/ocr.go b/system-tests/lib/cre/don/jobs/ocr/ocr.go index c0511559d95..4111fe7c773 100644 --- a/system-tests/lib/cre/don/jobs/ocr/ocr.go +++ b/system-tests/lib/cre/don/jobs/ocr/ocr.go @@ -89,6 +89,7 @@ func GenerateJobSpecsForStandardCapabilityWithOCR( return nil, errors.Wrap(err, "failed to find worker nodes") } + donName := donWithMetadata.Name // look for boostrap node and then for required values in its labels bootstrapNode, bootErr := node.FindOneWithLabel(donWithMetadata.NodesMetadata, &cre.Label{Key: node.NodeTypeKey, Value: cre.BootstrapNode}, node.EqualLabels) if bootErr != nil { @@ -103,6 +104,7 @@ func GenerateJobSpecsForStandardCapabilityWithOCR( if strings.Contains(p2pValue, donTopology.OCRPeeringData.OCRBootstraperPeerID) { bootstrapNode = n + donName = don.Name found = true break } @@ -119,9 +121,9 @@ func GenerateJobSpecsForStandardCapabilityWithOCR( return nil, errors.Wrap(nodeIDErr, "failed to get bootstrap node id from labels") } - internalHostsBS, err := getBoostrapWorkflowNames(bootstrapNode, donWithMetadata, infraInput) + internalHostsBS, err := getBoostrapWorkflowNames(bootstrapNode, donName, infraInput) if err != nil { - return nil, fmt.Errorf("no bootstrap node found for DON %s", donWithMetadata.Name) + return nil, fmt.Errorf("couldn't generate bootstrap node host for DON %s: %w", donName, err) } chainIDs, err := enabledChainsProvider(donTopology, nodeSetInput[donIdx], flag) @@ -258,7 +260,7 @@ func GenerateJobSpecsForStandardCapabilityWithOCR( return donToJobSpecs, nil } -func getBoostrapWorkflowNames(bootstrapNode *cre.NodeMetadata, donWithMetadata *cre.DonWithMetadata, infraInput *infra.Input) ([]string, error) { +func getBoostrapWorkflowNames(bootstrapNode *cre.NodeMetadata, donName string, infraInput *infra.Input) ([]string, error) { nodeIndexStr, nErr := node.FindLabelValue(bootstrapNode, node.IndexKey) if nErr != nil { return nil, errors.Wrap(nErr, "failed to find index label") @@ -269,7 +271,7 @@ func getBoostrapWorkflowNames(bootstrapNode *cre.NodeMetadata, donWithMetadata * return nil, errors.Wrap(nIErr, "failed to convert index label value to int") } - internalHostBS := don.InternalHost(nodeIndex, cre.BootstrapNode, donWithMetadata.Name, *infraInput) + internalHostBS := don.InternalHost(nodeIndex, cre.BootstrapNode, donName, *infraInput) return []string{internalHostBS}, nil } From aeaae8dc1c213ba2ff59e1a68e396687f453ea73 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 11:44:33 -0400 Subject: [PATCH 11/37] refactor(smoke/cre): accept v2 registry flag in PoR test --- system-tests/tests/smoke/cre/before_suite.go | 16 ++++++++++------ system-tests/tests/smoke/cre/cre_suite_test.go | 10 ++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/system-tests/tests/smoke/cre/before_suite.go b/system-tests/tests/smoke/cre/before_suite.go index 724c961315c..7b5103a2d5c 100644 --- a/system-tests/tests/smoke/cre/before_suite.go +++ b/system-tests/tests/smoke/cre/before_suite.go @@ -41,11 +41,11 @@ type TestEnvironment struct { } // setupTestEnvironment initializes the common test environment -func SetupTestEnvironment(t *testing.T) *TestEnvironment { +func SetupTestEnvironment(t *testing.T, flags ...string) *TestEnvironment { t.Helper() defaultTestConfig := getDefaultTestConfig(t) - createEnvironment(t, defaultTestConfig) + createEnvironment(t, defaultTestConfig, flags...) in := getEnvironmentConfig(t) envArtifact := getEnvironmentArtifact(t) fullCldEnvOutput, wrappedBlockchainOutputs, err := environment.BuildFromSavedState(t.Context(), cldlogger.NewSingleFileLogger(t), in, envArtifact) @@ -92,13 +92,13 @@ func getEnvironmentArtifact(t *testing.T) environment.EnvArtifact { return envArtifact } -func createEnvironment(t *testing.T, testConfig *TestConfig) { +func createEnvironment(t *testing.T, testConfig *TestConfig, flags ...string) { t.Helper() confErr := setConfigurationIfMissing(testConfig.EnvironmentConfigPath, testConfig.EnvironmentArtifactPath) require.NoError(t, confErr, "failed to set configuration") - createErr := createEnvironmentIfNotExists(testConfig.EnvironmentDirPath) + createErr := createEnvironmentIfNotExists(testConfig.EnvironmentDirPath, flags...) require.NoError(t, createErr, "failed to create environment") // transform the config file to the cache file, so that we can use the cached environment @@ -127,7 +127,7 @@ func setConfigurationIfMissing(configName, envArtifactPath string) error { return environment.SetDefaultPrivateKeyIfEmpty(blockchain.DefaultAnvilPrivateKey) } -func createEnvironmentIfNotExists(environmentDir string) error { +func createEnvironmentIfNotExists(environmentDir string, flags ...string) error { cachedConfigFile, cacheErr := ctfConfigToCacheFile() if cacheErr != nil { return errors.Wrap(cacheErr, "failed to get cached config file") @@ -135,7 +135,11 @@ func createEnvironmentIfNotExists(environmentDir string) error { if _, err := os.Stat(cachedConfigFile); os.IsNotExist(err) { framework.L.Info().Str("cached_config_file", cachedConfigFile).Msg("Cached config file does not exist, starting environment...") - cmd := exec.Command("go", "run", ".", "env", "start") + + args := []string{"run", ".", "env", "start"} + args = append(args, flags...) + + cmd := exec.Command("go", args...) cmd.Dir = environmentDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/system-tests/tests/smoke/cre/cre_suite_test.go b/system-tests/tests/smoke/cre/cre_suite_test.go index 836323f02be..582685f2c6a 100644 --- a/system-tests/tests/smoke/cre/cre_suite_test.go +++ b/system-tests/tests/smoke/cre/cre_suite_test.go @@ -47,3 +47,13 @@ func Test_CRE_Suite(t *testing.T) { }) }) } + +func Test_withV2Registries(t *testing.T) { + t.Run("[v1] CRE Proof of Reserve (PoR) Test", func(t *testing.T) { + const skipReason = "Integrate v2 registry contracts in local CRE/test setup - https://smartcontract-it.atlassian.net/browse/CRE-635" + t.Skipf("Skipping test for the following reason: %s", skipReason) + flags := []string{"--with-contracts-version", "v2"} + testEnv := SetupTestEnvironment(t, flags...) + ExecutePoRTest(t, testEnv) + }) +} From 25e9278cba323c799aa730d757b8ef9f4cecf1f3 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:20:42 -0400 Subject: [PATCH 12/37] feat(cre): get default contract set from cli flag --- .../environment/environment/environment.go | 9 ++-- .../lib/cre/environment/config/config.go | 31 ++++++++----- system-tests/lib/cre/types.go | 45 ++++++++++++++++++- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/core/scripts/cre/environment/environment/environment.go b/core/scripts/cre/environment/environment/environment.go index 7a50b7f055a..ca4ea70302e 100644 --- a/core/scripts/cre/environment/environment/environment.go +++ b/core/scripts/cre/environment/environment/environment.go @@ -286,14 +286,11 @@ func startCmd() *cobra.Command { return err } - contractVersionOverrides := make(map[string]string, 0) - if withContractsVersion == "v2" { - contractVersionOverrides[keystone_changeset.CapabilitiesRegistry.String()] = "2.0.0" - contractVersionOverrides[keystone_changeset.WorkflowRegistry.String()] = "2.0.0" - } + withV2Registries := withContractsVersion == "v2" envDependencies := cre.NewEnvironmentDependencies( flags.NewDefaultCapabilityFlagsProvider(), - cre.NewContractVersionsProvider(contractVersionOverrides), + cre.NewContractVersionsProvider(envconfig.GetDefaultContractSet(withV2Registries)), + cre.NewCLIFlagsProvider(withPluginsDockerImage, withV2Registries, withBeholder), ) if err := in.Validate(envDependencies); err != nil { diff --git a/system-tests/lib/cre/environment/config/config.go b/system-tests/lib/cre/environment/config/config.go index 430be732074..9eab1bc251a 100644 --- a/system-tests/lib/cre/environment/config/config.go +++ b/system-tests/lib/cre/environment/config/config.go @@ -49,21 +49,16 @@ func (c Config) Validate(envDependencies cre.CLIEnvironmentDependencies) error { } } - if err := validateContractVersions(envDependencies.GetContractVersions()); err != nil { + if err := validateContractVersions(envDependencies); err != nil { return fmt.Errorf("failed to validate initial contract set: %w", err) } return nil } -// TODO(CRE-741): support contracts other than major version 1 -func validateContractVersions(cv map[string]string) error { - supportedSet := map[string]string{ - keystone_changeset.OCR3Capability.String(): "1.0.0", - keystone_changeset.WorkflowRegistry.String(): "1.0.0", - keystone_changeset.CapabilitiesRegistry.String(): "1.1.0", - keystone_changeset.KeystoneForwarder.String(): "1.0.0", - } +func validateContractVersions(envDependencies cre.CLIEnvironmentDependencies) error { + supportedSet := GetDefaultContractSet(envDependencies.GetCLIFlags().WithV2Registries) + cv := envDependencies.GetContractVersions() for k, v := range supportedSet { version, ok := cv[k] if !ok { @@ -71,12 +66,28 @@ func validateContractVersions(cv map[string]string) error { } if version != v { - return fmt.Errorf("unsupported version %s for contract %s configured for deployment", v, k) + return fmt.Errorf("requested version %s for contract %s yet expected %s", version, k, v) } } return nil } +func GetDefaultContractSet(withV2Registries bool) map[string]string { + supportedSet := map[string]string{ + keystone_changeset.OCR3Capability.String(): "1.0.0", + keystone_changeset.WorkflowRegistry.String(): "1.0.0", + keystone_changeset.CapabilitiesRegistry.String(): "1.1.0", + keystone_changeset.KeystoneForwarder.String(): "1.0.0", + } + + if withV2Registries { + supportedSet[keystone_changeset.WorkflowRegistry.String()] = "2.0.0" + supportedSet[keystone_changeset.CapabilitiesRegistry.String()] = "2.0.0" + } + + return supportedSet +} + // ResolveCapabilityForChain merges defaults with chain override for a capability on a given chain. // Returns (enabled, mergedConfig). func ResolveCapabilityForChain( diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index efa85221e22..6cda4a3a331 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -66,6 +66,39 @@ const ( type CLIEnvironmentDependencies interface { CapabilityFlagsProvider ContractVersionsProvider + CLIFlagsProvider +} + +type CLIFlags struct { + WithV2Registries bool + WithPluginsDockerImage string + WithBeholder bool +} + +type CLIFlagsProvider interface { + GetCLIFlags() *CLIFlags +} + +func NewCLIFlagsProvider( + withPluginsDockerImage string, + withV2Registries, withBeholder bool, +) *cliFlagsProvider { + flags := &CLIFlags{ + WithV2Registries: withV2Registries, + WithPluginsDockerImage: withPluginsDockerImage, + WithBeholder: withBeholder, + } + return &cliFlagsProvider{ + flags: flags, + } +} + +type cliFlagsProvider struct { + flags *CLIFlags +} + +func (cfp *cliFlagsProvider) GetCLIFlags() *CLIFlags { + return cfp.flags } type ContractVersionsProvider interface { @@ -106,16 +139,26 @@ type CapabilityFlagsProvider interface { ChainSpecificCapabilityFlags() []CapabilityFlag } -func NewEnvironmentDependencies(cfp CapabilityFlagsProvider, cvp ContractVersionsProvider) *envionmentDependencies { +func NewEnvironmentDependencies( + cfp CapabilityFlagsProvider, + cvp ContractVersionsProvider, + cliFlagsProvider CLIFlagsProvider, +) *envionmentDependencies { return &envionmentDependencies{ flagsProvider: cfp, contractSetProvider: cvp, + cliFlagsProvider: cliFlagsProvider, } } type envionmentDependencies struct { flagsProvider CapabilityFlagsProvider contractSetProvider ContractVersionsProvider + cliFlagsProvider CLIFlagsProvider +} + +func (e *envionmentDependencies) GetCLIFlags() *CLIFlags { + return e.cliFlagsProvider.GetCLIFlags() } func (e *envionmentDependencies) GetContractVersions() map[string]string { From b9172b04c64166eeb770cf5eb2d80becffd82002 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 16:51:23 -0400 Subject: [PATCH 13/37] refactor(cre): cli flags clean up --- .../environment/environment/environment.go | 2 +- .../lib/cre/environment/config/config.go | 2 +- system-tests/lib/cre/types.go | 37 ++++++------------- 3 files changed, 13 insertions(+), 28 deletions(-) diff --git a/core/scripts/cre/environment/environment/environment.go b/core/scripts/cre/environment/environment/environment.go index ca4ea70302e..13795ec73f8 100644 --- a/core/scripts/cre/environment/environment/environment.go +++ b/core/scripts/cre/environment/environment/environment.go @@ -290,7 +290,7 @@ func startCmd() *cobra.Command { envDependencies := cre.NewEnvironmentDependencies( flags.NewDefaultCapabilityFlagsProvider(), cre.NewContractVersionsProvider(envconfig.GetDefaultContractSet(withV2Registries)), - cre.NewCLIFlagsProvider(withPluginsDockerImage, withV2Registries, withBeholder), + cre.NewCLIFlagsProvider(withV2Registries), ) if err := in.Validate(envDependencies); err != nil { diff --git a/system-tests/lib/cre/environment/config/config.go b/system-tests/lib/cre/environment/config/config.go index 9eab1bc251a..98679af0601 100644 --- a/system-tests/lib/cre/environment/config/config.go +++ b/system-tests/lib/cre/environment/config/config.go @@ -57,7 +57,7 @@ func (c Config) Validate(envDependencies cre.CLIEnvironmentDependencies) error { } func validateContractVersions(envDependencies cre.CLIEnvironmentDependencies) error { - supportedSet := GetDefaultContractSet(envDependencies.GetCLIFlags().WithV2Registries) + supportedSet := GetDefaultContractSet(envDependencies.GetCLIFlags().WithV2Registries()) cv := envDependencies.GetContractVersions() for k, v := range supportedSet { version, ok := cv[k] diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index 6cda4a3a331..c0d86430082 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -66,39 +66,26 @@ const ( type CLIEnvironmentDependencies interface { CapabilityFlagsProvider ContractVersionsProvider - CLIFlagsProvider -} - -type CLIFlags struct { - WithV2Registries bool - WithPluginsDockerImage string - WithBeholder bool + GetCLIFlags() CLIFlagsProvider } type CLIFlagsProvider interface { - GetCLIFlags() *CLIFlags + // If true, then use V2 Capability and Workflow Registries. + WithV2Registries() bool } -func NewCLIFlagsProvider( - withPluginsDockerImage string, - withV2Registries, withBeholder bool, -) *cliFlagsProvider { - flags := &CLIFlags{ - WithV2Registries: withV2Registries, - WithPluginsDockerImage: withPluginsDockerImage, - WithBeholder: withBeholder, - } +func NewCLIFlagsProvider(withV2Registries bool) *cliFlagsProvider { return &cliFlagsProvider{ - flags: flags, + withV2Registries: withV2Registries, } } type cliFlagsProvider struct { - flags *CLIFlags + withV2Registries bool } -func (cfp *cliFlagsProvider) GetCLIFlags() *CLIFlags { - return cfp.flags +func (cfp *cliFlagsProvider) WithV2Registries() bool { + return cfp.withV2Registries } type ContractVersionsProvider interface { @@ -127,9 +114,7 @@ func NewContractVersionsProvider(overrides map[string]string) *contractVersionsP ks_sol.ForwarderState.String(): "1.0.0", }, } - for k, v := range overrides { - cvp.contracts[k] = v - } + maps.Copy(cvp.contracts, overrides) return cvp } @@ -157,8 +142,8 @@ type envionmentDependencies struct { cliFlagsProvider CLIFlagsProvider } -func (e *envionmentDependencies) GetCLIFlags() *CLIFlags { - return e.cliFlagsProvider.GetCLIFlags() +func (e *envionmentDependencies) GetCLIFlags() CLIFlagsProvider { + return e.cliFlagsProvider } func (e *envionmentDependencies) GetContractVersions() map[string]string { From d8d02501cb044cd988a6e793b32fff163e12c603 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Thu, 28 Aug 2025 12:35:14 -0400 Subject: [PATCH 14/37] feat(operations): deploy v2 cap registry --- .../contracts/deploy_contracts_seq.go | 74 ++++++++++++++++--- 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index cf7450a0ec2..dfc3fc54dc9 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -8,14 +8,18 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" + + cap_reg_v2 "github.com/smartcontractkit/chainlink/deployment/cre/capabilities_registry/v2/changeset/operations/contracts" ) type DeployKeystoneContractsSequenceDeps struct { Env *deployment.Environment } -type EVMChainID uint64 -type Selector uint64 +type ( + EVMChainID uint64 + Selector uint64 +) // inputs and outputs have to be serializable, and must not contain sensitive data @@ -26,6 +30,9 @@ type DeployKeystoneContractsSequenceInput struct { DeployEVMOCR3 bool EVMChainIDs map[EVMChainID]Selector DeployConsensusOCR3 bool + + // WithV2Contracts if true will deploy Capability Registry V2 + WithV2Contracts bool } type DeployKeystoneContractsSequenceOutput struct { @@ -59,13 +66,29 @@ var DeployKeystoneContractsSequence = operations.NewSequence[DeployKeystoneContr as := datastore.NewMemoryDataStore() // Capabilities Registry contract - capabilitiesRegistryDeployReport, err := operations.ExecuteOperation(b, DeployCapabilityRegistryOp, DeployCapabilityRegistryOpDeps(deps), DeployCapabilityRegistryInput{ChainSelector: input.RegistryChainSelector}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), capabilitiesRegistryDeployReport.Output.Addresses, ab, capabilitiesRegistryDeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + if input.WithV2Contracts { + v2Report, err := operations.ExecuteOperation(b, cap_reg_v2.DeployCapabilitiesRegistry, cap_reg_v2.DeployCapabilitiesRegistryDeps(deps), cap_reg_v2.DeployCapabilitiesRegistryInput{ + ChainSelector: input.RegistryChainSelector, + }) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } + + out, err := ToV1Output(v2Report.Output) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } + + err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook) + } else { + capabilitiesRegistryDeployReport, err := operations.ExecuteOperation(b, DeployCapabilityRegistryOp, DeployCapabilityRegistryOpDeps(deps), DeployCapabilityRegistryInput{ChainSelector: input.RegistryChainSelector}) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } + err = updateAddresses(as.Addresses(), capabilitiesRegistryDeployReport.Output.Addresses, ab, capabilitiesRegistryDeployReport.Output.AddressBook) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } } // OCR3 Contract @@ -156,3 +179,36 @@ var DeployKeystoneContractsSequence = operations.NewSequence[DeployKeystoneContr func GetCapabilityContractIdentifier(chainID uint64) string { return fmt.Sprintf("capability_evm_%d", chainID) } + +// ToV1Output transforms the v2 output to v1 output by creating an address book +func ToV1Output(in cap_reg_v2.DeployCapabilitiesRegistryOutput) (DeployCapabilityRegistryOutput, error){ + ab := deployment.NewMemoryAddressBook() + ds := datastore.NewMemoryDataStore() + r := datastore.AddressRef{ + ChainSelector: in.ChainSelector, + Address: in.Address, + Type: datastore.ContractType(in.Type), + Version: semver.MustParse(in.Version), + Qualifier: in.Qualifier, + Labels: datastore.NewLabelSet(), + } + for _, l := range in.Labels { + r.Labels.Add(l) + } + + if err := ds.Addresses().Add(r); err != nil { + return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to add address ref: %w", err) + } + + if err := ab.Save(in.ChainSelector, in.Address, deployment.TypeAndVersion{ + Type: deployment.ContractType(in.Type), + Version: *semver.MustParse(in.Version), + Labels: deployment.NewLabelSet(in.Labels...), + }); err != nil { + return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to save address to address book: %w", err) + } + return DeployCapabilityRegistryOutput{ + Addresses: ds.Addresses(), + AddressBook: ab, + }, nil +} \ No newline at end of file From 407ecb4c64114bbf1a8d872611f14429ab12da7d Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Thu, 28 Aug 2025 14:03:04 -0400 Subject: [PATCH 15/37] refactor(capabilities): allow setting v2 config for cap --- system-tests/lib/cre/capabilities/builder.go | 29 ++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/system-tests/lib/cre/capabilities/builder.go b/system-tests/lib/cre/capabilities/builder.go index 43fb8a02dd2..3f14b3b0d14 100644 --- a/system-tests/lib/cre/capabilities/builder.go +++ b/system-tests/lib/cre/capabilities/builder.go @@ -7,12 +7,15 @@ import ( ) type Capability struct { - flag cre.CapabilityFlag - jobSpecFn cre.JobSpecFn - nodeConfigFn cre.NodeConfigFn - gatewayJobHandlerConfigFn cre.GatewayHandlerConfigFn - capabilityRegistryV1ConfigFn cre.CapabilityRegistryConfigFn - validateFn func(*Capability) error + flag cre.CapabilityFlag + jobSpecFn cre.JobSpecFn + nodeConfigFn cre.NodeConfigFn + gatewayJobHandlerConfigFn cre.GatewayHandlerConfigFn + registryConfigFns struct { + V1 cre.CapabilityRegistryConfigFn + V2 cre.CapabilityRegistryConfigFn + } + validateFn func(*Capability) error } func (c *Capability) Flag() cre.CapabilityFlag { @@ -32,7 +35,11 @@ func (c *Capability) GatewayJobHandlerConfigFn() cre.GatewayHandlerConfigFn { } func (c *Capability) CapabilityRegistryV1ConfigFn() cre.CapabilityRegistryConfigFn { - return c.capabilityRegistryV1ConfigFn + return c.registryConfigFns.V1 +} + +func (c *Capability) CapabilityRegistryV2ConfigFn() cre.CapabilityRegistryConfigFn { + return c.registryConfigFns.V2 } type Option func(*Capability) @@ -57,7 +64,13 @@ func WithGatewayJobHandlerConfigFn(gatewayJobHandlerConfigFn cre.GatewayHandlerC func WithCapabilityRegistryV1ConfigFn(capabilityRegistryV1ConfigFn cre.CapabilityRegistryConfigFn) Option { return func(c *Capability) { - c.capabilityRegistryV1ConfigFn = capabilityRegistryV1ConfigFn + c.registryConfigFns.V1 = capabilityRegistryV1ConfigFn + } +} + +func WithCapabilityRegistryV2ConfigFn(capabilityRegistryV1ConfigFn cre.CapabilityRegistryConfigFn) Option { + return func(c *Capability) { + c.registryConfigFns.V2 = capabilityRegistryV1ConfigFn } } From 2fcdc8f062c34592c6f3c0269979a0dcac2f5658 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Thu, 28 Aug 2025 15:42:30 -0400 Subject: [PATCH 16/37] chore: wire in v2 contracts --- system-tests/lib/cre/capabilities/builder.go | 19 ++++++++++++++---- system-tests/lib/cre/don/config/config.go | 5 +++-- .../lib/cre/don/config/definitions.go | 20 +++++++++++++++++-- .../lib/cre/environment/environment.go | 15 ++++++++++++-- system-tests/lib/cre/environment/topology.go | 2 ++ system-tests/lib/cre/types.go | 5 +++++ 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/system-tests/lib/cre/capabilities/builder.go b/system-tests/lib/cre/capabilities/builder.go index 3f14b3b0d14..8e41fe9a66e 100644 --- a/system-tests/lib/cre/capabilities/builder.go +++ b/system-tests/lib/cre/capabilities/builder.go @@ -3,18 +3,21 @@ package capabilities import ( "github.com/pkg/errors" + keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/system-tests/lib/cre" ) +type registryConfigFns struct { + V1 cre.CapabilityRegistryConfigFn + V2 cre.CapabilityRegistryConfigFn +} + type Capability struct { flag cre.CapabilityFlag jobSpecFn cre.JobSpecFn nodeConfigFn cre.NodeConfigFn gatewayJobHandlerConfigFn cre.GatewayHandlerConfigFn - registryConfigFns struct { - V1 cre.CapabilityRegistryConfigFn - V2 cre.CapabilityRegistryConfigFn - } + registryConfigFns registryConfigFns validateFn func(*Capability) error } @@ -83,6 +86,10 @@ func WithValidateFn(validateFn func(*Capability) error) Option { func New(flag cre.CapabilityFlag, opts ...Option) (*Capability, error) { capability := &Capability{ flag: flag, + registryConfigFns: registryConfigFns{ + V1: unimplmentedConfigFn, + V2: unimplmentedConfigFn, + }, } for _, opt := range opts { opt(capability) @@ -96,3 +103,7 @@ func New(flag cre.CapabilityFlag, opts ...Option) (*Capability, error) { return capability, nil } + +func unimplmentedConfigFn(donFlags []cre.CapabilityFlag, nodeSetInput *cre.CapabilitiesAwareNodeSet) ([]keystone_changeset.DONCapabilityWithConfig, error){ + return nil, errors.New("config function is not implemented") +} \ No newline at end of file diff --git a/system-tests/lib/cre/don/config/config.go b/system-tests/lib/cre/don/config/config.go index fb4d3a9a262..0e0fe3aedc6 100644 --- a/system-tests/lib/cre/don/config/config.go +++ b/system-tests/lib/cre/don/config/config.go @@ -156,7 +156,7 @@ func Generate(input cre.GenerateConfigsInput, nodeConfigFns []cre.NodeConfigFn) } // generate configuration for the bootstrap node - configOverrides[nodeIndex] = BootstrapEVM(donBootstrapNodePeerID, homeChainID, capabilitiesRegistryAddress, workerEVMInputs) + configOverrides[nodeIndex] = BootstrapEVM(donBootstrapNodePeerID, homeChainID, capabilitiesRegistryAddress, workerEVMInputs, input.WithV2RegistryContracts) if flags.HasFlag(input.Flags, cre.WorkflowDON) { configOverrides[nodeIndex] += BoostrapDon2DonPeering(input.CapabilitiesPeeringData) } @@ -300,7 +300,8 @@ func Generate(input cre.GenerateConfigsInput, nodeConfigFns []cre.NodeConfigFn) // connect worker nodes to all the chains, add chain ID for registry (home chain) // we configure both EVM chains, nodes and EVM.Workflow with Forwarder var workerErr error - configOverrides[nodeIndex], workerErr = WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost, input.OCRPeeringData, input.CapabilitiesPeeringData, capabilitiesRegistryAddress, homeChainID, workerEVMInputs) + configOverrides[nodeIndex], workerErr = WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost, input.OCRPeeringData, + input.CapabilitiesPeeringData, capabilitiesRegistryAddress, homeChainID, workerEVMInputs, input.WithV2RegistryContracts) if workerErr != nil { return nil, errors.Wrap(workerErr, "failed to generate worker [EVM.Workflow] config") } diff --git a/system-tests/lib/cre/don/config/definitions.go b/system-tests/lib/cre/don/config/definitions.go index c47877d04b5..6f7c59cf70f 100644 --- a/system-tests/lib/cre/don/config/definitions.go +++ b/system-tests/lib/cre/don/config/definitions.go @@ -44,7 +44,8 @@ const ( ` ) -func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitiesRegistryAddress common.Address, chains []*WorkerEVMInput) string { +func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitiesRegistryAddress common.Address, + chains []*WorkerEVMInput, withV2RegistryContracts bool) string { evmChainsConfig := "" for _, chain := range chains { evmChainsConfig += fmt.Sprintf(` @@ -63,6 +64,10 @@ func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitie chain.HTTPRPC, ) } + version := "1.0.0" + if withV2RegistryContracts { + version = "2.0.0" + } return fmt.Sprintf(` [Feature] LogPoller = true @@ -85,11 +90,13 @@ func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitie Address = '%s' NetworkID = 'evm' ChainID = '%d' + ContractVersion = '%s' `, donBootstrapNodePeerID, evmChainsConfig, capabilitiesRegistryAddress, homeChainID, + version, ) } @@ -119,7 +126,9 @@ type WorkerEVMInput struct { WorkflowConfig map[string]any // Configuration for EVM.Workflow section } -func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringData cre.OCRPeeringData, capabilitiesPeeringData cre.CapabilitiesPeeringData, capabilitiesRegistryAddress common.Address, homeChainID uint64, chains []*WorkerEVMInput) (string, error) { +func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringData cre.OCRPeeringData, + capabilitiesPeeringData cre.CapabilitiesPeeringData, capabilitiesRegistryAddress common.Address, + homeChainID uint64, chains []*WorkerEVMInput, withV2RegistryContracts bool) (string, error) { evmChainsConfig := "" for _, chain := range chains { evmChainsConfig += fmt.Sprintf(` @@ -165,6 +174,11 @@ func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringDa } } + version := "1.0.0" + if withV2RegistryContracts { + version = "2.0.0" + } + return fmt.Sprintf(` [Feature] LogPoller = true @@ -191,6 +205,7 @@ func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringDa Address = '%s' NetworkID = 'evm' ChainID = '%d' + ContractVersion = '%s' `, ocrPeeringData.Port, donBootstrapNodePeerID, @@ -203,6 +218,7 @@ func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringDa evmChainsConfig, capabilitiesRegistryAddress, homeChainID, + version, ), nil } diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index bbe56c0a7ee..fcfe2d9e0ad 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -40,7 +40,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/framework/components/s3provider" ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink/deployment" keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ks_contracts_op "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/operations/contracts" @@ -120,12 +119,17 @@ func mustGetAddress(dataStore datastore.MutableDataStore, chainSel uint64, contr return addrRef.Address } +func useV2registryContracts(cvs map[string]string) bool { + return false +} + func SetupTestEnvironment( ctx context.Context, testLogger zerolog.Logger, singleFileLogger logger.Logger, input SetupInput, ) (*SetupOutput, error) { + withV2RegistryContracts := useV2registryContracts(input.ContractVersions) topologyErr := libdon.ValidateTopology(input.CapabilitiesAwareNodeSets, input.InfraInput) if topologyErr != nil { return nil, pkgerrors.Wrap(topologyErr, "failed to validate topology") @@ -268,6 +272,7 @@ func SetupTestEnvironment( DeployEVMOCR3: evmOCR3AddrFlag, EVMChainIDs: chainsWithEVMCapability, DeployConsensusOCR3: consensusV2AddrFlag, + WithV2Contracts: withV2RegistryContracts, }, ) if err != nil { @@ -409,6 +414,7 @@ func SetupTestEnvironment( input.Capabilities, input.CapabilityConfigs, input.CopyCapabilityBinaries, + withV2RegistryContracts, ) if topoErr != nil { return nil, pkgerrors.Wrap(topoErr, "failed to build topology") @@ -726,7 +732,12 @@ func SetupTestEnvironment( capabilitiesContractFactoryFunctions := make([]cre.CapabilityRegistryConfigFn, 0) for _, capability := range input.Capabilities { - capabilitiesContractFactoryFunctions = append(capabilitiesContractFactoryFunctions, capability.CapabilityRegistryV1ConfigFn()) + configFn := capability.CapabilityRegistryV1ConfigFn() + if withV2RegistryContracts { + configFn = capability.CapabilityRegistryV2ConfigFn() + } + + capabilitiesContractFactoryFunctions = append(capabilitiesContractFactoryFunctions, configFn) } // Deprecated, use Capabilities instead diff --git a/system-tests/lib/cre/environment/topology.go b/system-tests/lib/cre/environment/topology.go index 5fbaaa2cfa0..77931845f1d 100644 --- a/system-tests/lib/cre/environment/topology.go +++ b/system-tests/lib/cre/environment/topology.go @@ -32,6 +32,7 @@ func BuildTopology( capabilities []cre.InstallableCapability, capabilityConfigs cre.CapabilityConfigs, copyCapabilityBinaries bool, + withV2RegistryContracts bool, ) (*cre.Topology, []*cre.CapabilitiesAwareNodeSet, error) { topologyErr := libdon.ValidateTopology(nodeSets, infraInput) if topologyErr != nil { @@ -127,6 +128,7 @@ func BuildTopology( GatewayConnectorOutput: topology.GatewayConnectorOutput, NodeSet: localNodeSets[i], CapabilityConfigs: capabilityConfigs, + WithV2RegistryContracts: withV2RegistryContracts, }, configFactoryFunctions, ) diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index c0d86430082..0ab6474e148 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -467,6 +467,7 @@ type GenerateConfigsInput struct { NodeSet *CapabilitiesAwareNodeSet CapabilityConfigs CapabilityConfigs GatewayConnectorOutput *GatewayConnectorOutput // optional, automatically set if some DON in the topology has the GatewayDON flag + WithV2RegistryContracts bool } func (g *GenerateConfigsInput) Validate() error { @@ -1072,4 +1073,8 @@ type InstallableCapability interface { // CapabilityRegistryV1ConfigFn returns a function to generate capability registry // configuration for the v1 registry format CapabilityRegistryV1ConfigFn() CapabilityRegistryConfigFn + + // CapabilityRegistryV2ConfigFn returns a function to generate capability registry + // configuration for the v2 registry format + CapabilityRegistryV2ConfigFn() CapabilityRegistryConfigFn } From 1baa38539d76f1349926ea9a348db9747d203171 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 10:47:14 -0400 Subject: [PATCH 17/37] refactor(environment): remove lint warnings --- system-tests/lib/cre/environment/create_jd_jobs_op.go | 4 ++-- system-tests/lib/cre/environment/environment.go | 2 +- system-tests/lib/cre/environment/fund_cl_nodes_op.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/system-tests/lib/cre/environment/create_jd_jobs_op.go b/system-tests/lib/cre/environment/create_jd_jobs_op.go index b5966d275f6..1e2ab4aecc6 100644 --- a/system-tests/lib/cre/environment/create_jd_jobs_op.go +++ b/system-tests/lib/cre/environment/create_jd_jobs_op.go @@ -36,7 +36,7 @@ type CreateJobsWithJdOpInput struct { type CreateJobsWithJdOpOutput struct { } -var CreateJobsWithJdOp = operations.NewOperation[CreateJobsWithJdOpInput, CreateJobsWithJdOpOutput, CreateJobsWithJdOpDeps]( +var CreateJobsWithJdOp = operations.NewOperation( "create-jobs-op", semver.MustParse("1.0.0"), "Create Jobs", @@ -84,7 +84,7 @@ var CreateJobsWithJdOp = operations.NewOperation[CreateJobsWithJdOpInput, Create // CreateJobsWithJdOpFactory creates a new operation with user-specified ID and version func CreateJobsWithJdOpFactory(id string, version string) *operations.Operation[CreateJobsWithJdOpInput, CreateJobsWithJdOpOutput, CreateJobsWithJdOpDeps] { - return operations.NewOperation[CreateJobsWithJdOpInput, CreateJobsWithJdOpOutput, CreateJobsWithJdOpDeps]( + return operations.NewOperation( id, semver.MustParse(version), "Create Jobs", diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index fcfe2d9e0ad..d1c6c49b307 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -119,7 +119,7 @@ func mustGetAddress(dataStore datastore.MutableDataStore, chainSel uint64, contr return addrRef.Address } -func useV2registryContracts(cvs map[string]string) bool { +func useV2registryContracts(_ map[string]string) bool { return false } diff --git a/system-tests/lib/cre/environment/fund_cl_nodes_op.go b/system-tests/lib/cre/environment/fund_cl_nodes_op.go index d21e5b52e3e..21310400e81 100644 --- a/system-tests/lib/cre/environment/fund_cl_nodes_op.go +++ b/system-tests/lib/cre/environment/fund_cl_nodes_op.go @@ -34,7 +34,7 @@ type FundCLNodesOpInput struct { type FundCLNodesOpOutput struct { } -var FundCLNodesOp = operations.NewOperation[FundCLNodesOpInput, FundCLNodesOpOutput, FundCLNodesOpDeps]( +var FundCLNodesOp = operations.NewOperation( "fund-cl-nodes-op", semver.MustParse("1.0.0"), "Fund Chainlink Nodes", From 3636fc6b19fe42c0a6660551b65fdcb4fb97275f Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:32:36 -0400 Subject: [PATCH 18/37] chore: support checking registry version --- system-tests/lib/cre/environment/environment.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index d1c6c49b307..e53df1793a6 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -119,8 +119,8 @@ func mustGetAddress(dataStore datastore.MutableDataStore, chainSel uint64, contr return addrRef.Address } -func useV2registryContracts(_ map[string]string) bool { - return false +func useV2registryContracts(cv map[string]string) bool { + return cv[keystone_changeset.CapabilitiesRegistry.String()] == "2.0.0" && cv[keystone_changeset.WorkflowRegistry.String()] == "2.0.0" } func SetupTestEnvironment( @@ -733,7 +733,7 @@ func SetupTestEnvironment( capabilitiesContractFactoryFunctions := make([]cre.CapabilityRegistryConfigFn, 0) for _, capability := range input.Capabilities { configFn := capability.CapabilityRegistryV1ConfigFn() - if withV2RegistryContracts { + if withV2RegistryContracts { configFn = capability.CapabilityRegistryV2ConfigFn() } From 08a9d1748b963fc90bbcd3a4945e06f4917bb821 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:58:40 -0400 Subject: [PATCH 19/37] refactor(lib/cre): get type and version when fetching contract --- system-tests/lib/cre/capabilities/builder.go | 18 +++++----- .../lib/cre/capabilities/gateway/gateway.go | 2 +- system-tests/lib/cre/contracts/contracts.go | 14 ++++---- system-tests/lib/cre/don/config/config.go | 13 ++++--- .../lib/cre/don/config/definitions.go | 36 +++++++++---------- .../lib/cre/environment/environment.go | 1 - system-tests/lib/cre/environment/topology.go | 2 -- system-tests/lib/cre/types.go | 1 - system-tests/lib/crecli/settings.go | 8 ++--- 9 files changed, 48 insertions(+), 47 deletions(-) diff --git a/system-tests/lib/cre/capabilities/builder.go b/system-tests/lib/cre/capabilities/builder.go index 8e41fe9a66e..d2b3352ac9c 100644 --- a/system-tests/lib/cre/capabilities/builder.go +++ b/system-tests/lib/cre/capabilities/builder.go @@ -8,8 +8,8 @@ import ( ) type registryConfigFns struct { - V1 cre.CapabilityRegistryConfigFn - V2 cre.CapabilityRegistryConfigFn + V1 cre.CapabilityRegistryConfigFn + V2 cre.CapabilityRegistryConfigFn } type Capability struct { @@ -18,7 +18,7 @@ type Capability struct { nodeConfigFn cre.NodeConfigFn gatewayJobHandlerConfigFn cre.GatewayHandlerConfigFn registryConfigFns registryConfigFns - validateFn func(*Capability) error + validateFn func(*Capability) error } func (c *Capability) Flag() cre.CapabilityFlag { @@ -65,15 +65,15 @@ func WithGatewayJobHandlerConfigFn(gatewayJobHandlerConfigFn cre.GatewayHandlerC } } -func WithCapabilityRegistryV1ConfigFn(capabilityRegistryV1ConfigFn cre.CapabilityRegistryConfigFn) Option { +func WithCapabilityRegistryV1ConfigFn(fn cre.CapabilityRegistryConfigFn) Option { return func(c *Capability) { - c.registryConfigFns.V1 = capabilityRegistryV1ConfigFn + c.registryConfigFns.V1 = fn } } -func WithCapabilityRegistryV2ConfigFn(capabilityRegistryV1ConfigFn cre.CapabilityRegistryConfigFn) Option { +func WithCapabilityRegistryV2ConfigFn(fn cre.CapabilityRegistryConfigFn) Option { return func(c *Capability) { - c.registryConfigFns.V2 = capabilityRegistryV1ConfigFn + c.registryConfigFns.V2 = fn } } @@ -104,6 +104,6 @@ func New(flag cre.CapabilityFlag, opts ...Option) (*Capability, error) { return capability, nil } -func unimplmentedConfigFn(donFlags []cre.CapabilityFlag, nodeSetInput *cre.CapabilitiesAwareNodeSet) ([]keystone_changeset.DONCapabilityWithConfig, error){ +func unimplmentedConfigFn(donFlags []cre.CapabilityFlag, nodeSetInput *cre.CapabilitiesAwareNodeSet) ([]keystone_changeset.DONCapabilityWithConfig, error) { return nil, errors.New("config function is not implemented") -} \ No newline at end of file +} diff --git a/system-tests/lib/cre/capabilities/gateway/gateway.go b/system-tests/lib/cre/capabilities/gateway/gateway.go index 3ad7a1dbdca..3b17bb3c050 100644 --- a/system-tests/lib/cre/capabilities/gateway/gateway.go +++ b/system-tests/lib/cre/capabilities/gateway/gateway.go @@ -151,7 +151,7 @@ func generateConfig(input cre.GenerateConfigsInput) (cre.NodeIndexToConfigOverri return nil, errors.Wrap(homeErr, "failed to get home chain ID") } - workflowRegistryAddress, workErr := crecontracts.FindAddressesForChain(input.AddressBook, input.HomeChainSelector, keystone_changeset.WorkflowRegistry.String()) + workflowRegistryAddress, _, workErr := crecontracts.FindAddressesForChain(input.AddressBook, input.HomeChainSelector, keystone_changeset.WorkflowRegistry.String()) if workErr != nil { return nil, errors.Wrap(workErr, "failed to find WorkflowRegistry address") } diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index 3467b22e050..e7d0fc60389 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -384,10 +384,10 @@ func DefaultOCR3Config(topology *cre.Topology) (*keystone_changeset.OracleConfig return oracleConfig, nil } -func FindAddressesForChain(addressBook cldf.AddressBook, chainSelector uint64, contractName string) (common.Address, error) { +func FindAddressesForChain(addressBook cldf.AddressBook, chainSelector uint64, contractName string) (common.Address, cldf.TypeAndVersion, error) { addresses, err := addressBook.AddressesForChain(chainSelector) if err != nil { - return common.Address{}, errors.Wrap(err, "failed to get addresses for chain") + return common.Address{}, cldf.TypeAndVersion{}, errors.Wrap(err, "failed to get addresses for chain") } for addrStr, tv := range addresses { @@ -395,14 +395,14 @@ func FindAddressesForChain(addressBook cldf.AddressBook, chainSelector uint64, c continue } - return common.HexToAddress(addrStr), nil + return common.HexToAddress(addrStr), tv, nil } - return common.Address{}, fmt.Errorf("failed to find %s address in the address book for chain %d", contractName, chainSelector) + return common.Address{}, cldf.TypeAndVersion{}, fmt.Errorf("failed to find %s address in the address book for chain %d", contractName, chainSelector) } func MustFindAddressesForChain(addressBook cldf.AddressBook, chainSelector uint64, contractName string) common.Address { - addr, err := FindAddressesForChain(addressBook, chainSelector, contractName) + addr, _, err := FindAddressesForChain(addressBook, chainSelector, contractName) if err != nil { panic(fmt.Errorf("failed to find %s address in the address book for chain %d", contractName, chainSelector)) } @@ -561,7 +561,7 @@ func DeployDataFeedsCacheContract(testLogger zerolog.Logger, chainSelector uint6 } testLogger.Info().Msgf("Data Feeds Cache contract deployed to %d", chainSelector) - dataFeedsCacheAddress, dataFeedsCacheErr := FindAddressesForChain( + dataFeedsCacheAddress, _, dataFeedsCacheErr := FindAddressesForChain( fullCldEnvOutput.Environment.ExistingAddresses, //nolint:staticcheck // won't migrate now chainSelector, df_changeset.DataFeedsCache.String(), @@ -588,7 +588,7 @@ func DeployReadBalancesContract(testLogger zerolog.Logger, chainSelector uint64, } testLogger.Info().Msgf("Read Balances contract deployed to %d", chainSelector) - readBalancesAddress, readContractErr := FindAddressesForChain( + readBalancesAddress, _, readContractErr := FindAddressesForChain( fullCldEnvOutput.Environment.ExistingAddresses, //nolint:staticcheck // won't migrate now chainSelector, keystone_changeset.BalanceReader.String(), diff --git a/system-tests/lib/cre/don/config/config.go b/system-tests/lib/cre/don/config/config.go index 0e0fe3aedc6..8f2987e3001 100644 --- a/system-tests/lib/cre/don/config/config.go +++ b/system-tests/lib/cre/don/config/config.go @@ -106,11 +106,16 @@ func Generate(input cre.GenerateConfigsInput, nodeConfigFns []cre.NodeConfigFn) } // find contract addresses - capabilitiesRegistryAddress, capErr := crecontracts.FindAddressesForChain(input.AddressBook, input.HomeChainSelector, keystone_changeset.CapabilitiesRegistry.String()) + capabilitiesRegistryAddress, capRegTypeVersion, capErr := crecontracts.FindAddressesForChain(input.AddressBook, input.HomeChainSelector, keystone_changeset.CapabilitiesRegistry.String()) if capErr != nil { return nil, errors.Wrap(capErr, "failed to find CapabilitiesRegistry address") } + capRegistry := AddressTypeVersion{ + Address: capabilitiesRegistryAddress, + TypeAndVersion: capRegTypeVersion, + } + // find bootstrap node for the Don var donBootstrapNodeHost string var donBootstrapNodePeerID string @@ -156,7 +161,7 @@ func Generate(input cre.GenerateConfigsInput, nodeConfigFns []cre.NodeConfigFn) } // generate configuration for the bootstrap node - configOverrides[nodeIndex] = BootstrapEVM(donBootstrapNodePeerID, homeChainID, capabilitiesRegistryAddress, workerEVMInputs, input.WithV2RegistryContracts) + configOverrides[nodeIndex] = BootstrapEVM(donBootstrapNodePeerID, homeChainID, capRegistry, workerEVMInputs) if flags.HasFlag(input.Flags, cre.WorkflowDON) { configOverrides[nodeIndex] += BoostrapDon2DonPeering(input.CapabilitiesPeeringData) } @@ -300,8 +305,8 @@ func Generate(input cre.GenerateConfigsInput, nodeConfigFns []cre.NodeConfigFn) // connect worker nodes to all the chains, add chain ID for registry (home chain) // we configure both EVM chains, nodes and EVM.Workflow with Forwarder var workerErr error - configOverrides[nodeIndex], workerErr = WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost, input.OCRPeeringData, - input.CapabilitiesPeeringData, capabilitiesRegistryAddress, homeChainID, workerEVMInputs, input.WithV2RegistryContracts) + configOverrides[nodeIndex], workerErr = WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost, input.OCRPeeringData, + input.CapabilitiesPeeringData, capRegistry, homeChainID, workerEVMInputs) if workerErr != nil { return nil, errors.Wrap(workerErr, "failed to generate worker [EVM.Workflow] config") } diff --git a/system-tests/lib/cre/don/config/definitions.go b/system-tests/lib/cre/don/config/definitions.go index 6f7c59cf70f..5e8a3a26dbd 100644 --- a/system-tests/lib/cre/don/config/definitions.go +++ b/system-tests/lib/cre/don/config/definitions.go @@ -9,6 +9,7 @@ import ( "github.com/gagliardetto/solana-go" "github.com/pkg/errors" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/system-tests/lib/cre" "github.com/smartcontractkit/chainlink/system-tests/lib/cre/don" ) @@ -44,8 +45,14 @@ const ( ` ) -func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitiesRegistryAddress common.Address, - chains []*WorkerEVMInput, withV2RegistryContracts bool) string { +type AddressTypeVersion struct { + Address common.Address + cldf.TypeAndVersion +} + +func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capRegistry AddressTypeVersion, + chains []*WorkerEVMInput, +) string { evmChainsConfig := "" for _, chain := range chains { evmChainsConfig += fmt.Sprintf(` @@ -64,10 +71,7 @@ func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitie chain.HTTPRPC, ) } - version := "1.0.0" - if withV2RegistryContracts { - version = "2.0.0" - } + return fmt.Sprintf(` [Feature] LogPoller = true @@ -94,9 +98,9 @@ func BootstrapEVM(donBootstrapNodePeerID string, homeChainID uint64, capabilitie `, donBootstrapNodePeerID, evmChainsConfig, - capabilitiesRegistryAddress, + capRegistry.Address, homeChainID, - version, + capRegistry.Version, ) } @@ -126,9 +130,10 @@ type WorkerEVMInput struct { WorkflowConfig map[string]any // Configuration for EVM.Workflow section } -func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringData cre.OCRPeeringData, - capabilitiesPeeringData cre.CapabilitiesPeeringData, capabilitiesRegistryAddress common.Address, - homeChainID uint64, chains []*WorkerEVMInput, withV2RegistryContracts bool) (string, error) { +func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringData cre.OCRPeeringData, + capabilitiesPeeringData cre.CapabilitiesPeeringData, capRegistry AddressTypeVersion, + homeChainID uint64, chains []*WorkerEVMInput, +) (string, error) { evmChainsConfig := "" for _, chain := range chains { evmChainsConfig += fmt.Sprintf(` @@ -174,11 +179,6 @@ func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringDa } } - version := "1.0.0" - if withV2RegistryContracts { - version = "2.0.0" - } - return fmt.Sprintf(` [Feature] LogPoller = true @@ -216,9 +216,9 @@ func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, ocrPeeringDa capabilitiesPeeringData.GlobalBootstraperHost, capabilitiesPeeringData.Port, evmChainsConfig, - capabilitiesRegistryAddress, + capRegistry.Address, homeChainID, - version, + capRegistry.Version, ), nil } diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index e53df1793a6..22fdc333f0e 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -414,7 +414,6 @@ func SetupTestEnvironment( input.Capabilities, input.CapabilityConfigs, input.CopyCapabilityBinaries, - withV2RegistryContracts, ) if topoErr != nil { return nil, pkgerrors.Wrap(topoErr, "failed to build topology") diff --git a/system-tests/lib/cre/environment/topology.go b/system-tests/lib/cre/environment/topology.go index 77931845f1d..5fbaaa2cfa0 100644 --- a/system-tests/lib/cre/environment/topology.go +++ b/system-tests/lib/cre/environment/topology.go @@ -32,7 +32,6 @@ func BuildTopology( capabilities []cre.InstallableCapability, capabilityConfigs cre.CapabilityConfigs, copyCapabilityBinaries bool, - withV2RegistryContracts bool, ) (*cre.Topology, []*cre.CapabilitiesAwareNodeSet, error) { topologyErr := libdon.ValidateTopology(nodeSets, infraInput) if topologyErr != nil { @@ -128,7 +127,6 @@ func BuildTopology( GatewayConnectorOutput: topology.GatewayConnectorOutput, NodeSet: localNodeSets[i], CapabilityConfigs: capabilityConfigs, - WithV2RegistryContracts: withV2RegistryContracts, }, configFactoryFunctions, ) diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index 0ab6474e148..8816c8764a9 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -467,7 +467,6 @@ type GenerateConfigsInput struct { NodeSet *CapabilitiesAwareNodeSet CapabilityConfigs CapabilityConfigs GatewayConnectorOutput *GatewayConnectorOutput // optional, automatically set if some DON in the topology has the GatewayDON flag - WithV2RegistryContracts bool } func (g *GenerateConfigsInput) Validate() error { diff --git a/system-tests/lib/crecli/settings.go b/system-tests/lib/crecli/settings.go index 676addfa238..9a6afc6543d 100644 --- a/system-tests/lib/crecli/settings.go +++ b/system-tests/lib/crecli/settings.go @@ -129,12 +129,12 @@ func PrepareCRECLISettingsFile( return nil, errors.Wrap(err, "failed to create CRE CLI settings file") } - capRegAddr, capRegErr := contracts.FindAddressesForChain(addressBook, homeChainSelector, keystone_changeset.CapabilitiesRegistry.String()) + capRegAddr, _, capRegErr := contracts.FindAddressesForChain(addressBook, homeChainSelector, keystone_changeset.CapabilitiesRegistry.String()) if capRegErr != nil { return nil, errors.Wrapf(capRegErr, "failed to get capabilities registry address for chain %d", homeChainSelector) } - workflowRegistryAddr, workflowRegistryErr := contracts.FindAddressesForChain(addressBook, homeChainSelector, keystone_changeset.WorkflowRegistry.String()) + workflowRegistryAddr, _, workflowRegistryErr := contracts.FindAddressesForChain(addressBook, homeChainSelector, keystone_changeset.WorkflowRegistry.String()) if workflowRegistryErr != nil { return nil, errors.Wrapf(workflowRegistryErr, "failed to get workflow registry address for chain %d", homeChainSelector) } @@ -194,7 +194,7 @@ func PrepareCRECLISettingsFile( } for chainSelector := range addresses { - dfAddr, dfErr := contracts.FindAddressesForChain(addressBook, chainSelector, df_changeset.DataFeedsCache.String()) + dfAddr, _, dfErr := contracts.FindAddressesForChain(addressBook, chainSelector, df_changeset.DataFeedsCache.String()) if dfErr == nil { profileSettings.Contracts.DataFeeds = append(profileSettings.Contracts.DataFeeds, ContractRegistry{ Name: df_changeset.DataFeedsCache.String(), @@ -204,7 +204,7 @@ func PrepareCRECLISettingsFile( } // it is okay if there's no data feeds cache address for a chain - forwaderAddr, forwaderErr := contracts.FindAddressesForChain(addressBook, chainSelector, string(keystone_changeset.KeystoneForwarder)) + forwaderAddr, _, forwaderErr := contracts.FindAddressesForChain(addressBook, chainSelector, string(keystone_changeset.KeystoneForwarder)) if forwaderErr == nil { profileSettings.Contracts.Keystone = append(profileSettings.Contracts.Keystone, ContractRegistry{ Name: keystone_changeset.KeystoneForwarder.String(), From 3d35e3426e351e14189945556a02c90a50e66280 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:05:27 -0400 Subject: [PATCH 20/37] chore: fix missing use of type and version --- .../tests/load/cre/workflow_don_load_test.go | 18 +++++++++--------- .../tests/load/cre/writer_don_load_test.go | 14 ++++++++------ system-tests/tests/smoke/cre/cre_suite_test.go | 4 ++-- system-tests/tests/smoke/cre/helpers_test.go | 6 +++--- system-tests/tests/smoke/cre/v1_por_test.go | 6 +++--- .../smoke/cre/v2_http_trigger_action_test.go | 8 ++++---- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/system-tests/tests/load/cre/workflow_don_load_test.go b/system-tests/tests/load/cre/workflow_don_load_test.go index 81fb6f6a087..04462271c22 100644 --- a/system-tests/tests/load/cre/workflow_don_load_test.go +++ b/system-tests/tests/load/cre/workflow_don_load_test.go @@ -140,7 +140,7 @@ func setupLoadTestEnvironment( in.WorkflowRegistryConfiguration = &cretypes.WorkflowRegistryInput{} in.WorkflowRegistryConfiguration.Out = universalSetupOutput.WorkflowRegistryConfigurationOutput - forwarderAddress, forwarderErr := crecontracts.FindAddressesForChain( + forwarderAddress, _, forwarderErr := crecontracts.FindAddressesForChain( universalSetupOutput.CldEnvironment.ExistingAddresses, //nolint:staticcheck // will not migrate now universalSetupOutput.BlockchainOutput[0].ChainSelector, keystone_changeset.KeystoneForwarder.String(), @@ -684,7 +684,8 @@ func (s *StreamsGun) createReport() (capabilities.OCRTriggerEvent, string, time. } func createFeedReport(lggr logger.Logger, price decimal.Decimal, timestamp uint64, - feeds []FeedWithStreamID, keyBundles []ocr2key.KeyBundle) (*capabilities.OCRTriggerEvent, string, error) { + feeds []FeedWithStreamID, keyBundles []ocr2key.KeyBundle, +) (*capabilities.OCRTriggerEvent, string, error) { values := make([]datastreamsllo.StreamValue, 0) priceBytes, err := price.MarshalBinary() @@ -758,7 +759,7 @@ func decodeTargetInput(inputs *values.Map) (evm.TargetRequest, error) { func saveKeyBundles(keyBundles []ocr2key.KeyBundle) error { cacheDir := "cache/keys" - if err := os.MkdirAll(cacheDir, 0755); err != nil { + if err := os.MkdirAll(cacheDir, 0o755); err != nil { return fmt.Errorf("failed to create cache directory: %w", err) } @@ -770,7 +771,7 @@ func saveKeyBundles(keyBundles []ocr2key.KeyBundle) error { } filename := fmt.Sprintf("%s/key_bundle_%d.json", cacheDir, i) - if err := os.WriteFile(filename, bytes, 0600); err != nil { + if err := os.WriteFile(filename, bytes, 0o600); err != nil { return fmt.Errorf("failed to write key bundle %d to file: %w", i, err) } } @@ -828,7 +829,7 @@ func NewFeedIDDF2(t *testing.T) ([32]byte, string) { func saveFeedAddresses(feedsAddresses [][]FeedWithStreamID) error { cacheDir := "cache/feeds" - if err := os.MkdirAll(cacheDir, 0755); err != nil { + if err := os.MkdirAll(cacheDir, 0o755); err != nil { return fmt.Errorf("failed to create cache directory: %w", err) } @@ -838,7 +839,7 @@ func saveFeedAddresses(feedsAddresses [][]FeedWithStreamID) error { return fmt.Errorf("failed to marshal feed addresses: %w", err) } - if err := os.WriteFile(filename, bytes, 0600); err != nil { + if err := os.WriteFile(filename, bytes, 0o600); err != nil { return fmt.Errorf("failed to write feed addresses to file: %w", err) } @@ -918,7 +919,6 @@ func WorkflowsJob(nodeID string, workflowName string, feeds []FeedConfig) *jobv1 ` tmpl, err := template.New("workflow").Parse(workflowTemplateLoad) - if err != nil { panic(err) } @@ -934,7 +934,8 @@ func WorkflowsJob(nodeID string, workflowName string, feeds []FeedConfig) *jobv1 return &jobv1.ProposeJobRequest{ NodeId: nodeID, - Spec: renderedTemplate.String()} + Spec: renderedTemplate.String(), + } } func MockCapabilitiesJob(nodeID, binaryPath string, mocks []*MockCapabilities) *jobv1.ProposeJobRequest { @@ -954,7 +955,6 @@ func MockCapabilitiesJob(nodeID, binaryPath string, mocks []*MockCapabilities) * {{- end }} """` tmpl, err := template.New("mock-job").Parse(jobTemplate) - if err != nil { panic(err) } diff --git a/system-tests/tests/load/cre/writer_don_load_test.go b/system-tests/tests/load/cre/writer_don_load_test.go index 8e82bec2619..47310eb79f2 100644 --- a/system-tests/tests/load/cre/writer_don_load_test.go +++ b/system-tests/tests/load/cre/writer_don_load_test.go @@ -98,7 +98,7 @@ func setupLoadTestWriterEnvironment( in.WorkflowRegistryConfiguration = &cretypes.WorkflowRegistryInput{} in.WorkflowRegistryConfiguration.Out = universalSetupOutput.WorkflowRegistryConfigurationOutput - forwarderAddress, forwarderErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, keystone_changeset.KeystoneForwarder.String()) //nolint:staticcheck // won't migrate now + forwarderAddress, _, forwarderErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, keystone_changeset.KeystoneForwarder.String()) //nolint:staticcheck // won't migrate now require.NoError(t, forwarderErr, "failed to find forwarder address for chain %d", universalSetupOutput.BlockchainOutput[0].ChainSelector) // DF cache start @@ -114,7 +114,7 @@ func setupLoadTestWriterEnvironment( mergeErr := universalSetupOutput.CldEnvironment.ExistingAddresses.Merge(dfOutput.AddressBook) //nolint:staticcheck // won't migrate now require.NoError(t, mergeErr, "failed to merge address book") - dfCacheAddress, dfCacheErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, changeset.DataFeedsCache.String()) //nolint:staticcheck // won't migrate now + dfCacheAddress, _, dfCacheErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, changeset.DataFeedsCache.String()) //nolint:staticcheck // won't migrate now require.NoError(t, dfCacheErr, "failed to find df cache address for chain %d", universalSetupOutput.BlockchainOutput[0].ChainSelector) // Config _, configErr := libcontracts.ConfigureDataFeedsCache(testLogger, &cretypes.ConfigureDataFeedsCacheInput{ @@ -441,7 +441,7 @@ type testParams struct { func exportTestParams(params testParams) error { // Create cache directory if it doesn't exist cacheDir := filepath.Join(os.TempDir(), "cache") - if err := os.MkdirAll(cacheDir, 0600); err != nil { + if err := os.MkdirAll(cacheDir, 0o600); err != nil { return fmt.Errorf("failed to create cache directory: %w", err) } @@ -464,7 +464,7 @@ func exportTestParams(params testParams) error { // Write to file in cache directory cacheFile := filepath.Join(cacheDir, "test_params.json") - if err := os.WriteFile(cacheFile, jsonData, 0600); err != nil { + if err := os.WriteFile(cacheFile, jsonData, 0o600); err != nil { return fmt.Errorf("failed to write test params file: %w", err) } @@ -685,6 +685,7 @@ func (s *WriterGun) executeRequest(metadata *pb2.Metadata, encodedReport []byte, return s.capProxy.Execute(context.TODO(), req) } + func (s *WriterGun) createEVMEncoder() (consensustypes.Encoder, error) { evmEncoderConfig := map[string]any{ "abi": "(bytes32 FeedID, uint32 Timestamp, uint224 Price)[] Reports", @@ -768,6 +769,7 @@ func (s *WriterGun) createRequestInputs(encodedReport []byte, sigs [][]byte, rep return inputBytes, configBytes, nil } + func stringTo32Byte(input string) ([32]byte, error) { var result [32]byte @@ -804,13 +806,13 @@ func convertToHashedWorkflowName(input string) string { func saveClientURL(url string) error { // Create cache directory if it doesn't exist cacheDir := filepath.Join(os.TempDir(), "cache") - if err := os.MkdirAll(cacheDir, 0600); err != nil { + if err := os.MkdirAll(cacheDir, 0o600); err != nil { return fmt.Errorf("failed to create cache directory: %w", err) } // Save URL to file cacheFile := filepath.Join(cacheDir, "client_url.txt") - if err := os.WriteFile(cacheFile, []byte(url), 0600); err != nil { + if err := os.WriteFile(cacheFile, []byte(url), 0o600); err != nil { return fmt.Errorf("failed to write client URL file: %w", err) } diff --git a/system-tests/tests/smoke/cre/cre_suite_test.go b/system-tests/tests/smoke/cre/cre_suite_test.go index 582685f2c6a..767950ef28c 100644 --- a/system-tests/tests/smoke/cre/cre_suite_test.go +++ b/system-tests/tests/smoke/cre/cre_suite_test.go @@ -50,8 +50,8 @@ func Test_CRE_Suite(t *testing.T) { func Test_withV2Registries(t *testing.T) { t.Run("[v1] CRE Proof of Reserve (PoR) Test", func(t *testing.T) { - const skipReason = "Integrate v2 registry contracts in local CRE/test setup - https://smartcontract-it.atlassian.net/browse/CRE-635" - t.Skipf("Skipping test for the following reason: %s", skipReason) + /* const skipReason = "Integrate v2 registry contracts in local CRE/test setup - https://smartcontract-it.atlassian.net/browse/CRE-635" + t.Skipf("Skipping test for the following reason: %s", skipReason) */ flags := []string{"--with-contracts-version", "v2"} testEnv := SetupTestEnvironment(t, flags...) ExecutePoRTest(t, testEnv) diff --git a/system-tests/tests/smoke/cre/helpers_test.go b/system-tests/tests/smoke/cre/helpers_test.go index b4951b4c15d..35aed78002b 100644 --- a/system-tests/tests/smoke/cre/helpers_test.go +++ b/system-tests/tests/smoke/cre/helpers_test.go @@ -51,7 +51,7 @@ See an example in a test using PoR workflow. func getWritableChainsFromSavedEnvironmentState(t *testing.T, testEnv *TestEnvironment) []uint64 { t.Helper() - var testLogger = framework.L + testLogger := framework.L testLogger.Info().Msg("Getting writable chains from saved environment state.") writeableChains := []uint64{} for _, bcOutput := range testEnv.WrappedBlockchainOutputs { @@ -200,7 +200,7 @@ Use it at the end of your test to `t.Cleanup()` the env after test run func deleteWorkflows(t *testing.T, uniqueWorkflowName string, workflowConfigFilePath string, compressedWorkflowWasmPath string, blockchainOutputs []*cre.WrappedBlockchainOutput, workflowRegistryAddress common.Address) { t.Helper() - var testLogger = framework.L + testLogger := framework.L testLogger.Info().Msgf("Deleting workflow artifacts (%s) after test.\n", uniqueWorkflowName) localEnvErr := creworkflow.RemoveWorkflowArtifactsFromLocalEnv(workflowConfigFilePath, compressedWorkflowWasmPath) require.NoError(t, localEnvErr, "failed to remove workflow artifacts from local environment") @@ -216,7 +216,7 @@ func compileAndDeployWorkflow[T WorkflowConfig](t *testing.T, testEnv *TestEnvir // Ignoring the deprecation warning as the suggest solution is not working in CI //lint:ignore SA1019 ignoring deprecation warning for this usage - workflowRegistryAddress, workflowRegistryErr := crecontracts.FindAddressesForChain( + workflowRegistryAddress, _, workflowRegistryErr := crecontracts.FindAddressesForChain( testEnv.FullCldEnvOutput.Environment.ExistingAddresses, //lint:ignore SA1019 ignoring deprecation warning for this usage homeChainSelector, keystone_changeset.WorkflowRegistry.String()) require.NoError(t, workflowRegistryErr, "failed to find workflow registry address for chain %d", testEnv.WrappedBlockchainOutputs[0].ChainID) diff --git a/system-tests/tests/smoke/cre/v1_por_test.go b/system-tests/tests/smoke/cre/v1_por_test.go index 0cf6b0a1bf7..ba39ae031d5 100644 --- a/system-tests/tests/smoke/cre/v1_por_test.go +++ b/system-tests/tests/smoke/cre/v1_por_test.go @@ -92,7 +92,7 @@ func ExecutePoRTest(t *testing.T, testEnv *TestEnvironment) { crecontracts.MergeAllDataStores(fullCldEnvOutput, dfOutput, rbOutput) testLogger.Info().Msgf("Configuring Data Feeds Cache contract...") - forwarderAddress, forwarderErr := crecontracts.FindAddressesForChain(fullCldEnvOutput.Environment.ExistingAddresses, chainSelector, keystone_changeset.KeystoneForwarder.String()) //nolint:staticcheck,nolintlint // SA1019: deprecated but we don't want to migrate now + forwarderAddress, _, forwarderErr := crecontracts.FindAddressesForChain(fullCldEnvOutput.Environment.ExistingAddresses, chainSelector, keystone_changeset.KeystoneForwarder.String()) //nolint:staticcheck,nolintlint // SA1019: deprecated but we don't want to migrate now require.NoError(t, forwarderErr, "failed to find Forwarder address for chain %d", chainSelector) uniqueWorkflowName := baseWorkflowTestConfig.WorkflowName + "-" + bcOutput.BlockchainOutput.ChainID + "-" + uuid.New().String()[0:4] // e.g. 'por-workflow-1337-5f37_config' @@ -167,7 +167,7 @@ func createPoRWorkflowConfigFile(workflowName string, workflowConfig *portypes.W } } - if err := os.WriteFile(workflowConfigOutputFile, configMarshalled, 0644); err != nil { //nolint:gosec // G306: we want it to be readable by everyone + if err := os.WriteFile(workflowConfigOutputFile, configMarshalled, 0o644); err != nil { //nolint:gosec // G306: we want it to be readable by everyone return "", errors.Wrap(err, "failed to write output file") } @@ -211,7 +211,7 @@ func validatePoRPrices(t *testing.T, testEnv *TestEnvironment, priceProvider Pri feedID := config.FeedIDs[idx] testEnv.Logger.Info().Msgf("Waiting for feed %s to update...", feedID) - dataFeedsCacheAddresses, dataFeedsCacheErr := crecontracts.FindAddressesForChain( + dataFeedsCacheAddresses, _, dataFeedsCacheErr := crecontracts.FindAddressesForChain( testEnv.FullCldEnvOutput.Environment.ExistingAddresses, //nolint:staticcheck,nolintlint // SA1019: deprecated but we don't want to migrate now bcOutput.ChainSelector, df_changeset.DataFeedsCache.String(), diff --git a/system-tests/tests/smoke/cre/v2_http_trigger_action_test.go b/system-tests/tests/smoke/cre/v2_http_trigger_action_test.go index bc24be419c1..9b4eac8d9c4 100644 --- a/system-tests/tests/smoke/cre/v2_http_trigger_action_test.go +++ b/system-tests/tests/smoke/cre/v2_http_trigger_action_test.go @@ -39,7 +39,7 @@ import ( func ExecuteHTTPTriggerActionTest(t *testing.T, testEnv *TestEnvironment) { HTTPWorkflowFileLocation := "../../../../core/scripts/cre/environment/examples/workflows/v2/http_simple/main.go" - var testLogger = framework.L + testLogger := framework.L homeChainSelector := testEnv.WrappedBlockchainOutputs[0].ChainSelector testEnv.Logger.Info().Msg("Starting HTTP trigger and action test...") @@ -59,7 +59,7 @@ func ExecuteHTTPTriggerActionTest(t *testing.T, testEnv *TestEnvironment) { compressedWorkflowWasmPath, httpConfigFilePath := createWorkflowArtifacts(t, testLogger, uniqueWorkflowName, &httpWorkflowConfig, HTTPWorkflowFileLocation) testLogger.Info().Msg("Registering HTTP workflow") - workflowRegistryAddress, err := crecontracts.FindAddressesForChain(testEnv.FullCldEnvOutput.Environment.ExistingAddresses, homeChainSelector, keystone_changeset.WorkflowRegistry.String()) //nolint:staticcheck,nolintlint // SA1019: deprecated but we don't want to migrate now + workflowRegistryAddress, _, err := crecontracts.FindAddressesForChain(testEnv.FullCldEnvOutput.Environment.ExistingAddresses, homeChainSelector, keystone_changeset.WorkflowRegistry.String()) //nolint:staticcheck,nolintlint // SA1019: deprecated but we don't want to migrate now require.NoError(t, err, "failed to find workflow registry address for chain %d", homeChainSelector) regConfig := &WorkflowRegistrationConfig{ @@ -197,7 +197,7 @@ type HTTPWorkflowConfig struct { } func createHTTPWorkflowConfigFile(workflowName string, cfg *HTTPWorkflowConfig) (string, error) { - var testLogger = framework.L + testLogger := framework.L mockServerURL := cfg.URL parsedURL, urlErr := url.Parse(mockServerURL) if urlErr != nil { @@ -218,7 +218,7 @@ func createHTTPWorkflowConfigFile(workflowName string, cfg *HTTPWorkflowConfig) configFileName := fmt.Sprintf("test_http_workflow_config_%s.json", workflowName) configPath := filepath.Join(os.TempDir(), configFileName) - writeErr := os.WriteFile(configPath, configBytes, 0644) //nolint:gosec // this is a test file + writeErr := os.WriteFile(configPath, configBytes, 0o644) //nolint:gosec // this is a test file if writeErr != nil { return "", errors.Wrap(writeErr, "failed to write HTTP workflow config file") } From 23dbfbaf3f1fddca5a6536f825b83e90d06faa7a Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 17:08:44 -0400 Subject: [PATCH 21/37] refactor: logs some contract versions --- .../contracts/deploy_contracts_seq.go | 58 +++++++++---------- .../lib/cre/environment/environment.go | 26 +++++---- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index dfc3fc54dc9..53748a8c665 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -57,7 +57,7 @@ func updateAddresses(addr datastore.MutableAddressRefStore, as datastore.Address } // DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). -var DeployKeystoneContractsSequence = operations.NewSequence[DeployKeystoneContractsSequenceInput, DeployKeystoneContractsSequenceOutput, DeployKeystoneContractsSequenceDeps]( +var DeployKeystoneContractsSequence = operations.NewSequence( "deploy-keystone-contracts-seq", semver.MustParse("1.0.0"), "Deploy Keystone Contracts (BalanceReader, OCR3, DON Time, Vault-OCR3, EVM-OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder)", @@ -73,7 +73,7 @@ var DeployKeystoneContractsSequence = operations.NewSequence[DeployKeystoneContr if err != nil { return DeployKeystoneContractsSequenceOutput{}, err } - + out, err := ToV1Output(v2Report.Output) if err != nil { return DeployKeystoneContractsSequenceOutput{}, err @@ -181,34 +181,34 @@ func GetCapabilityContractIdentifier(chainID uint64) string { } // ToV1Output transforms the v2 output to v1 output by creating an address book -func ToV1Output(in cap_reg_v2.DeployCapabilitiesRegistryOutput) (DeployCapabilityRegistryOutput, error){ - ab := deployment.NewMemoryAddressBook() - ds := datastore.NewMemoryDataStore() - r := datastore.AddressRef{ - ChainSelector: in.ChainSelector, - Address: in.Address, - Type: datastore.ContractType(in.Type), - Version: semver.MustParse(in.Version), - Qualifier: in.Qualifier, - Labels: datastore.NewLabelSet(), - } - for _, l := range in.Labels { - r.Labels.Add(l) - } - - if err := ds.Addresses().Add(r); err != nil { - return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to add address ref: %w", err) - } +func ToV1Output(in cap_reg_v2.DeployCapabilitiesRegistryOutput) (DeployCapabilityRegistryOutput, error) { + ab := deployment.NewMemoryAddressBook() + ds := datastore.NewMemoryDataStore() + r := datastore.AddressRef{ + ChainSelector: in.ChainSelector, + Address: in.Address, + Type: datastore.ContractType(in.Type), + Version: semver.MustParse(in.Version), + Qualifier: in.Qualifier, + Labels: datastore.NewLabelSet(), + } + for _, l := range in.Labels { + r.Labels.Add(l) + } - if err := ab.Save(in.ChainSelector, in.Address, deployment.TypeAndVersion{ - Type: deployment.ContractType(in.Type), - Version: *semver.MustParse(in.Version), - Labels: deployment.NewLabelSet(in.Labels...), - }); err != nil { - return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to save address to address book: %w", err) - } + if err := ds.Addresses().Add(r); err != nil { + return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to add address ref: %w", err) + } + + if err := ab.Save(in.ChainSelector, in.Address, deployment.TypeAndVersion{ + Type: deployment.ContractType(in.Type), + Version: *semver.MustParse(in.Version), + Labels: deployment.NewLabelSet(in.Labels...), + }); err != nil { + return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to save address to address book: %w", err) + } return DeployCapabilityRegistryOutput{ - Addresses: ds.Addresses(), + Addresses: ds.Addresses(), AddressBook: ab, }, nil -} \ No newline at end of file +} diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 22fdc333f0e..1f3509d6275 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -114,7 +114,7 @@ func mustGetAddress(dataStore datastore.MutableDataStore, chainSel uint64, contr ) addrRef, err := dataStore.Addresses().Get(key) if err != nil { - panic(fmt.Sprintf("Failed to get %s (qualifier=%s) address for chain %d: %s", contractType, qualifier, chainSel, err.Error())) + panic(fmt.Sprintf("Failed to get %s %s (qualifier=%s) address for chain %d: %s", contractType, version, qualifier, chainSel, err.Error())) } return addrRef.Address } @@ -327,26 +327,28 @@ func SetupTestEnvironment( return nil, pkgerrors.Wrap(err, "failed to add address to the datastore for Solana Forwarder state") } - testLogger.Info().Msgf("Deployed Forwarder contract on Solana chain chain %d programID: %s state: %s", sel, out.Output.ProgramID.String(), out.Output.State.String()) + testLogger.Info().Msgf("Deployed Forwarder %s contract on Solana chain chain %d programID: %s state: %s", input.ContractVersions[ks_sol.ForwarderContract.String()], sel, out.Output.ProgramID.String(), out.Output.State.String()) } allChainsCLDEnvironment.DataStore = memoryDatastore.Seal() ocr3Addr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], "capability_ocr3") - testLogger.Info().Msgf("Deployed OCR3 contract on chain %d at %s", homeChainSelector, ocr3Addr) + testLogger.Info().Msgf("Deployed OCR3 %s contract on chain %d at %s", input.ContractVersions[keystone_changeset.OCR3Capability.String()], homeChainSelector, ocr3Addr) donTimeAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], "DONTime") - testLogger.Info().Msgf("Deployed DON Time contract on chain %d at %s", homeChainSelector, donTimeAddr) + testLogger.Info().Msgf("Deployed OCR3 %s (DON Time) contract on chain %d at %s", input.ContractVersions[keystone_changeset.OCR3Capability.String()], homeChainSelector, donTimeAddr) - wfRegAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.WorkflowRegistry.String(), input.ContractVersions[keystone_changeset.WorkflowRegistry.String()], "") - testLogger.Info().Msgf("Deployed Workflow Registry contract on chain %d at %s", homeChainSelector, wfRegAddr) + wfRegVersion := input.ContractVersions[keystone_changeset.WorkflowRegistry.String()] + wfRegVersion = "1.0.0" // TODO(mstreet3): replace hardcoding of wf registry version + wfRegAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.WorkflowRegistry.String(), wfRegVersion, "") + testLogger.Info().Msgf("Deployed Workflow Registry %s contract on chain %d at %s", input.ContractVersions[keystone_changeset.WorkflowRegistry.String()], homeChainSelector, wfRegAddr) capRegAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.CapabilitiesRegistry.String(), input.ContractVersions[keystone_changeset.CapabilitiesRegistry.String()], "") - testLogger.Info().Msgf("Deployed Capabilities Registry contract on chain %d at %s", homeChainSelector, capRegAddr) + testLogger.Info().Msgf("Deployed Capabilities Registry %s contract on chain %d at %s", input.ContractVersions[keystone_changeset.CapabilitiesRegistry.String()], homeChainSelector, capRegAddr) var vaultOCR3CommonAddr common.Address if vaultOCR3AddrFlag { vaultOCR3Addr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], "capability_vault") - testLogger.Info().Msgf("Deployed Vault OCR3 contract on chain %d at %s", homeChainSelector, vaultOCR3Addr) + testLogger.Info().Msgf("Deployed OCR3 %s (Vault) contract on chain %d at %s", input.ContractVersions[keystone_changeset.OCR3Capability.String()], homeChainSelector, vaultOCR3Addr) vaultOCR3CommonAddr = common.HexToAddress(vaultOCR3Addr) } @@ -355,26 +357,26 @@ func SetupTestEnvironment( for chainID, selector := range chainsWithEVMCapability { qualifier := ks_contracts_op.GetCapabilityContractIdentifier(uint64(chainID)) evmOCR3Addr := mustGetAddress(memoryDatastore, uint64(selector), keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], qualifier) - testLogger.Info().Msgf("Deployed EVM OCR3 contract on chainID: %d, selector: %d, at: %s", chainID, selector, evmOCR3Addr) + testLogger.Info().Msgf("Deployed EVM OCR3 %s contract on chain %d, selector: %d, at: %s", input.ContractVersions[keystone_changeset.OCR3Capability.String()], chainID, selector, evmOCR3Addr) evmOCR3CommonAddresses[uint64(selector)] = common.HexToAddress(evmOCR3Addr) } } var consensusV2OCR3CommonAddr common.Address if consensusV2AddrFlag { consensusV2OCR3Addr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], "capability_consensus") - testLogger.Info().Msgf("Deployed Consensus V2 OCR3 contract on chain %d at %s", homeChainSelector, consensusV2OCR3Addr) + testLogger.Info().Msgf("Deployed Consensus V2 OCR3 %s contract on chain %d at %s", input.ContractVersions[keystone_changeset.OCR3Capability.String()], homeChainSelector, consensusV2OCR3Addr) consensusV2OCR3CommonAddr = common.HexToAddress(consensusV2OCR3Addr) } for _, forwarderSelector := range evmForwardersSelectors { forwarderAddr := mustGetAddress(memoryDatastore, forwarderSelector, keystone_changeset.KeystoneForwarder.String(), input.ContractVersions[keystone_changeset.KeystoneForwarder.String()], "") - testLogger.Info().Msgf("Deployed Forwarder contract on chain %d at %s", forwarderSelector, forwarderAddr) + testLogger.Info().Msgf("Deployed Forwarder %s contract on chain %d at %s", input.ContractVersions[keystone_changeset.KeystoneForwarder.String()], forwarderSelector, forwarderAddr) } for _, forwarderSelector := range solForwardersSelectors { forwarderAddr := mustGetAddress(memoryDatastore, forwarderSelector, ks_sol.ForwarderContract.String(), input.ContractVersions[ks_sol.ForwarderContract.String()], ks_sol.DefaultForwarderQualifier) forwarderStateAddr := mustGetAddress(memoryDatastore, forwarderSelector, ks_sol.ForwarderState.String(), input.ContractVersions[ks_sol.ForwarderState.String()], ks_sol.DefaultForwarderQualifier) - testLogger.Info().Msgf("Deployed Forwarder contract on Solana chain %d at %s state %s", forwarderSelector, forwarderAddr, forwarderStateAddr) + testLogger.Info().Msgf("Deployed Forwarder %s contract on Solana chain %d at %s state %s", input.ContractVersions[ks_sol.ForwarderContract.String()], forwarderSelector, forwarderAddr, forwarderStateAddr) } // get chainIDs, they'll be used for identifying ETH keys and Forwarder addresses From 05d947a5ddf908eef148e634760993f4e92be0e3 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 17:40:52 -0400 Subject: [PATCH 22/37] feat: deploys wf reg v2 in sequence --- .../contracts/deploy_contracts_seq.go | 99 ++++++++++++++----- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index 53748a8c665..b63ffe23e09 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/operations" cap_reg_v2 "github.com/smartcontractkit/chainlink/deployment/cre/capabilities_registry/v2/changeset/operations/contracts" + wf_reg_v2 "github.com/smartcontractkit/chainlink/deployment/cre/workflow_registry/v2/changeset/operations/contracts" ) type DeployKeystoneContractsSequenceDeps struct { @@ -74,7 +75,7 @@ var DeployKeystoneContractsSequence = operations.NewSequence( return DeployKeystoneContractsSequenceOutput{}, err } - out, err := ToV1Output(v2Report.Output) + out, err := toV1Output(v2Report.Output) if err != nil { return DeployKeystoneContractsSequenceOutput{}, err } @@ -102,13 +103,29 @@ var DeployKeystoneContractsSequence = operations.NewSequence( } // Workflow Registry contract - workflowRegistryDeployReport, err := operations.ExecuteOperation(b, DeployWorkflowRegistryOp, DeployWorkflowRegistryOpDeps(deps), DeployWorkflowRegistryInput{ChainSelector: input.RegistryChainSelector}) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err - } - err = updateAddresses(as.Addresses(), workflowRegistryDeployReport.Output.Addresses, ab, workflowRegistryDeployReport.Output.AddressBook) - if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + if input.WithV2Contracts { + v2Report, err := operations.ExecuteOperation(b, wf_reg_v2.DeployWorkflowRegistryOp, wf_reg_v2.DeployWorkflowRegistryOpDeps(deps), wf_reg_v2.DeployWorkflowRegistryOpInput{ + ChainSelector: input.RegistryChainSelector, + }) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } + + out, err := toV1Output(v2Report.Output) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } + + err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook) + } else { + workflowRegistryDeployReport, err := operations.ExecuteOperation(b, DeployWorkflowRegistryOp, DeployWorkflowRegistryOpDeps(deps), DeployWorkflowRegistryInput{ChainSelector: input.RegistryChainSelector}) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } + err = updateAddresses(as.Addresses(), workflowRegistryDeployReport.Output.Addresses, ab, workflowRegistryDeployReport.Output.AddressBook) + if err != nil { + return DeployKeystoneContractsSequenceOutput{}, err + } } // Keystone Forwarder contract @@ -180,34 +197,62 @@ func GetCapabilityContractIdentifier(chainID uint64) string { return fmt.Sprintf("capability_evm_%d", chainID) } -// ToV1Output transforms the v2 output to v1 output by creating an address book -func ToV1Output(in cap_reg_v2.DeployCapabilitiesRegistryOutput) (DeployCapabilityRegistryOutput, error) { +type DeprecatedOutput struct { + Addresses datastore.AddressRefStore + AddressBook deployment.AddressBook +} + +// toV1Output transforms a v2 output to a common v1 output format. +// It accepts any v2 output type and returns a generic struct that handles +// the deprecated address book. +func toV1Output(in any) (DeprecatedOutput, error) { ab := deployment.NewMemoryAddressBook() ds := datastore.NewMemoryDataStore() - r := datastore.AddressRef{ - ChainSelector: in.ChainSelector, - Address: in.Address, - Type: datastore.ContractType(in.Type), - Version: semver.MustParse(in.Version), - Qualifier: in.Qualifier, - Labels: datastore.NewLabelSet(), - } - for _, l := range in.Labels { - r.Labels.Add(l) + labels := deployment.NewLabelSet() + var r datastore.AddressRef + + switch v := in.(type) { + case cap_reg_v2.DeployCapabilitiesRegistryOutput: + r = datastore.AddressRef{ + ChainSelector: v.ChainSelector, + Address: v.Address, + Type: datastore.ContractType(v.Type), + Version: semver.MustParse(v.Version), + Qualifier: v.Qualifier, + Labels: datastore.NewLabelSet(v.Labels...), + } + for _, l := range v.Labels { + labels.Add(l) + } + case wf_reg_v2.DeployWorkflowRegistryOpOutput: + r = datastore.AddressRef{ + ChainSelector: v.ChainSelector, + Address: v.Address, + Type: datastore.ContractType(v.Type), + Version: semver.MustParse(v.Version), + Qualifier: v.Qualifier, + Labels: datastore.NewLabelSet(v.Labels...), + } + for _, l := range v.Labels { + labels.Add(l) + } + default: + return DeprecatedOutput{}, fmt.Errorf("unsupported input type for toCommonV1Output: %T", in) } if err := ds.Addresses().Add(r); err != nil { - return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to add address ref: %w", err) + return DeprecatedOutput{}, fmt.Errorf("failed to add address ref: %w", err) } - if err := ab.Save(in.ChainSelector, in.Address, deployment.TypeAndVersion{ - Type: deployment.ContractType(in.Type), - Version: *semver.MustParse(in.Version), - Labels: deployment.NewLabelSet(in.Labels...), + if err := ab.Save(r.ChainSelector, r.Address, deployment.TypeAndVersion{ + Type: deployment.ContractType(r.Type), + Version: *r.Version, + Labels: labels, }); err != nil { - return DeployCapabilityRegistryOutput{}, fmt.Errorf("failed to save address to address book: %w", err) + return DeprecatedOutput{}, fmt.Errorf("failed to save address to address book: %w", err) } - return DeployCapabilityRegistryOutput{ + + return DeprecatedOutput{ Addresses: ds.Addresses(), AddressBook: ab, }, nil From 05491d7203a8ad756f11b1c6ec8f2898873f2ec6 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 17:44:24 -0400 Subject: [PATCH 23/37] refactor: remove keystone from struct names --- .../contracts/deploy_contracts_seq.go | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index b63ffe23e09..7edf76b85bf 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -13,7 +13,7 @@ import ( wf_reg_v2 "github.com/smartcontractkit/chainlink/deployment/cre/workflow_registry/v2/changeset/operations/contracts" ) -type DeployKeystoneContractsSequenceDeps struct { +type DeployContractsSequenceDeps struct { Env *deployment.Environment } @@ -24,7 +24,7 @@ type ( // inputs and outputs have to be serializable, and must not contain sensitive data -type DeployKeystoneContractsSequenceInput struct { +type DeployContractsSequenceInput struct { RegistryChainSelector uint64 ForwardersSelectors []uint64 DeployVaultOCR3 bool @@ -36,7 +36,7 @@ type DeployKeystoneContractsSequenceInput struct { WithV2Contracts bool } -type DeployKeystoneContractsSequenceOutput struct { +type DeployContractsSequenceOutput struct { // Not sure if we can serialize the address book without modifications, but whatever is returned needs to be serializable. // This could also be the address datastore instead. AddressBook deployment.AddressBook @@ -57,12 +57,12 @@ func updateAddresses(addr datastore.MutableAddressRefStore, as datastore.Address return sourceAB.Merge(ab) } -// DeployKeystoneContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). -var DeployKeystoneContractsSequence = operations.NewSequence( +// DeployContractsSequence is a sequence that deploys the Keystone contracts (OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder). +var DeployContractsSequence = operations.NewSequence( "deploy-keystone-contracts-seq", semver.MustParse("1.0.0"), "Deploy Keystone Contracts (BalanceReader, OCR3, DON Time, Vault-OCR3, EVM-OCR3, Capabilities Registry, Workflow Registry, Keystone Forwarder)", - func(b operations.Bundle, deps DeployKeystoneContractsSequenceDeps, input DeployKeystoneContractsSequenceInput) (output DeployKeystoneContractsSequenceOutput, err error) { + func(b operations.Bundle, deps DeployContractsSequenceDeps, input DeployContractsSequenceInput) (output DeployContractsSequenceOutput, err error) { ab := deployment.NewMemoryAddressBook() as := datastore.NewMemoryDataStore() @@ -72,34 +72,34 @@ var DeployKeystoneContractsSequence = operations.NewSequence( ChainSelector: input.RegistryChainSelector, }) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } out, err := toV1Output(v2Report.Output) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook) } else { capabilitiesRegistryDeployReport, err := operations.ExecuteOperation(b, DeployCapabilityRegistryOp, DeployCapabilityRegistryOpDeps(deps), DeployCapabilityRegistryInput{ChainSelector: input.RegistryChainSelector}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), capabilitiesRegistryDeployReport.Output.Addresses, ab, capabilitiesRegistryDeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } } // OCR3 Contract ocr3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "capability_ocr3"}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), ocr3DeployReport.Output.Addresses, ab, ocr3DeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } // Workflow Registry contract @@ -108,55 +108,55 @@ var DeployKeystoneContractsSequence = operations.NewSequence( ChainSelector: input.RegistryChainSelector, }) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } out, err := toV1Output(v2Report.Output) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook) } else { workflowRegistryDeployReport, err := operations.ExecuteOperation(b, DeployWorkflowRegistryOp, DeployWorkflowRegistryOpDeps(deps), DeployWorkflowRegistryInput{ChainSelector: input.RegistryChainSelector}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), workflowRegistryDeployReport.Output.Addresses, ab, workflowRegistryDeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } } // Keystone Forwarder contract keystoneForwarderDeployReport, err := operations.ExecuteSequence(b, DeployKeystoneForwardersSequence, DeployKeystoneForwardersSequenceDeps(deps), DeployKeystoneForwardersInput{Targets: input.ForwardersSelectors}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), keystoneForwarderDeployReport.Output.Addresses, ab, keystoneForwarderDeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } // DON Time Contract - Copy of OCR3Capability donTimeDeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "DONTime"}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), donTimeDeployReport.Output.Addresses, ab, donTimeDeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } if input.DeployVaultOCR3 { // Vault OCR3 Contract vaultOCR3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "capability_vault"}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), vaultOCR3DeployReport.Output.Addresses, ab, vaultOCR3DeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } } @@ -166,11 +166,11 @@ var DeployKeystoneContractsSequence = operations.NewSequence( qualifier := GetCapabilityContractIdentifier(uint64(chainID)) evmOCR3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: uint64(selector), Qualifier: qualifier}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), evmOCR3DeployReport.Output.Addresses, ab, evmOCR3DeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } } } @@ -178,15 +178,15 @@ var DeployKeystoneContractsSequence = operations.NewSequence( if input.DeployConsensusOCR3 { evmOCR3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: input.RegistryChainSelector, Qualifier: "capability_consensus"}) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } err = updateAddresses(as.Addresses(), evmOCR3DeployReport.Output.Addresses, ab, evmOCR3DeployReport.Output.AddressBook) if err != nil { - return DeployKeystoneContractsSequenceOutput{}, err + return DeployContractsSequenceOutput{}, err } } - return DeployKeystoneContractsSequenceOutput{ + return DeployContractsSequenceOutput{ AddressBook: ab, Datastore: as.Seal(), }, nil From 288c2f4dca80308fcde45db815d7a8aefd48923d Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 18:03:45 -0400 Subject: [PATCH 24/37] feat: deploys v2 wf registry --- .../environment/environment/environment.go | 1 + .../contracts/deploy_capability_registry.go | 2 +- .../lib/cre/environment/config/config.go | 2 +- .../lib/cre/environment/environment.go | 20 +++++++------------ 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/core/scripts/cre/environment/environment/environment.go b/core/scripts/cre/environment/environment/environment.go index 13795ec73f8..944977fd7bd 100644 --- a/core/scripts/cre/environment/environment/environment.go +++ b/core/scripts/cre/environment/environment/environment.go @@ -650,6 +650,7 @@ func StartCLIEnvironment( CapabilitiesAwareNodeSets: in.NodeSets, BlockchainsInput: in.Blockchains, ContractVersions: env.GetContractVersions(), + WithV2Registries: env.GetCLIFlags().WithV2Registries(), JdInput: *in.JD, InfraInput: *in.Infra, S3ProviderInput: in.S3ProviderInput, diff --git a/deployment/cre/capabilities_registry/v2/changeset/operations/contracts/deploy_capability_registry.go b/deployment/cre/capabilities_registry/v2/changeset/operations/contracts/deploy_capability_registry.go index 9d34a6fdc51..51609ce3182 100644 --- a/deployment/cre/capabilities_registry/v2/changeset/operations/contracts/deploy_capability_registry.go +++ b/deployment/cre/capabilities_registry/v2/changeset/operations/contracts/deploy_capability_registry.go @@ -32,7 +32,7 @@ type DeployCapabilitiesRegistryOutput struct { // DeployCapabilitiesRegistry is an operation that deploys the V2 Capabilities Registry contract. // This atomic operation performs the single side effect of deploying and registering the contract. -var DeployCapabilitiesRegistry = operations.NewOperation[DeployCapabilitiesRegistryInput, DeployCapabilitiesRegistryOutput, DeployCapabilitiesRegistryDeps]( +var DeployCapabilitiesRegistry = operations.NewOperation( "deploy-capabilities-registry-v2-op", semver.MustParse("1.0.0"), "Deploy CapabilitiesRegistry V2 Contract", diff --git a/system-tests/lib/cre/environment/config/config.go b/system-tests/lib/cre/environment/config/config.go index 98679af0601..91e9fed8d12 100644 --- a/system-tests/lib/cre/environment/config/config.go +++ b/system-tests/lib/cre/environment/config/config.go @@ -81,7 +81,7 @@ func GetDefaultContractSet(withV2Registries bool) map[string]string { } if withV2Registries { - supportedSet[keystone_changeset.WorkflowRegistry.String()] = "2.0.0" + supportedSet[keystone_changeset.WorkflowRegistry.String()] = "2.0.0-dev" supportedSet[keystone_changeset.CapabilitiesRegistry.String()] = "2.0.0" } diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 1f3509d6275..9bd0b61bdeb 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -82,6 +82,7 @@ type SetupInput struct { JdInput jd.Input InfraInput infra.Input ContractVersions map[string]string + WithV2Registries bool OCR3Config *keystone_changeset.OracleConfig DONTimeConfig *keystone_changeset.OracleConfig VaultOCR3Config *keystone_changeset.OracleConfig @@ -119,17 +120,12 @@ func mustGetAddress(dataStore datastore.MutableDataStore, chainSel uint64, contr return addrRef.Address } -func useV2registryContracts(cv map[string]string) bool { - return cv[keystone_changeset.CapabilitiesRegistry.String()] == "2.0.0" && cv[keystone_changeset.WorkflowRegistry.String()] == "2.0.0" -} - func SetupTestEnvironment( ctx context.Context, testLogger zerolog.Logger, singleFileLogger logger.Logger, input SetupInput, ) (*SetupOutput, error) { - withV2RegistryContracts := useV2registryContracts(input.ContractVersions) topologyErr := libdon.ValidateTopology(input.CapabilitiesAwareNodeSets, input.InfraInput) if topologyErr != nil { return nil, pkgerrors.Wrap(topologyErr, "failed to validate topology") @@ -261,18 +257,18 @@ func SetupTestEnvironment( homeChainSelector := homeChainOutput.ChainSelector deployKeystoneReport, err := operations.ExecuteSequence( allChainsCLDEnvironment.OperationsBundle, - ks_contracts_op.DeployKeystoneContractsSequence, - ks_contracts_op.DeployKeystoneContractsSequenceDeps{ + ks_contracts_op.DeployContractsSequence, + ks_contracts_op.DeployContractsSequenceDeps{ Env: allChainsCLDEnvironment, }, - ks_contracts_op.DeployKeystoneContractsSequenceInput{ + ks_contracts_op.DeployContractsSequenceInput{ RegistryChainSelector: homeChainSelector, ForwardersSelectors: evmForwardersSelectors, DeployVaultOCR3: vaultOCR3AddrFlag, DeployEVMOCR3: evmOCR3AddrFlag, EVMChainIDs: chainsWithEVMCapability, DeployConsensusOCR3: consensusV2AddrFlag, - WithV2Contracts: withV2RegistryContracts, + WithV2Contracts: input.WithV2Registries, }, ) if err != nil { @@ -337,9 +333,7 @@ func SetupTestEnvironment( donTimeAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], "DONTime") testLogger.Info().Msgf("Deployed OCR3 %s (DON Time) contract on chain %d at %s", input.ContractVersions[keystone_changeset.OCR3Capability.String()], homeChainSelector, donTimeAddr) - wfRegVersion := input.ContractVersions[keystone_changeset.WorkflowRegistry.String()] - wfRegVersion = "1.0.0" // TODO(mstreet3): replace hardcoding of wf registry version - wfRegAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.WorkflowRegistry.String(), wfRegVersion, "") + wfRegAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.WorkflowRegistry.String(), input.ContractVersions[keystone_changeset.WorkflowRegistry.String()], "") testLogger.Info().Msgf("Deployed Workflow Registry %s contract on chain %d at %s", input.ContractVersions[keystone_changeset.WorkflowRegistry.String()], homeChainSelector, wfRegAddr) capRegAddr := mustGetAddress(memoryDatastore, homeChainSelector, keystone_changeset.CapabilitiesRegistry.String(), input.ContractVersions[keystone_changeset.CapabilitiesRegistry.String()], "") @@ -734,7 +728,7 @@ func SetupTestEnvironment( capabilitiesContractFactoryFunctions := make([]cre.CapabilityRegistryConfigFn, 0) for _, capability := range input.Capabilities { configFn := capability.CapabilityRegistryV1ConfigFn() - if withV2RegistryContracts { + if input.WithV2Registries { configFn = capability.CapabilityRegistryV2ConfigFn() } From aa8aee3cb3f49a6db19adfaf2364ac0a64cf893d Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Tue, 2 Sep 2025 18:10:37 -0400 Subject: [PATCH 25/37] chore: skip test --- .../changeset/operations/contracts/deploy_contracts_seq.go | 2 +- system-tests/tests/smoke/cre/cre_suite_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index 7edf76b85bf..5dd74f5d4c6 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -32,7 +32,7 @@ type DeployContractsSequenceInput struct { EVMChainIDs map[EVMChainID]Selector DeployConsensusOCR3 bool - // WithV2Contracts if true will deploy Capability Registry V2 + // WithV2Contracts if true will deploy Capability Registry and Workflow Registry V2 WithV2Contracts bool } diff --git a/system-tests/tests/smoke/cre/cre_suite_test.go b/system-tests/tests/smoke/cre/cre_suite_test.go index 767950ef28c..582685f2c6a 100644 --- a/system-tests/tests/smoke/cre/cre_suite_test.go +++ b/system-tests/tests/smoke/cre/cre_suite_test.go @@ -50,8 +50,8 @@ func Test_CRE_Suite(t *testing.T) { func Test_withV2Registries(t *testing.T) { t.Run("[v1] CRE Proof of Reserve (PoR) Test", func(t *testing.T) { - /* const skipReason = "Integrate v2 registry contracts in local CRE/test setup - https://smartcontract-it.atlassian.net/browse/CRE-635" - t.Skipf("Skipping test for the following reason: %s", skipReason) */ + const skipReason = "Integrate v2 registry contracts in local CRE/test setup - https://smartcontract-it.atlassian.net/browse/CRE-635" + t.Skipf("Skipping test for the following reason: %s", skipReason) flags := []string{"--with-contracts-version", "v2"} testEnv := SetupTestEnvironment(t, flags...) ExecutePoRTest(t, testEnv) From 905b5c3b38e3302b905f25f8d1184996190f38e8 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Tue, 2 Sep 2025 17:26:57 -0600 Subject: [PATCH 26/37] try to fix ci timeout --- .../configs/workflow-gateway-capabilities-don.toml | 7 ++++--- system-tests/tests/smoke/cre/cre_suite_test.go | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml b/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml index 88d9a575994..bec96d4495b 100644 --- a/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml +++ b/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml @@ -51,7 +51,7 @@ [nodesets.chain_capabilities] # we want to write only to the home chain, so that we can test whether remote write-evm-2337 capability of the 'capabilities DON' is used write-evm = ["1337"] - read-contract = ["1337", "2337"] + read-contract = ["1337"] # See ./examples/workflow-don-overrides.toml to learn how to override capability configs @@ -96,10 +96,11 @@ bootstrap_node_index = -1 gateway_node_index = -1 - capabilities = ["web-api-target", "vault"] + capabilities = ["vault"] [nodesets.chain_capabilities] - write-evm = ["1337", "2337"] + write-evm = ["2337"] + read-contract = ["2337"] [nodesets.db] image = "postgres:12.0" diff --git a/system-tests/tests/smoke/cre/cre_suite_test.go b/system-tests/tests/smoke/cre/cre_suite_test.go index 836323f02be..fdd0adfcb1a 100644 --- a/system-tests/tests/smoke/cre/cre_suite_test.go +++ b/system-tests/tests/smoke/cre/cre_suite_test.go @@ -8,8 +8,12 @@ import ( To execute tests locally start the local CRE first: Inside `core/scripts/cre/environment` directory 1. Ensure the necessary capabilities (i.e. readcontract, http-trigger, http-action) are listed in the environment configuration - 2. Run: `go run . env start && ctf obs up && ctf bs up` to start env + observability + blockscout. - 3. Execute the tests in `system-tests/tests/smoke/cre`: `go test -timeout 15m -run ^Test_CRE_Suite$`. + 2. Identify the appropriate topology that you want to test + 3. Stop and clear any existing environment: `go run . env stop -a` + 4. Run: `go run . env start -t && ./bin/ctf obs up` to start env + observability + 5. Optionally run blockscout `./bin/ctf bs up` + 6. Execute the tests in `system-tests/tests/smoke/cre` with CTF_CONFIG set to the corresponding topology file: + `export CTF_CONFIGS=../../../../core/scripts/cre/environment/configs/.toml; go test -timeout 15m -run ^Test_CRE_Suite$`. */ func Test_CRE_Suite(t *testing.T) { testEnv := SetupTestEnvironment(t) From 294cf1d916e9315e89db97a4fa43621cd9119ca7 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 3 Sep 2025 10:35:15 -0400 Subject: [PATCH 27/37] refactor: removes Get prefixes --- .../cre/environment/environment/environment.go | 6 +++--- .../contracts/deploy_contracts_seq.go | 11 +++++------ system-tests/lib/cre/capabilities/evm/evm.go | 14 ++++++++------ .../lib/cre/environment/config/config.go | 6 +++--- .../lib/cre/environment/environment.go | 2 +- system-tests/lib/cre/types.go | 18 ++++++++++-------- 6 files changed, 30 insertions(+), 27 deletions(-) diff --git a/core/scripts/cre/environment/environment/environment.go b/core/scripts/cre/environment/environment/environment.go index d44e4f30a40..da2edaa3c97 100644 --- a/core/scripts/cre/environment/environment/environment.go +++ b/core/scripts/cre/environment/environment/environment.go @@ -289,7 +289,7 @@ func startCmd() *cobra.Command { withV2Registries := withContractsVersion == "v2" envDependencies := cre.NewEnvironmentDependencies( flags.NewDefaultCapabilityFlagsProvider(), - cre.NewContractVersionsProvider(envconfig.GetDefaultContractSet(withV2Registries)), + cre.NewContractVersionsProvider(envconfig.DefaultContractSet(withV2Registries)), cre.NewCLIFlagsProvider(withV2Registries), ) @@ -662,8 +662,8 @@ func StartCLIEnvironment( universalSetupInput := creenv.SetupInput{ CapabilitiesAwareNodeSets: in.NodeSets, BlockchainsInput: in.Blockchains, - ContractVersions: env.GetContractVersions(), - WithV2Registries: env.GetCLIFlags().WithV2Registries(), + ContractVersions: env.ContractVersions(), + WithV2Registries: env.WithV2Registries(), JdInput: *in.JD, InfraInput: *in.Infra, S3ProviderInput: in.S3ProviderInput, diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index 5dd74f5d4c6..4a2c279da32 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -163,7 +163,7 @@ var DeployContractsSequence = operations.NewSequence( if input.DeployEVMOCR3 { for chainID, selector := range input.EVMChainIDs { // EVM cap OCR3 Contract - qualifier := GetCapabilityContractIdentifier(uint64(chainID)) + qualifier := CapabilityContractIdentifier(uint64(chainID)) evmOCR3DeployReport, err := operations.ExecuteOperation(b, DeployOCR3Op, DeployOCR3OpDeps(deps), DeployOCR3OpInput{ChainSelector: uint64(selector), Qualifier: qualifier}) if err != nil { return DeployContractsSequenceOutput{}, err @@ -193,7 +193,7 @@ var DeployContractsSequence = operations.NewSequence( }, ) -func GetCapabilityContractIdentifier(chainID uint64) string { +func CapabilityContractIdentifier(chainID uint64) string { return fmt.Sprintf("capability_evm_%d", chainID) } @@ -202,9 +202,8 @@ type DeprecatedOutput struct { AddressBook deployment.AddressBook } -// toV1Output transforms a v2 output to a common v1 output format. -// It accepts any v2 output type and returns a generic struct that handles -// the deprecated address book. +// toV1Output transforms a v2 output to a common output format that uses the deprecated +// address book. func toV1Output(in any) (DeprecatedOutput, error) { ab := deployment.NewMemoryAddressBook() ds := datastore.NewMemoryDataStore() @@ -237,7 +236,7 @@ func toV1Output(in any) (DeprecatedOutput, error) { labels.Add(l) } default: - return DeprecatedOutput{}, fmt.Errorf("unsupported input type for toCommonV1Output: %T", in) + return DeprecatedOutput{}, fmt.Errorf("unsupported input type for transform: %T", in) } if err := ds.Addresses().Add(r); err != nil { diff --git a/system-tests/lib/cre/capabilities/evm/evm.go b/system-tests/lib/cre/capabilities/evm/evm.go index e5fe4316bed..6a824352ad8 100644 --- a/system-tests/lib/cre/capabilities/evm/evm.go +++ b/system-tests/lib/cre/capabilities/evm/evm.go @@ -28,10 +28,12 @@ import ( "github.com/smartcontractkit/chainlink/system-tests/lib/cre/don/jobs/ocr/chainlevel" ) -const flag = cre.EVMCapability -const configTemplate = `'{"chainId":{{.ChainID}},"network":"{{.NetworkFamily}}","logTriggerPollInterval":{{.LogTriggerPollInterval}}, "creForwarderAddress":"{{.CreForwarderAddress}}","receiverGasMinimum":{{.ReceiverGasMinimum}},"nodeAddress":"{{.NodeAddress}}"}'` -const registrationRefresh = 20 * time.Second -const registrationExpiry = 60 * time.Second +const ( + flag = cre.EVMCapability + configTemplate = `'{"chainId":{{.ChainID}},"network":"{{.NetworkFamily}}","logTriggerPollInterval":{{.LogTriggerPollInterval}}, "creForwarderAddress":"{{.CreForwarderAddress}}","receiverGasMinimum":{{.ReceiverGasMinimum}},"nodeAddress":"{{.NodeAddress}}"}'` + registrationRefresh = 20 * time.Second + registrationExpiry = 60 * time.Second +) func New() (*capabilities.Capability, error) { return capabilities.New( @@ -99,7 +101,7 @@ func buildRuntimeValues(chainID uint64, networkFamily, creForwarderAddress, node } func jobSpec(input *cre.JobSpecInput) (cre.DonsToJobSpecs, error) { - var generateJobSpec = func(logger zerolog.Logger, chainID uint64, nodeAddress string, mergedConfig map[string]any) (string, error) { + generateJobSpec := func(logger zerolog.Logger, chainID uint64, nodeAddress string, mergedConfig map[string]any) (string, error) { cs, ok := chainselectors.EvmChainIdToChainSelector()[chainID] if !ok { return "", fmt.Errorf("chain selector not found for chainID: %d", chainID) @@ -150,7 +152,7 @@ func jobSpec(input *cre.JobSpecInput) (cre.DonsToJobSpecs, error) { input.CapabilitiesAwareNodeSets, input.InfraInput, flag, - contracts.GetCapabilityContractIdentifier, + contracts.CapabilityContractIdentifier, chainlevel.CapabilityEnabler, chainlevel.EnabledChainsProvider, generateJobSpec, diff --git a/system-tests/lib/cre/environment/config/config.go b/system-tests/lib/cre/environment/config/config.go index 91e9fed8d12..5befd6d2282 100644 --- a/system-tests/lib/cre/environment/config/config.go +++ b/system-tests/lib/cre/environment/config/config.go @@ -57,8 +57,8 @@ func (c Config) Validate(envDependencies cre.CLIEnvironmentDependencies) error { } func validateContractVersions(envDependencies cre.CLIEnvironmentDependencies) error { - supportedSet := GetDefaultContractSet(envDependencies.GetCLIFlags().WithV2Registries()) - cv := envDependencies.GetContractVersions() + supportedSet := DefaultContractSet(envDependencies.WithV2Registries()) + cv := envDependencies.ContractVersions() for k, v := range supportedSet { version, ok := cv[k] if !ok { @@ -72,7 +72,7 @@ func validateContractVersions(envDependencies cre.CLIEnvironmentDependencies) er return nil } -func GetDefaultContractSet(withV2Registries bool) map[string]string { +func DefaultContractSet(withV2Registries bool) map[string]string { supportedSet := map[string]string{ keystone_changeset.OCR3Capability.String(): "1.0.0", keystone_changeset.WorkflowRegistry.String(): "1.0.0", diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 8229af8089e..25b35cc9cfb 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -349,7 +349,7 @@ func SetupTestEnvironment( evmOCR3CommonAddresses := make(map[uint64]common.Address) if evmOCR3AddrFlag { for chainID, selector := range chainsWithEVMCapability { - qualifier := ks_contracts_op.GetCapabilityContractIdentifier(uint64(chainID)) + qualifier := ks_contracts_op.CapabilityContractIdentifier(uint64(chainID)) evmOCR3Addr := mustGetAddress(memoryDatastore, uint64(selector), keystone_changeset.OCR3Capability.String(), input.ContractVersions[keystone_changeset.OCR3Capability.String()], qualifier) testLogger.Info().Msgf("Deployed EVM OCR3 %s contract on chain %d, selector: %d, at: %s", input.ContractVersions[keystone_changeset.OCR3Capability.String()], chainID, selector, evmOCR3Addr) evmOCR3CommonAddresses[uint64(selector)] = common.HexToAddress(evmOCR3Addr) diff --git a/system-tests/lib/cre/types.go b/system-tests/lib/cre/types.go index a880b032833..638386733c8 100644 --- a/system-tests/lib/cre/types.go +++ b/system-tests/lib/cre/types.go @@ -66,9 +66,11 @@ const ( type CLIEnvironmentDependencies interface { CapabilityFlagsProvider ContractVersionsProvider - GetCLIFlags() CLIFlagsProvider + CLIFlagsProvider } +// CLIFlagsProvider provides access to select command line flags passed to the +// start command of the environment script. type CLIFlagsProvider interface { // If true, then use V2 Capability and Workflow Registries. WithV2Registries() bool @@ -89,15 +91,15 @@ func (cfp *cliFlagsProvider) WithV2Registries() bool { } type ContractVersionsProvider interface { - // GetContractVersions returns a map of contract name to semver - GetContractVersions() map[string]string + // ContractVersions returns a map of contract name to semver + ContractVersions() map[string]string } type contractVersionsProvider struct { contracts map[string]string } -func (cvp *contractVersionsProvider) GetContractVersions() map[string]string { +func (cvp *contractVersionsProvider) ContractVersions() map[string]string { cv := make(map[string]string, 0) maps.Copy(cv, cvp.contracts) return cv @@ -142,12 +144,12 @@ type envionmentDependencies struct { cliFlagsProvider CLIFlagsProvider } -func (e *envionmentDependencies) GetCLIFlags() CLIFlagsProvider { - return e.cliFlagsProvider +func (e *envionmentDependencies) WithV2Registries() bool { + return e.cliFlagsProvider.WithV2Registries() } -func (e *envionmentDependencies) GetContractVersions() map[string]string { - return e.contractSetProvider.GetContractVersions() +func (e *envionmentDependencies) ContractVersions() map[string]string { + return e.contractSetProvider.ContractVersions() } func (e *envionmentDependencies) SupportedCapabilityFlags() []CapabilityFlag { From 6bcb59d9a96f5642a2976954f2275eda5d8a8bdf Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 3 Sep 2025 11:24:52 -0400 Subject: [PATCH 28/37] chore: lint --- .../contracts/deploy_contracts_seq.go | 8 +++-- .../lib/cre/don/config/definitions.go | 31 ------------------- 2 files changed, 6 insertions(+), 33 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index 4a2c279da32..340c74221f9 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -80,7 +80,9 @@ var DeployContractsSequence = operations.NewSequence( return DeployContractsSequenceOutput{}, err } - err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook) + if err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook); err != nil { + return DeployContractsSequenceOutput{}, err + } } else { capabilitiesRegistryDeployReport, err := operations.ExecuteOperation(b, DeployCapabilityRegistryOp, DeployCapabilityRegistryOpDeps(deps), DeployCapabilityRegistryInput{ChainSelector: input.RegistryChainSelector}) if err != nil { @@ -116,7 +118,9 @@ var DeployContractsSequence = operations.NewSequence( return DeployContractsSequenceOutput{}, err } - err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook) + if err = updateAddresses(as.Addresses(), out.Addresses, ab, out.AddressBook); err != nil { + return DeployContractsSequenceOutput{}, err + } } else { workflowRegistryDeployReport, err := operations.ExecuteOperation(b, DeployWorkflowRegistryOp, DeployWorkflowRegistryOpDeps(deps), DeployWorkflowRegistryInput{ChainSelector: input.RegistryChainSelector}) if err != nil { diff --git a/system-tests/lib/cre/don/config/definitions.go b/system-tests/lib/cre/don/config/definitions.go index 3a66de6de18..ed848662fc4 100644 --- a/system-tests/lib/cre/don/config/definitions.go +++ b/system-tests/lib/cre/don/config/definitions.go @@ -9,37 +9,6 @@ import ( "github.com/smartcontractkit/chainlink/system-tests/lib/cre" ) -const ( - // Template for EVM workflow configuration - evmWorkflowConfigTemplate = ` - [EVM.Workflow] - FromAddress = '{{.FromAddress}}' - ForwarderAddress = '{{.ForwarderAddress}}' - GasLimitDefault = {{.GasLimitDefault}} - TxAcceptanceState = {{.TxAcceptanceState}} - PollPeriod = '{{.PollPeriod}}' - AcceptanceTimeout = '{{.AcceptanceTimeout}}' - - [EVM.Transactions] - ForwardersEnabled = true -` - - solWorkflowConfigTemplate = ` - Enabled = true - TxRetentionTimeout = '{{.TxRetentionTimeout}}' - - [Solana.Workflow] - Enabled = true - ForwarderAddress = '{{.ForwarderAddress}}' - FromAddress = '{{.FromAddress}}' - ForwarderState = '{{.ForwarderState}}' - PollPeriod = '{{.PollPeriod}}' - AcceptanceTimeout = '{{.AcceptanceTimeout}}' - TxAcceptanceState = {{.TxAcceptanceState}} - Local = {{.Local}} - ` -) - type AddressTypeVersion struct { Address common.Address cldf.TypeAndVersion From 077e3e252dd5cdda4ca6bacf514274d7a0a4323a Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 3 Sep 2025 11:52:01 -0400 Subject: [PATCH 29/37] fix linters --- system-tests/tests/load/cre/writer_don_load_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/system-tests/tests/load/cre/writer_don_load_test.go b/system-tests/tests/load/cre/writer_don_load_test.go index 47310eb79f2..19d08929224 100644 --- a/system-tests/tests/load/cre/writer_don_load_test.go +++ b/system-tests/tests/load/cre/writer_don_load_test.go @@ -98,7 +98,10 @@ func setupLoadTestWriterEnvironment( in.WorkflowRegistryConfiguration = &cretypes.WorkflowRegistryInput{} in.WorkflowRegistryConfiguration.Out = universalSetupOutput.WorkflowRegistryConfigurationOutput - forwarderAddress, _, forwarderErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, keystone_changeset.KeystoneForwarder.String()) //nolint:staticcheck // won't migrate now + forwarderAddress, _, forwarderErr := libcontracts.FindAddressesForChain( + universalSetupOutput.CldEnvironment.ExistingAddresses, //nolint:all // won't migrate now + universalSetupOutput.BlockchainOutput[0].ChainSelector, + keystone_changeset.KeystoneForwarder.String()) require.NoError(t, forwarderErr, "failed to find forwarder address for chain %d", universalSetupOutput.BlockchainOutput[0].ChainSelector) // DF cache start @@ -111,10 +114,10 @@ func setupLoadTestWriterEnvironment( dfOutput, dfErr := changeset2.RunChangeset(changeset.DeployCacheChangeset, *universalSetupOutput.CldEnvironment, deployConfig) require.NoError(t, dfErr, "failed to deploy data feed cache contract") - mergeErr := universalSetupOutput.CldEnvironment.ExistingAddresses.Merge(dfOutput.AddressBook) //nolint:staticcheck // won't migrate now + mergeErr := universalSetupOutput.CldEnvironment.ExistingAddresses.Merge(dfOutput.AddressBook) //nolint:all // won't migrate now require.NoError(t, mergeErr, "failed to merge address book") - dfCacheAddress, _, dfCacheErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, changeset.DataFeedsCache.String()) //nolint:staticcheck // won't migrate now + dfCacheAddress, _, dfCacheErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, changeset.DataFeedsCache.String()) //nolint:all // won't migrate now require.NoError(t, dfCacheErr, "failed to find df cache address for chain %d", universalSetupOutput.BlockchainOutput[0].ChainSelector) // Config _, configErr := libcontracts.ConfigureDataFeedsCache(testLogger, &cretypes.ConfigureDataFeedsCacheInput{ From 102505ca0948c13c307237024509ae293f59d2f3 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 3 Sep 2025 14:38:21 -0400 Subject: [PATCH 30/37] lint file --- system-tests/tests/load/cre/writer_don_load_test.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/system-tests/tests/load/cre/writer_don_load_test.go b/system-tests/tests/load/cre/writer_don_load_test.go index 19d08929224..47310eb79f2 100644 --- a/system-tests/tests/load/cre/writer_don_load_test.go +++ b/system-tests/tests/load/cre/writer_don_load_test.go @@ -98,10 +98,7 @@ func setupLoadTestWriterEnvironment( in.WorkflowRegistryConfiguration = &cretypes.WorkflowRegistryInput{} in.WorkflowRegistryConfiguration.Out = universalSetupOutput.WorkflowRegistryConfigurationOutput - forwarderAddress, _, forwarderErr := libcontracts.FindAddressesForChain( - universalSetupOutput.CldEnvironment.ExistingAddresses, //nolint:all // won't migrate now - universalSetupOutput.BlockchainOutput[0].ChainSelector, - keystone_changeset.KeystoneForwarder.String()) + forwarderAddress, _, forwarderErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, keystone_changeset.KeystoneForwarder.String()) //nolint:staticcheck // won't migrate now require.NoError(t, forwarderErr, "failed to find forwarder address for chain %d", universalSetupOutput.BlockchainOutput[0].ChainSelector) // DF cache start @@ -114,10 +111,10 @@ func setupLoadTestWriterEnvironment( dfOutput, dfErr := changeset2.RunChangeset(changeset.DeployCacheChangeset, *universalSetupOutput.CldEnvironment, deployConfig) require.NoError(t, dfErr, "failed to deploy data feed cache contract") - mergeErr := universalSetupOutput.CldEnvironment.ExistingAddresses.Merge(dfOutput.AddressBook) //nolint:all // won't migrate now + mergeErr := universalSetupOutput.CldEnvironment.ExistingAddresses.Merge(dfOutput.AddressBook) //nolint:staticcheck // won't migrate now require.NoError(t, mergeErr, "failed to merge address book") - dfCacheAddress, _, dfCacheErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, changeset.DataFeedsCache.String()) //nolint:all // won't migrate now + dfCacheAddress, _, dfCacheErr := libcontracts.FindAddressesForChain(universalSetupOutput.CldEnvironment.ExistingAddresses, universalSetupOutput.BlockchainOutput[0].ChainSelector, changeset.DataFeedsCache.String()) //nolint:staticcheck // won't migrate now require.NoError(t, dfCacheErr, "failed to find df cache address for chain %d", universalSetupOutput.BlockchainOutput[0].ChainSelector) // Config _, configErr := libcontracts.ConfigureDataFeedsCache(testLogger, &cretypes.ConfigureDataFeedsCacheInput{ From a16a9a5197fba9f11c01e0ea3835b64378968c46 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 3 Sep 2025 14:53:09 -0400 Subject: [PATCH 31/37] fix: overrite default config fn --- system-tests/lib/cre/capabilities/builder.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system-tests/lib/cre/capabilities/builder.go b/system-tests/lib/cre/capabilities/builder.go index 4db47948b44..6b67752bf6b 100644 --- a/system-tests/lib/cre/capabilities/builder.go +++ b/system-tests/lib/cre/capabilities/builder.go @@ -17,7 +17,7 @@ type Capability struct { jobSpecFn cre.JobSpecFn nodeConfigFn cre.NodeConfigTransformerFn gatewayJobHandlerConfigFn cre.GatewayHandlerConfigFn - registryConfigFns registryConfigFns + registryConfigFns *registryConfigFns validateFn func(*Capability) error } @@ -86,7 +86,7 @@ func WithValidateFn(validateFn func(*Capability) error) Option { func New(flag cre.CapabilityFlag, opts ...Option) (*Capability, error) { capability := &Capability{ flag: flag, - registryConfigFns: registryConfigFns{ + registryConfigFns: ®istryConfigFns{ V1: unimplmentedConfigFn, V2: unimplmentedConfigFn, }, From dba97e7895cfa1227222c266fb620784576d3020 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 3 Sep 2025 14:53:50 -0400 Subject: [PATCH 32/37] deps: changeset --- .changeset/forty-zebras-grab.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/forty-zebras-grab.md diff --git a/.changeset/forty-zebras-grab.md b/.changeset/forty-zebras-grab.md new file mode 100644 index 00000000000..d81816e043f --- /dev/null +++ b/.changeset/forty-zebras-grab.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal deploys V2 registries in local CRE From 93138c23d2361cb1fc3f0f6bb72d61973c6b3a24 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 3 Sep 2025 16:03:58 -0400 Subject: [PATCH 33/37] fix: allow nil config funcs to be skipped --- system-tests/lib/cre/capabilities/builder.go | 31 +++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/system-tests/lib/cre/capabilities/builder.go b/system-tests/lib/cre/capabilities/builder.go index 6b67752bf6b..90194a74a7a 100644 --- a/system-tests/lib/cre/capabilities/builder.go +++ b/system-tests/lib/cre/capabilities/builder.go @@ -3,7 +3,6 @@ package capabilities import ( "github.com/pkg/errors" - keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/system-tests/lib/cre" ) @@ -38,11 +37,17 @@ func (c *Capability) GatewayJobHandlerConfigFn() cre.GatewayHandlerConfigFn { } func (c *Capability) CapabilityRegistryV1ConfigFn() cre.CapabilityRegistryConfigFn { - return c.registryConfigFns.V1 + if c.registryConfigFns != nil { + return c.registryConfigFns.V1 + } + return nil } func (c *Capability) CapabilityRegistryV2ConfigFn() cre.CapabilityRegistryConfigFn { - return c.registryConfigFns.V2 + if c.registryConfigFns != nil { + return c.registryConfigFns.V2 + } + return nil } type Option func(*Capability) @@ -67,12 +72,24 @@ func WithGatewayJobHandlerConfigFn(gatewayJobHandlerConfigFn cre.GatewayHandlerC func WithCapabilityRegistryV1ConfigFn(fn cre.CapabilityRegistryConfigFn) Option { return func(c *Capability) { + if c.registryConfigFns == nil { + c.registryConfigFns = ®istryConfigFns{ + V1: fn, + } + return + } c.registryConfigFns.V1 = fn } } func WithCapabilityRegistryV2ConfigFn(fn cre.CapabilityRegistryConfigFn) Option { return func(c *Capability) { + if c.registryConfigFns == nil { + c.registryConfigFns = ®istryConfigFns{ + V2: fn, + } + return + } c.registryConfigFns.V2 = fn } } @@ -86,10 +103,6 @@ func WithValidateFn(validateFn func(*Capability) error) Option { func New(flag cre.CapabilityFlag, opts ...Option) (*Capability, error) { capability := &Capability{ flag: flag, - registryConfigFns: ®istryConfigFns{ - V1: unimplmentedConfigFn, - V2: unimplmentedConfigFn, - }, } for _, opt := range opts { opt(capability) @@ -103,7 +116,3 @@ func New(flag cre.CapabilityFlag, opts ...Option) (*Capability, error) { return capability, nil } - -func unimplmentedConfigFn(donFlags []cre.CapabilityFlag, nodeSetInput *cre.CapabilitiesAwareNodeSet) ([]keystone_changeset.DONCapabilityWithConfig, error) { - return nil, errors.New("config function is not implemented") -} From 8386d8e8e2a68e8926bf7c41508ee87b9b79d7e7 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Thu, 4 Sep 2025 08:11:18 -0600 Subject: [PATCH 34/37] put back web-api-target --- .../environment/configs/workflow-gateway-capabilities-don.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml b/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml index bec96d4495b..82de7ca0d50 100644 --- a/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml +++ b/core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml @@ -96,7 +96,7 @@ bootstrap_node_index = -1 gateway_node_index = -1 - capabilities = ["vault"] + capabilities = ["web-api-target","vault"] [nodesets.chain_capabilities] write-evm = ["2337"] From 95a93949ec8ca76b6365019b7fb691aae9879cf5 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Thu, 4 Sep 2025 11:15:19 -0400 Subject: [PATCH 35/37] refactor: create v2 deploy sequence --- .../contracts/deploy_contracts_seq.go | 49 ++++++++++++++++++- .../lib/cre/environment/environment.go | 7 ++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go index dbd1fdf1293..64131b4e314 100644 --- a/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go +++ b/deployment/keystone/changeset/operations/contracts/deploy_contracts_seq.go @@ -48,7 +48,7 @@ func updateAddresses(addr datastore.MutableAddressRefStore, as datastore.Address } // DeployRegistryContractsSequence is a sequence that deploys the the required registry contracts (Capabilities Registry, Workflow Registry). -var DeployRegistryContractsSequence = operations.NewSequence[DeployRegistryContractsSequenceInput, DeployContractSequenceOutput, DeployContractsSequenceDeps]( +var DeployRegistryContractsSequence = operations.NewSequence( // do not add optional contracts here (ocr, forwarder...), as this sequence is used to deploy the registry contracts that other sequences depend on "deploy-registry-contracts-seq", semver.MustParse("1.0.0"), @@ -82,6 +82,53 @@ var DeployRegistryContractsSequence = operations.NewSequence[DeployRegistryContr }, ) +// DeployV2RegistryContractsSequence is a sequence that deploys the the required registry contracts (Capabilities Registry, Workflow Registry). +var DeployV2RegistryContractsSequence = operations.NewSequence( + // do not add optional contracts here (ocr, forwarder...), as this sequence is used to deploy the registry contracts that other sequences depend on + "deploy-v2-registry-contracts-seq", + semver.MustParse("1.0.0"), + "Deploy V2 registry Contracts (Capabilities Registry, Workflow Registry)", + func(b operations.Bundle, deps DeployContractsSequenceDeps, input DeployRegistryContractsSequenceInput) (output DeployContractSequenceOutput, err error) { + ab := deployment.NewMemoryAddressBook() + as := datastore.NewMemoryDataStore() + + // Capabilities Registry contract + capabilitiesRegistryDeployReport, err := operations.ExecuteOperation(b, cap_reg_v2.DeployCapabilitiesRegistry, cap_reg_v2.DeployCapabilitiesRegistryDeps(deps), cap_reg_v2.DeployCapabilitiesRegistryInput{ChainSelector: input.RegistryChainSelector}) + if err != nil { + return DeployContractSequenceOutput{}, err + } + + v1Output, err := toV1Output(capabilitiesRegistryDeployReport.Output) + if err != nil { + return DeployContractSequenceOutput{}, err + } + + if err = updateAddresses(as.Addresses(), v1Output.Addresses, ab, v1Output.AddressBook); err != nil { + return DeployContractSequenceOutput{}, err + } + + // Workflow Registry contract + workflowRegistryDeployReport, err := operations.ExecuteOperation(b, wf_reg_v2.DeployWorkflowRegistryOp, wf_reg_v2.DeployWorkflowRegistryOpDeps(deps), wf_reg_v2.DeployWorkflowRegistryOpInput{ChainSelector: input.RegistryChainSelector}) + if err != nil { + return DeployContractSequenceOutput{}, err + } + + v1Output, err = toV1Output(workflowRegistryDeployReport.Output) + if err != nil { + return DeployContractSequenceOutput{}, err + } + + err = updateAddresses(as.Addresses(), v1Output.Addresses, ab, v1Output.AddressBook) + if err != nil { + return DeployContractSequenceOutput{}, err + } + return DeployContractSequenceOutput{ + AddressBook: ab, + Datastore: as.Seal(), + }, nil + }, +) + func CapabilityContractIdentifier(chainID uint64) string { return fmt.Sprintf("capability_evm_%d", chainID) } diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index e3eacc721e8..63bdda8d78e 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -255,9 +255,14 @@ func SetupTestEnvironment( // use CLD to deploy the registry contracts, which are required before constructing the node TOML configs homeChainSelector := homeChainOutput.ChainSelector + deployRegistrySeq := ks_contracts_op.DeployRegistryContractsSequence + if input.WithV2Registries { + deployRegistrySeq = ks_contracts_op.DeployV2RegistryContractsSequence + } + registryContractsReport, seqErr := operations.ExecuteSequence( allChainsCLDEnvironment.OperationsBundle, - ks_contracts_op.DeployRegistryContractsSequence, + deployRegistrySeq, ks_contracts_op.DeployContractsSequenceDeps{ Env: allChainsCLDEnvironment, }, From 646b1fb42a9d1c2444a5755cf78f047b4bca5d4f Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:45:21 -0400 Subject: [PATCH 36/37] clean up --- .../lib/cre/environment/environment.go | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index d95a34d1f7d..63bdda8d78e 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -349,42 +349,6 @@ func SetupTestEnvironment( testLogger.Info().Msgf("Deployed Forwarder %s contract on Solana chain chain %d programID: %s state: %s", input.ContractVersions[ks_sol.ForwarderContract.String()], sel, out.Output.ProgramID.String(), out.Output.State.String()) } - // deploy the various ocr contracts - // TODO move this deeper into the stack when we have all the p2p ids and can deploy and configure in one sequence - // deploy OCR3 contract - // we deploy OCR3 contract with a qualifier, so that we can distinguish it from other OCR3 contracts (Vault, EVM, ConsensusV2) - // TODO track the qualifiers in vars/consts rather than raw strings - _, seqErr = deployOCR3Contract("capability_ocr3", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if seqErr != nil { - return nil, fmt.Errorf("failed to deploy OCR3 contract %w", seqErr) - } - // deploy DONTime contract - _, seqErr = deployOCR3Contract("DONTime", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if seqErr != nil { - return nil, fmt.Errorf("failed to deploy DONTime contract %w", seqErr) - } - if vaultOCR3AddrFlag { - _, seqErr = deployOCR3Contract("capability_vault", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if seqErr != nil { - return nil, fmt.Errorf("failed to deploy Vault OCR3 contract %w", seqErr) - } - } - if evmOCR3AddrFlag { - for chainID, selector := range chainsWithEVMCapability { - qualifier := ks_contracts_op.CapabilityContractIdentifier(uint64(chainID)) - _, seqErr = deployOCR3Contract(qualifier, uint64(selector), allChainsCLDEnvironment, memoryDatastore) - if seqErr != nil { - return nil, fmt.Errorf("failed to deploy EVM OCR3 contract for chainID %d, selector %d: %w", chainID, selector, seqErr) - } - } - } - if consensusV2AddrFlag { - _, seqErr = deployOCR3Contract("capability_consensus", homeChainSelector, allChainsCLDEnvironment, memoryDatastore) - if seqErr != nil { - return nil, fmt.Errorf("failed to deploy Consensus V2 OCR3 contract %w", seqErr) - } - } - // deploy the various ocr contracts // TODO move this deeper into the stack when we have all the p2p ids and can deploy and configure in one sequence // deploy OCR3 contract From 6a4f8fe936a4b7c65e0dd8f29953011b65183430 Mon Sep 17 00:00:00 2001 From: Michael Street <5597260+MStreet3@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:50:21 -0400 Subject: [PATCH 37/37] lint --- system-tests/tests/load/cre/workflow_don_load_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-tests/tests/load/cre/workflow_don_load_test.go b/system-tests/tests/load/cre/workflow_don_load_test.go index 4378714ce9e..5b9399656c6 100644 --- a/system-tests/tests/load/cre/workflow_don_load_test.go +++ b/system-tests/tests/load/cre/workflow_don_load_test.go @@ -131,7 +131,7 @@ func setupLoadTestEnvironment( JdInput: *in.JD, InfraInput: *in.Infra, JobSpecFactoryFunctions: jobSpecFactoryFns, - ContractVersions: cretypes.NewContractVersionsProvider(envconfig.GetDefaultContractSet(false)).GetContractVersions(), + ContractVersions: cretypes.NewContractVersionsProvider(envconfig.DefaultContractSet(false)).ContractVersions(), } singleFileLogger := cldlogger.NewSingleFileLogger(t)