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:
parent
7b632c8ee8
commit
8ec8511d9d
6 changed files with 101 additions and 196 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -263,13 +256,9 @@ 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
|
||||||
}
|
}
|
||||||
|
@ -311,15 +300,10 @@ func (n *NEO) Initialize(ic *interop.Context) error {
|
||||||
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.
|
||||||
|
|
|
@ -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{}
|
||||||
|
|
|
@ -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{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue