[#1170] pkg/morph: Invalidate cache on RPC switch

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2022-03-31 16:12:42 +03:00 committed by Alex Vanin
parent 6508136204
commit 4ed5b1ceef
5 changed files with 58 additions and 25 deletions

View file

@ -39,7 +39,7 @@ import (
// expression (or just declaring a Client variable) is unsafe // expression (or just declaring a Client variable) is unsafe
// and can lead to panic. // and can lead to panic.
type Client struct { type Client struct {
cache cache cache
logger *logger.Logger // logging component logger *logger.Logger // logging component
@ -76,11 +76,50 @@ type Client struct {
} }
type cache struct { type cache struct {
nnsHash util.Uint160 m *sync.RWMutex
groupKey *keys.PublicKey
nnsHash *util.Uint160
gKey *keys.PublicKey
txHeights *lru.Cache txHeights *lru.Cache
} }
func (c cache) nns() *util.Uint160 {
c.m.RLock()
defer c.m.RUnlock()
return c.nnsHash
}
func (c *cache) setNNSHash(nnsHash util.Uint160) {
c.m.Lock()
defer c.m.Unlock()
c.nnsHash = &nnsHash
}
func (c cache) groupKey() *keys.PublicKey {
c.m.RLock()
defer c.m.RUnlock()
return c.gKey
}
func (c *cache) setGroupKey(groupKey *keys.PublicKey) {
c.m.Lock()
defer c.m.Unlock()
c.gKey = groupKey
}
func (c *cache) invalidate() {
c.m.Lock()
defer c.m.Unlock()
c.nnsHash = nil
c.gKey = nil
c.txHeights.Purge()
}
var ( var (
// ErrNilClient is returned by functions that expect // ErrNilClient is returned by functions that expect
// a non-nil Client pointer, but received nil. // a non-nil Client pointer, but received nil.

View file

@ -90,7 +90,7 @@ func New(key *keys.PrivateKey, endpoint string, opts ...Option) (*Client, error)
} }
cli := &Client{ cli := &Client{
cache: initClientCache(), cache: newClientCache(),
logger: cfg.logger, logger: cfg.logger,
acc: wallet.NewAccountFromPrivateKey(key), acc: wallet.NewAccountFromPrivateKey(key),
signer: cfg.signer, signer: cfg.signer,
@ -140,9 +140,10 @@ func newWSClient(cfg cfg, endpoint string) (*client.WSClient, error) {
) )
} }
func initClientCache() cache { func newClientCache() cache {
c, _ := lru.New(100) // returns error only if size is negative c, _ := lru.New(100) // returns error only if size is negative
return cache{ return cache{
m: &sync.RWMutex{},
txHeights: c, txHeights: c,
} }
} }

View file

@ -87,6 +87,7 @@ func (c *Client) switchRPC() bool {
continue continue
} }
c.cache.invalidate()
c.client = cli c.client = cli
return true return true

View file

@ -83,20 +83,18 @@ func (c *Client) NNSHash() (util.Uint160, error) {
return util.Uint160{}, ErrConnectionLost return util.Uint160{}, ErrConnectionLost
} }
c.mtx.RLock() nnsHash := c.cache.nns()
nnsHash := c.nnsHash
c.mtx.RUnlock()
if nnsHash.Equals(util.Uint160{}) { if nnsHash == nil {
cs, err := c.client.GetContractStateByID(nnsContractID) cs, err := c.client.GetContractStateByID(nnsContractID)
if err != nil { if err != nil {
return util.Uint160{}, fmt.Errorf("NNS contract state: %w", err) return util.Uint160{}, fmt.Errorf("NNS contract state: %w", err)
} }
c.mtx.Lock()
c.nnsHash = cs.Hash c.cache.setNNSHash(cs.Hash)
c.mtx.Unlock() nnsHash = &cs.Hash
} }
return nnsHash, nil return *nnsHash, nil
} }
func nnsResolveItem(c *client.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) { func nnsResolveItem(c *client.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) {
@ -202,12 +200,8 @@ func (c *Client) SetGroupSignerScope() error {
// contractGroupKey returns public key designating NeoFS contract group. // contractGroupKey returns public key designating NeoFS contract group.
func (c *Client) contractGroupKey() (*keys.PublicKey, error) { func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
c.mtx.RLock() if gKey := c.cache.groupKey(); gKey != nil {
pub := c.groupKey return gKey, nil
c.mtx.RUnlock()
if pub != nil {
return pub, nil
} }
nnsHash, err := c.NNSHash() nnsHash, err := c.NNSHash()
@ -225,13 +219,11 @@ func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
return nil, err return nil, err
} }
pub, err = keys.NewPublicKeyFromString(string(bs)) pub, err := keys.NewPublicKeyFromString(string(bs))
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.mtx.Lock() c.cache.setGroupKey(pub)
c.groupKey = pub
c.mtx.Unlock()
return pub, nil return pub, nil
} }

View file

@ -873,13 +873,13 @@ func (c *Client) CalculateNonceAndVUB(hash util.Uint256) (nonce uint32, vub uint
} }
func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) { func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) {
if rh, ok := c.txHeights.Get(h); ok { if rh, ok := c.cache.txHeights.Get(h); ok {
return rh.(uint32), nil return rh.(uint32), nil
} }
height, err := c.client.GetTransactionHeight(h) height, err := c.client.GetTransactionHeight(h)
if err != nil { if err != nil {
return 0, err return 0, err
} }
c.txHeights.Add(h, height) c.cache.txHeights.Add(h, height)
return height, nil return height, nil
} }