Skip to content

Commit

Permalink
deployment/ccip/changeset: mcms optional ccip home cses (#15658)
Browse files Browse the repository at this point in the history
* deployment/ccip/changeset: mcms optional ccip home cses

Add MCMS optionality for the rest of the CCIPHome changesets, and
organize things a little bit better by moving the AddDON changeset into
cs_ccip_home.go out of cs_add_chain.go

* fixes

* pr comments

* one more comment

* fix logger
  • Loading branch information
makramkd authored Dec 12, 2024
1 parent 52c2db4 commit 7a5e54c
Show file tree
Hide file tree
Showing 6 changed files with 489 additions and 247 deletions.
4 changes: 2 additions & 2 deletions deployment/ccip/changeset/accept_ownership_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) {
dest := allChains[1]

timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{
source: &proposalutils.TimelockExecutionContracts{
source: {
Timelock: state.Chains[source].Timelock,
CallProxy: state.Chains[source].CallProxy,
},
dest: &proposalutils.TimelockExecutionContracts{
dest: {
Timelock: state.Chains[dest].Timelock,
CallProxy: state.Chains[dest].CallProxy,
},
Expand Down
170 changes: 1 addition & 169 deletions deployment/ccip/changeset/cs_add_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@ import (

"github.com/smartcontractkit/chainlink-ccip/chainconfig"
"github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"

"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal"
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
"github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"

"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"

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
)
Expand Down Expand Up @@ -136,135 +132,6 @@ func NewChainInboundChangeset(
}, nil
}

type AddDonAndSetCandidateChangesetConfig struct {
HomeChainSelector uint64
FeedChainSelector uint64
NewChainSelector uint64
PluginType types.PluginType
NodeIDs []string
CCIPOCRParams CCIPOCRParams
}

func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (deployment.Nodes, error) {
if a.HomeChainSelector == 0 {
return nil, fmt.Errorf("HomeChainSelector must be set")
}
if a.FeedChainSelector == 0 {
return nil, fmt.Errorf("FeedChainSelector must be set")
}
if a.NewChainSelector == 0 {
return nil, fmt.Errorf("ocr config chain selector must be set")
}
if a.PluginType != types.PluginTypeCCIPCommit &&
a.PluginType != types.PluginTypeCCIPExec {
return nil, fmt.Errorf("PluginType must be set to either CCIPCommit or CCIPExec")
}
// TODO: validate token config
if len(a.NodeIDs) == 0 {
return nil, fmt.Errorf("nodeIDs must be set")
}
nodes, err := deployment.NodeInfo(a.NodeIDs, e.Offchain)
if err != nil {
return nil, fmt.Errorf("get node info: %w", err)
}

// check that chain config is set up for the new chain
chainConfig, err := state.Chains[a.HomeChainSelector].CCIPHome.GetChainConfig(nil, a.NewChainSelector)
if err != nil {
return nil, fmt.Errorf("get all chain configs: %w", err)
}

// FChain should never be zero if a chain config is set in CCIPHome
if chainConfig.FChain == 0 {
return nil, fmt.Errorf("chain config not set up for new chain %d", a.NewChainSelector)
}

err = a.CCIPOCRParams.Validate()
if err != nil {
return nil, fmt.Errorf("invalid ccip ocr params: %w", err)
}

if e.OCRSecrets.IsEmpty() {
return nil, fmt.Errorf("OCR secrets must be set")
}

return nodes, nil
}

// AddDonAndSetCandidateChangeset adds new DON for destination to home chain
// and sets the commit plugin config as candidateConfig for the don.
func AddDonAndSetCandidateChangeset(
e deployment.Environment,
cfg AddDonAndSetCandidateChangesetConfig,
) (deployment.ChangesetOutput, error) {
state, err := LoadOnchainState(e)
if err != nil {
return deployment.ChangesetOutput{}, err
}

nodes, err := cfg.Validate(e, state)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err)
}

newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome(
e.OCRSecrets,
state.Chains[cfg.NewChainSelector].OffRamp,
e.Chains[cfg.NewChainSelector],
nodes.NonBootstraps(),
state.Chains[cfg.HomeChainSelector].RMNHome.Address(),
cfg.CCIPOCRParams.OCRParameters,
cfg.CCIPOCRParams.CommitOffChainConfig,
cfg.CCIPOCRParams.ExecuteOffChainConfig,
)
if err != nil {
return deployment.ChangesetOutput{}, err
}
latestDon, err := internal.LatestCCIPDON(state.Chains[cfg.HomeChainSelector].CapabilityRegistry)
if err != nil {
return deployment.ChangesetOutput{}, err
}
commitConfig, ok := newDONArgs[cfg.PluginType]
if !ok {
return deployment.ChangesetOutput{}, fmt.Errorf("missing commit plugin in ocr3Configs")
}
donID := latestDon.Id + 1
addDonOp, err := newDonWithCandidateOp(
donID, commitConfig,
state.Chains[cfg.HomeChainSelector].CapabilityRegistry,
nodes.NonBootstraps(),
)
if err != nil {
return deployment.ChangesetOutput{}, err
}

var (
timelocksPerChain = map[uint64]common.Address{
cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(),
}
proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{
cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm,
}
)
prop, err := proposalutils.BuildProposalFromBatches(
timelocksPerChain,
proposerMCMSes,
[]timelock.BatchChainOperation{{
ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector),
Batch: []mcms.Operation{addDonOp},
}},
"setCandidate for commit and AddDon on new Chain",
0, // minDelay
)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w", err)
}

