[#12] Use multi client for contract resolving
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
0190bbbde3
commit
2ece73b786
2 changed files with 51 additions and 17 deletions
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue