Make code simpler, remove unused methods. Change-Id: I18807f2c14b5a96e533e5e3fc153e23c742c66c1 Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
173 lines
4.7 KiB
Go
173 lines
4.7 KiB
Go
package client
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"strconv"
|
|
"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/util"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
)
|
|
|
|
const (
|
|
nnsContractID = 1 // NNS contract must be deployed first in the sidechain
|
|
|
|
// NNSBalanceContractName is a name of the balance contract in NNS.
|
|
NNSBalanceContractName = "balance.frostfs"
|
|
// NNSContainerContractName is a name of the container contract in NNS.
|
|
NNSContainerContractName = "container.frostfs"
|
|
// NNSFrostFSIDContractName is a name of the frostfsid contract in NNS.
|
|
NNSFrostFSIDContractName = "frostfsid.frostfs"
|
|
// NNSNetmapContractName is a name of the netmap contract in NNS.
|
|
NNSNetmapContractName = "netmap.frostfs"
|
|
// NNSProxyContractName is a name of the proxy contract in NNS.
|
|
NNSProxyContractName = "proxy.frostfs"
|
|
// NNSGroupKeyName is a name for the FrostFS group key record in NNS.
|
|
NNSGroupKeyName = "group.frostfs"
|
|
// NNSPolicyContractName is a name of the policy contract in NNS.
|
|
NNSPolicyContractName = "policy.frostfs"
|
|
)
|
|
|
|
// 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.
|
|
func NNSAlphabetContractName(index int) string {
|
|
return "alphabet" + strconv.Itoa(index) + ".frostfs"
|
|
}
|
|
|
|
// NNSContractAddress returns contract address script hash based on its name
|
|
// in NNS contract.
|
|
// If script hash has not been found, returns ErrNNSRecordNotFound.
|
|
func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) {
|
|
c.switchLock.RLock()
|
|
defer c.switchLock.RUnlock()
|
|
|
|
if c.inactive {
|
|
return util.Uint160{}, ErrConnectionLost
|
|
}
|
|
|
|
sh, err = nnsResolve(c.nnsReader, name)
|
|
if err != nil {
|
|
return sh, fmt.Errorf("NNS.resolve: %w", err)
|
|
}
|
|
return sh, nil
|
|
}
|
|
|
|
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 available {
|
|
return nil, ErrNNSRecordNotFound
|
|
}
|
|
|
|
return r.Resolve(domain, big.NewInt(int64(nns.TXT)))
|
|
}
|
|
|
|
func nnsResolve(r *nnsClient.ContractReader, domain string) (util.Uint160, error) {
|
|
arr, err := nnsResolveItem(r, domain)
|
|
if err != nil {
|
|
return util.Uint160{}, err
|
|
}
|
|
|
|
if len(arr) == 0 {
|
|
return util.Uint160{}, errors.New("NNS record is missing")
|
|
}
|
|
bs, err := arr[0].TryBytes()
|
|
if err != nil {
|
|
return util.Uint160{}, fmt.Errorf("malformed response: %w", err)
|
|
}
|
|
|
|
// We support several formats for hash encoding, this logic should be maintained in sync
|
|
// with parseNNSResolveResult from cmd/frostfs-adm/internal/modules/morph/initialize_nns.go
|
|
h, err := util.Uint160DecodeStringLE(string(bs))
|
|
if err == nil {
|
|
return h, nil
|
|
}
|
|
|
|
h, err = address.StringToUint160(string(bs))
|
|
if err == nil {
|
|
return h, nil
|
|
}
|
|
|
|
return util.Uint160{}, errors.New("no valid hashes are found")
|
|
}
|
|
|
|
// SetGroupSignerScope makes the default signer scope include all FrostFS contracts.
|
|
// Should be called for side-chain client only.
|
|
func (c *Client) SetGroupSignerScope() error {
|
|
c.switchLock.RLock()
|
|
defer c.switchLock.RUnlock()
|
|
|
|
if c.inactive {
|
|
return ErrConnectionLost
|
|
}
|
|
|
|
pub, err := c.contractGroupKey()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Don't change c before everything is OK.
|
|
cfg := c.cfg
|
|
cfg.signer = &transaction.Signer{
|
|
Scopes: transaction.CustomGroups | transaction.CalledByEntry,
|
|
AllowedGroups: []*keys.PublicKey{pub},
|
|
}
|
|
rpcActor, err := newActor(c.client, c.acc, cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.cfg = cfg
|
|
c.setActor(rpcActor)
|
|
return nil
|
|
}
|
|
|
|
// contractGroupKey returns public key designating FrostFS contract group.
|
|
func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
|
|
success := false
|
|
startedAt := time.Now()
|
|
defer func() {
|
|
c.cache.metrics.AddMethodDuration("GroupKey", success, time.Since(startedAt))
|
|
}()
|
|
|
|
if gKey := c.cache.groupKey(); gKey != nil {
|
|
success = true
|
|
return gKey, nil
|
|
}
|
|
|
|
arr, err := nnsResolveItem(c.nnsReader, NNSGroupKeyName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(arr) == 0 {
|
|
return nil, errors.New("NNS record is missing")
|
|
}
|
|
|
|
bs, err := arr[0].TryBytes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pub, err := keys.NewPublicKeyFromString(string(bs))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c.cache.setGroupKey(pub)
|
|
|
|
success = true
|
|
return pub, nil
|
|
}
|