Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 28 additions & 27 deletions deployment/v2_0_0/changesets/build_lanes_cross_family.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,28 @@ type ConfigureChainsForLanesFromTopologyConfig struct {
BuildLanesCrossFamilyConfig
}

// committeeQualifiersForLaneLeg returns the committee qualifiers that apply to the leg
// from local → remote. A committee applies only if both the local and remote chain
// selectors appear in its ChainConfigs — meaning the committee is configured for both
// sides of the lane. When committees is nil, the single default qualifier is returned.
func committeeQualifiersForLaneLeg(local, remote uint64, committees map[string]offchain.CommitteeConfig) ([]string, error) {
if committees == nil {
return []string{defaultQualifier}, nil
}
localKey := strconv.FormatUint(local, 10)
remoteKey := strconv.FormatUint(remote, 10)
qualifiers := make([]string, 0, len(committees))
for q, committee := range committees {
_, hasLocal := committee.ChainConfigs[localKey]
_, hasRemote := committee.ChainConfigs[remoteKey]
if hasLocal && hasRemote {
qualifiers = append(qualifiers, q)
}
}
sort.Strings(qualifiers)
return qualifiers, nil
}

// expandLanesToPartialChainConfigs converts bidirectional lane pairs into the internal
// chain-centric representation used by the changeset apply path.
func expandLanesToPartialChainConfigs(lanes []CrossFamilyLanePair, committees map[string]offchain.CommitteeConfig) ([]partialChainConfig, error) {
Expand All @@ -77,35 +99,14 @@ func expandLanesToPartialChainConfigs(lanes []CrossFamilyLanePair, committees ma
return nil, fmt.Errorf("lane %d: chainA and chainB must differ", i)
}
var qualifiers []string
remoteKey := strconv.FormatUint(lane.ChainB, 10)
for _, cvCfg := range committees {
if _, exists := cvCfg.ChainConfigs[remoteKey]; exists {
qualifiers = append(qualifiers, cvCfg.Qualifier)
}
}
sort.Strings(qualifiers)
if len(qualifiers) == 0 {
if len(committees) == 0 {
qualifiers = []string{defaultQualifier}
} else {
return nil, fmt.Errorf("lane %d: no committees have chain_config for remote chain %d", i, lane.ChainB)
}
qualifiers, err := committeeQualifiersForLaneLeg(lane.ChainA, lane.ChainB, committees)
if err != nil {
return nil, fmt.Errorf("lane %d: %w", i, err)
}
mergeLaneLeg(byChain, lane.ChainA, lane.ChainB, qualifiers, lane.ChainAOverrides)
qualifiers = nil
remoteKey = strconv.FormatUint(lane.ChainA, 10)
for _, cvCfg := range committees {
if _, exists := cvCfg.ChainConfigs[remoteKey]; exists {
qualifiers = append(qualifiers, cvCfg.Qualifier)
}
}
sort.Strings(qualifiers)
if len(qualifiers) == 0 {
if len(committees) == 0 {
qualifiers = []string{defaultQualifier}
} else {
return nil, fmt.Errorf("lane %d: no committees have chain_config for remote chain %d", i, lane.ChainA)
}
qualifiers, err = committeeQualifiersForLaneLeg(lane.ChainB, lane.ChainA, committees)
if err != nil {
return nil, fmt.Errorf("lane %d: %w", i, err)
}
mergeLaneLeg(byChain, lane.ChainB, lane.ChainA, qualifiers, lane.ChainBOverrides)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ func TestExpandLanesToPartialChainConfigs_MultipleCommittees(t *testing.T) {
assert.Contains(t, cfgB.CommitteeVerifiers[1].RemoteChains, chainA)
}

func TestExpandLanesToPartialChainConfigs_FiltersCommitteeQualifiersPerRemoteChain(t *testing.T) {
func TestExpandLanesToPartialChainConfigs_FiltersCommitteeQualifiersPerLaneLeg(t *testing.T) {
chainA := uint64(100)
chainB := uint64(200)

// alpha is on both chains; beta only on chainA; gamma only on chainB.
// Only alpha covers both sides of the lane, so it is the only qualifier for either leg.
committees := map[string]offchain.CommitteeConfig{
"alpha": {
Qualifier: "alpha",
Expand Down Expand Up @@ -165,21 +166,17 @@ func TestExpandLanesToPartialChainConfigs_FiltersCommitteeQualifiersPerRemoteCha
bySel[c.ChainSelector] = c
}

// beta (chainA only) and gamma (chainB only) are excluded from both legs;
// only alpha spans both chains.
cfgA := bySel[chainA]
require.Len(t, cfgA.CommitteeVerifiers, 2)
require.Len(t, cfgA.CommitteeVerifiers, 1)
assert.Equal(t, "alpha", cfgA.CommitteeVerifiers[0].CommitteeQualifier)
assert.Equal(t, "gamma", cfgA.CommitteeVerifiers[1].CommitteeQualifier)
for _, cv := range cfgA.CommitteeVerifiers {
assert.Contains(t, cv.RemoteChains, chainB)
}
assert.Contains(t, cfgA.CommitteeVerifiers[0].RemoteChains, chainB)

cfgB := bySel[chainB]
require.Len(t, cfgB.CommitteeVerifiers, 2)
require.Len(t, cfgB.CommitteeVerifiers, 1)
assert.Equal(t, "alpha", cfgB.CommitteeVerifiers[0].CommitteeQualifier)
assert.Equal(t, "beta", cfgB.CommitteeVerifiers[1].CommitteeQualifier)
for _, cv := range cfgB.CommitteeVerifiers {
assert.Contains(t, cv.RemoteChains, chainA)
}
assert.Contains(t, cfgB.CommitteeVerifiers[0].RemoteChains, chainA)
}

func TestExpandLanesToPartialChainConfigs_ChainOverridesCommitteeVerifierFinalityConfig(t *testing.T) {
Expand Down Expand Up @@ -224,12 +221,12 @@ func TestExpandLanesToPartialChainConfigs_ChainOverridesCommitteeVerifierFinalit
cfg = c
}
}
require.Len(t, cfg.CommitteeVerifiers, 2)
// Only alpha covers both chainA and chainB; beta/gamma are single-chain.
require.Len(t, cfg.CommitteeVerifiers, 1)
for _, cv := range cfg.CommitteeVerifiers {
require.NotNil(t, cv.AllowedFinalityConfig)
require.Equal(t, *finalityCfg, *cv.AllowedFinalityConfig)
require.Contains(t, cv.RemoteChains, chainB)

}
}

Expand Down
Loading