code.vegaprotocol.io/vega@v0.79.0/cmd/vega/commands/propose_upgrade.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 "strings" 23 24 "code.vegaprotocol.io/vega/core/config" 25 "code.vegaprotocol.io/vega/core/protocolupgrade" 26 "code.vegaprotocol.io/vega/core/txn" 27 vgcrypto "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/blang/semver" 34 "github.com/jessevdk/go-flags" 35 ) 36 37 type ProposeUpgradeCmd struct { 38 config.VegaHomeFlag 39 config.OutputFlag 40 config.Passphrase `long:"passphrase-file"` 41 42 VegaReleaseTag string `description:"A valid vega core release tag for the upgrade proposal" long:"vega-release-tag" required:"true" short:"v"` 43 UpgradeBlockHeight uint64 `description:"The block height at which the upgrade should be made" long:"height" required:"true" short:"h"` 44 } 45 46 var proposeUpgradeCmd ProposeUpgradeCmd 47 48 func (opts *ProposeUpgradeCmd) 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 registryPass, err := opts.Get("node wallet", false) 58 if err != nil { 59 return err 60 } 61 62 vegaPaths := paths.New(opts.VegaHome) 63 64 _, conf, err := config.EnsureNodeConfig(vegaPaths) 65 if err != nil { 66 return err 67 } 68 69 if !conf.IsValidator() { 70 return errors.New("node is not a validator") 71 } 72 73 if !strings.HasPrefix(opts.VegaReleaseTag, "v") { 74 return errors.New("invalid vega release tag, expected prefix 'v' (example: v0.71.9)") 75 } 76 77 cmd := commandspb.ProtocolUpgradeProposal{ 78 VegaReleaseTag: opts.VegaReleaseTag, 79 UpgradeBlockHeight: opts.UpgradeBlockHeight, 80 } 81 82 commander, blockData, cfunc, err := getNodeWalletCommander(log, registryPass, vegaPaths) 83 if err != nil { 84 return fmt.Errorf("failed to get commander: %w", err) 85 } 86 87 if opts.UpgradeBlockHeight <= blockData.Height { 88 return fmt.Errorf("upgrade block earlier than current block height") 89 } 90 91 _, err = semver.Parse(protocolupgrade.TrimReleaseTag(opts.VegaReleaseTag)) 92 if err != nil { 93 return fmt.Errorf("invalid protocol version for upgrade received: version (%s), %w", opts.VegaReleaseTag, err) 94 } 95 96 defer cfunc() 97 98 tid := vgcrypto.RandomHash() 99 powNonce, _, err := vgcrypto.PoW(blockData.Hash, tid, uint(blockData.SpamPowDifficulty), vgcrypto.Sha3) 100 if err != nil { 101 return fmt.Errorf("failed to get proof of work: %w", err) 102 } 103 104 pow := &commandspb.ProofOfWork{ 105 Tid: tid, 106 Nonce: powNonce, 107 } 108 109 var txHash string 110 ch := make(chan struct{}) 111 commander.CommandWithPoW( 112 context.Background(), 113 txn.ProtocolUpgradeCommand, 114 &cmd, 115 func(h string, e error) { 116 txHash, err = h, e 117 close(ch) 118 }, nil, pow) 119 120 <-ch 121 122 if err != nil { 123 return err 124 } 125 126 if output.IsHuman() { 127 fmt.Printf("Upgrade proposal sent.\ntxHash: %s", txHash) 128 } else if output.IsJSON() { 129 return vgjson.Print(struct { 130 TxHash string `json:"txHash"` 131 }{ 132 TxHash: txHash, 133 }) 134 } 135 return err 136 } 137 138 func ProposeProtocolUpgrade(ctx context.Context, parser *flags.Parser) error { 139 proposeUpgradeCmd = ProposeUpgradeCmd{} 140 141 var ( 142 short = "Propose a protocol upgrade" 143 long = "Propose a protocol upgrade" 144 ) 145 _, err := parser.AddCommand("protocol_upgrade_proposal", short, long, &proposeUpgradeCmd) 146 return err 147 }