github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/contracts/release/release.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package release contains the node service that tracks client releases. 18 package release 19 20 //go:generate abigen --sol ./contract.sol --pkg release --out ./contract.go 21 22 import ( 23 "fmt" 24 "strings" 25 "time" 26 27 "github.com/atheioschain/go-atheios/accounts/abi/bind" 28 "github.com/atheioschain/go-atheios/common" 29 "github.com/atheioschain/go-atheios/eth" 30 "github.com/atheioschain/go-atheios/internal/ethapi" 31 "github.com/atheioschain/go-atheios/les" 32 "github.com/atheioschain/go-atheios/logger" 33 "github.com/atheioschain/go-atheios/logger/glog" 34 "github.com/atheioschain/go-atheios/node" 35 "github.com/atheioschain/go-atheios/p2p" 36 "github.com/atheioschain/go-atheios/rpc" 37 "golang.org/x/net/context" 38 ) 39 40 // Interval to check for new releases 41 const releaseRecheckInterval = time.Hour 42 43 // Config contains the configurations of the release service. 44 type Config struct { 45 Oracle common.Address // Ethereum address of the release oracle 46 Major uint32 // Major version component of the release 47 Minor uint32 // Minor version component of the release 48 Patch uint32 // Patch version component of the release 49 Commit [20]byte // Git SHA1 commit hash of the release 50 } 51 52 // ReleaseService is a node service that periodically checks the blockchain for 53 // newly released versions of the client being run and issues a warning to the 54 // user about it. 55 type ReleaseService struct { 56 config Config // Current version to check releases against 57 oracle *ReleaseOracle // Native binding to the release oracle contract 58 quit chan chan error // Quit channel to terminate the version checker 59 } 60 61 // NewReleaseService creates a new service to periodically check for new client 62 // releases and notify the user of such. 63 func NewReleaseService(ctx *node.ServiceContext, config Config) (node.Service, error) { 64 // Retrieve the Ethereum service dependency to access the blockchain 65 var apiBackend ethapi.Backend 66 var ethereum *eth.Ethereum 67 if err := ctx.Service(ðereum); err == nil { 68 apiBackend = ethereum.ApiBackend 69 } else { 70 var ethereum *les.LightEthereum 71 if err := ctx.Service(ðereum); err == nil { 72 apiBackend = ethereum.ApiBackend 73 } else { 74 return nil, err 75 } 76 } 77 // Construct the release service 78 contract, err := NewReleaseOracle(config.Oracle, eth.NewContractBackend(apiBackend)) 79 if err != nil { 80 return nil, err 81 } 82 return &ReleaseService{ 83 config: config, 84 oracle: contract, 85 quit: make(chan chan error), 86 }, nil 87 } 88 89 // Protocols returns an empty list of P2P protocols as the release service does 90 // not have a networking component. 91 func (r *ReleaseService) Protocols() []p2p.Protocol { return nil } 92 93 // APIs returns an empty list of RPC descriptors as the release service does not 94 // expose any functioanlity to the outside world. 95 func (r *ReleaseService) APIs() []rpc.API { return nil } 96 97 // Start spawns the periodic version checker goroutine 98 func (r *ReleaseService) Start(server *p2p.Server) error { 99 go r.checker() 100 return nil 101 } 102 103 // Stop terminates all goroutines belonging to the service, blocking until they 104 // are all terminated. 105 func (r *ReleaseService) Stop() error { 106 errc := make(chan error) 107 r.quit <- errc 108 return <-errc 109 } 110 111 // checker runs indefinitely in the background, periodically checking for new 112 // client releases. 113 func (r *ReleaseService) checker() { 114 // Set up the timers to periodically check for releases 115 timer := time.NewTimer(0) // Immediately fire a version check 116 defer timer.Stop() 117 118 for { 119 select { 120 // If the time arrived, check for a new release 121 case <-timer.C: 122 // Rechedule the timer before continuing 123 timer.Reset(releaseRecheckInterval) 124 125 // Retrieve the current version, and handle missing contracts gracefully 126 ctx, _ := context.WithTimeout(context.Background(), time.Second*5) 127 opts := &bind.CallOpts{Context: ctx} 128 version, err := r.oracle.CurrentVersion(opts) 129 if err != nil { 130 if err == bind.ErrNoCode { 131 glog.V(logger.Debug).Infof("Release oracle not found at %x", r.config.Oracle) 132 continue 133 } 134 glog.V(logger.Error).Infof("Failed to retrieve current release: %v", err) 135 continue 136 } 137 // Version was successfully retrieved, notify if newer than ours 138 if version.Major > r.config.Major || 139 (version.Major == r.config.Major && version.Minor > r.config.Minor) || 140 (version.Major == r.config.Major && version.Minor == r.config.Minor && version.Patch > r.config.Patch) { 141 142 warning := fmt.Sprintf("Client v%d.%d.%d-%x seems older than the latest upstream release v%d.%d.%d-%x", 143 r.config.Major, r.config.Minor, r.config.Patch, r.config.Commit[:4], version.Major, version.Minor, version.Patch, version.Commit[:4]) 144 howtofix := fmt.Sprintf("Please check https://github.com/atheioschain/go-atheios/releases for new releases") 145 separator := strings.Repeat("-", len(warning)) 146 147 glog.V(logger.Warn).Info(separator) 148 glog.V(logger.Warn).Info(warning) 149 glog.V(logger.Warn).Info(howtofix) 150 glog.V(logger.Warn).Info(separator) 151 } else { 152 glog.V(logger.Debug).Infof("Client v%d.%d.%d-%x seems up to date with upstream v%d.%d.%d-%x", 153 r.config.Major, r.config.Minor, r.config.Patch, r.config.Commit[:4], version.Major, version.Minor, version.Patch, version.Commit[:4]) 154 } 155 156 // If termination was requested, return 157 case errc := <-r.quit: 158 errc <- nil 159 return 160 } 161 } 162 }