@@ -30,6 +30,7 @@ type pathEndRuntime struct {
30
30
clientTrustedState provider.ClientTrustedState
31
31
connectionStateCache ConnectionStateCache
32
32
channelStateCache ChannelStateCache
33
+ channelStateCacheMu sync.RWMutex
33
34
channelOrderCache map [string ]chantypes.Order
34
35
latestHeader provider.IBCHeader
35
36
ibcHeaderCache IBCHeaderCache
@@ -107,7 +108,7 @@ func (pathEnd *pathEndRuntime) mergeMessageCache(messageCache IBCMessagesCache,
107
108
clientICQMessages := make (ClientICQMessagesCache )
108
109
109
110
for ch , pmc := range messageCache .PacketFlow {
110
- if pathEnd .info . ShouldRelayChannel (ChainChannelKey {ChainID : pathEnd .info .ChainID , CounterpartyChainID : counterpartyChainID , ChannelKey : ch }) {
111
+ if pathEnd .ShouldRelayChannel (ChainChannelKey {ChainID : pathEnd .info .ChainID , CounterpartyChainID : counterpartyChainID , ChannelKey : ch }) {
111
112
if inSync && pathEnd .metrics != nil {
112
113
for eventType , pCache := range pmc {
113
114
pathEnd .metrics .AddPacketsObserved (pathEnd .info .PathName , pathEnd .info .ChainID , ch .ChannelID , ch .PortID , eventType , len (pCache ))
@@ -403,7 +404,10 @@ func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func()
403
404
}
404
405
405
406
pathEnd .connectionStateCache = d .ConnectionStateCache // Update latest connection open state for chain
406
- pathEnd .channelStateCache = d .ChannelStateCache // Update latest channel open state for chain
407
+
408
+ pathEnd .channelStateCacheMu .Lock ()
409
+ pathEnd .channelStateCache = d .ChannelStateCache // Update latest channel open state for chain
410
+ pathEnd .channelStateCacheMu .Unlock ()
407
411
408
412
pathEnd .mergeMessageCache (d .IBCMessagesCache , counterpartyChainID , pathEnd .inSync && counterpartyInSync ) // Merge incoming packet IBC messages into the backlog
409
413
@@ -874,3 +878,44 @@ func (pathEnd *pathEndRuntime) localhostSentinelProofChannel(
874
878
Version : info .Version ,
875
879
}, nil
876
880
}
881
+
882
+ // ShouldRelayChannel determines whether a chain channel (and optionally a port), should be relayed
883
+ // by this path end.
884
+ //
885
+ // It first checks if the channel matches any rule in the path end's filter list. If the channel matches a channel
886
+ // in an allowed list, it returns true. If the channel matches any blocked channel it returns false. Otherwise, it returns true.
887
+ //
888
+ // If no filter rule matches, it checks if the channel or its counterparty is present in the path end's
889
+ // channel state cache. This cache only holds channels relevant to the client for this path end, ensuring
890
+ // the channel belongs to a client connected to this path end.
891
+ //
892
+ // Note that this function only determines whether the channel should be relayed based on the path end's
893
+ // configuration. It does not guarantee that the channel is actually relayable, as other checks
894
+ // (e.g., expired client) may still be necessary.
895
+ func (pathEnd * pathEndRuntime ) ShouldRelayChannel (chainChannelKey ChainChannelKey ) bool {
896
+ pe := pathEnd .info
897
+ if pe .Rule == RuleAllowList {
898
+ for _ , allowedChannel := range pe .FilterList {
899
+ if pe .shouldRelayChannelSingle (chainChannelKey , allowedChannel , true ) {
900
+ return true
901
+ }
902
+ }
903
+ return false
904
+ } else if pe .Rule == RuleDenyList {
905
+ for _ , blockedChannel := range pe .FilterList {
906
+ if ! pe .shouldRelayChannelSingle (chainChannelKey , blockedChannel , false ) {
907
+ return false
908
+ }
909
+ }
910
+ return true
911
+ }
912
+
913
+ pathEnd .channelStateCacheMu .RLock ()
914
+ defer pathEnd .channelStateCacheMu .RUnlock ()
915
+
916
+ // if no filter rule, check if the channel or counterparty channel is in the channelStateCache.
917
+ // Because channelStateCache only holds channels relevant to the client, we can ensure that the
918
+ // channel is built on top of a client for this pathEnd
919
+ _ , exists := pathEnd .channelStateCache [chainChannelKey .ChannelKey ]
920
+ return exists
921
+ }
0 commit comments