github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/gossip/discovery/discovery_impl.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package discovery 8 9 import ( 10 "bytes" 11 "fmt" 12 "math" 13 "strconv" 14 "strings" 15 "sync" 16 "time" 17 18 "github.com/hechain20/hechain/gossip/common" 19 "github.com/hechain20/hechain/gossip/gossip/msgstore" 20 "github.com/hechain20/hechain/gossip/protoext" 21 "github.com/hechain20/hechain/gossip/util" 22 proto "github.com/hyperledger/fabric-protos-go/gossip" 23 "github.com/pkg/errors" 24 ) 25 26 const ( 27 DefAliveTimeInterval = 5 * time.Second 28 DefAliveExpirationTimeout = 5 * DefAliveTimeInterval 29 DefAliveExpirationCheckInterval = DefAliveExpirationTimeout / 10 30 DefReconnectInterval = DefAliveExpirationTimeout 31 DefMsgExpirationFactor = 20 32 DefMaxConnectionAttempts = 120 33 ) 34 35 type timestamp struct { 36 incTime time.Time 37 seqNum uint64 38 lastSeen time.Time 39 } 40 41 func (ts *timestamp) String() string { 42 return fmt.Sprintf("%v, %v", ts.incTime.UnixNano(), ts.seqNum) 43 } 44 45 type gossipDiscoveryImpl struct { 46 incTime uint64 47 seqNum uint64 48 self NetworkMember 49 deadLastTS map[string]*timestamp // H 50 aliveLastTS map[string]*timestamp // V 51 id2Member map[string]*NetworkMember // all known members 52 aliveMembership *util.MembershipStore 53 deadMembership *util.MembershipStore 54 selfAliveMessage *protoext.SignedGossipMessage 55 56 msgStore *aliveMsgStore 57 58 comm CommService 59 crypt CryptoService 60 lock *sync.RWMutex 61 62 toDieChan chan struct{} 63 port int 64 logger util.Logger 65 disclosurePolicy DisclosurePolicy 66 pubsub *util.PubSub 67 68 aliveTimeInterval time.Duration 69 aliveExpirationTimeout time.Duration 70 aliveExpirationCheckInterval time.Duration 71 reconnectInterval time.Duration 72 msgExpirationFactor int 73 maxConnectionAttempts int 74 75 bootstrapPeers []string 76 anchorPeerTracker AnchorPeerTracker 77 } 78 79 type DiscoveryConfig struct { 80 AliveTimeInterval time.Duration 81 AliveExpirationTimeout time.Duration 82 AliveExpirationCheckInterval time.Duration 83 ReconnectInterval time.Duration 84 MaxConnectionAttempts int 85 MsgExpirationFactor int 86 BootstrapPeers []string 87 } 88 89 // NewDiscoveryService returns a new discovery service with the comm module passed and the crypto service passed 90 func NewDiscoveryService(self NetworkMember, comm CommService, crypt CryptoService, disPol DisclosurePolicy, 91 config DiscoveryConfig, anchorPeerTracker AnchorPeerTracker, logger util.Logger) Discovery { 92 d := &gossipDiscoveryImpl{ 93 self: self, 94 incTime: uint64(time.Now().UnixNano()), 95 seqNum: uint64(0), 96 deadLastTS: make(map[string]*timestamp), 97 aliveLastTS: make(map[string]*timestamp), 98 id2Member: make(map[string]*NetworkMember), 99 aliveMembership: util.NewMembershipStore(), 100 deadMembership: util.NewMembershipStore(), 101 crypt: crypt, 102 comm: comm, 103 lock: &sync.RWMutex{}, 104 toDieChan: make(chan struct{}), 105 logger: logger, 106 disclosurePolicy: disPol, 107 pubsub: util.NewPubSub(), 108 109 aliveTimeInterval: config.AliveTimeInterval, 110 aliveExpirationTimeout: config.AliveExpirationTimeout, 111 aliveExpirationCheckInterval: config.AliveExpirationCheckInterval, 112 reconnectInterval: config.ReconnectInterval, 113 maxConnectionAttempts: config.MaxConnectionAttempts, 114 msgExpirationFactor: config.MsgExpirationFactor, 115 116 bootstrapPeers: config.BootstrapPeers, 117 anchorPeerTracker: anchorPeerTracker, 118 } 119 120 d.validateSelfConfig() 121 d.msgStore = newAliveMsgStore(d) 122 123 go d.periodicalSendAlive() 124 go d.periodicalCheckAlive() 125 go d.handleMessages() 126 go d.periodicalReconnectToDead() 127 go d.handleEvents() 128 129 return d 130 } 131 132 // Lookup returns a network member, or nil if not found 133 func (d *gossipDiscoveryImpl) Lookup(PKIID common.PKIidType) *NetworkMember { 134 if bytes.Equal(PKIID, d.self.PKIid) { 135 return &d.self 136 } 137 d.lock.RLock() 138 defer d.lock.RUnlock() 139 return copyNetworkMember(d.id2Member[string(PKIID)]) 140 } 141 142 func (d *gossipDiscoveryImpl) Connect(member NetworkMember, id identifier) { 143 for _, endpoint := range []string{member.InternalEndpoint, member.Endpoint} { 144 if d.isMyOwnEndpoint(endpoint) { 145 d.logger.Debug("Skipping connecting to myself") 146 return 147 } 148 } 149 150 d.logger.Debug("Entering", member) 151 defer d.logger.Debug("Exiting") 152 go func() { 153 for i := 0; i < d.maxConnectionAttempts && !d.toDie(); i++ { 154 id, err := id() 155 if err != nil { 156 if d.toDie() { 157 return 158 } 159 d.logger.Warningf("Could not connect to %v : %v", member, err) 160 time.Sleep(d.reconnectInterval) 161 continue 162 } 163 peer := &NetworkMember{ 164 InternalEndpoint: member.InternalEndpoint, 165 Endpoint: member.Endpoint, 166 PKIid: id.ID, 167 } 168 m, err := d.createMembershipRequest(id.SelfOrg) 169 if err != nil { 170 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 171 continue 172 } 173 req, err := protoext.NoopSign(m) 174 if err != nil { 175 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 176 continue 177 } 178 req.Nonce = util.RandomUInt64() 179 req, err = protoext.NoopSign(req.GossipMessage) 180 if err != nil { 181 d.logger.Warningf("Failed adding NONCE to SignedGossipMessage %+v", errors.WithStack(err)) 182 continue 183 } 184 go d.sendUntilAcked(peer, req) 185 return 186 } 187 }() 188 } 189 190 func (d *gossipDiscoveryImpl) isMyOwnEndpoint(endpoint string) bool { 191 return endpoint == fmt.Sprintf("127.0.0.1:%d", d.port) || endpoint == fmt.Sprintf("localhost:%d", d.port) || 192 endpoint == d.self.InternalEndpoint || endpoint == d.self.Endpoint 193 } 194 195 func (d *gossipDiscoveryImpl) validateSelfConfig() { 196 endpoint := d.self.InternalEndpoint 197 if len(endpoint) == 0 { 198 d.logger.Panic("Internal endpoint is empty:", endpoint) 199 } 200 201 internalEndpointSplit := strings.Split(endpoint, ":") 202 if len(internalEndpointSplit) != 2 { 203 d.logger.Panicf("Self endpoint %s isn't formatted as 'host:port'", endpoint) 204 } 205 myPort, err := strconv.ParseInt(internalEndpointSplit[1], 10, 64) 206 if err != nil { 207 d.logger.Panicf("Self endpoint %s has not valid port, %+v", endpoint, errors.WithStack(err)) 208 } 209 210 if myPort > int64(math.MaxUint16) { 211 d.logger.Panicf("Self endpoint %s's port takes more than 16 bits", endpoint) 212 } 213 214 d.port = int(myPort) 215 } 216 217 func (d *gossipDiscoveryImpl) sendUntilAcked(peer *NetworkMember, message *protoext.SignedGossipMessage) { 218 nonce := message.Nonce 219 for i := 0; i < d.maxConnectionAttempts && !d.toDie(); i++ { 220 sub := d.pubsub.Subscribe(fmt.Sprintf("%d", nonce), time.Second*5) 221 d.comm.SendToPeer(peer, message) 222 if _, timeoutErr := sub.Listen(); timeoutErr == nil { 223 return 224 } 225 time.Sleep(d.reconnectInterval) 226 } 227 } 228 229 func (d *gossipDiscoveryImpl) InitiateSync(peerNum int) { 230 if d.toDie() { 231 return 232 } 233 var peers2SendTo []*NetworkMember 234 235 d.lock.RLock() 236 237 n := d.aliveMembership.Size() 238 k := peerNum 239 if k > n { 240 k = n 241 } 242 243 aliveMembersAsSlice := d.aliveMembership.ToSlice() 244 for _, i := range util.GetRandomIndices(k, n-1) { 245 pulledPeer := aliveMembersAsSlice[i].GetAliveMsg().Membership 246 var internalEndpoint string 247 if aliveMembersAsSlice[i].Envelope.SecretEnvelope != nil { 248 internalEndpoint = protoext.InternalEndpoint(aliveMembersAsSlice[i].Envelope.SecretEnvelope) 249 } 250 netMember := &NetworkMember{ 251 Endpoint: pulledPeer.Endpoint, 252 Metadata: pulledPeer.Metadata, 253 PKIid: pulledPeer.PkiId, 254 InternalEndpoint: internalEndpoint, 255 } 256 peers2SendTo = append(peers2SendTo, netMember) 257 } 258 259 d.lock.RUnlock() 260 261 if len(peers2SendTo) == 0 { 262 d.logger.Debugf("No peers to send to, aborting membership sync") 263 return 264 } 265 266 m, err := d.createMembershipRequest(true) 267 if err != nil { 268 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 269 return 270 } 271 memReq, err := protoext.NoopSign(m) 272 if err != nil { 273 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 274 return 275 } 276 277 for _, netMember := range peers2SendTo { 278 d.comm.SendToPeer(netMember, memReq) 279 } 280 } 281 282 func (d *gossipDiscoveryImpl) handleEvents() { 283 defer d.logger.Debug("Stopped") 284 285 for { 286 select { 287 case deadPeer := <-d.comm.PresumedDead(): 288 if d.isAlive(deadPeer) { 289 d.expireDeadMembers([]common.PKIidType{deadPeer}) 290 } 291 case changedPKIID := <-d.comm.IdentitySwitch(): 292 // If a peer changed its PKI-ID, purge the old PKI-ID 293 d.purge(changedPKIID) 294 case <-d.toDieChan: 295 return 296 } 297 } 298 } 299 300 func (d *gossipDiscoveryImpl) isAlive(pkiID common.PKIidType) bool { 301 d.lock.RLock() 302 defer d.lock.RUnlock() 303 _, alive := d.aliveLastTS[string(pkiID)] 304 return alive 305 } 306 307 func (d *gossipDiscoveryImpl) handleMessages() { 308 defer d.logger.Debug("Stopped") 309 310 in := d.comm.Accept() 311 for { 312 select { 313 case m := <-in: 314 d.handleMsgFromComm(m) 315 case <-d.toDieChan: 316 return 317 } 318 } 319 } 320 321 func (d *gossipDiscoveryImpl) handleMsgFromComm(msg protoext.ReceivedMessage) { 322 if msg == nil { 323 return 324 } 325 m := msg.GetGossipMessage() 326 if m.GetAliveMsg() == nil && m.GetMemRes() == nil && m.GetMemReq() == nil { 327 d.logger.Warning("Got message with wrong type (expected Alive or MembershipResponse or MembershipRequest message):", m.GossipMessage) 328 return 329 } 330 331 d.logger.Debug("Got message:", m) 332 defer d.logger.Debug("Exiting") 333 334 if memReq := m.GetMemReq(); memReq != nil { 335 selfInfoGossipMsg, err := protoext.EnvelopeToGossipMessage(memReq.SelfInformation) 336 if err != nil { 337 d.logger.Warningf("Failed deserializing GossipMessage from envelope: %+v", errors.WithStack(err)) 338 return 339 } 340 341 if !d.crypt.ValidateAliveMsg(selfInfoGossipMsg) { 342 return 343 } 344 345 if d.msgStore.CheckValid(selfInfoGossipMsg) { 346 d.handleAliveMessage(selfInfoGossipMsg) 347 } 348 349 var internalEndpoint string 350 if memReq.SelfInformation.SecretEnvelope != nil { 351 internalEndpoint = protoext.InternalEndpoint(memReq.SelfInformation.SecretEnvelope) 352 } 353 354 // Sending a membership response to a peer may block this routine 355 // in case the sending is deliberately slow (i.e attack). 356 // will keep this async until I'll write a timeout detector in the comm layer 357 go d.sendMemResponse(selfInfoGossipMsg.GetAliveMsg().Membership, internalEndpoint, m.Nonce) 358 return 359 } 360 361 if protoext.IsAliveMsg(m.GossipMessage) { 362 if !d.msgStore.CheckValid(m) || !d.crypt.ValidateAliveMsg(m) { 363 return 364 } 365 // If the message was sent by me, ignore it and don't forward it further 366 if d.isSentByMe(m) { 367 return 368 } 369 370 d.msgStore.Add(m) 371 d.handleAliveMessage(m) 372 d.comm.Forward(msg) 373 return 374 } 375 376 if memResp := m.GetMemRes(); memResp != nil { 377 d.pubsub.Publish(fmt.Sprintf("%d", m.Nonce), m.Nonce) 378 for _, env := range memResp.Alive { 379 am, err := protoext.EnvelopeToGossipMessage(env) 380 if err != nil { 381 d.logger.Warningf("Membership response contains an invalid message from an online peer:%+v", errors.WithStack(err)) 382 return 383 } 384 if !protoext.IsAliveMsg(am.GossipMessage) { 385 d.logger.Warning("Expected alive message, got", am, "instead") 386 return 387 } 388 389 if d.msgStore.CheckValid(am) && d.crypt.ValidateAliveMsg(am) { 390 d.handleAliveMessage(am) 391 } 392 } 393 394 for _, env := range memResp.Dead { 395 dm, err := protoext.EnvelopeToGossipMessage(env) 396 if err != nil { 397 d.logger.Warningf("Membership response contains an invalid message from an offline peer %+v", errors.WithStack(err)) 398 return 399 } 400 401 // Newer alive message exists or the message isn't authentic 402 if !d.msgStore.CheckValid(dm) || !d.crypt.ValidateAliveMsg(dm) { 403 continue 404 } 405 406 newDeadMembers := []*protoext.SignedGossipMessage{} 407 d.lock.RLock() 408 if _, known := d.id2Member[string(dm.GetAliveMsg().Membership.PkiId)]; !known { 409 newDeadMembers = append(newDeadMembers, dm) 410 } 411 d.lock.RUnlock() 412 d.learnNewMembers([]*protoext.SignedGossipMessage{}, newDeadMembers) 413 } 414 } 415 } 416 417 func (d *gossipDiscoveryImpl) sendMemResponse(targetMember *proto.Member, internalEndpoint string, nonce uint64) { 418 d.logger.Debug("Entering", protoext.MemberToString(targetMember)) 419 420 targetPeer := &NetworkMember{ 421 Endpoint: targetMember.Endpoint, 422 Metadata: targetMember.Metadata, 423 PKIid: targetMember.PkiId, 424 InternalEndpoint: internalEndpoint, 425 } 426 427 var aliveMsg *protoext.SignedGossipMessage 428 var err error 429 d.lock.RLock() 430 aliveMsg = d.selfAliveMessage 431 d.lock.RUnlock() 432 if aliveMsg == nil { 433 aliveMsg, err = d.createSignedAliveMessage(true) 434 if err != nil { 435 d.logger.Warningf("Failed creating alive message: %+v", errors.WithStack(err)) 436 return 437 } 438 } 439 memResp := d.createMembershipResponse(aliveMsg, targetPeer) 440 if memResp == nil { 441 errMsg := `Got a membership request from a peer that shouldn't have sent one: %v, closing connection to the peer as a result.` 442 d.logger.Warningf(errMsg, targetMember) 443 d.comm.CloseConn(targetPeer) 444 return 445 } 446 447 defer d.logger.Debug("Exiting, replying with", protoext.MembershipResponseToString(memResp)) 448 449 msg, err := protoext.NoopSign(&proto.GossipMessage{ 450 Tag: proto.GossipMessage_EMPTY, 451 Nonce: nonce, 452 Content: &proto.GossipMessage_MemRes{ 453 MemRes: memResp, 454 }, 455 }) 456 if err != nil { 457 err = errors.WithStack(err) 458 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 459 return 460 } 461 d.comm.SendToPeer(targetPeer, msg) 462 } 463 464 func (d *gossipDiscoveryImpl) createMembershipResponse(aliveMsg *protoext.SignedGossipMessage, targetMember *NetworkMember) *proto.MembershipResponse { 465 shouldBeDisclosed, omitConcealedFields := d.disclosurePolicy(targetMember) 466 467 if !shouldBeDisclosed(aliveMsg) { 468 return nil 469 } 470 471 d.lock.RLock() 472 defer d.lock.RUnlock() 473 474 deadPeers := []*proto.Envelope{} 475 476 for _, dm := range d.deadMembership.ToSlice() { 477 478 if !shouldBeDisclosed(dm) { 479 continue 480 } 481 deadPeers = append(deadPeers, omitConcealedFields(dm)) 482 } 483 484 var aliveSnapshot []*proto.Envelope 485 for _, am := range d.aliveMembership.ToSlice() { 486 if !shouldBeDisclosed(am) { 487 continue 488 } 489 aliveSnapshot = append(aliveSnapshot, omitConcealedFields(am)) 490 } 491 492 return &proto.MembershipResponse{ 493 Alive: append(aliveSnapshot, omitConcealedFields(aliveMsg)), 494 Dead: deadPeers, 495 } 496 } 497 498 func (d *gossipDiscoveryImpl) handleAliveMessage(m *protoext.SignedGossipMessage) { 499 d.logger.Debug("Entering", m) 500 defer d.logger.Debug("Exiting") 501 502 if d.isSentByMe(m) { 503 return 504 } 505 506 pkiID := m.GetAliveMsg().Membership.PkiId 507 508 ts := m.GetAliveMsg().Timestamp 509 510 d.lock.RLock() 511 _, known := d.id2Member[string(pkiID)] 512 d.lock.RUnlock() 513 514 if !known { 515 d.learnNewMembers([]*protoext.SignedGossipMessage{m}, []*protoext.SignedGossipMessage{}) 516 return 517 } 518 519 d.lock.RLock() 520 _, isAlive := d.aliveLastTS[string(pkiID)] 521 lastDeadTS, isDead := d.deadLastTS[string(pkiID)] 522 d.lock.RUnlock() 523 524 if !isAlive && !isDead { 525 d.logger.Panicf("Member %s is known but not found neither in alive nor in dead lastTS maps, isAlive=%v, isDead=%v", m.GetAliveMsg().Membership.Endpoint, isAlive, isDead) 526 return 527 } 528 529 if isAlive && isDead { 530 d.logger.Panicf("Member %s is both alive and dead at the same time", m.GetAliveMsg().Membership) 531 return 532 } 533 534 if isDead { 535 if before(lastDeadTS, ts) { 536 // resurrect peer 537 d.resurrectMember(m, *ts) 538 } else if !same(lastDeadTS, ts) { 539 d.logger.Debug("got old alive message about dead peer ", protoext.MemberToString(m.GetAliveMsg().Membership), "lastDeadTS:", lastDeadTS, "but got ts:", ts) 540 } 541 return 542 } 543 544 d.lock.RLock() 545 lastAliveTS, isAlive := d.aliveLastTS[string(pkiID)] 546 d.lock.RUnlock() 547 548 if isAlive { 549 if before(lastAliveTS, ts) { 550 d.learnExistingMembers([]*protoext.SignedGossipMessage{m}) 551 } else if !same(lastAliveTS, ts) { 552 d.logger.Debug("got old alive message about alive peer ", protoext.MemberToString(m.GetAliveMsg().Membership), "lastAliveTS:", lastAliveTS, "but got ts:", ts) 553 } 554 } 555 // else, ignore the message because it is too old 556 } 557 558 func (d *gossipDiscoveryImpl) purge(id common.PKIidType) { 559 d.logger.Infof("Purging %s from membership", id) 560 d.lock.Lock() 561 defer d.lock.Unlock() 562 d.aliveMembership.Remove(id) 563 d.deadMembership.Remove(id) 564 delete(d.id2Member, string(id)) 565 delete(d.deadLastTS, string(id)) 566 delete(d.aliveLastTS, string(id)) 567 } 568 569 func (d *gossipDiscoveryImpl) isSentByMe(m *protoext.SignedGossipMessage) bool { 570 pkiID := m.GetAliveMsg().Membership.PkiId 571 if !equalPKIid(pkiID, d.self.PKIid) { 572 return false 573 } 574 d.logger.Debug("Got alive message about ourselves,", m) 575 d.lock.RLock() 576 diffExternalEndpoint := d.self.Endpoint != m.GetAliveMsg().Membership.Endpoint 577 d.lock.RUnlock() 578 var diffInternalEndpoint bool 579 secretEnvelope := m.GetSecretEnvelope() 580 if secretEnvelope != nil { 581 internalEndpoint := protoext.InternalEndpoint(secretEnvelope) 582 if internalEndpoint != "" { 583 diffInternalEndpoint = internalEndpoint != d.self.InternalEndpoint 584 } 585 } 586 if diffInternalEndpoint || diffExternalEndpoint { 587 d.logger.Error("Bad configuration detected: Received AliveMessage from a peer with the same PKI-ID as myself:", m.GossipMessage) 588 } 589 return true 590 } 591 592 func (d *gossipDiscoveryImpl) resurrectMember(am *protoext.SignedGossipMessage, t proto.PeerTime) { 593 d.logger.Debug("Entering, AliveMessage:", am, "t:", t) 594 defer d.logger.Debug("Exiting") 595 d.lock.Lock() 596 defer d.lock.Unlock() 597 598 member := am.GetAliveMsg().Membership 599 pkiID := member.PkiId 600 d.aliveLastTS[string(pkiID)] = ×tamp{ 601 lastSeen: time.Now(), 602 seqNum: t.SeqNum, 603 incTime: tsToTime(t.IncNum), 604 } 605 606 var internalEndpoint string 607 if prevNetMem := d.id2Member[string(pkiID)]; prevNetMem != nil { 608 internalEndpoint = prevNetMem.InternalEndpoint 609 } 610 if am.Envelope.SecretEnvelope != nil { 611 internalEndpoint = protoext.InternalEndpoint(am.Envelope.SecretEnvelope) 612 } 613 614 d.id2Member[string(pkiID)] = &NetworkMember{ 615 Endpoint: member.Endpoint, 616 Metadata: member.Metadata, 617 PKIid: member.PkiId, 618 InternalEndpoint: internalEndpoint, 619 } 620 621 delete(d.deadLastTS, string(pkiID)) 622 d.deadMembership.Remove(pkiID) 623 d.aliveMembership.Put(pkiID, &protoext.SignedGossipMessage{GossipMessage: am.GossipMessage, Envelope: am.Envelope}) 624 } 625 626 func (d *gossipDiscoveryImpl) periodicalReconnectToDead() { 627 defer d.logger.Debug("Stopped") 628 629 for !d.toDie() { 630 wg := &sync.WaitGroup{} 631 632 for _, member := range d.copyLastSeen(d.deadLastTS) { 633 wg.Add(1) 634 go func(member NetworkMember) { 635 defer wg.Done() 636 if d.comm.Ping(&member) { 637 d.logger.Debug(member, "is responding, sending membership request") 638 d.sendMembershipRequest(&member, true) 639 } else { 640 d.logger.Debug(member, "is still dead") 641 } 642 }(member) 643 } 644 645 wg.Wait() 646 d.logger.Debug("Sleeping", d.reconnectInterval) 647 time.Sleep(d.reconnectInterval) 648 } 649 } 650 651 func (d *gossipDiscoveryImpl) sendMembershipRequest(member *NetworkMember, includeInternalEndpoint bool) { 652 m, err := d.createMembershipRequest(includeInternalEndpoint) 653 if err != nil { 654 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 655 return 656 } 657 req, err := protoext.NoopSign(m) 658 if err != nil { 659 d.logger.Errorf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 660 return 661 } 662 d.comm.SendToPeer(member, req) 663 } 664 665 func (d *gossipDiscoveryImpl) createMembershipRequest(includeInternalEndpoint bool) (*proto.GossipMessage, error) { 666 am, err := d.createSignedAliveMessage(includeInternalEndpoint) 667 if err != nil { 668 return nil, errors.WithStack(err) 669 } 670 req := &proto.MembershipRequest{ 671 SelfInformation: am.Envelope, 672 // TODO: sending the known peers is not secure because the remote peer might shouldn't know 673 // TODO: about the known peers. I'm deprecating this until a secure mechanism will be implemented. 674 // TODO: See FAB-2570 for tracking this issue. 675 Known: [][]byte{}, 676 } 677 return &proto.GossipMessage{ 678 Tag: proto.GossipMessage_EMPTY, 679 Nonce: uint64(0), 680 Content: &proto.GossipMessage_MemReq{ 681 MemReq: req, 682 }, 683 }, nil 684 } 685 686 func (d *gossipDiscoveryImpl) copyLastSeen(lastSeenMap map[string]*timestamp) []NetworkMember { 687 d.lock.RLock() 688 defer d.lock.RUnlock() 689 690 res := []NetworkMember{} 691 for pkiIDStr := range lastSeenMap { 692 res = append(res, *(d.id2Member[pkiIDStr])) 693 } 694 return res 695 } 696 697 func (d *gossipDiscoveryImpl) periodicalCheckAlive() { 698 defer d.logger.Debug("Stopped") 699 700 for !d.toDie() { 701 time.Sleep(d.aliveExpirationCheckInterval) 702 dead := d.getDeadMembers() 703 if len(dead) > 0 { 704 d.logger.Debugf("Got %v dead members: %v", len(dead), dead) 705 d.expireDeadMembers(dead) 706 } 707 } 708 } 709 710 func (d *gossipDiscoveryImpl) expireDeadMembers(dead []common.PKIidType) { 711 d.logger.Warning("Entering", dead) 712 defer d.logger.Warning("Exiting") 713 714 var deadMembers2Expire []NetworkMember 715 716 d.lock.Lock() 717 718 for _, pkiID := range dead { 719 if _, isAlive := d.aliveLastTS[string(pkiID)]; !isAlive { 720 continue 721 } 722 deadMembers2Expire = append(deadMembers2Expire, d.id2Member[string(pkiID)].Clone()) 723 // move lastTS from alive to dead 724 lastTS, hasLastTS := d.aliveLastTS[string(pkiID)] 725 if hasLastTS { 726 d.deadLastTS[string(pkiID)] = lastTS 727 delete(d.aliveLastTS, string(pkiID)) 728 } 729 730 if am := d.aliveMembership.MsgByID(pkiID); am != nil { 731 d.deadMembership.Put(pkiID, am) 732 d.aliveMembership.Remove(pkiID) 733 } 734 } 735 736 d.lock.Unlock() 737 738 for _, member2Expire := range deadMembers2Expire { 739 d.logger.Warning("Closing connection to", member2Expire) 740 d.comm.CloseConn(&member2Expire) 741 } 742 } 743 744 func (d *gossipDiscoveryImpl) getDeadMembers() []common.PKIidType { 745 d.lock.RLock() 746 defer d.lock.RUnlock() 747 748 dead := []common.PKIidType{} 749 for id, last := range d.aliveLastTS { 750 elapsedNonAliveTime := time.Since(last.lastSeen) 751 if elapsedNonAliveTime > d.aliveExpirationTimeout { 752 d.logger.Warning("Haven't heard from", []byte(id), "for", elapsedNonAliveTime) 753 dead = append(dead, common.PKIidType(id)) 754 } 755 } 756 return dead 757 } 758 759 func (d *gossipDiscoveryImpl) periodicalSendAlive() { 760 defer d.logger.Debug("Stopped") 761 762 for !d.toDie() { 763 d.logger.Debug("Sleeping", d.aliveTimeInterval) 764 time.Sleep(d.aliveTimeInterval) 765 if d.aliveMembership.Size() == 0 { 766 d.logger.Debugf("Empty membership, no one to send a heartbeat to") 767 continue 768 } 769 msg, err := d.createSignedAliveMessage(true) 770 if err != nil { 771 d.logger.Warningf("Failed creating alive message: %+v", errors.WithStack(err)) 772 return 773 } 774 d.lock.Lock() 775 d.selfAliveMessage = msg 776 d.lock.Unlock() 777 d.comm.Gossip(msg) 778 } 779 } 780 781 func (d *gossipDiscoveryImpl) aliveMsgAndInternalEndpoint() (*proto.GossipMessage, string) { 782 d.lock.Lock() 783 defer d.lock.Unlock() 784 d.seqNum++ 785 seqNum := d.seqNum 786 endpoint := d.self.Endpoint 787 meta := d.self.Metadata 788 pkiID := d.self.PKIid 789 internalEndpoint := d.self.InternalEndpoint 790 msg := &proto.GossipMessage{ 791 Tag: proto.GossipMessage_EMPTY, 792 Content: &proto.GossipMessage_AliveMsg{ 793 AliveMsg: &proto.AliveMessage{ 794 Membership: &proto.Member{ 795 Endpoint: endpoint, 796 Metadata: meta, 797 PkiId: pkiID, 798 }, 799 Timestamp: &proto.PeerTime{ 800 IncNum: d.incTime, 801 SeqNum: seqNum, 802 }, 803 }, 804 }, 805 } 806 return msg, internalEndpoint 807 } 808 809 func (d *gossipDiscoveryImpl) createSignedAliveMessage(includeInternalEndpoint bool) (*protoext.SignedGossipMessage, error) { 810 msg, internalEndpoint := d.aliveMsgAndInternalEndpoint() 811 envp := d.crypt.SignMessage(msg, internalEndpoint) 812 if envp == nil { 813 return nil, errors.New("Failed signing message") 814 } 815 signedMsg := &protoext.SignedGossipMessage{ 816 GossipMessage: msg, 817 Envelope: envp, 818 } 819 820 if !includeInternalEndpoint { 821 signedMsg.Envelope.SecretEnvelope = nil 822 } 823 824 return signedMsg, nil 825 } 826 827 func (d *gossipDiscoveryImpl) learnExistingMembers(aliveArr []*protoext.SignedGossipMessage) { 828 d.logger.Debugf("Entering: learnedMembers={%v}", aliveArr) 829 defer d.logger.Debug("Exiting") 830 831 d.lock.Lock() 832 defer d.lock.Unlock() 833 834 for _, m := range aliveArr { 835 am := m.GetAliveMsg() 836 if am == nil { 837 d.logger.Warning("Expected alive message, got instead:", m) 838 return 839 } 840 d.logger.Debug("updating", protoext.AliveMessageToString(am)) 841 842 var internalEndpoint string 843 if prevNetMem := d.id2Member[string(am.Membership.PkiId)]; prevNetMem != nil { 844 internalEndpoint = prevNetMem.InternalEndpoint 845 } 846 if m.Envelope.SecretEnvelope != nil { 847 internalEndpoint = protoext.InternalEndpoint(m.Envelope.SecretEnvelope) 848 } 849 850 // update member's data 851 member := d.id2Member[string(am.Membership.PkiId)] 852 member.Endpoint = am.Membership.Endpoint 853 member.Metadata = am.Membership.Metadata 854 member.InternalEndpoint = internalEndpoint 855 856 if _, isKnownAsDead := d.deadLastTS[string(am.Membership.PkiId)]; isKnownAsDead { 857 d.logger.Warning(am.Membership, "has already expired") 858 continue 859 } 860 861 if _, isKnownAsAlive := d.aliveLastTS[string(am.Membership.PkiId)]; !isKnownAsAlive { 862 d.logger.Warning(am.Membership, "has already expired") 863 continue 864 } else { 865 d.logger.Debug("Updating aliveness data:", protoext.AliveMessageToString(am)) 866 // update existing aliveness data 867 alive := d.aliveLastTS[string(am.Membership.PkiId)] 868 alive.incTime = tsToTime(am.Timestamp.IncNum) 869 alive.lastSeen = time.Now() 870 alive.seqNum = am.Timestamp.SeqNum 871 872 if am := d.aliveMembership.MsgByID(m.GetAliveMsg().Membership.PkiId); am != nil { 873 d.logger.Debug("Replacing", am, "in aliveMembership") 874 am.GossipMessage = m.GossipMessage 875 am.Envelope = m.Envelope 876 } 877 } 878 } 879 } 880 881 func (d *gossipDiscoveryImpl) learnNewMembers(aliveMembers []*protoext.SignedGossipMessage, deadMembers []*protoext.SignedGossipMessage) { 882 d.logger.Debugf("Entering: learnedMembers={%v}, deadMembers={%v}", aliveMembers, deadMembers) 883 defer d.logger.Debugf("Exiting") 884 885 d.lock.Lock() 886 defer d.lock.Unlock() 887 888 for _, am := range aliveMembers { 889 if equalPKIid(am.GetAliveMsg().Membership.PkiId, d.self.PKIid) { 890 continue 891 } 892 d.aliveLastTS[string(am.GetAliveMsg().Membership.PkiId)] = ×tamp{ 893 incTime: tsToTime(am.GetAliveMsg().Timestamp.IncNum), 894 lastSeen: time.Now(), 895 seqNum: am.GetAliveMsg().Timestamp.SeqNum, 896 } 897 898 d.aliveMembership.Put(am.GetAliveMsg().Membership.PkiId, &protoext.SignedGossipMessage{GossipMessage: am.GossipMessage, Envelope: am.Envelope}) 899 d.logger.Debugf("Learned about a new alive member: %v", am) 900 } 901 902 for _, dm := range deadMembers { 903 if equalPKIid(dm.GetAliveMsg().Membership.PkiId, d.self.PKIid) { 904 continue 905 } 906 d.deadLastTS[string(dm.GetAliveMsg().Membership.PkiId)] = ×tamp{ 907 incTime: tsToTime(dm.GetAliveMsg().Timestamp.IncNum), 908 lastSeen: time.Now(), 909 seqNum: dm.GetAliveMsg().Timestamp.SeqNum, 910 } 911 912 d.deadMembership.Put(dm.GetAliveMsg().Membership.PkiId, &protoext.SignedGossipMessage{GossipMessage: dm.GossipMessage, Envelope: dm.Envelope}) 913 d.logger.Debugf("Learned about a new dead member: %v", dm) 914 } 915 916 // update the member in any case 917 for _, a := range [][]*protoext.SignedGossipMessage{aliveMembers, deadMembers} { 918 for _, m := range a { 919 member := m.GetAliveMsg() 920 if member == nil { 921 d.logger.Warning("Expected alive message, got instead:", m) 922 return 923 } 924 925 var internalEndpoint string 926 if m.Envelope.SecretEnvelope != nil { 927 internalEndpoint = protoext.InternalEndpoint(m.Envelope.SecretEnvelope) 928 } 929 930 if prevNetMem := d.id2Member[string(member.Membership.PkiId)]; prevNetMem != nil { 931 internalEndpoint = prevNetMem.InternalEndpoint 932 } 933 934 d.id2Member[string(member.Membership.PkiId)] = &NetworkMember{ 935 Endpoint: member.Membership.Endpoint, 936 Metadata: member.Membership.Metadata, 937 PKIid: member.Membership.PkiId, 938 InternalEndpoint: internalEndpoint, 939 } 940 } 941 } 942 } 943 944 func (d *gossipDiscoveryImpl) GetMembership() []NetworkMember { 945 if d.toDie() { 946 return []NetworkMember{} 947 } 948 d.lock.RLock() 949 defer d.lock.RUnlock() 950 951 response := []NetworkMember{} 952 for _, m := range d.aliveMembership.ToSlice() { 953 member := m.GetAliveMsg() 954 response = append(response, NetworkMember{ 955 PKIid: member.Membership.PkiId, 956 Endpoint: member.Membership.Endpoint, 957 Metadata: member.Membership.Metadata, 958 InternalEndpoint: d.id2Member[string(m.GetAliveMsg().Membership.PkiId)].InternalEndpoint, 959 Envelope: m.Envelope, 960 }) 961 } 962 return response 963 } 964 965 func tsToTime(ts uint64) time.Time { 966 return time.Unix(int64(0), int64(ts)) 967 } 968 969 func (d *gossipDiscoveryImpl) UpdateMetadata(md []byte) { 970 d.lock.Lock() 971 defer d.lock.Unlock() 972 d.self.Metadata = md 973 } 974 975 func (d *gossipDiscoveryImpl) UpdateEndpoint(endpoint string) { 976 d.lock.Lock() 977 defer d.lock.Unlock() 978 979 d.self.Endpoint = endpoint 980 } 981 982 func (d *gossipDiscoveryImpl) Self() NetworkMember { 983 var env *proto.Envelope 984 msg, _ := d.aliveMsgAndInternalEndpoint() 985 sMsg, err := protoext.NoopSign(msg) 986 if err != nil { 987 d.logger.Warning("Failed creating SignedGossipMessage:", err) 988 } else { 989 env = sMsg.Envelope 990 } 991 mem := msg.GetAliveMsg().Membership 992 return NetworkMember{ 993 Endpoint: mem.Endpoint, 994 Metadata: mem.Metadata, 995 PKIid: mem.PkiId, 996 Envelope: env, 997 } 998 } 999 1000 func (d *gossipDiscoveryImpl) toDie() bool { 1001 select { 1002 case <-d.toDieChan: 1003 return true 1004 default: 1005 return false 1006 } 1007 } 1008 1009 func (d *gossipDiscoveryImpl) Stop() { 1010 select { 1011 case <-d.toDieChan: 1012 default: 1013 close(d.toDieChan) 1014 defer d.logger.Info("Stopped") 1015 d.logger.Info("Stopping") 1016 d.msgStore.Stop() 1017 } 1018 } 1019 1020 func copyNetworkMember(member *NetworkMember) *NetworkMember { 1021 if member == nil { 1022 return nil 1023 } else { 1024 copiedNetworkMember := &NetworkMember{} 1025 *copiedNetworkMember = *member 1026 return copiedNetworkMember 1027 } 1028 } 1029 1030 func equalPKIid(a, b common.PKIidType) bool { 1031 return bytes.Equal(a, b) 1032 } 1033 1034 func same(a *timestamp, b *proto.PeerTime) bool { 1035 return uint64(a.incTime.UnixNano()) == b.IncNum && a.seqNum == b.SeqNum 1036 } 1037 1038 func before(a *timestamp, b *proto.PeerTime) bool { 1039 return (uint64(a.incTime.UnixNano()) == b.IncNum && a.seqNum < b.SeqNum) || 1040 uint64(a.incTime.UnixNano()) < b.IncNum 1041 } 1042 1043 type aliveMsgStore struct { 1044 msgstore.MessageStore 1045 } 1046 1047 func newAliveMsgStore(d *gossipDiscoveryImpl) *aliveMsgStore { 1048 policy := protoext.NewGossipMessageComparator(0) 1049 trigger := func(m interface{}) {} 1050 aliveMsgTTL := d.aliveExpirationTimeout * time.Duration(d.msgExpirationFactor) 1051 externalLock := func() { d.lock.Lock() } 1052 externalUnlock := func() { d.lock.Unlock() } 1053 callback := func(m interface{}) { 1054 msg := m.(*protoext.SignedGossipMessage) 1055 if !protoext.IsAliveMsg(msg.GossipMessage) { 1056 return 1057 } 1058 membership := msg.GetAliveMsg().Membership 1059 id := membership.PkiId 1060 endpoint := membership.Endpoint 1061 internalEndpoint := protoext.InternalEndpoint(msg.SecretEnvelope) 1062 if util.Contains(endpoint, d.bootstrapPeers) || util.Contains(internalEndpoint, d.bootstrapPeers) || 1063 d.anchorPeerTracker.IsAnchorPeer(endpoint) || d.anchorPeerTracker.IsAnchorPeer(internalEndpoint) { 1064 // Never remove a bootstrap peer or an anchor peer 1065 d.logger.Debugf("Do not remove bootstrap or anchor peer endpoint %s from membership", endpoint) 1066 return 1067 } 1068 d.logger.Infof("Removing member: Endpoint: %s, InternalEndpoint: %s, PKIID: %x", endpoint, internalEndpoint, id) 1069 d.aliveMembership.Remove(id) 1070 d.deadMembership.Remove(id) 1071 delete(d.id2Member, string(id)) 1072 delete(d.deadLastTS, string(id)) 1073 delete(d.aliveLastTS, string(id)) 1074 } 1075 1076 s := &aliveMsgStore{ 1077 MessageStore: msgstore.NewMessageStoreExpirable(policy, trigger, aliveMsgTTL, externalLock, externalUnlock, callback), 1078 } 1079 return s 1080 } 1081 1082 func (s *aliveMsgStore) Add(msg interface{}) bool { 1083 m := msg.(*protoext.SignedGossipMessage) 1084 if !protoext.IsAliveMsg(m.GossipMessage) { 1085 panic(fmt.Sprint("Msg ", msg, " is not AliveMsg")) 1086 } 1087 return s.MessageStore.Add(msg) 1088 } 1089 1090 func (s *aliveMsgStore) CheckValid(msg interface{}) bool { 1091 m := msg.(*protoext.SignedGossipMessage) 1092 if !protoext.IsAliveMsg(m.GossipMessage) { 1093 panic(fmt.Sprint("Msg ", msg, " is not AliveMsg")) 1094 } 1095 return s.MessageStore.CheckValid(msg) 1096 }