github.com/braveheart12/insolar-09-08-19@v0.8.7/network/servicenetwork/servicenetwork.go (about) 1 /* 2 * The Clear BSD License 3 * 4 * Copyright (c) 2019 Insolar Technologies 5 * 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met: 9 * 10 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 * Neither the name of Insolar Technologies nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 * 14 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 * 16 */ 17 18 package servicenetwork 19 20 import ( 21 "context" 22 "strconv" 23 "strings" 24 "sync" 25 "time" 26 27 "github.com/insolar/insolar/component" 28 "github.com/insolar/insolar/configuration" 29 "github.com/insolar/insolar/consensus/packets" 30 "github.com/insolar/insolar/consensus/phases" 31 "github.com/insolar/insolar/core" 32 "github.com/insolar/insolar/instrumentation/inslogger" 33 "github.com/insolar/insolar/instrumentation/instracer" 34 "github.com/insolar/insolar/log" 35 "github.com/insolar/insolar/network" 36 "github.com/insolar/insolar/network/controller" 37 "github.com/insolar/insolar/network/controller/bootstrap" 38 "github.com/insolar/insolar/network/hostnetwork" 39 "github.com/insolar/insolar/network/merkle" 40 "github.com/insolar/insolar/network/routing" 41 "github.com/insolar/insolar/network/utils" 42 "github.com/pkg/errors" 43 "go.opencensus.io/trace" 44 ) 45 46 // ServiceNetwork is facade for network. 47 type ServiceNetwork struct { 48 cfg configuration.Configuration 49 cm *component.Manager 50 51 hostNetwork network.HostNetwork // TODO: should be injected 52 routingTable network.RoutingTable // TODO: should be injected 53 54 // dependencies 55 CertificateManager core.CertificateManager `inject:""` 56 PulseManager core.PulseManager `inject:""` 57 PulseStorage core.PulseStorage `inject:""` 58 CryptographyService core.CryptographyService `inject:""` 59 NetworkCoordinator core.NetworkCoordinator `inject:""` 60 CryptographyScheme core.PlatformCryptographyScheme `inject:""` 61 NodeKeeper network.NodeKeeper `inject:""` 62 NetworkSwitcher core.NetworkSwitcher `inject:""` 63 TerminationHandler core.TerminationHandler `inject:""` 64 65 // subcomponents 66 PhaseManager phases.PhaseManager `inject:"subcomponent"` 67 Controller network.Controller `inject:"subcomponent"` 68 69 isGenesis bool 70 isDiscovery bool 71 skip int 72 73 lock sync.Mutex 74 } 75 76 // NewServiceNetwork returns a new ServiceNetwork. 77 func NewServiceNetwork(conf configuration.Configuration, rootCm *component.Manager, isGenesis bool) (*ServiceNetwork, error) { 78 serviceNetwork := &ServiceNetwork{cm: component.NewManager(rootCm), cfg: conf, isGenesis: isGenesis, skip: conf.Service.Skip} 79 return serviceNetwork, nil 80 } 81 82 // SendMessage sends a message from MessageBus. 83 func (n *ServiceNetwork) SendMessage(nodeID core.RecordRef, method string, msg core.Parcel) ([]byte, error) { 84 return n.Controller.SendMessage(nodeID, method, msg) 85 } 86 87 // SendCascadeMessage sends a message from MessageBus to a cascade of nodes 88 func (n *ServiceNetwork) SendCascadeMessage(data core.Cascade, method string, msg core.Parcel) error { 89 return n.Controller.SendCascadeMessage(data, method, msg) 90 } 91 92 // RemoteProcedureRegister registers procedure for remote call on this host. 93 func (n *ServiceNetwork) RemoteProcedureRegister(name string, method core.RemoteProcedure) { 94 n.Controller.RemoteProcedureRegister(name, method) 95 } 96 97 // incrementPort increments port number if it not equals 0 98 func incrementPort(address string) (string, error) { 99 parts := strings.Split(address, ":") 100 if len(parts) < 2 { 101 return address, errors.New("failed to get port from address") 102 } 103 port, err := strconv.Atoi(parts[len(parts)-1]) 104 if err != nil { 105 return address, err 106 } 107 108 if port != 0 { 109 port++ 110 } 111 112 parts = append(parts[:len(parts)-1], strconv.Itoa(port)) 113 return strings.Join(parts, ":"), nil 114 } 115 116 // Start implements component.Initer 117 func (n *ServiceNetwork) Init(ctx context.Context) error { 118 n.routingTable = &routing.Table{} 119 internalTransport, err := hostnetwork.NewInternalTransport(n.cfg, n.CertificateManager.GetCertificate().GetNodeRef().String()) 120 if err != nil { 121 return errors.Wrap(err, "Failed to create internal transport") 122 } 123 124 var consensusAddress string 125 if n.cfg.Host.Transport.FixedPublicAddress != "" { 126 // workaround for Consensus transport, port+=1 of default transport 127 consensusAddress, err = incrementPort(n.cfg.Host.Transport.Address) 128 if err != nil { 129 return errors.Wrap(err, "failed to increment port.") 130 } 131 } else { 132 consensusAddress = n.NodeKeeper.GetOrigin().ConsensusAddress() 133 } 134 135 consensusNetwork, err := hostnetwork.NewConsensusNetwork( 136 consensusAddress, 137 n.CertificateManager.GetCertificate().GetNodeRef().String(), 138 n.NodeKeeper.GetOrigin().ShortID(), 139 n.routingTable, 140 ) 141 if err != nil { 142 return errors.Wrap(err, "Failed to create consensus network.") 143 } 144 145 n.hostNetwork = hostnetwork.NewHostTransport(internalTransport, n.routingTable) 146 options := controller.ConfigureOptions(n.cfg) 147 148 cert := n.CertificateManager.GetCertificate() 149 n.isDiscovery = utils.OriginIsDiscovery(cert) 150 151 n.cm.Inject(n, 152 cert, 153 n.NodeKeeper, 154 merkle.NewCalculator(), 155 consensusNetwork, 156 phases.NewCommunicator(), 157 phases.NewFirstPhase(), 158 phases.NewSecondPhase(), 159 phases.NewThirdPhase(), 160 phases.NewPhaseManager(), 161 bootstrap.NewSessionManager(), 162 controller.NewNetworkController(n.hostNetwork), 163 controller.NewRPCController(options, n.hostNetwork), 164 controller.NewPulseController(n.hostNetwork, n.routingTable), 165 bootstrap.NewBootstrapper(options, internalTransport), 166 bootstrap.NewAuthorizationController(options, internalTransport), 167 bootstrap.NewChallengeResponseController(options, internalTransport), 168 bootstrap.NewNetworkBootstrapper(), 169 ) 170 err = n.cm.Init(ctx) 171 if err != nil { 172 return errors.Wrap(err, "Failed to init internal components") 173 } 174 175 return nil 176 } 177 178 // Start implements component.Starter 179 func (n *ServiceNetwork) Start(ctx context.Context) error { 180 logger := inslogger.FromContext(ctx) 181 182 logger.Info("Network starts listening...") 183 n.routingTable.Inject(n.NodeKeeper) 184 n.hostNetwork.Start(ctx) 185 186 log.Info("Starting network component manager...") 187 err := n.cm.Start(ctx) 188 if err != nil { 189 return errors.Wrap(err, "Failed to bootstrap network") 190 } 191 192 log.Info("Bootstrapping network...") 193 _, err = n.Controller.Bootstrap(ctx) 194 if err != nil { 195 return errors.Wrap(err, "Failed to bootstrap network") 196 } 197 198 logger.Info("Service network started") 199 return nil 200 } 201 202 func (n *ServiceNetwork) Leave(ctx context.Context, ETA core.PulseNumber) { 203 logger := inslogger.FromContext(ctx) 204 logger.Info("Gracefully stopping service network") 205 206 n.NodeKeeper.AddPendingClaim(&packets.NodeLeaveClaim{ETA: ETA}) 207 } 208 209 // Stop implements core.Component 210 func (n *ServiceNetwork) Stop(ctx context.Context) error { 211 logger := inslogger.FromContext(ctx) 212 213 logger.Info("Stopping network components") 214 if err := n.cm.Stop(ctx); err != nil { 215 log.Errorf("Error while stopping network components: %s", err.Error()) 216 } 217 logger.Info("Stopping host network") 218 n.hostNetwork.Stop() 219 return nil 220 } 221 222 func (n *ServiceNetwork) HandlePulse(ctx context.Context, newPulse core.Pulse) { 223 currentTime := time.Now() 224 225 n.lock.Lock() 226 defer n.lock.Unlock() 227 228 if n.isGenesis { 229 return 230 } 231 traceID := "pulse_" + strconv.FormatUint(uint64(newPulse.PulseNumber), 10) 232 ctx, logger := inslogger.WithTraceField(ctx, traceID) 233 logger.Infof("Got new pulse number: %d", newPulse.PulseNumber) 234 ctx, span := instracer.StartSpan(ctx, "ServiceNetwork.Handlepulse") 235 span.AddAttributes( 236 trace.Int64Attribute("pulse.PulseNumber", int64(newPulse.PulseNumber)), 237 ) 238 defer span.End() 239 240 if !n.NodeKeeper.IsBootstrapped() { 241 n.Controller.SetLastIgnoredPulse(newPulse.NextPulseNumber) 242 return 243 } 244 if n.shoudIgnorePulse(newPulse) { 245 log.Infof("Ignore pulse %d: network is not yet initialized", newPulse.PulseNumber) 246 return 247 } 248 249 if n.NodeKeeper.GetState() == core.WaitingNodeNetworkState { 250 // do not set pulse because otherwise we will set invalid active list 251 // pass consensus, prepare valid active list and set it on next pulse 252 go n.phaseManagerOnPulse(ctx, newPulse, currentTime) 253 return 254 } 255 256 // Ignore core.ErrNotFound because 257 // sometimes we can't fetch current pulse in new nodes 258 // (for fresh bootstrapped light-material with in-memory pulse-tracker) 259 if currentPulse, err := n.PulseStorage.Current(ctx); err != nil { 260 if err != core.ErrNotFound { 261 logger.Fatalf("Could not get current pulse: %s", err.Error()) 262 } 263 } else { 264 if !isNextPulse(currentPulse, &newPulse) { 265 logger.Infof("Incorrect pulse number. Current: %+v. New: %+v", currentPulse, newPulse) 266 return 267 } 268 } 269 270 err := n.NetworkSwitcher.OnPulse(ctx, newPulse) 271 if err != nil { 272 logger.Error(errors.Wrap(err, "Failed to call OnPulse on NetworkSwitcher")) 273 } 274 275 logger.Debugf("Before set new current pulse number: %d", newPulse.PulseNumber) 276 err = n.PulseManager.Set(ctx, newPulse, n.NetworkSwitcher.GetState() == core.CompleteNetworkState) 277 if err != nil { 278 logger.Fatalf("Failed to set new pulse: %s", err.Error()) 279 } 280 logger.Infof("Set new current pulse number: %d", newPulse.PulseNumber) 281 282 go n.phaseManagerOnPulse(ctx, newPulse, currentTime) 283 } 284 285 func (n *ServiceNetwork) shoudIgnorePulse(newPulse core.Pulse) bool { 286 return n.isDiscovery && n.NodeKeeper.GetState() != core.WaitingNodeNetworkState && 287 newPulse.PulseNumber <= n.Controller.GetLastIgnoredPulse()+core.PulseNumber(n.skip) 288 } 289 290 func (n *ServiceNetwork) phaseManagerOnPulse(ctx context.Context, newPulse core.Pulse, pulseStartTime time.Time) { 291 logger := inslogger.FromContext(ctx) 292 293 if err := n.PhaseManager.OnPulse(ctx, &newPulse, pulseStartTime); err != nil { 294 errMsg := "Failed to pass consensus: " + err.Error() 295 logger.Error(errMsg) 296 n.TerminationHandler.Abort(errMsg) 297 } 298 } 299 300 func isNextPulse(currentPulse, newPulse *core.Pulse) bool { 301 return newPulse.PulseNumber > currentPulse.PulseNumber && newPulse.PulseNumber >= currentPulse.NextPulseNumber 302 }