native: initialize cache in OnPersist

If node started from non-zero height, `Initialize` is
not called thus cache is empty. Thus we should initialize
it before any tx is executed.
This commit is contained in:
Evgenii Stratonikov 2020-09-28 15:29:43 +03:00
parent 05118e96f4
commit 26dc807a2d

View file

@ -173,13 +173,10 @@ func (n *NEO) Initialize(ic *interop.Context) error {
}
committee := ic.Chain.GetStandByCommittee()
n.committee.Store(committee)
script, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee.Copy())
err := n.updateCache(committee, ic.Chain)
if err != nil {
return err
}
n.committeeHash.Store(hash.Hash160(script))
n.updateNextValidators(committee, ic.Chain)
err = ic.DAO.PutStorageItem(n.ContractID, prefixCommittee, &state.StorageItem{Value: committee.Bytes()})
if err != nil {
@ -207,10 +204,18 @@ func (n *NEO) Initialize(ic *interop.Context) error {
return nil
}
func (n *NEO) updateNextValidators(committee keys.PublicKeys, bc blockchainer.Blockchainer) {
func (n *NEO) updateCache(committee keys.PublicKeys, bc blockchainer.Blockchainer) error {
n.committee.Store(committee)
script, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee.Copy())
if err != nil {
return err
}
n.committeeHash.Store(hash.Hash160(script))
nextVals := committee[:bc.GetConfig().ValidatorsCount].Copy()
sort.Sort(nextVals)
n.nextValidators.Store(nextVals)
return nil
}
func (n *NEO) updateCommittee(ic *interop.Context) error {
@ -226,13 +231,9 @@ func (n *NEO) updateCommittee(ic *interop.Context) error {
if err != nil {
return err
}
n.committee.Store(committee)
script, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee.Copy())
if err != nil {
if err := n.updateCache(committee, ic.Chain); err != nil {
return err
}
n.committeeHash.Store(hash.Hash160(script))
n.updateNextValidators(committee, ic.Chain)
n.votesChanged.Store(false)
si := &state.StorageItem{Value: committee.Bytes()}
return ic.DAO.PutStorageItem(n.ContractID, prefixCommittee, si)
@ -246,6 +247,25 @@ func shouldUpdateCommittee(h uint32, bc blockchainer.Blockchainer) bool {
// OnPersist implements Contract interface.
func (n *NEO) OnPersist(ic *interop.Context) error {
gpb := n.gasPerBlockChanged.Load()
if gpb == nil {
committee := keys.PublicKeys{}
si := ic.DAO.GetStorageItem(n.ContractID, prefixCommittee)
if err := committee.DecodeBytes(si.Value); err != nil {
return err
}
if err := n.updateCache(committee, ic.Chain); err != nil {
return err
}
var gr state.GASRecord
si = ic.DAO.GetStorageItem(n.ContractID, []byte{prefixGASPerBlock})
if err := gr.FromBytes(si.Value); err != nil {
return err
}
n.gasPerBlock.Store(gr)
n.gasPerBlockChanged.Store(false)
}
if shouldUpdateCommittee(ic.Block.Index, ic.Chain) {
if err := n.updateCommittee(ic); err != nil {
return err