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( diff --git a/go.mod b/go.mod index 7b41a80c823..381696f5cab 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-20241029124258-09d605658a80 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241031121316-69118c4941c4 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e @@ -379,6 +379,7 @@ require ( replace ( // replicating the replace directive on cosmos SDK github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + github.com/smartcontractkit/chainlink-ccip => ../chainlink-ccip github.com/sourcegraph/sourcegraph/lib => github.com/sourcegraph/sourcegraph-public-snapshot/lib v0.0.0-20240822153003-c864f15af264 )