From d566c93a00e2857be5fdfeed7bf1249b040f7019 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 1 Nov 2024 02:12:36 +1100 Subject: [PATCH 01/16] update with changes from chainlink-ccip returning all configs --- core/capabilities/ccip/launcher/deployment.go | 45 +++++++++++++++---- core/capabilities/ccip/launcher/launcher.go | 43 +++++++++++------- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index 631c02d5cc9..f5bab3750be 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -4,7 +4,7 @@ import ( "fmt" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "go.uber.org/multierr" ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" @@ -13,13 +13,15 @@ import ( // activeCandidateDeployment represents a active-candidate deployment of OCR instances. type activeCandidateDeployment struct { // active is the active OCR instance. - // active must always be present. - active cctypes.CCIPOracle + // activeDigest is used to determine state transitions + active cctypes.CCIPOracle + activeDigest ocrtypes.ConfigDigest // candidate is the candidate OCR instance. // candidate may or may not be present. - // candidate must never be present if active is not present. - candidate cctypes.CCIPOracle + // candidateDigest is used to determine state transitions + candidate cctypes.CCIPOracle + candidateDigest ocrtypes.ConfigDigest } // ccipDeployment represents active-candidate deployments of both commit and exec @@ -29,6 +31,7 @@ type ccipDeployment struct { exec activeCandidateDeployment } +// TODO: Do we need to update the digests when we "close" the deployment? // Close shuts down all OCR instances in the deployment. func (c *ccipDeployment) Close() error { // we potentially run into this situation when @@ -83,6 +86,28 @@ func (c *ccipDeployment) CloseActive() error { return err } +// StartCandidate starts the candidate OCR instance. +// Candidate instances will generate reports but not transmit them +func (c *ccipDeployment) StartCandidate() error { + var err error + + err = multierr.Append(err, c.commit.candidate.Start()) + err = multierr.Append(err, c.exec.candidate.Start()) + + return err +} + +// CloseCandidate shuts off the candidate instance +// This is used when a candidate is revoked or replaced +func (c *ccipDeployment) CloseCandidate() error { + var err error + + err = multierr.Append(err, c.commit.candidate.Close()) + err = multierr.Append(err, c.exec.candidate.Close()) + + return err +} + // TransitionDeployment handles the active-candidate deployment transition. // prevDeployment is the previous deployment state. // there are two possible cases: @@ -133,10 +158,12 @@ func (c *ccipDeployment) HasCandidateInstance(pluginType cctypes.PluginType) boo } } -func isNewCandidateInstance(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { - return len(ocrConfigs) == 2 && !prevDeployment.HasCandidateInstance(pluginType) +func isNewCandidateInstance(pluginType cctypes.PluginType, ocrConfigs ccipreaderpkg.ActiveAndCandidate, prevDeployment ccipDeployment) bool { + return ocrConfigs.CandidateConfig.ConfigDigest != [32]byte{} && !prevDeployment.HasCandidateInstance(pluginType) } -func isPromotion(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { - return len(ocrConfigs) == 1 && prevDeployment.HasCandidateInstance(pluginType) +// Todo: not exactly correct. We could be replacing the candidate with nil +func isPromotion(pluginType cctypes.PluginType, ocrConfigs ccipreaderpkg.ActiveAndCandidate, prevDeployment ccipDeployment) bool { + return ocrConfigs.ActiveConfig.ConfigDigest != [32]byte{} && !prevDeployment.HasCandidateInstance(pluginType) + } diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index c52c6493181..e6aa8a943d1 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -8,6 +8,8 @@ import ( "time" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" @@ -252,11 +254,10 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DO continue } - // TODO: this doesn't seem to be correct; a newly added DON will not have an active - // instance but a candidate instance. - if err := dep.StartActive(); err != nil { - if shutdownErr := dep.CloseActive(); shutdownErr != nil { - l.lggr.Errorw("Failed to shutdown active instance after failed start", "donId", donID, "err", shutdownErr) + // expect that the new process is a candidate instance. + if err := dep.StartCandidate(); err != nil { + if shutdownErr := dep.CloseCandidate(); shutdownErr != nil { + l.lggr.Errorw("Failed to shutdown candidate instance after failed start", "donId", donID, "err", shutdownErr) } return fmt.Errorf("processAdded: start oracles for CCIP DON %d: %w", donID, err) } @@ -345,7 +346,7 @@ func updateDON( func createFutureActiveCandidateDeployment( donID uint32, prevDeployment ccipDeployment, - ocrConfigs []ccipreader.OCR3ConfigWithMeta, + ocrConfigs ccipreader.ActiveAndCandidate, oracleCreator cctypes.OracleCreator, pluginType cctypes.PluginType, ) (activeCandidateDeployment, error) { @@ -391,13 +392,14 @@ func createDON( don.ID, err) } + // TODO: is this true? What if an MCM operation sets to candidate and upgrades immediately within a "tick"? // upon creation we should only have one OCR config per plugin type. - if len(commitOCRConfigs) != 1 { - return nil, fmt.Errorf("expected exactly one OCR config for CCIP commit plugin (don id: %d), got %d", don.ID, len(commitOCRConfigs)) + if commitOCRConfigs.ActiveConfig.ConfigDigest != [32]byte{} { + return nil, fmt.Errorf("expected the newest config to be a candidate, not active (don id: %d), got %+v", don.ID, commitOCRConfigs) } - if len(execOCRConfigs) != 1 { - return nil, fmt.Errorf("expected exactly one OCR config for CCIP exec plugin (don id: %d), got %d", don.ID, len(execOCRConfigs)) + if execOCRConfigs.ActiveConfig.ConfigDigest != [32]byte{} { + return nil, fmt.Errorf("expected exactly one OCR config for CCIP exec plugin (don id: %d), got %+v", don.ID, execOCRConfigs) } if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { @@ -407,23 +409,34 @@ func createDON( // at this point we know we are either a member of the DON or a bootstrap node. // the injected oracleCreator will create the appropriate oracle. - commitOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(commitOCRConfigs[0])) + commitOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(commitOCRConfigs.CandidateConfig)) if err != nil { return nil, fmt.Errorf("failed to create CCIP commit oracle: %w", err) } - execOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(execOCRConfigs[0])) + execOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(execOCRConfigs.CandidateConfig)) if err != nil { return nil, fmt.Errorf("failed to create CCIP exec oracle: %w", err) } - // TODO: incorrect, should be setting candidate? + commitDigest, err := ocrtypes.BytesToConfigDigest(commitOCRConfigs.CandidateConfig.ConfigDigest[:]) + if err != nil { + return nil, fmt.Errorf("Candidate commit digest does not match type %w", err) + } + + execDigest, err := ocrtypes.BytesToConfigDigest(execOCRConfigs.CandidateConfig.ConfigDigest[:]) + if err != nil { + return nil, fmt.Errorf("exec commit digest does not match type %w", err) + } + return &ccipDeployment{ commit: activeCandidateDeployment{ - active: commitOracle, + candidate: commitOracle, + candidateDigest: commitDigest, }, exec: activeCandidateDeployment{ - active: execOracle, + candidate: execOracle, + candidateDigest: execDigest, }, }, nil } From d77f9c30e19f1c7848f84cf2ed22fc5216995d1e Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 1 Nov 2024 19:38:18 +1100 Subject: [PATCH 02/16] update launcher logic --- core/capabilities/ccip/launcher/deployment.go | 162 ++---------- core/capabilities/ccip/launcher/launcher.go | 243 ++++++------------ 2 files changed, 98 insertions(+), 307 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index f5bab3750be..cd1b03a2bbd 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -1,169 +1,45 @@ package launcher import ( - "fmt" + "golang.org/x/exp/maps" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "go.uber.org/multierr" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" ) -// activeCandidateDeployment represents a active-candidate deployment of OCR instances. -type activeCandidateDeployment struct { - // active is the active OCR instance. - // activeDigest is used to determine state transitions - active cctypes.CCIPOracle - activeDigest ocrtypes.ConfigDigest - - // candidate is the candidate OCR instance. - // candidate may or may not be present. - // candidateDigest is used to determine state transitions - candidate cctypes.CCIPOracle - candidateDigest ocrtypes.ConfigDigest -} - -// ccipDeployment represents active-candidate deployments of both commit and exec -// OCR instances. -type ccipDeployment struct { - commit activeCandidateDeployment - exec activeCandidateDeployment -} - -// TODO: Do we need to update the digests when we "close" the deployment? -// Close shuts down all OCR instances in the deployment. -func (c *ccipDeployment) Close() error { - // we potentially run into this situation when - // trying to close an active instance that doesn't exist - // this check protects us from nil pointer exception +type ccipPlugins map[ocrtypes.ConfigDigest]*cctypes.CCIPOracle +// Close is used to shut down an entire don immediately +func (c *ccipPlugins) Close() error { if c == nil { return nil } var err error - // shutdown active commit instance. - if c.commit.active != nil { - err = multierr.Append(err, c.commit.active.Close()) - } - - // shutdown candidate commit instance. - if c.commit.candidate != nil { - err = multierr.Append(err, c.commit.candidate.Close()) - } - - // shutdown active exec instance. - if c.exec.active != nil { - err = multierr.Append(err, c.exec.active.Close()) - } - - // shutdown candidate exec instance. - if c.exec.candidate != nil { - err = multierr.Append(err, c.exec.candidate.Close()) + for _, oracle := range *c { + err = multierr.Append(err, (*oracle).Close()) } return err } -// StartActive starts the active OCR instances. -func (c *ccipDeployment) StartActive() error { - var err error - - err = multierr.Append(err, c.commit.active.Start()) - err = multierr.Append(err, c.exec.active.Start()) - - return err -} - -// CloseActive shuts down the active OCR instances. -func (c *ccipDeployment) CloseActive() error { - var err error - - err = multierr.Append(err, c.commit.active.Close()) - err = multierr.Append(err, c.exec.active.Close()) - - return err -} - -// StartCandidate starts the candidate OCR instance. -// Candidate instances will generate reports but not transmit them -func (c *ccipDeployment) StartCandidate() error { +// Transition manages starting and stopping ocr instances +// If there are any new config digests, we need to start those instances +// If any of the previous config digests are no longer present, we need to shut those down +// We don't care about if they're exec/commit or active/candidate, that all happens in the plugin +func (c *ccipPlugins) Transition(prevPlugins *ccipPlugins) error { var err error - - err = multierr.Append(err, c.commit.candidate.Start()) - err = multierr.Append(err, c.exec.candidate.Start()) - - return err -} - -// CloseCandidate shuts off the candidate instance -// This is used when a candidate is revoked or replaced -func (c *ccipDeployment) CloseCandidate() error { - var err error - - err = multierr.Append(err, c.commit.candidate.Close()) - err = multierr.Append(err, c.exec.candidate.Close()) - - return err -} - -// TransitionDeployment handles the active-candidate deployment transition. -// prevDeployment is the previous deployment state. -// there are two possible cases: -// -// 1. both active and candidate are present in prevDeployment, but only active is present in c. -// this is a promotion of candidate to active, so we need to shut down the active deployment -// and make candidate the new active. In this case candidate is already running, so there's no -// need to start it. However, we need to shut down the active deployment. -// -// 2. only active is present in prevDeployment, both active and candidate are present in c. -// In this case, active is already running, so there's no need to start it. We need to -// start candidate. -func (c *ccipDeployment) TransitionDeployment(prevDeployment *ccipDeployment) error { - if prevDeployment == nil { - return fmt.Errorf("previous deployment is nil") + for _, digest := range maps.Keys(*prevPlugins) { + if *c == nil || (*c)[digest] == nil { + err = multierr.Append(err, (*(*prevPlugins)[digest]).Close()) + } } - var err error - if prevDeployment.commit.candidate != nil && c.commit.candidate == nil { - err = multierr.Append(err, prevDeployment.commit.active.Close()) - } else if prevDeployment.commit.candidate == nil && c.commit.candidate != nil { - err = multierr.Append(err, c.commit.candidate.Start()) - } else { - return fmt.Errorf("invalid active-candidate deployment transition") + for _, digest := range maps.Keys(*c) { + if *prevPlugins == nil || (*prevPlugins)[digest] == nil { + err = multierr.Append(err, (*(*c)[digest]).Start()) + } } - - if prevDeployment.exec.candidate != nil && c.exec.candidate == nil { - err = multierr.Append(err, prevDeployment.exec.active.Close()) - } else if prevDeployment.exec.candidate == nil && c.exec.candidate != nil { - err = multierr.Append(err, c.exec.candidate.Start()) - } else { - return fmt.Errorf("invalid active-candidate deployment transition") - } - return err } - -// HasCandidateInstance returns true if the deployment has a candidate instance for the -// given plugin type. -func (c *ccipDeployment) HasCandidateInstance(pluginType cctypes.PluginType) bool { - switch pluginType { - case cctypes.PluginTypeCCIPCommit: - return c.commit.candidate != nil - case cctypes.PluginTypeCCIPExec: - return c.exec.candidate != nil - default: - return false - } -} - -func isNewCandidateInstance(pluginType cctypes.PluginType, ocrConfigs ccipreaderpkg.ActiveAndCandidate, prevDeployment ccipDeployment) bool { - return ocrConfigs.CandidateConfig.ConfigDigest != [32]byte{} && !prevDeployment.HasCandidateInstance(pluginType) -} - -// Todo: not exactly correct. We could be replacing the candidate with nil -func isPromotion(pluginType cctypes.PluginType, ocrConfigs ccipreaderpkg.ActiveAndCandidate, prevDeployment ccipDeployment) bool { - return ocrConfigs.ActiveConfig.ConfigDigest != [32]byte{} && !prevDeployment.HasCandidateInstance(pluginType) - -} diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index e6aa8a943d1..4e6040682fa 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -2,7 +2,6 @@ package launcher import ( "context" - "errors" "fmt" "sync" "time" @@ -50,9 +49,9 @@ func New( IDsToNodes: make(map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo), IDsToCapabilities: make(map[string]registrysyncer.Capability), }, - dons: make(map[registrysyncer.DonID]*ccipDeployment), tickInterval: tickInterval, oracleCreator: oracleCreator, + instances: make(map[registrysyncer.DonID]*ccipPlugins), } } @@ -78,10 +77,10 @@ type launcher struct { wg sync.WaitGroup tickInterval time.Duration - // dons is a map of CCIP DON IDs to the OCR instances that are running on them. - // we can have up to two OCR instances per CCIP plugin, since we are running two plugins, - // thats four OCR instances per CCIP DON maximum. - dons map[registrysyncer.DonID]*ccipDeployment + // instances is a map of CCIP DON IDs to a map of the OCR instances that are running on them. + // This map uses the config digest as the key, and the instance as the value. + // We can have up to a maximum of 4 instances per CCIP DON (active/candidate) x (commit/exec) + instances map[registrysyncer.DonID]*ccipPlugins } // Launch implements registrysyncer.Launcher. @@ -103,7 +102,7 @@ func (l *launcher) runningDONIDs() []registrysyncer.DonID { l.lock.RLock() defer l.lock.RUnlock() var runningDONs []registrysyncer.DonID - for id := range l.dons { + for id := range l.instances { runningDONs = append(runningDONs, id) } return runningDONs @@ -118,8 +117,8 @@ func (l *launcher) Close() error { // shut down all running oracles. var err error - for _, ceDep := range l.dons { - err = multierr.Append(err, ceDep.Close()) + for _, ceDep := range l.instances { + err = multierr.Append(err, (*ceDep).Close()) } return err @@ -191,194 +190,150 @@ func (l *launcher) processDiff(diff diffResult) error { return err } +// processUpdate will manage when configurations of an existing don are updated +// If new oracles are needed, they are created and started. Old oens wil func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer.DON) error { l.lock.Lock() defer l.lock.Unlock() for donID, don := range updated { - prevDeployment, ok := l.dons[registrysyncer.DonID(don.ID)] + prevPlugins, ok := l.instances[donID] if !ok { return fmt.Errorf("invariant violation: expected to find CCIP DON %d in the map of running deployments", don.ID) } - // we encounter this when a node is removed from the don - if prevDeployment == nil { - return errors.New("this node was closed") - } - futDeployment, err := updateDON( - l.lggr, - l.myP2PID, - l.homeChainReader, - *prevDeployment, - don, - l.oracleCreator, - ) + latestConfigs, err := getConfigsForDon(l.homeChainReader, don) if err != nil { return err } - // When we remove a node from the don, this node does not have a future deployment - if futDeployment != nil { - if err := futDeployment.TransitionDeployment(prevDeployment); err != nil { - // TODO: how to handle a failed active-candidate deployment? - return fmt.Errorf("failed to handle active-candidate deployment for CCIP DON %d: %w", donID, err) + + // If a config digest is not already in our list, we need to create an oracle + // If a config digest is already in our list, we just need to point to the old one + // newP.Transition will make sure we shut down the old oracles, and start the new ones + var newP ccipPlugins + for _, c := range latestConfigs { + digest := c.ConfigDigest + if digest != [32]byte{} && (*prevPlugins)[digest] == nil { + oracle, err := l.oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(c)) + if err != nil { + return fmt.Errorf("failed to create CCIP oracle: %w for digest %w", err, digest) + } + + newP[digest] = &oracle + } else { + newP[digest] = (*prevPlugins)[digest] } + } - // update state. - l.dons[donID] = futDeployment - // update the state with the latest config. - // this way if one of the starts errors, we don't retry all of them. - l.regState.IDsToDONs[donID] = updated[donID] + err = newP.Transition(prevPlugins) + if err != nil { + return fmt.Errorf("Could not transition state %w", err) } + + l.instances[donID] = &newP } return nil } +// processAdded is for when a new don is created. We know that all oracles +// must be created and started func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DON) error { l.lock.Lock() defer l.lock.Unlock() for donID, don := range added { - dep, err := createDON( + configs, err := getConfigsForDon(l.homeChainReader, don) + newPlugins, err := createDON( l.lggr, l.myP2PID, - l.homeChainReader, don, l.oracleCreator, + configs, ) if err != nil { return fmt.Errorf("processAdded: call createDON %d: %w", donID, err) } - if dep == nil { + if newPlugins == nil { // not a member of this DON. continue } - // expect that the new process is a candidate instance. - if err := dep.StartCandidate(); err != nil { - if shutdownErr := dep.CloseCandidate(); shutdownErr != nil { - l.lggr.Errorw("Failed to shutdown candidate instance after failed start", "donId", donID, "err", shutdownErr) + // now that oracles are created, we need to start them. If there are issues with starting + // we should shut them down + if err := newPlugins.Transition(&ccipPlugins{}); err != nil { + if shutdownErr := newPlugins.Close(); shutdownErr != nil { + l.lggr.Errorw("Failed to shutdown don instances after a failed start", "donId", donID, "err", shutdownErr) } return fmt.Errorf("processAdded: start oracles for CCIP DON %d: %w", donID, err) } // update state. - l.dons[donID] = dep - // update the state with the latest config. - // this way if one of the starts errors, we don't retry all of them. - l.regState.IDsToDONs[donID] = added[donID] + l.instances[donID] = newPlugins } return nil } +// processRemoved handles the situation when an entire DON is removed func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysyncer.DON) error { l.lock.Lock() defer l.lock.Unlock() for id := range removed { - ceDep, ok := l.dons[id] + p, ok := l.instances[id] if !ok { // not running this particular DON. continue } - if err := ceDep.Close(); err != nil { + if err := p.Close(); err != nil { return fmt.Errorf("failed to shutdown oracles for CCIP DON %d: %w", id, err) + } // after a successful shutdown we can safely remove the DON deployment from the map. - delete(l.dons, id) - delete(l.regState.IDsToDONs, id) + delete(l.instances, id) } return nil } -// updateDON is a pure function that handles the case where a DON in the capability registry -// has received a new configuration. -// It returns a new ccipDeployment that can then be used to perform the active-candidate deployment, -// based on the previous deployment. -func updateDON( +// createDON is a pure function that handles the case where a new DON is added to the capability registry. +// It returns a new ccipDeployment that can then be used to start the active instance. +func createDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, - homeChainReader ccipreader.HomeChain, - prevDeployment ccipDeployment, don registrysyncer.DON, oracleCreator cctypes.OracleCreator, -) (futDeployment *ccipDeployment, err error) { - if !isMemberOfDON(don, p2pID) { - lggr.Infow("Not a member of this DON, skipping", "donId", don.ID, "p2pId", p2pID.String()) + configs []ccipreader.OCR3ConfigWithMeta, +) (*ccipPlugins, error) { + if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { + lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.ID, "p2pId", p2pID.String()) return nil, nil } - - // this should be a retryable error. - commitOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.ID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return nil, fmt.Errorf("failed to fetch OCR configs for CCIP commit plugin (don id: %d) from home chain config contract: %w", - don.ID, err) - } - - execOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.ID, uint8(cctypes.PluginTypeCCIPExec)) - if err != nil { - return nil, fmt.Errorf("failed to fetch OCR configs for CCIP exec plugin (don id: %d) from home chain config contract: %w", - don.ID, err) - } - - commitAcd, err := createFutureActiveCandidateDeployment(don.ID, prevDeployment, commitOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPCommit) - if err != nil { - return nil, fmt.Errorf("failed to create future active-candidate deployment for CCIP commit plugin: %w, don id: %d", err, don.ID) - } - - execAcd, err := createFutureActiveCandidateDeployment(don.ID, prevDeployment, execOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPExec) - if err != nil { - return nil, fmt.Errorf("failed to create future active-candidate deployment for CCIP exec plugin: %w, don id: %d", err, don.ID) - } - - return &ccipDeployment{ - commit: commitAcd, - exec: execAcd, - }, nil -} - -// TODO: this is not technically correct, CCIPHome has other transitions -// that are not covered here, e.g revokeCandidate. -func createFutureActiveCandidateDeployment( - donID uint32, - prevDeployment ccipDeployment, - ocrConfigs ccipreader.ActiveAndCandidate, - oracleCreator cctypes.OracleCreator, - pluginType cctypes.PluginType, -) (activeCandidateDeployment, error) { - var deployment activeCandidateDeployment - if isNewCandidateInstance(pluginType, ocrConfigs, prevDeployment) { - // this is a new candidate instance. - candidateOracle, err := oracleCreator.Create(donID, cctypes.OCR3ConfigWithMeta(ocrConfigs[1])) + var p ccipPlugins + for _, config := range configs { + digest, err := ocrtypes.BytesToConfigDigest(config.ConfigDigest[:]) if err != nil { - return activeCandidateDeployment{}, fmt.Errorf("failed to create CCIP commit oracle: %w", err) + return nil, fmt.Errorf("digest does not match type %w", err) } + if digest != [32]byte{} { + oracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(config)) + if err != nil { + return nil, fmt.Errorf("failed to create CCIP oracle: %w for digest %w", err, digest) + } - deployment.active = prevDeployment.commit.active - deployment.candidate = candidateOracle - } else if isPromotion(pluginType, ocrConfigs, prevDeployment) { - // this is a promotion of candidate->active. - deployment.active = prevDeployment.commit.candidate - } else { - return activeCandidateDeployment{}, fmt.Errorf("invariant violation: expected 1 or 2 OCR configs for CCIP plugin (type: %d), got %d", pluginType, len(ocrConfigs)) + p[digest] = &oracle + } } - - return deployment, nil + return &p, nil } -// createDON is a pure function that handles the case where a new DON is added to the capability registry. -// It returns a new ccipDeployment that can then be used to start the active instance. -func createDON( - lggr logger.Logger, - p2pID ragep2ptypes.PeerID, +func getConfigsForDon( homeChainReader ccipreader.HomeChain, - don registrysyncer.DON, - oracleCreator cctypes.OracleCreator, -) (*ccipDeployment, error) { + don registrysyncer.DON) ([]ccipreader.OCR3ConfigWithMeta, error) { + // this should be a retryable error. commitOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.ID, uint8(cctypes.PluginTypeCCIPCommit)) if err != nil { @@ -392,51 +347,11 @@ func createDON( don.ID, err) } - // TODO: is this true? What if an MCM operation sets to candidate and upgrades immediately within a "tick"? - // upon creation we should only have one OCR config per plugin type. - if commitOCRConfigs.ActiveConfig.ConfigDigest != [32]byte{} { - return nil, fmt.Errorf("expected the newest config to be a candidate, not active (don id: %d), got %+v", don.ID, commitOCRConfigs) - } - - if execOCRConfigs.ActiveConfig.ConfigDigest != [32]byte{} { - return nil, fmt.Errorf("expected exactly one OCR config for CCIP exec plugin (don id: %d), got %+v", don.ID, execOCRConfigs) - } - - if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { - lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.ID, "p2pId", p2pID.String()) - return nil, nil - } - - // at this point we know we are either a member of the DON or a bootstrap node. - // the injected oracleCreator will create the appropriate oracle. - commitOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(commitOCRConfigs.CandidateConfig)) - if err != nil { - return nil, fmt.Errorf("failed to create CCIP commit oracle: %w", err) - } - - execOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(execOCRConfigs.CandidateConfig)) - if err != nil { - return nil, fmt.Errorf("failed to create CCIP exec oracle: %w", err) - } - - commitDigest, err := ocrtypes.BytesToConfigDigest(commitOCRConfigs.CandidateConfig.ConfigDigest[:]) - if err != nil { - return nil, fmt.Errorf("Candidate commit digest does not match type %w", err) - } - - execDigest, err := ocrtypes.BytesToConfigDigest(execOCRConfigs.CandidateConfig.ConfigDigest[:]) - if err != nil { - return nil, fmt.Errorf("exec commit digest does not match type %w", err) - } - - return &ccipDeployment{ - commit: activeCandidateDeployment{ - candidate: commitOracle, - candidateDigest: commitDigest, - }, - exec: activeCandidateDeployment{ - candidate: execOracle, - candidateDigest: execDigest, - }, + return []ccipreader.OCR3ConfigWithMeta{ + commitOCRConfigs.CandidateConfig, + commitOCRConfigs.ActiveConfig, + execOCRConfigs.CandidateConfig, + execOCRConfigs.ActiveConfig, }, nil + } From ef006e00f948e0a257a6c44e820cde384eb61aee Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 1 Nov 2024 21:05:27 +1100 Subject: [PATCH 03/16] address comments, remove weird pointers from everywhere --- core/capabilities/ccip/launcher/deployment.go | 39 ++++++++++--------- core/capabilities/ccip/launcher/launcher.go | 28 ++++++------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index cd1b03a2bbd..d6e1a7f9804 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -8,37 +8,38 @@ import ( "go.uber.org/multierr" ) -type ccipPlugins map[ocrtypes.ConfigDigest]*cctypes.CCIPOracle +type ccipPlugins map[ocrtypes.ConfigDigest]cctypes.CCIPOracle -// Close is used to shut down an entire don immediately -func (c *ccipPlugins) Close() error { - if c == nil { - return nil - } - var err error - - for _, oracle := range *c { - err = multierr.Append(err, (*oracle).Close()) - } +// StartAll will call Oracle.Start on an entire don +func (c ccipPlugins) StartAll() error { + nilPlugins := make(ccipPlugins) + return c.Transition(nilPlugins) +} - return err +// CloseAll is used to shut down an entire don immediately +func (c ccipPlugins) CloseAll() error { + nilPlugins := make(ccipPlugins) + return nilPlugins.Transition(c) } // Transition manages starting and stopping ocr instances // If there are any new config digests, we need to start those instances // If any of the previous config digests are no longer present, we need to shut those down // We don't care about if they're exec/commit or active/candidate, that all happens in the plugin -func (c *ccipPlugins) Transition(prevPlugins *ccipPlugins) error { +func (c ccipPlugins) Transition(prevPlugins ccipPlugins) error { var err error - for _, digest := range maps.Keys(*prevPlugins) { - if *c == nil || (*c)[digest] == nil { - err = multierr.Append(err, (*(*prevPlugins)[digest]).Close()) + + // This shuts down instances that were present previously, but are no longer needed + for _, digest := range maps.Keys(prevPlugins) { + if c[digest] == nil { + err = multierr.Append(err, prevPlugins[digest].Close()) } } - for _, digest := range maps.Keys(*c) { - if *prevPlugins == nil || (*prevPlugins)[digest] == nil { - err = multierr.Append(err, (*(*c)[digest]).Start()) + // This starts instances that were not previously present, but are in the new config + for _, digest := range maps.Keys(c) { + if prevPlugins[digest] == nil { + err = multierr.Append(err, c[digest].Start()) } } return err diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 4e6040682fa..2cb6538ec17 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -51,7 +51,7 @@ func New( }, tickInterval: tickInterval, oracleCreator: oracleCreator, - instances: make(map[registrysyncer.DonID]*ccipPlugins), + instances: make(map[registrysyncer.DonID]ccipPlugins), } } @@ -80,7 +80,7 @@ type launcher struct { // instances is a map of CCIP DON IDs to a map of the OCR instances that are running on them. // This map uses the config digest as the key, and the instance as the value. // We can have up to a maximum of 4 instances per CCIP DON (active/candidate) x (commit/exec) - instances map[registrysyncer.DonID]*ccipPlugins + instances map[registrysyncer.DonID]ccipPlugins } // Launch implements registrysyncer.Launcher. @@ -118,7 +118,7 @@ func (l *launcher) Close() error { // shut down all running oracles. var err error for _, ceDep := range l.instances { - err = multierr.Append(err, (*ceDep).Close()) + err = multierr.Append(err, ceDep.CloseAll()) } return err @@ -210,18 +210,18 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer // If a config digest is not already in our list, we need to create an oracle // If a config digest is already in our list, we just need to point to the old one // newP.Transition will make sure we shut down the old oracles, and start the new ones - var newP ccipPlugins + var newP = make(ccipPlugins) for _, c := range latestConfigs { digest := c.ConfigDigest - if digest != [32]byte{} && (*prevPlugins)[digest] == nil { + if digest != [32]byte{} && prevPlugins[digest] == nil { oracle, err := l.oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(c)) if err != nil { return fmt.Errorf("failed to create CCIP oracle: %w for digest %w", err, digest) } - newP[digest] = &oracle + newP[digest] = oracle } else { - newP[digest] = (*prevPlugins)[digest] + newP[digest] = prevPlugins[digest] } } @@ -230,7 +230,7 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer return fmt.Errorf("Could not transition state %w", err) } - l.instances[donID] = &newP + l.instances[donID] = newP } return nil @@ -261,8 +261,8 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DO // now that oracles are created, we need to start them. If there are issues with starting // we should shut them down - if err := newPlugins.Transition(&ccipPlugins{}); err != nil { - if shutdownErr := newPlugins.Close(); shutdownErr != nil { + if err := newPlugins.StartAll(); err != nil { + if shutdownErr := newPlugins.CloseAll(); shutdownErr != nil { l.lggr.Errorw("Failed to shutdown don instances after a failed start", "donId", donID, "err", shutdownErr) } return fmt.Errorf("processAdded: start oracles for CCIP DON %d: %w", donID, err) @@ -287,7 +287,7 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce continue } - if err := p.Close(); err != nil { + if err := p.CloseAll(); err != nil { return fmt.Errorf("failed to shutdown oracles for CCIP DON %d: %w", id, err) } @@ -307,7 +307,7 @@ func createDON( don registrysyncer.DON, oracleCreator cctypes.OracleCreator, configs []ccipreader.OCR3ConfigWithMeta, -) (*ccipPlugins, error) { +) (ccipPlugins, error) { if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.ID, "p2pId", p2pID.String()) return nil, nil @@ -324,10 +324,10 @@ func createDON( return nil, fmt.Errorf("failed to create CCIP oracle: %w for digest %w", err, digest) } - p[digest] = &oracle + p[digest] = oracle } } - return &p, nil + return p, nil } func getConfigsForDon( From 25479d953aebbb3e9802d8087db24a0de91132a4 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 1 Nov 2024 21:07:22 +1100 Subject: [PATCH 04/16] properly initialize the ccipplugin maps --- core/capabilities/ccip/launcher/launcher.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 2cb6538ec17..6950397c113 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -210,7 +210,7 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer // If a config digest is not already in our list, we need to create an oracle // If a config digest is already in our list, we just need to point to the old one // newP.Transition will make sure we shut down the old oracles, and start the new ones - var newP = make(ccipPlugins) + newP := make(ccipPlugins) for _, c := range latestConfigs { digest := c.ConfigDigest if digest != [32]byte{} && prevPlugins[digest] == nil { @@ -312,7 +312,7 @@ func createDON( lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.ID, "p2pId", p2pID.String()) return nil, nil } - var p ccipPlugins + p := make(ccipPlugins) for _, config := range configs { digest, err := ocrtypes.BytesToConfigDigest(config.ConfigDigest[:]) if err != nil { From 1ef3e25449ac6110246afc36b5275f1ee8b2fb94 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 1 Nov 2024 21:29:56 +1100 Subject: [PATCH 05/16] comment --- core/capabilities/ccip/launcher/launcher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 6950397c113..ceff22181d0 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -300,7 +300,7 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce } // createDON is a pure function that handles the case where a new DON is added to the capability registry. -// It returns a new ccipDeployment that can then be used to start the active instance. +// It returns up to 4 plugins that are then started. func createDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, From 152233d92e2ada10c5fcc256c8fe922e61826c35 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 1 Nov 2024 23:12:24 +1100 Subject: [PATCH 06/16] some fixes --- core/capabilities/ccip/launcher/deployment.go | 24 ++++++++----- core/capabilities/ccip/launcher/launcher.go | 34 +++++++++++++------ .../ccip/types/mocks/home_chain_reader.go | 10 +++--- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index d6e1a7f9804..09a94a4bff5 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -1,11 +1,13 @@ package launcher import ( + "fmt" "golang.org/x/exp/maps" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "go.uber.org/multierr" + + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" ) type ccipPlugins map[ocrtypes.ConfigDigest]cctypes.CCIPOracle @@ -30,17 +32,23 @@ func (c ccipPlugins) Transition(prevPlugins ccipPlugins) error { var err error // This shuts down instances that were present previously, but are no longer needed - for _, digest := range maps.Keys(prevPlugins) { - if c[digest] == nil { - err = multierr.Append(err, prevPlugins[digest].Close()) + for digest, oracle := range prevPlugins { + if _, ok := c[digest]; !ok { + err = multierr.Append(err, oracle.Close()) } } - // This starts instances that were not previously present, but are in the new config - for _, digest := range maps.Keys(c) { - if prevPlugins[digest] == nil { - err = multierr.Append(err, c[digest].Start()) + // This will start the instances that were not previously present, but are in the new config + for digest, oracle := range c { + if _, ok := prevPlugins[digest]; !ok { + err = multierr.Append(err, oracle.Start()) } } return err } + +func (c ccipPlugins) PrintDigests() { + for _, d := range maps.Keys(c) { + fmt.Println(d.Hex()) + } +} diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index ceff22181d0..218658b034a 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -6,9 +6,10 @@ import ( "sync" "time" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" @@ -213,10 +214,10 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer newP := make(ccipPlugins) for _, c := range latestConfigs { digest := c.ConfigDigest - if digest != [32]byte{} && prevPlugins[digest] == nil { + if prevPlugins[digest] == nil { oracle, err := l.oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(c)) if err != nil { - return fmt.Errorf("failed to create CCIP oracle: %w for digest %w", err, digest) + return fmt.Errorf("failed to create CCIP oracle: %w for digest %v", err, digest) } newP[digest] = oracle @@ -231,6 +232,7 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer } l.instances[donID] = newP + l.regState.IDsToDONs[donID] = updated[donID] } return nil @@ -270,6 +272,7 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DO // update state. l.instances[donID] = newPlugins + l.regState.IDsToDONs[donID] = added[donID] } return nil @@ -294,6 +297,7 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce // after a successful shutdown we can safely remove the DON deployment from the map. delete(l.instances, id) + delete(l.regState.IDsToDONs, id) } return nil @@ -318,14 +322,14 @@ func createDON( if err != nil { return nil, fmt.Errorf("digest does not match type %w", err) } - if digest != [32]byte{} { - oracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(config)) - if err != nil { - return nil, fmt.Errorf("failed to create CCIP oracle: %w for digest %w", err, digest) - } - p[digest] = oracle + oracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(config)) + if err != nil { + return nil, fmt.Errorf("failed to create CCIP oracle: %w for digest %v", err, digest) } + + p[digest] = oracle + } return p, nil } @@ -347,11 +351,19 @@ func getConfigsForDon( don.ID, err) } - return []ccipreader.OCR3ConfigWithMeta{ + c := []ccipreader.OCR3ConfigWithMeta{ commitOCRConfigs.CandidateConfig, commitOCRConfigs.ActiveConfig, execOCRConfigs.CandidateConfig, execOCRConfigs.ActiveConfig, - }, nil + } + + ret := make([]ccipreader.OCR3ConfigWithMeta, 0, 4) + for _, config := range c { + if config.ConfigDigest != [32]byte{} { + ret = append(ret, config) + } + } + return ret, nil } diff --git a/core/capabilities/ccip/types/mocks/home_chain_reader.go b/core/capabilities/ccip/types/mocks/home_chain_reader.go index 7aa857d46cb..95fc20d226e 100644 --- a/core/capabilities/ccip/types/mocks/home_chain_reader.go +++ b/core/capabilities/ccip/types/mocks/home_chain_reader.go @@ -65,23 +65,23 @@ func (_m *HomeChainReader) Name() string { } // GetOCRConfigs provides a mock function with given fields: ctx, donID, pluginType -func (_m *HomeChainReader) GetOCRConfigs(ctx context.Context, donID uint32, pluginType uint8) ([]ccipreaderpkg.OCR3ConfigWithMeta, error) { +func (_m *HomeChainReader) GetOCRConfigs(ctx context.Context, donID uint32, pluginType uint8) (ccipreaderpkg.ActiveAndCandidate, error) { ret := _m.Called(ctx, donID, pluginType) if len(ret) == 0 { panic("no return value specified for GetOCRConfigs") } - var r0 []ccipreaderpkg.OCR3ConfigWithMeta + var r0 ccipreaderpkg.ActiveAndCandidate var r1 error - if rf, ok := ret.Get(0).(func(ctx context.Context, donID uint32, pluginType uint8) ([]ccipreaderpkg.OCR3ConfigWithMeta, error)); ok { + if rf, ok := ret.Get(0).(func(ctx context.Context, donID uint32, pluginType uint8) (ccipreaderpkg.ActiveAndCandidate, error)); ok { return rf(ctx, donID, pluginType) } - if rf, ok := ret.Get(0).(func(ctx context.Context, donID uint32, pluginType uint8) []ccipreaderpkg.OCR3ConfigWithMeta); ok { + if rf, ok := ret.Get(0).(func(ctx context.Context, donID uint32, pluginType uint8) ccipreaderpkg.ActiveAndCandidate); ok { r0 = rf(ctx, donID, pluginType) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]ccipreaderpkg.OCR3ConfigWithMeta) + r0 = ret.Get(0).(ccipreaderpkg.ActiveAndCandidate) } } From be75bfa9d2c74fb9e6ac31be5b250156bb2e0a35 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Sat, 2 Nov 2024 00:29:49 +1100 Subject: [PATCH 07/16] fixed deployment tests --- core/capabilities/ccip/launcher/deployment.go | 3 + .../ccip/launcher/deployment_test.go | 1475 ++++++++++------- 2 files changed, 886 insertions(+), 592 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index 09a94a4bff5..82a8772d064 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -31,6 +31,9 @@ func (c ccipPlugins) CloseAll() error { func (c ccipPlugins) Transition(prevPlugins ccipPlugins) error { var err error + if len(c) > 4 || len(prevPlugins) > 4 { + return fmt.Errorf("have more than 4 instances somehow") + } // This shuts down instances that were present previously, but are no longer needed for digest, oracle := range prevPlugins { if _, ok := c[digest]; !ok { diff --git a/core/capabilities/ccip/launcher/deployment_test.go b/core/capabilities/ccip/launcher/deployment_test.go index a7fa8888314..c0a2f835b1b 100644 --- a/core/capabilities/ccip/launcher/deployment_test.go +++ b/core/capabilities/ccip/launcher/deployment_test.go @@ -1,479 +1,298 @@ package launcher import ( - "errors" + "fmt" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "testing" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" mocktypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" - "github.com/stretchr/testify/require" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" ) -func Test_ccipDeployment_Close(t *testing.T) { +func Test_ccipDeployment_Transitions(t *testing.T) { + // we use a pointer to the oracle here for mock assertions type args struct { - commitBlue *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle + prevDeployment map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle + currDeployment map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle + } + assertions := func(t *testing.T, args args) { + for i, _ := range args.prevDeployment { + args.prevDeployment[i].AssertExpectations(t) + } + for i, _ := range args.currDeployment { + args.currDeployment[i].AssertExpectations(t) + } } tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool + name string + makeArgs func(t *testing.T) args + expect func(t *testing.T, args args) + wantErr bool }{ { - name: "no errors, active only", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, + name: "all plugins are new", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 4 { + prevP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 4 { + currP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + return args{prevDeployment: prevP, currDeployment: currP} }, expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) + for _, plugin := range args.prevDeployment { + plugin.On("Close").Return(nil).Once() + } + for _, plugin := range args.currDeployment { + plugin.On("Start").Return(nil).Once() + } }, wantErr: false, }, { - name: "no errors, active and candidate", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), + name: "no configs -> candidates", + makeArgs: func(t *testing.T) args { + prev := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + + curr := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 2 { + curr[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + return args{prevDeployment: prev, currDeployment: curr} }, expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitGreen.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execGreen.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitGreen.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execGreen.AssertExpectations(t) + // When we are creating candidates, they should be started + for _, plugin := range args.currDeployment { + plugin.On("Start").Return(nil).Once() + } }, wantErr: false, }, { - name: "error on commit active", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: activeCandidateDeployment{ - active: tt.args.commitBlue, - }, - exec: activeCandidateDeployment{ - active: tt.args.execBlue, - }, - } - if tt.args.commitGreen != nil { - c.commit.candidate = tt.args.commitGreen - } + name: "candidates -> active", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 2 { + prevP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } - if tt.args.execGreen != nil { - c.exec.candidate = tt.args.execGreen - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.Close() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_ccipDeployment_StartBlue(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for digest, oracle := range prevP { + currP[digest] = oracle + } + return args{prevDeployment: prevP, currDeployment: currP} }, expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) + // if candidates are being promoted, there should be nothing to start or stop + for _, plugin := range args.currDeployment { + plugin.AssertNotCalled(t, "Start") + plugin.AssertNotCalled(t, "Close") + } }, wantErr: false, }, { - name: "error on commit active", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), + name: "active -> active+candidates", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 2 { + prevP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for digest, oracle := range prevP { + currP[digest] = oracle + } + for range 2 { + currP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + return args{prevDeployment: prevP, currDeployment: currP} }, expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(errors.New("failed")).Once() - args.execBlue.On("Start").Return(nil).Once() + for digest, plugin := range args.currDeployment { + // if it previously existed, there should be noop + // if it's a new instance, it should be started + if _, ok := args.prevDeployment[digest]; ok { + plugin.AssertNotCalled(t, "Start") + plugin.AssertNotCalled(t, "Close") + } else { + plugin.On("Start").Return(nil).Once() + } + } }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, + wantErr: false, }, { - name: "error on exec active", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), + name: "active+candidate -> active", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 4 { + prevP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + // copy two digests over + i := 2 + for digest, oracle := range prevP { + if i == 0 { + continue + } + currP[digest] = oracle + i-- + } + return args{prevDeployment: prevP, currDeployment: currP} }, expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) + for digest, plugin := range args.prevDeployment { + + if _, ok := args.currDeployment[digest]; !ok { + // if the instance is no longer present, it should have been deleted + plugin.On("Close").Return(nil).Once() + } else { + // otherwise, it should have been left alone + plugin.AssertNotCalled(t, "Close") + plugin.AssertNotCalled(t, "Start") + } + } }, - wantErr: true, + wantErr: false, }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: activeCandidateDeployment{ - active: tt.args.commitBlue, - }, - exec: activeCandidateDeployment{ - active: tt.args.execBlue, - }, - } + { + name: "candidate -> different candidate", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 2 { + prevP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.StartActive() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 2 { + currP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } -func Test_ccipDeployment_CloseBlue(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), + return args{prevDeployment: prevP, currDeployment: currP} }, expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) + for _, plugin := range args.prevDeployment { + plugin.On("Close").Return(nil).Once() + } + for _, plugin := range args.currDeployment { + plugin.On("Start").Return(nil).Once() + } }, wantErr: false, }, { - name: "error on commit active", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), + name: "close all instances", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 4 { + prevP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + + return args{prevDeployment: prevP, currDeployment: currP} }, expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) + for _, plugin := range args.prevDeployment { + plugin.On("Close").Return(nil).Once() + } }, - wantErr: true, + wantErr: false, }, { - name: "error on exec active", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: activeCandidateDeployment{ - active: tt.args.commitBlue, - }, - exec: activeCandidateDeployment{ - active: tt.args.execBlue, - }, - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.CloseActive() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} + name: "start all instances", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) -func Test_ccipDeployment_HandleBlueGreen_PrevDeploymentNil(t *testing.T) { - require.Error(t, (&ccipDeployment{}).TransitionDeployment(nil)) -} + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 4 { + currP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } -func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle - } - tests := []struct { - name string - argsPrevDeployment args - argsFutureDeployment args - expect func(t *testing.T, args args, argsPrevDeployment args) - asserts func(t *testing.T, args args, argsPrevDeployment args) - wantErr bool - }{ - { - name: "promotion active to candidate", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, + return args{prevDeployment: prevP, currDeployment: currP} }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() - argsPrevDeployment.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.AssertExpectations(t) - argsPrevDeployment.execBlue.AssertExpectations(t) + expect: func(t *testing.T, args args) { + for _, plugin := range args.currDeployment { + plugin.On("Start").Return(nil).Once() + } }, wantErr: false, }, { - name: "new candidate deployment", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), + name: "should handle nil to nil", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + return args{prevDeployment: prevP, currDeployment: currP} }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) + expect: func(t *testing.T, args args) { + for _, plugin := range args.currDeployment { + plugin.On("Start").Return(nil).Once() + } }, wantErr: false, }, { - name: "error on commit candidate start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(errors.New("failed")).Once() - args.execGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec candidate start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, + name: "should throw error if there are more than 5 instances", + makeArgs: func(t *testing.T) args { + prevP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + currP := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 5 { + currP[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + return args{prevDeployment: prevP, currDeployment: currP} + }, + expect: func(t *testing.T, args args) {}, wantErr: true, }, { - name: "invalid active-candidate deployment transition commit: both prev and future deployment have candidate", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) {}, - asserts: func(t *testing.T, args args, argsPrevDeployment args) {}, - wantErr: true, - }, - { - name: "invalid active-candidate deployment transition exec: both prev and future exec deployment have candidate", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() + name: "candidate -> init", + makeArgs: func(t *testing.T) args { + prev := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + for range 2 { + prev[utils.RandomBytes32()] = mocktypes.NewCCIPOracle(t) + } + curr := make(map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle) + + return args{prevDeployment: prev, currDeployment: curr} }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) + expect: func(t *testing.T, args args) { + // When we are creating candidates, they should be started + for _, plugin := range args.prevDeployment { + plugin.On("Close").Return(nil).Once() + } }, - wantErr: true, + wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - futDeployment := &ccipDeployment{ - commit: activeCandidateDeployment{ - active: tt.argsFutureDeployment.commitBlue, - }, - exec: activeCandidateDeployment{ - active: tt.argsFutureDeployment.execBlue, - }, - } - if tt.argsFutureDeployment.commitGreen != nil { - futDeployment.commit.candidate = tt.argsFutureDeployment.commitGreen + args := tt.makeArgs(t) + prev := make(ccipPlugins) + for digest, oracle := range args.prevDeployment { + prev[digest] = oracle } - if tt.argsFutureDeployment.execGreen != nil { - futDeployment.exec.candidate = tt.argsFutureDeployment.execGreen + curr := make(ccipPlugins) + for digest, oracle := range args.currDeployment { + curr[digest] = oracle } - prevDeployment := &ccipDeployment{ - commit: activeCandidateDeployment{ - active: tt.argsPrevDeployment.commitBlue, - }, - exec: activeCandidateDeployment{ - active: tt.argsPrevDeployment.execBlue, - }, - } - if tt.argsPrevDeployment.commitGreen != nil { - prevDeployment.commit.candidate = tt.argsPrevDeployment.commitGreen - } - if tt.argsPrevDeployment.execGreen != nil { - prevDeployment.exec.candidate = tt.argsPrevDeployment.execGreen - } + fmt.Println("prev...") + prev.PrintDigests() + fmt.Println("curr...") + curr.PrintDigests() - tt.expect(t, tt.argsFutureDeployment, tt.argsPrevDeployment) - defer tt.asserts(t, tt.argsFutureDeployment, tt.argsPrevDeployment) - err := futDeployment.TransitionDeployment(prevDeployment) + tt.expect(t, args) + defer assertions(t, args) + err := curr.Transition(prev) if tt.wantErr { require.Error(t, err) } else { @@ -483,199 +302,671 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { } } -func Test_isNewGreenInstance(t *testing.T) { - type args struct { - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - prevDeployment ccipDeployment - } - tests := []struct { - name string - args args - want bool - }{ - { - "prev deployment only active", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, {}, - }, - prevDeployment: ccipDeployment{ - commit: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - }, - }, - }, - true, - }, - { - "candidate -> active promotion", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, - }, - prevDeployment: ccipDeployment{ - commit: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - candidate: mocktypes.NewCCIPOracle(t), - }, - }, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := isNewCandidateInstance(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment) - require.Equal(t, tt.want, got) - }) - } -} - -func Test_isPromotion(t *testing.T) { - type args struct { - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - prevDeployment ccipDeployment - } - tests := []struct { - name string - args args - want bool - }{ - { - "prev deployment only active", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, {}, - }, - prevDeployment: ccipDeployment{ - commit: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - }, - }, - }, - false, - }, - { - "candidate -> active promotion", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, - }, - prevDeployment: ccipDeployment{ - commit: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - candidate: mocktypes.NewCCIPOracle(t), - }, - }, - }, - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := isPromotion(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment); got != tt.want { - t.Errorf("isPromotion() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_ccipDeployment_HasGreenInstance(t *testing.T) { - type fields struct { - commit activeCandidateDeployment - exec activeCandidateDeployment - } - type args struct { - pluginType cctypes.PluginType - } - tests := []struct { - name string - fields fields - args args - want bool - }{ - { - "commit candidate present", - fields{ - commit: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - candidate: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - }, - true, - }, - { - "commit candidate not present", - fields{ - commit: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - }, - false, - }, - { - "exec candidate present", - fields{ - exec: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - candidate: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPExec, - }, - true, - }, - { - "exec candidate not present", - fields{ - exec: activeCandidateDeployment{ - active: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPExec, - }, - false, - }, - { - "invalid plugin type", - fields{}, - args{ - pluginType: cctypes.PluginType(100), - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{} - if tt.fields.commit.active != nil { - c.commit.active = tt.fields.commit.active - } - if tt.fields.commit.candidate != nil { - c.commit.candidate = tt.fields.commit.candidate - } - if tt.fields.exec.active != nil { - c.exec.active = tt.fields.exec.active - } - if tt.fields.exec.candidate != nil { - c.exec.candidate = tt.fields.exec.candidate - } - got := c.HasCandidateInstance(tt.args.pluginType) - require.Equal(t, tt.want, got) - }) - } -} +// +//func Test_ccipDeployment_Close(t *testing.T) { +// type args struct { +// commitBlue *mocktypes.CCIPOracle +// commitGreen *mocktypes.CCIPOracle +// execBlue *mocktypes.CCIPOracle +// execGreen *mocktypes.CCIPOracle +// } +// tests := []struct { +// name string +// args args +// expect func(t *testing.T, args args) +// asserts func(t *testing.T, args args) +// wantErr bool +// }{ +// { +// name: "no errors, active only", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: nil, +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: nil, +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Close").Return(nil).Once() +// args.execBlue.On("Close").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: false, +// }, +// { +// name: "no errors, active and candidate", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Close").Return(nil).Once() +// args.commitGreen.On("Close").Return(nil).Once() +// args.execBlue.On("Close").Return(nil).Once() +// args.execGreen.On("Close").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.commitGreen.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// args.execGreen.AssertExpectations(t) +// }, +// wantErr: false, +// }, +// { +// name: "error on commit active", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: nil, +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: nil, +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Close").Return(errors.New("failed")).Once() +// args.execBlue.On("Close").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// c := &ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: tt.args.commitBlue, +// }, +// exec: activeCandidateDeployment{ +// active: tt.args.execBlue, +// }, +// } +// if tt.args.commitGreen != nil { +// c.commit.candidate = tt.args.commitGreen +// } +// +// if tt.args.execGreen != nil { +// c.exec.candidate = tt.args.execGreen +// } +// +// tt.expect(t, tt.args) +// defer tt.asserts(t, tt.args) +// err := c.Close() +// if tt.wantErr { +// require.Error(t, err) +// } else { +// require.NoError(t, err) +// } +// }) +// } +//} +// +//func Test_ccipDeployment_StartBlue(t *testing.T) { +// type args struct { +// commitBlue *mocktypes.CCIPOracle +// execBlue *mocktypes.CCIPOracle +// } +// tests := []struct { +// name string +// args args +// expect func(t *testing.T, args args) +// asserts func(t *testing.T, args args) +// wantErr bool +// }{ +// { +// name: "no errors", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Start").Return(nil).Once() +// args.execBlue.On("Start").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: false, +// }, +// { +// name: "error on commit active", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Start").Return(errors.New("failed")).Once() +// args.execBlue.On("Start").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// { +// name: "error on exec active", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Start").Return(nil).Once() +// args.execBlue.On("Start").Return(errors.New("failed")).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// c := &ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: tt.args.commitBlue, +// }, +// exec: activeCandidateDeployment{ +// active: tt.args.execBlue, +// }, +// } +// +// tt.expect(t, tt.args) +// defer tt.asserts(t, tt.args) +// err := c.StartActive() +// if tt.wantErr { +// require.Error(t, err) +// } else { +// require.NoError(t, err) +// } +// }) +// } +//} +// +//func Test_ccipDeployment_CloseBlue(t *testing.T) { +// type args struct { +// commitBlue *mocktypes.CCIPOracle +// execBlue *mocktypes.CCIPOracle +// } +// tests := []struct { +// name string +// args args +// expect func(t *testing.T, args args) +// asserts func(t *testing.T, args args) +// wantErr bool +// }{ +// { +// name: "no errors", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Close").Return(nil).Once() +// args.execBlue.On("Close").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: false, +// }, +// { +// name: "error on commit active", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Close").Return(errors.New("failed")).Once() +// args.execBlue.On("Close").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// { +// name: "error on exec active", +// args: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args) { +// args.commitBlue.On("Close").Return(nil).Once() +// args.execBlue.On("Close").Return(errors.New("failed")).Once() +// }, +// asserts: func(t *testing.T, args args) { +// args.commitBlue.AssertExpectations(t) +// args.execBlue.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// c := &ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: tt.args.commitBlue, +// }, +// exec: activeCandidateDeployment{ +// active: tt.args.execBlue, +// }, +// } +// +// tt.expect(t, tt.args) +// defer tt.asserts(t, tt.args) +// err := c.CloseActive() +// if tt.wantErr { +// require.Error(t, err) +// } else { +// require.NoError(t, err) +// } +// }) +// } +//} +// +//func Test_ccipDeployment_HandleBlueGreen_PrevDeploymentNil(t *testing.T) { +// require.Error(t, (&ccipDeployment{}).TransitionDeployment(nil)) +//} +// +//func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { +// type args struct { +// commitBlue *mocktypes.CCIPOracle +// commitGreen *mocktypes.CCIPOracle +// execBlue *mocktypes.CCIPOracle +// execGreen *mocktypes.CCIPOracle +// } +// tests := []struct { +// name string +// argsPrevDeployment args +// argsFutureDeployment args +// expect func(t *testing.T, args args, argsPrevDeployment args) +// asserts func(t *testing.T, args args, argsPrevDeployment args) +// wantErr bool +// }{ +// { +// name: "promotion active to candidate", +// argsPrevDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// argsFutureDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: nil, +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: nil, +// }, +// expect: func(t *testing.T, args args, argsPrevDeployment args) { +// argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() +// argsPrevDeployment.execBlue.On("Close").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args, argsPrevDeployment args) { +// argsPrevDeployment.commitBlue.AssertExpectations(t) +// argsPrevDeployment.execBlue.AssertExpectations(t) +// }, +// wantErr: false, +// }, +// { +// name: "new candidate deployment", +// argsPrevDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: nil, +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: nil, +// }, +// argsFutureDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.On("Start").Return(nil).Once() +// args.execGreen.On("Start").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.AssertExpectations(t) +// args.execGreen.AssertExpectations(t) +// }, +// wantErr: false, +// }, +// { +// name: "error on commit candidate start", +// argsPrevDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: nil, +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: nil, +// }, +// argsFutureDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.On("Start").Return(errors.New("failed")).Once() +// args.execGreen.On("Start").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.AssertExpectations(t) +// args.execGreen.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// { +// name: "error on exec candidate start", +// argsPrevDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: nil, +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: nil, +// }, +// argsFutureDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.On("Start").Return(nil).Once() +// args.execGreen.On("Start").Return(errors.New("failed")).Once() +// }, +// asserts: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.AssertExpectations(t) +// args.execGreen.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// { +// name: "invalid active-candidate deployment transition commit: both prev and future deployment have candidate", +// argsPrevDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// argsFutureDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args, argsPrevDeployment args) {}, +// asserts: func(t *testing.T, args args, argsPrevDeployment args) {}, +// wantErr: true, +// }, +// { +// name: "invalid active-candidate deployment transition exec: both prev and future exec deployment have candidate", +// argsPrevDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: nil, +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// argsFutureDeployment: args{ +// commitBlue: mocktypes.NewCCIPOracle(t), +// commitGreen: mocktypes.NewCCIPOracle(t), +// execBlue: mocktypes.NewCCIPOracle(t), +// execGreen: mocktypes.NewCCIPOracle(t), +// }, +// expect: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.On("Start").Return(nil).Once() +// }, +// asserts: func(t *testing.T, args args, argsPrevDeployment args) { +// args.commitGreen.AssertExpectations(t) +// }, +// wantErr: true, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// futDeployment := &ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: tt.argsFutureDeployment.commitBlue, +// }, +// exec: activeCandidateDeployment{ +// active: tt.argsFutureDeployment.execBlue, +// }, +// } +// if tt.argsFutureDeployment.commitGreen != nil { +// futDeployment.commit.candidate = tt.argsFutureDeployment.commitGreen +// } +// if tt.argsFutureDeployment.execGreen != nil { +// futDeployment.exec.candidate = tt.argsFutureDeployment.execGreen +// } +// +// prevDeployment := &ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: tt.argsPrevDeployment.commitBlue, +// }, +// exec: activeCandidateDeployment{ +// active: tt.argsPrevDeployment.execBlue, +// }, +// } +// if tt.argsPrevDeployment.commitGreen != nil { +// prevDeployment.commit.candidate = tt.argsPrevDeployment.commitGreen +// } +// if tt.argsPrevDeployment.execGreen != nil { +// prevDeployment.exec.candidate = tt.argsPrevDeployment.execGreen +// } +// +// tt.expect(t, tt.argsFutureDeployment, tt.argsPrevDeployment) +// defer tt.asserts(t, tt.argsFutureDeployment, tt.argsPrevDeployment) +// err := futDeployment.TransitionDeployment(prevDeployment) +// if tt.wantErr { +// require.Error(t, err) +// } else { +// require.NoError(t, err) +// } +// }) +// } +//} +// +//func Test_isNewGreenInstance(t *testing.T) { +// type args struct { +// pluginType cctypes.PluginType +// ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta +// prevDeployment ccipDeployment +// } +// tests := []struct { +// name string +// args args +// want bool +// }{ +// { +// "prev deployment only active", +// args{ +// pluginType: cctypes.PluginTypeCCIPCommit, +// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ +// {}, {}, +// }, +// prevDeployment: ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// }, +// }, +// }, +// true, +// }, +// { +// "candidate -> active promotion", +// args{ +// pluginType: cctypes.PluginTypeCCIPCommit, +// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ +// {}, +// }, +// prevDeployment: ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// candidate: mocktypes.NewCCIPOracle(t), +// }, +// }, +// }, +// false, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// got := isNewCandidateInstance(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment) +// require.Equal(t, tt.want, got) +// }) +// } +//} +// +//func Test_isPromotion(t *testing.T) { +// type args struct { +// pluginType cctypes.PluginType +// ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta +// prevDeployment ccipDeployment +// } +// tests := []struct { +// name string +// args args +// want bool +// }{ +// { +// "prev deployment only active", +// args{ +// pluginType: cctypes.PluginTypeCCIPCommit, +// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ +// {}, {}, +// }, +// prevDeployment: ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// }, +// }, +// }, +// false, +// }, +// { +// "candidate -> active promotion", +// args{ +// pluginType: cctypes.PluginTypeCCIPCommit, +// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ +// {}, +// }, +// prevDeployment: ccipDeployment{ +// commit: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// candidate: mocktypes.NewCCIPOracle(t), +// }, +// }, +// }, +// true, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// if got := isPromotion(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment); got != tt.want { +// t.Errorf("isPromotion() = %v, want %v", got, tt.want) +// } +// }) +// } +//} +// +//func Test_ccipDeployment_HasGreenInstance(t *testing.T) { +// type fields struct { +// commit activeCandidateDeployment +// exec activeCandidateDeployment +// } +// type args struct { +// pluginType cctypes.PluginType +// } +// tests := []struct { +// name string +// fields fields +// args args +// want bool +// }{ +// { +// "commit candidate present", +// fields{ +// commit: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// candidate: mocktypes.NewCCIPOracle(t), +// }, +// }, +// args{ +// pluginType: cctypes.PluginTypeCCIPCommit, +// }, +// true, +// }, +// { +// "commit candidate not present", +// fields{ +// commit: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// }, +// }, +// args{ +// pluginType: cctypes.PluginTypeCCIPCommit, +// }, +// false, +// }, +// { +// "exec candidate present", +// fields{ +// exec: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// candidate: mocktypes.NewCCIPOracle(t), +// }, +// }, +// args{ +// pluginType: cctypes.PluginTypeCCIPExec, +// }, +// true, +// }, +// { +// "exec candidate not present", +// fields{ +// exec: activeCandidateDeployment{ +// active: mocktypes.NewCCIPOracle(t), +// }, +// }, +// args{ +// pluginType: cctypes.PluginTypeCCIPExec, +// }, +// false, +// }, +// { +// "invalid plugin type", +// fields{}, +// args{ +// pluginType: cctypes.PluginType(100), +// }, +// false, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// c := &ccipDeployment{} +// if tt.fields.commit.active != nil { +// c.commit.active = tt.fields.commit.active +// } +// if tt.fields.commit.candidate != nil { +// c.commit.candidate = tt.fields.commit.candidate +// } +// if tt.fields.exec.active != nil { +// c.exec.active = tt.fields.exec.active +// } +// if tt.fields.exec.candidate != nil { +// c.exec.candidate = tt.fields.exec.candidate +// } +// got := c.HasCandidateInstance(tt.args.pluginType) +// require.Equal(t, tt.want, got) +// }) +// } +//} From 2330e45d630edd943d4697d3f1e137cbe9af70e5 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Sat, 2 Nov 2024 02:06:50 +1100 Subject: [PATCH 08/16] update tests, goimports --- core/capabilities/ccip/launcher/deployment.go | 1 + .../ccip/launcher/deployment_test.go | 13 +- core/capabilities/ccip/launcher/launcher.go | 65 +- .../ccip/launcher/launcher_test.go | 559 ++++++++++++++---- 4 files changed, 484 insertions(+), 154 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index 82a8772d064..a5efab4b2a3 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -2,6 +2,7 @@ package launcher import ( "fmt" + "golang.org/x/exp/maps" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" diff --git a/core/capabilities/ccip/launcher/deployment_test.go b/core/capabilities/ccip/launcher/deployment_test.go index c0a2f835b1b..d81570e3900 100644 --- a/core/capabilities/ccip/launcher/deployment_test.go +++ b/core/capabilities/ccip/launcher/deployment_test.go @@ -1,14 +1,15 @@ package launcher import ( - "fmt" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "testing" - mocktypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/stretchr/testify/require" + + mocktypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" ) func Test_ccipDeployment_Transitions(t *testing.T) { @@ -284,12 +285,6 @@ func Test_ccipDeployment_Transitions(t *testing.T) { for digest, oracle := range args.currDeployment { curr[digest] = oracle } - - fmt.Println("prev...") - prev.PrintDigests() - fmt.Println("curr...") - curr.PrintDigests() - tt.expect(t, args) defer assertions(t, args) err := curr.Transition(prev) diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 218658b034a..934efe6debc 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -208,22 +208,15 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer return err } - // If a config digest is not already in our list, we need to create an oracle - // If a config digest is already in our list, we just need to point to the old one - // newP.Transition will make sure we shut down the old oracles, and start the new ones - newP := make(ccipPlugins) - for _, c := range latestConfigs { - digest := c.ConfigDigest - if prevPlugins[digest] == nil { - oracle, err := l.oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(c)) - if err != nil { - return fmt.Errorf("failed to create CCIP oracle: %w for digest %v", err, digest) - } - - newP[digest] = oracle - } else { - newP[digest] = prevPlugins[digest] - } + newP, err := updateDON( + l.lggr, + l.myP2PID, + prevPlugins, + don, + l.oracleCreator, + latestConfigs) + if err != nil { + return err } err = newP.Transition(prevPlugins) @@ -256,7 +249,7 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DO if err != nil { return fmt.Errorf("processAdded: call createDON %d: %w", donID, err) } - if newPlugins == nil { + if len(newPlugins) == 0 { // not a member of this DON. continue } @@ -303,8 +296,41 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce return nil } +func updateDON( + lggr logger.Logger, + p2pID ragep2ptypes.PeerID, + prevPlugins ccipPlugins, + don registrysyncer.DON, + oracleCreator cctypes.OracleCreator, + latestConfigs []ccipreader.OCR3ConfigWithMeta, +) (ccipPlugins, error) { + if !isMemberOfDON(don, p2pID) { + lggr.Infow("Not a member of this DON, skipping", "donId", don.ID, "p2pId", p2pID.String()) + } + + newP := make(ccipPlugins) + // If a config digest is not already in our list, we need to create an oracle + // If a config digest is already in our list, we just need to point to the old one + // newP.Transition will make sure we shut down the old oracles, and start the new ones + for _, c := range latestConfigs { + digest := c.ConfigDigest + if _, ok := prevPlugins[digest]; !ok { + oracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(c)) + if err != nil { + return nil, fmt.Errorf("failed to create CCIP oracle: %w for digest %x", err, digest) + } + + newP[digest] = oracle + } else { + newP[digest] = prevPlugins[digest] + } + } + + return newP, nil +} + // createDON is a pure function that handles the case where a new DON is added to the capability registry. -// It returns up to 4 plugins that are then started. +// It returns up to 4 plugins that are later started. func createDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, @@ -325,11 +351,10 @@ func createDON( oracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(config)) if err != nil { - return nil, fmt.Errorf("failed to create CCIP oracle: %w for digest %v", err, digest) + return nil, fmt.Errorf("failed to create CCIP oracle: %w for digest %x", err, digest) } p[digest] = oracle - } return p, nil } diff --git a/core/capabilities/ccip/launcher/launcher_test.go b/core/capabilities/ccip/launcher/launcher_test.go index bb3bb8a843a..a3aea17e372 100644 --- a/core/capabilities/ccip/launcher/launcher_test.go +++ b/core/capabilities/ccip/launcher/launcher_test.go @@ -2,9 +2,10 @@ package launcher import ( "math/big" - "reflect" "testing" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" @@ -48,20 +49,28 @@ func Test_createDON(t *testing.T) { func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - Nodes: getOCR3Nodes(3, 4), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - Nodes: getOCR3Nodes(3, 4), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) oracleCreator.EXPECT().Type().Return(cctypes.OracleTypePlugin).Once() }, false, @@ -81,20 +90,28 @@ func Test_createDON(t *testing.T) { func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - Nodes: getOCR3Nodes(3, 4), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - Nodes: getOCR3Nodes(3, 4), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) oracleCreator.EXPECT().Type().Return(cctypes.OracleTypeBootstrap).Once() oracleCreator.EXPECT().Create(mock.Anything, mock.Anything).Return(mocks.NewCCIPOracle(t), nil).Twice() }, @@ -112,20 +129,29 @@ func Test_createDON(t *testing.T) { func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - Nodes: getOCR3Nodes(3, 4), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) + homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - Nodes: getOCR3Nodes(3, 4), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) @@ -138,6 +164,65 @@ func Test_createDON(t *testing.T) { }, false, }, + { + "if a don is created with active and candidate configs, all should be created", + args{ + logger.TestLogger(t), + p2pID1, + mocks.NewHomeChainReader(t), + mocks.NewOracleCreator(t), + defaultRegistryDon, + }, + func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). + Return(mocks.NewCCIPOracle(t), nil).Twice() + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). + Return(mocks.NewCCIPOracle(t), nil).Twice() + }, + false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -145,7 +230,9 @@ func Test_createDON(t *testing.T) { tt.expect(t, tt.args, tt.args.oracleCreator, tt.args.homeChainReader) } - _, err := createDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.don, tt.args.oracleCreator) + latestConfigs, err := getConfigsForDon(tt.args.homeChainReader, tt.args.don) + require.NoError(t, err) + _, err = createDON(tt.args.lggr, tt.args.p2pID, tt.args.don, tt.args.oracleCreator, latestConfigs) if tt.wantErr { require.Error(t, err) } else { @@ -155,74 +242,280 @@ func Test_createDON(t *testing.T) { } } -func Test_createFutureBlueGreenDeployment(t *testing.T) { - type args struct { - donID uint32 - prevDeployment ccipDeployment - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - oracleCreator *mocks.OracleCreator - pluginType cctypes.PluginType - } - tests := []struct { - name string - args args - want activeCandidateDeployment - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := createFutureActiveCandidateDeployment(tt.args.donID, tt.args.prevDeployment, tt.args.ocrConfigs, tt.args.oracleCreator, tt.args.pluginType) - if (err != nil) != tt.wantErr { - t.Errorf("createFutureActiveCandidateDeployment() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("createFutureActiveCandidateDeployment() = %v, want %v", got, tt.want) - } - }) - } -} - func Test_updateDON(t *testing.T) { + var ( + digest1 = utils.RandomBytes32() + digest2 = utils.RandomBytes32() + ) type args struct { lggr logger.Logger p2pID ragep2ptypes.PeerID homeChainReader *mocks.HomeChainReader oracleCreator *mocks.OracleCreator - prevDeployment ccipDeployment don registrysyncer.DON + prevPlugins ccipPlugins } tests := []struct { - name string - args args - wantFutDeployment *ccipDeployment - wantErr bool + name string + args args + desiredLen int + expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) + wantErr bool }{ - // TODO: Add test cases. + { + name: "should start new plugins", + args: args{ + logger.TestLogger(t), + p2pID3, + mocks.NewHomeChainReader(t), + mocks.NewOracleCreator(t), + registrysyncer.DON{ + DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), + CapabilityConfigurations: defaultCapCfgs, + }, + ccipPlugins{ + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + }, + }, + desiredLen: 2, + expect: func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). + Return(mocks.NewCCIPOracle(t), nil) + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). + Return(mocks.NewCCIPOracle(t), nil) + }, + wantErr: false, + }, + { + name: "should return no plugins if config is empty", + args: args{ + logger.TestLogger(t), + p2pID3, + mocks.NewHomeChainReader(t), + mocks.NewOracleCreator(t), + registrysyncer.DON{ + DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), + CapabilityConfigurations: defaultCapCfgs, + }, + ccipPlugins{ + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + }, + }, + desiredLen: 0, + expect: func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + }, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + }, nil) + oracleCreator.AssertNotCalled(t, "Create") + }, + wantErr: false, + }, + { + name: "should maintain existing plugins", + args: args{ + logger.TestLogger(t), + p2pID3, + mocks.NewHomeChainReader(t), + mocks.NewOracleCreator(t), + registrysyncer.DON{ + DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), + CapabilityConfigurations: defaultCapCfgs, + }, + ccipPlugins{ + digest1: mocks.NewCCIPOracle(t), + digest2: mocks.NewCCIPOracle(t), + }, + }, + desiredLen: 4, + expect: func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: digest1, + }, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: digest2, + }, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). + Return(mocks.NewCCIPOracle(t), nil).Once() + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). + Return(mocks.NewCCIPOracle(t), nil).Once() + }, + wantErr: false, + }, + { + name: "should start brand new plugins if all are new", + args: args{ + logger.TestLogger(t), + p2pID3, + mocks.NewHomeChainReader(t), + mocks.NewOracleCreator(t), + registrysyncer.DON{ + DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), + CapabilityConfigurations: defaultCapCfgs, + }, + ccipPlugins{ + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + utils.RandomBytes32(): mocks.NewCCIPOracle(t), + }, + }, + desiredLen: 4, + expect: func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), + }, + }, nil) + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). + Return(mocks.NewCCIPOracle(t), nil).Twice() + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). + Return(mocks.NewCCIPOracle(t), nil).Twice() + }, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotFutDeployment, err := updateDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.prevDeployment, tt.args.don, tt.args.oracleCreator) + if tt.expect != nil { + tt.expect(t, tt.args, tt.args.oracleCreator, tt.args.homeChainReader) + } + + latestConfigs, err := getConfigsForDon(tt.args.homeChainReader, tt.args.don) + require.NoError(t, err) + newPlugins, err := updateDON(tt.args.lggr, tt.args.p2pID, tt.args.prevPlugins, tt.args.don, tt.args.oracleCreator, latestConfigs) if (err != nil) != tt.wantErr { t.Errorf("updateDON() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(gotFutDeployment, tt.wantFutDeployment) { - t.Errorf("updateDON() = %v, want %v", gotFutDeployment, tt.wantFutDeployment) + + if len(newPlugins) != tt.desiredLen { + t.Errorf("updateDON() error. Wanted new length of plugins to be %d, got %d", tt.desiredLen, len(newPlugins)) } }) } } func Test_launcher_processDiff(t *testing.T) { + var ( + digest1 = utils.RandomBytes32() + digest2 = utils.RandomBytes32() + ) type fields struct { lggr logger.Logger p2pID ragep2ptypes.PeerID homeChainReader *mocks.HomeChainReader oracleCreator *mocks.OracleCreator - dons map[registrysyncer.DonID]*ccipDeployment + instances map[registrysyncer.DonID]ccipPlugins regState registrysyncer.LocalRegistry } type args struct { @@ -238,22 +531,18 @@ func Test_launcher_processDiff(t *testing.T) { { "don removed success", fields{ - dons: map[registrysyncer.DonID]*ccipDeployment{ + instances: map[registrysyncer.DonID]ccipPlugins{ 1: { - commit: activeCandidateDeployment{ - active: newMock(t, - func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, - func(m *mocks.CCIPOracle) { - m.On("Close").Return(nil) - }), - }, - exec: activeCandidateDeployment{ - active: newMock(t, - func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, - func(m *mocks.CCIPOracle) { - m.On("Close").Return(nil) - }), - }, + utils.RandomBytes32(): newMock(t, + func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, + func(m *mocks.CCIPOracle) { + m.On("Close").Return(nil).Once() + }), + utils.RandomBytes32(): newMock(t, + func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, + func(m *mocks.CCIPOracle) { + m.On("Close").Return(nil).Once() + }), }, }, regState: registrysyncer.LocalRegistry{ @@ -270,7 +559,7 @@ func Test_launcher_processDiff(t *testing.T) { }, }, func(t *testing.T, l *launcher) { - require.Len(t, l.dons, 0) + require.Len(t, l.instances, 0) require.Len(t, l.regState.IDsToDONs, 0) }, false, @@ -284,17 +573,27 @@ func Test_launcher_processDiff(t *testing.T) { return mocks.NewHomeChainReader(t) }, func(m *mocks.HomeChainReader) { m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{}, + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) }), oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { return mocks.NewOracleCreator(t) @@ -312,7 +611,7 @@ func Test_launcher_processDiff(t *testing.T) { })). Return(execOracle, nil) }), - dons: map[registrysyncer.DonID]*ccipDeployment{}, + instances: map[registrysyncer.DonID]ccipPlugins{}, regState: registrysyncer.LocalRegistry{ IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{}, }, @@ -325,7 +624,7 @@ func Test_launcher_processDiff(t *testing.T) { }, }, func(t *testing.T, l *launcher) { - require.Len(t, l.dons, 1) + require.Len(t, l.instances, 1) require.Len(t, l.regState.IDsToDONs, 1) }, false, @@ -339,25 +638,39 @@ func Test_launcher_processDiff(t *testing.T) { return mocks.NewHomeChainReader(t) }, func(m *mocks.HomeChainReader) { m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }, { - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: digest1, }, - }}, nil) + }, nil) m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), + Return(ccipreaderpkg.ActiveAndCandidate{ + ActiveConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: digest2, }, - }, { - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), + CandidateConfig: ccipreaderpkg.OCR3ConfigWithMeta{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + ConfigDigest: utils.RandomBytes32(), }, - }}, nil) + }, nil) }), oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { return mocks.NewOracleCreator(t) @@ -375,18 +688,14 @@ func Test_launcher_processDiff(t *testing.T) { })). Return(execOracle, nil) }), - dons: map[registrysyncer.DonID]*ccipDeployment{ + instances: map[registrysyncer.DonID]ccipPlugins{ 1: { - commit: activeCandidateDeployment{ - active: newMock(t, func(t *testing.T) *mocks.CCIPOracle { - return mocks.NewCCIPOracle(t) - }, func(m *mocks.CCIPOracle) {}), - }, - exec: activeCandidateDeployment{ - active: newMock(t, func(t *testing.T) *mocks.CCIPOracle { - return mocks.NewCCIPOracle(t) - }, func(m *mocks.CCIPOracle) {}), - }, + digest1: newMock(t, func(t *testing.T) *mocks.CCIPOracle { + return mocks.NewCCIPOracle(t) + }, func(m *mocks.CCIPOracle) {}), + digest2: newMock(t, func(t *testing.T) *mocks.CCIPOracle { + return mocks.NewCCIPOracle(t) + }, func(m *mocks.CCIPOracle) {}), }, }, regState: registrysyncer.LocalRegistry{ @@ -407,7 +716,7 @@ func Test_launcher_processDiff(t *testing.T) { }, }, func(t *testing.T, l *launcher) { - require.Len(t, l.dons, 1) + require.Len(t, l.instances, 1) require.Len(t, l.regState.IDsToDONs, 1) require.Len(t, l.regState.IDsToDONs[1].Members, 2) }, @@ -417,7 +726,7 @@ func Test_launcher_processDiff(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := &launcher{ - dons: tt.fields.dons, + instances: tt.fields.instances, regState: tt.fields.regState, myP2PID: tt.fields.p2pID, lggr: tt.fields.lggr, From 9fc3236473bccca4bf23b1fbcc7ec8df917552c8 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Sat, 2 Nov 2024 02:33:06 +1100 Subject: [PATCH 09/16] remove unused code --- core/capabilities/ccip/launcher/deployment.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index a5efab4b2a3..2a10764940d 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -3,8 +3,6 @@ package launcher import ( "fmt" - "golang.org/x/exp/maps" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "go.uber.org/multierr" @@ -50,9 +48,3 @@ func (c ccipPlugins) Transition(prevPlugins ccipPlugins) error { } return err } - -func (c ccipPlugins) PrintDigests() { - for _, d := range maps.Keys(c) { - fmt.Println(d.Hex()) - } -} From 2156449c1ad0c0a080f9b57842a56e353c809610 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Mon, 4 Nov 2024 11:16:39 +0900 Subject: [PATCH 10/16] go mod reset --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 03084edf658..250ff5ee883 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101151110-0be8888ce1d9 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e diff --git a/go.sum b/go.sum index c9ffda30070..630d16c92e8 100644 --- a/go.sum +++ b/go.sum @@ -1075,8 +1075,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 h1:+VR9yKhbz+iCtWnCabaCDP18lIqGnk7YvGQIbJYgDrs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101151110-0be8888ce1d9 h1:F9s1BSs7lQtlaTHFjFLHppuNI2A6EBxfK+pyEFUJwsI= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101151110-0be8888ce1d9/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= From c9c6eeaf30a277e984905e0e370853c82746e4d8 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Mon, 4 Nov 2024 17:13:12 +0900 Subject: [PATCH 11/16] check error, use new hash of chainlink-ccip --- core/capabilities/ccip/launcher/deployment.go | 2 +- core/capabilities/ccip/launcher/launcher.go | 3 +++ go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index 2a10764940d..8af3247a14c 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -31,7 +31,7 @@ func (c ccipPlugins) Transition(prevPlugins ccipPlugins) error { var err error if len(c) > 4 || len(prevPlugins) > 4 { - return fmt.Errorf("have more than 4 instances somehow") + return fmt.Errorf("current ccipPlugins or prevPlugins have more than 4 instances: len(prevPlugins): %d, len(currPlugins): %d", len(prevPlugins), len(c)) } // This shuts down instances that were present previously, but are no longer needed for digest, oracle := range prevPlugins { diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 934efe6debc..54271f2370a 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -239,6 +239,9 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DO for donID, don := range added { configs, err := getConfigsForDon(l.homeChainReader, don) + if err != nil { + return fmt.Errorf("failed to get current configs for don %d: %w", donID, err) + } newPlugins, err := createDON( l.lggr, l.myP2PID, diff --git a/go.mod b/go.mod index 250ff5ee883..b19aa6234a2 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101151110-0be8888ce1d9 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e diff --git a/go.sum b/go.sum index 630d16c92e8..d83d26e40db 100644 --- a/go.sum +++ b/go.sum @@ -1075,8 +1075,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101151110-0be8888ce1d9 h1:F9s1BSs7lQtlaTHFjFLHppuNI2A6EBxfK+pyEFUJwsI= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101151110-0be8888ce1d9/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= From 723891ea7f2c227fe497fd85c7324b9f966e1f7a Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Mon, 4 Nov 2024 17:54:26 +0900 Subject: [PATCH 12/16] use make command --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- deployment/go.mod | 2 +- deployment/go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index d5100c6f3d2..669a23ade66 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -288,7 +288,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect github.com/smartcontractkit/chain-selectors v1.0.27 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 005d95779ae..45a0e9fe3a1 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1090,8 +1090,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 h1:+VR9yKhbz+iCtWnCabaCDP18lIqGnk7YvGQIbJYgDrs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= diff --git a/deployment/go.mod b/deployment/go.mod index 14630351641..b275ade81b3 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -23,7 +23,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.27 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 diff --git a/deployment/go.sum b/deployment/go.sum index 5c4f0df9cad..f66ab6d972f 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1382,8 +1382,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 h1:+VR9yKhbz+iCtWnCabaCDP18lIqGnk7YvGQIbJYgDrs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 054fbb27787..4e228d1a2f3 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -35,7 +35,7 @@ require ( github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index d4f87ad83e7..1ccefe52890 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1403,8 +1403,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 h1:+VR9yKhbz+iCtWnCabaCDP18lIqGnk7YvGQIbJYgDrs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index de72bc705e7..5a726255b4a 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -64,7 +64,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 13e1974b17e..36246aca7b8 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1392,8 +1392,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4 h1:+VR9yKhbz+iCtWnCabaCDP18lIqGnk7YvGQIbJYgDrs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241101132401-00090bf7feb4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= From d0adb22a3fd131c714e747af5eaab12759cfadc3 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Mon, 4 Nov 2024 18:07:58 +0900 Subject: [PATCH 13/16] lint --- .../ccip/launcher/deployment_test.go | 674 +----------------- core/capabilities/ccip/launcher/launcher.go | 1 - .../ccip/launcher/launcher_test.go | 4 +- 3 files changed, 4 insertions(+), 675 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment_test.go b/core/capabilities/ccip/launcher/deployment_test.go index d81570e3900..5a005e3ad6b 100644 --- a/core/capabilities/ccip/launcher/deployment_test.go +++ b/core/capabilities/ccip/launcher/deployment_test.go @@ -19,10 +19,10 @@ func Test_ccipDeployment_Transitions(t *testing.T) { currDeployment map[ocrtypes.ConfigDigest]*mocktypes.CCIPOracle } assertions := func(t *testing.T, args args) { - for i, _ := range args.prevDeployment { + for i := range args.prevDeployment { args.prevDeployment[i].AssertExpectations(t) } - for i, _ := range args.currDeployment { + for i := range args.currDeployment { args.currDeployment[i].AssertExpectations(t) } } @@ -151,7 +151,6 @@ func Test_ccipDeployment_Transitions(t *testing.T) { }, expect: func(t *testing.T, args args) { for digest, plugin := range args.prevDeployment { - if _, ok := args.currDeployment[digest]; !ok { // if the instance is no longer present, it should have been deleted plugin.On("Close").Return(nil).Once() @@ -296,672 +295,3 @@ func Test_ccipDeployment_Transitions(t *testing.T) { }) } } - -// -//func Test_ccipDeployment_Close(t *testing.T) { -// type args struct { -// commitBlue *mocktypes.CCIPOracle -// commitGreen *mocktypes.CCIPOracle -// execBlue *mocktypes.CCIPOracle -// execGreen *mocktypes.CCIPOracle -// } -// tests := []struct { -// name string -// args args -// expect func(t *testing.T, args args) -// asserts func(t *testing.T, args args) -// wantErr bool -// }{ -// { -// name: "no errors, active only", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: nil, -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: nil, -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Close").Return(nil).Once() -// args.execBlue.On("Close").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: false, -// }, -// { -// name: "no errors, active and candidate", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Close").Return(nil).Once() -// args.commitGreen.On("Close").Return(nil).Once() -// args.execBlue.On("Close").Return(nil).Once() -// args.execGreen.On("Close").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.commitGreen.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// args.execGreen.AssertExpectations(t) -// }, -// wantErr: false, -// }, -// { -// name: "error on commit active", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: nil, -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: nil, -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Close").Return(errors.New("failed")).Once() -// args.execBlue.On("Close").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// c := &ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: tt.args.commitBlue, -// }, -// exec: activeCandidateDeployment{ -// active: tt.args.execBlue, -// }, -// } -// if tt.args.commitGreen != nil { -// c.commit.candidate = tt.args.commitGreen -// } -// -// if tt.args.execGreen != nil { -// c.exec.candidate = tt.args.execGreen -// } -// -// tt.expect(t, tt.args) -// defer tt.asserts(t, tt.args) -// err := c.Close() -// if tt.wantErr { -// require.Error(t, err) -// } else { -// require.NoError(t, err) -// } -// }) -// } -//} -// -//func Test_ccipDeployment_StartBlue(t *testing.T) { -// type args struct { -// commitBlue *mocktypes.CCIPOracle -// execBlue *mocktypes.CCIPOracle -// } -// tests := []struct { -// name string -// args args -// expect func(t *testing.T, args args) -// asserts func(t *testing.T, args args) -// wantErr bool -// }{ -// { -// name: "no errors", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Start").Return(nil).Once() -// args.execBlue.On("Start").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: false, -// }, -// { -// name: "error on commit active", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Start").Return(errors.New("failed")).Once() -// args.execBlue.On("Start").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// { -// name: "error on exec active", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Start").Return(nil).Once() -// args.execBlue.On("Start").Return(errors.New("failed")).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// c := &ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: tt.args.commitBlue, -// }, -// exec: activeCandidateDeployment{ -// active: tt.args.execBlue, -// }, -// } -// -// tt.expect(t, tt.args) -// defer tt.asserts(t, tt.args) -// err := c.StartActive() -// if tt.wantErr { -// require.Error(t, err) -// } else { -// require.NoError(t, err) -// } -// }) -// } -//} -// -//func Test_ccipDeployment_CloseBlue(t *testing.T) { -// type args struct { -// commitBlue *mocktypes.CCIPOracle -// execBlue *mocktypes.CCIPOracle -// } -// tests := []struct { -// name string -// args args -// expect func(t *testing.T, args args) -// asserts func(t *testing.T, args args) -// wantErr bool -// }{ -// { -// name: "no errors", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Close").Return(nil).Once() -// args.execBlue.On("Close").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: false, -// }, -// { -// name: "error on commit active", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Close").Return(errors.New("failed")).Once() -// args.execBlue.On("Close").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// { -// name: "error on exec active", -// args: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args) { -// args.commitBlue.On("Close").Return(nil).Once() -// args.execBlue.On("Close").Return(errors.New("failed")).Once() -// }, -// asserts: func(t *testing.T, args args) { -// args.commitBlue.AssertExpectations(t) -// args.execBlue.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// c := &ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: tt.args.commitBlue, -// }, -// exec: activeCandidateDeployment{ -// active: tt.args.execBlue, -// }, -// } -// -// tt.expect(t, tt.args) -// defer tt.asserts(t, tt.args) -// err := c.CloseActive() -// if tt.wantErr { -// require.Error(t, err) -// } else { -// require.NoError(t, err) -// } -// }) -// } -//} -// -//func Test_ccipDeployment_HandleBlueGreen_PrevDeploymentNil(t *testing.T) { -// require.Error(t, (&ccipDeployment{}).TransitionDeployment(nil)) -//} -// -//func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { -// type args struct { -// commitBlue *mocktypes.CCIPOracle -// commitGreen *mocktypes.CCIPOracle -// execBlue *mocktypes.CCIPOracle -// execGreen *mocktypes.CCIPOracle -// } -// tests := []struct { -// name string -// argsPrevDeployment args -// argsFutureDeployment args -// expect func(t *testing.T, args args, argsPrevDeployment args) -// asserts func(t *testing.T, args args, argsPrevDeployment args) -// wantErr bool -// }{ -// { -// name: "promotion active to candidate", -// argsPrevDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// argsFutureDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: nil, -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: nil, -// }, -// expect: func(t *testing.T, args args, argsPrevDeployment args) { -// argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() -// argsPrevDeployment.execBlue.On("Close").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args, argsPrevDeployment args) { -// argsPrevDeployment.commitBlue.AssertExpectations(t) -// argsPrevDeployment.execBlue.AssertExpectations(t) -// }, -// wantErr: false, -// }, -// { -// name: "new candidate deployment", -// argsPrevDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: nil, -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: nil, -// }, -// argsFutureDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.On("Start").Return(nil).Once() -// args.execGreen.On("Start").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.AssertExpectations(t) -// args.execGreen.AssertExpectations(t) -// }, -// wantErr: false, -// }, -// { -// name: "error on commit candidate start", -// argsPrevDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: nil, -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: nil, -// }, -// argsFutureDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.On("Start").Return(errors.New("failed")).Once() -// args.execGreen.On("Start").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.AssertExpectations(t) -// args.execGreen.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// { -// name: "error on exec candidate start", -// argsPrevDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: nil, -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: nil, -// }, -// argsFutureDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.On("Start").Return(nil).Once() -// args.execGreen.On("Start").Return(errors.New("failed")).Once() -// }, -// asserts: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.AssertExpectations(t) -// args.execGreen.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// { -// name: "invalid active-candidate deployment transition commit: both prev and future deployment have candidate", -// argsPrevDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// argsFutureDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args, argsPrevDeployment args) {}, -// asserts: func(t *testing.T, args args, argsPrevDeployment args) {}, -// wantErr: true, -// }, -// { -// name: "invalid active-candidate deployment transition exec: both prev and future exec deployment have candidate", -// argsPrevDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: nil, -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// argsFutureDeployment: args{ -// commitBlue: mocktypes.NewCCIPOracle(t), -// commitGreen: mocktypes.NewCCIPOracle(t), -// execBlue: mocktypes.NewCCIPOracle(t), -// execGreen: mocktypes.NewCCIPOracle(t), -// }, -// expect: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.On("Start").Return(nil).Once() -// }, -// asserts: func(t *testing.T, args args, argsPrevDeployment args) { -// args.commitGreen.AssertExpectations(t) -// }, -// wantErr: true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// futDeployment := &ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: tt.argsFutureDeployment.commitBlue, -// }, -// exec: activeCandidateDeployment{ -// active: tt.argsFutureDeployment.execBlue, -// }, -// } -// if tt.argsFutureDeployment.commitGreen != nil { -// futDeployment.commit.candidate = tt.argsFutureDeployment.commitGreen -// } -// if tt.argsFutureDeployment.execGreen != nil { -// futDeployment.exec.candidate = tt.argsFutureDeployment.execGreen -// } -// -// prevDeployment := &ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: tt.argsPrevDeployment.commitBlue, -// }, -// exec: activeCandidateDeployment{ -// active: tt.argsPrevDeployment.execBlue, -// }, -// } -// if tt.argsPrevDeployment.commitGreen != nil { -// prevDeployment.commit.candidate = tt.argsPrevDeployment.commitGreen -// } -// if tt.argsPrevDeployment.execGreen != nil { -// prevDeployment.exec.candidate = tt.argsPrevDeployment.execGreen -// } -// -// tt.expect(t, tt.argsFutureDeployment, tt.argsPrevDeployment) -// defer tt.asserts(t, tt.argsFutureDeployment, tt.argsPrevDeployment) -// err := futDeployment.TransitionDeployment(prevDeployment) -// if tt.wantErr { -// require.Error(t, err) -// } else { -// require.NoError(t, err) -// } -// }) -// } -//} -// -//func Test_isNewGreenInstance(t *testing.T) { -// type args struct { -// pluginType cctypes.PluginType -// ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta -// prevDeployment ccipDeployment -// } -// tests := []struct { -// name string -// args args -// want bool -// }{ -// { -// "prev deployment only active", -// args{ -// pluginType: cctypes.PluginTypeCCIPCommit, -// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ -// {}, {}, -// }, -// prevDeployment: ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// }, -// }, -// }, -// true, -// }, -// { -// "candidate -> active promotion", -// args{ -// pluginType: cctypes.PluginTypeCCIPCommit, -// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ -// {}, -// }, -// prevDeployment: ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// candidate: mocktypes.NewCCIPOracle(t), -// }, -// }, -// }, -// false, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// got := isNewCandidateInstance(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment) -// require.Equal(t, tt.want, got) -// }) -// } -//} -// -//func Test_isPromotion(t *testing.T) { -// type args struct { -// pluginType cctypes.PluginType -// ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta -// prevDeployment ccipDeployment -// } -// tests := []struct { -// name string -// args args -// want bool -// }{ -// { -// "prev deployment only active", -// args{ -// pluginType: cctypes.PluginTypeCCIPCommit, -// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ -// {}, {}, -// }, -// prevDeployment: ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// }, -// }, -// }, -// false, -// }, -// { -// "candidate -> active promotion", -// args{ -// pluginType: cctypes.PluginTypeCCIPCommit, -// ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ -// {}, -// }, -// prevDeployment: ccipDeployment{ -// commit: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// candidate: mocktypes.NewCCIPOracle(t), -// }, -// }, -// }, -// true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// if got := isPromotion(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment); got != tt.want { -// t.Errorf("isPromotion() = %v, want %v", got, tt.want) -// } -// }) -// } -//} -// -//func Test_ccipDeployment_HasGreenInstance(t *testing.T) { -// type fields struct { -// commit activeCandidateDeployment -// exec activeCandidateDeployment -// } -// type args struct { -// pluginType cctypes.PluginType -// } -// tests := []struct { -// name string -// fields fields -// args args -// want bool -// }{ -// { -// "commit candidate present", -// fields{ -// commit: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// candidate: mocktypes.NewCCIPOracle(t), -// }, -// }, -// args{ -// pluginType: cctypes.PluginTypeCCIPCommit, -// }, -// true, -// }, -// { -// "commit candidate not present", -// fields{ -// commit: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// }, -// }, -// args{ -// pluginType: cctypes.PluginTypeCCIPCommit, -// }, -// false, -// }, -// { -// "exec candidate present", -// fields{ -// exec: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// candidate: mocktypes.NewCCIPOracle(t), -// }, -// }, -// args{ -// pluginType: cctypes.PluginTypeCCIPExec, -// }, -// true, -// }, -// { -// "exec candidate not present", -// fields{ -// exec: activeCandidateDeployment{ -// active: mocktypes.NewCCIPOracle(t), -// }, -// }, -// args{ -// pluginType: cctypes.PluginTypeCCIPExec, -// }, -// false, -// }, -// { -// "invalid plugin type", -// fields{}, -// args{ -// pluginType: cctypes.PluginType(100), -// }, -// false, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// c := &ccipDeployment{} -// if tt.fields.commit.active != nil { -// c.commit.active = tt.fields.commit.active -// } -// if tt.fields.commit.candidate != nil { -// c.commit.candidate = tt.fields.commit.candidate -// } -// if tt.fields.exec.active != nil { -// c.exec.active = tt.fields.exec.active -// } -// if tt.fields.exec.candidate != nil { -// c.exec.candidate = tt.fields.exec.candidate -// } -// got := c.HasCandidateInstance(tt.args.pluginType) -// require.Equal(t, tt.want, got) -// }) -// } -//} diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 54271f2370a..3d478ef2024 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -365,7 +365,6 @@ func createDON( func getConfigsForDon( homeChainReader ccipreader.HomeChain, don registrysyncer.DON) ([]ccipreader.OCR3ConfigWithMeta, error) { - // this should be a retryable error. commitOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.ID, uint8(cctypes.PluginTypeCCIPCommit)) if err != nil { diff --git a/core/capabilities/ccip/launcher/launcher_test.go b/core/capabilities/ccip/launcher/launcher_test.go index a3aea17e372..887f05b9fc7 100644 --- a/core/capabilities/ccip/launcher/launcher_test.go +++ b/core/capabilities/ccip/launcher/launcher_test.go @@ -559,8 +559,8 @@ func Test_launcher_processDiff(t *testing.T) { }, }, func(t *testing.T, l *launcher) { - require.Len(t, l.instances, 0) - require.Len(t, l.regState.IDsToDONs, 0) + require.Empty(t, l.instances) + require.Empty(t, l.regState.IDsToDONs) }, false, }, From ba19484a25467690cd869ebef901c336b0f349a0 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Mon, 4 Nov 2024 22:32:04 +0900 Subject: [PATCH 14/16] comments --- core/capabilities/ccip/launcher/deployment.go | 62 ++++++++++++++----- .../ccip/launcher/deployment_test.go | 6 +- core/capabilities/ccip/launcher/launcher.go | 24 +++---- .../ccip/launcher/launcher_test.go | 18 +++--- go.mod | 2 +- go.sum | 2 + 6 files changed, 73 insertions(+), 41 deletions(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index 8af3247a14c..7ea3b1302d8 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -2,6 +2,7 @@ package launcher import ( "fmt" + "sync" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "go.uber.org/multierr" @@ -9,42 +10,71 @@ import ( cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" ) -type ccipPlugins map[ocrtypes.ConfigDigest]cctypes.CCIPOracle +// MaxPlugins is the maximum number of plugins possible. +// A plugin represents a possible combination of (active/candidate) x (commit/exec) +// If we ever have more than 4 plugins in a prev or desired state, something went wrong +const MaxPlugins = 4 + +type pluginRegistry map[ocrtypes.ConfigDigest]cctypes.CCIPOracle // StartAll will call Oracle.Start on an entire don -func (c ccipPlugins) StartAll() error { - nilPlugins := make(ccipPlugins) - return c.Transition(nilPlugins) +func (c pluginRegistry) StartAll() error { + emptyPluginRegistry := make(pluginRegistry) + return c.TransitionFrom(emptyPluginRegistry) } // CloseAll is used to shut down an entire don immediately -func (c ccipPlugins) CloseAll() error { - nilPlugins := make(ccipPlugins) - return nilPlugins.Transition(c) +func (c pluginRegistry) CloseAll() error { + emptyPluginRegistry := make(pluginRegistry) + return emptyPluginRegistry.TransitionFrom(c) } -// Transition manages starting and stopping ocr instances +// TransitionFrom manages starting and stopping ocr instances // If there are any new config digests, we need to start those instances // If any of the previous config digests are no longer present, we need to shut those down // We don't care about if they're exec/commit or active/candidate, that all happens in the plugin -func (c ccipPlugins) Transition(prevPlugins ccipPlugins) error { - var err error +func (c pluginRegistry) TransitionFrom(prevPlugins pluginRegistry) error { + var allErrs error - if len(c) > 4 || len(prevPlugins) > 4 { - return fmt.Errorf("current ccipPlugins or prevPlugins have more than 4 instances: len(prevPlugins): %d, len(currPlugins): %d", len(prevPlugins), len(c)) + if len(c) > MaxPlugins || len(prevPlugins) > MaxPlugins { + return fmt.Errorf("current pluginRegistry or prevPlugins have more than 4 instances: len(prevPlugins): %d, len(currPlugins): %d", len(prevPlugins), len(c)) } + + var wg sync.WaitGroup + var mu sync.Mutex // This shuts down instances that were present previously, but are no longer needed for digest, oracle := range prevPlugins { if _, ok := c[digest]; !ok { - err = multierr.Append(err, oracle.Close()) + wg.Add(1) + go func(o cctypes.CCIPOracle) { + defer wg.Done() + if err := o.Close(); err != nil { + mu.Lock() + allErrs = multierr.Append(allErrs, err) + mu.Unlock() + } + }(oracle) } } + wg.Wait() // This will start the instances that were not previously present, but are in the new config for digest, oracle := range c { - if _, ok := prevPlugins[digest]; !ok { - err = multierr.Append(err, oracle.Start()) + if digest == [32]byte{} { + allErrs = multierr.Append(allErrs, fmt.Errorf("cannot start a plugin with an empty config digest")) + } else if _, ok := prevPlugins[digest]; !ok { + wg.Add(1) + go func(o cctypes.CCIPOracle) { + defer wg.Done() + if err := o.Start(); err != nil { + mu.Lock() + allErrs = multierr.Append(allErrs, err) + mu.Unlock() + } + }(oracle) } } - return err + wg.Wait() + + return allErrs } diff --git a/core/capabilities/ccip/launcher/deployment_test.go b/core/capabilities/ccip/launcher/deployment_test.go index 5a005e3ad6b..34b5dd6d18b 100644 --- a/core/capabilities/ccip/launcher/deployment_test.go +++ b/core/capabilities/ccip/launcher/deployment_test.go @@ -276,17 +276,17 @@ func Test_ccipDeployment_Transitions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { args := tt.makeArgs(t) - prev := make(ccipPlugins) + prev := make(pluginRegistry) for digest, oracle := range args.prevDeployment { prev[digest] = oracle } - curr := make(ccipPlugins) + curr := make(pluginRegistry) for digest, oracle := range args.currDeployment { curr[digest] = oracle } tt.expect(t, args) defer assertions(t, args) - err := curr.Transition(prev) + err := curr.TransitionFrom(prev) if tt.wantErr { require.Error(t, err) } else { diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 3d478ef2024..167ac0a815e 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -52,7 +52,7 @@ func New( }, tickInterval: tickInterval, oracleCreator: oracleCreator, - instances: make(map[registrysyncer.DonID]ccipPlugins), + instances: make(map[registrysyncer.DonID]pluginRegistry), } } @@ -81,7 +81,7 @@ type launcher struct { // instances is a map of CCIP DON IDs to a map of the OCR instances that are running on them. // This map uses the config digest as the key, and the instance as the value. // We can have up to a maximum of 4 instances per CCIP DON (active/candidate) x (commit/exec) - instances map[registrysyncer.DonID]ccipPlugins + instances map[registrysyncer.DonID]pluginRegistry } // Launch implements registrysyncer.Launcher. @@ -192,7 +192,7 @@ func (l *launcher) processDiff(diff diffResult) error { } // processUpdate will manage when configurations of an existing don are updated -// If new oracles are needed, they are created and started. Old oens wil +// If new oracles are needed, they are created and started. Old ones will be shut down func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer.DON) error { l.lock.Lock() defer l.lock.Unlock() @@ -208,7 +208,7 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer return err } - newP, err := updateDON( + newPlugins, err := updateDON( l.lggr, l.myP2PID, prevPlugins, @@ -219,12 +219,12 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer return err } - err = newP.Transition(prevPlugins) + err = newPlugins.TransitionFrom(prevPlugins) if err != nil { - return fmt.Errorf("Could not transition state %w", err) + return fmt.Errorf("could not transition state %w", err) } - l.instances[donID] = newP + l.instances[donID] = newPlugins l.regState.IDsToDONs[donID] = updated[donID] } @@ -302,16 +302,16 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce func updateDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, - prevPlugins ccipPlugins, + prevPlugins pluginRegistry, don registrysyncer.DON, oracleCreator cctypes.OracleCreator, latestConfigs []ccipreader.OCR3ConfigWithMeta, -) (ccipPlugins, error) { +) (pluginRegistry, error) { if !isMemberOfDON(don, p2pID) { lggr.Infow("Not a member of this DON, skipping", "donId", don.ID, "p2pId", p2pID.String()) } - newP := make(ccipPlugins) + newP := make(pluginRegistry) // If a config digest is not already in our list, we need to create an oracle // If a config digest is already in our list, we just need to point to the old one // newP.Transition will make sure we shut down the old oracles, and start the new ones @@ -340,12 +340,12 @@ func createDON( don registrysyncer.DON, oracleCreator cctypes.OracleCreator, configs []ccipreader.OCR3ConfigWithMeta, -) (ccipPlugins, error) { +) (pluginRegistry, error) { if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.ID, "p2pId", p2pID.String()) return nil, nil } - p := make(ccipPlugins) + p := make(pluginRegistry) for _, config := range configs { digest, err := ocrtypes.BytesToConfigDigest(config.ConfigDigest[:]) if err != nil { diff --git a/core/capabilities/ccip/launcher/launcher_test.go b/core/capabilities/ccip/launcher/launcher_test.go index 887f05b9fc7..188ee48c215 100644 --- a/core/capabilities/ccip/launcher/launcher_test.go +++ b/core/capabilities/ccip/launcher/launcher_test.go @@ -253,7 +253,7 @@ func Test_updateDON(t *testing.T) { homeChainReader *mocks.HomeChainReader oracleCreator *mocks.OracleCreator don registrysyncer.DON - prevPlugins ccipPlugins + prevPlugins pluginRegistry } tests := []struct { name string @@ -273,7 +273,7 @@ func Test_updateDON(t *testing.T) { DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), CapabilityConfigurations: defaultCapCfgs, }, - ccipPlugins{ + pluginRegistry{ utils.RandomBytes32(): mocks.NewCCIPOracle(t), utils.RandomBytes32(): mocks.NewCCIPOracle(t), }, @@ -326,7 +326,7 @@ func Test_updateDON(t *testing.T) { DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), CapabilityConfigurations: defaultCapCfgs, }, - ccipPlugins{ + pluginRegistry{ utils.RandomBytes32(): mocks.NewCCIPOracle(t), utils.RandomBytes32(): mocks.NewCCIPOracle(t), utils.RandomBytes32(): mocks.NewCCIPOracle(t), @@ -362,7 +362,7 @@ func Test_updateDON(t *testing.T) { DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), CapabilityConfigurations: defaultCapCfgs, }, - ccipPlugins{ + pluginRegistry{ digest1: mocks.NewCCIPOracle(t), digest2: mocks.NewCCIPOracle(t), }, @@ -427,7 +427,7 @@ func Test_updateDON(t *testing.T) { DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), CapabilityConfigurations: defaultCapCfgs, }, - ccipPlugins{ + pluginRegistry{ utils.RandomBytes32(): mocks.NewCCIPOracle(t), utils.RandomBytes32(): mocks.NewCCIPOracle(t), utils.RandomBytes32(): mocks.NewCCIPOracle(t), @@ -515,7 +515,7 @@ func Test_launcher_processDiff(t *testing.T) { p2pID ragep2ptypes.PeerID homeChainReader *mocks.HomeChainReader oracleCreator *mocks.OracleCreator - instances map[registrysyncer.DonID]ccipPlugins + instances map[registrysyncer.DonID]pluginRegistry regState registrysyncer.LocalRegistry } type args struct { @@ -531,7 +531,7 @@ func Test_launcher_processDiff(t *testing.T) { { "don removed success", fields{ - instances: map[registrysyncer.DonID]ccipPlugins{ + instances: map[registrysyncer.DonID]pluginRegistry{ 1: { utils.RandomBytes32(): newMock(t, func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, @@ -611,7 +611,7 @@ func Test_launcher_processDiff(t *testing.T) { })). Return(execOracle, nil) }), - instances: map[registrysyncer.DonID]ccipPlugins{}, + instances: map[registrysyncer.DonID]pluginRegistry{}, regState: registrysyncer.LocalRegistry{ IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{}, }, @@ -688,7 +688,7 @@ func Test_launcher_processDiff(t *testing.T) { })). Return(execOracle, nil) }), - instances: map[registrysyncer.DonID]ccipPlugins{ + instances: map[registrysyncer.DonID]pluginRegistry{ 1: { digest1: newMock(t, func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) diff --git a/go.mod b/go.mod index b19aa6234a2..cd089a62e6d 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e diff --git a/go.sum b/go.sum index d83d26e40db..7f7831494bd 100644 --- a/go.sum +++ b/go.sum @@ -1077,6 +1077,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 h1:GWjim4uGGFbye4XbJP0cPAbARhc8u3cAJU8jLYy0mXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= From 8bcff5cd1ca1050d50a88a45601279dac5f2f945 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Mon, 4 Nov 2024 22:33:47 +0900 Subject: [PATCH 15/16] new go mod tidy --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- deployment/go.mod | 2 +- deployment/go.sum | 4 ++-- go.sum | 2 -- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 9 files changed, 12 insertions(+), 14 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 669a23ade66..0392bfab5c2 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -288,7 +288,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect github.com/smartcontractkit/chain-selectors v1.0.27 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 45a0e9fe3a1..3e5bc90f90f 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1090,8 +1090,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 h1:GWjim4uGGFbye4XbJP0cPAbARhc8u3cAJU8jLYy0mXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= diff --git a/deployment/go.mod b/deployment/go.mod index b275ade81b3..4f5d3e95624 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -23,7 +23,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.27 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 diff --git a/deployment/go.sum b/deployment/go.sum index f66ab6d972f..0607d6161fd 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1382,8 +1382,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 h1:GWjim4uGGFbye4XbJP0cPAbARhc8u3cAJU8jLYy0mXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= diff --git a/go.sum b/go.sum index 7f7831494bd..fceb95c5efb 100644 --- a/go.sum +++ b/go.sum @@ -1075,8 +1075,6 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 h1:GWjim4uGGFbye4XbJP0cPAbARhc8u3cAJU8jLYy0mXM= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 4e228d1a2f3..b223f729e8b 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -35,7 +35,7 @@ require ( github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 1ccefe52890..df4ad771076 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1403,8 +1403,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 h1:GWjim4uGGFbye4XbJP0cPAbARhc8u3cAJU8jLYy0mXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 5a726255b4a..2cbbda250fd 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -64,7 +64,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 36246aca7b8..f6c81e4c500 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1392,8 +1392,8 @@ github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+3 github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a h1:fUwKTcdVIP0cTDtqhuJWAqjebyRa0JlLlx4e2mYVXRc= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104080732-1f1a8812250a/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4 h1:GWjim4uGGFbye4XbJP0cPAbARhc8u3cAJU8jLYy0mXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241104130643-4b7e196370c4/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7 h1:AGi0kAtMRW1zl1h7sGw+3CKO4Nlev6iA08YfEcgJCGs= github.com/smartcontractkit/chainlink-common v0.3.1-0.20241101093830-33711d0c3de7/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= From 03a1ad8ad4ffca9d47a7627f4e6b72bf8ce5366a Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Mon, 4 Nov 2024 22:47:31 +0900 Subject: [PATCH 16/16] lint --- core/capabilities/ccip/launcher/deployment.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index 7ea3b1302d8..64571183425 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -1,6 +1,7 @@ package launcher import ( + "errors" "fmt" "sync" @@ -61,7 +62,7 @@ func (c pluginRegistry) TransitionFrom(prevPlugins pluginRegistry) error { // This will start the instances that were not previously present, but are in the new config for digest, oracle := range c { if digest == [32]byte{} { - allErrs = multierr.Append(allErrs, fmt.Errorf("cannot start a plugin with an empty config digest")) + allErrs = multierr.Append(allErrs, errors.New("cannot start a plugin with an empty config digest")) } else if _, ok := prevPlugins[digest]; !ok { wg.Add(1) go func(o cctypes.CCIPOracle) {