code.vegaprotocol.io/vega@v0.79.0/cmd/vega/commands/rotate_eth_key.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 commands 17 18 import ( 19 "context" 20 "errors" 21 "fmt" 22 23 "code.vegaprotocol.io/vega/core/config" 24 "code.vegaprotocol.io/vega/core/nodewallets" 25 "code.vegaprotocol.io/vega/core/txn" 26 "code.vegaprotocol.io/vega/core/validators" 27 "code.vegaprotocol.io/vega/libs/crypto" 28 vgjson "code.vegaprotocol.io/vega/libs/json" 29 "code.vegaprotocol.io/vega/logging" 30 "code.vegaprotocol.io/vega/paths" 31 commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" 32 33 "github.com/jessevdk/go-flags" 34 ) 35 36 type RotateEthKeyCmd struct { 37 config.VegaHomeFlag 38 config.OutputFlag 39 config.Passphrase `long:"passphrase-file"` 40 41 TargetBlock uint64 `description:"The future block height at which the rotation will take place" long:"target-block" short:"b"` 42 RotateFrom string `description:"Ethereum address being rotated from" long:"rotate-from" short:"r"` 43 SubmitterAddress string `description:"Ethereum address to use as a submitter to contract changes" long:"submitter-address" short:"s"` 44 } 45 46 var rotateEthKeyCmd RotateEthKeyCmd 47 48 func (opts *RotateEthKeyCmd) Execute(_ []string) error { 49 log := logging.NewLoggerFromConfig(logging.NewDefaultConfig()) 50 defer log.AtExit() 51 52 output, err := opts.GetOutput() 53 if err != nil { 54 return err 55 } 56 57 vegaPaths := paths.New(opts.VegaHome) 58 59 _, conf, err := config.EnsureNodeConfig(vegaPaths) 60 if err != nil { 61 return err 62 } 63 64 if !conf.IsValidator() { 65 return errors.New("node is not a validator") 66 } 67 68 registryPass, err := opts.Get("node wallet", false) 69 if err != nil { 70 return err 71 } 72 73 nodeWallets, err := nodewallets.GetNodeWallets(conf.NodeWallet, vegaPaths, registryPass) 74 if err != nil { 75 return fmt.Errorf("couldn't get node wallets: %w", err) 76 } 77 78 // ensure the nodewallet is setup properly, if not we could not complete the command 79 if err := nodeWallets.Verify(); err != nil { 80 return fmt.Errorf("node wallet misconfigured: %w", err) 81 } 82 83 cmd := commandspb.EthereumKeyRotateSubmission{ 84 CurrentAddress: crypto.EthereumChecksumAddress(opts.RotateFrom), 85 NewAddress: nodeWallets.Ethereum.PubKey().Hex(), 86 TargetBlock: opts.TargetBlock, 87 SubmitterAddress: opts.SubmitterAddress, 88 } 89 90 if len(cmd.SubmitterAddress) != 0 { 91 cmd.SubmitterAddress = crypto.EthereumChecksumAddress(cmd.SubmitterAddress) 92 } 93 94 if err := validators.SignEthereumKeyRotation(&cmd, nodeWallets.Ethereum); err != nil { 95 return err 96 } 97 98 commander, _, cfunc, err := getNodeWalletCommander(log, registryPass, vegaPaths) 99 if err != nil { 100 return fmt.Errorf("failed to get commander: %w", err) 101 } 102 defer cfunc() 103 104 var txHash string 105 ch := make(chan struct{}) 106 commander.Command( 107 context.Background(), 108 txn.RotateEthereumKeySubmissionCommand, 109 &cmd, 110 func(h string, e error) { 111 txHash, err = h, e 112 close(ch) 113 }, nil) 114 115 <-ch 116 if err != nil { 117 return err 118 } 119 120 if output.IsHuman() { 121 fmt.Printf("ethereum key rotation successfully sent\ntxHash: %s\nethereum signature: %v\nRotating from: %s\nRotating to: %s", 122 txHash, 123 cmd.EthereumSignature.Value, 124 opts.RotateFrom, 125 cmd.NewAddress, 126 ) 127 } else if output.IsJSON() { 128 return vgjson.Print(struct { 129 TxHash string `json:"txHash"` 130 EthereumSignature string `json:"ethereumSignature"` 131 RotateFrom string `json:"rotateFrom"` 132 RotateTo string `json:"rotateTo"` 133 }{ 134 TxHash: txHash, 135 RotateFrom: opts.RotateFrom, 136 RotateTo: cmd.NewAddress, 137 EthereumSignature: cmd.EthereumSignature.Value, 138 }) 139 } 140 141 return nil 142 } 143 144 func RotateEthKey(ctx context.Context, parser *flags.Parser) error { 145 announceNodeCmd = AnnounceNodeCmd{} 146 147 var ( 148 short = "Send a transaction to rotate to current ethereum key" 149 long = "Send a transaction to rotate to current ethereum key" 150 ) 151 _, err := parser.AddCommand("rotate_eth_key", short, long, &rotateEthKeyCmd) 152 return err 153 }