diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index d230a91ec..e66816531 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -253,6 +253,11 @@ func (bc *Blockchain) init() error { } } + err = bc.contracts.NEO.InitializeCache(bc, bc.dao) + if err != nil { + return fmt.Errorf("can't init cache for NEO native contract: %w", err) + } + return nil } diff --git a/pkg/core/native/contract.go b/pkg/core/native/contract.go index e115d2a0b..e3ab6a18b 100644 --- a/pkg/core/native/contract.go +++ b/pkg/core/native/contract.go @@ -40,8 +40,8 @@ func (cs *Contracts) ByHash(h util.Uint160) interop.Contract { func NewContracts() *Contracts { cs := new(Contracts) - gas := NewGAS() - neo := NewNEO() + gas := newGAS() + neo := newNEO() neo.GAS = gas gas.NEO = neo diff --git a/pkg/core/native/native_gas.go b/pkg/core/native/native_gas.go index 310131086..2913ed45e 100644 --- a/pkg/core/native/native_gas.go +++ b/pkg/core/native/native_gas.go @@ -24,8 +24,8 @@ const gasContractID = -2 const GASFactor = NEOTotalSupply const initialGAS = 30000000 -// NewGAS returns GAS native contract. -func NewGAS() *GAS { +// newGAS returns GAS native contract. +func newGAS() *GAS { g := &GAS{} nep5 := newNEP5Native(gasName) nep5.symbol = "gas" diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index e41979269..43830e1cc 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -89,8 +89,8 @@ func makeValidatorKey(key *keys.PublicKey) []byte { return b } -// NewNEO returns NEO native contract. -func NewNEO() *NEO { +// newNEO returns NEO native contract. +func newNEO() *NEO { n := &NEO{} nep5 := newNEP5Native(neoName) nep5.symbol = "neo" @@ -204,6 +204,30 @@ func (n *NEO) Initialize(ic *interop.Context) error { return nil } +// InitializeCache initializes all NEO cache with the proper values from storage. +// Cache initialisation should be done apart from Initialize because Initialize is +// called only when deploying native contracts. +func (n *NEO) InitializeCache(bc blockchainer.Blockchainer, d dao.DAO) error { + committee := keys.PublicKeys{} + si := d.GetStorageItem(n.ContractID, prefixCommittee) + if err := committee.DecodeBytes(si.Value); err != nil { + return err + } + if err := n.updateCache(committee, bc); err != nil { + return err + } + + var gr state.GASRecord + si = d.GetStorageItem(n.ContractID, []byte{prefixGASPerBlock}) + if err := gr.FromBytes(si.Value); err != nil { + return err + } + n.gasPerBlock.Store(gr) + n.gasPerBlockChanged.Store(false) + + return nil +} + func (n *NEO) updateCache(committee keys.PublicKeys, bc blockchainer.Blockchainer) error { n.committee.Store(committee) script, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee.Copy()) @@ -247,25 +271,6 @@ 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