github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/gossip/discovery/discovery_impl.go (about) 1 /* 2 Copyright IBM Corp. 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 proto "github.com/hyperledger/fabric-protos-go/gossip" 19 "github.com/osdi23p228/fabric/gossip/common" 20 "github.com/osdi23p228/fabric/gossip/gossip/msgstore" 21 "github.com/osdi23p228/fabric/gossip/protoext" 22 "github.com/osdi23p228/fabric/gossip/util" 23 "github.com/pkg/errors" 24 ) 25 26 const DefAliveTimeInterval = 5 * time.Second 27 const DefAliveExpirationTimeout = 5 * DefAliveTimeInterval 28 const DefAliveExpirationCheckInterval = DefAliveExpirationTimeout / 10 29 const DefReconnectInterval = DefAliveExpirationTimeout 30 const DefMsgExpirationFactor = 20 31 const DefMaxConnectionAttempts = 120 32 33 type timestamp struct { 34 incTime time.Time 35 seqNum uint64 36 lastSeen time.Time 37 } 38 39 func (ts *timestamp) String() string { 40 return fmt.Sprintf("%v, %v", ts.incTime.UnixNano(), ts.seqNum) 41 } 42 43 type gossipDiscoveryImpl struct { 44 incTime uint64 45 seqNum uint64 46 self NetworkMember 47 deadLastTS map[string]*timestamp // H 48 aliveLastTS map[string]*timestamp // V 49 id2Member map[string]*NetworkMember // all known members 50 aliveMembership *util.MembershipStore 51 deadMembership *util.MembershipStore 52 selfAliveMessage *protoext.SignedGossipMessage 53 54 msgStore *aliveMsgStore 55 56 comm CommService 57 crypt CryptoService 58 lock *sync.RWMutex 59 60 toDieChan chan struct{} 61 port int 62 logger util.Logger 63 disclosurePolicy DisclosurePolicy 64 pubsub *util.PubSub 65 66 aliveTimeInterval time.Duration 67 aliveExpirationTimeout time.Duration 68 aliveExpirationCheckInterval time.Duration 69 reconnectInterval time.Duration 70 msgExpirationFactor int 71 maxConnectionAttempts int 72 73 bootstrapPeers []string 74 anchorPeerTracker AnchorPeerTracker 75 } 76 77 type DiscoveryConfig struct { 78 AliveTimeInterval time.Duration 79 AliveExpirationTimeout time.Duration 80 AliveExpirationCheckInterval time.Duration 81 ReconnectInterval time.Duration 82 MaxConnectionAttempts int 83 MsgExpirationFactor int 84 BootstrapPeers []string 85 } 86 87 // NewDiscoveryService returns a new discovery service with the comm module passed and the crypto service passed 88 func NewDiscoveryService(self NetworkMember, comm CommService, crypt CryptoService, disPol DisclosurePolicy, 89 config DiscoveryConfig, anchorPeerTracker AnchorPeerTracker, logger util.Logger) Discovery { 90 d := &gossipDiscoveryImpl{ 91 self: self, 92 incTime: uint64(time.Now().UnixNano()), 93 seqNum: uint64(0), 94 deadLastTS: make(map[string]*timestamp), 95 aliveLastTS: make(map[string]*timestamp), 96 id2Member: make(map[string]*NetworkMember), 97 aliveMembership: util.NewMembershipStore(), 98 deadMembership: util.NewMembershipStore(), 99 crypt: crypt, 100 comm: comm, 101 lock: &sync.RWMutex{}, 102 toDieChan: make(chan struct{}), 103 logger: logger, 104 disclosurePolicy: disPol, 105 pubsub: util.NewPubSub(), 106 107 aliveTimeInterval: config.AliveTimeInterval, 108 aliveExpirationTimeout: config.AliveExpirationTimeout, 109 aliveExpirationCheckInterval: config.AliveExpirationCheckInterval, 110 reconnectInterval: config.ReconnectInterval, 111 maxConnectionAttempts: config.MaxConnectionAttempts, 112 msgExpirationFactor: config.MsgExpirationFactor, 113 114 bootstrapPeers: config.BootstrapPeers, 115 anchorPeerTracker: anchorPeerTracker, 116 } 117 118 d.validateSelfConfig() 119 d.msgStore = newAliveMsgStore(d) 120 121 go d.periodicalSendAlive() 122 go d.periodicalCheckAlive() 123 go d.handleMessages() 124 go d.periodicalReconnectToDead() 125 go d.handleEvents() 126 127 return d 128 } 129 130 // Lookup returns a network member, or nil if not found 131 func (d *gossipDiscoveryImpl) Lookup(PKIID common.PKIidType) *NetworkMember { 132 if bytes.Equal(PKIID, d.self.PKIid) { 133 return &d.self 134 } 135 d.lock.RLock() 136 defer d.lock.RUnlock() 137 return copyNetworkMember(d.id2Member[string(PKIID)]) 138 } 139 140 func (d *gossipDiscoveryImpl) Connect(member NetworkMember, id identifier) { 141 for _, endpoint := range []string{member.InternalEndpoint, member.Endpoint} { 142 if d.isMyOwnEndpoint(endpoint) { 143 d.logger.Debug("Skipping connecting to myself") 144 return 145 } 146 } 147 148 d.logger.Debug("Entering", member) 149 defer d.logger.Debug("Exiting") 150 go func() { 151 for i := 0; i < d.maxConnectionAttempts && !d.toDie(); i++ { 152 id, err := id() 153 if err != nil { 154 if d.toDie() { 155 return 156 } 157 d.logger.Warningf("Could not connect to %v : %v", member, err) 158 time.Sleep(d.reconnectInterval) 159 continue 160 } 161 peer := &NetworkMember{ 162 InternalEndpoint: member.InternalEndpoint, 163 Endpoint: member.Endpoint, 164 PKIid: id.ID, 165 } 166 m, err := d.createMembershipRequest(id.SelfOrg) 167 if err != nil { 168 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 169 continue 170 } 171 req, err := protoext.NoopSign(m) 172 if err != nil { 173 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 174 continue 175 } 176 req.Nonce = util.RandomUInt64() 177 req, err = protoext.NoopSign(req.GossipMessage) 178 if err != nil { 179 d.logger.Warningf("Failed adding NONCE to SignedGossipMessage %+v", errors.WithStack(err)) 180 continue 181 } 182 go d.sendUntilAcked(peer, req) 183 return 184 } 185 186 }() 187 } 188 189 func (d *gossipDiscoveryImpl) isMyOwnEndpoint(endpoint string) bool { 190 return endpoint == fmt.Sprintf("127.0.0.1:%d", d.port) || endpoint == fmt.Sprintf("localhost:%d", d.port) || 191 endpoint == d.self.InternalEndpoint || endpoint == d.self.Endpoint 192 } 193 194 func (d *gossipDiscoveryImpl) validateSelfConfig() { 195 endpoint := d.self.InternalEndpoint 196 if len(endpoint) == 0 { 197 d.logger.Panic("Internal endpoint is empty:", endpoint) 198 } 199 200 internalEndpointSplit := strings.Split(endpoint, ":") 201 if len(internalEndpointSplit) != 2 { 202 d.logger.Panicf("Self endpoint %s isn't formatted as 'host:port'", endpoint) 203 } 204 myPort, err := strconv.ParseInt(internalEndpointSplit[1], 10, 64) 205 if err != nil { 206 d.logger.Panicf("Self endpoint %s has not valid port, %+v", endpoint, errors.WithStack(err)) 207 } 208 209 if myPort > int64(math.MaxUint16) { 210 d.logger.Panicf("Self endpoint %s's port takes more than 16 bits", endpoint) 211 } 212 213 d.port = int(myPort) 214 } 215 216 func (d *gossipDiscoveryImpl) sendUntilAcked(peer *NetworkMember, message *protoext.SignedGossipMessage) { 217 nonce := message.Nonce 218 for i := 0; i < d.maxConnectionAttempts && !d.toDie(); i++ { 219 sub := d.pubsub.Subscribe(fmt.Sprintf("%d", nonce), time.Second*5) 220 d.comm.SendToPeer(peer, message) 221 if _, timeoutErr := sub.Listen(); timeoutErr == nil { 222 return 223 } 224 time.Sleep(d.reconnectInterval) 225 } 226 } 227 228 func (d *gossipDiscoveryImpl) InitiateSync(peerNum int) { 229 if d.toDie() { 230 return 231 } 232 var peers2SendTo []*NetworkMember 233 234 d.lock.RLock() 235 236 n := d.aliveMembership.Size() 237 k := peerNum 238 if k > n { 239 k = n 240 } 241 242 aliveMembersAsSlice := d.aliveMembership.ToSlice() 243 for _, i := range util.GetRandomIndices(k, n-1) { 244 pulledPeer := aliveMembersAsSlice[i].GetAliveMsg().Membership 245 var internalEndpoint string 246 if aliveMembersAsSlice[i].Envelope.SecretEnvelope != nil { 247 internalEndpoint = protoext.InternalEndpoint(aliveMembersAsSlice[i].Envelope.SecretEnvelope) 248 } 249 netMember := &NetworkMember{ 250 Endpoint: pulledPeer.Endpoint, 251 Metadata: pulledPeer.Metadata, 252 PKIid: pulledPeer.PkiId, 253 InternalEndpoint: internalEndpoint, 254 } 255 peers2SendTo = append(peers2SendTo, netMember) 256 } 257 258 d.lock.RUnlock() 259 260 if len(peers2SendTo) == 0 { 261 d.logger.Debugf("No peers to send to, aborting membership sync") 262 return 263 } 264 265 m, err := d.createMembershipRequest(true) 266 if err != nil { 267 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 268 return 269 } 270 memReq, err := protoext.NoopSign(m) 271 if err != nil { 272 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 273 return 274 } 275 276 for _, netMember := range peers2SendTo { 277 d.comm.SendToPeer(netMember, memReq) 278 } 279 } 280 281 func (d *gossipDiscoveryImpl) handleEvents() { 282 defer d.logger.Debug("Stopped") 283 284 for { 285 select { 286 case deadPeer := <-d.comm.PresumedDead(): 287 if d.isAlive(deadPeer) { 288 d.expireDeadMembers([]common.PKIidType{deadPeer}) 289 } 290 case changedPKIID := <-d.comm.IdentitySwitch(): 291 // If a peer changed its PKI-ID, purge the old PKI-ID 292 d.purge(changedPKIID) 293 case <-d.toDieChan: 294 return 295 } 296 } 297 } 298 299 func (d *gossipDiscoveryImpl) isAlive(pkiID common.PKIidType) bool { 300 d.lock.RLock() 301 defer d.lock.RUnlock() 302 _, alive := d.aliveLastTS[string(pkiID)] 303 return alive 304 } 305 306 func (d *gossipDiscoveryImpl) handleMessages() { 307 defer d.logger.Debug("Stopped") 308 309 in := d.comm.Accept() 310 for { 311 select { 312 case m := <-in: 313 d.handleMsgFromComm(m) 314 case <-d.toDieChan: 315 return 316 } 317 } 318 } 319 320 func (d *gossipDiscoveryImpl) handleMsgFromComm(msg protoext.ReceivedMessage) { 321 if msg == nil { 322 return 323 } 324 m := msg.GetGossipMessage() 325 if m.GetAliveMsg() == nil && m.GetMemRes() == nil && m.GetMemReq() == nil { 326 d.logger.Warning("Got message with wrong type (expected Alive or MembershipResponse or MembershipRequest message):", m.GossipMessage) 327 return 328 } 329 330 d.logger.Debug("Got message:", m) 331 defer d.logger.Debug("Exiting") 332 333 if memReq := m.GetMemReq(); memReq != nil { 334 selfInfoGossipMsg, err := protoext.EnvelopeToGossipMessage(memReq.SelfInformation) 335 if err != nil { 336 d.logger.Warningf("Failed deserializing GossipMessage from envelope: %+v", errors.WithStack(err)) 337 return 338 } 339 340 if !d.crypt.ValidateAliveMsg(selfInfoGossipMsg) { 341 return 342 } 343 344 if d.msgStore.CheckValid(selfInfoGossipMsg) { 345 d.handleAliveMessage(selfInfoGossipMsg) 346 } 347 348 var internalEndpoint string 349 if memReq.SelfInformation.SecretEnvelope != nil { 350 internalEndpoint = protoext.InternalEndpoint(memReq.SelfInformation.SecretEnvelope) 351 } 352 353 // Sending a membership response to a peer may block this routine 354 // in case the sending is deliberately slow (i.e attack). 355 // will keep this async until I'll write a timeout detector in the comm layer 356 go d.sendMemResponse(selfInfoGossipMsg.GetAliveMsg().Membership, internalEndpoint, m.Nonce) 357 return 358 } 359 360 if protoext.IsAliveMsg(m.GossipMessage) { 361 if !d.msgStore.CheckValid(m) || !d.crypt.ValidateAliveMsg(m) { 362 return 363 } 364 // If the message was sent by me, ignore it and don't forward it further 365 if d.isSentByMe(m) { 366 return 367 } 368 369 d.msgStore.Add(m) 370 d.handleAliveMessage(m) 371 d.comm.Forward(msg) 372 return 373 } 374 375 if memResp := m.GetMemRes(); memResp != nil { 376 d.pubsub.Publish(fmt.Sprintf("%d", m.Nonce), m.Nonce) 377 for _, env := range memResp.Alive { 378 am, err := protoext.EnvelopeToGossipMessage(env) 379 if err != nil { 380 d.logger.Warningf("Membership response contains an invalid message from an online peer:%+v", errors.WithStack(err)) 381 return 382 } 383 if !protoext.IsAliveMsg(am.GossipMessage) { 384 d.logger.Warning("Expected alive message, got", am, "instead") 385 return 386 } 387 388 if d.msgStore.CheckValid(am) && d.crypt.ValidateAliveMsg(am) { 389 d.handleAliveMessage(am) 390 } 391 } 392 393 for _, env := range memResp.Dead { 394 dm, err := protoext.EnvelopeToGossipMessage(env) 395 if err != nil { 396 d.logger.Warningf("Membership response contains an invalid message from an offline peer %+v", errors.WithStack(err)) 397 return 398 } 399 400 // Newer alive message exists or the message isn't authentic 401 if !d.msgStore.CheckValid(dm) || !d.crypt.ValidateAliveMsg(dm) { 402 continue 403 } 404 405 newDeadMembers := []*protoext.SignedGossipMessage{} 406 d.lock.RLock() 407 if _, known := d.id2Member[string(dm.GetAliveMsg().Membership.PkiId)]; !known { 408 newDeadMembers = append(newDeadMembers, dm) 409 } 410 d.lock.RUnlock() 411 d.learnNewMembers([]*protoext.SignedGossipMessage{}, newDeadMembers) 412 } 413 } 414 } 415 416 func (d *gossipDiscoveryImpl) sendMemResponse(targetMember *proto.Member, internalEndpoint string, nonce uint64) { 417 d.logger.Debug("Entering", protoext.MemberToString(targetMember)) 418 419 targetPeer := &NetworkMember{ 420 Endpoint: targetMember.Endpoint, 421 Metadata: targetMember.Metadata, 422 PKIid: targetMember.PkiId, 423 InternalEndpoint: internalEndpoint, 424 } 425 426 var aliveMsg *protoext.SignedGossipMessage 427 var err error 428 d.lock.RLock() 429 aliveMsg = d.selfAliveMessage 430 d.lock.RUnlock() 431 if aliveMsg == nil { 432 aliveMsg, err = d.createSignedAliveMessage(true) 433 if err != nil { 434 d.logger.Warningf("Failed creating alive message: %+v", errors.WithStack(err)) 435 return 436 } 437 } 438 memResp := d.createMembershipResponse(aliveMsg, targetPeer) 439 if memResp == nil { 440 errMsg := `Got a membership request from a peer that shouldn't have sent one: %v, closing connection to the peer as a result.` 441 d.logger.Warningf(errMsg, targetMember) 442 d.comm.CloseConn(targetPeer) 443 return 444 } 445 446 defer d.logger.Debug("Exiting, replying with", protoext.MembershipResponseToString(memResp)) 447 448 msg, err := protoext.NoopSign(&proto.GossipMessage{ 449 Tag: proto.GossipMessage_EMPTY, 450 Nonce: nonce, 451 Content: &proto.GossipMessage_MemRes{ 452 MemRes: memResp, 453 }, 454 }) 455 if err != nil { 456 err = errors.WithStack(err) 457 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 458 return 459 } 460 d.comm.SendToPeer(targetPeer, msg) 461 } 462 463 func (d *gossipDiscoveryImpl) createMembershipResponse(aliveMsg *protoext.SignedGossipMessage, targetMember *NetworkMember) *proto.MembershipResponse { 464 shouldBeDisclosed, omitConcealedFields := d.disclosurePolicy(targetMember) 465 466 if !shouldBeDisclosed(aliveMsg) { 467 return nil 468 } 469 470 d.lock.RLock() 471 defer d.lock.RUnlock() 472 473 deadPeers := []*proto.Envelope{} 474 475 for _, dm := range d.deadMembership.ToSlice() { 476 477 if !shouldBeDisclosed(dm) { 478 continue 479 } 480 deadPeers = append(deadPeers, omitConcealedFields(dm)) 481 } 482 483 var aliveSnapshot []*proto.Envelope 484 for _, am := range d.aliveMembership.ToSlice() { 485 if !shouldBeDisclosed(am) { 486 continue 487 } 488 aliveSnapshot = append(aliveSnapshot, omitConcealedFields(am)) 489 } 490 491 return &proto.MembershipResponse{ 492 Alive: append(aliveSnapshot, omitConcealedFields(aliveMsg)), 493 Dead: deadPeers, 494 } 495 } 496 497 func (d *gossipDiscoveryImpl) handleAliveMessage(m *protoext.SignedGossipMessage) { 498 d.logger.Debug("Entering", m) 499 defer d.logger.Debug("Exiting") 500 501 if d.isSentByMe(m) { 502 return 503 } 504 505 pkiID := m.GetAliveMsg().Membership.PkiId 506 507 ts := m.GetAliveMsg().Timestamp 508 509 d.lock.RLock() 510 _, known := d.id2Member[string(pkiID)] 511 d.lock.RUnlock() 512 513 if !known { 514 d.learnNewMembers([]*protoext.SignedGossipMessage{m}, []*protoext.SignedGossipMessage{}) 515 return 516 } 517 518 d.lock.RLock() 519 _, isAlive := d.aliveLastTS[string(pkiID)] 520 lastDeadTS, isDead := d.deadLastTS[string(pkiID)] 521 d.lock.RUnlock() 522 523 if !isAlive && !isDead { 524 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) 525 return 526 } 527 528 if isAlive && isDead { 529 d.logger.Panicf("Member %s is both alive and dead at the same time", m.GetAliveMsg().Membership) 530 return 531 } 532 533 if isDead { 534 if before(lastDeadTS, ts) { 535 // resurrect peer 536 d.resurrectMember(m, *ts) 537 } else if !same(lastDeadTS, ts) { 538 d.logger.Debug("got old alive message about dead peer ", protoext.MemberToString(m.GetAliveMsg().Membership), "lastDeadTS:", lastDeadTS, "but got ts:", ts) 539 } 540 return 541 } 542 543 d.lock.RLock() 544 lastAliveTS, isAlive := d.aliveLastTS[string(pkiID)] 545 d.lock.RUnlock() 546 547 if isAlive { 548 if before(lastAliveTS, ts) { 549 d.learnExistingMembers([]*protoext.SignedGossipMessage{m}) 550 } else if !same(lastAliveTS, ts) { 551 d.logger.Debug("got old alive message about alive peer ", protoext.MemberToString(m.GetAliveMsg().Membership), "lastAliveTS:", lastAliveTS, "but got ts:", ts) 552 } 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(common.PKIidType(pkiID)) 623 d.aliveMembership.Put(common.PKIidType(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: uint64(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 966 func tsToTime(ts uint64) time.Time { 967 return time.Unix(int64(0), int64(ts)) 968 } 969 970 func (d *gossipDiscoveryImpl) UpdateMetadata(md []byte) { 971 d.lock.Lock() 972 defer d.lock.Unlock() 973 d.self.Metadata = md 974 } 975 976 func (d *gossipDiscoveryImpl) UpdateEndpoint(endpoint string) { 977 d.lock.Lock() 978 defer d.lock.Unlock() 979 980 d.self.Endpoint = endpoint 981 } 982 983 func (d *gossipDiscoveryImpl) Self() NetworkMember { 984 var env *proto.Envelope 985 msg, _ := d.aliveMsgAndInternalEndpoint() 986 sMsg, err := protoext.NoopSign(msg) 987 if err != nil { 988 d.logger.Warning("Failed creating SignedGossipMessage:", err) 989 } else { 990 env = sMsg.Envelope 991 } 992 mem := msg.GetAliveMsg().Membership 993 return NetworkMember{ 994 Endpoint: mem.Endpoint, 995 Metadata: mem.Metadata, 996 PKIid: mem.PkiId, 997 Envelope: env, 998 } 999 } 1000 1001 func (d *gossipDiscoveryImpl) toDie() bool { 1002 select { 1003 case <-d.toDieChan: 1004 return true 1005 default: 1006 return false 1007 } 1008 } 1009 1010 func (d *gossipDiscoveryImpl) Stop() { 1011 select { 1012 case <-d.toDieChan: 1013 default: 1014 close(d.toDieChan) 1015 defer d.logger.Info("Stopped") 1016 d.logger.Info("Stopping") 1017 d.msgStore.Stop() 1018 } 1019 } 1020 1021 func copyNetworkMember(member *NetworkMember) *NetworkMember { 1022 if member == nil { 1023 return nil 1024 } else { 1025 copiedNetworkMember := &NetworkMember{} 1026 *copiedNetworkMember = *member 1027 return copiedNetworkMember 1028 } 1029 } 1030 1031 func equalPKIid(a, b common.PKIidType) bool { 1032 return bytes.Equal(a, b) 1033 } 1034 1035 func same(a *timestamp, b *proto.PeerTime) bool { 1036 return uint64(a.incTime.UnixNano()) == b.IncNum && a.seqNum == b.SeqNum 1037 } 1038 1039 func before(a *timestamp, b *proto.PeerTime) bool { 1040 return (uint64(a.incTime.UnixNano()) == b.IncNum && a.seqNum < b.SeqNum) || 1041 uint64(a.incTime.UnixNano()) < b.IncNum 1042 } 1043 1044 type aliveMsgStore struct { 1045 msgstore.MessageStore 1046 } 1047 1048 func newAliveMsgStore(d *gossipDiscoveryImpl) *aliveMsgStore { 1049 policy := protoext.NewGossipMessageComparator(0) 1050 trigger := func(m interface{}) {} 1051 aliveMsgTTL := d.aliveExpirationTimeout * time.Duration(d.msgExpirationFactor) 1052 externalLock := func() { d.lock.Lock() } 1053 externalUnlock := func() { d.lock.Unlock() } 1054 callback := func(m interface{}) { 1055 msg := m.(*protoext.SignedGossipMessage) 1056 if !protoext.IsAliveMsg(msg.GossipMessage) { 1057 return 1058 } 1059 membership := msg.GetAliveMsg().Membership 1060 id := membership.PkiId 1061 endpoint := membership.Endpoint 1062 internalEndpoint := protoext.InternalEndpoint(msg.SecretEnvelope) 1063 if util.Contains(endpoint, d.bootstrapPeers) || util.Contains(internalEndpoint, d.bootstrapPeers) || 1064 d.anchorPeerTracker.IsAnchorPeer(endpoint) || d.anchorPeerTracker.IsAnchorPeer(internalEndpoint) { 1065 // Never remove a bootstrap peer or an anchor peer 1066 d.logger.Debugf("Do not remove bootstrap or anchor peer endpoint %s from membership", endpoint) 1067 return 1068 } 1069 d.logger.Infof("Removing member: Endpoint: %s, InternalEndpoint: %s, PKIID: %x", endpoint, internalEndpoint, id) 1070 d.aliveMembership.Remove(id) 1071 d.deadMembership.Remove(id) 1072 delete(d.id2Member, string(id)) 1073 delete(d.deadLastTS, string(id)) 1074 delete(d.aliveLastTS, string(id)) 1075 } 1076 1077 s := &aliveMsgStore{ 1078 MessageStore: msgstore.NewMessageStoreExpirable(policy, trigger, aliveMsgTTL, externalLock, externalUnlock, callback), 1079 } 1080 return s 1081 } 1082 1083 func (s *aliveMsgStore) Add(msg interface{}) bool { 1084 m := msg.(*protoext.SignedGossipMessage) 1085 if !protoext.IsAliveMsg(m.GossipMessage) { 1086 panic(fmt.Sprint("Msg ", msg, " is not AliveMsg")) 1087 } 1088 return s.MessageStore.Add(msg) 1089 } 1090 1091 func (s *aliveMsgStore) CheckValid(msg interface{}) bool { 1092 m := msg.(*protoext.SignedGossipMessage) 1093 if !protoext.IsAliveMsg(m.GossipMessage) { 1094 panic(fmt.Sprint("Msg ", msg, " is not AliveMsg")) 1095 } 1096 return s.MessageStore.CheckValid(msg) 1097 }