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 }