From d90024c9a19615b08086b4311234b4542ac8042c Mon Sep 17 00:00:00 2001 From: Gustavo Gama Date: Tue, 18 Feb 2025 02:04:18 -0300 Subject: [PATCH] chore(deployment): migrate changesets from cs_ccip_home to new mcms lib --- deployment/ccip/changeset/cs_ccip_home.go | 277 +++++++++++----------- 1 file changed, 143 insertions(+), 134 deletions(-) diff --git a/deployment/ccip/changeset/cs_ccip_home.go b/deployment/ccip/changeset/cs_ccip_home.go index 0922b526e5a..b8aae8e8232 100644 --- a/deployment/ccip/changeset/cs_ccip_home.go +++ b/deployment/ccip/changeset/cs_ccip_home.go @@ -10,11 +10,13 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "golang.org/x/exp/maps" + mcmslib "github.com/smartcontractkit/mcms" + mcmssdk "github.com/smartcontractkit/mcms/sdk" + mcmsevmsdk "github.com/smartcontractkit/mcms/sdk/evm" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" @@ -388,7 +390,7 @@ func PromoteCandidateChangeset( homeChain := e.Chains[cfg.HomeChainSelector] - var ops []mcms.Operation + var mcmsTxs []mcmstypes.Transaction for _, plugin := range cfg.PluginInfo { for _, donID := range donIDs { promoteCandidateOps, err := promoteCandidateForChainOps( @@ -403,9 +405,9 @@ func PromoteCandidateChangeset( cfg.MCMS != nil, ) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("generating promote candidate ops: %w", err) + return deployment.ChangesetOutput{}, fmt.Errorf("generating promote candidate mcms txs: %w", err) } - ops = append(ops, promoteCandidateOps) + mcmsTxs = append(mcmsTxs, promoteCandidateOps) } } @@ -414,28 +416,25 @@ func PromoteCandidateChangeset( return deployment.ChangesetOutput{}, nil } - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: ops, - }}, + timelocks := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address().Hex()} + proposers := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm.Address().Hex()} + inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} + batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: mcmsTxs}} + + prop, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), + timelocks, + proposers, + inspectors, + batches, "promoteCandidate", cfg.MCMS.MinDelay, ) if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*prop}}, nil } type SetCandidatePluginInfo struct { @@ -615,7 +614,7 @@ func AddDonAndSetCandidateChangeset( if cfg.MCMS != nil { txOpts = deployment.SimTransactOpts() } - var donOps []mcms.Operation + var donMcmsTxs []mcmstypes.Transaction for chainSelector, params := range cfg.PluginInfo.OCRConfigPerRemoteChainSelector { offRampAddress, err := state.GetOffRampAddress(chainSelector) if err != nil { @@ -660,23 +659,23 @@ func AddDonAndSetCandidateChangeset( if err != nil { return deployment.ChangesetOutput{}, err } - donOps = append(donOps, addDonOp) + donMcmsTxs = append(donMcmsTxs, addDonOp) } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: donOps, - }}, + timelocks := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address().Hex()} + proposers := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm.Address().Hex()} + inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} + batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: donMcmsTxs}} + + prop, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), + timelocks, + proposers, + inspectors, + batches, "addDON on new Chain && setCandidate for plugin "+cfg.PluginInfo.PluginType.String(), cfg.MCMS.MinDelay, ) @@ -684,9 +683,7 @@ func AddDonAndSetCandidateChangeset( return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w", err) } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*prop}}, nil } // newDonWithCandidateOp sets the candidate commit config by calling setCandidate on CCIPHome contract through the AddDON call on CapReg contract @@ -700,7 +697,7 @@ func newDonWithCandidateOp( capReg *capabilities_registry.CapabilitiesRegistry, nodes deployment.Nodes, mcmsEnabled bool, -) (mcms.Operation, error) { +) (mcmstypes.Transaction, error) { encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( "setCandidate", donID, @@ -709,7 +706,7 @@ func newDonWithCandidateOp( [32]byte{}, ) if err != nil { - return mcms.Operation{}, fmt.Errorf("pack set candidate call: %w", err) + return mcmstypes.Transaction{}, fmt.Errorf("pack set candidate call: %w", err) } addDonTx, err := capReg.AddDON( @@ -725,22 +722,27 @@ func newDonWithCandidateOp( false, // acceptsWorkflows nodes.DefaultF(), ) + if err != nil { + return mcmstypes.Transaction{}, fmt.Errorf("failed to call AddDON (ptype: %s): %w", + types.PluginType(pluginConfig.PluginType).String(), err) + } + if !mcmsEnabled { _, err = deployment.ConfirmIfNoErrorWithABI( homeChain, addDonTx, ccip_home.CCIPHomeABI, err) if err != nil { - return mcms.Operation{}, fmt.Errorf("error confirming addDon call: %w", err) + return mcmstypes.Transaction{}, fmt.Errorf("error confirming addDon call: %w", err) } } + + tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), addDonTx.Data(), + big.NewInt(0), string(CapabilitiesRegistry), []string{}) if err != nil { - return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ %s config: %w", - types.PluginType(pluginConfig.PluginType).String(), err) + return mcmstypes.Transaction{}, fmt.Errorf("failed to create AddDON mcms tx (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginConfig.PluginType).String(), err) } - return mcms.Operation{ - To: capReg.Address(), - Data: addDonTx.Data(), - Value: big.NewInt(0), - }, nil + + return tx, nil } type SetCandidateChangesetConfig struct { @@ -804,7 +806,7 @@ func SetCandidateChangeset( if cfg.MCMS != nil { txOpts = deployment.SimTransactOpts() } - var setCandidateOps []mcms.Operation + var setCandidateMcmsTxs []mcmstypes.Transaction pluginInfos := make([]string, 0) for _, plugin := range cfg.PluginInfo { pluginInfos = append(pluginInfos, plugin.String()) @@ -845,35 +847,32 @@ func SetCandidateChangeset( if err != nil { return deployment.ChangesetOutput{}, err } - setCandidateOps = append(setCandidateOps, setCandidateMCMSOps...) + setCandidateMcmsTxs = append(setCandidateMcmsTxs, setCandidateMCMSOps...) } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: setCandidateOps, - }}, + timelocks := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address().Hex()} + proposers := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm.Address().Hex()} + inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} + batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: setCandidateMcmsTxs}} + + prop, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), + timelocks, + proposers, + inspectors, + batches, fmt.Sprintf("SetCandidate for plugin details %v", pluginInfos), cfg.MCMS.MinDelay, ) if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*prop}}, nil } // setCandidateOnExistingDon calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract @@ -886,7 +885,7 @@ func setCandidateOnExistingDon( donID uint32, pluginConfig ccip_home.CCIPHomeOCR3Config, mcmsEnabled bool, -) ([]mcms.Operation, error) { +) ([]mcmstypes.Transaction, error) { if donID == 0 { return nil, errors.New("donID is zero") } @@ -916,21 +915,27 @@ func setCandidateOnExistingDon( false, nodes.DefaultF(), ) + if err != nil { + return nil, fmt.Errorf("failed to call UpdateDON in set candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginConfig.PluginType).String(), err) + } + if !mcmsEnabled { _, err = deployment.ConfirmIfNoErrorWithABI( homeChain, updateDonTx, ccip_home.CCIPHomeABI, err) if err != nil { - return nil, fmt.Errorf("error confirming updateDon call: %w", err) + return nil, fmt.Errorf("error confirming UpdateDON call in set candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginConfig.PluginType).String(), err) } } + + tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), updateDonTx.Data(), big.NewInt(0), string(CapabilitiesRegistry), []string{}) if err != nil { - return nil, fmt.Errorf("update don w/ setCandidate call: %w", err) + return nil, fmt.Errorf("failed to create UpdateDON mcms tx in set candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginConfig.PluginType).String(), err) } - return []mcms.Operation{{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }}, nil + + return []mcmstypes.Transaction{tx}, nil } // promoteCandidateOp will create the MCMS Operation for `promoteCandidateAndRevokeActive` directed towards the capabilityRegistry @@ -943,10 +948,10 @@ func promoteCandidateOp( donID uint32, pluginType uint8, mcmsEnabled bool, -) (mcms.Operation, error) { +) (mcmstypes.Transaction, error) { allConfigs, err := ccipHome.GetAllConfigs(nil, donID, pluginType) if err != nil { - return mcms.Operation{}, err + return mcmstypes.Transaction{}, err } encodedPromotionCall, err := internal.CCIPHomeABI.Pack( @@ -957,7 +962,7 @@ func promoteCandidateOp( allConfigs.ActiveConfig.ConfigDigest, ) if err != nil { - return mcms.Operation{}, fmt.Errorf("pack promotion call: %w", err) + return mcmstypes.Transaction{}, fmt.Errorf("pack promotion call: %w", err) } updateDonTx, err := capReg.UpdateDON( @@ -973,23 +978,28 @@ func promoteCandidateOp( false, nodes.DefaultF(), ) + if err != nil { + return mcmstypes.Transaction{}, fmt.Errorf("failed to call UpdateDON in promote candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginType).String(), err) + } + if !mcmsEnabled { _, err = deployment.ConfirmIfNoErrorWithABI( homeChain, updateDonTx, ccip_home.CCIPHomeABI, err) if err != nil { - return mcms.Operation{}, - fmt.Errorf("error confirming updateDon call for donID(%d) and plugin type (%d): %w", donID, pluginType, err) + return mcmstypes.Transaction{}, fmt.Errorf("error confirming UpdateDON call in promote candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginType).String(), err) } } + + tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), updateDonTx.Data(), + big.NewInt(0), string(CapabilitiesRegistry), []string{}) if err != nil { - return mcms.Operation{}, fmt.Errorf("error creating updateDon op for donID(%d) and plugin type (%s): %w", + return mcmstypes.Transaction{}, fmt.Errorf("failed to create UpdateDON mcms tx in promote candidate (don: %d; ptype: %s): %w", donID, types.PluginType(pluginType).String(), err) } - return mcms.Operation{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }, nil + + return tx, nil } // promoteCandidateForChainOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract @@ -1003,16 +1013,16 @@ func promoteCandidateForChainOps( pluginType cctypes.PluginType, allowEmpty bool, mcmsEnabled bool, -) (mcms.Operation, error) { +) (mcmstypes.Transaction, error) { if donID == 0 { - return mcms.Operation{}, errors.New("donID is zero") + return mcmstypes.Transaction{}, errors.New("donID is zero") } digest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(pluginType)) if err != nil { - return mcms.Operation{}, err + return mcmstypes.Transaction{}, err } if digest == [32]byte{} && !allowEmpty { - return mcms.Operation{}, errors.New("candidate config digest is zero, promoting empty config is not allowed") + return mcmstypes.Transaction{}, 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( @@ -1026,7 +1036,7 @@ func promoteCandidateForChainOps( mcmsEnabled, ) if err != nil { - return mcms.Operation{}, fmt.Errorf("promote candidate op for plugin %s: %w", pluginType.String(), err) + return mcmstypes.Transaction{}, fmt.Errorf("promote candidate op for plugin %s: %w", pluginType.String(), err) } return updatePluginOp, nil } @@ -1132,17 +1142,17 @@ func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChang return deployment.ChangesetOutput{}, nil } - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: ops, - }}, + timelocks := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address().Hex()} + proposers := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm.Address().Hex()} + inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} + batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: ops}} + + prop, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), + timelocks, + proposers, + inspectors, + batches, fmt.Sprintf("revokeCandidate for don %d", cfg.RemoteChainSelector), cfg.MCMS.MinDelay, ) @@ -1150,11 +1160,7 @@ func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChang return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*prop}}, nil } func revokeCandidateOps( @@ -1166,7 +1172,7 @@ func revokeCandidateOps( donID uint32, pluginType uint8, mcmsEnabled bool, -) ([]mcms.Operation, error) { +) ([]mcmstypes.Transaction, error) { if donID == 0 { return nil, errors.New("donID is zero") } @@ -1200,22 +1206,28 @@ func revokeCandidateOps( nodes.DefaultF(), ) if err != nil { - return nil, fmt.Errorf("update don w/ revokeCandidate call: %w", deployment.MaybeDataErr(err)) + return nil, fmt.Errorf("failed to call UpdateDON in revoke candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginType).String(), err) } + if !mcmsEnabled { _, err = deployment.ConfirmIfNoErrorWithABI( homeChain, updateDonTx, capabilities_registry.CapabilitiesRegistryABI, err) if err != nil { - return nil, fmt.Errorf("error confirming updateDon call: %w", err) + return nil, fmt.Errorf("error confirming UpdateDON call in revoke candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginType).String(), err) } } - return []mcms.Operation{{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }}, nil + tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), updateDonTx.Data(), + big.NewInt(0), string(CapabilitiesRegistry), []string{}) + if err != nil { + return nil, fmt.Errorf("failed to create UpdateDON mcms tx in revoke candidate (don: %d; ptype: %s): %w", + donID, types.PluginType(pluginType).String(), err) + } + + return []mcmstypes.Transaction{tx}, nil } type ChainConfig struct { @@ -1332,33 +1344,30 @@ func UpdateChainConfigChangeset(e deployment.Environment, cfg UpdateChainConfigC return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: []mcms.Operation{ - { - To: state.Chains[cfg.HomeChainSelector].CCIPHome.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }}, + timelocks := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address().Hex()} + proposers := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm.Address().Hex()} + inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} + batchOp, err := proposalutils.BatchOperationForChain(cfg.HomeChainSelector, state.Chains[cfg.HomeChainSelector].CCIPHome.Address().Hex(), + tx.Data(), big.NewInt(0), string(CCIPHome), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create batch operation: %w", err) + } + + prop, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), + timelocks, + proposers, + inspectors, + []mcmstypes.BatchOperation{batchOp}, "Update chain config", cfg.MCMS.MinDelay, ) if err != nil { return deployment.ChangesetOutput{}, err } + e.Logger.Infof("Proposed chain config update on chain %d removes %v, adds %v", cfg.HomeChainSelector, cfg.RemoteChainRemoves, cfg.RemoteChainAdds) - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*prop}}, nil } func isChainConfigEqual(a, b ccip_home.CCIPHomeChainConfig) bool {