diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index fd9053782..395319d0a 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -31,7 +31,8 @@ type NEO struct { nextValidators atomic.Value validators atomic.Value // committee contains cached committee members and - // is updated during block persist. It's value + // is updated once in a while depending on committee size + // (every 28 blocks for mainnet). It's value // is always equal to value stored by `prefixCommittee`. committee atomic.Value } @@ -212,10 +213,18 @@ func (n *NEO) updateCommittee(ic *interop.Context) error { return ic.DAO.PutStorageItem(n.ContractID, prefixCommittee, si) } +func shouldUpdateCommittee(h uint32, bc blockchainer.Blockchainer) bool { + cfg := bc.GetConfig() + r := cfg.ValidatorsCount + len(cfg.StandbyCommittee) + return h%uint32(r) == 0 +} + // OnPersist implements Contract interface. func (n *NEO) OnPersist(ic *interop.Context) error { - if err := n.updateCommittee(ic); err != nil { - return err + if shouldUpdateCommittee(ic.Block.Index, ic.Chain) { + if err := n.updateCommittee(ic); err != nil { + return err + } } gas, err := n.GetGASPerBlock(ic, ic.Block.Index) diff --git a/pkg/core/native_neo_test.go b/pkg/core/native_neo_test.go index 531119ff5..6544f5112 100644 --- a/pkg/core/native_neo_test.go +++ b/pkg/core/native_neo_test.go @@ -35,6 +35,14 @@ func TestNEO_Vote(t *testing.T) { ic.VM = vm.New() ic.Block = bc.newBlock(tx) + freq := testchain.ValidatorsCount + testchain.CommitteeSize() + advanceChain := func(t *testing.T) { + for i := 0; i < freq; i++ { + require.NoError(t, neo.OnPersist(ic)) + ic.Block.Index++ + } + } + standBySorted := bc.GetStandByValidators() sort.Sort(standBySorted) pubs, err := neo.ComputeNextBlockValidators(bc, ic.DAO) @@ -73,7 +81,7 @@ func TestNEO_Vote(t *testing.T) { require.NoError(t, err) require.Equal(t, standBySorted, pubs) - require.NoError(t, neo.OnPersist(ic)) + advanceChain(t) pubs = neo.GetNextBlockValidatorsInternal() require.EqualValues(t, standBySorted, pubs) @@ -90,7 +98,7 @@ func TestNEO_Vote(t *testing.T) { require.NoError(t, neo.RegisterCandidateInternal(ic, priv.PublicKey())) } - require.NoError(t, neo.OnPersist(ic)) + advanceChain(t) pubs, err = neo.ComputeNextBlockValidators(bc, ic.DAO) require.NoError(t, err) sortedCandidates := candidates.Copy() @@ -102,7 +110,7 @@ func TestNEO_Vote(t *testing.T) { require.NoError(t, neo.UnregisterCandidateInternal(ic, candidates[0])) require.Error(t, neo.VoteInternal(ic, h, candidates[0])) - require.NoError(t, neo.OnPersist(ic)) + advanceChain(t) pubs, err = neo.ComputeNextBlockValidators(bc, ic.DAO) require.NoError(t, err)