[#936] morph/nns: Add record existence check
Also, add ErrNNSRecordNotFound error that indicates that required hash is not presented in `NNS` contract. Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
parent
e500efb9b3
commit
b492201a84
1 changed files with 45 additions and 1 deletions
|
@ -32,6 +32,13 @@ const (
|
||||||
NNSReputationContractName = "reputation.neofs"
|
NNSReputationContractName = "reputation.neofs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
|
||||||
// NNSAlphabetContractName returns contract name of the alphabet contract in NNS
|
// NNSAlphabetContractName returns contract name of the alphabet contract in NNS
|
||||||
// based on alphabet index.
|
// based on alphabet index.
|
||||||
func NNSAlphabetContractName(index int) string {
|
func NNSAlphabetContractName(index int) string {
|
||||||
|
@ -40,6 +47,7 @@ func NNSAlphabetContractName(index int) string {
|
||||||
|
|
||||||
// NNSContractAddress returns contract address script hash based on its name
|
// NNSContractAddress returns contract address script hash based on its name
|
||||||
// in NNS contract.
|
// in NNS contract.
|
||||||
|
// If script hash has not been found, returns ErrNNSRecordNotFound.
|
||||||
func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) {
|
func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) {
|
||||||
if c.multiClient != nil {
|
if c.multiClient != nil {
|
||||||
return sh, c.multiClient.iterateClients(func(c *Client) error {
|
return sh, c.multiClient.iterateClients(func(c *Client) error {
|
||||||
|
@ -61,6 +69,15 @@ func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func nnsResolve(c *client.Client, nnsHash util.Uint160, domain string) (util.Uint160, error) {
|
func nnsResolve(c *client.Client, nnsHash util.Uint160, domain string) (util.Uint160, error) {
|
||||||
|
found, err := exists(c, nnsHash, domain)
|
||||||
|
if err != nil {
|
||||||
|
return util.Uint160{}, fmt.Errorf("could not check presence in NNS contract for %s: %w", domain, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return util.Uint160{}, ErrNNSRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{
|
result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{
|
||||||
{
|
{
|
||||||
Type: smartcontract.StringType,
|
Type: smartcontract.StringType,
|
||||||
|
@ -78,7 +95,7 @@ func nnsResolve(c *client.Client, nnsHash util.Uint160, domain string) (util.Uin
|
||||||
return util.Uint160{}, fmt.Errorf("invocation failed: %s", result.FaultException)
|
return util.Uint160{}, fmt.Errorf("invocation failed: %s", result.FaultException)
|
||||||
}
|
}
|
||||||
if len(result.Stack) == 0 {
|
if len(result.Stack) == 0 {
|
||||||
return util.Uint160{}, errors.New("result stack is empty")
|
return util.Uint160{}, errEmptyResultStack
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the result of resolving NNS record.
|
// Parse the result of resolving NNS record.
|
||||||
|
@ -97,3 +114,30 @@ func nnsResolve(c *client.Client, nnsHash util.Uint160, domain string) (util.Uin
|
||||||
}
|
}
|
||||||
return util.Uint160DecodeStringLE(string(bs))
|
return util.Uint160DecodeStringLE(string(bs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func exists(c *client.Client, 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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue