-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: migrator length check to use consensus type (#2556)
* make solana migration optional * add unit tests * get all foreign chains unit test * add unit test for chains supporting migration * add unit test for chains supporting migration * refactor to add a filter chain function * move filter to pkg * add more unit tests * format code * add unit test for ChainListByGateway * rename tests * add test case with repeated filters * add FilterByConsensus and FilterByGateway functions * format code 1
- Loading branch information
Showing
11 changed files
with
415 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package chains | ||
|
||
// ChainFilter is a function that filters chains based on some criteria | ||
type ChainFilter func(c Chain) bool | ||
|
||
// FilterExternalChains filters chains that are external | ||
func FilterExternalChains(c Chain) bool { | ||
return c.IsExternal | ||
} | ||
|
||
// FilterByGateway filters chains by gateway | ||
func FilterByGateway(gw CCTXGateway) ChainFilter { | ||
return func(chain Chain) bool { return chain.CctxGateway == gw } | ||
} | ||
|
||
// FilterByConsensus filters chains by consensus type | ||
func FilterByConsensus(cs Consensus) ChainFilter { | ||
return func(chain Chain) bool { return chain.Consensus == cs } | ||
} | ||
|
||
// FilterChains applies a list of filters to a list of chains | ||
func FilterChains(chainList []Chain, filters ...ChainFilter) []Chain { | ||
// Apply each filter to the list of supported chains | ||
for _, filter := range filters { | ||
var filteredChains []Chain | ||
for _, chain := range chainList { | ||
if filter(chain) { | ||
filteredChains = append(filteredChains, chain) | ||
} | ||
} | ||
chainList = filteredChains | ||
} | ||
|
||
// Return the filtered list of chains | ||
return chainList | ||
} | ||
|
||
// CombineFilterChains combines multiple lists of chains into a single list | ||
func CombineFilterChains(chainLists ...[]Chain) []Chain { | ||
chainMap := make(map[Chain]bool) | ||
var combinedChains []Chain | ||
|
||
// Add chains from each slice to remove duplicates | ||
for _, chains := range chainLists { | ||
for _, chain := range chains { | ||
if !chainMap[chain] { | ||
chainMap[chain] = true | ||
combinedChains = append(combinedChains, chain) | ||
} | ||
} | ||
} | ||
|
||
return combinedChains | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
package chains_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
"github.com/zeta-chain/zetacore/pkg/chains" | ||
) | ||
|
||
func TestFilterChains(t *testing.T) { | ||
tt := []struct { | ||
name string | ||
filters []chains.ChainFilter | ||
expected func() []chains.Chain | ||
}{ | ||
{ | ||
name: "Filter external chains", | ||
filters: []chains.ChainFilter{chains.FilterExternalChains}, | ||
expected: func() []chains.Chain { | ||
return chains.ExternalChainList([]chains.Chain{}) | ||
}, | ||
}, | ||
{ | ||
name: "Filter gateway observer chains", | ||
filters: []chains.ChainFilter{chains.FilterByGateway(chains.CCTXGateway_observers)}, | ||
expected: func() []chains.Chain { | ||
return chains.ChainListByGateway(chains.CCTXGateway_observers, []chains.Chain{}) | ||
}, | ||
}, | ||
{ | ||
name: "Filter consensus ethereum chains", | ||
filters: []chains.ChainFilter{chains.FilterByConsensus(chains.Consensus_ethereum)}, | ||
expected: func() []chains.Chain { | ||
return chains.ChainListByConsensus(chains.Consensus_ethereum, []chains.Chain{}) | ||
}, | ||
}, | ||
{ | ||
name: "Filter consensus bitcoin chains", | ||
filters: []chains.ChainFilter{chains.FilterByConsensus(chains.Consensus_bitcoin)}, | ||
expected: func() []chains.Chain { | ||
return chains.ChainListByConsensus(chains.Consensus_bitcoin, []chains.Chain{}) | ||
}, | ||
}, | ||
{ | ||
name: "Filter consensus solana chains", | ||
filters: []chains.ChainFilter{chains.FilterByConsensus(chains.Consensus_solana_consensus)}, | ||
expected: func() []chains.Chain { | ||
return chains.ChainListByConsensus(chains.Consensus_solana_consensus, []chains.Chain{}) | ||
}, | ||
}, | ||
{ | ||
name: "Apply multiple filters external chains and gateway observer", | ||
filters: []chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
}, | ||
expected: func() []chains.Chain { | ||
externalChains := chains.ExternalChainList([]chains.Chain{}) | ||
var gatewayObserverChains []chains.Chain | ||
for _, chain := range externalChains { | ||
if chain.CctxGateway == chains.CCTXGateway_observers { | ||
gatewayObserverChains = append(gatewayObserverChains, chain) | ||
} | ||
} | ||
return gatewayObserverChains | ||
}, | ||
}, | ||
{ | ||
name: "Apply multiple filters external chains with gateway observer and consensus ethereum", | ||
filters: []chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_ethereum), | ||
}, | ||
expected: func() []chains.Chain { | ||
externalChains := chains.ExternalChainList([]chains.Chain{}) | ||
var filterMultipleChains []chains.Chain | ||
for _, chain := range externalChains { | ||
if chain.CctxGateway == chains.CCTXGateway_observers && | ||
chain.Consensus == chains.Consensus_ethereum { | ||
filterMultipleChains = append(filterMultipleChains, chain) | ||
} | ||
} | ||
return filterMultipleChains | ||
}, | ||
}, | ||
{ | ||
name: "Apply multiple filters external chains with gateway observer and consensus bitcoin", | ||
filters: []chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_bitcoin), | ||
}, | ||
expected: func() []chains.Chain { | ||
externalChains := chains.ExternalChainList([]chains.Chain{}) | ||
var filterMultipleChains []chains.Chain | ||
for _, chain := range externalChains { | ||
if chain.CctxGateway == chains.CCTXGateway_observers && | ||
chain.Consensus == chains.Consensus_bitcoin { | ||
filterMultipleChains = append(filterMultipleChains, chain) | ||
} | ||
} | ||
return filterMultipleChains | ||
}, | ||
}, | ||
{ | ||
name: "test three same filters", | ||
filters: []chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterExternalChains, | ||
chains.FilterExternalChains, | ||
}, | ||
expected: func() []chains.Chain { | ||
externalChains := chains.ExternalChainList([]chains.Chain{}) | ||
return externalChains | ||
}, | ||
}, | ||
{ | ||
name: "Test multiple filters in random order", | ||
filters: []chains.ChainFilter{ | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_ethereum), | ||
chains.FilterExternalChains, | ||
}, | ||
expected: func() []chains.Chain { | ||
externalChains := chains.ExternalChainList([]chains.Chain{}) | ||
var filterMultipleChains []chains.Chain | ||
for _, chain := range externalChains { | ||
if chain.CctxGateway == chains.CCTXGateway_observers && | ||
chain.Consensus == chains.Consensus_ethereum { | ||
filterMultipleChains = append(filterMultipleChains, chain) | ||
} | ||
} | ||
return filterMultipleChains | ||
}, | ||
}, | ||
} | ||
for _, tc := range tt { | ||
t.Run(tc.name, func(t *testing.T) { | ||
chainList := chains.ExternalChainList([]chains.Chain{}) | ||
filteredChains := chains.FilterChains(chainList, tc.filters...) | ||
require.ElementsMatch(t, tc.expected(), filteredChains) | ||
require.Len(t, filteredChains, len(tc.expected())) | ||
}) | ||
} | ||
} | ||
|
||
func TestCombineFilterChains(t *testing.T) { | ||
tt := []struct { | ||
name string | ||
chainLists func() [][]chains.Chain | ||
expected func() []chains.Chain | ||
}{ | ||
{ | ||
name: "test support TSS migration filter", | ||
chainLists: func() [][]chains.Chain { | ||
return [][]chains.Chain{ | ||
chains.FilterChains( | ||
chains.ExternalChainList([]chains.Chain{}), | ||
[]chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_ethereum), | ||
}...), | ||
chains.FilterChains( | ||
chains.ExternalChainList([]chains.Chain{}), | ||
[]chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_bitcoin), | ||
}...), | ||
} | ||
}, | ||
expected: func() []chains.Chain { | ||
chainList := chains.ExternalChainList([]chains.Chain{}) | ||
var filterMultipleChains []chains.Chain | ||
for _, chain := range chainList { | ||
if chain.CctxGateway == chains.CCTXGateway_observers && | ||
(chain.Consensus == chains.Consensus_ethereum || chain.Consensus == chains.Consensus_bitcoin) { | ||
filterMultipleChains = append(filterMultipleChains, chain) | ||
} | ||
} | ||
return filterMultipleChains | ||
}, | ||
}, | ||
{ | ||
name: "test support TSS migration filter with solana", | ||
chainLists: func() [][]chains.Chain { | ||
return [][]chains.Chain{ | ||
chains.FilterChains( | ||
chains.ExternalChainList([]chains.Chain{}), | ||
[]chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_ethereum), | ||
}...), | ||
chains.FilterChains( | ||
chains.ExternalChainList([]chains.Chain{}), | ||
[]chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_bitcoin), | ||
}...), | ||
chains.FilterChains( | ||
chains.ExternalChainList([]chains.Chain{}), | ||
[]chains.ChainFilter{ | ||
chains.FilterExternalChains, | ||
chains.FilterByGateway(chains.CCTXGateway_observers), | ||
chains.FilterByConsensus(chains.Consensus_solana_consensus), | ||
}...), | ||
} | ||
}, | ||
expected: func() []chains.Chain { | ||
chainList := chains.ExternalChainList([]chains.Chain{}) | ||
var filterMultipleChains []chains.Chain | ||
for _, chain := range chainList { | ||
if chain.CctxGateway == chains.CCTXGateway_observers && | ||
(chain.Consensus == chains.Consensus_ethereum || chain.Consensus == chains.Consensus_bitcoin || chain.Consensus == chains.Consensus_solana_consensus) { | ||
filterMultipleChains = append(filterMultipleChains, chain) | ||
} | ||
} | ||
return filterMultipleChains | ||
}, | ||
}, | ||
} | ||
for _, tc := range tt { | ||
t.Run(tc.name, func(t *testing.T) { | ||
chainLists := tc.chainLists() | ||
combinedChains := chains.CombineFilterChains(chainLists...) | ||
require.ElementsMatch(t, tc.expected(), combinedChains) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.