diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 84076ce3..14301e17 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "sync" "time" lru "github.com/hashicorp/golang-lru" @@ -43,8 +44,11 @@ type Client struct { } type cache struct { - nnsHash util.Uint160 - groupKey *keys.PublicKey + // mtx protects primitive values. + mtx sync.RWMutex + nnsHash util.Uint160 + groupKey *keys.PublicKey + // txHeights is a thread-safe LRU cache for transaction heights. txHeights *lru.Cache } diff --git a/pkg/morph/client/nns.go b/pkg/morph/client/nns.go index 562f7700..53a76560 100644 --- a/pkg/morph/client/nns.go +++ b/pkg/morph/client/nns.go @@ -85,14 +85,20 @@ func (c *Client) NNSHash() (util.Uint160, error) { }) } - if c.nnsHash.Equals(util.Uint160{}) { + c.mtx.RLock() + nnsHash := c.nnsHash + c.mtx.RUnlock() + + if nnsHash.Equals(util.Uint160{}) { cs, err := c.client.GetContractStateByID(nnsContractID) if err != nil { return util.Uint160{}, fmt.Errorf("NNS contract state: %w", err) } + c.mtx.Lock() c.nnsHash = cs.Hash + c.mtx.Unlock() } - return c.nnsHash, nil + return nnsHash, nil } func nnsResolveItem(c *client.Client, nnsHash util.Uint160, domain string) (stackitem.Item, error) { @@ -197,8 +203,12 @@ func (c *Client) SetGroupSignerScope() error { // contractGroupKey returns public key designating NeoFS contract group. func (c *Client) contractGroupKey() (*keys.PublicKey, error) { - if c.groupKey != nil { - return c.groupKey, nil + c.mtx.RLock() + pub := c.groupKey + c.mtx.RUnlock() + + if pub != nil { + return pub, nil } nnsHash, err := c.NNSHash() @@ -216,11 +226,13 @@ func (c *Client) contractGroupKey() (*keys.PublicKey, error) { return nil, err } - pub, err := keys.NewPublicKeyFromString(string(bs)) + pub, err = keys.NewPublicKeyFromString(string(bs)) if err != nil { return nil, err } + c.mtx.Lock() c.groupKey = pub + c.mtx.Unlock() return pub, nil }