From bc76efe9c36a790887cf97f85f0c181a579d719a Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 1 Nov 2024 02:12:36 +1100 Subject: [PATCH] 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 }