[#XX] Use contract resolver from sdk

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2023-10-12 18:04:22 +03:00
parent e3b6f534cc
commit eccc3f8077
2 changed files with 22 additions and 74 deletions

View file

@ -6,7 +6,8 @@ import (
"strings" "strings"
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/resolver" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ns"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
@ -31,12 +32,7 @@ type Config struct {
// New creates new FrostfsID contract wrapper that implements auth.FrostFSID interface. // New creates new FrostfsID contract wrapper that implements auth.FrostFSID interface.
func New(ctx context.Context, cfg Config) (*FrostFSID, error) { func New(ctx context.Context, cfg Config) (*FrostFSID, error) {
rpcCli, err := rpcclient.New(ctx, cfg.RPCAddress, rpcclient.Options{}) contractHash, err := fetchContractHash(cfg)
if err != nil {
return nil, fmt.Errorf("init rpc client: %w", err)
}
contractHash, err := fetchContractHash(rpcCli, cfg.Contract)
if err != nil { if err != nil {
return nil, fmt.Errorf("resolve frostfs contract hash: %w", err) return nil, fmt.Errorf("resolve frostfs contract hash: %w", err)
} }
@ -48,6 +44,11 @@ func New(ctx context.Context, cfg Config) (*FrostFSID, error) {
} }
} }
rpcCli, err := rpcclient.New(ctx, cfg.RPCAddress, rpcclient.Options{})
if err != nil {
return nil, fmt.Errorf("init rpc client: %w", err)
}
cli, err := client.New(rpcCli, wallet.NewAccountFromPrivateKey(key), contractHash, nil) cli, err := client.New(rpcCli, wallet.NewAccountFromPrivateKey(key), contractHash, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("init frostfsid client: %w", err) return nil, fmt.Errorf("init frostfsid client: %w", err)
@ -63,15 +64,24 @@ func (f *FrostFSID) ValidatePublicKey(key *keys.PublicKey) error {
return err return err
} }
func fetchContractHash(rpcCli *rpcclient.Client, contractName string) (util.Uint160, error) { func fetchContractHash(cfg Config) (util.Uint160, error) {
if hash, err := util.Uint160DecodeStringLE(contractName); err == nil { if hash, err := util.Uint160DecodeStringLE(cfg.Contract); err == nil {
return hash, nil return hash, nil
} }
splitName := strings.Split(contractName, ".") splitName := strings.Split(cfg.Contract, ".")
if len(splitName) != 2 { if len(splitName) != 2 {
return util.Uint160{}, fmt.Errorf("invalid contract name: '%s'", contractName) return util.Uint160{}, fmt.Errorf("invalid contract name: '%s'", cfg.Contract)
} }
return resolver.ResolveHash(rpcCli, contractName) var domain container.Domain
domain.SetName(splitName[0])
domain.SetZone(splitName[1])
var nns ns.NNS
if err := nns.Dial(cfg.RPCAddress); err != nil {
return util.Uint160{}, fmt.Errorf("dial nns %s: %w", cfg.RPCAddress, err)
}
return nns.ResolveContractHash(domain)
} }

View file

@ -1,62 +0,0 @@
package resolver
import (
"errors"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
// ResolveHash resolves contract hash.
func ResolveHash(cli *rpcclient.Client, domain string) (util.Uint160, error) {
nnsCs, err := cli.GetContractStateByID(1)
if err != nil {
return util.Uint160{}, fmt.Errorf("get NNS contract by id: %w", err)
}
item, err := nnsResolve(invoker.New(cli, nil), nnsCs.Hash, domain)
if err != nil {
return util.Uint160{}, err
}
return parseNNSResolveResult(item)
}
func nnsResolve(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (stackitem.Item, error) {
return unwrap.Item(inv.Call(nnsHash, "resolve", domain, int64(nns.TXT)))
}
// parseNNSResolveResult parses 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.
func parseNNSResolveResult(res stackitem.Item) (util.Uint160, error) {
arr, ok := res.Value().([]stackitem.Item)
if !ok {
arr = []stackitem.Item{res}
}
if _, ok := res.Value().(stackitem.Null); ok || len(arr) == 0 {
return util.Uint160{}, errors.New("NNS record is missing")
}
for i := range arr {
bs, err := arr[i].TryBytes()
if err != nil {
continue
}
h, err := address.StringToUint160(string(bs))
if err == nil {
return h, nil
}
h, err = util.Uint160DecodeStringLE(string(bs))
if err == nil {
return h, nil
}
}
return util.Uint160{}, errors.New("no valid hashes are found")
}