forked from TrueCloudLab/frostfs-node
[#749] morph/client: allow to fetch contract group key
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
4838d3bb80
commit
9e2f7ac371
6 changed files with 83 additions and 23 deletions
|
@ -18,8 +18,6 @@ import (
|
||||||
|
|
||||||
const contractWalletName = "contract.json"
|
const contractWalletName = "contract.json"
|
||||||
|
|
||||||
const groupKeyDomain = "group.neofs"
|
|
||||||
|
|
||||||
func initializeContractWallet(walletDir string) (*wallet.Wallet, error) {
|
func initializeContractWallet(walletDir string) (*wallet.Wallet, error) {
|
||||||
var (
|
var (
|
||||||
password string
|
password string
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/config"
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/config"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
|
morphClient "github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -266,7 +267,7 @@ func (c *initializeContext) getSigner() transaction.Signer {
|
||||||
return signer
|
return signer
|
||||||
}
|
}
|
||||||
|
|
||||||
groupKey, err := nnsResolveKey(c.Client, nnsCs.Hash, groupKeyDomain)
|
groupKey, err := nnsResolveKey(c.Client, nnsCs.Hash, morphClient.NNSGroupKeyName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.groupKey = groupKey
|
c.groupKey = groupKey
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
|
morphClient "github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -274,7 +275,7 @@ func (c *initializeContext) updateContracts() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.Command.Printf("NNS: Set %s -> %s\n", groupKeyDomain, hex.EncodeToString(groupKey.Bytes()))
|
c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes()))
|
||||||
|
|
||||||
totalGasCost += sysFee
|
totalGasCost += sysFee
|
||||||
if err := c.sendCommitteeTx(w.Bytes(), totalGasCost); err != nil {
|
if err := c.sendCommitteeTx(w.Bytes(), totalGasCost); err != nil {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
morphClient "github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultNameServiceDomainPrice = 10_0000_0000
|
const defaultNameServiceDomainPrice = 10_0000_0000
|
||||||
|
@ -74,7 +75,7 @@ func (c *initializeContext) setNNS() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.Command.Printf("NNS: Set %s -> %s\n", groupKeyDomain, hex.EncodeToString(groupKey.Bytes()))
|
c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes()))
|
||||||
|
|
||||||
return c.awaitTx()
|
return c.awaitTx()
|
||||||
}
|
}
|
||||||
|
@ -89,13 +90,13 @@ func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.Publi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (int64, error) {
|
func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (int64, error) {
|
||||||
isAvail, err := c.Client.NNSIsAvailable(nnsHash, groupKeyDomain)
|
isAvail, err := c.Client.NNSIsAvailable(nnsHash, morphClient.NNSGroupKeyName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isAvail {
|
if !isAvail {
|
||||||
currentPub, err := nnsResolveKey(c.Client, nnsHash, groupKeyDomain)
|
currentPub, err := nnsResolveKey(c.Client, nnsHash, morphClient.NNSGroupKeyName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -108,7 +109,7 @@ func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHas
|
||||||
sysFee := int64(native.GASFactor)
|
sysFee := int64(native.GASFactor)
|
||||||
if isAvail {
|
if isAvail {
|
||||||
emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All,
|
emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All,
|
||||||
groupKeyDomain, c.CommitteeAcc.Contract.ScriptHash(),
|
morphClient.NNSGroupKeyName, c.CommitteeAcc.Contract.ScriptHash(),
|
||||||
"ops@nspcc.ru", int64(3600), int64(600), int64(604800), int64(3600))
|
"ops@nspcc.ru", int64(3600), int64(600), int64(604800), int64(3600))
|
||||||
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
||||||
sysFee += defaultRegisterSysfee
|
sysFee += defaultRegisterSysfee
|
||||||
|
|
|
@ -42,7 +42,8 @@ type Client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type cache struct {
|
type cache struct {
|
||||||
nnsHash util.Uint160
|
nnsHash util.Uint160
|
||||||
|
groupKey *keys.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
type singleClient struct {
|
type singleClient struct {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
nns "github.com/nspcc-dev/neo-go/examples/nft-nd-nns"
|
nns "github.com/nspcc-dev/neo-go/examples/nft-nd-nns"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
@ -32,6 +33,8 @@ const (
|
||||||
NNSReputationContractName = "reputation.neofs"
|
NNSReputationContractName = "reputation.neofs"
|
||||||
// NNSSubnetworkContractName is a name of the subnet contract in NNS.
|
// NNSSubnetworkContractName is a name of the subnet contract in NNS.
|
||||||
NNSSubnetworkContractName = "subnet.neofs"
|
NNSSubnetworkContractName = "subnet.neofs"
|
||||||
|
// NNSGroupKeyName is a name for the NeoFS group key record in NNS.
|
||||||
|
NNSGroupKeyName = "group.neofs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -58,29 +61,47 @@ func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.nnsHash.Equals(util.Uint160{}) {
|
nnsHash, err := c.NNSHash()
|
||||||
cs, err := c.client.GetContractStateByID(nnsContractID)
|
if err != nil {
|
||||||
if err != nil {
|
return util.Uint160{}, err
|
||||||
return sh, fmt.Errorf("NNS contract state: %w", err)
|
|
||||||
}
|
|
||||||
c.nnsHash = cs.Hash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sh, err = nnsResolve(c.client, c.nnsHash, name)
|
sh, err = nnsResolve(c.client, nnsHash, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sh, fmt.Errorf("NNS.resolve: %w", err)
|
return sh, fmt.Errorf("NNS.resolve: %w", err)
|
||||||
}
|
}
|
||||||
return sh, nil
|
return sh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func nnsResolve(c *client.Client, nnsHash util.Uint160, domain string) (util.Uint160, error) {
|
// NNSHash returns NNS contract hash.
|
||||||
|
func (c *Client) NNSHash() (util.Uint160, error) {
|
||||||
|
if c.multiClient != nil {
|
||||||
|
var sh util.Uint160
|
||||||
|
return sh, c.multiClient.iterateClients(func(c *Client) error {
|
||||||
|
var err error
|
||||||
|
sh, err = c.NNSHash()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.nnsHash.Equals(util.Uint160{}) {
|
||||||
|
cs, err := c.client.GetContractStateByID(nnsContractID)
|
||||||
|
if err != nil {
|
||||||
|
return util.Uint160{}, fmt.Errorf("NNS contract state: %w", err)
|
||||||
|
}
|
||||||
|
c.nnsHash = cs.Hash
|
||||||
|
}
|
||||||
|
return c.nnsHash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func nnsResolveItem(c *client.Client, nnsHash util.Uint160, domain string) (stackitem.Item, error) {
|
||||||
found, err := exists(c, nnsHash, domain)
|
found, err := exists(c, nnsHash, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.Uint160{}, fmt.Errorf("could not check presence in NNS contract for %s: %w", domain, err)
|
return nil, fmt.Errorf("could not check presence in NNS contract for %s: %w", domain, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
return util.Uint160{}, ErrNNSRecordNotFound
|
return nil, ErrNNSRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{
|
result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{
|
||||||
|
@ -94,19 +115,26 @@ func nnsResolve(c *client.Client, nnsHash util.Uint160, domain string) (util.Uin
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.Uint160{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if result.State != vm.HaltState.String() {
|
if result.State != vm.HaltState.String() {
|
||||||
return util.Uint160{}, fmt.Errorf("invocation failed: %s", result.FaultException)
|
return nil, fmt.Errorf("invocation failed: %s", result.FaultException)
|
||||||
}
|
}
|
||||||
if len(result.Stack) == 0 {
|
if len(result.Stack) == 0 {
|
||||||
return util.Uint160{}, errEmptyResultStack
|
return nil, errEmptyResultStack
|
||||||
|
}
|
||||||
|
return result.Stack[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func nnsResolve(c *client.Client, nnsHash util.Uint160, domain string) (util.Uint160, error) {
|
||||||
|
res, err := nnsResolveItem(c, nnsHash, domain)
|
||||||
|
if err != nil {
|
||||||
|
return util.Uint160{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the result of resolving NNS record.
|
// Parse the result of resolving NNS record.
|
||||||
// It works with multiple formats (corresponding to multiple NNS versions).
|
// It works with multiple formats (corresponding to multiple NNS versions).
|
||||||
// If array of hashes is provided, it returns only the first one.
|
// If array of hashes is provided, it returns only the first one.
|
||||||
res := result.Stack[0]
|
|
||||||
if arr, ok := res.Value().([]stackitem.Item); ok {
|
if arr, ok := res.Value().([]stackitem.Item); ok {
|
||||||
if len(arr) == 0 {
|
if len(arr) == 0 {
|
||||||
return util.Uint160{}, errors.New("NNS record is missing")
|
return util.Uint160{}, errors.New("NNS record is missing")
|
||||||
|
@ -146,3 +174,33 @@ func exists(c *client.Client, nnsHash util.Uint160, domain string) (bool, error)
|
||||||
// and, therefore, exists
|
// and, therefore, exists
|
||||||
return !available, nil
|
return !available, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContractGroupKey returns public key designating NeoFS contract group.
|
||||||
|
func (c *Client) ContractGroupKey() (*keys.PublicKey, error) {
|
||||||
|
if c.groupKey != nil {
|
||||||
|
return c.groupKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nnsHash, err := c.NNSHash()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
item, err := nnsResolveItem(c.client, nnsHash, NNSGroupKeyName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bs, err := item.TryBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := keys.NewPublicKeyFromString(string(bs))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.groupKey = pub
|
||||||
|
return pub, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue