Skip to content

Commit

Permalink
Ccip-4692 make ccip home and jobspec changeset idempotent (#16022)
Browse files Browse the repository at this point in the history
* remove deployCCIPContracts

* deprecate existing add lane

* make jobspec and deployhome chain idempotent

* make jobspec changeset idempotent

* adjust tests

* fix lint

* more fix

* try a fix

* more

* another rounder of fix
  • Loading branch information
AnieeG authored Jan 23, 2025
1 parent 496f1db commit 5e404d2
Show file tree
Hide file tree
Showing 16 changed files with 596 additions and 227 deletions.
85 changes: 35 additions & 50 deletions deployment/ccip/changeset/cs_ccip_home.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/merklemulti"

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal"
commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset"
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
Expand All @@ -33,34 +34,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
)

const (
// ========= Changeset Defaults =========
FirstBlockAge = 8 * time.Hour
RemoteGasPriceBatchWriteFrequency = 30 * time.Minute
TokenPriceBatchWriteFrequency = 30 * time.Minute
BatchGasLimit = 6_500_000
RelativeBoostPerWaitHour = 0.5
InflightCacheExpiry = 10 * time.Minute
RootSnoozeTime = 30 * time.Minute
BatchingStrategyID = 0
DeltaProgress = 30 * time.Second
DeltaResend = 10 * time.Second
DeltaInitial = 20 * time.Second
DeltaRound = 2 * time.Second
DeltaGrace = 2 * time.Second
DeltaCertifiedCommitRequest = 10 * time.Second
DeltaStage = 10 * time.Second
Rmax = 3
MaxDurationQuery = 500 * time.Millisecond
MaxDurationObservation = 5 * time.Second
MaxDurationShouldAcceptAttestedReport = 10 * time.Second
MaxDurationShouldTransmitAcceptedReport = 10 * time.Second
GasPriceDeviationPPB = 1000
DAGasPriceDeviationPPB = 0
OptimisticConfirmations = 1
// ======================================
)

