forked from TrueCloudLab/frostfs-node
[#932] adm: Move generate.go
to package generate
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
This commit is contained in:
parent
b8cf0a6b88
commit
86b2515744
6 changed files with 104 additions and 92 deletions
215
cmd/frostfs-adm/internal/modules/morph/generate/generate.go
Normal file
215
cmd/frostfs-adm/internal/modules/morph/generate/generate.go
Normal file
|
@ -0,0 +1,215 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"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"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||
"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/opcode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func AlphabetCreds(cmd *cobra.Command, _ []string) error {
|
||||
// alphabet size is not part of the config
|
||||
size, err := cmd.Flags().GetUint(morphUtil.AlphabetSizeFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if size == 0 {
|
||||
return errors.New("size must be > 0")
|
||||
}
|
||||
if size > morphUtil.MaxAlphabetNodes {
|
||||
return morphUtil.ErrTooManyAlphabetNodes
|
||||
}
|
||||
|
||||
v := viper.GetViper()
|
||||
walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag))
|
||||
pwds, err := initializeWallets(v, walletDir, int(size))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = morphUtil.InitializeContractWallet(v, walletDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Println("size:", size)
|
||||
cmd.Println("alphabet-wallets:", walletDir)
|
||||
for i := range pwds {
|
||||
cmd.Printf("wallet[%d]: %s\n", i, pwds[i])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, error) {
|
||||
wallets := make([]*wallet.Wallet, size)
|
||||
pubs := make(keys.PublicKeys, size)
|
||||
passwords := make([]string, size)
|
||||
|
||||
for i := range wallets {
|
||||
password, err := config.GetPassword(v, innerring.GlagoliticLetter(i).String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't fetch password: %w", err)
|
||||
}
|
||||
|
||||
p := filepath.Join(walletDir, innerring.GlagoliticLetter(i).String()+".json")
|
||||
f, err := os.OpenFile(p, os.O_CREATE, 0o644)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't create wallet file: %w", err)
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return nil, fmt.Errorf("can't close wallet file: %w", err)
|
||||
}
|
||||
w, err := wallet.NewWallet(p)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't create wallet: %w", err)
|
||||
}
|
||||
if err := w.CreateAccount(morphUtil.SingleAccountName, password); err != nil {
|
||||
return nil, fmt.Errorf("can't create account: %w", err)
|
||||
}
|
||||
|
||||
passwords[i] = password
|
||||
wallets[i] = w
|
||||
pubs[i] = w.Accounts[0].PrivateKey().PublicKey()
|
||||
}
|
||||
|
||||
var errG errgroup.Group
|
||||
|
||||
// Create committee account with N/2+1 multi-signature.
|
||||
majCount := smartcontract.GetMajorityHonestNodeCount(size)
|
||||
// Create consensus account with 2*N/3+1 multi-signature.
|
||||
bftCount := smartcontract.GetDefaultHonestNodeCount(size)
|
||||
for i := range wallets {
|
||||
i := i
|
||||
ps := pubs.Copy()
|
||||
errG.Go(func() error {
|
||||
if err := addMultisigAccount(wallets[i], majCount, morphUtil.CommitteeAccountName, passwords[i], ps); err != nil {
|
||||
return fmt.Errorf("can't create committee account: %w", err)
|
||||
}
|
||||
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 {
|
||||
return fmt.Errorf("can't save wallet: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := errG.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return passwords, nil
|
||||
}
|
||||
|
||||
func addMultisigAccount(w *wallet.Wallet, m int, name, password string, pubs keys.PublicKeys) error {
|
||||
acc := wallet.NewAccountFromPrivateKey(w.Accounts[0].PrivateKey())
|
||||
acc.Label = name
|
||||
|
||||
if err := acc.ConvertMultisig(m, pubs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := acc.Encrypt(password, keys.NEP2ScryptParams()); err != nil {
|
||||
return err
|
||||
}
|
||||
w.AddAccount(acc)
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateStorageCreds(cmd *cobra.Command, _ []string) error {
|
||||
return refillGas(cmd, storageGasConfigFlag, true)
|
||||
}
|
||||
|
||||
func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error) {
|
||||
// storage wallet path is not part of the config
|
||||
storageWalletPath, _ := cmd.Flags().GetString(morphUtil.StorageWalletFlag)
|
||||
// wallet address is not part of the config
|
||||
walletAddress, _ := cmd.Flags().GetString(walletAddressFlag)
|
||||
|
||||
var gasReceiver util.Uint160
|
||||
|
||||
if len(walletAddress) != 0 {
|
||||
gasReceiver, err = address.StringToUint160(walletAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err)
|
||||
}
|
||||
} else {
|
||||
if storageWalletPath == "" {
|
||||
return fmt.Errorf("missing wallet path (use '--%s <out.json>')", morphUtil.StorageWalletFlag)
|
||||
}
|
||||
|
||||
var w *wallet.Wallet
|
||||
|
||||
if createWallet {
|
||||
w, err = wallet.NewWallet(storageWalletPath)
|
||||
} else {
|
||||
w, err = wallet.NewWalletFromFile(storageWalletPath)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't create wallet: %w", err)
|
||||
}
|
||||
|
||||
if createWallet {
|
||||
var password string
|
||||
|
||||
label, _ := cmd.Flags().GetString(storageWalletLabelFlag)
|
||||
password, err := config.GetStoragePassword(viper.GetViper(), label)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't fetch password: %w", err)
|
||||
}
|
||||
|
||||
if label == "" {
|
||||
label = morphUtil.SingleAccountName
|
||||
}
|
||||
|
||||
if err := w.CreateAccount(label, password); err != nil {
|
||||
return fmt.Errorf("can't create account: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
gasReceiver = w.Accounts[0].Contract.ScriptHash()
|
||||
}
|
||||
|
||||
gasStr := viper.GetString(gasFlag)
|
||||
|
||||
gasAmount, err := morphUtil.ParseGASAmount(gasStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bw := io.NewBufBinWriter()
|
||||
emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All,
|
||||
wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil)
|
||||
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
||||
if bw.Err != nil {
|
||||
return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err)
|
||||
}
|
||||
|
||||
if err := wCtx.SendCommitteeTx(bw.Bytes(), false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return wCtx.AwaitTx()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue