[#1689] morph/client: Reuse auto-generated wrappers for NNS

Make code simpler, remove unused methods.

Change-Id: I18807f2c14b5a96e533e5e3fc153e23c742c66c1
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2025-03-21 15:56:11 +03:00 committed by Dmitrii Stepanov
parent ccdd6cb767
commit 3bb1fb744a
2 changed files with 19 additions and 81 deletions

View file

@ -9,6 +9,7 @@ import (
"sync/atomic"
"time"
nnsClient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics"
morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics"
@ -62,6 +63,8 @@ type Client struct {
rolemgmt *rolemgmt.Contract // neo-go Designation contract wrapper
nnsHash util.Uint160 // NNS contract hash
nnsReader *nnsClient.ContractReader // NNS contract wrapper
acc *wallet.Account // neo account
accAddr util.Uint160 // account's address
@ -576,6 +579,7 @@ func (c *Client) setActor(act *actor.Actor) {
c.rpcActor = act
c.gasToken = nep17.New(act, gas.Hash)
c.rolemgmt = rolemgmt.New(act)
c.nnsReader = nnsClient.NewReader(act, c.nnsHash)
}
func (c *Client) GetActor() *actor.Actor {

View file

@ -8,14 +8,12 @@ import (
"time"
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
nnsClient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
)
const (
@ -37,12 +35,8 @@ const (
NNSPolicyContractName = "policy.frostfs"
)
var (
// ErrNNSRecordNotFound means that there is no such record in NNS contract.
ErrNNSRecordNotFound = errors.New("record has not been found in NNS contract")
errEmptyResultStack = errors.New("returned result stack is empty")
)
// ErrNNSRecordNotFound means that there is no such record in NNS contract.
var ErrNNSRecordNotFound = errors.New("record has not been found in NNS contract")
// NNSAlphabetContractName returns contract name of the alphabet contract in NNS
// based on alphabet index.
@ -61,67 +55,36 @@ func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) {
return util.Uint160{}, ErrConnectionLost
}
nnsHash := c.NNSHash()
sh, err = nnsResolve(c.client, nnsHash, name)
sh, err = nnsResolve(c.nnsReader, name)
if err != nil {
return sh, fmt.Errorf("NNS.resolve: %w", err)
}
return sh, nil
}
// NNSHash returns NNS contract hash.
func (c *Client) NNSHash() util.Uint160 {
return c.nnsHash
}
func nnsResolveItem(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) {
found, err := exists(c, nnsHash, domain)
func nnsResolveItem(r *nnsClient.ContractReader, domain string) ([]stackitem.Item, error) {
available, err := r.IsAvailable(domain)
if err != nil {
return nil, fmt.Errorf("check presence in NNS contract for %s: %w", domain, err)
}
if !found {
if available {
return nil, ErrNNSRecordNotFound
}
result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{
{
Type: smartcontract.StringType,
Value: domain,
},
{
Type: smartcontract.IntegerType,
Value: big.NewInt(int64(nns.TXT)),
},
}, nil)
if err != nil {
return nil, err
}
if result.State != vmstate.Halt.String() {
return nil, fmt.Errorf("invocation failed: %s", result.FaultException)
}
if len(result.Stack) == 0 {
return nil, errEmptyResultStack
}
return result.Stack[0], nil
return r.Resolve(domain, big.NewInt(int64(nns.TXT)))
}
func nnsResolve(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (util.Uint160, error) {
res, err := nnsResolveItem(c, nnsHash, domain)
func nnsResolve(r *nnsClient.ContractReader, domain string) (util.Uint160, error) {
arr, err := nnsResolveItem(r, domain)
if err != nil {
return util.Uint160{}, err
}
// Parse the result of resolving NNS record.
// It works with multiple formats (corresponding to multiple NNS versions).
// If array of hashes is provided, it returns only the first one.
if arr, ok := res.Value().([]stackitem.Item); ok {
if len(arr) == 0 {
return util.Uint160{}, errors.New("NNS record is missing")
}
res = arr[0]
if len(arr) == 0 {
return util.Uint160{}, errors.New("NNS record is missing")
}
bs, err := res.TryBytes()
bs, err := arr[0].TryBytes()
if err != nil {
return util.Uint160{}, fmt.Errorf("malformed response: %w", err)
}
@ -141,33 +104,6 @@ func nnsResolve(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (uti
return util.Uint160{}, errors.New("no valid hashes are found")
}
func exists(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (bool, error) {
result, err := c.InvokeFunction(nnsHash, "isAvailable", []smartcontract.Parameter{
{
Type: smartcontract.StringType,
Value: domain,
},
}, nil)
if err != nil {
return false, err
}
if len(result.Stack) == 0 {
return false, errEmptyResultStack
}
res := result.Stack[0]
available, err := res.TryBool()
if err != nil {
return false, fmt.Errorf("malformed response: %w", err)
}
// not available means that it is taken
// and, therefore, exists
return !available, nil
}
// SetGroupSignerScope makes the default signer scope include all FrostFS contracts.
// Should be called for side-chain client only.
func (c *Client) SetGroupSignerScope() error {
@ -211,14 +147,12 @@ func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
return gKey, nil
}
nnsHash := c.NNSHash()
item, err := nnsResolveItem(c.client, nnsHash, NNSGroupKeyName)
arr, err := nnsResolveItem(c.nnsReader, NNSGroupKeyName)
if err != nil {
return nil, err
}
arr, ok := item.Value().([]stackitem.Item)
if !ok || len(arr) == 0 {
if len(arr) == 0 {
return nil, errors.New("NNS record is missing")
}