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)] = &timestamp{
   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)] = &timestamp{
   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)] = &timestamp{
   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  }