Skip to content

Commit 1984928

Browse files
authored
Parallelise State loading & FeeQuoter validation for faster resolution (#22065)
* Parallelise State loading & FeeQuoter validation for faster resolution * fixes
1 parent 99bb1ac commit 1984928

2 files changed

Lines changed: 97 additions & 64 deletions

File tree

deployment/ccip/shared/stateview/evm/validate_feequoter.go

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/ethereum/go-ethereum/accounts/abi"
1010
"github.com/ethereum/go-ethereum/accounts/abi/bind"
1111
"github.com/ethereum/go-ethereum/common"
12+
"golang.org/x/sync/errgroup"
1213

1314
chain_selectors "github.com/smartcontractkit/chain-selectors"
1415

@@ -312,57 +313,72 @@ func (c CCIPChainState) validateAllDestChainConfigs(
312313
v16FeeTokens []common.Address,
313314
fqV2 *fqv2ops.FeeQuoterContract,
314315
) error {
316+
var mu sync.Mutex
315317
var errs []error
318+
grp := errgroup.Group{}
319+
grp.SetLimit(20)
316320

317321
for _, destChainSel := range connectedChains {
318-
var v16Cfg *fee_quoter.FeeQuoterDestChainConfig
319-
var v20Cfg *fqv2ops.DestChainConfig
320-
var legacyCfg *evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig
321-
322-
if c.FeeQuoter != nil && v16FeeTokens != nil {
323-
cfg, err := c.FeeQuoter.GetDestChainConfig(callOpts, destChainSel)
324-
if err != nil {
325-
errs = append(errs, fmt.Errorf("failed to get FeeQuoter v1.6 dest chain config for chain %d: %w", destChainSel, err))
326-
} else {
327-
v16Cfg = &cfg
322+
dest := destChainSel
323+
grp.Go(func() error {
324+
var destErrs []error
325+
var v16Cfg *fee_quoter.FeeQuoterDestChainConfig
326+
var v20Cfg *fqv2ops.DestChainConfig
327+
var legacyCfg *evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig
328+
329+
if c.FeeQuoter != nil && v16FeeTokens != nil {
330+
cfg, err := c.FeeQuoter.GetDestChainConfig(callOpts, dest)
331+
if err != nil {
332+
destErrs = append(destErrs, fmt.Errorf("failed to get FeeQuoter v1.6 dest chain config for chain %d: %w", dest, err))
333+
} else {
334+
v16Cfg = &cfg
335+
}
328336
}
329-
}
330-
if fqV2 != nil {
331-
cfg, err := fqV2.GetDestChainConfig(callOpts, destChainSel)
332-
if err != nil {
333-
errs = append(errs, fmt.Errorf("failed to get FeeQuoter v2.0 dest chain config for chain %d: %w", destChainSel, err))
334-
} else {
335-
v20Cfg = &cfg
337+
if fqV2 != nil {
338+
cfg, err := fqV2.GetDestChainConfig(callOpts, dest)
339+
if err != nil {
340+
destErrs = append(destErrs, fmt.Errorf("failed to get FeeQuoter v2.0 dest chain config for chain %d: %w", dest, err))
341+
} else {
342+
v20Cfg = &cfg
343+
}
336344
}
337-
}
338-
if legacyOnRamp := c.EVM2EVMOnRamp[destChainSel]; legacyOnRamp != nil {
339-
cfg, err := legacyOnRamp.GetDynamicConfig(callOpts)
340-
if err != nil {
341-
errs = append(errs, fmt.Errorf("failed to get v1.5 OnRamp dynamic config for dest chain %d: %w", destChainSel, err))
342-
} else {
343-
legacyCfg = &cfg
345+
if legacyOnRamp := c.EVM2EVMOnRamp[dest]; legacyOnRamp != nil {
346+
cfg, err := legacyOnRamp.GetDynamicConfig(callOpts)
347+
if err != nil {
348+
destErrs = append(destErrs, fmt.Errorf("failed to get v1.5 OnRamp dynamic config for dest chain %d: %w", dest, err))
349+
} else {
350+
legacyCfg = &cfg
351+
}
344352
}
345-
}
346353

347-
v16Enabled := v16Cfg != nil && v16Cfg.IsEnabled
348-
v20Enabled := v20Cfg != nil && v20Cfg.IsEnabled
354+
v16Enabled := v16Cfg != nil && v16Cfg.IsEnabled
355+
v20Enabled := v20Cfg != nil && v20Cfg.IsEnabled
349356

350-
// Skip v1.6 checks when lane is enabled only in v2.0.
351-
if v16Cfg != nil && (v16Enabled || !v20Enabled) {
352-
if err := c.validateV16DestChainConfig(callOpts, sourceChainSel, destChainSel, *v16Cfg, legacyCfg); err != nil {
353-
errs = append(errs, err)
357+
// Skip v1.6 checks when lane is enabled only in v2.0.
358+
if v16Cfg != nil && (v16Enabled || !v20Enabled) {
359+
if err := c.validateV16DestChainConfig(callOpts, sourceChainSel, dest, *v16Cfg, legacyCfg); err != nil {
360+
destErrs = append(destErrs, err)
361+
}
354362
}
355-
}
356-
if v20Cfg != nil {
357-
v16ForV20 := v16Cfg
358-
if !v16Enabled && v20Enabled {
359-
v16ForV20 = nil
363+
if v20Cfg != nil {
364+
v16ForV20 := v16Cfg
365+
if !v16Enabled && v20Enabled {
366+
v16ForV20 = nil
367+
}
368+
if err := c.validateV20DestChainConfig(callOpts, sourceChainSel, dest, *v20Cfg, v16ForV20, legacyCfg, fqV2); err != nil {
369+
destErrs = append(destErrs, err)
370+
}
360371
}
361-
if err := c.validateV20DestChainConfig(callOpts, sourceChainSel, destChainSel, *v20Cfg, v16ForV20, legacyCfg, fqV2); err != nil {
362-
errs = append(errs, err)
372+
373+
if len(destErrs) > 0 {
374+
mu.Lock()
375+
errs = append(errs, destErrs...)
376+
mu.Unlock()
363377
}
364-
}
378+
return nil
379+
})
365380
}
381+
_ = grp.Wait()
366382

367383
return errors.Join(errs...)
368384
}
@@ -533,33 +549,40 @@ func (c CCIPChainState) validateAllTokenTransferFeeConfigs(
533549
e.Logger.Debugw("Validating TokenTransferFeeConfigs", "tokens", len(allTokens), "connectedChains", len(connectedChains))
534550
var mu sync.Mutex
535551
var errs []error
536-
var wg sync.WaitGroup
537-
sem := make(chan struct{}, 20)
552+
outerGrp := errgroup.Group{}
553+
outerGrp.SetLimit(20)
538554
for _, tokenAddr := range allTokens {
539555
token := tokenAddr
540556
tokenLabel := token.Hex()
541557
if sym, ok := addrToSymbol[token]; ok {
542558
tokenLabel = fmt.Sprintf("%s (%s)", sym, token.Hex())
543559
}
544-
wg.Add(1)
545-
sem <- struct{}{}
546-
go func() {
547-
defer wg.Done()
548-
defer func() { <-sem }()
560+
outerGrp.Go(func() error {
549561
var tokenErrs []error
562+
var tokenMu sync.Mutex
563+
innerGrp := errgroup.Group{}
564+
innerGrp.SetLimit(10)
550565
for _, destChainSel := range connectedChains {
551-
if err := c.validateTokenTransferFee(callOpts, destChainSel, token, tokenLabel, fqV2); err != nil {
552-
tokenErrs = append(tokenErrs, err)
553-
}
566+
dest := destChainSel
567+
innerGrp.Go(func() error {
568+
if err := c.validateTokenTransferFee(callOpts, dest, token, tokenLabel, fqV2); err != nil {
569+
tokenMu.Lock()
570+
tokenErrs = append(tokenErrs, err)
571+
tokenMu.Unlock()
572+
}
573+
return nil
574+
})
554575
}
576+
_ = innerGrp.Wait()
555577
if len(tokenErrs) > 0 {
556578
mu.Lock()
557579
errs = append(errs, tokenErrs...)
558580
mu.Unlock()
559581
}
560-
}()
582+
return nil
583+
})
561584
}
562-
wg.Wait()
585+
_ = outerGrp.Wait()
563586

564587
return errors.Join(errs...)
565588
}

deployment/ccip/shared/stateview/state.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,20 +1048,30 @@ func LoadOnchainState(e cldf.Environment, opts ...LoadOption) (CCIPOnChainState,
10481048
TonChains: tonChains,
10491049
evmMu: &sync.RWMutex{},
10501050
}
1051+
grp, ctx := errgroup.WithContext(e.GetContext())
1052+
grp.SetLimit(10) // parallel EVM chain loading with bounded concurrency
10511053
for chainSelector, chain := range e.BlockChains.EVMChains() {
1052-
// get all addresses for chain from addressbook
1053-
// here we do not load addresses from datastore as there can be multiple
1054-
// contracts of the same type and version in datastore which can lead to
1055-
// ambiguity while loading the state
1056-
addresses, err := e.ExistingAddresses.AddressesForChain(chainSelector)
1057-
if err != nil && !errors.Is(err, cldf.ErrChainNotFound) {
1058-
return state, fmt.Errorf("failed to get addresses for chain %d: %w", chainSelector, err)
1059-
}
1060-
chainState, err := LoadChainState(e.GetContext(), chain, addresses, opts...)
1061-
if err != nil {
1062-
return state, err
1063-
}
1064-
state.WriteEVMChainState(chainSelector, chainState)
1054+
sel := chainSelector
1055+
ch := chain
1056+
grp.Go(func() error {
1057+
// get all addresses for chain from addressbook
1058+
// here we do not load addresses from datastore as there can be multiple
1059+
// contracts of the same type and version in datastore which can lead to
1060+
// ambiguity while loading the state
1061+
addresses, err := e.ExistingAddresses.AddressesForChain(sel)
1062+
if err != nil && !errors.Is(err, cldf.ErrChainNotFound) {
1063+
return fmt.Errorf("failed to get addresses for chain %d: %w", sel, err)
1064+
}
1065+
chainState, err := LoadChainState(ctx, ch, addresses, opts...)
1066+
if err != nil {
1067+
return err
1068+
}
1069+
state.WriteEVMChainState(sel, chainState)
1070+
return nil
1071+
})
1072+
}
1073+
if err := grp.Wait(); err != nil {
1074+
return state, err
10651075
}
10661076
return state, state.Validate()
10671077
}

0 commit comments

Comments
 (0)