package notary import ( "errors" "fmt" "math/big" "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "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" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/rpcclient/notary" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" "github.com/spf13/viper" ) const ( // defaultNotaryDepositLifetime is an amount of blocks notary deposit stays valid. // https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/native/notary.go#L48 defaultNotaryDepositLifetime = 5760 walletAccountFlag = "account" notaryDepositTillFlag = "till" ) var errInvalidNotaryDepositLifetime = errors.New("notary deposit lifetime must be a positive integer") func depositNotary(cmd *cobra.Command, _ []string) error { w, err := openWallet(cmd) if err != nil { return err } accHash := w.GetChangeAddress() if addr, err := cmd.Flags().GetString(walletAccountFlag); err == nil { accHash, err = address.StringToUint160(addr) if err != nil { return fmt.Errorf("invalid address: %s", addr) } } acc := w.GetAccount(accHash) if acc == nil { return fmt.Errorf("can't find account for %s", accHash) } prompt := fmt.Sprintf("Enter password for %s >", address.Uint160ToString(accHash)) pass, err := input.ReadPassword(prompt) if err != nil { return fmt.Errorf("can't get password: %v", err) } err = acc.Decrypt(pass, keys.NEP2ScryptParams()) if err != nil { return fmt.Errorf("can't unlock account: %v", err) } gasStr, err := cmd.Flags().GetString(commonflags.RefillGasAmountFlag) if err != nil { return err } gasAmount, err := helper.ParseGASAmount(gasStr) if err != nil { return err } till := int64(defaultNotaryDepositLifetime) tillStr, err := cmd.Flags().GetString(notaryDepositTillFlag) if err != nil { return err } if tillStr != "" { till, err = strconv.ParseInt(tillStr, 10, 64) if err != nil || till <= 0 { return errInvalidNotaryDepositLifetime } } return transferGas(cmd, acc, accHash, gasAmount, till) } func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error { c, err := helper.NewRemoteClient(viper.GetViper()) if err != nil { return err } if err := helper.CheckNotaryEnabled(c); err != nil { return err } height, err := c.GetBlockCount() if err != nil { return fmt.Errorf("can't get current height: %v", err) } act, err := actor.New(c, []actor.SignerAccount{{ Signer: transaction.Signer{ Account: acc.Contract.ScriptHash(), Scopes: transaction.Global, }, Account: acc, }}) if err != nil { return fmt.Errorf("could not create actor: %w", err) } gasActor := nep17.New(act, gas.Hash) txHash, vub, err := gasActor.Transfer( accHash, notary.Hash, big.NewInt(int64(gasAmount)), []any{nil, int64(height) + till}, ) if err != nil { return fmt.Errorf("could not send tx: %w", err) } return helper.AwaitTx(cmd, c, []helper.HashVUBPair{{Hash: txHash, Vub: vub}}) } func openWallet(cmd *cobra.Command) (*wallet.Wallet, error) { p, err := cmd.Flags().GetString(commonflags.StorageWalletFlag) if err != nil { return nil, err } else if p == "" { return nil, fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) } w, err := wallet.NewWalletFromFile(p) if err != nil { return nil, fmt.Errorf("can't open wallet: %v", err) } return w, nil }