core: remove mutexes and atomic values from native cache

Native cache is always wrapped into independant layers, so concurrent
RW access is no-op.
This commit is contained in:
Anna Shaleva 2022-04-19 12:26:46 +03:00
parent 7b632c8ee8
commit 8ec8511d9d
6 changed files with 101 additions and 196 deletions

View file

@ -48,11 +48,11 @@ type roleData struct {
} }
type DesignationCache struct { type DesignationCache struct {
rolesChangedFlag atomic.Value rolesChangedFlag bool
oracles atomic.Value oracles roleData
stateVals atomic.Value stateVals roleData
neofsAlphabet atomic.Value neofsAlphabet roleData
notaries atomic.Value notaries roleData
} }
const ( const (
@ -101,24 +101,7 @@ func (c *DesignationCache) Persist(ps storage.NativeContractCache) (storage.Nati
} }
func copyDesignationCache(src, dst *DesignationCache) { func copyDesignationCache(src, dst *DesignationCache) {
dst.rolesChangedFlag.Store(src.rolesChangedFlag.Load()) *dst = *src
for _, r := range []noderoles.Role{noderoles.StateValidator, noderoles.Oracle, noderoles.NeoFSAlphabet, noderoles.P2PNotary} {
data := getCachedRoleData(src, r)
if data != nil {
var v = &roleData{}
*v = *data
switch r {
case noderoles.StateValidator:
dst.stateVals.Store(v)
case noderoles.Oracle:
dst.oracles.Store(v)
case noderoles.NeoFSAlphabet:
dst.neofsAlphabet.Store(v)
case noderoles.P2PNotary:
dst.notaries.Store(v)
}
}
}
} }
func (s *Designate) isValidRole(r noderoles.Role) bool { func (s *Designate) isValidRole(r noderoles.Role) bool {
@ -153,7 +136,7 @@ func newDesignate(p2pSigExtensionsEnabled bool) *Designate {
// Initialize initializes Oracle contract. // Initialize initializes Oracle contract.
func (s *Designate) Initialize(ic *interop.Context) error { func (s *Designate) Initialize(ic *interop.Context) error {
cache := &DesignationCache{} cache := &DesignationCache{}
cache.rolesChangedFlag.Store(true) cache.rolesChangedFlag = true
ic.DAO.Store.SetCache(s.ID, cache) ic.DAO.Store.SetCache(s.ID, cache)
return nil return nil
} }
@ -185,7 +168,7 @@ func (s *Designate) PostPersist(ic *interop.Context) error {
} }
} }
cache.rolesChangedFlag.Store(false) cache.rolesChangedFlag = false
return nil return nil
} }
@ -215,8 +198,7 @@ func (s *Designate) getDesignatedByRole(ic *interop.Context, args []stackitem.It
} }
func rolesChanged(cache *DesignationCache) bool { func rolesChanged(cache *DesignationCache) bool {
rc := cache.rolesChangedFlag.Load() return cache.rolesChangedFlag
return rc == nil || rc.(bool)
} }
func (s *Designate) hashFromNodes(r noderoles.Role, nodes keys.PublicKeys) util.Uint160 { func (s *Designate) hashFromNodes(r noderoles.Role, nodes keys.PublicKeys) util.Uint160 {
@ -233,16 +215,14 @@ func (s *Designate) hashFromNodes(r noderoles.Role, nodes keys.PublicKeys) util.
return hash.Hash160(script) return hash.Hash160(script)
} }
func (s *Designate) updateCachedRoleData(v *atomic.Value, d *dao.Simple, r noderoles.Role) error { func (s *Designate) updateCachedRoleData(v *roleData, d *dao.Simple, r noderoles.Role) error {
nodeKeys, height, err := s.GetDesignatedByRole(d, r, math.MaxUint32) nodeKeys, height, err := s.GetDesignatedByRole(d, r, math.MaxUint32)
if err != nil { if err != nil {
return err return err
} }
v.Store(&roleData{ v.nodes = nodeKeys
nodes: nodeKeys, v.addr = s.hashFromNodes(r, nodeKeys)
addr: s.hashFromNodes(r, nodeKeys), v.height = height
height: height,
})
switch r { switch r {
case noderoles.Oracle: case noderoles.Oracle:
if orc, _ := s.OracleService.Load().(services.Oracle); orc != nil { if orc, _ := s.OracleService.Load().(services.Oracle); orc != nil {
@ -261,19 +241,15 @@ func (s *Designate) updateCachedRoleData(v *atomic.Value, d *dao.Simple, r noder
} }
func getCachedRoleData(cache *DesignationCache, r noderoles.Role) *roleData { func getCachedRoleData(cache *DesignationCache, r noderoles.Role) *roleData {
var val interface{}
switch r { switch r {
case noderoles.Oracle: case noderoles.Oracle:
val = cache.oracles.Load() return &cache.oracles
case noderoles.StateValidator: case noderoles.StateValidator:
val = cache.stateVals.Load() return &cache.stateVals
case noderoles.NeoFSAlphabet: case noderoles.NeoFSAlphabet:
val = cache.neofsAlphabet.Load() return &cache.neofsAlphabet
case noderoles.P2PNotary: case noderoles.P2PNotary:
val = cache.notaries.Load() return &cache.notaries
}
if val != nil {
return val.(*roleData)
} }
return nil return nil
} }
@ -381,7 +357,7 @@ func (s *Designate) DesignateAsRole(ic *interop.Context, r noderoles.Role, pubs
} }
sort.Sort(pubs) sort.Sort(pubs)
nl := NodeList(pubs) nl := NodeList(pubs)
ic.DAO.Store.GetRWCache(s.ID).(*DesignationCache).rolesChangedFlag.Store(true) ic.DAO.Store.GetRWCache(s.ID).(*DesignationCache).rolesChangedFlag = true
err := putConvertibleToDAO(s.ID, ic.DAO, key, &nl) err := putConvertibleToDAO(s.ID, ic.DAO, key, &nl)
if err != nil { if err != nil {
return err return err
@ -413,6 +389,6 @@ func (s *Designate) getRole(item stackitem.Item) (noderoles.Role, bool) {
// InitializeCache invalidates native Designate cache. // InitializeCache invalidates native Designate cache.
func (s *Designate) InitializeCache(d *dao.Simple) { func (s *Designate) InitializeCache(d *dao.Simple) {
cache := &DesignationCache{} cache := &DesignationCache{}
cache.rolesChangedFlag.Store(true) cache.rolesChangedFlag = true
d.Store.SetCache(s.ID, cache) d.Store.SetCache(s.ID, cache)
} }

View file

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
"sync"
"unicode/utf8" "unicode/utf8"
"github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/dao"
@ -33,7 +32,6 @@ type Management struct {
} }
type ManagementCache struct { type ManagementCache struct {
mtx sync.RWMutex
contracts map[util.Uint160]*state.Contract contracts map[util.Uint160]*state.Contract
// nep11 is a map of NEP11-compliant contracts which is updated with every PostPersist. // nep11 is a map of NEP11-compliant contracts which is updated with every PostPersist.
nep11 map[util.Uint160]struct{} nep11 map[util.Uint160]struct{}
@ -188,9 +186,7 @@ func (m *Management) getContract(ic *interop.Context, args []stackitem.Item) sta
// GetContract returns contract with given hash from given DAO. // GetContract returns contract with given hash from given DAO.
func (m *Management) GetContract(d *dao.Simple, hash util.Uint160) (*state.Contract, error) { func (m *Management) GetContract(d *dao.Simple, hash util.Uint160) (*state.Contract, error) {
cache := d.Store.GetROCache(m.ID).(*ManagementCache) cache := d.Store.GetROCache(m.ID).(*ManagementCache)
cache.mtx.RLock()
cs, ok := cache.contracts[hash] cs, ok := cache.contracts[hash]
cache.mtx.RUnlock()
if !ok { if !ok {
return nil, storage.ErrKeyNotFound return nil, storage.ErrKeyNotFound
} else if cs != nil { } else if cs != nil {
@ -304,10 +300,8 @@ func (m *Management) deployWithData(ic *interop.Context, args []stackitem.Item)
func (m *Management) markUpdated(d *dao.Simple, h util.Uint160) { func (m *Management) markUpdated(d *dao.Simple, h util.Uint160) {
cache := d.Store.GetRWCache(m.ID).(*ManagementCache) cache := d.Store.GetRWCache(m.ID).(*ManagementCache)
cache.mtx.Lock()
// Just set it to nil, to refresh cache in `PostPersist`. // Just set it to nil, to refresh cache in `PostPersist`.
cache.contracts[h] = nil cache.contracts[h] = nil
cache.mtx.Unlock()
} }
// Deploy creates contract's hash/ID and saves new contract into the given DAO. // Deploy creates contract's hash/ID and saves new contract into the given DAO.
@ -520,9 +514,7 @@ func (m *Management) OnPersist(ic *interop.Context) error {
if cache == nil { if cache == nil {
cache = ic.DAO.Store.GetRWCache(m.ID).(*ManagementCache) cache = ic.DAO.Store.GetRWCache(m.ID).(*ManagementCache)
} }
cache.mtx.Lock()
updateContractCache(cache, cs) updateContractCache(cache, cs)
cache.mtx.Unlock()
} }
return nil return nil
@ -558,8 +550,6 @@ func (m *Management) InitializeCache(d *dao.Simple) error {
// PostPersist implements Contract interface. // PostPersist implements Contract interface.
func (m *Management) PostPersist(ic *interop.Context) error { func (m *Management) PostPersist(ic *interop.Context) error {
cache := ic.DAO.Store.GetRWCache(m.ID).(*ManagementCache) cache := ic.DAO.Store.GetRWCache(m.ID).(*ManagementCache)
cache.mtx.Lock()
defer cache.mtx.Unlock()
for h, cs := range cache.contracts { for h, cs := range cache.contracts {
if cs != nil { if cs != nil {
continue continue
@ -582,12 +572,10 @@ func (m *Management) PostPersist(ic *interop.Context) error {
// is returned. // is returned.
func (m *Management) GetNEP11Contracts(d *dao.Simple) []util.Uint160 { func (m *Management) GetNEP11Contracts(d *dao.Simple) []util.Uint160 {
cache := d.Store.GetROCache(m.ID).(*ManagementCache) cache := d.Store.GetROCache(m.ID).(*ManagementCache)
cache.mtx.RLock()
result := make([]util.Uint160, 0, len(cache.nep11)) result := make([]util.Uint160, 0, len(cache.nep11))
for h := range cache.nep11 { for h := range cache.nep11 {
result = append(result, h) result = append(result, h)
} }
cache.mtx.RUnlock()
return result return result
} }
@ -596,12 +584,10 @@ func (m *Management) GetNEP11Contracts(d *dao.Simple) []util.Uint160 {
// is returned. // is returned.
func (m *Management) GetNEP17Contracts(d *dao.Simple) []util.Uint160 { func (m *Management) GetNEP17Contracts(d *dao.Simple) []util.Uint160 {
cache := d.Store.GetROCache(m.ID).(*ManagementCache) cache := d.Store.GetROCache(m.ID).(*ManagementCache)
cache.mtx.RLock()
result := make([]util.Uint160, 0, len(cache.nep17)) result := make([]util.Uint160, 0, len(cache.nep17))
for h := range cache.nep17 { for h := range cache.nep17 {
result = append(result, h) result = append(result, h)
} }
cache.mtx.RUnlock()
return result return result
} }

View file

@ -8,7 +8,6 @@ import (
"math/big" "math/big"
"sort" "sort"
"strings" "strings"
"sync/atomic"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/dao"
@ -44,22 +43,22 @@ type NEO struct {
type NeoCache struct { type NeoCache struct {
// gasPerBlock represents current value of generated gas per block. // gasPerBlock represents current value of generated gas per block.
// It is append-only and doesn't need to be copied when used. // It is append-only and doesn't need to be copied when used.
gasPerBlock atomic.Value gasPerBlock gasRecord
gasPerBlockChanged atomic.Value gasPerBlockChanged bool
registerPrice atomic.Value registerPrice int64
registerPriceChanged atomic.Value registerPriceChanged bool
votesChanged atomic.Value votesChanged bool
nextValidators atomic.Value nextValidators keys.PublicKeys
validators atomic.Value validators keys.PublicKeys
// committee contains cached committee members and their votes. // committee contains cached committee members and their votes.
// It is updated once in a while depending on committee size // It is updated once in a while depending on committee size
// (every 28 blocks for mainnet). It's value // (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 keysWithVotes
// committeeHash contains script hash of the committee. // committeeHash contains script hash of the committee.
committeeHash atomic.Value committeeHash util.Uint160
// gasPerVoteCache contains last updated value of GAS per vote reward for candidates. // gasPerVoteCache contains last updated value of GAS per vote reward for candidates.
// It is set in state-modifying methods only and read in `PostPersist` thus is not protected // It is set in state-modifying methods only and read in `PostPersist` thus is not protected
@ -134,27 +133,21 @@ func (c *NeoCache) Persist(ps storage.NativeContractCache) (storage.NativeContra
} }
func copyNeoCache(src, dst *NeoCache) { func copyNeoCache(src, dst *NeoCache) {
dst.votesChanged.Store(src.votesChanged.Load()) dst.votesChanged = src.votesChanged
dst.nextValidators.Store(src.nextValidators.Load().(keys.PublicKeys).Copy()) dst.nextValidators = src.nextValidators.Copy()
dst.validators.Store(src.validators.Load().(keys.PublicKeys).Copy()) dst.validators = src.validators.Copy()
committeeSrc := src.committee.Load().(keysWithVotes)
committeeDst := make(keysWithVotes, len(committeeSrc)) dst.committee = make(keysWithVotes, len(src.committee))
copy(committeeDst, committeeSrc) copy(dst.committee, src.committee)
dst.committee.Store(committeeDst) dst.committeeHash = src.committeeHash
dst.committeeHash.Store(src.committeeHash.Load())
regPriceChanged := src.registerPriceChanged.Load().(bool) dst.registerPriceChanged = src.registerPriceChanged
dst.registerPriceChanged.Store(regPriceChanged) dst.registerPrice = src.registerPrice
if !regPriceChanged {
dst.registerPrice.Store(src.registerPrice.Load()) dst.gasPerBlockChanged = src.gasPerBlockChanged
} dst.gasPerBlock = make(gasRecord, len(src.gasPerBlock))
gasPerBlockChanged := src.gasPerBlockChanged.Load().(bool) copy(dst.gasPerBlock, src.gasPerBlock)
dst.gasPerBlockChanged.Store(gasPerBlockChanged)
if !gasPerBlockChanged {
recordsSrc := src.gasPerBlock.Load().(gasRecord)
recordsDst := make(gasRecord, len(recordsSrc))
copy(recordsDst, recordsSrc)
dst.gasPerBlock.Store(recordsDst)
}
dst.gasPerVoteCache = make(map[string]big.Int) dst.gasPerVoteCache = make(map[string]big.Int)
for k, v := range src.gasPerVoteCache { for k, v := range src.gasPerVoteCache {
dst.gasPerVoteCache[k] = v dst.gasPerVoteCache[k] = v
@ -262,14 +255,10 @@ func (n *NEO) Initialize(ic *interop.Context) error {
} }
cache := &NeoCache{ cache := &NeoCache{
gasPerVoteCache: make(map[string]big.Int), gasPerVoteCache: make(map[string]big.Int),
votesChanged: true,
registerPriceChanged: true,
} }
cache.votesChanged.Store(true)
cache.nextValidators.Store(keys.PublicKeys(nil))
cache.validators.Store(keys.PublicKeys(nil))
cache.committee.Store(keysWithVotes(nil))
cache.committeeHash.Store(util.Uint160{})
cache.registerPriceChanged.Store(true)
// We need cache to be present in DAO before the subsequent call to `mint`. // We need cache to be present in DAO before the subsequent call to `mint`.
ic.DAO.Store.SetCache(n.ID, cache) ic.DAO.Store.SetCache(n.ID, cache)
@ -294,13 +283,13 @@ func (n *NEO) Initialize(ic *interop.Context) error {
n.putGASRecord(ic.DAO, index, value) n.putGASRecord(ic.DAO, index, value)
gr := &gasRecord{{Index: index, GASPerBlock: *value}} gr := &gasRecord{{Index: index, GASPerBlock: *value}}
cache.gasPerBlock.Store(*gr) cache.gasPerBlock = *gr
cache.gasPerBlockChanged.Store(false) cache.gasPerBlockChanged = false
ic.DAO.PutStorageItem(n.ID, []byte{prefixVotersCount}, state.StorageItem{}) ic.DAO.PutStorageItem(n.ID, []byte{prefixVotersCount}, state.StorageItem{})
setIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice}, DefaultRegisterPrice) setIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice}, DefaultRegisterPrice)
cache.registerPrice.Store(int64(DefaultRegisterPrice)) cache.registerPrice = int64(DefaultRegisterPrice)
cache.registerPriceChanged.Store(false) cache.registerPriceChanged = false
return nil return nil
} }
@ -310,16 +299,11 @@ func (n *NEO) Initialize(ic *interop.Context) error {
// called only when deploying native contracts. // called only when deploying native contracts.
func (n *NEO) InitializeCache(bc interop.Ledger, d *dao.Simple) error { func (n *NEO) InitializeCache(bc interop.Ledger, d *dao.Simple) error {
cache := &NeoCache{ cache := &NeoCache{
gasPerVoteCache: make(map[string]big.Int), gasPerVoteCache: make(map[string]big.Int),
votesChanged: true,
registerPriceChanged: true,
} }
cache.votesChanged.Store(true)
cache.nextValidators.Store(keys.PublicKeys(nil))
cache.validators.Store(keys.PublicKeys(nil))
cache.committee.Store(keysWithVotes(nil))
cache.committeeHash.Store(util.Uint160{})
cache.registerPriceChanged.Store(true)
var committee = keysWithVotes{} var committee = keysWithVotes{}
si := d.GetStorageItem(n.ID, prefixCommittee) si := d.GetStorageItem(n.ID, prefixCommittee)
if err := committee.DecodeBytes(si); err != nil { if err := committee.DecodeBytes(si); err != nil {
@ -329,8 +313,8 @@ func (n *NEO) InitializeCache(bc interop.Ledger, d *dao.Simple) error {
return fmt.Errorf("failed to update cache: %w", err) return fmt.Errorf("failed to update cache: %w", err)
} }
cache.gasPerBlock.Store(n.getSortedGASRecordFromDAO(d)) cache.gasPerBlock = n.getSortedGASRecordFromDAO(d)
cache.gasPerBlockChanged.Store(false) cache.gasPerBlockChanged = false
d.Store.SetCache(n.ID, cache) d.Store.SetCache(n.ID, cache)
return nil return nil
@ -345,28 +329,26 @@ func (n *NEO) initConfigCache(cfg config.ProtocolConfiguration) error {
} }
func (n *NEO) updateCache(cache *NeoCache, cvs keysWithVotes, bc interop.Ledger) error { func (n *NEO) updateCache(cache *NeoCache, cvs keysWithVotes, bc interop.Ledger) error {
cache.committee.Store(cvs) cache.committee = cvs
var committee = getCommitteeMembers(cache) var committee = getCommitteeMembers(cache)
script, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee.Copy()) script, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee.Copy())
if err != nil { if err != nil {
return err return err
} }
cache.committeeHash.Store(hash.Hash160(script)) cache.committeeHash = hash.Hash160(script)
// TODO: use block height from interop context for proper historical calls handling. // TODO: use block height from interop context for proper historical calls handling.
nextVals := committee[:n.cfg.GetNumOfCNs(bc.BlockHeight()+1)].Copy() nextVals := committee[:n.cfg.GetNumOfCNs(bc.BlockHeight()+1)].Copy()
sort.Sort(nextVals) sort.Sort(nextVals)
cache.nextValidators.Store(nextVals) cache.nextValidators = nextVals
return nil return nil
} }
func (n *NEO) updateCommittee(cache *NeoCache, ic *interop.Context) error { func (n *NEO) updateCommittee(cache *NeoCache, ic *interop.Context) error {
votesChanged := cache.votesChanged.Load().(bool) if !cache.votesChanged {
if !votesChanged {
// We need to put in storage anyway, as it affects dumps // We need to put in storage anyway, as it affects dumps
committee := cache.committee.Load().(keysWithVotes) ic.DAO.PutStorageItem(n.ID, prefixCommittee, cache.committee.Bytes())
ic.DAO.PutStorageItem(n.ID, prefixCommittee, committee.Bytes())
return nil return nil
} }
@ -377,7 +359,7 @@ func (n *NEO) updateCommittee(cache *NeoCache, ic *interop.Context) error {
if err := n.updateCache(cache, cvs, ic.Chain); err != nil { if err := n.updateCache(cache, cvs, ic.Chain); err != nil {
return err return err
} }
cache.votesChanged.Store(false) cache.votesChanged = false
ic.DAO.PutStorageItem(n.ID, prefixCommittee, cvs.Bytes()) ic.DAO.PutStorageItem(n.ID, prefixCommittee, cvs.Bytes())
return nil return nil
} }
@ -386,11 +368,11 @@ func (n *NEO) updateCommittee(cache *NeoCache, ic *interop.Context) error {
func (n *NEO) OnPersist(ic *interop.Context) error { func (n *NEO) OnPersist(ic *interop.Context) error {
if n.cfg.ShouldUpdateCommitteeAt(ic.Block.Index) { if n.cfg.ShouldUpdateCommitteeAt(ic.Block.Index) {
cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache) cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache)
oldKeys := cache.nextValidators.Load().(keys.PublicKeys) oldKeys := cache.nextValidators
oldCom := cache.committee.Load().(keysWithVotes) oldCom := cache.committee
if n.cfg.GetNumOfCNs(ic.Block.Index) != len(oldKeys) || if n.cfg.GetNumOfCNs(ic.Block.Index) != len(oldKeys) ||
n.cfg.GetCommitteeSize(ic.Block.Index) != len(oldCom) { n.cfg.GetCommitteeSize(ic.Block.Index) != len(oldCom) {
cache.votesChanged.Store(true) cache.votesChanged = true
} }
if err := n.updateCommittee(cache, ic); err != nil { if err := n.updateCommittee(cache, ic); err != nil {
return err return err
@ -417,7 +399,7 @@ func (n *NEO) PostPersist(ic *interop.Context) error {
voterReward.Div(voterReward, big.NewInt(int64(committeeSize+validatorsCount))) voterReward.Div(voterReward, big.NewInt(int64(committeeSize+validatorsCount)))
voterReward.Div(voterReward, big100) voterReward.Div(voterReward, big100)
var cs = cache.committee.Load().(keysWithVotes) var cs = cache.committee
var key = make([]byte, 38) var key = make([]byte, 38)
for i := range cs { for i := range cs {
if cs[i].Votes.Sign() > 0 { if cs[i].Votes.Sign() > 0 {
@ -448,15 +430,15 @@ func (n *NEO) PostPersist(ic *interop.Context) error {
} }
} }
} }
if cache.gasPerBlockChanged.Load().(bool) { if cache.gasPerBlockChanged {
cache.gasPerBlock.Store(n.getSortedGASRecordFromDAO(ic.DAO)) cache.gasPerBlock = n.getSortedGASRecordFromDAO(ic.DAO)
cache.gasPerBlockChanged.Store(false) cache.gasPerBlockChanged = false
} }
if cache.registerPriceChanged.Load().(bool) { if cache.registerPriceChanged {
p := getIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice}) p := getIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice})
cache.registerPrice.Store(p) cache.registerPrice = p
cache.registerPriceChanged.Store(false) cache.registerPriceChanged = false
} }
return nil return nil
} }
@ -581,10 +563,10 @@ func (n *NEO) getSortedGASRecordFromDAO(d *dao.Simple) gasRecord {
func (n *NEO) GetGASPerBlock(d *dao.Simple, index uint32) *big.Int { func (n *NEO) GetGASPerBlock(d *dao.Simple, index uint32) *big.Int {
cache := d.Store.GetROCache(n.ID).(*NeoCache) cache := d.Store.GetROCache(n.ID).(*NeoCache)
var gr gasRecord var gr gasRecord
if cache.gasPerBlockChanged.Load().(bool) { if cache.gasPerBlockChanged {
gr = n.getSortedGASRecordFromDAO(d) gr = n.getSortedGASRecordFromDAO(d)
} else { } else {
gr = cache.gasPerBlock.Load().(gasRecord) gr = cache.gasPerBlock
} }
for i := len(gr) - 1; i >= 0; i-- { for i := len(gr) - 1; i >= 0; i-- {
if gr[i].Index <= index { if gr[i].Index <= index {
@ -598,7 +580,7 @@ func (n *NEO) GetGASPerBlock(d *dao.Simple, index uint32) *big.Int {
// GetCommitteeAddress returns address of the committee. // GetCommitteeAddress returns address of the committee.
func (n *NEO) GetCommitteeAddress(d *dao.Simple) util.Uint160 { func (n *NEO) GetCommitteeAddress(d *dao.Simple) util.Uint160 {
cache := d.Store.GetROCache(n.ID).(*NeoCache) cache := d.Store.GetROCache(n.ID).(*NeoCache)
return cache.committeeHash.Load().(util.Uint160) return cache.committeeHash
} }
func (n *NEO) checkCommittee(ic *interop.Context) bool { func (n *NEO) checkCommittee(ic *interop.Context) bool {
@ -627,7 +609,7 @@ func (n *NEO) SetGASPerBlock(ic *interop.Context, index uint32, gas *big.Int) er
return errors.New("invalid committee signature") return errors.New("invalid committee signature")
} }
cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache) cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache)
cache.gasPerBlockChanged.Store(true) cache.gasPerBlockChanged = true
n.putGASRecord(ic.DAO, index, gas) n.putGASRecord(ic.DAO, index, gas)
return nil return nil
} }
@ -638,8 +620,8 @@ func (n *NEO) getRegisterPrice(ic *interop.Context, _ []stackitem.Item) stackite
func (n *NEO) getRegisterPriceInternal(d *dao.Simple) int64 { func (n *NEO) getRegisterPriceInternal(d *dao.Simple) int64 {
cache := d.Store.GetROCache(n.ID).(*NeoCache) cache := d.Store.GetROCache(n.ID).(*NeoCache)
if !cache.registerPriceChanged.Load().(bool) { if !cache.registerPriceChanged {
return cache.registerPrice.Load().(int64) return cache.registerPrice
} }
return getIntWithKey(n.ID, d, []byte{prefixRegisterPrice}) return getIntWithKey(n.ID, d, []byte{prefixRegisterPrice})
} }
@ -655,7 +637,7 @@ func (n *NEO) setRegisterPrice(ic *interop.Context, args []stackitem.Item) stack
setIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice}, price.Int64()) setIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice}, price.Int64())
cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache) cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache)
cache.registerPriceChanged.Store(true) cache.registerPriceChanged = true
return stackitem.Null{} return stackitem.Null{}
} }
@ -726,8 +708,8 @@ func (n *NEO) CalculateNEOHolderReward(d *dao.Simple, value *big.Int, start, end
} }
var gr gasRecord var gr gasRecord
cache := d.Store.GetROCache(n.ID).(*NeoCache) cache := d.Store.GetROCache(n.ID).(*NeoCache)
if !cache.gasPerBlockChanged.Load().(bool) { if !cache.gasPerBlockChanged {
gr = cache.gasPerBlock.Load().(gasRecord) gr = cache.gasPerBlock
} else { } else {
gr = n.getSortedGASRecordFromDAO(d) gr = n.getSortedGASRecordFromDAO(d)
} }
@ -801,7 +783,7 @@ func (n *NEO) UnregisterCandidateInternal(ic *interop.Context, pub *keys.PublicK
return nil return nil
} }
cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache) cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache)
cache.validators.Store(keys.PublicKeys(nil)) cache.validators = nil
c := new(candidate).FromBytes(si) c := new(candidate).FromBytes(si)
c.Registered = false c.Registered = false
ok, err := n.dropCandidateIfZero(ic.DAO, cache, pub, c) ok, err := n.dropCandidateIfZero(ic.DAO, cache, pub, c)
@ -881,7 +863,7 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public
// 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.NEOBalance, d *dao.Simple, value *big.Int, isNewVote bool) error { func (n *NEO) ModifyAccountVotes(acc *state.NEOBalance, d *dao.Simple, value *big.Int, isNewVote bool) error {
cache := d.Store.GetRWCache(n.ID).(*NeoCache) cache := d.Store.GetRWCache(n.ID).(*NeoCache)
cache.votesChanged.Store(true) cache.votesChanged = true
if acc.VoteTo != nil { if acc.VoteTo != nil {
key := makeValidatorKey(acc.VoteTo) key := makeValidatorKey(acc.VoteTo)
si := d.GetStorageItem(n.ID, key) si := d.GetStorageItem(n.ID, key)
@ -896,7 +878,7 @@ func (n *NEO) ModifyAccountVotes(acc *state.NEOBalance, d *dao.Simple, value *bi
return err return err
} }
} }
cache.validators.Store(keys.PublicKeys(nil)) cache.validators = nil
return putConvertibleToDAO(n.ID, d, key, cd) return putConvertibleToDAO(n.ID, d, key, cd)
} }
return nil return nil
@ -992,7 +974,7 @@ func (n *NEO) getAccountState(ic *interop.Context, args []stackitem.Item) stacki
func (n *NEO) ComputeNextBlockValidators(bc interop.Ledger, d *dao.Simple) (keys.PublicKeys, error) { func (n *NEO) ComputeNextBlockValidators(bc interop.Ledger, d *dao.Simple) (keys.PublicKeys, error) {
numOfCNs := n.cfg.GetNumOfCNs(bc.BlockHeight() + 1) numOfCNs := n.cfg.GetNumOfCNs(bc.BlockHeight() + 1)
cache := d.Store.GetRWCache(n.ID).(*NeoCache) cache := d.Store.GetRWCache(n.ID).(*NeoCache)
if vals := cache.validators.Load().(keys.PublicKeys); vals != nil && numOfCNs == len(vals) { if vals := cache.validators; vals != nil && numOfCNs == len(vals) {
return vals.Copy(), nil return vals.Copy(), nil
} }
result, _, err := n.computeCommitteeMembers(bc, d) result, _, err := n.computeCommitteeMembers(bc, d)
@ -1001,7 +983,7 @@ func (n *NEO) ComputeNextBlockValidators(bc interop.Ledger, d *dao.Simple) (keys
} }
result = result[:numOfCNs] result = result[:numOfCNs]
sort.Sort(result) sort.Sort(result)
cache.validators.Store(result) cache.validators = result
return result, nil return result, nil
} }
@ -1031,7 +1013,7 @@ func (n *NEO) GetCommitteeMembers(d *dao.Simple) keys.PublicKeys {
} }
func getCommitteeMembers(cache *NeoCache) keys.PublicKeys { func getCommitteeMembers(cache *NeoCache) keys.PublicKeys {
var cvs = cache.committee.Load().(keysWithVotes) var cvs = cache.committee
var committee = make(keys.PublicKeys, len(cvs)) var committee = make(keys.PublicKeys, len(cvs))
var err error var err error
for i := range committee { for i := range committee {
@ -1107,7 +1089,7 @@ func (n *NEO) getNextBlockValidators(ic *interop.Context, _ []stackitem.Item) st
// GetNextBlockValidatorsInternal returns next block validators. // GetNextBlockValidatorsInternal returns next block validators.
func (n *NEO) GetNextBlockValidatorsInternal(d *dao.Simple) keys.PublicKeys { func (n *NEO) GetNextBlockValidatorsInternal(d *dao.Simple) keys.PublicKeys {
cache := d.Store.GetROCache(n.ID).(*NeoCache) cache := d.Store.GetROCache(n.ID).(*NeoCache)
return cache.nextValidators.Load().(keys.PublicKeys).Copy() return cache.nextValidators.Copy()
} }
// BalanceOf returns native NEO token balance for the acc. // BalanceOf returns native NEO token balance for the acc.

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
"sync"
"github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop"
@ -35,7 +34,6 @@ type Notary struct {
} }
type NotaryCache struct { type NotaryCache struct {
lock sync.RWMutex
// isValid defies whether cached values were changed during the current // isValid defies whether cached values were changed during the current
// consensus iteration. If false, these values will be updated after // consensus iteration. If false, these values will be updated after
// blockchain DAO persisting. If true, we can safely use cached values. // blockchain DAO persisting. If true, we can safely use cached values.
@ -84,9 +82,7 @@ func (c *NotaryCache) Persist(ps storage.NativeContractCache) (storage.NativeCon
} }
func copyNotaryCache(src, dst *NotaryCache) { func copyNotaryCache(src, dst *NotaryCache) {
dst.isValid = src.isValid *dst = *src
dst.maxNotValidBeforeDelta = src.maxNotValidBeforeDelta
dst.notaryServiceFeePerKey = src.notaryServiceFeePerKey
} }
// newNotary returns Notary native contract. // newNotary returns Notary native contract.
@ -224,8 +220,6 @@ func (n *Notary) OnPersist(ic *interop.Context) error {
// PostPersist implements Contract interface. // PostPersist implements Contract interface.
func (n *Notary) PostPersist(ic *interop.Context) error { func (n *Notary) PostPersist(ic *interop.Context) error {
cache := ic.DAO.Store.GetRWCache(n.ID).(*NotaryCache) cache := ic.DAO.Store.GetRWCache(n.ID).(*NotaryCache)
cache.lock.Lock()
defer cache.lock.Unlock()
if cache.isValid { if cache.isValid {
return nil return nil
} }
@ -440,8 +434,6 @@ func (n *Notary) getMaxNotValidBeforeDelta(ic *interop.Context, _ []stackitem.It
// GetMaxNotValidBeforeDelta is an internal representation of Notary getMaxNotValidBeforeDelta method. // GetMaxNotValidBeforeDelta is an internal representation of Notary getMaxNotValidBeforeDelta method.
func (n *Notary) GetMaxNotValidBeforeDelta(dao *dao.Simple) uint32 { func (n *Notary) GetMaxNotValidBeforeDelta(dao *dao.Simple) uint32 {
cache := dao.Store.GetROCache(n.ID).(*NotaryCache) cache := dao.Store.GetROCache(n.ID).(*NotaryCache)
cache.lock.RLock()
defer cache.lock.RUnlock()
if cache.isValid { if cache.isValid {
return cache.maxNotValidBeforeDelta return cache.maxNotValidBeforeDelta
} }
@ -460,8 +452,6 @@ func (n *Notary) setMaxNotValidBeforeDelta(ic *interop.Context, args []stackitem
panic("invalid committee signature") panic("invalid committee signature")
} }
cache := ic.DAO.Store.GetRWCache(n.ID).(*NotaryCache) cache := ic.DAO.Store.GetRWCache(n.ID).(*NotaryCache)
cache.lock.Lock()
defer cache.lock.Unlock()
setIntWithKey(n.ID, ic.DAO, maxNotValidBeforeDeltaKey, int64(value)) setIntWithKey(n.ID, ic.DAO, maxNotValidBeforeDeltaKey, int64(value))
cache.isValid = false cache.isValid = false
return stackitem.Null{} return stackitem.Null{}
@ -475,8 +465,6 @@ func (n *Notary) getNotaryServiceFeePerKey(ic *interop.Context, _ []stackitem.It
// GetNotaryServiceFeePerKey is an internal representation of Notary getNotaryServiceFeePerKey method. // GetNotaryServiceFeePerKey is an internal representation of Notary getNotaryServiceFeePerKey method.
func (n *Notary) GetNotaryServiceFeePerKey(dao *dao.Simple) int64 { func (n *Notary) GetNotaryServiceFeePerKey(dao *dao.Simple) int64 {
cache := dao.Store.GetROCache(n.ID).(*NotaryCache) cache := dao.Store.GetROCache(n.ID).(*NotaryCache)
cache.lock.RLock()
defer cache.lock.RUnlock()
if cache.isValid { if cache.isValid {
return cache.notaryServiceFeePerKey return cache.notaryServiceFeePerKey
} }
@ -493,8 +481,6 @@ func (n *Notary) setNotaryServiceFeePerKey(ic *interop.Context, args []stackitem
panic("invalid committee signature") panic("invalid committee signature")
} }
cache := ic.DAO.Store.GetRWCache(n.ID).(*NotaryCache) cache := ic.DAO.Store.GetRWCache(n.ID).(*NotaryCache)
cache.lock.Lock()
defer cache.lock.Unlock()
setIntWithKey(n.ID, ic.DAO, notaryServiceFeeKey, int64(value)) setIntWithKey(n.ID, ic.DAO, notaryServiceFeeKey, int64(value))
cache.isValid = false cache.isValid = false
return stackitem.Null{} return stackitem.Null{}

View file

@ -47,8 +47,8 @@ type Oracle struct {
} }
type OracleCache struct { type OracleCache struct {
requestPrice atomic.Value requestPrice int64
requestPriceChanged atomic.Value requestPriceChanged bool
} }
const ( const (
@ -110,8 +110,7 @@ func (c *OracleCache) Persist(ps storage.NativeContractCache) (storage.NativeCon
} }
func copyOracleCache(src, dst *OracleCache) { func copyOracleCache(src, dst *OracleCache) {
dst.requestPrice.Store(src.requestPrice.Load()) *dst = *src
dst.requestPriceChanged.Store(src.requestPriceChanged.Load())
} }
func newOracle() *Oracle { func newOracle() *Oracle {
@ -174,9 +173,9 @@ func (o *Oracle) OnPersist(ic *interop.Context) error {
func (o *Oracle) PostPersist(ic *interop.Context) error { func (o *Oracle) PostPersist(ic *interop.Context) error {
p := o.getPriceInternal(ic.DAO) p := o.getPriceInternal(ic.DAO)
cache := ic.DAO.Store.GetRWCache(o.ID).(*OracleCache) cache := ic.DAO.Store.GetRWCache(o.ID).(*OracleCache)
if cache.requestPriceChanged.Load().(bool) { if cache.requestPriceChanged {
cache.requestPrice.Store(p) cache.requestPrice = p
cache.requestPriceChanged.Store(false) cache.requestPriceChanged = false
} }
var nodes keys.PublicKeys var nodes keys.PublicKeys
@ -253,16 +252,16 @@ func (o *Oracle) Initialize(ic *interop.Context) error {
setIntWithKey(o.ID, ic.DAO, prefixRequestPrice, DefaultOracleRequestPrice) setIntWithKey(o.ID, ic.DAO, prefixRequestPrice, DefaultOracleRequestPrice)
cache := &OracleCache{} cache := &OracleCache{}
cache.requestPrice.Store(int64(DefaultOracleRequestPrice)) cache.requestPrice = int64(DefaultOracleRequestPrice)
cache.requestPriceChanged.Store(false) cache.requestPriceChanged = false
ic.DAO.Store.SetCache(o.ID, cache) ic.DAO.Store.SetCache(o.ID, cache)
return nil return nil
} }
func (o *Oracle) InitializeCache(d *dao.Simple) { func (o *Oracle) InitializeCache(d *dao.Simple) {
cache := &OracleCache{} cache := &OracleCache{}
cache.requestPrice.Store(getIntWithKey(o.ID, d, prefixRequestPrice)) cache.requestPrice = getIntWithKey(o.ID, d, prefixRequestPrice)
cache.requestPriceChanged.Store(false) cache.requestPriceChanged = false
d.Store.SetCache(o.ID, cache) d.Store.SetCache(o.ID, cache)
} }
@ -481,8 +480,8 @@ func (o *Oracle) getPrice(ic *interop.Context, _ []stackitem.Item) stackitem.Ite
func (o *Oracle) getPriceInternal(d *dao.Simple) int64 { func (o *Oracle) getPriceInternal(d *dao.Simple) int64 {
cache := d.Store.GetROCache(o.ID).(*OracleCache) cache := d.Store.GetROCache(o.ID).(*OracleCache)
if !cache.requestPriceChanged.Load().(bool) { if !cache.requestPriceChanged {
return cache.requestPrice.Load().(int64) return cache.requestPrice
} }
return getIntWithKey(o.ID, d, prefixRequestPrice) return getIntWithKey(o.ID, d, prefixRequestPrice)
} }
@ -497,7 +496,7 @@ func (o *Oracle) setPrice(ic *interop.Context, args []stackitem.Item) stackitem.
} }
setIntWithKey(o.ID, ic.DAO, prefixRequestPrice, price.Int64()) setIntWithKey(o.ID, ic.DAO, prefixRequestPrice, price.Int64())
cache := ic.DAO.Store.GetRWCache(o.ID).(*OracleCache) cache := ic.DAO.Store.GetRWCache(o.ID).(*OracleCache)
cache.requestPriceChanged.Store(true) cache.requestPriceChanged = true
return stackitem.Null{} return stackitem.Null{}
} }

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"sort" "sort"
"sync"
"github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop"
@ -57,7 +56,6 @@ type Policy struct {
} }
type PolicyCache struct { type PolicyCache struct {
lock sync.RWMutex
// isValid defies whether cached values were changed during the current // isValid defies whether cached values were changed during the current
// consensus iteration. If false, these values will be updated after // consensus iteration. If false, these values will be updated after
// blockchain DAO persisting. If true, we can safely use cached values. // blockchain DAO persisting. If true, we can safely use cached values.
@ -215,8 +213,6 @@ func (p *Policy) OnPersist(ic *interop.Context) error {
// PostPersist implements Contract interface. // PostPersist implements Contract interface.
func (p *Policy) PostPersist(ic *interop.Context) error { func (p *Policy) PostPersist(ic *interop.Context) error {
cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache) cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache)
cache.lock.Lock()
defer cache.lock.Unlock()
if cache.isValid { if cache.isValid {
return nil return nil
} }
@ -233,8 +229,6 @@ func (p *Policy) getFeePerByte(ic *interop.Context, _ []stackitem.Item) stackite
// GetFeePerByteInternal returns required transaction's fee per byte. // GetFeePerByteInternal returns required transaction's fee per byte.
func (p *Policy) GetFeePerByteInternal(dao *dao.Simple) int64 { func (p *Policy) GetFeePerByteInternal(dao *dao.Simple) int64 {
cache := dao.Store.GetROCache(p.ID).(*PolicyCache) cache := dao.Store.GetROCache(p.ID).(*PolicyCache)
cache.lock.RLock()
defer cache.lock.RUnlock()
if cache.isValid { if cache.isValid {
return cache.feePerByte return cache.feePerByte
} }
@ -244,8 +238,6 @@ func (p *Policy) GetFeePerByteInternal(dao *dao.Simple) int64 {
// GetMaxVerificationGas returns maximum gas allowed to be burned during verificaion. // GetMaxVerificationGas returns maximum gas allowed to be burned during verificaion.
func (p *Policy) GetMaxVerificationGas(dao *dao.Simple) int64 { func (p *Policy) GetMaxVerificationGas(dao *dao.Simple) int64 {
cache := dao.Store.GetROCache(p.ID).(*PolicyCache) cache := dao.Store.GetROCache(p.ID).(*PolicyCache)
cache.lock.RLock()
defer cache.lock.RUnlock()
if cache.isValid { if cache.isValid {
return cache.maxVerificationGas return cache.maxVerificationGas
} }
@ -259,8 +251,6 @@ func (p *Policy) getExecFeeFactor(ic *interop.Context, _ []stackitem.Item) stack
// GetExecFeeFactorInternal returns current execution fee factor. // GetExecFeeFactorInternal returns current execution fee factor.
func (p *Policy) GetExecFeeFactorInternal(d *dao.Simple) int64 { func (p *Policy) GetExecFeeFactorInternal(d *dao.Simple) int64 {
cache := d.Store.GetROCache(p.ID).(*PolicyCache) cache := d.Store.GetROCache(p.ID).(*PolicyCache)
cache.lock.RLock()
defer cache.lock.RUnlock()
if cache.isValid { if cache.isValid {
return int64(cache.execFeeFactor) return int64(cache.execFeeFactor)
} }
@ -276,8 +266,6 @@ func (p *Policy) setExecFeeFactor(ic *interop.Context, args []stackitem.Item) st
panic("invalid committee signature") panic("invalid committee signature")
} }
cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache) cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache)
cache.lock.Lock()
defer cache.lock.Unlock()
setIntWithKey(p.ID, ic.DAO, execFeeFactorKey, int64(value)) setIntWithKey(p.ID, ic.DAO, execFeeFactorKey, int64(value))
cache.isValid = false cache.isValid = false
return stackitem.Null{} return stackitem.Null{}
@ -292,8 +280,6 @@ func (p *Policy) isBlocked(ic *interop.Context, args []stackitem.Item) stackitem
// IsBlockedInternal checks whether provided account is blocked. // IsBlockedInternal checks whether provided account is blocked.
func (p *Policy) IsBlockedInternal(dao *dao.Simple, hash util.Uint160) bool { func (p *Policy) IsBlockedInternal(dao *dao.Simple, hash util.Uint160) bool {
cache := dao.Store.GetROCache(p.ID).(*PolicyCache) cache := dao.Store.GetROCache(p.ID).(*PolicyCache)
cache.lock.RLock()
defer cache.lock.RUnlock()
if cache.isValid { if cache.isValid {
length := len(cache.blockedAccounts) length := len(cache.blockedAccounts)
i := sort.Search(length, func(i int) bool { i := sort.Search(length, func(i int) bool {
@ -315,8 +301,6 @@ func (p *Policy) getStoragePrice(ic *interop.Context, _ []stackitem.Item) stacki
// GetStoragePriceInternal returns current execution fee factor. // GetStoragePriceInternal returns current execution fee factor.
func (p *Policy) GetStoragePriceInternal(d *dao.Simple) int64 { func (p *Policy) GetStoragePriceInternal(d *dao.Simple) int64 {
cache := d.Store.GetROCache(p.ID).(*PolicyCache) cache := d.Store.GetROCache(p.ID).(*PolicyCache)
cache.lock.RLock()
defer cache.lock.RUnlock()
if cache.isValid { if cache.isValid {
return int64(cache.storagePrice) return int64(cache.storagePrice)
} }
@ -332,8 +316,6 @@ func (p *Policy) setStoragePrice(ic *interop.Context, args []stackitem.Item) sta
panic("invalid committee signature") panic("invalid committee signature")
} }
cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache) cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache)
cache.lock.Lock()
defer cache.lock.Unlock()
setIntWithKey(p.ID, ic.DAO, storagePriceKey, int64(value)) setIntWithKey(p.ID, ic.DAO, storagePriceKey, int64(value))
cache.isValid = false cache.isValid = false
return stackitem.Null{} return stackitem.Null{}
@ -349,8 +331,6 @@ func (p *Policy) setFeePerByte(ic *interop.Context, args []stackitem.Item) stack
panic("invalid committee signature") panic("invalid committee signature")
} }
cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache) cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache)
cache.lock.Lock()
defer cache.lock.Unlock()
setIntWithKey(p.ID, ic.DAO, feePerByteKey, value) setIntWithKey(p.ID, ic.DAO, feePerByteKey, value)
cache.isValid = false cache.isValid = false
return stackitem.Null{} return stackitem.Null{}
@ -373,8 +353,6 @@ func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stacki
} }
key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...) key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...)
cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache) cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache)
cache.lock.Lock()
defer cache.lock.Unlock()
ic.DAO.PutStorageItem(p.ID, key, state.StorageItem{}) ic.DAO.PutStorageItem(p.ID, key, state.StorageItem{})
cache.isValid = false cache.isValid = false
return stackitem.NewBool(true) return stackitem.NewBool(true)
@ -392,8 +370,6 @@ func (p *Policy) unblockAccount(ic *interop.Context, args []stackitem.Item) stac
} }
key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...) key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...)
cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache) cache := ic.DAO.Store.GetRWCache(p.ID).(*PolicyCache)
cache.lock.Lock()
defer cache.lock.Unlock()
ic.DAO.DeleteStorageItem(p.ID, key) ic.DAO.DeleteStorageItem(p.ID, key)
cache.isValid = false cache.isValid = false
return stackitem.NewBool(true) return stackitem.NewBool(true)