Skip to content
Closed
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
1 change: 1 addition & 0 deletions build/devenv/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (

CustomExecutorQualifier = "custom"

CCTPVerifierResolverQualifier = "CCTPVerifierResolver"
CCTPPrimaryReceiverQualifier = "cctp-primary"
CCTPSecondaryReceiverQualifier = "cctp-secondary"

Expand Down
70 changes: 13 additions & 57 deletions build/devenv/components/tokenverifier/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package tokenverifier
import (
"context"
"fmt"
"strconv"

chainsel "github.com/smartcontractkit/chain-selectors"
"github.com/smartcontractkit/chainlink-ccv/build/devenv/chainreg"
Expand All @@ -14,7 +13,6 @@ import (
"github.com/smartcontractkit/chainlink-ccv/build/devenv/services"
ccvdeployment "github.com/smartcontractkit/chainlink-ccv/deployment"
ccvchangesets "github.com/smartcontractkit/chainlink-ccv/deployment/changesets"
"github.com/smartcontractkit/chainlink-ccv/verifier/pkg/token"
"github.com/smartcontractkit/chainlink-deployments-framework/deployment"
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"
)
Expand Down Expand Up @@ -88,6 +86,7 @@ func (c *component) RunPhase4(
}

familyLombardQualifier := make(map[string]string, len(inputs))
familyCCTPQualifier := make(map[string]string, len(inputs))
for _, in := range inputs {
if in == nil {
continue
Expand All @@ -101,6 +100,12 @@ func (c *component) RunPhase4(
q = devenvcommon.LombardVerifierResolverQualifier
}
familyLombardQualifier[fam] = q

q = in.CCTPQualifier
if q == "" {
q = devenvcommon.CCTPVerifierResolverQualifier
}
familyCCTPQualifier[fam] = q
}

localEnv := *e
Expand All @@ -116,12 +121,13 @@ func (c *component) RunPhase4(
if family == "" {
family = chainsel.FamilyEVM
}
familySelectors := selectorsForFamily(selectors, family)
familySelectors := devenvcommon.SelectorsForFamily(selectors, family)
if len(familySelectors) == 0 {
return nil, nil, fmt.Errorf("tokenverifier: no chain selectors found for family %q (instance %q)", family, tvIn.ContainerName)
}

lombardQualifier := familyLombardQualifier[family]
cctpQualifier := familyCCTPQualifier[family]

cs := ccvchangesets.GenerateTokenVerifierConfig()
output, csErr := cs.Apply(localEnv, ccvchangesets.GenerateTokenVerifierConfigInput{
Expand All @@ -134,6 +140,7 @@ func (c *component) RunPhase4(
},
CCTP: ccvchangesets.CCTPConfigInput{
VerifierID: "CCTPVerifier",
Qualifier: cctpQualifier,
AttestationAPI: fakeOut.InternalHTTPURL + "/cctp",
},
})
Expand All @@ -154,20 +161,17 @@ func (c *component) RunPhase4(
remoteByFamily[selFamily] = append(remoteByFamily[selFamily], sel)
}
for remoteFamily, remoteSelectors := range remoteByFamily {
remoteLombardQualifier := familyLombardQualifier[remoteFamily]
if remoteLombardQualifier == "" {
remoteLombardQualifier = devenvcommon.LombardVerifierResolverQualifier
}
remoteOutput, remoteErr := ccvchangesets.GenerateTokenVerifierConfig().Apply(localEnv, ccvchangesets.GenerateTokenVerifierConfigInput{
ServiceIdentifier: tvIn.ContainerName,
ChainSelectors: remoteSelectors,
Lombard: ccvchangesets.LombardConfigInput{
VerifierID: "LombardVerifier",
Qualifier: remoteLombardQualifier,
Qualifier: familyLombardQualifier[remoteFamily],
AttestationAPI: fakeOut.InternalHTTPURL + "/lombard",
},
CCTP: ccvchangesets.CCTPConfigInput{
VerifierID: "CCTPVerifier",
Qualifier: familyCCTPQualifier[remoteFamily],
AttestationAPI: fakeOut.InternalHTTPURL + "/cctp",
},
})
Expand All @@ -182,7 +186,7 @@ func (c *component) RunPhase4(
return nil, nil, fmt.Errorf("tokenverifier: getting token verifier config: %w", cfgErr)
}

tokenVerifierCfg.TokenVerifiers = dropUnreachableVerifiers(tokenVerifierCfg.TokenVerifiers, familySelectors)
tokenVerifierCfg.TokenVerifiers = devenvcommon.DropUnreachableTokenVerifiers(tokenVerifierCfg.TokenVerifiers, familySelectors)
inputs[i].GeneratedConfig = tokenVerifierCfg
}

Expand All @@ -208,54 +212,6 @@ func (c *component) RunPhase4(
return map[string]any{Key: inputs}, nil, nil
}

// dropUnreachableVerifiers removes any verifier-type entry (CCTP or Lombard) whose
// resolved verifier-resolver addresses have no chain in common with localSelectors:
// an instance can never coordinate a verifier type it has no locally-reachable chains for.
func dropUnreachableVerifiers(verifiers []token.VerifierConfig, localSelectors []uint64) []token.VerifierConfig {
local := make(map[string]struct{}, len(localSelectors))
for _, sel := range localSelectors {
local[strconv.FormatUint(sel, 10)] = struct{}{}
}

reachable := make([]token.VerifierConfig, 0, len(verifiers))
for _, vc := range verifiers {
var resolvers map[string]any
switch {
case vc.CCTPConfig != nil:
resolvers = vc.CCTPConfig.VerifierResolvers
case vc.LombardConfig != nil:
resolvers = vc.LombardConfig.VerifierResolvers
}
hasLocalChain := false
for chainSelectorStr := range resolvers {
if _, ok := local[chainSelectorStr]; ok {
hasLocalChain = true
break
}
}
if hasLocalChain {
reachable = append(reachable, vc)
}
}
return reachable
}

// selectorsForFamily filters selectors down to those belonging to family, by cross-referencing
// each selector's registered chain details. Order is not guaranteed to match the input.
func selectorsForFamily(selectors []uint64, family string) []uint64 {
var filtered []uint64
for _, sel := range selectors {
selFamily, err := chainsel.GetSelectorFamily(sel)
if err != nil {
continue
}
if selFamily == family {
filtered = append(filtered, sel)
}
}
return filtered
}

func decode(raw any) ([]*services.TokenVerifierInput, error) {
inputs, err := devenvruntime.DecodeConfig[[]*services.TokenVerifierInput](raw, Key)
if err != nil {
Expand Down
72 changes: 68 additions & 4 deletions build/devenv/environment_monolith.go
Original file line number Diff line number Diff line change
Expand Up @@ -784,34 +784,97 @@ func NewEnvironment() (in *Cfg, err error) {
///////////////////////////////////

progress.Stage(ctx, stageLaunchTokenVerifiers)
familyLombardQualifier := make(map[string]string, len(in.TokenVerifier))
familyCCTPQualifier := make(map[string]string, len(in.TokenVerifier))
for _, tv := range in.TokenVerifier {
if in == nil {
continue
}
fam := tv.ChainFamily
if fam == "" {
fam = chainsel.FamilyEVM
}
q := tv.LombardQualifier
if q == "" {
q = devenvcommon.LombardVerifierResolverQualifier
}
familyLombardQualifier[fam] = q

q = tv.CCTPQualifier
if q == "" {
q = devenvcommon.CCTPVerifierResolverQualifier
}
familyCCTPQualifier[fam] = q
}

localEnv := *e
// Generate token verifier configs using changeset (on-chain state as source of truth)
for i, tokenVerifierInput := range in.TokenVerifier {
if tokenVerifierInput == nil {
continue
}
family := tokenVerifierInput.ChainFamily
if family == "" {
family = chainsel.FamilyEVM
}
localSelectors := devenvcommon.SelectorsForFamily(selectors, family)
if len(localSelectors) == 0 {
return nil, fmt.Errorf("no chain selectors found for token verifier family %q (instance %q)", family, tokenVerifierInput.ContainerName)
}

if fakeOut == nil {
return nil, fmt.Errorf("fake data provider is required for token verifiers to provide attestation API endpoints, but it was not created successfully")
}

// Use changeset to generate token verifier config from on-chain state
cs := ccvchangesets.GenerateTokenVerifierConfig()
output, err := cs.Apply(*e, ccvchangesets.GenerateTokenVerifierConfigInput{
output, err := cs.Apply(localEnv, ccvchangesets.GenerateTokenVerifierConfigInput{
ServiceIdentifier: "TokenVerifier",
ChainSelectors: selectors,
ChainSelectors: localSelectors,
Lombard: ccvchangesets.LombardConfigInput{
VerifierID: "LombardVerifier",
Qualifier: devenvcommon.LombardVerifierResolverQualifier,
Qualifier: familyLombardQualifier[family],
AttestationAPI: fakeOut.InternalHTTPURL + "/lombard",
},
CCTP: ccvchangesets.CCTPConfigInput{
VerifierID: "CCTPVerifier",
Qualifier: familyCCTPQualifier[family],
AttestationAPI: fakeOut.InternalHTTPURL + "/cctp",
},
})
if err != nil {
return nil, fmt.Errorf("failed to generate token verifier config: %w", err)
}
localEnv.DataStore = output.DataStore.Seal()

remoteByFamily := make(map[string][]uint64)
for _, selector := range selectors {
selectorFamily, familyErr := chainsel.GetSelectorFamily(selector)
if familyErr != nil || selectorFamily == family {
continue
}
remoteByFamily[selectorFamily] = append(remoteByFamily[selectorFamily], selector)
}
for remoteFamily, remoteSelectors := range remoteByFamily {
remoteOutput, remoteErr := ccvchangesets.GenerateTokenVerifierConfig().Apply(localEnv, ccvchangesets.GenerateTokenVerifierConfigInput{
ServiceIdentifier: "TokenVerifier",
ChainSelectors: remoteSelectors,
Lombard: ccvchangesets.LombardConfigInput{
VerifierID: "LombardVerifier",
Qualifier: familyLombardQualifier[remoteFamily],
AttestationAPI: fakeOut.InternalHTTPURL + "/lombard",
},
CCTP: ccvchangesets.CCTPConfigInput{
VerifierID: "CCTPVerifier",
Qualifier: familyCCTPQualifier[remoteFamily],
AttestationAPI: fakeOut.InternalHTTPURL + "/cctp",
},
})
if remoteErr != nil {
return nil, fmt.Errorf("failed to generate cross-family token verifier config for %q (family %q): %w", tokenVerifierInput.ContainerName, remoteFamily, remoteErr)
}
localEnv.DataStore = remoteOutput.DataStore.Seal()
}

// Get generated config from output datastore
tokenVerifierCfg, err := ccvdeployment.GetTokenVerifierConfig(
Expand All @@ -820,8 +883,9 @@ func NewEnvironment() (in *Cfg, err error) {
if err != nil {
return nil, fmt.Errorf("failed to get token verifier config from output: %w", err)
}
tokenVerifierCfg.TokenVerifiers = devenvcommon.DropUnreachableTokenVerifiers(tokenVerifierCfg.TokenVerifiers, localSelectors)
in.TokenVerifier[i].GeneratedConfig = tokenVerifierCfg
e.DataStore = output.DataStore.Seal()
e.DataStore = localEnv.DataStore
}

if fakeOut != nil {
Expand Down
4 changes: 4 additions & 0 deletions build/devenv/services/tokenVerifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ type TokenVerifierInput struct {
// generated config should resolve addresses for.
LombardQualifier string `toml:"lombard_qualifier"`

// CCTPQualifier identifies which CCTP verifier/resolver deployment this instance's
// generated config should resolve addresses for.
CCTPQualifier string `toml:"cctp_qualifier"`

// GeneratedConfig stores the generated token verifier configuration from the changeset.
GeneratedConfig *token.Config `toml:"-"`

Expand Down
Loading