[#932] adm: Prepare to move InitializeContext to util package

Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
This commit is contained in:
Anton Nikiforov 2024-02-01 14:30:59 +03:00
parent bee3741f4e
commit b68f7be0b6
20 changed files with 277 additions and 270 deletions

View file

@ -85,7 +85,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
return errors.New("empty config pairs") return errors.New("empty config pairs")
} }
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return fmt.Errorf("can't initialize context: %w", err) return fmt.Errorf("can't initialize context: %w", err)
} }
@ -119,12 +119,12 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
} }
} }
err = wCtx.sendConsensusTx(bw.Bytes()) err = wCtx.SendConsensusTx(bw.Bytes())
if err != nil { if err != nil {
return err return err
} }
return wCtx.awaitTx() return wCtx.AwaitTx()
} }
func parseConfigPair(kvStr string, force bool) (key string, val any, err error) { func parseConfigPair(kvStr string, force bool) (key string, val any, err error) {

View file

@ -193,11 +193,11 @@ func restoreContainers(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("invalid filename: %w", err) return fmt.Errorf("invalid filename: %w", err)
} }
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return err return err
} }
defer wCtx.close() defer wCtx.Close()
containers, err := parseContainers(filename) containers, err := parseContainers(filename)
if err != nil { if err != nil {
@ -219,10 +219,10 @@ func restoreContainers(cmd *cobra.Command, _ []string) error {
return err return err
} }
return wCtx.awaitTx() return wCtx.AwaitTx()
} }
func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *initializeContext, ch util.Uint160) error { func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *InitializeContext, ch util.Uint160) error {
bw := io.NewBufBinWriter() bw := io.NewBufBinWriter()
for _, cnt := range containers { for _, cnt := range containers {
hv := hash.Sha256(cnt.Value) hv := hash.Sha256(cnt.Value)
@ -246,7 +246,7 @@ func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd
panic(bw.Err) panic(bw.Err)
} }
if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil {
return err return err
} }
} }
@ -262,7 +262,7 @@ func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) {
} }
} }
func isContainerRestored(cmd *cobra.Command, wCtx *initializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { func isContainerRestored(cmd *cobra.Command, wCtx *InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) {
emit.AppCall(bw.BinWriter, containerHash, "get", callflag.All, hashValue.BytesBE()) emit.AppCall(bw.BinWriter, containerHash, "get", callflag.All, hashValue.BytesBE())
res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil) res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil)
if err != nil { if err != nil {
@ -300,7 +300,7 @@ func parseContainers(filename string) ([]Container, error) {
return containers, nil return containers, nil
} }
func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { func fetchContainerContractHash(wCtx *InitializeContext) (util.Uint160, error) {
r := management.NewReader(wCtx.ReadOnlyInvoker) r := management.NewReader(wCtx.ReadOnlyInvoker)
nnsCs, err := r.GetContractByID(1) nnsCs, err := r.GetContractByID(1)
if err != nil { if err != nil {

View file

@ -60,11 +60,11 @@ func init() {
func deployContractCmd(cmd *cobra.Command, args []string) error { func deployContractCmd(cmd *cobra.Command, args []string) error {
v := viper.GetViper() v := viper.GetViper()
c, err := newInitializeContext(cmd, v) c, err := NewInitializeContext(cmd, v)
if err != nil { if err != nil {
return fmt.Errorf("initialization error: %w", err) return fmt.Errorf("initialization error: %w", err)
} }
defer c.close() defer c.Close()
ctrPath, _ := cmd.Flags().GetString(contractPathFlag) ctrPath, _ := cmd.Flags().GetString(contractPathFlag)
ctrName, err := probeContractName(ctrPath) ctrName, err := probeContractName(ctrPath)
@ -123,13 +123,13 @@ func deployContractCmd(cmd *cobra.Command, args []string) error {
panic(fmt.Errorf("BUG: can't create deployment script: %w", writer.Err)) panic(fmt.Errorf("BUG: can't create deployment script: %w", writer.Err))
} }
if err := c.sendCommitteeTx(writer.Bytes(), false); err != nil { if err := c.SendCommitteeTx(writer.Bytes(), false); err != nil {
return err return err
} }
return c.awaitTx() return c.AwaitTx()
} }
func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domain string, cs *contractState, writer *io.BufBinWriter) error { func registerNNS(nnsCs *state.Contract, c *InitializeContext, zone string, domain string, cs *util.ContractState, writer *io.BufBinWriter) error {
bw := io.NewBufBinWriter() bw := io.NewBufBinWriter()
emit.Instruction(bw.BinWriter, opcode.INITSSLOT, []byte{1}) emit.Instruction(bw.BinWriter, opcode.INITSSLOT, []byte{1})
emit.AppCall(bw.BinWriter, nnsCs.Hash, "getPrice", callflag.All) emit.AppCall(bw.BinWriter, nnsCs.Hash, "getPrice", callflag.All)
@ -139,7 +139,7 @@ func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domai
start := bw.Len() start := bw.Len()
needRecord := false needRecord := false
ok, err := c.nnsRootRegistered(nnsCs.Hash, zone) ok, err := c.NNSRootRegistered(nnsCs.Hash, zone)
if err != nil { if err != nil {
return err return err
} else if !ok { } else if !ok {
@ -155,7 +155,7 @@ func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domai
frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600))
emit.Opcodes(bw.BinWriter, opcode.ASSERT) emit.Opcodes(bw.BinWriter, opcode.ASSERT)
} else { } else {
s, ok, err := c.nnsRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) s, ok, err := c.NNSRegisterDomainScript(nnsCs.Hash, cs.Hash, domain)
if err != nil { if err != nil {
return err return err
} }

View file

@ -54,7 +54,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error {
irSize := 0 irSize := 0
for ; irSize < lastGlagoliticLetter; irSize++ { for ; irSize < lastGlagoliticLetter; irSize++ {
ok, err := nnsIsAvailable(c, cs.Hash, getAlphabetNNSDomain(irSize)) ok, err := morphUtil.NNSIsAvailable(c, cs.Hash, getAlphabetNNSDomain(irSize))
if err != nil { if err != nil {
return err return err
} else if ok { } else if ok {

View file

@ -17,7 +17,7 @@ import (
) )
func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { func forceNewEpochCmd(cmd *cobra.Command, _ []string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return fmt.Errorf("can't to initialize context: %w", err) return fmt.Errorf("can't to initialize context: %w", err)
} }
@ -38,8 +38,8 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error {
return err return err
} }
if err = wCtx.sendConsensusTx(bw.Bytes()); err == nil { if err = wCtx.SendConsensusTx(bw.Bytes()); err == nil {
err = wCtx.awaitTx() err = wCtx.AwaitTx()
} }
if err != nil && strings.Contains(err.Error(), "invalid epoch") { if err != nil && strings.Contains(err.Error(), "invalid epoch") {
cmd.Println("Epoch has already ticked.") cmd.Println("Epoch has already ticked.")
@ -48,7 +48,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error {
return err return err
} }
func emitNewEpochCall(bw *io.BufBinWriter, wCtx *initializeContext, nmHash util.Uint160) error { func emitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error {
curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch")) curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch"))
if err != nil { if err != nil {
return errors.New("can't fetch current epoch from the netmap contract") return errors.New("can't fetch current epoch from the netmap contract")

View file

@ -416,11 +416,11 @@ type frostfsidClient struct {
bw *io.BufBinWriter bw *io.BufBinWriter
contractHash util.Uint160 contractHash util.Uint160
roCli *frostfsidclient.Client // client can be used only for waiting tx, parsing and forming method params roCli *frostfsidclient.Client // client can be used only for waiting tx, parsing and forming method params
wCtx *initializeContext wCtx *InitializeContext
} }
func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) {
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return nil, fmt.Errorf("can't to initialize context: %w", err) return nil, fmt.Errorf("can't to initialize context: %w", err)
} }
@ -449,16 +449,16 @@ func (f *frostfsidClient) addCall(method string, args []any) {
} }
func (f *frostfsidClient) sendWait() error { func (f *frostfsidClient) sendWait() error {
if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil { if err := f.wCtx.SendConsensusTx(f.bw.Bytes()); err != nil {
return err return err
} }
f.bw.Reset() f.bw.Reset()
return f.wCtx.awaitTx() return f.wCtx.AwaitTx()
} }
func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) {
if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil { if err := f.wCtx.SendConsensusTx(f.bw.Bytes()); err != nil {
return nil, err return nil, err
} }
f.bw.Reset() f.bw.Reset()

View file

@ -195,7 +195,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error
return err return err
} }
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return err return err
} }
@ -208,11 +208,11 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error
return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err) return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err)
} }
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil { if err := wCtx.SendCommitteeTx(bw.Bytes(), false); err != nil {
return err return err
} }
return wCtx.awaitTx() return wCtx.AwaitTx()
} }
func parseGASAmount(s string) (fixedn.Fixed8, error) { func parseGASAmount(s string) (fixedn.Fixed8, error) {

View file

@ -7,6 +7,7 @@ import (
"path/filepath" "path/filepath"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
@ -75,8 +76,8 @@ func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*
return w, nil return w, nil
} }
func (c *initializeContext) addManifestGroup(h util.Uint160, cs *contractState) error { func addManifestGroup(cw *wallet.Wallet, h util.Uint160, cs *util2.ContractState) error {
priv := c.ContractWallet.Accounts[0].PrivateKey() priv := cw.Accounts[0].PrivateKey()
pub := priv.PublicKey() pub := priv.PublicKey()
sig := priv.Sign(h.BytesBE()) sig := priv.Sign(h.BytesBE())

View file

@ -20,14 +20,14 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type cache struct { type Cache struct {
nnsCs *state.Contract NNSCs *state.Contract
groupKey *keys.PublicKey GroupKey *keys.PublicKey
} }
type initializeContext struct { type InitializeContext struct {
morphUtil.ClientContext morphUtil.ClientContext
cache Cache
// CommitteeAcc is used for retrieving the committee address and the verification script. // CommitteeAcc is used for retrieving the committee address and the verification script.
CommitteeAcc *wallet.Account CommitteeAcc *wallet.Account
// ConsensusAcc is used for retrieving the committee address and the verification script. // ConsensusAcc is used for retrieving the committee address and the verification script.
@ -37,62 +37,62 @@ type initializeContext struct {
ContractWallet *wallet.Wallet ContractWallet *wallet.Wallet
// Accounts contains simple signature accounts in the same order as in Wallets. // Accounts contains simple signature accounts in the same order as in Wallets.
Accounts []*wallet.Account Accounts []*wallet.Account
Contracts map[string]*contractState Contracts map[string]*morphUtil.ContractState
Command *cobra.Command Command *cobra.Command
ContractPath string ContractPath string
ContractURL string ContractURL string
} }
func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { func initializeSideChainCmd(cmd *cobra.Command, _ []string) error {
initCtx, err := newInitializeContext(cmd, viper.GetViper()) initCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return fmt.Errorf("initialization error: %w", err) return fmt.Errorf("initialization error: %w", err)
} }
defer initCtx.close() defer initCtx.Close()
// 1. Transfer funds to committee accounts. // 1. Transfer funds to committee accounts.
cmd.Println("Stage 1: transfer GAS to alphabet nodes.") cmd.Println("Stage 1: transfer GAS to alphabet nodes.")
if err := initCtx.transferFunds(); err != nil { if err := transferFunds(initCtx); err != nil {
return err return err
} }
cmd.Println("Stage 2: set notary and alphabet nodes in designate contract.") cmd.Println("Stage 2: set notary and alphabet nodes in designate contract.")
if err := initCtx.setNotaryAndAlphabetNodes(); err != nil { if err := setNotaryAndAlphabetNodes(initCtx); err != nil {
return err return err
} }
// 3. Deploy NNS contract. // 3. Deploy NNS contract.
cmd.Println("Stage 3: deploy NNS contract.") cmd.Println("Stage 3: deploy NNS contract.")
if err := initCtx.deployNNS(deployMethodName); err != nil { if err := deployNNS(initCtx, deployMethodName); err != nil {
return err return err
} }
// 4. Deploy NeoFS contracts. // 4. Deploy NeoFS contracts.
cmd.Println("Stage 4: deploy NeoFS contracts.") cmd.Println("Stage 4: deploy NeoFS contracts.")
if err := initCtx.deployContracts(); err != nil { if err := deployContracts(initCtx); err != nil {
return err return err
} }
cmd.Println("Stage 4.1: Transfer GAS to proxy contract.") cmd.Println("Stage 4.1: Transfer GAS to proxy contract.")
if err := initCtx.transferGASToProxy(); err != nil { if err := transferGASToProxy(initCtx); err != nil {
return err return err
} }
cmd.Println("Stage 5: register candidates.") cmd.Println("Stage 5: register candidates.")
if err := initCtx.registerCandidates(); err != nil { if err := registerCandidates(initCtx); err != nil {
return err return err
} }
cmd.Println("Stage 6: transfer NEO to alphabet contracts.") cmd.Println("Stage 6: transfer NEO to alphabet contracts.")
if err := initCtx.transferNEOToAlphabetContracts(); err != nil { if err := transferNEOToAlphabetContracts(initCtx); err != nil {
return err return err
} }
cmd.Println("Stage 7: set addresses in NNS.") cmd.Println("Stage 7: set addresses in NNS.")
return initCtx.setNNS() return setNNS(initCtx)
} }
func (c *initializeContext) close() { func (c *InitializeContext) Close() {
if local, ok := c.Client.(*morphUtil.LocalClient); ok { if local, ok := c.Client.(*morphUtil.LocalClient); ok {
err := local.Dump() err := local.Dump()
if err != nil { if err != nil {
@ -102,7 +102,7 @@ func (c *initializeContext) close() {
} }
} }
func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) { func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContext, error) {
walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag))
wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) wallets, err := morphUtil.GetAlphabetWallets(v, walletDir)
if err != nil { if err != nil {
@ -160,7 +160,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
return nil, fmt.Errorf("client context: %w", err) return nil, fmt.Errorf("client context: %w", err)
} }
initCtx := &initializeContext{ initCtx := &InitializeContext{
ClientContext: *cliCtx, ClientContext: *cliCtx,
ConsensusAcc: consensusAcc, ConsensusAcc: consensusAcc,
CommitteeAcc: committeeAcc, CommitteeAcc: committeeAcc,
@ -168,7 +168,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
Wallets: wallets, Wallets: wallets,
Accounts: accounts, Accounts: accounts,
Command: cmd, Command: cmd,
Contracts: make(map[string]*contractState), Contracts: make(map[string]*morphUtil.ContractState),
ContractPath: ctrPath, ContractPath: ctrPath,
ContractURL: ctrURL, ContractURL: ctrURL,
} }
@ -246,13 +246,13 @@ func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) {
return accounts, nil return accounts, nil
} }
func (c *initializeContext) awaitTx() error { func (c *InitializeContext) AwaitTx() error {
return c.ClientContext.AwaitTx(c.Command) return c.ClientContext.AwaitTx(c.Command)
} }
func (c *initializeContext) nnsContractState() (*state.Contract, error) { func (c *InitializeContext) NNSContractState() (*state.Contract, error) {
if c.nnsCs != nil { if c.NNSCs != nil {
return c.nnsCs, nil return c.NNSCs, nil
} }
r := management.NewReader(c.ReadOnlyInvoker) r := management.NewReader(c.ReadOnlyInvoker)
@ -261,16 +261,16 @@ func (c *initializeContext) nnsContractState() (*state.Contract, error) {
return nil, err return nil, err
} }
c.nnsCs = cs c.NNSCs = cs
return cs, nil return cs, nil
} }
func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transaction.Signer { func (c *InitializeContext) GetSigner(tryGroup bool, acc *wallet.Account) transaction.Signer {
if tryGroup && c.groupKey != nil { if tryGroup && c.GroupKey != nil {
return transaction.Signer{ return transaction.Signer{
Account: acc.Contract.ScriptHash(), Account: acc.Contract.ScriptHash(),
Scopes: transaction.CustomGroups, Scopes: transaction.CustomGroups,
AllowedGroups: keys.PublicKeys{c.groupKey}, AllowedGroups: keys.PublicKeys{c.GroupKey},
} }
} }
@ -283,14 +283,14 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa
return signer return signer
} }
nnsCs, err := c.nnsContractState() nnsCs, err := c.NNSContractState()
if err != nil { if err != nil {
return signer return signer
} }
groupKey, err := nnsResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, morphClient.NNSGroupKeyName) groupKey, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, morphClient.NNSGroupKeyName)
if err == nil { if err == nil {
c.groupKey = groupKey c.GroupKey = groupKey
signer.Scopes = transaction.CustomGroups signer.Scopes = transaction.CustomGroups
signer.AllowedGroups = keys.PublicKeys{groupKey} signer.AllowedGroups = keys.PublicKeys{groupKey}
@ -298,21 +298,21 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa
return signer return signer
} }
// sendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC. // SendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC.
// If tryGroup is false, global scope is used for the signer (useful when // If tryGroup is false, global scope is used for the signer (useful when
// working with native contracts). // working with native contracts).
func (c *initializeContext) sendCommitteeTx(script []byte, tryGroup bool) error { func (c *InitializeContext) SendCommitteeTx(script []byte, tryGroup bool) error {
return c.sendMultiTx(script, tryGroup, false) return c.sendMultiTx(script, tryGroup, false)
} }
// sendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC. // SendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC.
// Not that because this is used only after the contracts were initialized and deployed, // Not that because this is used only after the contracts were initialized and deployed,
// we always try to have a group scope. // we always try to have a group scope.
func (c *initializeContext) sendConsensusTx(script []byte) error { func (c *InitializeContext) SendConsensusTx(script []byte) error {
return c.sendMultiTx(script, true, true) return c.sendMultiTx(script, true, true)
} }
func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error { func (c *InitializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error {
var act *actor.Actor var act *actor.Actor
var err error var err error
@ -321,12 +321,12 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen
// Even for consensus signatures we need the committee to pay. // Even for consensus signatures we need the committee to pay.
signers := make([]actor.SignerAccount, 1, 2) signers := make([]actor.SignerAccount, 1, 2)
signers[0] = actor.SignerAccount{ signers[0] = actor.SignerAccount{
Signer: c.getSigner(tryGroup, c.CommitteeAcc), Signer: c.GetSigner(tryGroup, c.CommitteeAcc),
Account: c.CommitteeAcc, Account: c.CommitteeAcc,
} }
if withConsensus { if withConsensus {
signers = append(signers, actor.SignerAccount{ signers = append(signers, actor.SignerAccount{
Signer: c.getSigner(tryGroup, c.ConsensusAcc), Signer: c.GetSigner(tryGroup, c.ConsensusAcc),
Account: c.ConsensusAcc, Account: c.ConsensusAcc,
}) })
} }
@ -346,11 +346,11 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen
return fmt.Errorf("could not perform test invocation: %w", err) return fmt.Errorf("could not perform test invocation: %w", err)
} }
if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil { if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil {
return err return err
} }
if withConsensus { if withConsensus {
if err := c.multiSign(tx, morphUtil.ConsensusAccountName); err != nil { if err := c.MultiSign(tx, morphUtil.ConsensusAccountName); err != nil {
return err return err
} }
} }

View file

@ -4,7 +4,6 @@ import (
"archive/tar" "archive/tar"
"compress/gzip" "compress/gzip"
"encoding/hex" "encoding/hex"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -22,12 +21,11 @@ import (
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
io2 "github.com/nspcc-dev/neo-go/pkg/io" io2 "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"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"
@ -66,24 +64,16 @@ var (
} }
) )
type contractState struct {
NEF *nef.File
RawNEF []byte
Manifest *manifest.Manifest
RawManifest []byte
Hash util.Uint160
}
const ( const (
updateMethodName = "update" updateMethodName = "update"
deployMethodName = "deploy" deployMethodName = "deploy"
) )
func (c *initializeContext) deployNNS(method string) error { func deployNNS(c *InitializeContext, method string) error {
cs := c.getContract(morphUtil.NNSContract) cs := c.GetContract(morphUtil.NNSContract)
h := cs.Hash h := cs.Hash
nnsCs, err := c.nnsContractState() nnsCs, err := c.NNSContractState()
if err != nil { if err != nil {
return err return err
} }
@ -99,7 +89,7 @@ func (c *initializeContext) deployNNS(method string) error {
h = nnsCs.Hash h = nnsCs.Hash
} }
err = c.addManifestGroup(h, cs) err = addManifestGroup(c.ContractWallet, h, cs)
if err != nil { if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err) return fmt.Errorf("can't sign manifest group: %v", err)
} }
@ -116,17 +106,17 @@ func (c *initializeContext) deployNNS(method string) error {
return fmt.Errorf("failed to create deploy tx for %s: %w", morphUtil.NNSContract, err) return fmt.Errorf("failed to create deploy tx for %s: %w", morphUtil.NNSContract, err)
} }
if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil {
return fmt.Errorf("can't send deploy transaction: %w", err) return fmt.Errorf("can't send deploy transaction: %w", err)
} }
return c.awaitTx() return c.AwaitTx()
} }
func (c *initializeContext) updateContracts() error { func updateContractsInternal(c *InitializeContext) error {
alphaCs := c.getContract(morphUtil.AlphabetContract) alphaCs := c.GetContract(morphUtil.AlphabetContract)
nnsCs, err := c.nnsContractState() nnsCs, err := c.NNSContractState()
if err != nil { if err != nil {
return err return err
} }
@ -147,19 +137,19 @@ func (c *initializeContext) updateContracts() error {
emit.Bytes(w.BinWriter, alphaCs.RawNEF) emit.Bytes(w.BinWriter, alphaCs.RawNEF)
emit.Opcodes(w.BinWriter, opcode.STSFLD0) emit.Opcodes(w.BinWriter, opcode.STSFLD0)
keysParam, err := c.deployAlphabetAccounts(nnsHash, w, alphaCs) keysParam, err := deployAlphabetAccounts(c, nnsHash, w, alphaCs)
if err != nil { if err != nil {
return err return err
} }
w.Reset() w.Reset()
if err = c.deployOrUpdateContracts(w, nnsHash, keysParam); err != nil { if err = deployOrUpdateContracts(c, w, nnsHash, keysParam); err != nil {
return err return err
} }
groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey() groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey()
_, _, err = c.emitUpdateNNSGroupScript(w, nnsHash, groupKey) _, _, err = c.EmitUpdateNNSGroupScript(w, nnsHash, groupKey)
if err != nil { if err != nil {
return err return err
} }
@ -170,20 +160,20 @@ func (c *initializeContext) updateContracts() error {
emit.Opcodes(w.BinWriter, opcode.PACK) emit.Opcodes(w.BinWriter, opcode.PACK)
emit.AppCallNoArgs(w.BinWriter, nnsHash, "setPrice", callflag.All) emit.AppCallNoArgs(w.BinWriter, nnsHash, "setPrice", callflag.All)
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil { if err := c.SendCommitteeTx(w.Bytes(), false); err != nil {
return err return err
} }
return c.awaitTx() return c.AwaitTx()
} }
func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error { func deployOrUpdateContracts(c *InitializeContext, w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error {
emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1})
emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All) emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All)
emit.Opcodes(w.BinWriter, opcode.STSFLD0) emit.Opcodes(w.BinWriter, opcode.STSFLD0)
emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1) emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1)
for _, ctrName := range contractList { for _, ctrName := range contractList {
cs := c.getContract(ctrName) cs := c.GetContract(ctrName)
method := updateMethodName method := updateMethodName
ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName)) ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName))
@ -196,7 +186,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
} }
} }
err = c.addManifestGroup(ctrHash, cs) err = addManifestGroup(c.ContractWallet, ctrHash, cs)
if err != nil { if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err) return fmt.Errorf("can't sign manifest group: %v", err)
} }
@ -206,7 +196,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
invokeHash = ctrHash invokeHash = ctrHash
} }
args, err := c.getContractDeployData(ctrName, keysParam, updateMethodName) args, err := getContractDeployData(c, ctrName, keysParam, updateMethodName)
if err != nil { if err != nil {
return fmt.Errorf("%s: getting update params: %v", ctrName, err) return fmt.Errorf("%s: getting update params: %v", ctrName, err)
} }
@ -223,9 +213,9 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
w.WriteBytes(res.Script) w.WriteBytes(res.Script)
if method == deployMethodName { if method == deployMethodName {
// same actions are done in initializeContext.setNNS, can be unified // same actions are done in InitializeContext.setNNS, can be unified
domain := ctrName + ".frostfs" domain := ctrName + ".frostfs"
script, ok, err := c.nnsRegisterDomainScript(nnsHash, cs.Hash, domain) script, ok, err := c.NNSRegisterDomainScript(nnsHash, cs.Hash, domain)
if err != nil { if err != nil {
return err return err
} }
@ -243,7 +233,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
return nil return nil
} }
func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *contractState) ([]any, error) { func deployAlphabetAccounts(c *InitializeContext, nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) {
var keysParam []any var keysParam []any
baseGroups := alphaCs.Manifest.Groups baseGroups := alphaCs.Manifest.Groups
@ -257,11 +247,11 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.
keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes())
params := c.getAlphabetDeployItems(i, len(c.Wallets)) params := c.GetAlphabetDeployItems(i, len(c.Wallets))
emit.Array(w.BinWriter, params...) emit.Array(w.BinWriter, params...)
alphaCs.Manifest.Groups = baseGroups alphaCs.Manifest.Groups = baseGroups
err = c.addManifestGroup(ctrHash, alphaCs) err = addManifestGroup(c.ContractWallet, ctrHash, alphaCs)
if err != nil { if err != nil {
return nil, fmt.Errorf("can't sign manifest group: %v", err) return nil, fmt.Errorf("can't sign manifest group: %v", err)
} }
@ -272,7 +262,7 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.
emit.Opcodes(w.BinWriter, opcode.PACK) emit.Opcodes(w.BinWriter, opcode.PACK)
emit.AppCallNoArgs(w.BinWriter, ctrHash, updateMethodName, callflag.All) emit.AppCallNoArgs(w.BinWriter, ctrHash, updateMethodName, callflag.All)
} }
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil { if err := c.SendCommitteeTx(w.Bytes(), false); err != nil {
if !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { if !strings.Contains(err.Error(), common.ErrAlreadyUpdated) {
return nil, err return nil, err
} }
@ -282,8 +272,8 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.
return keysParam, nil return keysParam, nil
} }
func (c *initializeContext) deployContracts() error { func deployContracts(c *InitializeContext) error {
alphaCs := c.getContract(morphUtil.AlphabetContract) alphaCs := c.GetContract(morphUtil.AlphabetContract)
var keysParam []any var keysParam []any
@ -292,19 +282,19 @@ func (c *initializeContext) deployContracts() error {
// alphabet contracts should be deployed by individual nodes to get different hashes. // alphabet contracts should be deployed by individual nodes to get different hashes.
for i, acc := range c.Accounts { for i, acc := range c.Accounts {
ctrHash := state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) ctrHash := state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name)
if c.isUpdated(ctrHash, alphaCs) { if c.IsUpdated(ctrHash, alphaCs) {
c.Command.Printf("Alphabet contract #%d is already deployed.\n", i) c.Command.Printf("Alphabet contract #%d is already deployed.\n", i)
continue continue
} }
alphaCs.Manifest.Groups = baseGroups alphaCs.Manifest.Groups = baseGroups
err := c.addManifestGroup(ctrHash, alphaCs) err := addManifestGroup(c.ContractWallet, ctrHash, alphaCs)
if err != nil { if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err) return fmt.Errorf("can't sign manifest group: %v", err)
} }
keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes())
params := getContractDeployParameters(alphaCs, c.getAlphabetDeployItems(i, len(c.Wallets))) params := getContractDeployParameters(alphaCs, c.GetAlphabetDeployItems(i, len(c.Wallets)))
act, err := actor.NewSimple(c.Client, acc) act, err := actor.NewSimple(c.Client, acc)
if err != nil { if err != nil {
@ -320,20 +310,20 @@ func (c *initializeContext) deployContracts() error {
} }
for _, ctrName := range contractList { for _, ctrName := range contractList {
cs := c.getContract(ctrName) cs := c.GetContract(ctrName)
ctrHash := cs.Hash ctrHash := cs.Hash
if c.isUpdated(ctrHash, cs) { if c.IsUpdated(ctrHash, cs) {
c.Command.Printf("%s contract is already deployed.\n", ctrName) c.Command.Printf("%s contract is already deployed.\n", ctrName)
continue continue
} }
err := c.addManifestGroup(ctrHash, cs) err := addManifestGroup(c.ContractWallet, ctrHash, cs)
if err != nil { if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err) return fmt.Errorf("can't sign manifest group: %v", err)
} }
args, err := c.getContractDeployData(ctrName, keysParam, deployMethodName) args, err := getContractDeployData(c, ctrName, keysParam, deployMethodName)
if err != nil { if err != nil {
return fmt.Errorf("%s: getting deploy params: %v", ctrName, err) return fmt.Errorf("%s: getting deploy params: %v", ctrName, err)
} }
@ -343,25 +333,25 @@ func (c *initializeContext) deployContracts() error {
return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) return fmt.Errorf("can't deploy %s contract: %w", ctrName, err)
} }
if err := c.sendCommitteeTx(res.Script, false); err != nil { if err := c.SendCommitteeTx(res.Script, false); err != nil {
return err return err
} }
} }
return c.awaitTx() return c.AwaitTx()
} }
func (c *initializeContext) isUpdated(ctrHash util.Uint160, cs *contractState) bool { func (c *InitializeContext) IsUpdated(ctrHash util.Uint160, cs *morphUtil.ContractState) bool {
r := management.NewReader(c.ReadOnlyInvoker) r := management.NewReader(c.ReadOnlyInvoker)
realCs, err := r.GetContract(ctrHash) realCs, err := r.GetContract(ctrHash)
return err == nil && realCs != nil && realCs.NEF.Checksum == cs.NEF.Checksum return err == nil && realCs != nil && realCs.NEF.Checksum == cs.NEF.Checksum
} }
func (c *initializeContext) getContract(ctrName string) *contractState { func (c *InitializeContext) GetContract(ctrName string) *morphUtil.ContractState {
return c.Contracts[ctrName] return c.Contracts[ctrName]
} }
func (c *initializeContext) readContracts(names []string) error { func (c *InitializeContext) readContracts(names []string) error {
var ( var (
fi os.FileInfo fi os.FileInfo
err error err error
@ -401,7 +391,7 @@ func (c *initializeContext) readContracts(names []string) error {
return err return err
} }
for _, name := range names { for _, name := range names {
if err := m[name].parse(); err != nil { if err := m[name].Parse(); err != nil {
return err return err
} }
c.Contracts[name] = m[name] c.Contracts[name] = m[name]
@ -418,7 +408,7 @@ func (c *initializeContext) readContracts(names []string) error {
return nil return nil
} }
func readContract(ctrPath, ctrName string) (*contractState, error) { func readContract(ctrPath, ctrName string) (*morphUtil.ContractState, error) {
rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef")) rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef"))
if err != nil { if err != nil {
return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err) return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err)
@ -428,34 +418,18 @@ func readContract(ctrPath, ctrName string) (*contractState, error) {
return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err) return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err)
} }
cs := &contractState{ cs := &morphUtil.ContractState{
RawNEF: rawNef, RawNEF: rawNef,
RawManifest: rawManif, RawManifest: rawManif,
} }
return cs, cs.parse() return cs, cs.Parse()
} }
func (cs *contractState) parse() error { func readContractsFromArchive(file io.Reader, names []string) (map[string]*morphUtil.ContractState, error) {
nf, err := nef.FileFromBytes(cs.RawNEF) m := make(map[string]*morphUtil.ContractState, len(names))
if err != nil {
return fmt.Errorf("can't parse NEF file: %w", err)
}
m := new(manifest.Manifest)
if err := json.Unmarshal(cs.RawManifest, m); err != nil {
return fmt.Errorf("can't parse manifest file: %w", err)
}
cs.NEF = &nf
cs.Manifest = m
return nil
}
func readContractsFromArchive(file io.Reader, names []string) (map[string]*contractState, error) {
m := make(map[string]*contractState, len(names))
for i := range names { for i := range names {
m[names[i]] = new(contractState) m[names[i]] = new(morphUtil.ContractState)
} }
gr, err := gzip.NewReader(file) gr, err := gzip.NewReader(file)
@ -503,11 +477,11 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*contr
return m, nil return m, nil
} }
func getContractDeployParameters(cs *contractState, deployData []any) []any { func getContractDeployParameters(cs *morphUtil.ContractState, deployData []any) []any {
return []any{cs.RawNEF, cs.RawManifest, deployData} return []any{cs.RawNEF, cs.RawManifest, deployData}
} }
func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any, method string) ([]any, error) { func getContractDeployData(c *InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) {
items := make([]any, 0, 6) items := make([]any, 0, 6)
switch ctrName { switch ctrName {
@ -544,7 +518,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
err error err error
) )
if method == updateMethodName { if method == updateMethodName {
h, found, err = c.getFrostfsIDAdminFromContract() h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker)
} }
if method != updateMethodName || err == nil && !found { if method != updateMethodName || err == nil && !found {
h, found, err = getFrostfsIDAdmin(viper.GetViper()) h, found, err = getFrostfsIDAdmin(viper.GetViper())
@ -561,7 +535,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
case morphUtil.NetmapContract: case morphUtil.NetmapContract:
md := getDefaultNetmapContractConfigMap() md := getDefaultNetmapContractConfigMap()
if method == updateMethodName { if method == updateMethodName {
if err := c.mergeNetmapConfig(md); err != nil { if err := mergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil {
return nil, err return nil, err
} }
} }
@ -586,17 +560,17 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
return items, nil return items, nil
} }
func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, error) { func getFrostfsIDAdminFromContract(roInvoker *invoker.Invoker) (util.Uint160, bool, error) {
r := management.NewReader(c.ReadOnlyInvoker) r := management.NewReader(roInvoker)
cs, err := r.GetContractByID(1) cs, err := r.GetContractByID(1)
if err != nil { if err != nil {
return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err)
} }
fidHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract)) fidHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract))
if err != nil { if err != nil {
return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err)
} }
item, err := unwrap.Item(c.ReadOnlyInvoker.Call(fidHash, "getAdmin")) item, err := unwrap.Item(roInvoker.Call(fidHash, "getAdmin"))
if err != nil { if err != nil {
return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err) return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err)
} }
@ -615,25 +589,25 @@ func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool,
return h, true, nil return h, true, nil
} }
func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, error) { func getNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Item, error) {
r := management.NewReader(c.ReadOnlyInvoker) r := management.NewReader(roInvoker)
cs, err := r.GetContractByID(1) cs, err := r.GetContractByID(1)
if err != nil { if err != nil {
return nil, fmt.Errorf("get nns contract: %w", err) return nil, fmt.Errorf("get nns contract: %w", err)
} }
nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract)) nmHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract))
if err != nil { if err != nil {
return nil, fmt.Errorf("can't get netmap contract hash: %w", err) return nil, fmt.Errorf("can't get netmap contract hash: %w", err)
} }
arr, err := unwrap.Array(c.ReadOnlyInvoker.Call(nmHash, "listConfig")) arr, err := unwrap.Array(roInvoker.Call(nmHash, "listConfig"))
if err != nil { if err != nil {
return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract") return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract")
} }
return arr, err return arr, err
} }
func (c *initializeContext) mergeNetmapConfig(md map[string]any) error { func mergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error {
arr, err := c.getNetConfigFromNetmapContract() arr, err := getNetConfigFromNetmapContract(roInvoker)
if err != nil { if err != nil {
return err return err
} }
@ -652,7 +626,7 @@ func (c *initializeContext) mergeNetmapConfig(md map[string]any) error {
return nil return nil
} }
func (c *initializeContext) getAlphabetDeployItems(i, n int) []any { func (c *InitializeContext) GetAlphabetDeployItems(i, n int) []any {
items := make([]any, 5) items := make([]any, 5)
items[0] = c.Contracts[morphUtil.NetmapContract].Hash items[0] = c.Contracts[morphUtil.NetmapContract].Hash
items[1] = c.Contracts[morphUtil.ProxyContract].Hash items[1] = c.Contracts[morphUtil.ProxyContract].Hash

View file

@ -14,16 +14,11 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "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/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
nnsClient "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"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/vmstate" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
) )
@ -31,14 +26,14 @@ const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second
const frostfsOpsEmail = "ops@frostfs.info" const frostfsOpsEmail = "ops@frostfs.info"
func (c *initializeContext) setNNS() error { func setNNS(c *InitializeContext) error {
r := management.NewReader(c.ReadOnlyInvoker) r := management.NewReader(c.ReadOnlyInvoker)
nnsCs, err := r.GetContractByID(1) nnsCs, err := r.GetContractByID(1)
if err != nil { if err != nil {
return err return err
} }
ok, err := c.nnsRootRegistered(nnsCs.Hash, "frostfs") ok, err := c.NNSRootRegistered(nnsCs.Hash, "frostfs")
if err != nil { if err != nil {
return err return err
} else if !ok { } else if !ok {
@ -47,48 +42,48 @@ func (c *initializeContext) setNNS() error {
"frostfs", c.CommitteeAcc.Contract.ScriptHash(), "frostfs", c.CommitteeAcc.Contract.ScriptHash(),
frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600))
emit.Opcodes(bw.BinWriter, opcode.ASSERT) emit.Opcodes(bw.BinWriter, opcode.ASSERT)
if err := c.sendCommitteeTx(bw.Bytes(), true); err != nil { if err := c.SendCommitteeTx(bw.Bytes(), true); err != nil {
return fmt.Errorf("can't add domain root to NNS: %w", err) return fmt.Errorf("can't add domain root to NNS: %w", err)
} }
if err := c.awaitTx(); err != nil { if err := c.AwaitTx(); err != nil {
return err return err
} }
} }
alphaCs := c.getContract(morphUtil.AlphabetContract) alphaCs := c.GetContract(morphUtil.AlphabetContract)
for i, acc := range c.Accounts { for i, acc := range c.Accounts {
alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name)
domain := getAlphabetNNSDomain(i) domain := getAlphabetNNSDomain(i)
if err := c.nnsRegisterDomain(nnsCs.Hash, alphaCs.Hash, domain); err != nil { if err := nnsRegisterDomain(c, nnsCs.Hash, alphaCs.Hash, domain); err != nil {
return err return err
} }
c.Command.Printf("NNS: Set %s -> %s\n", domain, alphaCs.Hash.StringLE()) c.Command.Printf("NNS: Set %s -> %s\n", domain, alphaCs.Hash.StringLE())
} }
for _, ctrName := range contractList { for _, ctrName := range contractList {
cs := c.getContract(ctrName) cs := c.GetContract(ctrName)
domain := ctrName + ".frostfs" domain := ctrName + ".frostfs"
if err := c.nnsRegisterDomain(nnsCs.Hash, cs.Hash, domain); err != nil { if err := nnsRegisterDomain(c, nnsCs.Hash, cs.Hash, domain); err != nil {
return err return err
} }
c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE()) c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE())
} }
groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey() groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey()
err = c.updateNNSGroup(nnsCs.Hash, groupKey) err = updateNNSGroup(c, nnsCs.Hash, groupKey)
if err != nil { if err != nil {
return err return err
} }
c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes())) c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes()))
return c.awaitTx() return c.AwaitTx()
} }
func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.PublicKey) error { func updateNNSGroup(c *InitializeContext, nnsHash util.Uint160, pub *keys.PublicKey) error {
bw := io.NewBufBinWriter() bw := io.NewBufBinWriter()
keyAlreadyAdded, domainRegCodeEmitted, err := c.emitUpdateNNSGroupScript(bw, nnsHash, pub) keyAlreadyAdded, domainRegCodeEmitted, err := c.EmitUpdateNNSGroupScript(bw, nnsHash, pub)
if keyAlreadyAdded || err != nil { if keyAlreadyAdded || err != nil {
return err return err
} }
@ -101,20 +96,20 @@ func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.Publi
script = w.Bytes() script = w.Bytes()
} }
return c.sendCommitteeTx(script, true) return c.SendCommitteeTx(script, true)
} }
// emitUpdateNNSGroupScript emits script for updating group key stored in NNS. // EmitUpdateNNSGroupScript emits script for updating group key stored in NNS.
// First return value is true iff the key is already there and nothing should be done. // First return value is true iff the key is already there and nothing should be done.
// Second return value is true iff a domain registration code was emitted. // Second return value is true iff a domain registration code was emitted.
func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) { func (c *InitializeContext) EmitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) {
isAvail, err := nnsIsAvailable(c.Client, nnsHash, morphClient.NNSGroupKeyName) isAvail, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, morphClient.NNSGroupKeyName)
if err != nil { if err != nil {
return false, false, err return false, false, err
} }
if !isAvail { if !isAvail {
currentPub, err := nnsResolveKey(c.ReadOnlyInvoker, nnsHash, morphClient.NNSGroupKeyName) currentPub, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsHash, morphClient.NNSGroupKeyName)
if err != nil { if err != nil {
return false, false, err return false, false, err
} }
@ -165,8 +160,8 @@ func wrapRegisterScriptWithPrice(w *io.BufBinWriter, nnsHash util.Uint160, s []b
} }
} }
func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) { func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) {
ok, err := nnsIsAvailable(c.Client, nnsHash, domain) ok, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, domain)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
@ -191,8 +186,8 @@ func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.U
return nil, s == expectedHash, nil return nil, s == expectedHash, nil
} }
func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160, domain string) error { func nnsRegisterDomain(c *InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error {
script, ok, err := c.nnsRegisterDomainScript(nnsHash, expectedHash, domain) script, ok, err := c.NNSRegisterDomainScript(nnsHash, expectedHash, domain)
if ok || err != nil { if ok || err != nil {
return err return err
} }
@ -206,10 +201,10 @@ func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160
domain, int64(nns.TXT), expectedHash.StringLE()) domain, int64(nns.TXT), expectedHash.StringLE())
emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All, emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All,
domain, int64(nns.TXT), address.Uint160ToString(expectedHash)) domain, int64(nns.TXT), address.Uint160ToString(expectedHash))
return c.sendCommitteeTx(w.Bytes(), true) return c.SendCommitteeTx(w.Bytes(), true)
} }
func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string) (bool, error) { func (c *InitializeContext) NNSRootRegistered(nnsHash util.Uint160, zone string) (bool, error) {
res, err := c.CommitteeAct.Call(nnsHash, "isAvailable", "name."+zone) res, err := c.CommitteeAct.Call(nnsHash, "isAvailable", "name."+zone)
if err != nil { if err != nil {
return false, err return false, err
@ -219,43 +214,3 @@ func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string)
} }
var errMissingNNSRecord = errors.New("missing NNS record") var errMissingNNSRecord = errors.New("missing NNS record")
func nnsResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) {
res, err := morphUtil.NNSResolve(inv, nnsHash, domain)
if err != nil {
return nil, err
}
if _, ok := res.Value().(stackitem.Null); ok {
return nil, errors.New("NNS record is missing")
}
arr, ok := res.Value().([]stackitem.Item)
if !ok {
return nil, errors.New("API of the NNS contract method `resolve` has changed")
}
for i := range arr {
var bs []byte
bs, err = arr[i].TryBytes()
if err != nil {
continue
}
return keys.NewPublicKeyFromString(string(bs))
}
return nil, errors.New("no valid keys are found")
}
func nnsIsAvailable(c morphUtil.Client, nnsHash util.Uint160, name string) (bool, error) {
switch c.(type) {
case *rpcclient.Client:
inv := invoker.New(c, nil)
reader := nnsClient.NewReader(inv, nnsHash)
return reader.IsAvailable(name)
default:
b, err := unwrap.Bool(morphUtil.InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil))
if err != nil {
return false, fmt.Errorf("`isAvailable`: invalid response: %w", err)
}
return b, nil
}
}

