github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/deliverservice/config.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package deliverservice
     8  
     9  import (
    10  	"encoding/pem"
    11  	"io/ioutil"
    12  	"time"
    13  
    14  	"github.com/hechain20/hechain/core/config"
    15  	"github.com/hechain20/hechain/internal/pkg/comm"
    16  	"github.com/hechain20/hechain/internal/pkg/peer/orderers"
    17  
    18  	"github.com/pkg/errors"
    19  	"github.com/spf13/viper"
    20  )
    21  
    22  const (
    23  	DefaultReConnectBackoffThreshold   = time.Hour * 1
    24  	DefaultReConnectTotalTimeThreshold = time.Second * 60 * 60
    25  	DefaultConnectionTimeout           = time.Second * 3
    26  )
    27  
    28  // DeliverServiceConfig is the struct that defines the deliverservice configuration.
    29  type DeliverServiceConfig struct {
    30  	// PeerTLSEnabled enables/disables Peer TLS.
    31  	PeerTLSEnabled bool
    32  	// BlockGossipEnabled enables block forwarding via gossip
    33  	BlockGossipEnabled bool
    34  	// ReConnectBackoffThreshold sets the delivery service maximal delay between consencutive retries.
    35  	ReConnectBackoffThreshold time.Duration
    36  	// ReconnectTotalTimeThreshold sets the total time the delivery service may spend in reconnection attempts
    37  	// until its retry logic gives up and returns an error.
    38  	ReconnectTotalTimeThreshold time.Duration
    39  	// ConnectionTimeout sets the delivery service <-> ordering service node connection timeout
    40  	ConnectionTimeout time.Duration
    41  	// Keepalive option for deliveryservice
    42  	KeepaliveOptions comm.KeepaliveOptions
    43  	// SecOpts provides the TLS info for connections
    44  	SecOpts comm.SecureOptions
    45  
    46  	// OrdererEndpointOverrides is a map of orderer addresses which should be
    47  	// re-mapped to a different orderer endpoint.
    48  	OrdererEndpointOverrides map[string]*orderers.Endpoint
    49  }
    50  
    51  type AddressOverride struct {
    52  	From        string
    53  	To          string
    54  	CACertsFile string
    55  }
    56  
    57  // GlobalConfig obtains a set of configuration from viper, build and returns the config struct.
    58  func GlobalConfig() *DeliverServiceConfig {
    59  	c := &DeliverServiceConfig{}
    60  	c.loadDeliverServiceConfig()
    61  	return c
    62  }
    63  
    64  func LoadOverridesMap() (map[string]*orderers.Endpoint, error) {
    65  	var overrides []AddressOverride
    66  	err := viper.UnmarshalKey("peer.deliveryclient.addressOverrides", &overrides)
    67  	if err != nil {
    68  		return nil, errors.WithMessage(err, "could not unmarshal peer.deliveryclient.addressOverrides")
    69  	}
    70  
    71  	if len(overrides) == 0 {
    72  		return nil, nil
    73  	}
    74  
    75  	overrideMap := map[string]*orderers.Endpoint{}
    76  	for _, override := range overrides {
    77  		var rootCerts [][]byte
    78  		if override.CACertsFile != "" {
    79  			pem, err := ioutil.ReadFile(override.CACertsFile)
    80  			if err != nil {
    81  				logger.Warningf("could not read file '%s' specified for caCertsFile of orderer endpoint override from '%s' to '%s': %s", override.CACertsFile, override.From, override.To, err)
    82  				continue
    83  			}
    84  			rootCerts = extractCerts(pem)
    85  			if len(rootCerts) == 0 {
    86  				logger.Warningf("Attempted to create a cert pool for override of orderer address '%s' to '%s' but did not find any valid certs in '%s'", override.From, override.To, override.CACertsFile)
    87  				continue
    88  			}
    89  		}
    90  		overrideMap[override.From] = &orderers.Endpoint{
    91  			Address:   override.To,
    92  			RootCerts: rootCerts,
    93  		}
    94  	}
    95  
    96  	return overrideMap, nil
    97  }
    98  
    99  // extractCerts is a hacky way of breaking apart a collection of PEM encoded
   100  // certificates. This is used to preserve the semantics of
   101  // x509.CertPool#AppendCertsFromPEM after removing the CertPool from the
   102  // orderers.Endpoint.
   103  func extractCerts(pemCerts []byte) [][]byte {
   104  	var certs [][]byte
   105  	for len(pemCerts) > 0 {
   106  		var block *pem.Block
   107  		block, pemCerts = pem.Decode(pemCerts)
   108  		if block == nil {
   109  			break
   110  		}
   111  		if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
   112  			continue
   113  		}
   114  		certs = append(certs, pem.EncodeToMemory(block))
   115  	}
   116  	return certs
   117  }
   118  
   119  func (c *DeliverServiceConfig) loadDeliverServiceConfig() {
   120  	enabledKey := "peer.deliveryclient.blockGossipEnabled"
   121  	enabledConfigOptionMissing := !viper.IsSet(enabledKey)
   122  	if enabledConfigOptionMissing {
   123  		logger.Infof("peer.deliveryclient.blockGossipEnabled is not set, defaulting to true.")
   124  	}
   125  	c.BlockGossipEnabled = enabledConfigOptionMissing || viper.GetBool(enabledKey)
   126  
   127  	c.PeerTLSEnabled = viper.GetBool("peer.tls.enabled")
   128  
   129  	c.ReConnectBackoffThreshold = viper.GetDuration("peer.deliveryclient.reConnectBackoffThreshold")
   130  	if c.ReConnectBackoffThreshold == 0 {
   131  		c.ReConnectBackoffThreshold = DefaultReConnectBackoffThreshold
   132  	}
   133  
   134  	c.ReconnectTotalTimeThreshold = viper.GetDuration("peer.deliveryclient.reconnectTotalTimeThreshold")
   135  	if c.ReconnectTotalTimeThreshold == 0 {
   136  		c.ReconnectTotalTimeThreshold = DefaultReConnectTotalTimeThreshold
   137  	}
   138  
   139  	c.ConnectionTimeout = viper.GetDuration("peer.deliveryclient.connTimeout")
   140  	if c.ConnectionTimeout == 0 {
   141  		c.ConnectionTimeout = DefaultConnectionTimeout
   142  	}
   143  
   144  	c.KeepaliveOptions = comm.DefaultKeepaliveOptions
   145  	if viper.IsSet("peer.keepalive.deliveryClient.interval") {
   146  		c.KeepaliveOptions.ClientInterval = viper.GetDuration("peer.keepalive.deliveryClient.interval")
   147  	}
   148  	if viper.IsSet("peer.keepalive.deliveryClient.timeout") {
   149  		c.KeepaliveOptions.ClientTimeout = viper.GetDuration("peer.keepalive.deliveryClient.timeout")
   150  	}
   151  
   152  	c.SecOpts = comm.SecureOptions{
   153  		UseTLS:            viper.GetBool("peer.tls.enabled"),
   154  		RequireClientCert: viper.GetBool("peer.tls.clientAuthRequired"),
   155  	}
   156  
   157  	if c.SecOpts.RequireClientCert {
   158  		certFile := config.GetPath("peer.tls.clientCert.file")
   159  		if certFile == "" {
   160  			certFile = config.GetPath("peer.tls.cert.file")
   161  		}
   162  
   163  		keyFile := config.GetPath("peer.tls.clientKey.file")
   164  		if keyFile == "" {
   165  			keyFile = config.GetPath("peer.tls.key.file")
   166  		}
   167  
   168  		keyPEM, err := ioutil.ReadFile(keyFile)
   169  		if err != nil {
   170  			panic(errors.WithMessagef(err, "unable to load key at '%s'", keyFile))
   171  		}
   172  		c.SecOpts.Key = keyPEM
   173  		certPEM, err := ioutil.ReadFile(certFile)
   174  		if err != nil {
   175  			panic(errors.WithMessagef(err, "unable to load cert at '%s'", certFile))
   176  		}
   177  		c.SecOpts.Certificate = certPEM
   178  	}
   179  
   180  	overridesMap, err := LoadOverridesMap()
   181  	if err != nil {
   182  		panic(err)
   183  	}
   184  
   185  	c.OrdererEndpointOverrides = overridesMap
   186  }