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  }