code.vegaprotocol.io/vega@v0.79.0/wallet/version/version.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  	"errors"
    20  	"sort"
    21  	"strings"
    22  
    23  	vgversion "code.vegaprotocol.io/vega/libs/version"
    24  	coreversion "code.vegaprotocol.io/vega/version"
    25  	"code.vegaprotocol.io/vega/wallet/network"
    26  )
    27  
    28  var ErrCouldNotListNetworks = errors.New("couldn't list the networks")
    29  
    30  // RequestVersionFn is the function in charge of retrieving the network version
    31  // ran by the host lists.
    32  type RequestVersionFn func(hosts []string) (string, error)
    33  
    34  //go:generate go run github.com/golang/mock/mockgen -destination mocks/store_mock.go -package mocks code.vegaprotocol.io/vega/wallet/version NetworkStore
    35  type NetworkStore interface {
    36  	ListNetworks() ([]string, error)
    37  	GetNetwork(string) (*network.Network, error)
    38  }
    39  
    40  func IsUnreleased() bool {
    41  	return vgversion.IsUnreleased(coreversion.Get())
    42  }
    43  
    44  type GetSoftwareVersionResponse struct {
    45  	Version string `json:"version"`
    46  	GitHash string `json:"gitHash"`
    47  }
    48  
    49  func GetSoftwareVersionInfo() *GetSoftwareVersionResponse {
    50  	response := &GetSoftwareVersionResponse{
    51  		Version: coreversion.Get(),
    52  		GitHash: coreversion.GetCommitHash(),
    53  	}
    54  
    55  	return response
    56  }
    57  
    58  type CheckSoftwareCompatibilityResponse struct {
    59  	NetworksCompatibility []NetworkCompatibility `json:"networksCompatibility"`
    60  }
    61  
    62  type NetworkCompatibility struct {
    63  	Network          string `json:"network"`
    64  	IsCompatible     bool   `json:"isCompatible"`
    65  	RetrievedVersion string `json:"retrievedVersion"`
    66  	Error            error  `json:"error"`
    67  }
    68  
    69  func CheckSoftwareCompatibility(netStore NetworkStore, requestVersionFn RequestVersionFn) (*CheckSoftwareCompatibilityResponse, error) {
    70  	networks, err := netStore.ListNetworks()
    71  	// If there's an error we don't fail the command as the compatibility matrix
    72  	// is just a nice to have.
    73  	if err != nil {
    74  		// Best-effort, so we don't fail.
    75  		return nil, ErrCouldNotListNetworks
    76  	}
    77  
    78  	networksCompatibility := make([]NetworkCompatibility, 0, len(networks))
    79  
    80  	coreVersion := coreversion.Get()
    81  	coreVersionForComparison := onlyMajorAndMinor(coreVersion)
    82  
    83  	for _, net := range networks {
    84  		networkCompatibility := NetworkCompatibility{
    85  			Network: net,
    86  		}
    87  
    88  		netConfig, err := netStore.GetNetwork(net)
    89  		if err != nil {
    90  			// Best-effort, so we don't fail.
    91  			networkCompatibility.Error = err
    92  			networksCompatibility = append(networksCompatibility, networkCompatibility)
    93  			continue
    94  		}
    95  
    96  		if err := netConfig.EnsureCanConnectGRPCNode(); err != nil {
    97  			// Best-effort, so we don't fail.
    98  			networkCompatibility.Error = err
    99  			networksCompatibility = append(networksCompatibility, networkCompatibility)
   100  			continue
   101  		}
   102  
   103  		networkVersion, err := requestVersionFn(netConfig.API.GRPC.Hosts)
   104  		if err != nil {
   105  			// Best-effort, so we don't fail.
   106  			networkCompatibility.Error = err
   107  			networksCompatibility = append(networksCompatibility, networkCompatibility)
   108  			continue
   109  		}
   110  
   111  		networkCompatibility.RetrievedVersion = networkVersion
   112  		networkVersionForComparison := onlyMajorAndMinor(networkVersion)
   113  
   114  		if networkVersionForComparison != coreVersionForComparison {
   115  			networkCompatibility.IsCompatible = false
   116  			networksCompatibility = append(networksCompatibility, networkCompatibility)
   117  			continue
   118  		}
   119  
   120  		networkCompatibility.IsCompatible = true
   121  		networksCompatibility = append(networksCompatibility, networkCompatibility)
   122  	}
   123  
   124  	// Ensure the output is determinist.
   125  	sort.Slice(networksCompatibility, func(a, b int) bool {
   126  		return networksCompatibility[a].Network < networksCompatibility[b].Network
   127  	})
   128  
   129  	return &CheckSoftwareCompatibilityResponse{
   130  		NetworksCompatibility: networksCompatibility,
   131  	}, nil
   132  }
   133  
   134  func onlyMajorAndMinor(version string) string {
   135  	segments := strings.Split(version, ".")
   136  	if len(segments) < 2 {
   137  		// It doesn't seem to be a valid semantic version.
   138  		return version
   139  	}
   140  
   141  	return segments[0] + "." + segments[1]
   142  }