diff --git a/cmd/s3-lifecycler/app.go b/cmd/s3-lifecycler/app.go index 7cee56c..79f42b5 100644 --- a/cmd/s3-lifecycler/app.go +++ b/cmd/s3-lifecycler/app.go @@ -95,7 +95,7 @@ func (a *App) init(ctx context.Context) { a.log.Fatal(logs.CouldntCreateWalletSource, zap.Error(err)) } - frostfsidContract, err := resolver.ResolveContractHash(a.cfg.GetString(cfgMorphContractFrostfsID), endpoints[0].Address) + frostfsidContract, err := resolver.ResolveContractHash(cli, a.cfg.GetString(cfgMorphContractFrostfsID)) if err != nil { a.log.Fatal(logs.ResolveFrostfsIDContract, zap.Error(err)) } @@ -105,7 +105,7 @@ func (a *App) init(ctx context.Context) { ContractHash: frostfsidContract, } - containerContract, err := resolver.ResolveContractHash(a.cfg.GetString(cfgMorphContractContainer), endpoints[0].Address) + containerContract, err := resolver.ResolveContractHash(cli, a.cfg.GetString(cfgMorphContractContainer)) if err != nil { a.log.Fatal(logs.ResolveContainerContract, zap.Error(err)) } @@ -146,7 +146,7 @@ func (a *App) init(ctx context.Context) { } }() - netmapContract, err := resolver.ResolveContractHash(a.cfg.GetString(cfgMorphContractNetmap), endpoints[0].Address) + netmapContract, err := resolver.ResolveContractHash(cli, a.cfg.GetString(cfgMorphContractNetmap)) if err != nil { a.log.Fatal(logs.ResolveNetmapContract, zap.Error(err)) } diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index f491f2e..9146e37 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -1,34 +1,68 @@ package resolver import ( + "errors" "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ns" + "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-s3-lifecycler/internal/morph" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // ResolveContractHash determine contract hash by resolving NNS name. -func ResolveContractHash(contractHash, rpcAddress string) (util.Uint160, error) { +func ResolveContractHash(cli *morph.Client, contractHash string) (util.Uint160, error) { if hash, err := util.Uint160DecodeStringLE(contractHash); err == nil { return hash, nil } - splitName := strings.Split(contractHash, ".") - if len(splitName) != 2 { + if strings.Count(contractHash, ".") != 1 { return util.Uint160{}, fmt.Errorf("invalid contract name: '%s'", contractHash) } - var domain container.Domain - domain.SetName(splitName[0]) - domain.SetZone(splitName[1]) - - var nns ns.NNS - if err := nns.Dial(rpcAddress); err != nil { - return util.Uint160{}, fmt.Errorf("dial nns %s: %w", rpcAddress, err) + nnsContract, err := cli.Client().NNSHash() + if err != nil { + return util.Uint160{}, fmt.Errorf("get NNS contract hash: %w", err) } - defer nns.Close() - return nns.ResolveContractHash(domain) + return invokeResolve(cli, nnsContract, contractHash) +} + +func invokeResolve(cli *morph.Client, nnsContract util.Uint160, contractHash string) (util.Uint160, error) { + items, err := cli.Client().TestInvoke(nnsContract, "resolve", contractHash, int64(nns.TXT)) + if err != nil { + return util.Uint160{}, fmt.Errorf("contract invocation: %w", err) + } + if len(items) != 1 { + return util.Uint160{}, fmt.Errorf("stack has %d items", len(items)) + } + + if _, ok := items[0].(stackitem.Null); !ok { + arr, ok := items[0].Value().([]stackitem.Item) + if !ok { + // unexpected for types from stackitem package + return util.Uint160{}, errors.New("invalid cast to stack item slice") + } + + for i := range arr { + recordValue, err := arr[i].TryBytes() + if err != nil { + return util.Uint160{}, fmt.Errorf("convert array item to byte slice: %w", err) + } + + strRecordValue := string(recordValue) + scriptHash, err := address.StringToUint160(strRecordValue) + if err == nil { + return scriptHash, nil + } + scriptHash, err = util.Uint160DecodeStringLE(strRecordValue) + if err == nil { + return scriptHash, nil + } + } + } + + return util.Uint160{}, errors.New("record not found") }