code.vegaprotocol.io/vega@v0.79.0/cmd/data-node/commands/networkhistory/networkhistory.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 networkhistory 17 18 import ( 19 "context" 20 "fmt" 21 22 "code.vegaprotocol.io/vega/datanode/admin" 23 "code.vegaprotocol.io/vega/datanode/config" 24 "code.vegaprotocol.io/vega/datanode/networkhistory" 25 vgjson "code.vegaprotocol.io/vega/libs/json" 26 "code.vegaprotocol.io/vega/logging" 27 "code.vegaprotocol.io/vega/paths" 28 v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2" 29 30 "github.com/jessevdk/go-flags" 31 "google.golang.org/grpc" 32 ) 33 34 type Cmd struct { 35 // Subcommands 36 Show showCmd `command:"show" description:"shows network history segments currently stored by the node"` 37 Load loadCmd `command:"load" description:"load [from height] [to height], loads the given span of network history into the datanode, if no span is specified the latest contiguous network history will be loaded"` 38 Rollback rollbackCmd `command:"rollback" description:"rollback [to height], rolls back the datanode to the given height, the rollback height must match the to height of a network history segment"` 39 Fetch fetchCmd `command:"fetch" description:"fetch <history segment id> <blocks to fetch>, fetches the given segment and all previous segments until <blocks to fetch> blocks have been retrieved"` 40 LatestHistorySegmentFromPeers latestHistorySegmentFromPeers `command:"latest-history-segment-from-peers" description:"latest-history-segment-from-peers returns the id of the networks latest history segment"` 41 LatestHistorySegment latestHistorySegment `command:"latest-history-segment" description:"latest-history-segment returns the id of the node's latest history segment"` 42 ListActivePeers listActivePeers `command:"list-active-peers" description:"list the active datanode peers"` 43 Copy copyCmd `command:"copy" description:"copy a history segment from network history to a file"` 44 } 45 46 var networkHistoryCmd Cmd 47 48 func NetworkHistory(_ context.Context, parser *flags.Parser) error { 49 cfg := config.NewDefaultConfig() 50 networkHistoryCmd = Cmd{ 51 Show: showCmd{}, 52 Load: loadCmd{ 53 Config: cfg, 54 }, 55 Fetch: fetchCmd{}, 56 LatestHistorySegmentFromPeers: latestHistorySegmentFromPeers{}, 57 LatestHistorySegment: latestHistorySegment{}, 58 ListActivePeers: listActivePeers{}, 59 Copy: copyCmd{ 60 Config: cfg, 61 }, 62 } 63 64 desc := "commands for managing network history" 65 _, err := parser.AddCommand("network-history", desc, desc, &networkHistoryCmd) 66 if err != nil { 67 return err 68 } 69 return nil 70 } 71 72 func getDatanodeClient(cfg config.Config) (v2.TradingDataServiceClient, *grpc.ClientConn, error) { 73 return networkhistory.GetDatanodeClientFromIPAndPort(cfg.API.IP, cfg.API.Port, cfg.API.MaxMsgSize) 74 } 75 76 func getDatanodeAdminClient(log *logging.Logger, cfg config.Config) *admin.Client { 77 client := admin.NewClient(log, cfg.Admin) 78 return client 79 } 80 81 func datanodeLive(cfg config.Config) bool { 82 client, conn, err := getDatanodeClient(cfg) 83 if err != nil { 84 return false 85 } 86 defer conn.Close() 87 88 _, err = client.Ping(context.Background(), &v2.PingRequest{}) 89 return err == nil 90 } 91 92 // getConfig figures out where to read a config file from, reads it, and then applies any extra 93 // modifications on top of that. 94 // 95 // This is working around a bit of awkwardness in that the config supplied by go-flags is a blank 96 // config updated with command line flags. There is not enough information in it to apply an 97 // 'overlay' to a config read from a file, because it is not possible for us to tell if someone 98 // is trying to override a value back to its 'zero' value. (e.g. --something.enabled=false gives 99 // the same go-flags structure as no argument at all). 100 func fixConfig(config *config.Config, vegaPaths paths.Paths) error { 101 configFilePath, err := vegaPaths.CreateConfigPathFor(paths.DataNodeDefaultConfigFile) 102 if err != nil { 103 return fmt.Errorf("couldn't get path for %s: %w", paths.DataNodeDefaultConfigFile, err) 104 } 105 106 // Read config from file 107 err = paths.ReadStructuredFile(configFilePath, config) 108 if err != nil { 109 return fmt.Errorf("failed to read config:%w", err) 110 } 111 112 // Apply command-line flags on top 113 _, err = flags.NewParser(config, flags.Default|flags.IgnoreUnknown).Parse() 114 if err != nil { 115 return fmt.Errorf("failed to parse args:%w", err) 116 } 117 return nil 118 } 119 120 func handleErr(log *logging.Logger, outputJSON bool, msg string, err error) { 121 if outputJSON { 122 _ = vgjson.Print(struct { 123 Error string `json:"error"` 124 }{ 125 Error: err.Error(), 126 }) 127 } else { 128 log.Error(msg, logging.Error(err)) 129 } 130 }