github.com/braveheart12/insolar-09-08-19@v0.8.7/pulsar/networking.go (about)

     1  /*
     2   *    Copyright 2019 Insolar Technologies
     3   *
     4   *    Licensed under the Apache License, Version 2.0 (the "License");
     5   *    you may not use this file except in compliance with the License.
     6   *    You may obtain a copy of the License at
     7   *
     8   *        http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   *    Unless required by applicable law or agreed to in writing, software
    11   *    distributed under the License is distributed on an "AS IS" BASIS,
    12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *    See the License for the specific language governing permissions and
    14   *    limitations under the License.
    15   */
    16  
    17  package pulsar
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"github.com/insolar/insolar/core"
    24  	"github.com/insolar/insolar/instrumentation/inslogger"
    25  	"github.com/insolar/insolar/instrumentation/instracer"
    26  	"github.com/insolar/insolar/log"
    27  	"github.com/insolar/insolar/pulsar/entropygenerator"
    28  	"github.com/pkg/errors"
    29  )
    30  
    31  // Handler is a wrapper for rpc-calls
    32  // It contains rpc-methods logic and pulsar's methods
    33  //
    34  type Handler struct {
    35  	Pulsar *Pulsar
    36  }
    37  
    38  // NewHandler is a constructor of Handler
    39  func NewHandler(pulsar *Pulsar) *Handler {
    40  	return &Handler{Pulsar: pulsar}
    41  }
    42  
    43  func (handler *Handler) isRequestValid(ctx context.Context, request *Payload) (success bool, neighbour *Neighbour, err error) {
    44  	ctx, span := instracer.StartSpan(ctx, "Pulsar.Handler.isRequestValid")
    45  	defer span.End()
    46  
    47  	if handler.Pulsar.IsStateFailed() {
    48  		return false, nil, nil
    49  	}
    50  
    51  	neighbour, err = handler.Pulsar.FetchNeighbour(request.PublicKey)
    52  	if err != nil {
    53  		inslogger.FromContext(ctx).Warn("Message from unknown host %v", request.PublicKey)
    54  		return false, neighbour, err
    55  	}
    56  
    57  	result, err := handler.Pulsar.checkPayloadSignature(request)
    58  	if err != nil {
    59  		inslogger.FromContext(ctx).Warnf("Message %v, from host %v failed with error %v", request.Body, request.PublicKey, err)
    60  		return false, neighbour, err
    61  	}
    62  	if !result {
    63  		inslogger.FromContext(ctx).Warnf("Message %v, from host %v failed signature check", request.Body, request.PublicKey)
    64  		return false, neighbour, errors.New("signature check failed")
    65  	}
    66  
    67  	return true, neighbour, nil
    68  }
    69  
    70  // HealthCheck is a handler of call with nil-payload
    71  // It uses for checking connection status between pulsars
    72  func (handler *Handler) HealthCheck(request *Payload, response *Payload) error {
    73  	log.Debug("[HealthCheck]")
    74  	return nil
    75  }
    76  
    77  // MakeHandshake is a handler of call with handshake purpose
    78  func (handler *Handler) MakeHandshake(request *Payload, response *Payload) error {
    79  	ctx, inslog := inslogger.WithTraceField(context.Background(), handler.Pulsar.ID)
    80  	_, span := instracer.StartSpan(ctx, "Pulsar.Handler.MakeHandshake")
    81  	defer span.End()
    82  
    83  	inslog.Infof("[MakeHandshake] from %v", request.PublicKey)
    84  	neighbour, err := handler.Pulsar.FetchNeighbour(request.PublicKey)
    85  	if err != nil {
    86  		inslog.Warn("Message from unknown host %v", request.PublicKey)
    87  		return err
    88  	}
    89  
    90  	result, err := handler.Pulsar.checkPayloadSignature(request)
    91  	if err != nil {
    92  		inslog.Warnf("Message %v, from host %v failed with error %v", request.Body, request.PublicKey, err)
    93  		return err
    94  	}
    95  	if !result {
    96  		inslog.Warnf("Message %v, from host %v failed signature check")
    97  		return err
    98  	}
    99  
   100  	generator := entropygenerator.StandardEntropyGenerator{}
   101  	message, err := handler.Pulsar.preparePayload(&HandshakePayload{Entropy: generator.GenerateEntropy()})
   102  	if err != nil {
   103  		inslog.Error(err)
   104  		return err
   105  	}
   106  	*response = *message
   107  
   108  	neighbour.OutgoingClient.Lock()
   109  
   110  	if neighbour.OutgoingClient.IsInitialised() {
   111  		neighbour.OutgoingClient.Unlock()
   112  		return nil
   113  	}
   114  	err = neighbour.OutgoingClient.CreateConnection(neighbour.ConnectionType, neighbour.ConnectionAddress)
   115  	neighbour.OutgoingClient.Unlock()
   116  	if err != nil {
   117  		inslog.Error(err)
   118  		return err
   119  	}
   120  	inslog.Infof("Pulsar - %v connected to - %v", handler.Pulsar.Config.MainListenerAddress, neighbour.ConnectionAddress)
   121  	return nil
   122  }
   123  
   124  // ReceiveSignatureForEntropy is a handler of call for receiving Sign of Entropy from one of the pulsars
   125  func (handler *Handler) ReceiveSignatureForEntropy(request *Payload, response *Payload) error {
   126  	ctx, inslog := inslogger.WithTraceField(context.Background(), handler.Pulsar.ID)
   127  	ctx, span := instracer.StartSpan(ctx, "Pulsar.Handler.ReceiveSignatureForEntropy")
   128  	defer span.End()
   129  
   130  	inslog.Infof("[ReceiveSignatureForEntropy] from %v", request.PublicKey)
   131  	ok, _, err := handler.isRequestValid(ctx, request)
   132  	if !ok {
   133  		if err != nil {
   134  			inslog.Error(err)
   135  		}
   136  		return err
   137  	}
   138  
   139  	requestBody := request.Body.(*EntropySignaturePayload)
   140  	if requestBody.PulseNumber <= handler.Pulsar.GetLastPulse().PulseNumber {
   141  		return errors.New("last pulse number is bigger than received one")
   142  	}
   143  
   144  	if handler.Pulsar.StateSwitcher.GetState() < GenerateEntropy {
   145  		err = handler.Pulsar.StartConsensusProcess(ctx, requestBody.PulseNumber)
   146  		if err != nil {
   147  			handler.Pulsar.StateSwitcher.SwitchToState(ctx, Failed, err)
   148  			return nil
   149  		}
   150  	}
   151  
   152  	bftCell := &BftCell{}
   153  	bftCell.SetSign(requestBody.EntropySignature)
   154  	handler.Pulsar.AddItemToVector(request.PublicKey, bftCell)
   155  
   156  	return nil
   157  }
   158  
   159  // ReceiveEntropy is a handler of call for receiving Entropy from one of the pulsars
   160  func (handler *Handler) ReceiveEntropy(request *Payload, response *Payload) error {
   161  	ctx, inslog := inslogger.WithTraceField(context.Background(), fmt.Sprintf("%v_%v", handler.Pulsar.ID, string(handler.Pulsar.ProcessingPulseNumber)))
   162  	ctx, span := instracer.StartSpan(ctx, "Pulsar.Handler.ReceiveEntropy")
   163  	defer span.End()
   164  
   165  	inslog.Infof("[ReceiveEntropy] from %v", request.PublicKey)
   166  	ok, _, err := handler.isRequestValid(ctx, request)
   167  	if !ok {
   168  		if err != nil {
   169  			log.Error(err)
   170  		}
   171  		return err
   172  	}
   173  
   174  	requestBody := request.Body.(*EntropyPayload)
   175  	if requestBody.PulseNumber != handler.Pulsar.ProcessingPulseNumber {
   176  		return errors.Errorf("processing pulse number - %v is bigger than received one - %v", requestBody.PulseNumber, handler.Pulsar.ProcessingPulseNumber)
   177  	}
   178  
   179  	if btfCell, ok := handler.Pulsar.GetItemFromVector(request.PublicKey); ok {
   180  
   181  		publicKey, err := handler.Pulsar.KeyProcessor.ImportPublicKeyPEM([]byte(request.PublicKey))
   182  		if err != nil {
   183  			inslog.Errorf("[ReceiveEntropy] %v", err)
   184  			return err
   185  		}
   186  
   187  		isVerified := handler.Pulsar.CryptographyService.Verify(publicKey, core.SignatureFromBytes(btfCell.GetSign()), requestBody.Entropy[:])
   188  		if err != nil || !isVerified {
   189  			handler.Pulsar.AddItemToVector(request.PublicKey, nil)
   190  			inslog.Errorf("signature and Entropy aren't matched")
   191  			return errors.New("signature and Entropy aren't matched")
   192  		}
   193  
   194  		btfCell.SetEntropy(requestBody.Entropy)
   195  		btfCell.SetIsEntropyReceived(true)
   196  	}
   197  
   198  	return nil
   199  }
   200  
   201  // ReceiveVector is a handler of call for receiving vector of Entropy
   202  func (handler *Handler) ReceiveVector(request *Payload, response *Payload) error {
   203  	ctx, inslog := inslogger.WithTraceField(context.Background(), fmt.Sprintf("%v_%v", handler.Pulsar.ID, string(handler.Pulsar.ProcessingPulseNumber)))
   204  	ctx, span := instracer.StartSpan(ctx, "Pulsar.Handler.ReceiveVector")
   205  	defer span.End()
   206  
   207  	log.Infof("[ReceiveVector] from %v", request.PublicKey)
   208  	ok, _, err := handler.isRequestValid(ctx, request)
   209  	if !ok {
   210  		if err != nil {
   211  			inslog.Errorf("%v - %v", handler.Pulsar.Config.MainListenerAddress, err)
   212  		}
   213  		return err
   214  	}
   215  
   216  	state := handler.Pulsar.StateSwitcher.GetState()
   217  	if state >= Verifying {
   218  		return errors.New("pulsar is in the bft state")
   219  	}
   220  
   221  	requestBody := request.Body.(*VectorPayload)
   222  	if requestBody.PulseNumber != handler.Pulsar.ProcessingPulseNumber {
   223  		return errors.Errorf("processing pulse number - %v is bigger than received one - %v", requestBody.PulseNumber, handler.Pulsar.ProcessingPulseNumber)
   224  	}
   225  
   226  	handler.Pulsar.SetBftGridItem(request.PublicKey, requestBody.Vector)
   227  
   228  	return nil
   229  }
   230  
   231  // ReceiveChosenSignature is a handler of call with the confirmation signature
   232  func (handler *Handler) ReceiveChosenSignature(request *Payload, response *Payload) error {
   233  	ctx, inslog := inslogger.WithTraceField(context.Background(), fmt.Sprintf("%v_%v", handler.Pulsar.ID, string(handler.Pulsar.ProcessingPulseNumber)))
   234  	ctx, span := instracer.StartSpan(ctx, "Pulsar.Handler.ReceiveChosenSignature")
   235  	defer span.End()
   236  
   237  	log.Infof("[ReceiveChosenSignature] from %v", request.PublicKey)
   238  	ok, _, err := handler.isRequestValid(ctx, request)
   239  	if !ok {
   240  		if err != nil {
   241  			inslog.Error(err)
   242  		}
   243  		return err
   244  	}
   245  
   246  	requestBody := request.Body.(*PulseSenderConfirmationPayload)
   247  	if requestBody.PulseNumber != handler.Pulsar.ProcessingPulseNumber {
   248  		return errors.Errorf("processing pulse number - %v is bigger than received one - %v", requestBody.PulseNumber, handler.Pulsar.ProcessingPulseNumber)
   249  	}
   250  
   251  	publicKey, err := handler.Pulsar.KeyProcessor.ImportPublicKeyPEM([]byte(request.PublicKey))
   252  	if err != nil {
   253  		inslog.Errorf("[ReceiveEntropy] %v", err)
   254  		return err
   255  	}
   256  
   257  	payload := PulseSenderConfirmationPayload{
   258  		core.PulseSenderConfirmation{
   259  			ChosenPublicKey: requestBody.ChosenPublicKey,
   260  			Entropy:         requestBody.Entropy,
   261  			PulseNumber:     requestBody.PulseNumber,
   262  		},
   263  	}
   264  
   265  	hashProvider := handler.Pulsar.PlatformCryptographyScheme.IntegrityHasher()
   266  	hash, err := payload.Hash(hashProvider)
   267  	if err != nil {
   268  		inslog.Errorf("[ReceiveEntropy] %v", err)
   269  		return err
   270  	}
   271  
   272  	isVerified := handler.Pulsar.CryptographyService.Verify(publicKey, core.SignatureFromBytes(requestBody.Signature), hash)
   273  
   274  	if !isVerified {
   275  		inslog.Errorf("signature and chosen publicKey aren't matched")
   276  		return errors.New("signature check failed")
   277  	}
   278  
   279  	handler.Pulsar.currentSlotSenderConfirmationsLock.Lock()
   280  	handler.Pulsar.CurrentSlotSenderConfirmations[request.PublicKey] = core.PulseSenderConfirmation{
   281  		ChosenPublicKey: requestBody.ChosenPublicKey,
   282  		Signature:       requestBody.Signature,
   283  		PulseNumber:     requestBody.PulseNumber,
   284  		Entropy:         requestBody.Entropy,
   285  	}
   286  	handler.Pulsar.currentSlotSenderConfirmationsLock.Unlock()
   287  	return nil
   288  }
   289  
   290  // ReceivePulse is a handler of call with the freshest pulse
   291  func (handler *Handler) ReceivePulse(request *Payload, response *Payload) error {
   292  	ctx, inslog := inslogger.WithTraceField(context.Background(), fmt.Sprintf("%v_%v", handler.Pulsar.ID, string(handler.Pulsar.ProcessingPulseNumber)))
   293  	ctx, span := instracer.StartSpan(ctx, "Pulsar.Handler.ReceivePulse")
   294  	defer span.End()
   295  
   296  	log.Infof("[ReceivePulse] from %v", request.PublicKey)
   297  	ok, _, err := handler.isRequestValid(ctx, request)
   298  	if !ok {
   299  		if err != nil {
   300  			inslog.Error(err)
   301  		}
   302  		return err
   303  	}
   304  
   305  	requestBody := request.Body.(*PulsePayload)
   306  	if handler.Pulsar.ProcessingPulseNumber != 0 && requestBody.Pulse.PulseNumber != handler.Pulsar.ProcessingPulseNumber {
   307  		return errors.Errorf("processing pulse number is not zero and received number is not the same")
   308  	}
   309  
   310  	if handler.Pulsar.ProcessingPulseNumber == 0 && requestBody.Pulse.PulseNumber < handler.Pulsar.GetLastPulse().PulseNumber {
   311  		return errors.Errorf("last pulse number - %v is bigger than received one - %v", handler.Pulsar.GetLastPulse().PulseNumber, requestBody.Pulse.PulseNumber)
   312  	}
   313  
   314  	err = handler.Pulsar.Storage.SetLastPulse(&requestBody.Pulse)
   315  	if err != nil {
   316  		log.Error(err)
   317  		return err
   318  	}
   319  	err = handler.Pulsar.Storage.SavePulse(&requestBody.Pulse)
   320  	if err != nil {
   321  		log.Error(err)
   322  		return err
   323  	}
   324  
   325  	handler.Pulsar.SetLastPulse(&requestBody.Pulse)
   326  	handler.Pulsar.ProcessingPulseNumber = 0
   327  
   328  	return nil
   329  }