View file

@ -28,8 +28,8 @@ const (
registerBatchSize = transaction.MaxAttributes - 1 registerBatchSize = transaction.MaxAttributes - 1
) )
func (c *initializeContext) registerCandidateRange(start, end int) error { func registerCandidateRange(c *InitializeContext, start, end int) error {
regPrice, err := c.getCandidateRegisterPrice() regPrice, err := getCandidateRegisterPrice(c)
if err != nil { if err != nil {
return fmt.Errorf("can't fetch registration price: %w", err) return fmt.Errorf("can't fetch registration price: %w", err)
} }
@ -46,7 +46,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error {
} }
signers := []actor.SignerAccount{{ signers := []actor.SignerAccount{{
Signer: c.getSigner(false, c.CommitteeAcc), Signer: c.GetSigner(false, c.CommitteeAcc),
Account: c.CommitteeAcc, Account: c.CommitteeAcc,
}} }}
for _, acc := range c.Accounts[start:end] { for _, acc := range c.Accounts[start:end] {
@ -68,7 +68,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error {
if err != nil { if err != nil {
return fmt.Errorf("can't create tx: %w", err) return fmt.Errorf("can't create tx: %w", err)
} }
if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil { if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil {
return fmt.Errorf("can't sign a transaction: %w", err) return fmt.Errorf("can't sign a transaction: %w", err)
} }
@ -82,7 +82,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error {
return c.SendTx(tx, c.Command, true) return c.SendTx(tx, c.Command, true)
} }
func (c *initializeContext) registerCandidates() error { func registerCandidates(c *InitializeContext) error {
cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neo.Hash, "getCandidates")) cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neo.Hash, "getCandidates"))
if err != nil { if err != nil {
return fmt.Errorf("`getCandidates`: %w", err) return fmt.Errorf("`getCandidates`: %w", err)
@ -107,7 +107,7 @@ func (c *initializeContext) registerCandidates() error {
if have >= end { if have >= end {
continue continue
} }
if err := c.registerCandidateRange(start, end); err != nil { if err := registerCandidateRange(c, start, end); err != nil {
return fmt.Errorf("registering candidates %d..%d: %q", start, end-1, err) return fmt.Errorf("registering candidates %d..%d: %q", start, end-1, err)
} }
} }
@ -115,15 +115,15 @@ func (c *initializeContext) registerCandidates() error {
return nil return nil
} }
func (c *initializeContext) transferNEOToAlphabetContracts() error { func transferNEOToAlphabetContracts(c *InitializeContext) error {
neoHash := neo.Hash neoHash := neo.Hash
ok, err := c.transferNEOFinished(neoHash) ok, err := transferNEOFinished(c, neoHash)
if ok || err != nil { if ok || err != nil {
return err return err
} }
cs := c.getContract(morphUtil.AlphabetContract) cs := c.GetContract(morphUtil.AlphabetContract)
amount := initialAlphabetNEOAmount / len(c.Wallets) amount := initialAlphabetNEOAmount / len(c.Wallets)
bw := io.NewBufBinWriter() bw := io.NewBufBinWriter()
@ -134,14 +134,14 @@ func (c *initializeContext) transferNEOToAlphabetContracts() error {
emit.Opcodes(bw.BinWriter, opcode.ASSERT) emit.Opcodes(bw.BinWriter, opcode.ASSERT)
} }
if err := c.sendCommitteeTx(bw.Bytes(), false); err != nil { if err := c.SendCommitteeTx(bw.Bytes(), false); err != nil {
return err return err
} }
return c.awaitTx() return c.AwaitTx()
} }
func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, error) { func transferNEOFinished(c *InitializeContext, neoHash util.Uint160) (bool, error) {
r := nep17.NewReader(c.ReadOnlyInvoker, neoHash) r := nep17.NewReader(c.ReadOnlyInvoker, neoHash)
bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash()) bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash())
return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err
@ -149,7 +149,7 @@ func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, err
var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response") var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response")
func (c *initializeContext) getCandidateRegisterPrice() (int64, error) { func getCandidateRegisterPrice(c *InitializeContext) (int64, error) {
switch c.Client.(type) { switch c.Client.(type) {
case *rpcclient.Client: case *rpcclient.Client:
inv := invoker.New(c.Client, nil) inv := invoker.New(c.Client, nil)

View file

@ -9,8 +9,8 @@ import (
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
) )
func (c *initializeContext) setNotaryAndAlphabetNodes() error { func setNotaryAndAlphabetNodes(c *InitializeContext) error {
if ok, err := c.setRolesFinished(); ok || err != nil { if ok, err := setRolesFinished(c); ok || err != nil {
if err == nil { if err == nil {
c.Command.Println("Stage 2: already performed.") c.Command.Println("Stage 2: already performed.")
} }
@ -28,14 +28,14 @@ func (c *initializeContext) setNotaryAndAlphabetNodes() error {
emit.AppCall(w.BinWriter, rolemgmt.Hash, "designateAsRole", emit.AppCall(w.BinWriter, rolemgmt.Hash, "designateAsRole",
callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs) callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs)
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil { if err := c.SendCommitteeTx(w.Bytes(), false); err != nil {
return err return err
} }
return c.awaitTx() return c.AwaitTx()
} }
func (c *initializeContext) setRolesFinished() (bool, error) { func setRolesFinished(c *InitializeContext) (bool, error) {
height, err := c.Client.GetBlockCount() height, err := c.Client.GetBlockCount()
if err != nil { if err != nil {
return false, err return false, err

View file

@ -28,8 +28,8 @@ const (
initialProxyGASAmount = 50_000 * native.GASFactor initialProxyGASAmount = 50_000 * native.GASFactor
) )
func (c *initializeContext) transferFunds() error { func transferFunds(c *InitializeContext) error {
ok, err := c.transferFundsFinished() ok, err := transferFundsFinished(c)
if ok || err != nil { if ok || err != nil {
if err == nil { if err == nil {
c.Command.Println("Stage 1: already performed.") c.Command.Println("Stage 1: already performed.")
@ -68,14 +68,14 @@ func (c *initializeContext) transferFunds() error {
return fmt.Errorf("can't create transfer transaction: %w", err) return fmt.Errorf("can't create transfer transaction: %w", err)
} }
if err := c.multiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil { if err := c.MultiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil {
return fmt.Errorf("can't send transfer transaction: %w", err) return fmt.Errorf("can't send transfer transaction: %w", err)
} }
return c.awaitTx() return c.AwaitTx()
} }
func (c *initializeContext) transferFundsFinished() (bool, error) { func transferFundsFinished(c *InitializeContext) (bool, error) {
acc := c.Accounts[0] acc := c.Accounts[0]
r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash)
@ -83,15 +83,15 @@ func (c *initializeContext) transferFundsFinished() (bool, error) {
return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err
} }
func (c *initializeContext) multiSignAndSend(tx *transaction.Transaction, accType string) error { func (c *InitializeContext) MultiSignAndSend(tx *transaction.Transaction, accType string) error {
if err := c.multiSign(tx, accType); err != nil { if err := c.MultiSign(tx, accType); err != nil {
return err return err
} }
return c.SendTx(tx, c.Command, false) return c.SendTx(tx, c.Command, false)
} }
func (c *initializeContext) multiSign(tx *transaction.Transaction, accType string) error { func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType string) error {
version, err := c.Client.GetVersion() version, err := c.Client.GetVersion()
if err != nil { if err != nil {
// error appears only if client // error appears only if client
@ -143,8 +143,8 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin
return fmt.Errorf("%s account was not found among transaction signers", accType) return fmt.Errorf("%s account was not found among transaction signers", accType)
} }
func (c *initializeContext) transferGASToProxy() error { func transferGASToProxy(c *InitializeContext) error {
proxyCs := c.getContract(morphUtil.ProxyContract) proxyCs := c.GetContract(morphUtil.ProxyContract)
r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash)
bal, err := r.BalanceOf(proxyCs.Hash) bal, err := r.BalanceOf(proxyCs.Hash)
@ -161,11 +161,11 @@ func (c *initializeContext) transferGASToProxy() error {
return err return err
} }
if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil {
return err return err
} }
return c.awaitTx() return c.AwaitTx()
} }
type transferTarget struct { type transferTarget struct {

View file

@ -25,7 +25,7 @@ const (
) )
func setPolicyCmd(cmd *cobra.Command, args []string) error { func setPolicyCmd(cmd *cobra.Command, args []string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return fmt.Errorf("can't to initialize context: %w", err) return fmt.Errorf("can't to initialize context: %w", err)
} }
@ -51,11 +51,11 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error {
emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value)) emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value))
} }
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil { if err := wCtx.SendCommitteeTx(bw.Bytes(), false); err != nil {
return err return err
} }
return wCtx.awaitTx() return wCtx.AwaitTx()
} }
func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { func dumpPolicyCmd(cmd *cobra.Command, _ []string) error {

View file

@ -36,7 +36,7 @@ func removeProxyAccount(cmd *cobra.Command, _ []string) {
} }
func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return fmt.Errorf("can't to initialize context: %w", err) return fmt.Errorf("can't to initialize context: %w", err)
} }
@ -55,11 +55,11 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error
bw := io.NewBufBinWriter() bw := io.NewBufBinWriter()
emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr) emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr)
if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil {
return err return err
} }
if err = wCtx.awaitTx(); err != nil { if err = wCtx.AwaitTx(); err != nil {
return err return err
} }