return deployment.ChangesetOutput{
Proposals: []timelock.MCMSWithTimelockProposal{*prop},
}, nil
}

func applyChainConfigUpdatesOp(
e deployment.Environment,
state CCIPOnChainState,
Expand Down Expand Up @@ -304,38 +171,3 @@ func applyChainConfigUpdatesOp(
Value: big.NewInt(0),
}, nil
}

// newDonWithCandidateOp sets the candidate commit config by calling setCandidate on CCIPHome contract through the AddDON call on CapReg contract
// This should be done first before calling any other UpdateDON calls
// This proposes to set up OCR3 config for the commit plugin for the DON
func newDonWithCandidateOp(
donID uint32,
pluginConfig ccip_home.CCIPHomeOCR3Config,
capReg *capabilities_registry.CapabilitiesRegistry,
nodes deployment.Nodes,
) (mcms.Operation, error) {
encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack(
"setCandidate",
donID,
pluginConfig.PluginType,
pluginConfig,
[32]byte{},
)
if err != nil {
return mcms.Operation{}, fmt.Errorf("pack set candidate call: %w", err)
}
addDonTx, err := capReg.AddDON(deployment.SimTransactOpts(), nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{
{
CapabilityId: internal.CCIPCapabilityID,
Config: encodedSetCandidateCall,
},
}, false, false, nodes.DefaultF())
if err != nil {
return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ commit config: %w", err)
}
return mcms.Operation{
To: capReg.Address(),
Data: addDonTx.Data(),
Value: big.NewInt(0),
}, nil
}
43 changes: 21 additions & 22 deletions deployment/ccip/changeset/cs_add_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,9 @@ func TestAddChainInbound(t *testing.T) {

assertTimelockOwnership(t, e, initialDeploy, state)

nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain)
require.NoError(t, err)

// TODO This currently is not working - Able to send the request here but request gets stuck in execution
// Send a new message and expect that this is delivered once the chain is completely set up as inbound
//TestSendRequest(t, e.Env, state, initialDeploy[0], newChain, true)
var nodeIDs []string
for _, node := range nodes {
nodeIDs = append(nodeIDs, node.NodeID)
}

_, err = commonchangeset.ApplyChangesets(t, e.Env, map[uint64]*proposalutils.TimelockExecutionContracts{
e.HomeChainSel: {
Expand All @@ -203,45 +196,51 @@ func TestAddChainInbound(t *testing.T) {
{
Changeset: commonchangeset.WrapChangeSet(AddDonAndSetCandidateChangeset),
Config: AddDonAndSetCandidateChangesetConfig{
HomeChainSelector: e.HomeChainSel,
FeedChainSelector: e.FeedChainSel,
NewChainSelector: newChain,
PluginType: types.PluginTypeCCIPCommit,
NodeIDs: nodeIDs,
CCIPOCRParams: DefaultOCRParams(
e.FeedChainSel,
tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9),
nil,
),
SetCandidateChangesetConfig: SetCandidateChangesetConfig{
HomeChainSelector: e.HomeChainSel,
FeedChainSelector: e.FeedChainSel,
DONChainSelector: newChain,
PluginType: types.PluginTypeCCIPCommit,
CCIPOCRParams: DefaultOCRParams(
e.FeedChainSel,
tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9),
nil,
),
MCMS: &MCMSConfig{
MinDelay: 0,
},
},
},
},
{
Changeset: commonchangeset.WrapChangeSet(SetCandidatePluginChangeset),
Config: AddDonAndSetCandidateChangesetConfig{
Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset),
Config: SetCandidateChangesetConfig{
HomeChainSelector: e.HomeChainSel,
FeedChainSelector: e.FeedChainSel,
NewChainSelector: newChain,
DONChainSelector: newChain,
PluginType: types.PluginTypeCCIPExec,
NodeIDs: nodeIDs,
CCIPOCRParams: DefaultOCRParams(
e.FeedChainSel,
tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9),
nil,
),
MCMS: &MCMSConfig{
MinDelay: 0,
},
},
},
{
Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset),
Config: PromoteAllCandidatesChangesetConfig{
HomeChainSelector: e.HomeChainSel,
DONChainSelector: newChain,
NodeIDs: nodeIDs,
MCMS: &MCMSConfig{
MinDelay: 0,
},
},
},
})
require.NoError(t, err)

// verify if the configs are updated
require.NoError(t, ValidateCCIPHomeConfigSetUp(
Expand Down
Loading

0 comments on commit 7a5e54c

Please sign in to comment.