native: do not update committee every block

Update frequency depends on committee size and
amount of validators. For mainnet it is 28.
This commit is contained in:
Evgenii Stratonikov 2020-09-22 13:03:34 +03:00
parent 81a11c629a
commit af16519413
2 changed files with 23 additions and 6 deletions

View file

@ -31,7 +31,8 @@ type NEO struct {
nextValidators atomic.Value nextValidators atomic.Value
validators atomic.Value validators atomic.Value
// committee contains cached committee members and // 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`. // is always equal to value stored by `prefixCommittee`.
committee atomic.Value committee atomic.Value
} }
@ -212,11 +213,19 @@ func (n *NEO) updateCommittee(ic *interop.Context) error {
return ic.DAO.PutStorageItem(n.ContractID, prefixCommittee, si) 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. // OnPersist implements Contract interface.
func (n *NEO) OnPersist(ic *interop.Context) error { func (n *NEO) OnPersist(ic *interop.Context) error {
if shouldUpdateCommittee(ic.Block.Index, ic.Chain) {
if err := n.updateCommittee(ic); err != nil { if err := n.updateCommittee(ic); err != nil {
return err return err
} }
}
gas, err := n.GetGASPerBlock(ic, ic.Block.Index) gas, err := n.GetGASPerBlock(ic, ic.Block.Index)
if err != nil { if err != nil {

View file

@ -35,6 +35,14 @@ func TestNEO_Vote(t *testing.T) {
ic.VM = vm.New() ic.VM = vm.New()
ic.Block = bc.newBlock(tx) 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() standBySorted := bc.GetStandByValidators()
sort.Sort(standBySorted) sort.Sort(standBySorted)
pubs, err := neo.ComputeNextBlockValidators(bc, ic.DAO) pubs, err := neo.ComputeNextBlockValidators(bc, ic.DAO)
@ -73,7 +81,7 @@ func TestNEO_Vote(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, standBySorted, pubs) require.Equal(t, standBySorted, pubs)
require.NoError(t, neo.OnPersist(ic)) advanceChain(t)
pubs = neo.GetNextBlockValidatorsInternal() pubs = neo.GetNextBlockValidatorsInternal()
require.EqualValues(t, standBySorted, pubs) 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.RegisterCandidateInternal(ic, priv.PublicKey()))
} }
require.NoError(t, neo.OnPersist(ic)) advanceChain(t)
pubs, err = neo.ComputeNextBlockValidators(bc, ic.DAO) pubs, err = neo.ComputeNextBlockValidators(bc, ic.DAO)
require.NoError(t, err) require.NoError(t, err)
sortedCandidates := candidates.Copy() sortedCandidates := candidates.Copy()
@ -102,7 +110,7 @@ func TestNEO_Vote(t *testing.T) {
require.NoError(t, neo.UnregisterCandidateInternal(ic, candidates[0])) require.NoError(t, neo.UnregisterCandidateInternal(ic, candidates[0]))
require.Error(t, neo.VoteInternal(ic, h, 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) pubs, err = neo.ComputeNextBlockValidators(bc, ic.DAO)
require.NoError(t, err) require.NoError(t, err)