1 // package version provide the version info for the node, and also provide
2 // support for version compatibility check and update notification.
4 // The version format should follow Semantic Versioning (https://semver.org/):
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.
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.
13 // 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.
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.
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.
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.
32 gover "github.com/hashicorp/go-version"
33 log "github.com/sirupsen/logrus"
34 "gopkg.in/fatih/set.v0"
38 // If needing to edit the iota, please ensure the following:
42 noUpdate uint16 = iota
49 // The full version string
51 // GitCommit is set with --ldflags "-X main.gitCommit=$(git rev-parse HEAD)"
58 Version += "+" + GitCommit[:8]
60 Status = &UpdateStatus{
64 versionStatus: noUpdate,
68 type UpdateStatus struct {
76 func (s *UpdateStatus) AddSeed(seedAddr string) {
79 s.seedSet.Add(seedAddr)
82 // CheckUpdate checks whether there is a newer version to update.
83 // If there is, it set the "Status" variable to a proper value.
85 // localVerStr: the version of the node itself
86 // remoteVerStr: the version received from a seed node.
87 // remoteAddr: the version received from a seed node.
89 // 1. small update: seed version is higher than the node itself
90 // 2. significant update: seed mojor version is higher than the node itself
91 func (s *UpdateStatus) CheckUpdate(localVerStr string, remoteVerStr string, remoteAddr string) error {
95 if !s.seedSet.Has(remoteAddr) {
99 localVersion, err := gover.NewVersion(localVerStr)
103 remoteVersion, err := gover.NewVersion(remoteVerStr)
107 if remoteVersion.GreaterThan(localVersion) {
108 if s.versionStatus == noUpdate {
109 s.versionStatus = hasUpdate
112 maxVersion, err := gover.NewVersion(s.maxVerSeen)
117 if remoteVersion.GreaterThan(maxVersion) {
118 s.maxVerSeen = remoteVerStr
121 if remoteVersion.Segments()[0] > localVersion.Segments()[0] {
122 s.versionStatus = hasMUpdate
124 if s.versionStatus != noUpdate {
125 log.WithFields(log.Fields{
127 "Current version": localVerStr,
128 "Newer version": remoteVerStr,
130 }).Warn("Please update your bytomd via https://github.com/Bytom/bytom/releases/ or http://bytom.io/wallet/")
136 func (s *UpdateStatus) MaxVerSeen() string {
142 func (s *UpdateStatus) VersionStatus() uint16 {
145 return s.versionStatus
148 // CompatibleWith checks whether the remote peer version is compatible with the
151 // | local | remote |
153 // | 1.0.3 | same major&moinor version. |
154 // | 1.0.4 | same major version. |
155 func CompatibleWith(remoteVerStr string) (bool, error) {
156 localVersion, err := gover.NewVersion(Version)
160 remoteVersion, err := gover.NewVersion(remoteVerStr)
164 return (localVersion.Segments()[0] == remoteVersion.Segments()[0]), nil