code.vegaprotocol.io/vega@v0.79.0/wallet/version/helpers.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 version
    17  
    18  import (
    19  	"context"
    20  	"errors"
    21  	"fmt"
    22  	"net/http"
    23  	"strings"
    24  	"time"
    25  
    26  	apipb "code.vegaprotocol.io/vega/protos/vega/api/v1"
    27  
    28  	"google.golang.org/grpc"
    29  	"google.golang.org/grpc/credentials"
    30  	"google.golang.org/grpc/credentials/insecure"
    31  )
    32  
    33  var (
    34  	ErrConnectionError      = errors.New("verify you are connected to the internet")
    35  	ErrCouldNotConnectNodes = errors.New("could not connect to any nodes: verify your network configuration is up to date")
    36  )
    37  
    38  func GetNetworkVersionThroughGRPC(hosts []string) (string, error) {
    39  	for _, host := range hosts {
    40  		version, err := queryNetworkVersion(host)
    41  		if err != nil {
    42  			continue
    43  		}
    44  		return version, nil
    45  	}
    46  
    47  	// Before advising the users to check their network configuration, the software
    48  	// pings vega.xyz to verify whether or not they are connected to the internet.
    49  	// This should help the user with troubleshooting their setup.
    50  	ctx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
    51  	defer cancelFn()
    52  	req, err := http.NewRequestWithContext(ctx, http.MethodHead, "https://vega.xyz", nil)
    53  	if err != nil {
    54  		return "", fmt.Errorf("could not build the request that verifies the network connection: %w", err)
    55  	}
    56  	resp, err := http.DefaultClient.Do(req)
    57  	if err != nil || resp.StatusCode != http.StatusOK {
    58  		return "", ErrConnectionError
    59  	}
    60  	if resp.Body != nil {
    61  		_ = resp.Body.Close()
    62  	}
    63  
    64  	// If it reaches that point, it's been possible to get a response to the ping to
    65  	// `vega.xyz`, which suggest the issue comes from the network configuration
    66  	// (outdated, or misconfigured), or from the nodes themselves (not responding,
    67  	// or giving unexpected responses).
    68  	return "", ErrCouldNotConnectNodes
    69  }
    70  
    71  func queryNetworkVersion(host string) (string, error) {
    72  	useTLS := strings.HasPrefix(host, "tls://")
    73  
    74  	var creds credentials.TransportCredentials
    75  	if useTLS {
    76  		host = host[6:]
    77  		creds = credentials.NewClientTLSFromCert(nil, "")
    78  	} else {
    79  		creds = insecure.NewCredentials()
    80  	}
    81  
    82  	connection, err := grpc.Dial(host, grpc.WithTransportCredentials(creds))
    83  	if err != nil {
    84  		return "", fmt.Errorf("couldn't initialize gRPC client: %w", err)
    85  	}
    86  	defer func() {
    87  		_ = connection.Close()
    88  	}()
    89  
    90  	client := apipb.NewCoreServiceClient(connection)
    91  
    92  	timeout, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
    93  	defer cancelFn()
    94  
    95  	statistics, err := client.Statistics(timeout, &apipb.StatisticsRequest{})
    96  	if err != nil {
    97  		return "", err
    98  	}
    99  
   100  	return statistics.Statistics.AppVersion, nil
   101  }