var (
_ deployment.ChangeSet[AddDonAndSetCandidateChangesetConfig] = AddDonAndSetCandidateChangeset
_ deployment.ChangeSet[PromoteCandidateChangesetConfig] = PromoteCandidateChangeset
Expand Down Expand Up @@ -219,8 +192,8 @@ func WithDefaultCommitOffChainConfig(feedChainSel uint64, tokenInfo map[ccipocr3
return func(params *CCIPOCRParams) {
if params.CommitOffChainConfig == nil {
params.CommitOffChainConfig = &pluginconfig.CommitOffchainConfig{
RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(RemoteGasPriceBatchWriteFrequency),
TokenPriceBatchWriteFrequency: *config.MustNewDuration(TokenPriceBatchWriteFrequency),
RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(globals.RemoteGasPriceBatchWriteFrequency),
TokenPriceBatchWriteFrequency: *config.MustNewDuration(globals.TokenPriceBatchWriteFrequency),
TokenInfo: tokenInfo,
PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel),
NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves,
Expand All @@ -246,12 +219,12 @@ func WithDefaultExecuteOffChainConfig(tokenDataObservers []pluginconfig.TokenDat
return func(params *CCIPOCRParams) {
if params.ExecuteOffChainConfig == nil {
params.ExecuteOffChainConfig = &pluginconfig.ExecuteOffchainConfig{
BatchGasLimit: BatchGasLimit,
RelativeBoostPerWaitHour: RelativeBoostPerWaitHour,
InflightCacheExpiry: *config.MustNewDuration(InflightCacheExpiry),
RootSnoozeTime: *config.MustNewDuration(RootSnoozeTime),
MessageVisibilityInterval: *config.MustNewDuration(FirstBlockAge),
BatchingStrategyID: BatchingStrategyID,
BatchGasLimit: globals.BatchGasLimit,
RelativeBoostPerWaitHour: globals.RelativeBoostPerWaitHour,
InflightCacheExpiry: *config.MustNewDuration(globals.InflightCacheExpiry),
RootSnoozeTime: *config.MustNewDuration(globals.RootSnoozeTime),
MessageVisibilityInterval: *config.MustNewDuration(globals.FirstBlockAge),
BatchingStrategyID: globals.BatchingStrategyID,
TokenDataObservers: tokenDataObservers,
}
} else if tokenDataObservers != nil {
Expand All @@ -266,18 +239,18 @@ func DeriveCCIPOCRParams(
) CCIPOCRParams {
params := CCIPOCRParams{
OCRParameters: commontypes.OCRParameters{
DeltaProgress: DeltaProgress,
DeltaResend: DeltaResend,
DeltaInitial: DeltaInitial,
DeltaRound: DeltaRound,
DeltaGrace: DeltaGrace,
DeltaCertifiedCommitRequest: DeltaCertifiedCommitRequest,
DeltaStage: DeltaStage,
Rmax: Rmax,
MaxDurationQuery: MaxDurationQuery,
MaxDurationObservation: MaxDurationObservation,
MaxDurationShouldAcceptAttestedReport: MaxDurationShouldAcceptAttestedReport,
MaxDurationShouldTransmitAcceptedReport: MaxDurationShouldTransmitAcceptedReport,
DeltaProgress: globals.DeltaProgress,
DeltaResend: globals.DeltaResend,
DeltaInitial: globals.DeltaInitial,
DeltaRound: globals.DeltaRound,
DeltaGrace: globals.DeltaGrace,
DeltaCertifiedCommitRequest: globals.DeltaCertifiedCommitRequest,
DeltaStage: globals.DeltaStage,
Rmax: globals.Rmax,
MaxDurationQuery: globals.MaxDurationQuery,
MaxDurationObservation: globals.MaxDurationObservation,
MaxDurationShouldAcceptAttestedReport: globals.MaxDurationShouldAcceptAttestedReport,
MaxDurationShouldTransmitAcceptedReport: globals.MaxDurationShouldTransmitAcceptedReport,
},
}
for _, opt := range opts {
Expand All @@ -289,8 +262,9 @@ func DeriveCCIPOCRParams(
type PromoteCandidatePluginInfo struct {
// RemoteChainSelectors is the chain selector of the DONs that we want to promote the candidate config of.
// Note that each (chain, ccip capability version) pair has a unique DON ID.
RemoteChainSelectors []uint64
PluginType types.PluginType
RemoteChainSelectors []uint64
PluginType types.PluginType
AllowEmptyConfigPromote bool // safe guard to prevent promoting empty config to active
}

type PromoteCandidateChangesetConfig struct {
Expand Down Expand Up @@ -356,7 +330,13 @@ func (p PromoteCandidateChangesetConfig) Validate(e deployment.Environment) (map
if err != nil {
return nil, fmt.Errorf("fetching %s configs from cciphome: %w", plugin.PluginType.String(), err)
}
// If promoteCandidate is called with AllowEmptyConfigPromote set to false and
// the CandidateConfig config digest is zero, do not promote the candidate config to active.
if !plugin.AllowEmptyConfigPromote && pluginConfigs.CandidateConfig.ConfigDigest == [32]byte{} {
return nil, fmt.Errorf("%s candidate config digest is empty", plugin.PluginType.String())
}

// If the active and candidate config digests are both zero, we should not promote the candidate config to active.
if pluginConfigs.ActiveConfig.ConfigDigest == [32]byte{} &&
pluginConfigs.CandidateConfig.ConfigDigest == [32]byte{} {
return nil, fmt.Errorf("%s active and candidate config digests are both zero", plugin.PluginType.String())
Expand Down Expand Up @@ -420,6 +400,7 @@ func PromoteCandidateChangeset(
nodes.NonBootstraps(),
donID,
plugin.PluginType,
plugin.AllowEmptyConfigPromote,
cfg.MCMS != nil,
)
if err != nil {
Expand Down Expand Up @@ -1019,6 +1000,7 @@ func promoteCandidateForChainOps(
nodes deployment.Nodes,
donID uint32,
pluginType cctypes.PluginType,
allowEmpty bool,
mcmsEnabled bool,
) (mcms.Operation, error) {
if donID == 0 {
Expand All @@ -1028,6 +1010,9 @@ func promoteCandidateForChainOps(
if err != nil {
return mcms.Operation{}, err
}
if digest == [32]byte{} && !allowEmpty {
return mcms.Operation{}, errors.New("candidate config digest is zero, promoting empty config is not allowed")
}
fmt.Println("Promoting candidate for plugin", pluginType.String(), "with digest", digest)
updatePluginOp, err := promoteCandidateOp(
txOpts,
Expand Down
12 changes: 7 additions & 5 deletions deployment/ccip/changeset/cs_ccip_home_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
"github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
Expand Down Expand Up @@ -161,8 +162,9 @@ func Test_PromoteCandidate(t *testing.T) {
HomeChainSelector: tenv.HomeChainSel,
PluginInfo: []changeset.PromoteCandidatePluginInfo{
{
RemoteChainSelectors: []uint64{dest},
PluginType: types.PluginTypeCCIPCommit,
RemoteChainSelectors: []uint64{dest},
PluginType: types.PluginTypeCCIPCommit,
AllowEmptyConfigPromote: true,
},
},
MCMS: mcmsConfig,
Expand Down Expand Up @@ -562,9 +564,9 @@ func Test_UpdateChainConfigs(t *testing.T) {
RemoteChainAdds: map[uint64]changeset.ChainConfig{
otherChain: {
EncodableChainConfig: chainconfig.ChainConfig{
GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(changeset.GasPriceDeviationPPB)},
DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(changeset.DAGasPriceDeviationPPB)},
OptimisticConfirmations: changeset.OptimisticConfirmations,
GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.GasPriceDeviationPPB)},
DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.DAGasPriceDeviationPPB)},
OptimisticConfirmations: globals.OptimisticConfirmations,
},
FChain: otherChainConfig.FChain,
Readers: otherChainConfig.Readers,
Expand Down
15 changes: 11 additions & 4 deletions deployment/ccip/changeset/cs_chain_contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/logger"

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal"
commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset"
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
Expand Down Expand Up @@ -942,9 +943,10 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC
}

type SetOCR3OffRampConfig struct {
HomeChainSel uint64
RemoteChainSels []uint64
MCMS *MCMSConfig
HomeChainSel uint64
RemoteChainSels []uint64
CCIPHomeConfigType globals.ConfigType
MCMS *MCMSConfig
}

func (c SetOCR3OffRampConfig) Validate(e deployment.Environment) error {
Expand All @@ -955,6 +957,10 @@ func (c SetOCR3OffRampConfig) Validate(e deployment.Environment) error {
if _, ok := state.Chains[c.HomeChainSel]; !ok {
return fmt.Errorf("home chain %d not found in onchain state", c.HomeChainSel)
}
if c.CCIPHomeConfigType != globals.ConfigTypeActive &&
c.CCIPHomeConfigType != globals.ConfigTypeCandidate {
return fmt.Errorf("invalid CCIPHomeConfigType should be either %s or %s", globals.ConfigTypeActive, globals.ConfigTypeCandidate)
}
for _, remote := range c.RemoteChainSels {
chainState, ok := state.Chains[remote]
if !ok {
Expand Down Expand Up @@ -989,7 +995,8 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig)
state.Chains[cfg.HomeChainSel].CapabilityRegistry,
state.Chains[cfg.HomeChainSel].CCIPHome,
remote)
args, err := internal.BuildSetOCR3ConfigArgs(donID, state.Chains[cfg.HomeChainSel].CCIPHome, remote)
args, err := internal.BuildSetOCR3ConfigArgs(
donID, state.Chains[cfg.HomeChainSel].CCIPHome, remote, cfg.CCIPHomeConfigType)
if err != nil {
return deployment.ChangesetOutput{}, err
}
Expand Down
Loading

0 comments on commit 5e404d2

Please sign in to comment.