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  }