Skip to content

Commit 5545293

Browse files
authored
Make config import available for only existing chains during deployment (#1889)
* remove unsupported method * making import config available for only existing chains * register laneversion resolver * add supported chain method * fixing test
1 parent e1e6583 commit 5545293

6 files changed

Lines changed: 114 additions & 70 deletions

File tree

ccv/chains/evm/deployment/v1_7_0/adapters/init.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func init() {
3434
ccvadapters.GetVerifierJobConfigRegistry().Register(chainsel.FamilyEVM, &EVMVerifierJobConfigAdapter{})
3535
ccvadapters.GetDeployChainContractsRegistry().Register(chainsel.FamilyEVM, &EVMDeployChainContractsAdapter{})
3636
ccvadapters.GetDeployChainContractsRegistry().RegisterConfigImporter(chainsel.FamilyEVM, semver.MustParse("1.6.0"), &adapters1_6.ConfigImportAdapter{})
37+
ccvadapters.GetDeployChainContractsRegistry().RegisterLaneVersionResolver(chainsel.FamilyEVM, &adapters1_2.LaneVersionResolver{})
3738
ccvadapters.GetIndexerConfigRegistry().Register(chainsel.FamilyEVM, &EVMIndexerConfigAdapter{})
3839
ccvadapters.GetAggregatorConfigRegistry().Register(chainsel.FamilyEVM, &EVMAggregatorConfigAdapter{})
3940
ccvadapters.GetTokenVerifierConfigRegistry().Register(chainsel.FamilyEVM, &EVMTokenVerifierConfigAdapter{})

chains/evm/deployment/v1_2_0/adapters/laneversionresolver.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import (
77
"github.com/Masterminds/semver/v3"
88
"github.com/ethereum/go-ethereum/accounts/abi/bind"
99
"github.com/ethereum/go-ethereum/common"
10-
"github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router"
10+
chain_selectors "github.com/smartcontractkit/chain-selectors"
1111
"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
1212
"github.com/smartcontractkit/chainlink-deployments-framework/datastore"
1313
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
1414

15+
"github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router"
16+
1517
"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/utils"
1618
evm_datastore_utils "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/utils/datastore"
1719
routerops "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_2_0/operations/router"
@@ -20,6 +22,22 @@ import (
2022

2123
type LaneVersionResolver struct{}
2224

25+
func (r *LaneVersionResolver) IsSupportedChain(e cldf.Environment, chainSel uint64) bool {
26+
family, err := chain_selectors.GetSelectorFamily(chainSel)
27+
if err != nil || family != chain_selectors.FamilyEVM {
28+
return false
29+
}
30+
_, err = datastore_utils.FindAndFormatRef(e.DataStore, datastore.AddressRef{
31+
Type: datastore.ContractType(routerops.ContractType),
32+
Version: routerops.Version,
33+
ChainSelector: chainSel,
34+
}, chainSel, evm_datastore_utils.ToEVMAddress)
35+
if err != nil {
36+
return false
37+
}
38+
return true
39+
}
40+
2341
// DeriveLaneVersionsForChain derives the versions of the lanes for a given chain by looking at the router's offramps and onramps.
2442
// It returns a map of remote chain selector to lane version, a list of unique lane versions, and an error if any.
2543
func (r *LaneVersionResolver) DeriveLaneVersionsForChain(e cldf.Environment, chainSel uint64) (map[uint64]*semver.Version, []*semver.Version, error) {

deployment/deploy/product.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,7 @@ type ConfigImporter interface {
108108
// For example - in case of EVM chains, we can look at the onramps and offramps connected to the router to determine
109109
// which version of the lane is deployed for each remote chain.
110110
type LaneVersionResolver interface {
111+
// IsSupportedChain checks if the given chain selector corresponds to a chain that is supported by this lane version resolver.
112+
IsSupportedChain(e cldf.Environment, chainSel uint64) bool
111113
DeriveLaneVersionsForChain(e cldf.Environment, chainSel uint64) (map[uint64]*semver.Version, []*semver.Version, error)
112114
}

deployment/v1_7_0/adapters/deploy_chain_contracts.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ type DeployChainContractsAdapter interface {
123123
}
124124

125125
type DeployChainContractsRegistry struct {
126-
mu sync.Mutex
127-
adapters map[string]DeployChainContractsAdapter
128-
configImporters map[string]deploy.ConfigImporter
126+
mu sync.Mutex
127+
adapters map[string]DeployChainContractsAdapter
128+
configImporters map[string]deploy.ConfigImporter
129+
laneVersionResolver map[string]deploy.LaneVersionResolver
129130
}
130131

131132
var (
@@ -135,8 +136,9 @@ var (
135136

136137
func NewDeployChainContractsRegistry() *DeployChainContractsRegistry {
137138
return &DeployChainContractsRegistry{
138-
adapters: make(map[string]DeployChainContractsAdapter),
139-
configImporters: make(map[string]deploy.ConfigImporter),
139+
adapters: make(map[string]DeployChainContractsAdapter),
140+
configImporters: make(map[string]deploy.ConfigImporter),
141+
laneVersionResolver: make(map[string]deploy.LaneVersionResolver),
140142
}
141143
}
142144

@@ -164,6 +166,25 @@ func (r *DeployChainContractsRegistry) RegisterConfigImporter(family string, ver
164166
}
165167
}
166168

169+
func (r *DeployChainContractsRegistry) RegisterLaneVersionResolver(family string, resolver deploy.LaneVersionResolver) {
170+
r.mu.Lock()
171+
defer r.mu.Unlock()
172+
if _, exists := r.laneVersionResolver[family]; !exists {
173+
r.laneVersionResolver[family] = resolver
174+
}
175+
}
176+
177+
func (r *DeployChainContractsRegistry) GetLaneVersionResolver(sel uint64) (deploy.LaneVersionResolver, bool) {
178+
family, err := chainsel.GetSelectorFamily(sel)
179+
if err != nil {
180+
return nil, false
181+
}
182+
r.mu.Lock()
183+
defer r.mu.Unlock()
184+
resolver, ok := r.laneVersionResolver[family]
185+
return resolver, ok
186+
}
187+
167188
func (r *DeployChainContractsRegistry) Get(family string) (DeployChainContractsAdapter, bool) {
168189
r.mu.Lock()
169190
defer r.mu.Unlock()

deployment/v1_7_0/changesets/deploy_chain_contracts.go

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -137,38 +137,44 @@ func DeployChainContracts(registry *adapters.DeployChainContractsRegistry) deplo
137137
},
138138
}
139139
if !cfg.Cfg.IgnoreImportedConfigFromPreviousVersion {
140-
// so far we do not need any config from 1.5.0 , so only importing config from 1.6.0
141-
// if in the future we need to import some config from 1.5.0,
142-
// we should leverage lane version resolver to get the right adapter to import config
143-
version := semver.MustParse("1.6.0")
144-
configImporter, ok := registry.GetConfigImporter(sel, version)
145-
if !ok {
146-
return deployment.ChangesetOutput{}, utils.ErrNoAdapterForSelectorRegistered("ConfigImporter", sel, version)
147-
}
148-
populateCfgOutput, err := deploy.PopulateMetaDataFromConfigImporter(e, configImporter, sel)
140+
importNeeded, err := shouldImportConfigFromPreviousVersion(e, registry, sel)
149141
if err != nil {
150-
return deployment.ChangesetOutput{}, fmt.Errorf("failed to populate metadata from config importer for chain %d: %w", sel, err)
142+
return deployment.ChangesetOutput{}, fmt.Errorf("failed to check if config import from previous version is needed for chain %d: %w", sel, err)
151143
}
152-
// if the importer found config from previous version,
153-
// import it and merge it with the input config, giving precedence to the imported config
154-
if len(populateCfgOutput.Metadata.Contracts) > 0 {
155-
importReport, err := operations.ExecuteSequence(
156-
e.OperationsBundle,
157-
adapter.SetContractParamsFromImportedConfig(),
158-
e.BlockChains, adapters.DeployChainConfigCreatorInput{
159-
ChainSelector: sel,
160-
ContractMeta: populateCfgOutput.Metadata.Contracts,
161-
ExistingAddresses: existingAddresses,
162-
UserProvidedConfig: input.ContractParams,
163-
})
164-
if err != nil {
165-
return deployment.ChangesetOutput{Reports: allReports},
166-
fmt.Errorf("failed to execute config importer sequence for chain %d: %w", sel, err)
144+
if importNeeded {
145+
// so far we do not need any config from 1.5.0 , so only importing config from 1.6.0
146+
// if in the future we need to import some config from 1.5.0,
147+
// we should leverage lane version resolver to get the right adapter to import config
148+
version := semver.MustParse("1.6.0")
149+
configImporter, ok := registry.GetConfigImporter(sel, version)
150+
if !ok {
151+
return deployment.ChangesetOutput{}, utils.ErrNoAdapterForSelectorRegistered("ConfigImporter", sel, version)
167152
}
168-
allReports = append(allReports, importReport.ExecutionReports...)
169-
input.ContractParams, err = input.ContractParams.MergeWithOverrideIfNotEmpty(importReport.Output)
153+
populateCfgOutput, err := deploy.PopulateMetaDataFromConfigImporter(e, configImporter, sel)
170154
if err != nil {
171-
return deployment.ChangesetOutput{}, fmt.Errorf("failed to merge imported config with input config for chain %d: %w", sel, err)
155+
return deployment.ChangesetOutput{}, fmt.Errorf("failed to populate metadata from config importer for chain %d: %w", sel, err)
156+
}
157+
// if the importer found config from previous version,
158+
// import it and merge it with the input config, giving precedence to the imported config
159+
if len(populateCfgOutput.Metadata.Contracts) > 0 {
160+
importReport, err := operations.ExecuteSequence(
161+
e.OperationsBundle,
162+
adapter.SetContractParamsFromImportedConfig(),
163+
e.BlockChains, adapters.DeployChainConfigCreatorInput{
164+
ChainSelector: sel,
165+
ContractMeta: populateCfgOutput.Metadata.Contracts,
166+
ExistingAddresses: existingAddresses,
167+
UserProvidedConfig: input.ContractParams,
168+
})
169+
if err != nil {
170+
return deployment.ChangesetOutput{Reports: allReports},
171+
fmt.Errorf("failed to execute config importer sequence for chain %d: %w", sel, err)
172+
}
173+
allReports = append(allReports, importReport.ExecutionReports...)
174+
input.ContractParams, err = input.ContractParams.MergeWithOverrideIfNotEmpty(importReport.Output)
175+
if err != nil {
176+
return deployment.ChangesetOutput{}, fmt.Errorf("failed to merge imported config with input config for chain %d: %w", sel, err)
177+
}
172178
}
173179
}
174180
}
@@ -263,3 +269,26 @@ func BuildCommitteeVerifierParams(
263269

264270
return params, nil
265271
}
272+
273+
// shouldImportConfigFromPreviousVersion checks if any of the lanes connected to the given chain selector are using version 1.6.0,
274+
// if so, it returns true, indicating that we should import config from previous version, otherwise it returns false
275+
func shouldImportConfigFromPreviousVersion(e deployment.Environment, registry *adapters.DeployChainContractsRegistry, sel uint64) (bool, error) {
276+
res, exists := registry.GetLaneVersionResolver(sel)
277+
if !exists {
278+
return false, fmt.Errorf("no lane version resolver registered for chain %d", sel)
279+
}
280+
if !res.IsSupportedChain(e, sel) {
281+
return false, nil
282+
}
283+
_, versions, err := res.DeriveLaneVersionsForChain(e, sel)
284+
if err != nil {
285+
return false, fmt.Errorf("failed to derive lane versions for chain %d: %w", sel, err)
286+
}
287+
reqVersion := semver.MustParse("1.6.0")
288+
for _, v := range versions {
289+
if v.Equal(reqVersion) {
290+
return true, nil
291+
}
292+
}
293+
return false, nil
294+
}

deployment/v1_7_0/changesets/deploy_chain_contracts_test.go

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ type mockDeployAdapter struct {
3535
errByChain map[uint64]error
3636
}
3737

38+
func (m *mockDeployAdapter) IsSupportedChain(_ deployment.Environment, _ uint64) bool {
39+
return false
40+
}
41+
42+
func (m *mockDeployAdapter) DeriveLaneVersionsForChain(_ deployment.Environment, _ uint64) (map[uint64]*semver.Version, []*semver.Version, error) {
43+
return map[uint64]*semver.Version{}, []*semver.Version{}, nil
44+
}
45+
3846
func (m *mockDeployAdapter) InitializeAdapter(_ deployment.Environment, _ uint64) error {
3947
return nil
4048
}
@@ -285,41 +293,6 @@ func TestDeployChainContracts_Validate(t *testing.T) {
285293
}
286294
}
287295

288-
func TestDeployChainContracts_With_MissingAdapterForConfigImport(t *testing.T) {
289-
sel1 := chainsel.TEST_90000001.Selector
290-
env := newDeployTestEnv(t, []uint64{sel1})
291-
292-
expectedAddr := datastore.AddressRef{
293-
ChainSelector: sel1,
294-
Type: "TestContract",
295-
Version: semver.MustParse("2.0.0"),
296-
Address: "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
297-
}
298-
299-
mock := &mockDeployAdapter{
300-
outputByChain: map[uint64]sequences.OnChainOutput{
301-
sel1: {
302-
Addresses: []datastore.AddressRef{expectedAddr},
303-
},
304-
},
305-
}
306-
307-
registry := adapters.NewDeployChainContractsRegistry()
308-
registry.Register(chainsel.FamilyEVM, mock)
309-
310-
cs := changesets.DeployChainContracts(registry)
311-
_, err := cs.Apply(env, cs_core.WithMCMS[changesets.DeployChainContractsCfg]{
312-
MCMS: mcms.Input{},
313-
Cfg: changesets.DeployChainContractsCfg{
314-
Topology: newDeployTestTopology(sel1),
315-
ChainSelectors: []uint64{sel1},
316-
DefaultCfg: newDefaultPerChainCfg(),
317-
},
318-
})
319-
require.Error(t, err)
320-
require.Contains(t, err.Error(), "no ConfigImporter adapter registered")
321-
}
322-
323296
func TestDeployChainContracts_With_DummyConfigImport(t *testing.T) {
324297
sel1 := chainsel.TEST_90000001.Selector
325298
env := newDeployTestEnv(t, []uint64{sel1})
@@ -334,7 +307,7 @@ func TestDeployChainContracts_With_DummyConfigImport(t *testing.T) {
334307
}
335308
registry := adapters.NewDeployChainContractsRegistry()
336309
registry.Register(chainsel.FamilyEVM, mock)
337-
registry.RegisterConfigImporter(chainsel.FamilyEVM, semver.MustParse("1.6.0"), &mockDeployAdapter{})
310+
registry.RegisterLaneVersionResolver(chainsel.FamilyEVM, mock)
338311

339312
cs := changesets.DeployChainContracts(registry)
340313
_, err := cs.Apply(env, cs_core.WithMCMS[changesets.DeployChainContractsCfg]{

0 commit comments

Comments
 (0)