From cda3a3d83440ffab9ec415376cc085bea802c027 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 31 Jan 2024 17:26:26 +0300 Subject: [PATCH] [#932] adm: Refactor command `morph` Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/ape.go | 21 +-- .../internal/modules/morph/ape_util.go | 9 +- .../internal/modules/morph/balance.go | 9 +- .../internal/modules/morph/config.go | 3 +- .../internal/modules/morph/container.go | 5 +- .../internal/modules/morph/deploy.go | 5 +- .../internal/modules/morph/dump_hashes.go | 7 +- .../internal/modules/morph/frostfsid.go | 47 +++--- .../internal/modules/morph/generate.go | 8 +- .../internal/modules/morph/generate_test.go | 3 +- .../internal/modules/morph/initialize.go | 144 +++--------------- .../modules/morph/initialize_deploy.go | 3 +- .../internal/modules/morph/initialize_nns.go | 5 +- .../modules/morph/initialize_register.go | 5 +- .../modules/morph/initialize_roles.go | 3 +- .../internal/modules/morph/initialize_test.go | 19 +-- .../modules/morph/initialize_transfer.go | 11 +- .../modules/morph/netmap_candidates.go | 3 +- .../internal/modules/morph/notary.go | 5 +- .../internal/modules/morph/policy.go | 3 +- .../internal/modules/morph/root.go | 88 ++++++----- .../internal/modules/morph/util/const.go | 15 ++ .../internal/modules/morph/util/initialize.go | 90 +++++++++++ .../modules/morph/{ => util}/local_client.go | 46 +++--- .../modules/morph/{ => util}/n3client.go | 45 ++++-- .../internal/modules/morph/{ => util}/util.go | 12 +- 26 files changed, 324 insertions(+), 290 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/const.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/initialize.go rename cmd/frostfs-adm/internal/modules/morph/{ => util}/local_client.go (89%) rename cmd/frostfs-adm/internal/modules/morph/{ => util}/n3client.go (72%) rename cmd/frostfs-adm/internal/modules/morph/{ => util}/util.go (86%) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape.go index 9f1d75ad..5ff6e7ab 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -41,7 +42,7 @@ var ( Use: "add-rule-chain", Short: "Add rule chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: addRuleChain, @@ -51,7 +52,7 @@ var ( Use: "rm-rule-chain", Short: "Remove rule chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: removeRuleChain, @@ -61,7 +62,7 @@ var ( Use: "list-rule-chains", Short: "List rule chains", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: listRuleChains, @@ -71,7 +72,7 @@ var ( Use: "set-admin", Short: "Set admin", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: setAdmin, @@ -81,7 +82,7 @@ var ( Use: "get-admin", Short: "Get admin", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: getAdmin, @@ -91,7 +92,7 @@ var ( func initAddRuleChainCmd() { apeCmd.AddCommand(addRuleChainCmd) - addRuleChainCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + addRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) addRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) @@ -110,7 +111,7 @@ func initAddRuleChainCmd() { func initRemoveRuleChainCmd() { apeCmd.AddCommand(removeRuleChainCmd) - removeRuleChainCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + removeRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) removeRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) @@ -124,7 +125,7 @@ func initRemoveRuleChainCmd() { func initListRuleChainsCmd() { apeCmd.AddCommand(listRuleChainsCmd) - listRuleChainsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + listRuleChainsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) listRuleChainsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) @@ -136,7 +137,7 @@ func initListRuleChainsCmd() { func initSetAdminCmd() { apeCmd.AddCommand(setAdminCmd) - setAdminCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + setAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) setAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) setAdminCmd.Flags().String(addrAdminFlag, "", addrAdminDesc) _ = setAdminCmd.MarkFlagRequired(addrAdminFlag) @@ -145,7 +146,7 @@ func initSetAdminCmd() { func initGetAdminCmd() { apeCmd.AddCommand(getAdminCmd) - getAdminCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + getAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) getAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go index f64a7e10..30668532 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -6,6 +6,7 @@ import ( "os" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -77,17 +78,17 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *actor.Actor) { v := viper.GetViper() - c, err := getN3Client(v) + c, err := morphUtil.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) - wallets, err := getAlphabetWallets(v, walletDir) + wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) - committeeAcc, err := getWalletAccount(wallets[0], committeeAccountName) + committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], committeeAccountName) commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) - ac, err := newActor(c, committeeAcc) + ac, err := morphUtil.NewActor(c, committeeAcc) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) inv := &ac.Invoker diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance.go index 0fee45a8..b4259e11 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance.go @@ -7,6 +7,7 @@ import ( "math/big" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -49,7 +50,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { nmHash util.Uint160 ) - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return err } @@ -150,7 +151,7 @@ func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash return nil } -func printAlphabetContractBalances(cmd *cobra.Command, c Client, inv *invoker.Invoker, count int, nnsHash util.Uint160) error { +func printAlphabetContractBalances(cmd *cobra.Command, c morphUtil.Client, inv *invoker.Invoker, count int, nnsHash util.Uint160) error { alphaList := make([]accBalancePair, count) w := io.NewBufBinWriter() @@ -184,7 +185,7 @@ func printAlphabetContractBalances(cmd *cobra.Command, c Client, inv *invoker.In return nil } -func fetchIRNodes(c Client, desigHash util.Uint160) ([]accBalancePair, error) { +func fetchIRNodes(c morphUtil.Client, desigHash util.Uint160) ([]accBalancePair, error) { inv := invoker.New(c, nil) height, err := c.GetBlockCount() @@ -192,7 +193,7 @@ func fetchIRNodes(c Client, desigHash util.Uint160) ([]accBalancePair, error) { return nil, fmt.Errorf("can't get block height: %w", err) } - arr, err := getDesignatedByRole(inv, desigHash, noderoles.NeoFSAlphabet, height) + arr, err := morphUtil.GetDesignatedByRole(inv, desigHash, noderoles.NeoFSAlphabet, height) if err != nil { return nil, errors.New("can't fetch list of IR nodes from the netmap contract") } diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index db7d2ab8..d9ddcb8a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -10,6 +10,7 @@ import ( "strings" "text/tabwriter" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -24,7 +25,7 @@ import ( const forceConfigSet = "force" func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := util.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index e7a7f546..b9db4c4e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -7,6 +7,7 @@ import ( "os" "sort" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" @@ -73,7 +74,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -163,7 +164,7 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo } func listContainers(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index 1facd6d1..db54a8db 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -7,6 +7,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -38,7 +39,7 @@ Contract's manifest file name must be 'config.json'. NNS name is taken by stripping '_contract.nef' from the NEF file (similar to frostfs contracts).`, PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: deployContractCmd, } @@ -49,7 +50,7 @@ func init() { ff.String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) _ = deployCmd.MarkFlagFilename(alphabetWalletsFlag) - ff.StringP(endpointFlag, "r", "", endpointFlagDesc) + ff.StringP(util.EndpointFlag, "r", "", util.EndpointFlagDesc) ff.String(contractPathFlag, "", "Path to the contract directory") _ = deployCmd.MarkFlagFilename(contractPathFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 14a492c5..60e9de9c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -8,6 +8,7 @@ import ( "text/tabwriter" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -33,7 +34,7 @@ type contractDumpInfo struct { } func dumpContractHashes(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -110,7 +111,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return nil } -func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c Client) error { +func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c morphUtil.Client) error { const nnsMaxTokens = 100 inv := invoker.New(c, nil) @@ -224,7 +225,7 @@ func printContractInfo(cmd *cobra.Command, infos []contractDumpInfo) { cmd.Print(buf.String()) } -func fillContractVersion(cmd *cobra.Command, c Client, infos []contractDumpInfo) { +func fillContractVersion(cmd *cobra.Command, c morphUtil.Client, infos []contractDumpInfo) { bw := io.NewBufBinWriter() sub := io.NewBufBinWriter() for i := range infos { diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 50cd4774..8150dcb5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -6,6 +6,7 @@ import ( "sort" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -41,7 +42,7 @@ var ( Short: "Create new namespace in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateNamespace, } @@ -51,7 +52,7 @@ var ( Short: "List all namespaces in frostfsid", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListNamespaces, } @@ -61,7 +62,7 @@ var ( Short: "Create subject in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateSubject, } @@ -71,7 +72,7 @@ var ( Short: "Delete subject from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidDeleteSubject, } @@ -81,7 +82,7 @@ var ( Short: "List subjects in namespace", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListSubjects, } @@ -91,7 +92,7 @@ var ( Short: "Create group in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateGroup, } @@ -101,7 +102,7 @@ var ( Short: "Delete group from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidDeleteGroup, } @@ -111,7 +112,7 @@ var ( Short: "List groups in namespace", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListGroups, } @@ -121,7 +122,7 @@ var ( Short: "Add subject to group", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidAddSubjectToGroup, } @@ -131,7 +132,7 @@ var ( Short: "Remove subject from group", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidRemoveSubjectFromGroup, } @@ -141,7 +142,7 @@ var ( Short: "List subjects in group", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListGroupSubjects, } @@ -149,20 +150,20 @@ var ( func initFrostfsIDCreateNamespaceCmd() { frostfsidCmd.AddCommand(frostfsidCreateNamespaceCmd) - frostfsidCreateNamespaceCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateNamespaceCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") frostfsidCreateNamespaceCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListNamespacesCmd() { frostfsidCmd.AddCommand(frostfsidListNamespacesCmd) - frostfsidListNamespacesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListNamespacesCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListNamespacesCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDCreateSubjectCmd() { frostfsidCmd.AddCommand(frostfsidCreateSubjectCmd) - frostfsidCreateSubjectCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateSubjectCmd.Flags().String(namespaceFlag, "", "Namespace where create subject") frostfsidCreateSubjectCmd.Flags().String(subjectNameFlag, "", "Subject name, must be unique in namespace") frostfsidCreateSubjectCmd.Flags().String(subjectKeyFlag, "", "Subject hex-encoded public key") @@ -171,14 +172,14 @@ func initFrostfsIDCreateSubjectCmd() { func initFrostfsIDDeleteSubjectCmd() { frostfsidCmd.AddCommand(frostfsidDeleteSubjectCmd) - frostfsidDeleteSubjectCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidDeleteSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteSubjectCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidDeleteSubjectCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListSubjectsCmd() { frostfsidCmd.AddCommand(frostfsidListSubjectsCmd) - frostfsidListSubjectsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") frostfsidListSubjectsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -186,7 +187,7 @@ func initFrostfsIDListSubjectsCmd() { func initFrostfsIDCreateGroupCmd() { frostfsidCmd.AddCommand(frostfsidCreateGroupCmd) - frostfsidCreateGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") frostfsidCreateGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -194,7 +195,7 @@ func initFrostfsIDCreateGroupCmd() { func initFrostfsIDDeleteGroupCmd() { frostfsidCmd.AddCommand(frostfsidDeleteGroupCmd) - frostfsidDeleteGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidDeleteGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteGroupCmd.Flags().String(namespaceFlag, "", "Namespace to delete group") frostfsidDeleteGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidDeleteGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -202,14 +203,14 @@ func initFrostfsIDDeleteGroupCmd() { func initFrostfsIDListGroupsCmd() { frostfsidCmd.AddCommand(frostfsidListGroupsCmd) - frostfsidListGroupsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListGroupsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") frostfsidListGroupsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDAddSubjectToGroupCmd() { frostfsidCmd.AddCommand(frostfsidAddSubjectToGroupCmd) - frostfsidAddSubjectToGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidAddSubjectToGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidAddSubjectToGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidAddSubjectToGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidAddSubjectToGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -217,7 +218,7 @@ func initFrostfsIDAddSubjectToGroupCmd() { func initFrostfsIDRemoveSubjectFromGroupCmd() { frostfsidCmd.AddCommand(frostfsidRemoveSubjectFromGroupCmd) - frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidRemoveSubjectFromGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidRemoveSubjectFromGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidRemoveSubjectFromGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -225,7 +226,7 @@ func initFrostfsIDRemoveSubjectFromGroupCmd() { func initFrostfsIDListGroupSubjectsCmd() { frostfsidCmd.AddCommand(frostfsidListGroupSubjectsCmd) - frostfsidListGroupSubjectsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListGroupSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") @@ -467,5 +468,5 @@ func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { } f.wCtx.Command.Println("Waiting for transactions to persist...") - return f.roCli.Wait(f.wCtx.SentTxs[0].hash, f.wCtx.SentTxs[0].vub, nil) + return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index b8e00696..2d82c123 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -7,6 +7,7 @@ import ( "path/filepath" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -27,7 +28,6 @@ import ( const ( singleAccountName = "single" committeeAccountName = "committee" - consensusAccountName = "consensus" ) func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { @@ -39,8 +39,8 @@ func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { if size == 0 { return errors.New("size must be > 0") } - if size > maxAlphabetNodes { - return ErrTooManyAlphabetNodes + if size > morphUtil.MaxAlphabetNodes { + return morphUtil.ErrTooManyAlphabetNodes } v := viper.GetViper() @@ -109,7 +109,7 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er if err := addMultisigAccount(wallets[i], majCount, committeeAccountName, passwords[i], ps); err != nil { return fmt.Errorf("can't create committee account: %w", err) } - if err := addMultisigAccount(wallets[i], bftCount, consensusAccountName, passwords[i], ps); err != nil { + if err := addMultisigAccount(wallets[i], bftCount, morphUtil.ConsensusAccountName, passwords[i], ps); err != nil { return fmt.Errorf("can't create consentus account: %w", err) } if err := wallets[i].SavePretty(); err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate_test.go index 7f0a2708..2386b94e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate_test.go @@ -10,6 +10,7 @@ import ( "sync" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -87,7 +88,7 @@ func TestGenerateAlphabet(t *testing.T) { err := a.Decrypt(strconv.FormatUint(i, 10), keys.NEP2ScryptParams()) require.NoError(t, err, "can't decrypt account") switch a.Label { - case consensusAccountName: + case util.ConsensusAccountName: require.Equal(t, smartcontract.GetDefaultHonestNodeCount(size), len(a.Contract.Parameters)) case committeeAccountName: require.Equal(t, smartcontract.GetMajorityHonestNodeCount(size), len(a.Contract.Parameters)) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 04e8620c..2dff2f06 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -4,10 +4,9 @@ import ( "errors" "fmt" "os" - "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -15,28 +14,19 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" "github.com/spf13/viper" ) -const ( - // maxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size - // of the invocation script. - // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 - maxAlphabetNodes = 22 -) - type cache struct { nnsCs *state.Contract groupKey *keys.PublicKey } type initializeContext struct { - clientContext + morphUtil.ClientContext cache // CommitteeAcc is used for retrieving the committee address and the verification script. CommitteeAcc *wallet.Account @@ -53,8 +43,6 @@ type initializeContext struct { ContractURL string } -var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", maxAlphabetNodes) - func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { initCtx, err := newInitializeContext(cmd, viper.GetViper()) if err != nil { @@ -105,8 +93,8 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { } func (c *initializeContext) close() { - if local, ok := c.Client.(*localClient); ok { - err := local.dump() + if local, ok := c.Client.(*morphUtil.LocalClient); ok { + err := local.Dump() if err != nil { c.Command.PrintErrf("Can't write dump: %v\n", err) os.Exit(1) @@ -116,7 +104,7 @@ func (c *initializeContext) close() { func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) { walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) - wallets, err := getAlphabetWallets(v, walletDir) + wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) if err != nil { return nil, err } @@ -134,12 +122,12 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex return nil, err } - committeeAcc, err := getWalletAccount(wallets[0], committeeAccountName) + committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], committeeAccountName) if err != nil { return nil, fmt.Errorf("can't find committee account: %w", err) } - consensusAcc, err := getWalletAccount(wallets[0], consensusAccountName) + consensusAcc, err := morphUtil.GetWalletAccount(wallets[0], morphUtil.ConsensusAccountName) if err != nil { return nil, fmt.Errorf("can't find consensus account: %w", err) } @@ -167,13 +155,13 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex return nil, err } - cliCtx, err := defaultClientContext(c, committeeAcc) + cliCtx, err := morphUtil.DefaultClientContext(c, committeeAcc) if err != nil { return nil, fmt.Errorf("client context: %w", err) } initCtx := &initializeContext{ - clientContext: *cliCtx, + ClientContext: *cliCtx, ConsensusAcc: consensusAcc, CommitteeAcc: committeeAcc, ContractWallet: w, @@ -210,16 +198,16 @@ func validateInit(cmd *cobra.Command) error { return nil } -func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) (Client, error) { - var c Client +func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) (morphUtil.Client, error) { + var c morphUtil.Client var err error if ldf := cmd.Flags().Lookup(localDumpFlag); ldf != nil && ldf.Changed { - if cmd.Flags().Changed(endpointFlag) { - return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", endpointFlag, localDumpFlag) + if cmd.Flags().Changed(morphUtil.EndpointFlag) { + return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", morphUtil.EndpointFlag, localDumpFlag) } - c, err = newLocalClient(cmd, v, wallets, ldf.Value.String()) + c, err = morphUtil.NewLocalClient(cmd, v, wallets, ldf.Value.String()) } else { - c, err = getN3Client(v) + c, err = morphUtil.GetN3Client(v) } if err != nil { return nil, fmt.Errorf("can't create N3 client: %w", err) @@ -249,7 +237,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { accounts := make([]*wallet.Account, len(wallets)) for i, w := range wallets { - acc, err := getWalletAccount(w, singleAccountName) + acc, err := morphUtil.GetWalletAccount(w, singleAccountName) if err != nil { return nil, fmt.Errorf("wallet %s is invalid (no single account): %w", w.Path(), err) } @@ -259,7 +247,7 @@ func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, 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) { @@ -310,89 +298,6 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa return signer } -func (c *clientContext) awaitTx(cmd *cobra.Command) error { - if len(c.SentTxs) == 0 { - return nil - } - - if local, ok := c.Client.(*localClient); ok { - if err := local.putTransactions(); err != nil { - return fmt.Errorf("can't persist transactions: %w", err) - } - } - - err := awaitTx(cmd, c.Client, c.SentTxs) - c.SentTxs = c.SentTxs[:0] - - return err -} - -func awaitTx(cmd *cobra.Command, c Client, txs []hashVUBPair) error { - cmd.Println("Waiting for transactions to persist...") - - at := trigger.Application - - var retErr error - -loop: - for i := range txs { - var it int - var pollInterval time.Duration - var pollIntervalChanged bool - for { - // We must fetch current height before application log, to avoid race condition. - currBlock, err := c.GetBlockCount() - if err != nil { - return fmt.Errorf("can't fetch current block height: %w", err) - } - res, err := c.GetApplicationLog(txs[i].hash, &at) - if err == nil { - if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vmstate.Halt { - retErr = fmt.Errorf("tx %d persisted in %s state: %s", - i, res.Executions[0].VMState, res.Executions[0].FaultException) - } - continue loop - } - if txs[i].vub < currBlock { - return fmt.Errorf("tx was not persisted: vub=%d, height=%d", txs[i].vub, currBlock) - } - - pollInterval, pollIntervalChanged = nextPollInterval(it, pollInterval) - if pollIntervalChanged && viper.GetBool(commonflags.Verbose) { - cmd.Printf("Pool interval to check transaction persistence changed: %s\n", pollInterval.String()) - } - - timer := time.NewTimer(pollInterval) - select { - case <-cmd.Context().Done(): - return cmd.Context().Err() - case <-timer.C: - } - - it++ - } - } - - return retErr -} - -func nextPollInterval(it int, previous time.Duration) (time.Duration, bool) { - const minPollInterval = 1 * time.Second - const maxPollInterval = 16 * time.Second - const changeAfter = 5 - if it == 0 { - return minPollInterval, true - } - if it%changeAfter != 0 { - return previous, false - } - nextInterval := previous * 2 - if nextInterval > maxPollInterval { - return maxPollInterval, previous != maxPollInterval - } - return nextInterval, true -} - // 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 // working with native contracts). @@ -445,24 +350,15 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen return err } if withConsensus { - if err := c.multiSign(tx, consensusAccountName); err != nil { + if err := c.multiSign(tx, morphUtil.ConsensusAccountName); err != nil { return err } } - return c.sendTx(tx, c.Command, false) + return c.SendTx(tx, c.Command, false) } -func getWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) { - for i := range w.Accounts { - if w.Accounts[i].Label == typ { - return w.Accounts[i], nil - } - } - return nil, fmt.Errorf("account for '%s' not found", typ) -} - -func checkNotaryEnabled(c Client) error { +func checkNotaryEnabled(c morphUtil.Client) error { ns, err := c.GetNativeContracts() if err != nil { return fmt.Errorf("can't get native contract hashes: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index f715f0e0..9f0e929a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/common" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" @@ -332,7 +333,7 @@ func (c *initializeContext) deployContracts() error { return fmt.Errorf("can't deploy alphabet #%d contract: %w", i, err) } - c.SentTxs = append(c.SentTxs, hashVUBPair{hash: txHash, vub: vub}) + c.SentTxs = append(c.SentTxs, morphUtil.HashVUBPair{Hash: txHash, Vub: vub}) } for _, ctrName := range contractList { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 1bf4c4be..7364ba0e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -8,6 +8,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -288,14 +289,14 @@ func parseNNSResolveResult(res stackitem.Item) (util.Uint160, error) { return util.Uint160{}, errors.New("no valid hashes are found") } -func nnsIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) { +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(invokeFunction(c, nnsHash, "isAvailable", []any{name}, nil)) + b, err := unwrap.Bool(morphUtil.InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil)) if err != nil { return false, fmt.Errorf("`isAvailable`: invalid response: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index 92145a79..e8e73ae7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -78,7 +79,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 { @@ -156,7 +157,7 @@ func (c *initializeContext) getCandidateRegisterPrice() (int64, error) { return reader.GetRegisterPrice() default: neoHash := neo.Hash - res, err := invokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil) + res, err := morphUtil.InvokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil) if err != nil { return 0, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go index 46466602..aed35e23 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go @@ -1,6 +1,7 @@ package morph import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt" @@ -40,6 +41,6 @@ func (c *initializeContext) setRolesFinished() (bool, error) { return false, err } - pubs, err := getDesignatedByRole(c.ReadOnlyInvoker, rolemgmt.Hash, noderoles.NeoFSAlphabet, height) + pubs, err := util.GetDesignatedByRole(c.ReadOnlyInvoker, rolemgmt.Hash, noderoles.NeoFSAlphabet, height) return len(pubs) == len(c.Wallets), err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index 613c6389..cf71a01d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -42,10 +43,10 @@ func TestInitialize(t *testing.T) { testInitialize(t, 16) }) t.Run("max nodes", func(t *testing.T) { - testInitialize(t, maxAlphabetNodes) + testInitialize(t, util.MaxAlphabetNodes) }) t.Run("too many nodes", func(t *testing.T) { - require.ErrorIs(t, generateTestData(t, t.TempDir(), maxAlphabetNodes+1), ErrTooManyAlphabetNodes) + require.ErrorIs(t, generateTestData(t, t.TempDir(), util.MaxAlphabetNodes+1), util.ErrTooManyAlphabetNodes) }) } @@ -54,7 +55,7 @@ func testInitialize(t *testing.T, committeeSize int) { v := viper.GetViper() require.NoError(t, generateTestData(t, testdataDir, committeeSize)) - v.Set(protoConfigPath, filepath.Join(testdataDir, protoFileName)) + v.Set(util.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. require.NoError(t, initCmd.Flags().Set(contractsInitFlag, contractsPath)) @@ -150,33 +151,33 @@ func TestNextPollInterval(t *testing.T) { var pollInterval time.Duration var iteration int - pollInterval, hasChanged := nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged := util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, time.Second, pollInterval) iteration = 4 - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.False(t, hasChanged) require.Equal(t, time.Second, pollInterval) iteration = 5 - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, 2*time.Second, pollInterval) iteration = 10 - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, 4*time.Second, pollInterval) iteration = 20 pollInterval = 32 * time.Second - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) // from 32s to 16s require.Equal(t, 16*time.Second, pollInterval) pollInterval = 16 * time.Second - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.False(t, hasChanged) require.Equal(t, 16*time.Second, pollInterval) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index 12b94a2e..e9945cee 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" @@ -67,7 +68,7 @@ func (c *initializeContext) transferFunds() error { return fmt.Errorf("can't create transfer transaction: %w", err) } - if err := c.multiSignAndSend(tx, consensusAccountName); err != nil { + if err := c.multiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil { return fmt.Errorf("can't send transfer transaction: %w", err) } @@ -87,7 +88,7 @@ func (c *initializeContext) multiSignAndSend(tx *transaction.Transaction, accTyp 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 { @@ -102,11 +103,11 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin // Use parameter context to avoid dealing with signature order. pc := scContext.NewParameterContext("", network, tx) h := c.CommitteeAcc.Contract.ScriptHash() - if accType == consensusAccountName { + if accType == morphUtil.ConsensusAccountName { h = c.ConsensusAcc.Contract.ScriptHash() } for _, w := range c.Wallets { - acc, err := getWalletAccount(w, accType) + acc, err := morphUtil.GetWalletAccount(w, accType) if err != nil { return fmt.Errorf("can't find %s wallet account: %w", accType, err) } @@ -174,7 +175,7 @@ type transferTarget struct { Data any } -func createNEP17MultiTransferTx(c Client, acc *wallet.Account, recipients []transferTarget) (*transaction.Transaction, error) { +func createNEP17MultiTransferTx(c morphUtil.Client, acc *wallet.Account, recipients []transferTarget) (*transaction.Transaction, error) { from := acc.Contract.ScriptHash() w := io.NewBufBinWriter() diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go index bb1de09c..7d31d181 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go @@ -2,6 +2,7 @@ package morph import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -11,7 +12,7 @@ import ( ) func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { - c, err := getN3Client(viper.GetViper()) + c, err := util.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary.go index 2459f127..3e7afdbf 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary.go @@ -5,6 +5,7 @@ import ( "math/big" "strconv" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -79,7 +80,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error { } func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error { - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return err } @@ -116,7 +117,7 @@ func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, return fmt.Errorf("could not send tx: %w", err) } - return awaitTx(cmd, c, []hashVUBPair{{hash: txHash, vub: vub}}) + return morphUtil.AwaitTx(cmd, c, []morphUtil.HashVUBPair{{Hash: txHash, Vub: vub}}) } func openWallet(cmd *cobra.Command) (*wallet.Wallet, error) { diff --git a/cmd/frostfs-adm/internal/modules/morph/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy.go index 005a0271..ba73d132 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy.go @@ -7,6 +7,7 @@ import ( "strings" "text/tabwriter" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -58,7 +59,7 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error { } func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := util.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client:", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 6cc2d5a9..dad8c4ee 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -1,6 +1,7 @@ package morph import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -9,9 +10,6 @@ const ( alphabetWalletsFlag = "alphabet-wallets" alphabetWalletsFlagDesc = "Path to alphabet wallets dir" alphabetSizeFlag = "size" - endpointFlag = "rpc-endpoint" - endpointFlagDesc = "N3 RPC node endpoint" - endpointFlagShort = "r" storageWalletFlag = "storage-wallet" storageWalletLabelFlag = "label" storageGasCLIFlag = "initial-gas" @@ -42,8 +40,8 @@ const ( walletAccountFlag = "account" notaryDepositTillFlag = "till" localDumpFlag = "local-dump" - protoConfigPath = "protocol" - walletAddressFlag = "wallet-address" + + walletAddressFlag = "wallet-address" ) var ( @@ -68,7 +66,7 @@ var ( Short: "Initialize side chain network with smart-contracts and network settings", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(epochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) _ = viper.BindPFlag(maxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) _ = viper.BindPFlag(homomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) @@ -76,7 +74,7 @@ var ( _ = viper.BindPFlag(containerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) _ = viper.BindPFlag(containerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) _ = viper.BindPFlag(withdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) - _ = viper.BindPFlag(protoConfigPath, cmd.Flags().Lookup(protoConfigPath)) + _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) }, RunE: initializeSideChainCmd, } @@ -86,7 +84,7 @@ var ( Short: "Generate storage node wallet for the morph network", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(storageGasConfigFlag, cmd.Flags().Lookup(storageGasCLIFlag)) }, RunE: generateStorageCreds, @@ -97,7 +95,7 @@ var ( Short: "Refill GAS of storage node's wallet in the morph network", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(refillGasAmountFlag, cmd.Flags().Lookup(refillGasAmountFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { @@ -110,7 +108,7 @@ var ( Short: "Create new FrostFS epoch event in the side chain", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: forceNewEpochCmd, } @@ -121,7 +119,7 @@ var ( Long: `Move nodes to the Offline state in the candidates list and tick an epoch to update the netmap`, PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: removeNodesCmd, } @@ -132,7 +130,7 @@ var ( Short: "Add/update global config value in the FrostFS network", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Args: cobra.MinimumNArgs(1), RunE: setConfigCmd, @@ -144,7 +142,7 @@ var ( Short: "Set global policy values", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: setPolicyCmd, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -156,7 +154,7 @@ var ( Use: "dump-policy", Short: "Dump FrostFS policy", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpPolicyCmd, } @@ -165,7 +163,7 @@ var ( Use: "dump-hashes", Short: "Dump deployed contract hashes", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpContractHashes, } @@ -174,7 +172,7 @@ var ( Use: "dump-config", Short: "Dump FrostFS network config", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpNetworkConfig, } @@ -183,7 +181,7 @@ var ( Use: "dump-balances", Short: "Dump GAS balances", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpBalances, } @@ -193,7 +191,7 @@ var ( Short: "Update FrostFS contracts", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: updateContracts, } @@ -202,7 +200,7 @@ var ( Use: "dump-containers", Short: "Dump FrostFS containers to file", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpContainers, } @@ -212,7 +210,7 @@ var ( Short: "Restore FrostFS containers from file", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: restoreContainers, } @@ -221,7 +219,7 @@ var ( Use: "list-containers", Short: "List FrostFS containers", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: listContainers, } @@ -230,7 +228,7 @@ var ( Use: "deposit-notary", Short: "Deposit GAS for notary service", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: depositNotary, } @@ -239,7 +237,7 @@ var ( Use: "netmap-candidates", Short: "List netmap candidates nodes", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: listNetmapCandidatesNodes, @@ -250,7 +248,7 @@ var ( Short: "Adds account to proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Run: addProxyAccount, } @@ -260,7 +258,7 @@ var ( Short: "Remove from proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Run: removeProxyAccount, } @@ -313,24 +311,24 @@ func init() { func initProxyAddAccount() { RootCmd.AddCommand(proxyAddAccountCmd) - proxyAddAccountCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + proxyAddAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) proxyAddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") } func initProxyRemoveAccount() { RootCmd.AddCommand(proxyRemoveAccountCmd) - proxyRemoveAccountCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + proxyRemoveAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) proxyRemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") } func initNetmapCandidatesCmd() { RootCmd.AddCommand(netmapCandidatesCmd) - netmapCandidatesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + netmapCandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } func initDepositoryNotaryCmd() { RootCmd.AddCommand(depositNotaryCmd) - depositNotaryCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + depositNotaryCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) depositNotaryCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") depositNotaryCmd.Flags().String(walletAccountFlag, "", "Wallet account address") depositNotaryCmd.Flags().String(refillGasAmountFlag, "", "Amount of GAS to deposit") @@ -340,7 +338,7 @@ func initDepositoryNotaryCmd() { func initRefillGasCmd() { RootCmd.AddCommand(refillGasCmd) refillGasCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - refillGasCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + refillGasCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) refillGasCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") refillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") refillGasCmd.Flags().String(refillGasAmountFlag, "", "Additional amount of GAS to transfer") @@ -349,21 +347,21 @@ func initRefillGasCmd() { func initListContainersCmd() { RootCmd.AddCommand(listContainersCmd) - listContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + listContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) listContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") } func initRestoreContainersCmd() { RootCmd.AddCommand(restoreContainersCmd) restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - restoreContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + restoreContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) restoreContainersCmd.Flags().String(containerDumpFlag, "", "File to restore containers from") restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore") } func initDumpContainersCmd() { RootCmd.AddCommand(dumpContainersCmd) - dumpContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) dumpContainersCmd.Flags().String(containerDumpFlag, "", "File where to save dumped containers") dumpContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") dumpContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to dump") @@ -372,7 +370,7 @@ func initDumpContainersCmd() { func initUpdateContractsCmd() { RootCmd.AddCommand(updateContractsCmd) updateContractsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - updateContractsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + updateContractsCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) updateContractsCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) updateContractsCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) updateContractsCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) @@ -380,7 +378,7 @@ func initUpdateContractsCmd() { func initDumpBalancesCmd() { RootCmd.AddCommand(dumpBalancesCmd) - dumpBalancesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpBalancesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) dumpBalancesCmd.Flags().BoolP(dumpBalancesStorageFlag, "s", false, "Dump balances of storage nodes from the current netmap") dumpBalancesCmd.Flags().BoolP(dumpBalancesAlphabetFlag, "a", false, "Dump balances of alphabet contracts") dumpBalancesCmd.Flags().BoolP(dumpBalancesProxyFlag, "p", false, "Dump balances of the proxy contract") @@ -390,52 +388,52 @@ func initDumpBalancesCmd() { func initSetConfigCmd() { RootCmd.AddCommand(setConfig) setConfig.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - setConfig.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + setConfig.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") setConfig.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initDumpNetworkConfigCmd() { RootCmd.AddCommand(dumpNetworkConfigCmd) - dumpNetworkConfigCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpNetworkConfigCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } func initDumpContractHashesCmd() { RootCmd.AddCommand(dumpContractHashesCmd) - dumpContractHashesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpContractHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) dumpContractHashesCmd.Flags().String(customZoneFlag, "", "Custom zone to search.") } func initSetPolicyCmd() { RootCmd.AddCommand(setPolicy) setPolicy.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - setPolicy.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + setPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) setPolicy.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initDumpPolicyCmd() { RootCmd.AddCommand(dumpPolicy) - dumpPolicy.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) removeNodes.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - removeNodes.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + removeNodes.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) removeNodes.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initForceNewEpochCmd() { RootCmd.AddCommand(forceNewEpoch) forceNewEpoch.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - forceNewEpoch.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + forceNewEpoch.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) forceNewEpoch.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) generateStorageCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - generateStorageCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + generateStorageCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) generateStorageCmd.Flags().String(storageWalletFlag, "", "Path to new storage node wallet") generateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") generateStorageCmd.Flags().StringP(storageWalletLabelFlag, "l", "", "Wallet label") @@ -444,7 +442,7 @@ func initGenerateStorageCmd() { func initInitCmd() { RootCmd.AddCommand(initCmd) initCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - initCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + initCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) initCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) initCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") @@ -453,7 +451,7 @@ func initInitCmd() { // Defaults are taken from neo-preodolenie. initCmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") - initCmd.Flags().String(protoConfigPath, "", "Path to the consensus node configuration") + initCmd.Flags().String(util.ProtoConfigPath, "", "Path to the consensus node configuration") initCmd.Flags().String(localDumpFlag, "", "Path to the blocks dump file") initCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go new file mode 100644 index 00000000..7278d835 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -0,0 +1,15 @@ +package util + +const ( + ConsensusAccountName = "consensus" + ProtoConfigPath = "protocol" + + // MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size + // of the invocation script. + // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 + MaxAlphabetNodes = 22 + + EndpointFlag = "rpc-endpoint" + EndpointFlagDesc = "N3 RPC node endpoint" + EndpointFlagShort = "r" +) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go new file mode 100644 index 00000000..d15d99b9 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go @@ -0,0 +1,90 @@ +package util + +import ( + "fmt" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", MaxAlphabetNodes) + +func AwaitTx(cmd *cobra.Command, c Client, txs []HashVUBPair) error { + cmd.Println("Waiting for transactions to persist...") + + at := trigger.Application + + var retErr error + +loop: + for i := range txs { + var it int + var pollInterval time.Duration + var pollIntervalChanged bool + for { + // We must fetch current height before application log, to avoid race condition. + currBlock, err := c.GetBlockCount() + if err != nil { + return fmt.Errorf("can't fetch current block height: %w", err) + } + res, err := c.GetApplicationLog(txs[i].Hash, &at) + if err == nil { + if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vmstate.Halt { + retErr = fmt.Errorf("tx %d persisted in %s state: %s", + i, res.Executions[0].VMState, res.Executions[0].FaultException) + } + continue loop + } + if txs[i].Vub < currBlock { + return fmt.Errorf("tx was not persisted: Vub=%d, height=%d", txs[i].Vub, currBlock) + } + + pollInterval, pollIntervalChanged = NextPollInterval(it, pollInterval) + if pollIntervalChanged && viper.GetBool(commonflags.Verbose) { + cmd.Printf("Pool interval to check transaction persistence changed: %s\n", pollInterval.String()) + } + + timer := time.NewTimer(pollInterval) + select { + case <-cmd.Context().Done(): + return cmd.Context().Err() + case <-timer.C: + } + + it++ + } + } + + return retErr +} + +func NextPollInterval(it int, previous time.Duration) (time.Duration, bool) { + const minPollInterval = 1 * time.Second + const maxPollInterval = 16 * time.Second + const changeAfter = 5 + if it == 0 { + return minPollInterval, true + } + if it%changeAfter != 0 { + return previous, false + } + nextInterval := previous * 2 + if nextInterval > maxPollInterval { + return maxPollInterval, previous != maxPollInterval + } + return nextInterval, true +} + +func GetWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) { + for i := range w.Accounts { + if w.Accounts[i].Label == typ { + return w.Accounts[i], nil + } + } + return nil, fmt.Errorf("account for '%s' not found", typ) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/util/local_client.go similarity index 89% rename from cmd/frostfs-adm/internal/modules/morph/local_client.go rename to cmd/frostfs-adm/internal/modules/morph/util/local_client.go index 1a723042..4b001ca8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/local_client.go @@ -1,4 +1,4 @@ -package morph +package util import ( "crypto/elliptic" @@ -38,7 +38,7 @@ import ( "go.uber.org/zap" ) -type localClient struct { +type LocalClient struct { bc *core.Blockchain transactions []*transaction.Transaction dumpPath string @@ -46,8 +46,8 @@ type localClient struct { maxGasInvoke int64 } -func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*localClient, error) { - cfg, err := config.LoadFile(v.GetString(protoConfigPath)) +func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) { + cfg, err := config.LoadFile(v.GetString(ProtoConfigPath)) if err != nil { return nil, err } @@ -60,7 +60,7 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ProtocolConfiguration.ValidatorsCount)) accounts := make([]*wallet.Account, len(wallets)) for i := range accounts { - accounts[i], err = getWalletAccount(wallets[i], consensusAccountName) + accounts[i], err = GetWalletAccount(wallets[i], ConsensusAccountName) if err != nil { return nil, err } @@ -102,7 +102,7 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet } } - return &localClient{ + return &LocalClient{ bc: bc, dumpPath: dumpPath, accounts: accounts[:m], @@ -110,15 +110,15 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet }, nil } -func (l *localClient) GetBlockCount() (uint32, error) { +func (l *LocalClient) GetBlockCount() (uint32, error) { return l.bc.BlockHeight(), nil } -func (l *localClient) GetNativeContracts() ([]state.NativeContract, error) { +func (l *LocalClient) GetNativeContracts() ([]state.NativeContract, error) { return l.bc.GetNatives(), nil } -func (l *localClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*result.ApplicationLog, error) { +func (l *LocalClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*result.ApplicationLog, error) { aer, err := l.bc.GetAppExecResults(h, *t) if err != nil { return nil, err @@ -128,13 +128,13 @@ func (l *localClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*resul return &a, nil } -func (l *localClient) GetCommittee() (keys.PublicKeys, error) { +func (l *LocalClient) GetCommittee() (keys.PublicKeys, error) { // not used by `morph init` command panic("unexpected call") } // InvokeFunction is implemented via `InvokeScript`. -func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) { +func (l *LocalClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) { var err error pp := make([]any, len(sPrm)) @@ -145,21 +145,21 @@ func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smart } } - return invokeFunction(l, h, method, pp, ss) + return InvokeFunction(l, h, method, pp, ss) } -func (l *localClient) TerminateSession(_ uuid.UUID) (bool, error) { +func (l *LocalClient) TerminateSession(_ uuid.UUID) (bool, error) { // not used by `morph init` command panic("unexpected call") } -func (l *localClient) TraverseIterator(_, _ uuid.UUID, _ int) ([]stackitem.Item, error) { +func (l *LocalClient) TraverseIterator(_, _ uuid.UUID, _ int) ([]stackitem.Item, error) { // not used by `morph init` command panic("unexpected call") } // GetVersion return default version. -func (l *localClient) GetVersion() (*result.Version, error) { +func (l *LocalClient) GetVersion() (*result.Version, error) { c := l.bc.GetConfig() return &result.Version{ Protocol: result.Protocol{ @@ -180,7 +180,7 @@ func (l *localClient) GetVersion() (*result.Version, error) { }, nil } -func (l *localClient) InvokeContractVerify(util.Uint160, []smartcontract.Parameter, []transaction.Signer, ...transaction.Witness) (*result.Invoke, error) { +func (l *LocalClient) InvokeContractVerify(util.Uint160, []smartcontract.Parameter, []transaction.Signer, ...transaction.Witness) (*result.Invoke, error) { // not used by `morph init` command panic("unexpected call") } @@ -188,7 +188,7 @@ func (l *localClient) InvokeContractVerify(util.Uint160, []smartcontract.Paramet // CalculateNetworkFee calculates network fee for the given transaction. // Copied from neo-go with minor corrections (no need to support non-notary mode): // https://github.com/nspcc-dev/neo-go/blob/v0.103.0/pkg/services/rpcsrv/server.go#L911 -func (l *localClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { +func (l *LocalClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { // Avoid setting hash for this tx: server code doesn't touch client transaction. data := tx.Bytes() tx, err := transaction.NewTransactionFromBytes(data) @@ -259,7 +259,7 @@ func (l *localClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, e return netFee, nil } -func (l *localClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { +func (l *LocalClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash()) if err != nil { return nil, err @@ -295,7 +295,7 @@ func (l *localClient) InvokeScript(script []byte, signers []transaction.Signer) }, nil } -func (l *localClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) { +func (l *LocalClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) { // We need to test that transaction was formed correctly to catch as many errors as we can. bs := tx.Bytes() _, err := transaction.NewTransactionFromBytes(bs) @@ -307,7 +307,7 @@ func (l *localClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint return tx.Hash(), nil } -func (l *localClient) putTransactions() error { +func (l *LocalClient) putTransactions() error { // 1. Prepare new block. lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash()) if err != nil { @@ -349,7 +349,7 @@ func (l *localClient) putTransactions() error { return l.bc.AddBlock(b) } -func invokeFunction(c Client, h util.Uint160, method string, parameters []any, signers []transaction.Signer) (*result.Invoke, error) { +func InvokeFunction(c Client, h util.Uint160, method string, parameters []any, signers []transaction.Signer) (*result.Invoke, error) { w := io.NewBufBinWriter() emit.Array(w.BinWriter, parameters...) emit.AppCallNoArgs(w.BinWriter, h, method, callflag.All) @@ -361,7 +361,7 @@ func invokeFunction(c Client, h util.Uint160, method string, parameters []any, s var errGetDesignatedByRoleResponse = errors.New("`getDesignatedByRole`: invalid response") -func getDesignatedByRole(inv *invoker.Invoker, h util.Uint160, role noderoles.Role, u uint32) (keys.PublicKeys, error) { +func GetDesignatedByRole(inv *invoker.Invoker, h util.Uint160, role noderoles.Role, u uint32) (keys.PublicKeys, error) { arr, err := unwrap.Array(inv.Call(h, "getDesignatedByRole", int64(role), int64(u))) if err != nil { return nil, errGetDesignatedByRoleResponse @@ -382,7 +382,7 @@ func getDesignatedByRole(inv *invoker.Invoker, h util.Uint160, role noderoles.Ro return pubs, nil } -func (l *localClient) dump() (err error) { +func (l *LocalClient) Dump() (err error) { defer l.bc.Close() f, err := os.Create(l.dumpPath) diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/util/n3client.go similarity index 72% rename from cmd/frostfs-adm/internal/modules/morph/n3client.go rename to cmd/frostfs-adm/internal/modules/morph/util/n3client.go index 584bb852..0cc751cf 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/n3client.go @@ -1,4 +1,4 @@ -package morph +package util import ( "context" @@ -34,19 +34,19 @@ type Client interface { CalculateNetworkFee(tx *transaction.Transaction) (int64, error) } -type hashVUBPair struct { - hash util.Uint256 - vub uint32 +type HashVUBPair struct { + Hash util.Uint256 + Vub uint32 } -type clientContext struct { +type ClientContext struct { Client Client // a raw neo-go client OR a local chain implementation CommitteeAct *actor.Actor // committee actor with the Global witness scope ReadOnlyInvoker *invoker.Invoker // R/O contract invoker, does not contain any signer - SentTxs []hashVUBPair + SentTxs []HashVUBPair } -func getN3Client(v *viper.Viper) (Client, error) { +func GetN3Client(v *viper.Viper) (Client, error) { // number of opened connections // by neo-go client per one host const ( @@ -55,7 +55,7 @@ func getN3Client(v *viper.Viper) (Client, error) { ) ctx := context.Background() - endpoint := v.GetString(endpointFlag) + endpoint := v.GetString(EndpointFlag) if endpoint == "" { return nil, errors.New("missing endpoint") } @@ -72,20 +72,20 @@ func getN3Client(v *viper.Viper) (Client, error) { return c, nil } -func defaultClientContext(c Client, committeeAcc *wallet.Account) (*clientContext, error) { - commAct, err := newActor(c, committeeAcc) +func DefaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) { + commAct, err := NewActor(c, committeeAcc) if err != nil { return nil, err } - return &clientContext{ + return &ClientContext{ Client: c, CommitteeAct: commAct, ReadOnlyInvoker: invoker.New(c, nil), }, nil } -func (c *clientContext) sendTx(tx *transaction.Transaction, cmd *cobra.Command, await bool) error { +func (c *ClientContext) SendTx(tx *transaction.Transaction, cmd *cobra.Command, await bool) error { h, err := c.Client.SendRawTransaction(tx) if err != nil { return err @@ -95,10 +95,27 @@ func (c *clientContext) sendTx(tx *transaction.Transaction, cmd *cobra.Command, return fmt.Errorf("sent and actual tx hashes mismatch:\n\tsent: %v\n\tactual: %v", tx.Hash().StringLE(), h.StringLE()) } - c.SentTxs = append(c.SentTxs, hashVUBPair{hash: h, vub: tx.ValidUntilBlock}) + c.SentTxs = append(c.SentTxs, HashVUBPair{Hash: h, Vub: tx.ValidUntilBlock}) if await { - return c.awaitTx(cmd) + return c.AwaitTx(cmd) } return nil } + +func (c *ClientContext) AwaitTx(cmd *cobra.Command) error { + if len(c.SentTxs) == 0 { + return nil + } + + if local, ok := c.Client.(*LocalClient); ok { + if err := local.putTransactions(); err != nil { + return fmt.Errorf("can't persist transactions: %w", err) + } + } + + err := AwaitTx(cmd, c.Client, c.SentTxs) + c.SentTxs = c.SentTxs[:0] + + return err +} diff --git a/cmd/frostfs-adm/internal/modules/morph/util.go b/cmd/frostfs-adm/internal/modules/morph/util/util.go similarity index 86% rename from cmd/frostfs-adm/internal/modules/morph/util.go rename to cmd/frostfs-adm/internal/modules/morph/util/util.go index 8b5489ab..bbe635a4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/util.go @@ -1,4 +1,4 @@ -package morph +package util import ( "errors" @@ -15,19 +15,19 @@ import ( "github.com/spf13/viper" ) -func getAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { - wallets, err := openAlphabetWallets(v, walletDir) +func GetAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { + wallets, err := OpenAlphabetWallets(v, walletDir) if err != nil { return nil, err } - if len(wallets) > maxAlphabetNodes { + if len(wallets) > MaxAlphabetNodes { return nil, ErrTooManyAlphabetNodes } return wallets, nil } -func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { +func OpenAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { walletFiles, err := os.ReadDir(walletDir) if err != nil { return nil, fmt.Errorf("can't read alphabet wallets dir: %w", err) @@ -75,7 +75,7 @@ loop: return wallets, nil } -func newActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) { +func NewActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) { return actor.New(c, []actor.SignerAccount{{ Signer: transaction.Signer{ Account: committeeAcc.Contract.ScriptHash(),