View file

@ -29,11 +29,11 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error {
} }
} }
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return fmt.Errorf("can't initialize context: %w", err) return fmt.Errorf("can't initialize context: %w", err)
} }
defer wCtx.close() defer wCtx.Close()
r := management.NewReader(wCtx.ReadOnlyInvoker) r := management.NewReader(wCtx.ReadOnlyInvoker)
cs, err := r.GetContractByID(1) cs, err := r.GetContractByID(1)
@ -56,9 +56,9 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error {
return err return err
} }
if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil {
return err return err
} }
return wCtx.awaitTx() return wCtx.AwaitTx()
} }

View file

@ -8,14 +8,14 @@ import (
) )
func updateContracts(cmd *cobra.Command, _ []string) error { func updateContracts(cmd *cobra.Command, _ []string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper()) wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil { if err != nil {
return fmt.Errorf("initialization error: %w", err) return fmt.Errorf("initialization error: %w", err)
} }
if err := wCtx.deployNNS(updateMethodName); err != nil { if err := deployNNS(wCtx, updateMethodName); err != nil {
return err return err
} }
return wCtx.updateContracts() return updateContractsInternal(wCtx)
} }

View file

@ -7,8 +7,11 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"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/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
nns2 "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
@ -144,3 +147,43 @@ func NNSResolveHash(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (
func DomainOf(contract string) string { func DomainOf(contract string) string {
return contract + ".frostfs" return contract + ".frostfs"
} }
func NNSResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) {
res, err := NNSResolve(inv, nnsHash, domain)
if err != nil {
return nil, err
}
if _, ok := res.Value().(stackitem.Null); ok {
return nil, errors.New("NNS record is missing")
}
arr, ok := res.Value().([]stackitem.Item)
if !ok {
return nil, errors.New("API of the NNS contract method `resolve` has changed")
}
for i := range arr {
var bs []byte
bs, err = arr[i].TryBytes()
if err != nil {
continue
}
return keys.NewPublicKeyFromString(string(bs))
}
return nil, errors.New("no valid keys are found")
}
func NNSIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) {
switch c.(type) {
case *rpcclient.Client:
inv := invoker.New(c, nil)
reader := nns2.NewReader(inv, nnsHash)
return reader.IsAvailable(name)
default:
b, err := unwrap.Bool(InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil))
if err != nil {
return false, fmt.Errorf("`isAvailable`: invalid response: %w", err)
}
return b, nil
}
}

View file

@ -0,0 +1,34 @@
package util
import (
"encoding/json"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util"
)
func (cs *ContractState) Parse() error {
nf, err := nef.FileFromBytes(cs.RawNEF)
if err != nil {
return fmt.Errorf("can't parse NEF file: %w", err)
}
m := new(manifest.Manifest)
if err := json.Unmarshal(cs.RawManifest, m); err != nil {
return fmt.Errorf("can't parse manifest file: %w", err)
}
cs.NEF = &nf
cs.Manifest = m
return nil
}
type ContractState struct {
NEF *nef.File
RawNEF []byte
Manifest *manifest.Manifest
RawManifest []byte
Hash util.Uint160
}