github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/version/version.go (about) 1 // package version provide the version info for the node, and also provide 2 // support for version compatibility check and update notification. 3 // 4 // The version format should follow Semantic Versioning (https://semver.org/): 5 // MAJOR.MINOR.PATCH 6 // 1. MAJOR version when you make incompatible API changes, 7 // 2. MINOR version when you add functionality in a backwards-compatible manner, and 8 // 3. PATCH version when you make backwards-compatible bug fixes. 9 // 10 // A pre-release version MAY be denoted by appending a hyphen and a series of 11 // dot separated identifiers immediately following the patch version. 12 // Examples: 13 // 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92. 14 // Precedence: 15 // 1. Pre-release versions have a lower precedence than the associated normal version! 16 // Numeric identifiers always have lower precedence than non-numeric identifiers. 17 // 2. A larger set of pre-release fields has a higher precedence than a smaller set, 18 // if all of the preceding identifiers are equal. 19 // 3. Example: 20 // 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0. 21 // 22 // Build metadata MAY be denoted by appending a plus sign and a series of dot 23 // separated identifiers immediately following the patch or pre-release version. 24 // Build metadata SHOULD be ignored when determining version precedence. Thus 25 // two versions that differ only in the build metadata, have the same precedence. 26 27 package version 28 29 import ( 30 "sync" 31 32 gover "github.com/hashicorp/go-version" 33 log "github.com/sirupsen/logrus" 34 "gopkg.in/fatih/set.v0" 35 ) 36 37 const ( 38 // If needing to edit the iota, please ensure the following: 39 // noUpdate = 0 40 // hasUpdate = 1 41 // hasMUpdate = 2 42 noUpdate uint16 = iota 43 hasUpdate 44 hasMUpdate 45 logModule = "version" 46 ) 47 48 var ( 49 // The full version string 50 Version = "2.0.6" 51 // GitCommit is set with --ldflags "-X main.gitCommit=$(git rev-parse HEAD)" 52 GitCommit string 53 Status *UpdateStatus 54 ) 55 56 func init() { 57 if GitCommit != "" { 58 Version += "+" + GitCommit[:8] 59 } 60 61 Status = &UpdateStatus{ 62 maxVerSeen: Version, 63 notified: false, 64 seedSet: set.New(), 65 versionStatus: noUpdate, 66 } 67 } 68 69 type UpdateStatus struct { 70 sync.RWMutex 71 maxVerSeen string 72 notified bool 73 seedSet *set.Set 74 versionStatus uint16 75 } 76 77 func (s *UpdateStatus) AddSeed(seedAddr string) { 78 s.Lock() 79 defer s.Unlock() 80 s.seedSet.Add(seedAddr) 81 } 82 83 // CheckUpdate checks whether there is a newer version to update. 84 // If there is, it set the "Status" variable to a proper value. 85 // params: 86 // localVerStr: the version of the node itself 87 // remoteVerStr: the version received from a seed node. 88 // remoteAddr: the version received from a seed node. 89 // current rule: 90 // 1. small update: seed version is higher than the node itself 91 // 2. significant update: seed mojor version is higher than the node itself 92 func (s *UpdateStatus) CheckUpdate(localVerStr string, remoteVerStr string, remoteAddr string) error { 93 s.Lock() 94 defer s.Unlock() 95 96 if !s.seedSet.Has(remoteAddr) { 97 return nil 98 } 99 100 localVersion, err := gover.NewVersion(localVerStr) 101 if err != nil { 102 return err 103 } 104 remoteVersion, err := gover.NewVersion(remoteVerStr) 105 if err != nil { 106 return err 107 } 108 if remoteVersion.GreaterThan(localVersion) { 109 if s.versionStatus == noUpdate { 110 s.versionStatus = hasUpdate 111 } 112 113 maxVersion, err := gover.NewVersion(s.maxVerSeen) 114 if err != nil { 115 return err 116 } 117 118 if remoteVersion.GreaterThan(maxVersion) { 119 s.maxVerSeen = remoteVerStr 120 } 121 } 122 if remoteVersion.Segments()[0] > localVersion.Segments()[0] { 123 s.versionStatus = hasMUpdate 124 } 125 if s.versionStatus != noUpdate { 126 log.WithFields(log.Fields{ 127 "module": logModule, 128 "Current version": localVerStr, 129 "Newer version": remoteVerStr, 130 "seed": remoteAddr, 131 }).Warn("Please update your bytomd via https://github.com/Bytom/bytom/releases/ or http://bytom.io/wallet/") 132 s.notified = true 133 } 134 return nil 135 } 136 137 func (s *UpdateStatus) MaxVerSeen() string { 138 s.RLock() 139 defer s.RUnlock() 140 return s.maxVerSeen 141 } 142 143 func (s *UpdateStatus) VersionStatus() uint16 { 144 s.RLock() 145 defer s.RUnlock() 146 return s.versionStatus 147 } 148 149 // CompatibleWith checks whether the remote peer version is compatible with the 150 // node itself. 151 // RULES: 152 // | local | remote | 153 // | - | - | 154 // | 1.0.3 | same major&moinor version. | 155 // | 1.0.4 | same major version. | 156 func CompatibleWith(remoteVerStr string) (bool, error) { 157 localVersion, err := gover.NewVersion(Version) 158 if err != nil { 159 return false, err 160 } 161 remoteVersion, err := gover.NewVersion(remoteVerStr) 162 if err != nil { 163 return false, err 164 } 165 return (localVersion.Segments()[0] == remoteVersion.Segments()[0]), nil 166 }