native: do not rewrite NextValidators in (*NEO).OnPersist()

There is no need in writing the same value again and again.
Closes #1337.
This commit is contained in:
Evgenii Stratonikov 2020-08-20 18:49:01 +03:00
parent 1809076dc6
commit 4782a94200
2 changed files with 34 additions and 1 deletions

View file

@ -26,7 +26,9 @@ type NEO struct {
nep5TokenNative nep5TokenNative
GAS *GAS GAS *GAS
validators atomic.Value votesChanged atomic.Value
nextValidators atomic.Value
validators atomic.Value
} }
// keyWithVotes is a serialized key with votes balance. It's not deserialized // keyWithVotes is a serialized key with votes balance. It's not deserialized
@ -79,6 +81,8 @@ func NewNEO() *NEO {
nep5.ContractID = neoContractID nep5.ContractID = neoContractID
n.nep5TokenNative = *nep5 n.nep5TokenNative = *nep5
n.votesChanged.Store(true)
n.nextValidators.Store(keys.PublicKeys(nil))
n.validators.Store(keys.PublicKeys(nil)) n.validators.Store(keys.PublicKeys(nil))
onp := n.Methods["onPersist"] onp := n.Methods["onPersist"]
@ -152,10 +156,28 @@ func (n *NEO) Initialize(ic *interop.Context) error {
// 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 !n.votesChanged.Load().(bool) {
return nil
}
pubs, err := n.GetValidatorsInternal(ic.Chain, ic.DAO) pubs, err := n.GetValidatorsInternal(ic.Chain, ic.DAO)
if err != nil { if err != nil {
return err return err
} }
prev := n.nextValidators.Load().(keys.PublicKeys)
if len(prev) == len(pubs) {
var needUpdate bool
for i := range pubs {
if !pubs[i].Equal(prev[i]) {
needUpdate = true
break
}
}
if !needUpdate {
return nil
}
}
n.votesChanged.Store(false)
n.nextValidators.Store(pubs)
si := new(state.StorageItem) si := new(state.StorageItem)
si.Value = pubs.Bytes() si.Value = pubs.Bytes()
return ic.DAO.PutStorageItem(n.ContractID, nextValidatorsKey, si) return ic.DAO.PutStorageItem(n.ContractID, nextValidatorsKey, si)
@ -328,6 +350,7 @@ const (
// ModifyAccountVotes modifies votes of the specified account by value (can be negative). // ModifyAccountVotes modifies votes of the specified account by value (can be negative).
// typ specifies if this modify is occurring during transfer or vote (with old or new validator). // typ specifies if this modify is occurring during transfer or vote (with old or new validator).
func (n *NEO) ModifyAccountVotes(acc *state.NEOBalanceState, d dao.DAO, value *big.Int, typ int) error { func (n *NEO) ModifyAccountVotes(acc *state.NEOBalanceState, d dao.DAO, value *big.Int, typ int) error {
n.votesChanged.Store(true)
if acc.VoteTo != nil { if acc.VoteTo != nil {
key := makeValidatorKey(acc.VoteTo) key := makeValidatorKey(acc.VoteTo)
si := d.GetStorageItem(n.ContractID, key) si := d.GetStorageItem(n.ContractID, key)

View file

@ -70,6 +70,11 @@ 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))
pubs, err = neo.GetNextBlockValidatorsInternal(bc, ic.DAO)
require.NoError(t, err)
require.EqualValues(t, standBySorted, pubs)
// Register and give some value to the last validator. // Register and give some value to the last validator.
require.NoError(t, neo.RegisterCandidateInternal(ic, candidates[0])) require.NoError(t, neo.RegisterCandidateInternal(ic, candidates[0]))
priv := testchain.PrivateKeyByID(0) priv := testchain.PrivateKeyByID(0)
@ -84,6 +89,11 @@ func TestNEO_Vote(t *testing.T) {
sort.Sort(sortedCandidates) sort.Sort(sortedCandidates)
require.EqualValues(t, sortedCandidates, pubs) require.EqualValues(t, sortedCandidates, pubs)
require.NoError(t, neo.OnPersist(ic))
pubs, err = neo.GetNextBlockValidatorsInternal(bc, ic.DAO)
require.NoError(t, err)
require.EqualValues(t, sortedCandidates, pubs)
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]))