From df2225cafe43a02eb89660d8431af82dca70c6b2 Mon Sep 17 00:00:00 2001 From: "Abdelrahman Soliman (Boda)" <2677789+asoliman92@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:23:03 +0400 Subject: [PATCH] Fix/ccip 2466 homechain config sync (#1077) Fix some of previous PR commit as it was merged with auto-merge before addressing all of them. --- .../ocr3/plugins/ccip/commit/factory.go | 2 +- .../ocr3/plugins/ccip/commit/plugin.go | 24 ++--- .../plugins/ccip/commit/plugin_e2e_test.go | 46 ++++----- .../ccip/internal/reader/home_chain.go | 65 ++++++------- .../ccip/internal/reader/home_chain_test.go | 95 +++---------------- 5 files changed, 75 insertions(+), 157 deletions(-) diff --git a/core/services/ocr3/plugins/ccip/commit/factory.go b/core/services/ocr3/plugins/ccip/commit/factory.go index 429f111957..876070daa5 100644 --- a/core/services/ocr3/plugins/ccip/commit/factory.go +++ b/core/services/ocr3/plugins/ccip/commit/factory.go @@ -68,7 +68,7 @@ func (p PluginFactory) NewReportingPlugin(config ocr3types.ReportingPluginConfig nil, //reportCodec nil, //msgHasher nil, // lggr - nil, //homeChainPoller + nil, //homeChain ), ocr3types.ReportingPluginInfo{}, nil } diff --git a/core/services/ocr3/plugins/ccip/commit/plugin.go b/core/services/ocr3/plugins/ccip/commit/plugin.go index ab8f55157e..58be6d1cd0 100644 --- a/core/services/ocr3/plugins/ccip/commit/plugin.go +++ b/core/services/ocr3/plugins/ccip/commit/plugin.go @@ -35,7 +35,7 @@ type Plugin struct { msgHasher cciptypes.MessageHasher lggr logger.Logger - homeChainPoller reader.HomeChainPoller + homeChain reader.HomeChain } func NewPlugin( @@ -48,7 +48,7 @@ func NewPlugin( reportCodec cciptypes.CommitPluginCodec, msgHasher cciptypes.MessageHasher, lggr logger.Logger, - homeChainPoller reader.HomeChainPoller, + homeChain reader.HomeChain, ) *Plugin { return &Plugin{ nodeID: nodeID, @@ -59,7 +59,7 @@ func NewPlugin( reportCodec: reportCodec, msgHasher: msgHasher, lggr: lggr, - homeChainPoller: homeChainPoller, + homeChain: homeChain, } } @@ -122,7 +122,7 @@ func (p *Plugin) Observation(ctx context.Context, outctx ocr3types.OutcomeContex return types.Observation{}, fmt.Errorf("observe gas prices: %w", err) } - fChain, err := p.homeChainPoller.GetFChain() + fChain, err := p.homeChain.GetFChain() if err != nil { return types.Observation{}, fmt.Errorf("get f chain: %w", err) } @@ -328,7 +328,7 @@ func (p *Plugin) Close() error { } func (p *Plugin) knownSourceChainsSlice() []cciptypes.ChainSelector { - knownSourceChains, err := p.homeChainPoller.GetKnownCCIPChains() + knownSourceChains, err := p.homeChain.GetKnownCCIPChains() if err != nil { p.lggr.Errorw("error getting known chains", "err", err) return nil @@ -343,7 +343,7 @@ func (p *Plugin) supportedChains() (mapset.Set[cciptypes.ChainSelector], error) if !exists { return nil, fmt.Errorf("oracle ID %d not found in oracleIDToP2pID", p.nodeID) } - supportedChains, err := p.homeChainPoller.GetSupportedChainsForPeer(p2pID) + supportedChains, err := p.homeChain.GetSupportedChainsForPeer(p2pID) if err != nil { p.lggr.Warnw("error getting supported chains", err) return mapset.NewSet[cciptypes.ChainSelector](), fmt.Errorf("error getting supported chains: %w", err) @@ -352,18 +352,10 @@ func (p *Plugin) supportedChains() (mapset.Set[cciptypes.ChainSelector], error) return supportedChains, nil } -func (p *Plugin) getDestChainConfig() (reader.ChainConfig, error) { - cfg, err := p.homeChainPoller.GetChainConfig(p.cfg.DestChain) - if err != nil { - return reader.ChainConfig{}, fmt.Errorf("get chain config: %w", err) - } - return cfg, nil -} - func (p *Plugin) supportsDestChain() (bool, error) { - destChainConfig, err := p.getDestChainConfig() + destChainConfig, err := p.homeChain.GetChainConfig(p.cfg.DestChain) if err != nil { - return false, fmt.Errorf("error getting chain config: %w", err) + return false, fmt.Errorf("get chain config: %w", err) } return destChainConfig.SupportedNodes.Contains(p.oracleIDToP2pID[p.nodeID]), nil } diff --git a/core/services/ocr3/plugins/ccip/commit/plugin_e2e_test.go b/core/services/ocr3/plugins/ccip/commit/plugin_e2e_test.go index bc93fa96d7..c3cb20c6b5 100644 --- a/core/services/ocr3/plugins/ccip/commit/plugin_e2e_test.go +++ b/core/services/ocr3/plugins/ccip/commit/plugin_e2e_test.go @@ -205,17 +205,17 @@ func setupEmptyOutcome(ctx context.Context, t *testing.T, lggr logger.Logger) [] }, } - homeChainPoller := setupHomeChainPoller(lggr, chainConfigInfos) - err := homeChainPoller.Start(ctx) + homeChain := setupHomeChainPoller(lggr, chainConfigInfos) + err := homeChain.Start(ctx) if err != nil { return nil } oracleIDToP2pID := GetP2pIDs(1, 2, 3) nodes := []nodeSetup{ - newNode(ctx, t, lggr, 1, cfg, homeChainPoller, oracleIDToP2pID), - newNode(ctx, t, lggr, 2, cfg, homeChainPoller, oracleIDToP2pID), - newNode(ctx, t, lggr, 3, cfg, homeChainPoller, oracleIDToP2pID), + newNode(ctx, t, lggr, 1, cfg, homeChain, oracleIDToP2pID), + newNode(ctx, t, lggr, 2, cfg, homeChain, oracleIDToP2pID), + newNode(ctx, t, lggr, 3, cfg, homeChain, oracleIDToP2pID), } for _, n := range nodes { @@ -227,7 +227,7 @@ func setupEmptyOutcome(ctx context.Context, t *testing.T, lggr logger.Logger) [] ).Return([]cciptypes.SeqNum{}, nil) } - err = homeChainPoller.Close() + err = homeChain.Close() if err != nil { return nil } @@ -275,15 +275,15 @@ func setupAllNodesReadAllChains(ctx context.Context, t *testing.T, lggr logger.L }, } - homeChainPoller := setupHomeChainPoller(lggr, chainConfigInfos) - err := homeChainPoller.Start(ctx) + homeChain := setupHomeChainPoller(lggr, chainConfigInfos) + err := homeChain.Start(ctx) if err != nil { return nil } oracleIDToP2pID := GetP2pIDs(1, 2, 3) - n1 := newNode(ctx, t, lggr, 1, cfg, homeChainPoller, oracleIDToP2pID) - n2 := newNode(ctx, t, lggr, 2, cfg, homeChainPoller, oracleIDToP2pID) - n3 := newNode(ctx, t, lggr, 3, cfg, homeChainPoller, oracleIDToP2pID) + n1 := newNode(ctx, t, lggr, 1, cfg, homeChain, oracleIDToP2pID) + n2 := newNode(ctx, t, lggr, 2, cfg, homeChain, oracleIDToP2pID) + n3 := newNode(ctx, t, lggr, 3, cfg, homeChain, oracleIDToP2pID) nodes := []nodeSetup{n1, n2, n3} for _, n := range nodes { @@ -319,7 +319,7 @@ func setupAllNodesReadAllChains(ctx context.Context, t *testing.T, lggr logger.L } // No need to keep it running in the background anymore for this test - err = homeChainPoller.Close() + err = homeChain.Close() if err != nil { return nil } @@ -368,15 +368,15 @@ func setupNodesDoNotAgreeOnMsgs(ctx context.Context, t *testing.T, lggr logger.L }, } - homeChainPoller := setupHomeChainPoller(lggr, chainConfigInfos) - err := homeChainPoller.Start(ctx) + homeChain := setupHomeChainPoller(lggr, chainConfigInfos) + err := homeChain.Start(ctx) if err != nil { return nil } oracleIDToP2pID := GetP2pIDs(1, 2, 3) - n1 := newNode(ctx, t, lggr, 1, cfg, homeChainPoller, oracleIDToP2pID) - n2 := newNode(ctx, t, lggr, 2, cfg, homeChainPoller, oracleIDToP2pID) - n3 := newNode(ctx, t, lggr, 3, cfg, homeChainPoller, oracleIDToP2pID) + n1 := newNode(ctx, t, lggr, 1, cfg, homeChain, oracleIDToP2pID) + n2 := newNode(ctx, t, lggr, 2, cfg, homeChain, oracleIDToP2pID) + n3 := newNode(ctx, t, lggr, 3, cfg, homeChain, oracleIDToP2pID) nodes := []nodeSetup{n1, n2, n3} for i, n := range nodes { @@ -414,7 +414,7 @@ func setupNodesDoNotAgreeOnMsgs(ctx context.Context, t *testing.T, lggr logger.L } // No need to keep it running in the background anymore for this test - err = homeChainPoller.Close() + err = homeChain.Close() if err != nil { return nil } @@ -430,7 +430,7 @@ type nodeSetup struct { msgHasher *mocks.MessageHasher } -func newNode(ctx context.Context, t *testing.T, lggr logger.Logger, id int, cfg cciptypes.CommitPluginConfig, homeChainPoller reader.HomeChainPoller, oracleIDToP2pID map[commontypes.OracleID]libocrtypes.PeerID) nodeSetup { +func newNode(ctx context.Context, t *testing.T, lggr logger.Logger, id int, cfg cciptypes.CommitPluginConfig, homeChain reader.HomeChain, oracleIDToP2pID map[commontypes.OracleID]libocrtypes.PeerID) nodeSetup { ccipReader := mocks.NewCCIPReader() priceReader := mocks.NewTokenPricesReader() reportCodec := mocks.NewCommitPluginJSONReportCodec() @@ -446,7 +446,7 @@ func newNode(ctx context.Context, t *testing.T, lggr logger.Logger, id int, cfg reportCodec, msgHasher, lggr, - homeChainPoller, + homeChain, ) return nodeSetup{ @@ -458,7 +458,7 @@ func newNode(ctx context.Context, t *testing.T, lggr logger.Logger, id int, cfg } } -func setupHomeChainPoller(lggr logger.Logger, chainConfigInfos []reader.ChainConfigInfo) *reader.HomeChainConfigPoller { +func setupHomeChainPoller(lggr logger.Logger, chainConfigInfos []reader.ChainConfigInfo) reader.HomeChain { homeChainReader := mocks.NewContractReaderMock() homeChainReader.On( "GetLatestValue", mock.Anything, "CCIPCapabilityConfiguration", "getAllChainConfigs", mock.Anything, mock.Anything).Run( @@ -467,13 +467,13 @@ func setupHomeChainPoller(lggr logger.Logger, chainConfigInfos []reader.ChainCon *arg = chainConfigInfos }).Return(nil) - homeChainPoller := reader.NewHomeChainConfigPoller( + homeChain := reader.NewHomeChainConfigPoller( homeChainReader, lggr, 10*time.Millisecond, // to prevent linting error because of logging after finishing tests, we close the poller after each test, having lower polling interval make it catch up faster ) - return homeChainPoller + return homeChain } func GetP2pIDs(ids ...int) map[commontypes.OracleID]libocrtypes.PeerID { res := make(map[commontypes.OracleID]libocrtypes.PeerID) diff --git a/core/services/ocr3/plugins/ccip/internal/reader/home_chain.go b/core/services/ocr3/plugins/ccip/internal/reader/home_chain.go index b4768323ca..aeb9d071a0 100644 --- a/core/services/ocr3/plugins/ccip/internal/reader/home_chain.go +++ b/core/services/ocr3/plugins/ccip/internal/reader/home_chain.go @@ -14,7 +14,7 @@ import ( libocrtypes "github.com/smartcontractkit/libocr/ragep2p/types" ) -type HomeChainPoller interface { +type HomeChain interface { GetChainConfig(chainSelector cciptypes.ChainSelector) (ChainConfig, error) GetAllChainConfigs() (map[cciptypes.ChainSelector]ChainConfig, error) // GetSupportedChainsForPeer Gets all chain selectors that the peerID can read/write from/to @@ -37,7 +37,7 @@ type state struct { fChain map[cciptypes.ChainSelector]int } -type HomeChainConfigPoller struct { +type homeChainPoller struct { stopCh services.StopChan sync services.StateMachine homeChainReader types.ContractReader @@ -55,8 +55,8 @@ func NewHomeChainConfigPoller( homeChainReader types.ContractReader, lggr logger.Logger, pollingInterval time.Duration, -) *HomeChainConfigPoller { - return &HomeChainConfigPoller{ +) HomeChain { + return &homeChainPoller{ stopCh: make(chan struct{}), homeChainReader: homeChainReader, state: state{}, @@ -67,7 +67,7 @@ func NewHomeChainConfigPoller( } } -func (r *HomeChainConfigPoller) Start(ctx context.Context) error { +func (r *homeChainPoller) Start(ctx context.Context) error { err := r.fetchAndSetConfigs(ctx) if err != nil { // Just log, don't return error as we want to keep polling @@ -80,7 +80,7 @@ func (r *HomeChainConfigPoller) Start(ctx context.Context) error { }) } -func (r *HomeChainConfigPoller) poll() { +func (r *homeChainPoller) poll() { ctx, cancel := r.stopCh.NewCtx() defer cancel() ticker := time.NewTicker(r.pollingDuration) @@ -97,16 +97,17 @@ func (r *HomeChainConfigPoller) poll() { r.mutex.Lock() r.failedPolls++ r.mutex.Unlock() - r.lggr.Errorw("Fetching and setting configs failed", "err", err) + r.lggr.Errorw("fetching and setting configs failed", "failedPolls", r.failedPolls, "err", err) } } } } -func (r *HomeChainConfigPoller) fetchAndSetConfigs(ctx context.Context) error { - chainConfigInfos, err := r.fetchOnChainConfig(ctx) +func (r *homeChainPoller) fetchAndSetConfigs(ctx context.Context) error { + var chainConfigInfos []ChainConfigInfo + err := r.homeChainReader.GetLatestValue(ctx, "CCIPCapabilityConfiguration", "getAllChainConfigs", nil, &chainConfigInfos) if err != nil { - r.lggr.Errorw("Fetching on-chain configs failed", "err", err) + r.lggr.Errorw("fetching on-chain configs failed", "err", err) return err } if len(chainConfigInfos) == 0 { @@ -114,7 +115,7 @@ func (r *HomeChainConfigPoller) fetchAndSetConfigs(ctx context.Context) error { r.lggr.Warnw("no on chain configs found") return nil } - homeChainConfigs, err := r.convertOnChainConfigToHomeChainConfig(chainConfigInfos) + homeChainConfigs, err := convertOnChainConfigToHomeChainConfig(chainConfigInfos) if err != nil { r.lggr.Errorw("error converting OnChainConfigs to ChainConfig", "err", err) return err @@ -124,7 +125,7 @@ func (r *HomeChainConfigPoller) fetchAndSetConfigs(ctx context.Context) error { return nil } -func (r *HomeChainConfigPoller) setState(chainConfigs map[cciptypes.ChainSelector]ChainConfig) { +func (r *homeChainPoller) setState(chainConfigs map[cciptypes.ChainSelector]ChainConfig) { r.mutex.Lock() defer r.mutex.Unlock() s := &r.state @@ -134,23 +135,23 @@ func (r *HomeChainConfigPoller) setState(chainConfigs map[cciptypes.ChainSelecto s.fChain = createFChain(chainConfigs) } -func (r *HomeChainConfigPoller) GetChainConfig(chainSelector cciptypes.ChainSelector) (ChainConfig, error) { +func (r *homeChainPoller) GetChainConfig(chainSelector cciptypes.ChainSelector) (ChainConfig, error) { r.mutex.RLock() defer r.mutex.RUnlock() s := r.state - if _, ok := s.chainConfigs[chainSelector]; !ok { - return ChainConfig{}, fmt.Errorf("chain config not found for chain %v", chainSelector) + if chainConfig, ok := s.chainConfigs[chainSelector]; ok { + return chainConfig, nil } - return s.chainConfigs[chainSelector], nil + return ChainConfig{}, fmt.Errorf("chain config not found for chain %v", chainSelector) } -func (r *HomeChainConfigPoller) GetAllChainConfigs() (map[cciptypes.ChainSelector]ChainConfig, error) { +func (r *homeChainPoller) GetAllChainConfigs() (map[cciptypes.ChainSelector]ChainConfig, error) { r.mutex.RLock() defer r.mutex.RUnlock() return r.state.chainConfigs, nil } -func (r *HomeChainConfigPoller) GetSupportedChainsForPeer(id libocrtypes.PeerID) (mapset.Set[cciptypes.ChainSelector], error) { +func (r *homeChainPoller) GetSupportedChainsForPeer(id libocrtypes.PeerID) (mapset.Set[cciptypes.ChainSelector], error) { r.mutex.RLock() defer r.mutex.RUnlock() s := r.state @@ -161,7 +162,7 @@ func (r *HomeChainConfigPoller) GetSupportedChainsForPeer(id libocrtypes.PeerID) return s.nodeSupportedChains[id], nil } -func (r *HomeChainConfigPoller) GetKnownCCIPChains() (mapset.Set[cciptypes.ChainSelector], error) { +func (r *homeChainPoller) GetKnownCCIPChains() (mapset.Set[cciptypes.ChainSelector], error) { r.mutex.RLock() defer r.mutex.RUnlock() knownSourceChains := mapset.NewSet[cciptypes.ChainSelector]() @@ -172,26 +173,26 @@ func (r *HomeChainConfigPoller) GetKnownCCIPChains() (mapset.Set[cciptypes.Chain return knownSourceChains, nil } -func (r *HomeChainConfigPoller) GetFChain() (map[cciptypes.ChainSelector]int, error) { +func (r *homeChainPoller) GetFChain() (map[cciptypes.ChainSelector]int, error) { r.mutex.RLock() defer r.mutex.RUnlock() return r.state.fChain, nil } -func (r *HomeChainConfigPoller) Close() error { +func (r *homeChainPoller) Close() error { return r.sync.StopOnce(r.Name(), func() error { close(r.stopCh) return nil }) } -func (r *HomeChainConfigPoller) Ready() error { +func (r *homeChainPoller) Ready() error { r.mutex.RLock() defer r.mutex.RUnlock() return r.sync.Ready() } -func (r *HomeChainConfigPoller) HealthReport() map[string]error { +func (r *homeChainPoller) HealthReport() map[string]error { r.mutex.RLock() defer r.mutex.RUnlock() if r.failedPolls >= MaxFailedPolls { @@ -200,8 +201,8 @@ func (r *HomeChainConfigPoller) HealthReport() map[string]error { return map[string]error{r.Name(): r.sync.Healthy()} } -func (r *HomeChainConfigPoller) Name() string { - return "HomeChainConfigPoller" +func (r *homeChainPoller) Name() string { + return "homeChainPoller" } func createFChain(chainConfigs map[cciptypes.ChainSelector]ChainConfig) map[cciptypes.ChainSelector]int { @@ -234,17 +235,7 @@ func createNodesSupportedChains(chainConfigs map[cciptypes.ChainSelector]ChainCo return nodeSupportedChains } -func (r *HomeChainConfigPoller) fetchOnChainConfig(ctx context.Context) ([]ChainConfigInfo, error) { - r.lggr.Infow("Fetching HomeChainConfigMapper") - var chainConfigInfo []ChainConfigInfo - err := r.homeChainReader.GetLatestValue(ctx, "CCIPCapabilityConfiguration", "getAllChainConfigs", nil, &chainConfigInfo) - if err != nil { - return nil, err - } - return chainConfigInfo, err -} - -func (r *HomeChainConfigPoller) convertOnChainConfigToHomeChainConfig(capabilityConfigs []ChainConfigInfo) (map[cciptypes.ChainSelector]ChainConfig, error) { +func convertOnChainConfigToHomeChainConfig(capabilityConfigs []ChainConfigInfo) (map[cciptypes.ChainSelector]ChainConfig, error) { chainConfigs := make(map[cciptypes.ChainSelector]ChainConfig) for _, capabilityConfig := range capabilityConfigs { chainSelector := capabilityConfig.ChainSelector @@ -282,4 +273,4 @@ type ChainConfig struct { Config []byte `json:"config"` } -var _ HomeChainPoller = (*HomeChainConfigPoller)(nil) +var _ HomeChain = (*homeChainPoller)(nil) diff --git a/core/services/ocr3/plugins/ccip/internal/reader/home_chain_test.go b/core/services/ocr3/plugins/ccip/internal/reader/home_chain_test.go index d9d8e2a154..ad7c86d6a1 100644 --- a/core/services/ocr3/plugins/ccip/internal/reader/home_chain_test.go +++ b/core/services/ocr3/plugins/ccip/internal/reader/home_chain_test.go @@ -50,88 +50,18 @@ func TestHomeChainConfigPoller_HealthReport(t *testing.T) { // Initially it's healthy healthy := configPoller.HealthReport() - assert.Equal(t, map[string]error{"HomeChainConfigPoller": error(nil)}, healthy) + assert.Equal(t, map[string]error{configPoller.Name(): error(nil)}, healthy) // After one second it will try polling 10 times and fail time.Sleep(1 * time.Second) errors := configPoller.HealthReport() - _ = configPoller.Close() + + err := configPoller.Close() + time.Sleep(100 * time.Millisecond) + assert.NoError(t, err) assert.Equal(t, 1, len(errors)) - assert.Errorf(t, errors["HomeChainConfigPoller"], "polling failed %d times in a row", MaxFailedPolls) -} -func Test_ConvertOnChainConfigToHomeChainConfig(t *testing.T) { - var tests = []struct { - name string - onChainConfigs []ChainConfigInfo - homeChainConfig map[cciptypes.ChainSelector]ChainConfig - expErr string - }{ - { - name: "Convert", - onChainConfigs: []ChainConfigInfo{ - { - ChainSelector: chainA, - ChainConfig: HomeChainConfigMapper{ - FChain: 1, - Readers: []libocrtypes.PeerID{ - p2pOracleAId, - p2pOracleBId, - p2pOracleCId, - }, - Config: []byte{0}, - }, - }, - { - ChainSelector: chainB, - ChainConfig: HomeChainConfigMapper{ - FChain: 2, - Readers: []libocrtypes.PeerID{ - p2pOracleAId, - p2pOracleBId, - }, - Config: []byte{0}, - }, - }, - { - ChainSelector: chainC, - ChainConfig: HomeChainConfigMapper{ - FChain: 3, - Readers: []libocrtypes.PeerID{ - p2pOracleCId, - }, - Config: []byte{0}, - }, - }, - }, - homeChainConfig: map[cciptypes.ChainSelector]ChainConfig{ - chainA: { - FChain: 1, - SupportedNodes: mapset.NewSet(p2pOracleAId, p2pOracleBId, p2pOracleCId), - }, - chainB: { - FChain: 2, - SupportedNodes: mapset.NewSet(p2pOracleAId, p2pOracleBId), - }, - chainC: { - FChain: 3, - SupportedNodes: mapset.NewSet(p2pOracleCId), - }, - }, - }, - } - for _, tc := range tests { - configPoller := NewHomeChainConfigPoller( - nil, - logger.Test(t), - 1*time.Second, - ) - t.Run(tc.name, func(t *testing.T) { - resultConfig, err := configPoller.convertOnChainConfigToHomeChainConfig(tc.onChainConfigs) - assert.NoError(t, err) - assert.Equal(t, tc.homeChainConfig, resultConfig) - }) - } + assert.Errorf(t, errors[configPoller.Name()], "polling failed %d times in a row", MaxFailedPolls) } func Test_PollingWorking(t *testing.T) { @@ -196,13 +126,18 @@ func Test_PollingWorking(t *testing.T) { configPoller := NewHomeChainConfigPoller( homeChainReader, logger.Test(t), - 1*time.Second, + 400*time.Millisecond, ) ctx := context.Background() - _ = configPoller.Start(ctx) - _ = configPoller.Close() - time.Sleep(100 * time.Millisecond) + err := configPoller.Start(ctx) + assert.NoError(t, err) + time.Sleep(1 * time.Second) + err = configPoller.Close() + assert.NoError(t, err) + + // called 3 times, once when it's started, and 2 times when it's polling + homeChainReader.AssertNumberOfCalls(t, "GetLatestValue", 3) configs, err := configPoller.GetAllChainConfigs() assert.NoError(t, err)