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