diff --git a/pkg/innerring/processors/governance/list.go b/pkg/innerring/processors/governance/list.go index 4babe930..f5e21d75 100644 --- a/pkg/innerring/processors/governance/list.go +++ b/pkg/innerring/processors/governance/list.go @@ -7,7 +7,10 @@ import ( "github.com/pkg/errors" ) -var errNotEnoughKeys = errors.New("alphabet list in mainnet is too short") +var ( + errNotEnoughKeys = errors.New("alphabet list in mainnet is too short") + errNotEqualLen = errors.New("old and new alphabet lists have different length") +) // newAlphabetList returns updated list of sidechain keys with no more than 1\3 // of new keys from mainnet list. Function returns `errNotEnoughKeys` if @@ -62,3 +65,29 @@ func newAlphabetList(sidechain, mainnet keys.PublicKeys) (keys.PublicKeys, error return result, nil } + +// updateInnerRing function removes `before` keys from `innerRing` and adds +// `after` keys in the list. If length of `before` and `after` is not the same +// then function returns errNotEqualLen +func updateInnerRing(innerRing, before, after keys.PublicKeys) (keys.PublicKeys, error) { + lnBefore := len(before) + if lnBefore != len(after) { + return nil, errNotEqualLen + } + + result := make(keys.PublicKeys, 0, len(innerRing)) + + // O(n^2) for 7 nodes is not THAT bad. +loop: + for i := range innerRing { + for j := range before { + if innerRing[i].Equal(before[j]) { + result = append(result, after[j]) + continue loop + } + } + result = append(result, innerRing[i]) + } + + return result, nil +} diff --git a/pkg/innerring/processors/governance/list_test.go b/pkg/innerring/processors/governance/list_test.go index d249ac22..8cc64cd0 100644 --- a/pkg/innerring/processors/governance/list_test.go +++ b/pkg/innerring/processors/governance/list_test.go @@ -52,6 +52,56 @@ func TestNewAlphabetList(t *testing.T) { }) } +func TestUpdateInnerRing(t *testing.T) { + k, err := generateKeys(6) + require.NoError(t, err) + + t.Run("same keys", func(t *testing.T) { + ir := k[:3] + before := k[1:3] + after := keys.PublicKeys{k[2], k[1]} + + list, err := updateInnerRing(ir, before, after) + require.NoError(t, err) + + sort.Sort(ir) + sort.Sort(list) + require.True(t, equalPublicKeyLists(ir, list)) + }) + + t.Run("unknown keys", func(t *testing.T) { + ir := k[:3] + before := k[3:4] + after := k[4:5] + + list, err := updateInnerRing(ir, before, after) + require.NoError(t, err) + + require.True(t, equalPublicKeyLists(ir, list)) + }) + + t.Run("different size", func(t *testing.T) { + ir := k[:3] + before := k[1:3] + after := k[4:5] + + _, err = updateInnerRing(ir, before, after) + require.Error(t, err) + }) + + t.Run("new list", func(t *testing.T) { + ir := k[:3] + before := k[1:3] + after := k[4:6] + exp := keys.PublicKeys{k[0], k[4], k[5]} + + list, err := updateInnerRing(ir, before, after) + require.NoError(t, err) + + require.True(t, equalPublicKeyLists(exp, list)) + }) +} + func generateKeys(n int) (keys.PublicKeys, error) { pubKeys := make(keys.PublicKeys, 0, n)