Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deployment/ccip/changeset: add RevokeCandidate cs #15665

Merged
merged 10 commits into from
Dec 16, 2024
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 @@ -21,11 +21,11 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) {
dest := allChains[1]

timelockContracts := map[uint64]*commonchangeset.TimelockExecutionContracts{
source: &commonchangeset.TimelockExecutionContracts{
source: {
Timelock: state.Chains[source].Timelock,
CallProxy: state.Chains[source].CallProxy,
},
dest: &commonchangeset.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
}
35 changes: 22 additions & 13 deletions deployment/ccip/changeset/cs_add_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,31 +207,39 @@ 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,
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(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,
},
},
},
{
Expand All @@ -246,6 +254,7 @@ func TestAddChainInbound(t *testing.T) {
},
},
})
require.NoError(t, err)

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