github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/gossip/comm/comm_impl.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package comm
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/tls"
    22  	"errors"
    23  	"fmt"
    24  	"net"
    25  	"reflect"
    26  	"sync"
    27  	"sync/atomic"
    28  	"time"
    29  
    30  	"github.com/hyperledger/fabric/gossip/api"
    31  	"github.com/hyperledger/fabric/gossip/common"
    32  	"github.com/hyperledger/fabric/gossip/identity"
    33  	"github.com/hyperledger/fabric/gossip/util"
    34  	proto "github.com/hyperledger/fabric/protos/gossip"
    35  	"github.com/op/go-logging"
    36  	"github.com/spf13/viper"
    37  	"golang.org/x/net/context"
    38  	"google.golang.org/grpc"
    39  	"google.golang.org/grpc/credentials"
    40  	"google.golang.org/grpc/peer"
    41  )
    42  
    43  const (
    44  	defDialTimeout  = time.Second * time.Duration(3)
    45  	defConnTimeout  = time.Second * time.Duration(2)
    46  	defRecvBuffSize = 20
    47  	defSendBuffSize = 20
    48  	sendOverflowErr = "Send buffer overflow"
    49  )
    50  
    51  var errSendOverflow = errors.New(sendOverflowErr)
    52  
    53  // SetDialTimeout sets the dial timeout
    54  func SetDialTimeout(timeout time.Duration) {
    55  	viper.Set("peer.gossip.dialTimeout", timeout)
    56  }
    57  
    58  func (c *commImpl) SetDialOpts(opts ...grpc.DialOption) {
    59  	if len(opts) == 0 {
    60  		c.logger.Warning("Given an empty set of grpc.DialOption, aborting")
    61  		return
    62  	}
    63  	c.opts = opts
    64  }
    65  
    66  // NewCommInstanceWithServer creates a comm instance that creates an underlying gRPC server
    67  func NewCommInstanceWithServer(port int, idMapper identity.Mapper, peerIdentity api.PeerIdentityType,
    68  	secureDialOpts api.PeerSecureDialOpts, dialOpts ...grpc.DialOption) (Comm, error) {
    69  
    70  	var ll net.Listener
    71  	var s *grpc.Server
    72  	var certHash []byte
    73  
    74  	if len(dialOpts) == 0 {
    75  		dialOpts = []grpc.DialOption{grpc.WithTimeout(util.GetDurationOrDefault("peer.gossip.dialTimeout", defDialTimeout))}
    76  	}
    77  
    78  	if port > 0 {
    79  		s, ll, secureDialOpts, certHash = createGRPCLayer(port)
    80  	}
    81  
    82  	commInst := &commImpl{
    83  		selfCertHash:   certHash,
    84  		PKIID:          idMapper.GetPKIidOfCert(peerIdentity),
    85  		idMapper:       idMapper,
    86  		logger:         util.GetLogger(util.LoggingCommModule, fmt.Sprintf("%d", port)),
    87  		peerIdentity:   peerIdentity,
    88  		opts:           dialOpts,
    89  		secureDialOpts: secureDialOpts,
    90  		port:           port,
    91  		lsnr:           ll,
    92  		gSrv:           s,
    93  		msgPublisher:   NewChannelDemultiplexer(),
    94  		lock:           &sync.RWMutex{},
    95  		deadEndpoints:  make(chan common.PKIidType, 100),
    96  		stopping:       int32(0),
    97  		exitChan:       make(chan struct{}, 1),
    98  		subscriptions:  make([]chan proto.ReceivedMessage, 0),
    99  	}
   100  	commInst.connStore = newConnStore(commInst, commInst.logger)
   101  
   102  	if port > 0 {
   103  		commInst.stopWG.Add(1)
   104  		go func() {
   105  			defer commInst.stopWG.Done()
   106  			s.Serve(ll)
   107  		}()
   108  		proto.RegisterGossipServer(s, commInst)
   109  	}
   110  
   111  	return commInst, nil
   112  }
   113  
   114  // NewCommInstance creates a new comm instance that binds itself to the given gRPC server
   115  func NewCommInstance(s *grpc.Server, cert *tls.Certificate, idStore identity.Mapper,
   116  	peerIdentity api.PeerIdentityType, secureDialOpts api.PeerSecureDialOpts,
   117  	dialOpts ...grpc.DialOption) (Comm, error) {
   118  
   119  	dialOpts = append(dialOpts, grpc.WithTimeout(util.GetDurationOrDefault("peer.gossip.dialTimeout", defDialTimeout)))
   120  	commInst, err := NewCommInstanceWithServer(-1, idStore, peerIdentity, secureDialOpts, dialOpts...)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	if cert != nil {
   126  		inst := commInst.(*commImpl)
   127  		if len(cert.Certificate) == 0 {
   128  			inst.logger.Panic("Certificate supplied but certificate chain is empty")
   129  		} else {
   130  			inst.selfCertHash = certHashFromRawCert(cert.Certificate[0])
   131  		}
   132  	}
   133  
   134  	proto.RegisterGossipServer(s, commInst.(*commImpl))
   135  
   136  	return commInst, nil
   137  }
   138  
   139  type commImpl struct {
   140  	selfCertHash   []byte
   141  	peerIdentity   api.PeerIdentityType
   142  	idMapper       identity.Mapper
   143  	logger         *logging.Logger
   144  	opts           []grpc.DialOption
   145  	secureDialOpts func() []grpc.DialOption
   146  	connStore      *connectionStore
   147  	PKIID          []byte
   148  	deadEndpoints  chan common.PKIidType
   149  	msgPublisher   *ChannelDeMultiplexer
   150  	lock           *sync.RWMutex
   151  	lsnr           net.Listener
   152  	gSrv           *grpc.Server
   153  	exitChan       chan struct{}
   154  	stopWG         sync.WaitGroup
   155  	subscriptions  []chan proto.ReceivedMessage
   156  	port           int
   157  	stopping       int32
   158  }
   159  
   160  func (c *commImpl) createConnection(endpoint string, expectedPKIID common.PKIidType) (*connection, error) {
   161  	var err error
   162  	var cc *grpc.ClientConn
   163  	var stream proto.Gossip_GossipStreamClient
   164  	var pkiID common.PKIidType
   165  	var connInfo *proto.ConnectionInfo
   166  	var dialOpts []grpc.DialOption
   167  
   168  	c.logger.Debug("Entering", endpoint, expectedPKIID)
   169  	defer c.logger.Debug("Exiting")
   170  
   171  	if c.isStopping() {
   172  		return nil, errors.New("Stopping")
   173  	}
   174  	dialOpts = append(dialOpts, c.secureDialOpts()...)
   175  	dialOpts = append(dialOpts, grpc.WithBlock())
   176  	dialOpts = append(dialOpts, c.opts...)
   177  	cc, err = grpc.Dial(endpoint, dialOpts...)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	cl := proto.NewGossipClient(cc)
   183  
   184  	if _, err = cl.Ping(context.Background(), &proto.Empty{}); err != nil {
   185  		cc.Close()
   186  		return nil, err
   187  	}
   188  
   189  	ctx, cf := context.WithCancel(context.Background())
   190  	if stream, err = cl.GossipStream(ctx); err == nil {
   191  		connInfo, err = c.authenticateRemotePeer(stream)
   192  		if err == nil {
   193  			pkiID = connInfo.ID
   194  			if expectedPKIID != nil && !bytes.Equal(pkiID, expectedPKIID) {
   195  				// PKIID is nil when we don't know the remote PKI id's
   196  				c.logger.Warning("Remote endpoint claims to be a different peer, expected", expectedPKIID, "but got", pkiID)
   197  				cc.Close()
   198  				return nil, errors.New("Authentication failure")
   199  			}
   200  			conn := newConnection(cl, cc, stream, nil)
   201  			conn.pkiID = pkiID
   202  			conn.info = connInfo
   203  			conn.logger = c.logger
   204  			conn.cancel = cf
   205  
   206  			h := func(m *proto.SignedGossipMessage) {
   207  				c.logger.Debug("Got message:", m)
   208  				c.msgPublisher.DeMultiplex(&ReceivedMessageImpl{
   209  					conn:                conn,
   210  					lock:                conn,
   211  					SignedGossipMessage: m,
   212  					connInfo:            connInfo,
   213  				})
   214  			}
   215  			conn.handler = h
   216  			return conn, nil
   217  		}
   218  		c.logger.Warning("Authentication failed:", err)
   219  	}
   220  	cc.Close()
   221  	return nil, err
   222  }
   223  
   224  func (c *commImpl) Send(msg *proto.SignedGossipMessage, peers ...*RemotePeer) {
   225  	if c.isStopping() || len(peers) == 0 {
   226  		return
   227  	}
   228  
   229  	c.logger.Debug("Entering, sending", msg, "to ", len(peers), "peers")
   230  
   231  	for _, peer := range peers {
   232  		go func(peer *RemotePeer, msg *proto.SignedGossipMessage) {
   233  			c.sendToEndpoint(peer, msg)
   234  		}(peer, msg)
   235  	}
   236  }
   237  
   238  func (c *commImpl) sendToEndpoint(peer *RemotePeer, msg *proto.SignedGossipMessage) {
   239  	if c.isStopping() {
   240  		return
   241  	}
   242  	c.logger.Debug("Entering, Sending to", peer.Endpoint, ", msg:", msg)
   243  	defer c.logger.Debug("Exiting")
   244  	var err error
   245  
   246  	conn, err := c.connStore.getConnection(peer)
   247  	if err == nil {
   248  		disConnectOnErr := func(err error) {
   249  			c.logger.Warning(peer, "isn't responsive:", err)
   250  			c.disconnect(peer.PKIID)
   251  		}
   252  		conn.send(msg, disConnectOnErr)
   253  		return
   254  	}
   255  	c.logger.Warning("Failed obtaining connection for", peer, "reason:", err)
   256  	c.disconnect(peer.PKIID)
   257  }
   258  
   259  func (c *commImpl) isStopping() bool {
   260  	return atomic.LoadInt32(&c.stopping) == int32(1)
   261  }
   262  
   263  func (c *commImpl) Probe(remotePeer *RemotePeer) error {
   264  	var dialOpts []grpc.DialOption
   265  	endpoint := remotePeer.Endpoint
   266  	pkiID := remotePeer.PKIID
   267  	if c.isStopping() {
   268  		return errors.New("Stopping")
   269  	}
   270  	c.logger.Debug("Entering, endpoint:", endpoint, "PKIID:", pkiID)
   271  	dialOpts = append(dialOpts, c.secureDialOpts()...)
   272  	dialOpts = append(dialOpts, grpc.WithBlock())
   273  	dialOpts = append(dialOpts, c.opts...)
   274  
   275  	cc, err := grpc.Dial(remotePeer.Endpoint, dialOpts...)
   276  	if err != nil {
   277  		c.logger.Debug("Returning", err)
   278  		return err
   279  	}
   280  	defer cc.Close()
   281  	cl := proto.NewGossipClient(cc)
   282  	_, err = cl.Ping(context.Background(), &proto.Empty{})
   283  	c.logger.Debug("Returning", err)
   284  	return err
   285  }
   286  
   287  func (c *commImpl) Handshake(remotePeer *RemotePeer) (api.PeerIdentityType, error) {
   288  	var dialOpts []grpc.DialOption
   289  	dialOpts = append(dialOpts, c.secureDialOpts()...)
   290  	dialOpts = append(dialOpts, grpc.WithBlock())
   291  	dialOpts = append(dialOpts, c.opts...)
   292  
   293  	cc, err := grpc.Dial(remotePeer.Endpoint, dialOpts...)
   294  	if err != nil {
   295  		return nil, err
   296  	}
   297  	defer cc.Close()
   298  
   299  	cl := proto.NewGossipClient(cc)
   300  	if _, err = cl.Ping(context.Background(), &proto.Empty{}); err != nil {
   301  		return nil, err
   302  	}
   303  
   304  	stream, err := cl.GossipStream(context.Background())
   305  	if err != nil {
   306  		return nil, err
   307  	}
   308  	connInfo, err := c.authenticateRemotePeer(stream)
   309  	if err != nil {
   310  		c.logger.Warning("Authentication failed:", err)
   311  		return nil, err
   312  	}
   313  	if len(remotePeer.PKIID) > 0 && !bytes.Equal(connInfo.ID, remotePeer.PKIID) {
   314  		return nil, errors.New("PKI-ID of remote peer doesn't match expected PKI-ID")
   315  	}
   316  	return connInfo.Identity, nil
   317  }
   318  
   319  func (c *commImpl) Accept(acceptor common.MessageAcceptor) <-chan proto.ReceivedMessage {
   320  	genericChan := c.msgPublisher.AddChannel(acceptor)
   321  	specificChan := make(chan proto.ReceivedMessage, 10)
   322  
   323  	if c.isStopping() {
   324  		c.logger.Warning("Accept() called but comm module is stopping, returning empty channel")
   325  		return specificChan
   326  	}
   327  
   328  	c.lock.Lock()
   329  	c.subscriptions = append(c.subscriptions, specificChan)
   330  	c.lock.Unlock()
   331  
   332  	go func() {
   333  		defer c.logger.Debug("Exiting Accept() loop")
   334  		defer func() {
   335  			recover()
   336  		}()
   337  
   338  		c.stopWG.Add(1)
   339  		defer c.stopWG.Done()
   340  
   341  		for {
   342  			select {
   343  			case msg := <-genericChan:
   344  				specificChan <- msg.(*ReceivedMessageImpl)
   345  			case s := <-c.exitChan:
   346  				c.exitChan <- s
   347  				return
   348  			}
   349  		}
   350  	}()
   351  	return specificChan
   352  }
   353  
   354  func (c *commImpl) PresumedDead() <-chan common.PKIidType {
   355  	return c.deadEndpoints
   356  }
   357  
   358  func (c *commImpl) CloseConn(peer *RemotePeer) {
   359  	c.logger.Debug("Closing connection for", peer)
   360  	c.connStore.closeConn(peer)
   361  }
   362  
   363  func (c *commImpl) emptySubscriptions() {
   364  	c.lock.Lock()
   365  	defer c.lock.Unlock()
   366  	for _, ch := range c.subscriptions {
   367  		close(ch)
   368  	}
   369  }
   370  
   371  func (c *commImpl) Stop() {
   372  	if c.isStopping() {
   373  		return
   374  	}
   375  	atomic.StoreInt32(&c.stopping, int32(1))
   376  	c.logger.Info("Stopping")
   377  	defer c.logger.Info("Stopped")
   378  	if c.gSrv != nil {
   379  		c.gSrv.Stop()
   380  	}
   381  	if c.lsnr != nil {
   382  		c.lsnr.Close()
   383  	}
   384  	c.connStore.shutdown()
   385  	c.logger.Debug("Shut down connection store, connection count:", c.connStore.connNum())
   386  	c.exitChan <- struct{}{}
   387  	c.msgPublisher.Close()
   388  	c.logger.Debug("Shut down publisher")
   389  	c.emptySubscriptions()
   390  	c.logger.Debug("Closed subscriptions, waiting for goroutines to stop...")
   391  	c.stopWG.Wait()
   392  }
   393  
   394  func (c *commImpl) GetPKIid() common.PKIidType {
   395  	return c.PKIID
   396  }
   397  
   398  func extractRemoteAddress(stream stream) string {
   399  	var remoteAddress string
   400  	p, ok := peer.FromContext(stream.Context())
   401  	if ok {
   402  		if address := p.Addr; address != nil {
   403  			remoteAddress = address.String()
   404  		}
   405  	}
   406  	return remoteAddress
   407  }
   408  
   409  func (c *commImpl) authenticateRemotePeer(stream stream) (*proto.ConnectionInfo, error) {
   410  	ctx := stream.Context()
   411  	remoteAddress := extractRemoteAddress(stream)
   412  	remoteCertHash := extractCertificateHashFromContext(ctx)
   413  	var err error
   414  	var cMsg *proto.SignedGossipMessage
   415  	var signer proto.Signer
   416  	useTLS := c.selfCertHash != nil
   417  
   418  	// If TLS is enabled, sign the connection message in order to bind
   419  	// the TLS session to the peer's identity
   420  	if useTLS {
   421  		signer = func(msg []byte) ([]byte, error) {
   422  			return c.idMapper.Sign(msg)
   423  		}
   424  	} else { // If we don't use TLS, we have no unique text to sign,
   425  		//  so don't sign anything
   426  		signer = func(msg []byte) ([]byte, error) {
   427  			return msg, nil
   428  		}
   429  	}
   430  
   431  	// TLS enabled but not detected on other side
   432  	if useTLS && len(remoteCertHash) == 0 {
   433  		c.logger.Warningf("%s didn't send TLS certificate", remoteAddress)
   434  		return nil, errors.New("No TLS certificate")
   435  	}
   436  
   437  	cMsg, err = c.createConnectionMsg(c.PKIID, c.selfCertHash, c.peerIdentity, signer)
   438  	if err != nil {
   439  		return nil, err
   440  	}
   441  
   442  	c.logger.Debug("Sending", cMsg, "to", remoteAddress)
   443  	stream.Send(cMsg.Envelope)
   444  	m, err := readWithTimeout(stream, util.GetDurationOrDefault("peer.gossip.connTimeout", defConnTimeout), remoteAddress)
   445  	if err != nil {
   446  		c.logger.Warningf("Failed reading messge from %s, reason: %v", remoteAddress, err)
   447  		return nil, err
   448  	}
   449  	receivedMsg := m.GetConn()
   450  	if receivedMsg == nil {
   451  		c.logger.Warning("Expected connection message from", remoteAddress, "but got", receivedMsg)
   452  		return nil, errors.New("Wrong type")
   453  	}
   454  
   455  	if receivedMsg.PkiId == nil {
   456  		c.logger.Warning("%s didn't send a pkiID", remoteAddress)
   457  		return nil, errors.New("No PKI-ID")
   458  	}
   459  
   460  	c.logger.Debug("Received", receivedMsg, "from", remoteAddress)
   461  	err = c.idMapper.Put(receivedMsg.PkiId, receivedMsg.Identity)
   462  	if err != nil {
   463  		c.logger.Warning("Identity store rejected", remoteAddress, ":", err)
   464  		return nil, err
   465  	}
   466  
   467  	connInfo := &proto.ConnectionInfo{
   468  		ID:       receivedMsg.PkiId,
   469  		Identity: receivedMsg.Identity,
   470  		Endpoint: remoteAddress,
   471  	}
   472  
   473  	// if TLS is enabled and detected, verify remote peer
   474  	if useTLS {
   475  		// If the remote peer sent its TLS certificate, make sure it actually matches the TLS cert
   476  		// that the peer used.
   477  		if !bytes.Equal(remoteCertHash, receivedMsg.TlsCertHash) {
   478  			return nil, fmt.Errorf("Expected %v in remote hash of TLS cert, but got %v", remoteCertHash, receivedMsg.TlsCertHash)
   479  		}
   480  		verifier := func(peerIdentity []byte, signature, message []byte) error {
   481  			pkiID := c.idMapper.GetPKIidOfCert(api.PeerIdentityType(peerIdentity))
   482  			return c.idMapper.Verify(pkiID, signature, message)
   483  		}
   484  		err = m.Verify(receivedMsg.Identity, verifier)
   485  		if err != nil {
   486  			c.logger.Error("Failed verifying signature from", remoteAddress, ":", err)
   487  			return nil, err
   488  		}
   489  		connInfo.Auth = &proto.AuthInfo{
   490  			Signature:  m.Signature,
   491  			SignedData: m.Payload,
   492  		}
   493  	}
   494  
   495  	c.logger.Debug("Authenticated", remoteAddress)
   496  
   497  	return connInfo, nil
   498  }
   499  
   500  func (c *commImpl) GossipStream(stream proto.Gossip_GossipStreamServer) error {
   501  	if c.isStopping() {
   502  		return errors.New("Shutting down")
   503  	}
   504  	connInfo, err := c.authenticateRemotePeer(stream)
   505  	if err != nil {
   506  		c.logger.Error("Authentication failed:", err)
   507  		return err
   508  	}
   509  	c.logger.Debug("Servicing", extractRemoteAddress(stream))
   510  
   511  	conn := c.connStore.onConnected(stream, connInfo)
   512  
   513  	// if connStore denied the connection, it means we already have a connection to that peer
   514  	// so close this stream
   515  	if conn == nil {
   516  		return nil
   517  	}
   518  
   519  	h := func(m *proto.SignedGossipMessage) {
   520  		c.msgPublisher.DeMultiplex(&ReceivedMessageImpl{
   521  			conn:                conn,
   522  			lock:                conn,
   523  			SignedGossipMessage: m,
   524  			connInfo:            connInfo,
   525  		})
   526  	}
   527  
   528  	conn.handler = h
   529  
   530  	defer func() {
   531  		c.logger.Debug("Client", extractRemoteAddress(stream), " disconnected")
   532  		c.connStore.closeByPKIid(connInfo.ID)
   533  		conn.close()
   534  	}()
   535  
   536  	return conn.serviceConnection()
   537  }
   538  
   539  func (c *commImpl) Ping(context.Context, *proto.Empty) (*proto.Empty, error) {
   540  	return &proto.Empty{}, nil
   541  }
   542  
   543  func (c *commImpl) disconnect(pkiID common.PKIidType) {
   544  	if c.isStopping() {
   545  		return
   546  	}
   547  	c.deadEndpoints <- pkiID
   548  	c.connStore.closeByPKIid(pkiID)
   549  }
   550  
   551  func readWithTimeout(stream interface{}, timeout time.Duration, address string) (*proto.SignedGossipMessage, error) {
   552  	incChan := make(chan *proto.SignedGossipMessage, 1)
   553  	errChan := make(chan error, 1)
   554  	go func() {
   555  		if srvStr, isServerStr := stream.(proto.Gossip_GossipStreamServer); isServerStr {
   556  			if m, err := srvStr.Recv(); err == nil {
   557  				msg, err := m.ToGossipMessage()
   558  				if err != nil {
   559  					errChan <- err
   560  					return
   561  				}
   562  				incChan <- msg
   563  			}
   564  		} else if clStr, isClientStr := stream.(proto.Gossip_GossipStreamClient); isClientStr {
   565  			if m, err := clStr.Recv(); err == nil {
   566  				msg, err := m.ToGossipMessage()
   567  				if err != nil {
   568  					errChan <- err
   569  					return
   570  				}
   571  				incChan <- msg
   572  			}
   573  		} else {
   574  			panic(fmt.Errorf("Stream isn't a GossipStreamServer or a GossipStreamClient, but %v. Aborting", reflect.TypeOf(stream)))
   575  		}
   576  	}()
   577  	select {
   578  	case <-time.NewTicker(timeout).C:
   579  		return nil, fmt.Errorf("Timed out waiting for connection message from %s", address)
   580  	case m := <-incChan:
   581  		return m, nil
   582  	case err := <-errChan:
   583  		return nil, err
   584  	}
   585  }
   586  
   587  func (c *commImpl) createConnectionMsg(pkiID common.PKIidType, certHash []byte, cert api.PeerIdentityType, signer proto.Signer) (*proto.SignedGossipMessage, error) {
   588  	m := &proto.GossipMessage{
   589  		Tag:   proto.GossipMessage_EMPTY,
   590  		Nonce: 0,
   591  		Content: &proto.GossipMessage_Conn{
   592  			Conn: &proto.ConnEstablish{
   593  				TlsCertHash: certHash,
   594  				Identity:    cert,
   595  				PkiId:       pkiID,
   596  			},
   597  		},
   598  	}
   599  	sMsg := &proto.SignedGossipMessage{
   600  		GossipMessage: m,
   601  	}
   602  	_, err := sMsg.Sign(signer)
   603  	return sMsg, err
   604  }
   605  
   606  type stream interface {
   607  	Send(envelope *proto.Envelope) error
   608  	Recv() (*proto.Envelope, error)
   609  	grpc.Stream
   610  }
   611  
   612  func createGRPCLayer(port int) (*grpc.Server, net.Listener, api.PeerSecureDialOpts, []byte) {
   613  	var returnedCertHash []byte
   614  	var s *grpc.Server
   615  	var ll net.Listener
   616  	var err error
   617  	var serverOpts []grpc.ServerOption
   618  	var dialOpts []grpc.DialOption
   619  
   620  	cert := GenerateCertificatesOrPanic()
   621  	returnedCertHash = certHashFromRawCert(cert.Certificate[0])
   622  
   623  	tlsConf := &tls.Config{
   624  		Certificates:       []tls.Certificate{cert},
   625  		ClientAuth:         tls.RequestClientCert,
   626  		InsecureSkipVerify: true,
   627  	}
   628  	serverOpts = append(serverOpts, grpc.Creds(credentials.NewTLS(tlsConf)))
   629  	ta := credentials.NewTLS(&tls.Config{
   630  		Certificates:       []tls.Certificate{cert},
   631  		InsecureSkipVerify: true,
   632  	})
   633  	dialOpts = append(dialOpts, grpc.WithTransportCredentials(ta))
   634  
   635  	listenAddress := fmt.Sprintf("%s:%d", "", port)
   636  	ll, err = net.Listen("tcp", listenAddress)
   637  	if err != nil {
   638  		panic(err)
   639  	}
   640  	secureDialOpts := func() []grpc.DialOption {
   641  		return dialOpts
   642  	}
   643  	s = grpc.NewServer(serverOpts...)
   644  	return s, ll, secureDialOpts, returnedCertHash
   645  }