code.vegaprotocol.io/vega@v0.79.0/cmd/vega/commands/nodewallet/import.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package nodewallet 17 18 import ( 19 "encoding/base64" 20 "encoding/json" 21 "errors" 22 "fmt" 23 24 "code.vegaprotocol.io/vega/core/config" 25 "code.vegaprotocol.io/vega/core/nodewallets" 26 vgfmt "code.vegaprotocol.io/vega/libs/fmt" 27 vgfs "code.vegaprotocol.io/vega/libs/fs" 28 vgjson "code.vegaprotocol.io/vega/libs/json" 29 "code.vegaprotocol.io/vega/logging" 30 "code.vegaprotocol.io/vega/paths" 31 32 tmconfig "github.com/cometbft/cometbft/config" 33 "github.com/jessevdk/go-flags" 34 ) 35 36 var ( 37 ErrOneOfTendermintFlagIsRequired = errors.New("one of --tendermint-home or --tendermint-pubkey flag is required") 38 ErrTendermintFlagsAreMutuallyExclusive = errors.New("--tendermint-home and --tendermint-pubkey are mutually exclusive") 39 ErrClefOptionMissing = errors.New("--clef-account and --clef-address must both be set to import a clef wallet") 40 ) 41 42 type importCmd struct { 43 config.OutputFlag 44 45 Config nodewallets.Config 46 47 WalletPassphrase config.Passphrase `long:"wallet-passphrase-file"` 48 49 Chain string `choice:"vega" choice:"ethereum" choice:"tendermint" description:"The chain to be imported" long:"chain" required:"true" short:"c"` 50 WalletPath config.PromptString `description:"The path to the wallet file to import" long:"wallet-path"` 51 Force bool `description:"Should the command re-write an existing nodewallet file if it exists" long:"force"` 52 53 // clef flags 54 EthereumClefAddress string `description:"The URL to the clef instance that Vega will use." long:"ethereum-clef-address"` 55 EthereumClefAccount string `description:"The Ethereum account to be imported by Vega from Clef. In hex." long:"ethereum-clef-account"` 56 57 // tendermint flags 58 TendermintPubkey string `description:"The tendermint pubkey of the tendermint validator node" long:"tendermint-pubkey"` 59 TendermintHome string `description:"The tendermint home from which to look the for the pubkey" long:"tendermint-home"` 60 } 61 62 func (opts *importCmd) Execute(_ []string) error { 63 output, err := opts.GetOutput() 64 if err != nil { 65 return err 66 } 67 68 log := logging.NewLoggerFromConfig(logging.NewDefaultConfig()) 69 defer log.AtExit() 70 71 if (opts.EthereumClefAccount != "") != (opts.EthereumClefAddress != "") { 72 return ErrClefOptionMissing 73 } 74 75 registryPass, err := rootCmd.PassphraseFile.Get("node wallet", false) 76 if err != nil { 77 return err 78 } 79 80 vegaPaths := paths.New(rootCmd.VegaHome) 81 82 _, conf, err := config.EnsureNodeConfig(vegaPaths) 83 if err != nil { 84 return err 85 } 86 87 opts.Config = conf.NodeWallet 88 89 if _, err := flags.NewParser(opts, flags.Default|flags.IgnoreUnknown).Parse(); err != nil { 90 return err 91 } 92 93 var walletPass, walletPath string 94 if opts.Chain == vegaChain || (opts.Chain == ethereumChain && opts.EthereumClefAddress == "") { 95 walletPass, err = opts.WalletPassphrase.Get("blockchain wallet", false) 96 if err != nil { 97 return err 98 } 99 walletPath, err = opts.WalletPath.Get("wallet path", "wallet-path") 100 if err != nil { 101 return err 102 } 103 } 104 105 var data map[string]string 106 switch opts.Chain { 107 case ethereumChain: 108 data, err = nodewallets.ImportEthereumWallet( 109 vegaPaths, 110 registryPass, 111 walletPass, 112 opts.EthereumClefAccount, 113 opts.EthereumClefAddress, 114 walletPath, 115 opts.Force, 116 ) 117 if err != nil { 118 return fmt.Errorf("couldn't import Ethereum node wallet: %w", err) 119 } 120 case vegaChain: 121 data, err = nodewallets.ImportVegaWallet(vegaPaths, registryPass, walletPass, walletPath, opts.Force) 122 if err != nil { 123 return fmt.Errorf("couldn't import Vega node wallet: %w", err) 124 } 125 case tendermintChain: 126 if len(opts.TendermintHome) == 0 && len(opts.TendermintPubkey) == 0 { 127 return ErrOneOfTendermintFlagIsRequired 128 } 129 if len(opts.TendermintHome) > 0 && len(opts.TendermintPubkey) > 0 { 130 return ErrTendermintFlagsAreMutuallyExclusive 131 } 132 133 tendermintPubkey := opts.TendermintPubkey 134 if len(opts.TendermintHome) > 0 { 135 tendermintPubkey, err = getLocalTendermintPubkey(opts.TendermintHome) 136 if err != nil { 137 return fmt.Errorf("couldn't retrieve tendermint public key: %w", err) 138 } 139 } 140 141 // validate the key is base64 142 _, err := base64.StdEncoding.DecodeString(tendermintPubkey) 143 if err != nil { 144 return fmt.Errorf("tendermint pubkey must be base64 encoded: %w", err) 145 } 146 147 data, err = nodewallets.ImportTendermintPubkey(vegaPaths, registryPass, tendermintPubkey, opts.Force) 148 if err != nil { 149 return fmt.Errorf("couldn't import Tendermint pubkey: %w", err) 150 } 151 } 152 153 if output.IsHuman() { 154 fmt.Println(green("import successful:")) 155 vgfmt.PrettyPrint(data) 156 } else if output.IsJSON() { 157 if err := vgjson.Print(data); err != nil { 158 return err 159 } 160 } 161 162 return nil 163 } 164 165 func getLocalTendermintPubkey(tendermintHome string) (string, error) { 166 tmConfig := tmconfig.DefaultConfig() 167 tmConfig.SetRoot(tendermintHome) 168 genesisFilePath := tmConfig.PrivValidatorKeyFile() 169 170 data, err := vgfs.ReadFile(genesisFilePath) 171 if err != nil { 172 return "", err 173 } 174 175 privValidatorKey := struct { 176 PubKey struct { 177 Value string `json:"value"` 178 } `json:"pub_key"` 179 }{} 180 181 if err = json.Unmarshal(data, &privValidatorKey); err != nil { 182 return "", fmt.Errorf("could not read priv_validator_key.json: %w", err) 183 } 184 185 return privValidatorKey.PubKey.Value, nil 186 }