github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/orderer/common/cluster/util.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package cluster
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/x509"
    12  	"encoding/hex"
    13  	"encoding/json"
    14  	"encoding/pem"
    15  	"fmt"
    16  	"sync"
    17  	"sync/atomic"
    18  	"time"
    19  
    20  	"github.com/hyperledger/fabric-protos-go/common"
    21  	"github.com/hyperledger/fabric/bccsp"
    22  	"github.com/hyperledger/fabric/common/channelconfig"
    23  	"github.com/hyperledger/fabric/common/configtx"
    24  	"github.com/hyperledger/fabric/common/flogging"
    25  	"github.com/hyperledger/fabric/common/policies"
    26  	"github.com/hyperledger/fabric/common/tools/protolator"
    27  	"github.com/hyperledger/fabric/common/util"
    28  	"github.com/hyperledger/fabric/core/comm"
    29  	"github.com/hyperledger/fabric/protoutil"
    30  	"github.com/pkg/errors"
    31  	"google.golang.org/grpc"
    32  )
    33  
    34  // ConnByCertMap maps certificates represented as strings
    35  // to gRPC connections
    36  type ConnByCertMap map[string]*grpc.ClientConn
    37  
    38  // Lookup looks up a certificate and returns the connection that was mapped
    39  // to the certificate, and whether it was found or not
    40  func (cbc ConnByCertMap) Lookup(cert []byte) (*grpc.ClientConn, bool) {
    41  	conn, ok := cbc[string(cert)]
    42  	return conn, ok
    43  }
    44  
    45  // Put associates the given connection to the certificate
    46  func (cbc ConnByCertMap) Put(cert []byte, conn *grpc.ClientConn) {
    47  	cbc[string(cert)] = conn
    48  }
    49  
    50  // Remove removes the connection that is associated to the given certificate
    51  func (cbc ConnByCertMap) Remove(cert []byte) {
    52  	delete(cbc, string(cert))
    53  }
    54  
    55  func (cbc ConnByCertMap) Size() int {
    56  	return len(cbc)
    57  }
    58  
    59  // MemberMapping defines NetworkMembers by their ID
    60  type MemberMapping map[uint64]*Stub
    61  
    62  // Put inserts the given stub to the MemberMapping
    63  func (mp MemberMapping) Put(stub *Stub) {
    64  	mp[stub.ID] = stub
    65  }
    66  
    67  // ByID retrieves the Stub with the given ID from the MemberMapping
    68  func (mp MemberMapping) ByID(ID uint64) *Stub {
    69  	return mp[ID]
    70  }
    71  
    72  // LookupByClientCert retrieves a Stub with the given client certificate
    73  func (mp MemberMapping) LookupByClientCert(cert []byte) *Stub {
    74  	for _, stub := range mp {
    75  		if bytes.Equal(stub.ClientTLSCert, cert) {
    76  			return stub
    77  		}
    78  	}
    79  	return nil
    80  }
    81  
    82  // ServerCertificates returns a set of the server certificates
    83  // represented as strings
    84  func (mp MemberMapping) ServerCertificates() StringSet {
    85  	res := make(StringSet)
    86  	for _, member := range mp {
    87  		res[string(member.ServerTLSCert)] = struct{}{}
    88  	}
    89  	return res
    90  }
    91  
    92  // StringSet is a set of strings
    93  type StringSet map[string]struct{}
    94  
    95  // union adds the elements of the given set to the StringSet
    96  func (ss StringSet) union(set StringSet) {
    97  	for k := range set {
    98  		ss[k] = struct{}{}
    99  	}
   100  }
   101  
   102  // subtract removes all elements in the given set from the StringSet
   103  func (ss StringSet) subtract(set StringSet) {
   104  	for k := range set {
   105  		delete(ss, k)
   106  	}
   107  }
   108  
   109  // PredicateDialer creates gRPC connections
   110  // that are only established if the given predicate
   111  // is fulfilled
   112  type PredicateDialer struct {
   113  	lock   sync.RWMutex
   114  	Config comm.ClientConfig
   115  }
   116  
   117  func (dialer *PredicateDialer) UpdateRootCAs(serverRootCAs [][]byte) {
   118  	dialer.lock.Lock()
   119  	defer dialer.lock.Unlock()
   120  	dialer.Config.SecOpts.ServerRootCAs = serverRootCAs
   121  }
   122  
   123  // Dial creates a new gRPC connection that can only be established, if the remote node's
   124  // certificate chain satisfy verifyFunc
   125  func (dialer *PredicateDialer) Dial(address string, verifyFunc RemoteVerifier) (*grpc.ClientConn, error) {
   126  	dialer.lock.RLock()
   127  	cfg := dialer.Config.Clone()
   128  	dialer.lock.RUnlock()
   129  
   130  	cfg.SecOpts.VerifyCertificate = verifyFunc
   131  	client, err := comm.NewGRPCClient(cfg)
   132  	if err != nil {
   133  		return nil, errors.WithStack(err)
   134  	}
   135  	return client.NewConnection(address)
   136  }
   137  
   138  // DERtoPEM returns a PEM representation of the DER
   139  // encoded certificate
   140  func DERtoPEM(der []byte) string {
   141  	return string(pem.EncodeToMemory(&pem.Block{
   142  		Type:  "CERTIFICATE",
   143  		Bytes: der,
   144  	}))
   145  }
   146  
   147  // StandardDialer wraps an ClientConfig, and provides
   148  // a means to connect according to given EndpointCriteria.
   149  type StandardDialer struct {
   150  	Config comm.ClientConfig
   151  }
   152  
   153  // Dial dials an address according to the given EndpointCriteria
   154  func (dialer *StandardDialer) Dial(endpointCriteria EndpointCriteria) (*grpc.ClientConn, error) {
   155  	cfg := dialer.Config.Clone()
   156  	cfg.SecOpts.ServerRootCAs = endpointCriteria.TLSRootCAs
   157  
   158  	client, err := comm.NewGRPCClient(cfg)
   159  	if err != nil {
   160  		return nil, errors.Wrap(err, "failed creating gRPC client")
   161  	}
   162  
   163  	return client.NewConnection(endpointCriteria.Endpoint)
   164  }
   165  
   166  //go:generate mockery -dir . -name BlockVerifier -case underscore -output ./mocks/
   167  
   168  // BlockVerifier verifies block signatures.
   169  type BlockVerifier interface {
   170  	// VerifyBlockSignature verifies a signature of a block.
   171  	// It has an optional argument of a configuration envelope
   172  	// which would make the block verification to use validation rules
   173  	// based on the given configuration in the ConfigEnvelope.
   174  	// If the config envelope passed is nil, then the validation rules used
   175  	// are the ones that were applied at commit of previous blocks.
   176  	VerifyBlockSignature(sd []*protoutil.SignedData, config *common.ConfigEnvelope) error
   177  }
   178  
   179  // BlockSequenceVerifier verifies that the given consecutive sequence
   180  // of blocks is valid.
   181  type BlockSequenceVerifier func(blocks []*common.Block, channel string) error
   182  
   183  // Dialer creates a gRPC connection to a remote address
   184  type Dialer interface {
   185  	Dial(endpointCriteria EndpointCriteria) (*grpc.ClientConn, error)
   186  }
   187  
   188  // VerifyBlocks verifies the given consecutive sequence of blocks is valid,
   189  // and returns nil if it's valid, else an error.
   190  func VerifyBlocks(blockBuff []*common.Block, signatureVerifier BlockVerifier) error {
   191  	if len(blockBuff) == 0 {
   192  		return errors.New("buffer is empty")
   193  	}
   194  	// First, we verify that the block hash in every block is:
   195  	// Equal to the hash in the header
   196  	// Equal to the previous hash in the succeeding block
   197  	for i := range blockBuff {
   198  		if err := VerifyBlockHash(i, blockBuff); err != nil {
   199  			return err
   200  		}
   201  	}
   202  
   203  	var config *common.ConfigEnvelope
   204  	// Verify all configuration blocks that are found inside the block batch,
   205  	// with the configuration that was committed (nil) or with one that is picked up
   206  	// during iteration over the block batch.
   207  	for _, block := range blockBuff {
   208  		configFromBlock, err := ConfigFromBlock(block)
   209  		if err == errNotAConfig {
   210  			continue
   211  		}
   212  		if err != nil {
   213  			return err
   214  		}
   215  		// The block is a configuration block, so verify it
   216  		if err := VerifyBlockSignature(block, signatureVerifier, config); err != nil {
   217  			return err
   218  		}
   219  		config = configFromBlock
   220  	}
   221  
   222  	// Verify the last block's signature
   223  	lastBlock := blockBuff[len(blockBuff)-1]
   224  	return VerifyBlockSignature(lastBlock, signatureVerifier, config)
   225  }
   226  
   227  var errNotAConfig = errors.New("not a config block")
   228  
   229  // ConfigFromBlock returns a ConfigEnvelope if exists, or a *NotAConfigBlock error.
   230  // It may also return some other error in case parsing failed.
   231  func ConfigFromBlock(block *common.Block) (*common.ConfigEnvelope, error) {
   232  	if block == nil || block.Data == nil || len(block.Data.Data) == 0 {
   233  		return nil, errors.New("empty block")
   234  	}
   235  	txn := block.Data.Data[0]
   236  	env, err := protoutil.GetEnvelopeFromBlock(txn)
   237  	if err != nil {
   238  		return nil, errors.WithStack(err)
   239  	}
   240  	payload, err := protoutil.UnmarshalPayload(env.Payload)
   241  	if err != nil {
   242  		return nil, errors.WithStack(err)
   243  	}
   244  	if block.Header.Number == 0 {
   245  		configEnvelope, err := configtx.UnmarshalConfigEnvelope(payload.Data)
   246  		if err != nil {
   247  			return nil, errors.Wrap(err, "invalid config envelope")
   248  		}
   249  		return configEnvelope, nil
   250  	}
   251  	if payload.Header == nil {
   252  		return nil, errors.New("nil header in payload")
   253  	}
   254  	chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   255  	if err != nil {
   256  		return nil, errors.WithStack(err)
   257  	}
   258  	if common.HeaderType(chdr.Type) != common.HeaderType_CONFIG {
   259  		return nil, errNotAConfig
   260  	}
   261  	configEnvelope, err := configtx.UnmarshalConfigEnvelope(payload.Data)
   262  	if err != nil {
   263  		return nil, errors.Wrap(err, "invalid config envelope")
   264  	}
   265  	return configEnvelope, nil
   266  }
   267  
   268  // VerifyBlockHash verifies the hash chain of the block with the given index
   269  // among the blocks of the given block buffer.
   270  func VerifyBlockHash(indexInBuffer int, blockBuff []*common.Block) error {
   271  	if len(blockBuff) <= indexInBuffer {
   272  		return errors.Errorf("index %d out of bounds (total %d blocks)", indexInBuffer, len(blockBuff))
   273  	}
   274  	block := blockBuff[indexInBuffer]
   275  	if block.Header == nil {
   276  		return errors.New("missing block header")
   277  	}
   278  	seq := block.Header.Number
   279  	dataHash := protoutil.BlockDataHash(block.Data)
   280  	// Verify data hash matches the hash in the header
   281  	if !bytes.Equal(dataHash, block.Header.DataHash) {
   282  		computedHash := hex.EncodeToString(dataHash)
   283  		claimedHash := hex.EncodeToString(block.Header.DataHash)
   284  		return errors.Errorf("computed hash of block (%d) (%s) doesn't match claimed hash (%s)",
   285  			seq, computedHash, claimedHash)
   286  	}
   287  	// We have a previous block in the buffer, ensure current block's previous hash matches the previous one.
   288  	if indexInBuffer > 0 {
   289  		prevBlock := blockBuff[indexInBuffer-1]
   290  		currSeq := block.Header.Number
   291  		if prevBlock.Header == nil {
   292  			return errors.New("previous block header is nil")
   293  		}
   294  		prevSeq := prevBlock.Header.Number
   295  		if prevSeq+1 != currSeq {
   296  			return errors.Errorf("sequences %d and %d were received consecutively", prevSeq, currSeq)
   297  		}
   298  		if !bytes.Equal(block.Header.PreviousHash, protoutil.BlockHeaderHash(prevBlock.Header)) {
   299  			claimedPrevHash := hex.EncodeToString(block.Header.PreviousHash)
   300  			actualPrevHash := hex.EncodeToString(protoutil.BlockHeaderHash(prevBlock.Header))
   301  			return errors.Errorf("block [%d]'s hash (%s) mismatches block [%d]'s prev block hash (%s)",
   302  				prevSeq, actualPrevHash, currSeq, claimedPrevHash)
   303  		}
   304  	}
   305  	return nil
   306  }
   307  
   308  // SignatureSetFromBlock creates a signature set out of a block.
   309  func SignatureSetFromBlock(block *common.Block) ([]*protoutil.SignedData, error) {
   310  	if block.Metadata == nil || len(block.Metadata.Metadata) <= int(common.BlockMetadataIndex_SIGNATURES) {
   311  		return nil, errors.New("no metadata in block")
   312  	}
   313  	metadata, err := protoutil.GetMetadataFromBlock(block, common.BlockMetadataIndex_SIGNATURES)
   314  	if err != nil {
   315  		return nil, errors.Errorf("failed unmarshaling medatata for signatures: %v", err)
   316  	}
   317  
   318  	var signatureSet []*protoutil.SignedData
   319  	for _, metadataSignature := range metadata.Signatures {
   320  		sigHdr, err := protoutil.UnmarshalSignatureHeader(metadataSignature.SignatureHeader)
   321  		if err != nil {
   322  			return nil, errors.Errorf("failed unmarshaling signature header for block with id %d: %v",
   323  				block.Header.Number, err)
   324  		}
   325  		signatureSet = append(signatureSet,
   326  			&protoutil.SignedData{
   327  				Identity: sigHdr.Creator,
   328  				Data: util.ConcatenateBytes(metadata.Value,
   329  					metadataSignature.SignatureHeader, protoutil.BlockHeaderBytes(block.Header)),
   330  				Signature: metadataSignature.Signature,
   331  			},
   332  		)
   333  	}
   334  	return signatureSet, nil
   335  }
   336  
   337  // VerifyBlockSignature verifies the signature on the block with the given BlockVerifier and the given config.
   338  func VerifyBlockSignature(block *common.Block, verifier BlockVerifier, config *common.ConfigEnvelope) error {
   339  	signatureSet, err := SignatureSetFromBlock(block)
   340  	if err != nil {
   341  		return err
   342  	}
   343  	return verifier.VerifyBlockSignature(signatureSet, config)
   344  }
   345  
   346  // EndpointCriteria defines criteria of how to connect to a remote orderer node.
   347  type EndpointCriteria struct {
   348  	Endpoint   string   // Endpoint of the form host:port
   349  	TLSRootCAs [][]byte // PEM encoded TLS root CA certificates
   350  }
   351  
   352  // String returns a string representation of this EndpointCriteria
   353  func (ep EndpointCriteria) String() string {
   354  	var formattedCAs []interface{}
   355  	for _, rawCAFile := range ep.TLSRootCAs {
   356  		var bl *pem.Block
   357  		pemContent := rawCAFile
   358  		for {
   359  			bl, pemContent = pem.Decode(pemContent)
   360  			if bl == nil {
   361  				break
   362  			}
   363  			cert, err := x509.ParseCertificate(bl.Bytes)
   364  			if err != nil {
   365  				break
   366  			}
   367  
   368  			issuedBy := cert.Issuer.String()
   369  			if cert.Issuer.String() == cert.Subject.String() {
   370  				issuedBy = "self"
   371  			}
   372  
   373  			info := make(map[string]interface{})
   374  			info["Expired"] = time.Now().After(cert.NotAfter)
   375  			info["Subject"] = cert.Subject.String()
   376  			info["Issuer"] = issuedBy
   377  			formattedCAs = append(formattedCAs, info)
   378  		}
   379  	}
   380  
   381  	formattedEndpointCriteria := make(map[string]interface{})
   382  	formattedEndpointCriteria["Endpoint"] = ep.Endpoint
   383  	formattedEndpointCriteria["CAs"] = formattedCAs
   384  
   385  	rawJSON, err := json.Marshal(formattedEndpointCriteria)
   386  	if err != nil {
   387  		return fmt.Sprintf("{\"Endpoint\": \"%s\"}", ep.Endpoint)
   388  	}
   389  
   390  	return string(rawJSON)
   391  }
   392  
   393  // EndpointconfigFromConfigBlock retrieves TLS CA certificates and endpoints
   394  // from a config block.
   395  func EndpointconfigFromConfigBlock(block *common.Block, bccsp bccsp.BCCSP) ([]EndpointCriteria, error) {
   396  	if block == nil {
   397  		return nil, errors.New("nil block")
   398  	}
   399  	envelopeConfig, err := protoutil.ExtractEnvelope(block, 0)
   400  	if err != nil {
   401  		return nil, err
   402  	}
   403  
   404  	bundle, err := channelconfig.NewBundleFromEnvelope(envelopeConfig, bccsp)
   405  	if err != nil {
   406  		return nil, errors.Wrap(err, "failed extracting bundle from envelope")
   407  	}
   408  	msps, err := bundle.MSPManager().GetMSPs()
   409  	if err != nil {
   410  		return nil, errors.Wrap(err, "failed obtaining MSPs from MSPManager")
   411  	}
   412  	ordererConfig, ok := bundle.OrdererConfig()
   413  	if !ok {
   414  		return nil, errors.New("failed obtaining orderer config from bundle")
   415  	}
   416  
   417  	mspIDsToCACerts := make(map[string][][]byte)
   418  	var aggregatedTLSCerts [][]byte
   419  	for _, org := range ordererConfig.Organizations() {
   420  		// Validate that every orderer org has a corresponding MSP instance in the MSP Manager.
   421  		msp, exists := msps[org.MSPID()]
   422  		if !exists {
   423  			return nil, errors.Errorf("no MSP found for MSP with ID of %s", org.MSPID())
   424  		}
   425  
   426  		// Build a per org mapping of the TLS CA certs for this org,
   427  		// and aggregate all TLS CA certs into aggregatedTLSCerts to be used later on.
   428  		var caCerts [][]byte
   429  		caCerts = append(caCerts, msp.GetTLSIntermediateCerts()...)
   430  		caCerts = append(caCerts, msp.GetTLSRootCerts()...)
   431  		mspIDsToCACerts[org.MSPID()] = caCerts
   432  		aggregatedTLSCerts = append(aggregatedTLSCerts, caCerts...)
   433  	}
   434  
   435  	endpointsPerOrg := perOrgEndpoints(ordererConfig, mspIDsToCACerts)
   436  	if len(endpointsPerOrg) > 0 {
   437  		return endpointsPerOrg, nil
   438  	}
   439  
   440  	return globalEndpointsFromConfig(aggregatedTLSCerts, bundle), nil
   441  }
   442  
   443  func perOrgEndpoints(ordererConfig channelconfig.Orderer, mspIDsToCerts map[string][][]byte) []EndpointCriteria {
   444  	var endpointsPerOrg []EndpointCriteria
   445  
   446  	for _, org := range ordererConfig.Organizations() {
   447  		for _, endpoint := range org.Endpoints() {
   448  			endpointsPerOrg = append(endpointsPerOrg, EndpointCriteria{
   449  				TLSRootCAs: mspIDsToCerts[org.MSPID()],
   450  				Endpoint:   endpoint,
   451  			})
   452  		}
   453  	}
   454  
   455  	return endpointsPerOrg
   456  }
   457  
   458  func globalEndpointsFromConfig(aggregatedTLSCerts [][]byte, bundle *channelconfig.Bundle) []EndpointCriteria {
   459  	var globalEndpoints []EndpointCriteria
   460  	for _, endpoint := range bundle.ChannelConfig().OrdererAddresses() {
   461  		globalEndpoints = append(globalEndpoints, EndpointCriteria{
   462  			Endpoint:   endpoint,
   463  			TLSRootCAs: aggregatedTLSCerts,
   464  		})
   465  	}
   466  	return globalEndpoints
   467  }
   468  
   469  //go:generate mockery -dir . -name VerifierFactory -case underscore -output ./mocks/
   470  
   471  // VerifierFactory creates BlockVerifiers.
   472  type VerifierFactory interface {
   473  	// VerifierFromConfig creates a BlockVerifier from the given configuration.
   474  	VerifierFromConfig(configuration *common.ConfigEnvelope, channel string) (BlockVerifier, error)
   475  }
   476  
   477  // VerificationRegistry registers verifiers and retrieves them.
   478  type VerificationRegistry struct {
   479  	LoadVerifier       func(chain string) BlockVerifier
   480  	Logger             *flogging.FabricLogger
   481  	VerifierFactory    VerifierFactory
   482  	VerifiersByChannel map[string]BlockVerifier
   483  }
   484  
   485  // RegisterVerifier adds a verifier into the registry if applicable.
   486  func (vr *VerificationRegistry) RegisterVerifier(chain string) {
   487  	if _, exists := vr.VerifiersByChannel[chain]; exists {
   488  		vr.Logger.Debugf("No need to register verifier for chain %s", chain)
   489  		return
   490  	}
   491  
   492  	v := vr.LoadVerifier(chain)
   493  	if v == nil {
   494  		vr.Logger.Errorf("Failed loading verifier for chain %s", chain)
   495  		return
   496  	}
   497  
   498  	vr.VerifiersByChannel[chain] = v
   499  	vr.Logger.Infof("Registered verifier for chain %s", chain)
   500  }
   501  
   502  // RetrieveVerifier returns a BlockVerifier for the given channel, or nil if not found.
   503  func (vr *VerificationRegistry) RetrieveVerifier(channel string) BlockVerifier {
   504  	verifier, exists := vr.VerifiersByChannel[channel]
   505  	if exists {
   506  		return verifier
   507  	}
   508  	vr.Logger.Errorf("No verifier for channel %s exists", channel)
   509  	return nil
   510  }
   511  
   512  // BlockCommitted notifies the VerificationRegistry upon a block commit, which may
   513  // trigger a registration of a verifier out of the block in case the block is a config block.
   514  func (vr *VerificationRegistry) BlockCommitted(block *common.Block, channel string) {
   515  	conf, err := ConfigFromBlock(block)
   516  	// The block doesn't contain a config block, but is a valid block
   517  	if err == errNotAConfig {
   518  		vr.Logger.Debugf("Committed block [%d] for channel %s that is not a config block",
   519  			block.Header.Number, channel)
   520  		return
   521  	}
   522  	// The block isn't a valid block
   523  	if err != nil {
   524  		vr.Logger.Errorf("Failed parsing block of channel %s: %v, content: %s",
   525  			channel, err, BlockToString(block))
   526  		return
   527  	}
   528  
   529  	// The block contains a config block
   530  	verifier, err := vr.VerifierFactory.VerifierFromConfig(conf, channel)
   531  	if err != nil {
   532  		vr.Logger.Errorf("Failed creating a verifier from a config block for channel %s: %v, content: %s",
   533  			channel, err, BlockToString(block))
   534  		return
   535  	}
   536  
   537  	vr.VerifiersByChannel[channel] = verifier
   538  
   539  	vr.Logger.Debugf("Committed config block [%d] for channel %s", block.Header.Number, channel)
   540  }
   541  
   542  // BlockToString returns a string representation of this block.
   543  func BlockToString(block *common.Block) string {
   544  	buff := &bytes.Buffer{}
   545  	protolator.DeepMarshalJSON(buff, block)
   546  	return buff.String()
   547  }
   548  
   549  // BlockCommitFunc signals a block commit.
   550  type BlockCommitFunc func(block *common.Block, channel string)
   551  
   552  // LedgerInterceptor intercepts block commits.
   553  type LedgerInterceptor struct {
   554  	Channel              string
   555  	InterceptBlockCommit BlockCommitFunc
   556  	LedgerWriter
   557  }
   558  
   559  // Append commits a block into the ledger, and also fires the configured callback.
   560  func (interceptor *LedgerInterceptor) Append(block *common.Block) error {
   561  	defer interceptor.InterceptBlockCommit(block, interceptor.Channel)
   562  	return interceptor.LedgerWriter.Append(block)
   563  }
   564  
   565  // BlockVerifierAssembler creates a BlockVerifier out of a config envelope
   566  type BlockVerifierAssembler struct {
   567  	Logger *flogging.FabricLogger
   568  	BCCSP  bccsp.BCCSP
   569  }
   570  
   571  // VerifierFromConfig creates a BlockVerifier from the given configuration.
   572  func (bva *BlockVerifierAssembler) VerifierFromConfig(configuration *common.ConfigEnvelope, channel string) (BlockVerifier, error) {
   573  	bundle, err := channelconfig.NewBundle(channel, configuration.Config, bva.BCCSP)
   574  	if err != nil {
   575  		return nil, errors.Wrap(err, "failed extracting bundle from envelope")
   576  	}
   577  	policyMgr := bundle.PolicyManager()
   578  
   579  	return &BlockValidationPolicyVerifier{
   580  		Logger:    bva.Logger,
   581  		PolicyMgr: policyMgr,
   582  		Channel:   channel,
   583  		BCCSP:     bva.BCCSP,
   584  	}, nil
   585  }
   586  
   587  // BlockValidationPolicyVerifier verifies signatures based on the block validation policy.
   588  type BlockValidationPolicyVerifier struct {
   589  	Logger    *flogging.FabricLogger
   590  	Channel   string
   591  	PolicyMgr policies.Manager
   592  	BCCSP     bccsp.BCCSP
   593  }
   594  
   595  // VerifyBlockSignature verifies the signed data associated to a block, optionally with the given config envelope.
   596  func (bv *BlockValidationPolicyVerifier) VerifyBlockSignature(sd []*protoutil.SignedData, envelope *common.ConfigEnvelope) error {
   597  	policyMgr := bv.PolicyMgr
   598  	// If the envelope passed isn't nil, we should use a different policy manager.
   599  	if envelope != nil {
   600  		bundle, err := channelconfig.NewBundle(bv.Channel, envelope.Config, bv.BCCSP)
   601  		if err != nil {
   602  			buff := &bytes.Buffer{}
   603  			protolator.DeepMarshalJSON(buff, envelope.Config)
   604  			bv.Logger.Errorf("Failed creating a new bundle for channel %s, Config content is: %s", bv.Channel, buff.String())
   605  			return err
   606  		}
   607  		bv.Logger.Infof("Initializing new PolicyManager for channel %s", bv.Channel)
   608  		policyMgr = bundle.PolicyManager()
   609  	}
   610  	policy, exists := policyMgr.GetPolicy(policies.BlockValidation)
   611  	if !exists {
   612  		return errors.Errorf("policy %s wasn't found", policies.BlockValidation)
   613  	}
   614  	return policy.EvaluateSignedData(sd)
   615  }
   616  
   617  //go:generate mockery -dir . -name BlockRetriever -case underscore -output ./mocks/
   618  
   619  // BlockRetriever retrieves blocks
   620  type BlockRetriever interface {
   621  	// Block returns a block with the given number,
   622  	// or nil if such a block doesn't exist.
   623  	Block(number uint64) *common.Block
   624  }
   625  
   626  // LastConfigBlock returns the last config block relative to the given block.
   627  func LastConfigBlock(block *common.Block, blockRetriever BlockRetriever) (*common.Block, error) {
   628  	if block == nil {
   629  		return nil, errors.New("nil block")
   630  	}
   631  	if blockRetriever == nil {
   632  		return nil, errors.New("nil blockRetriever")
   633  	}
   634  	if block.Metadata == nil || len(block.Metadata.Metadata) <= int(common.BlockMetadataIndex_LAST_CONFIG) {
   635  		return nil, errors.New("no metadata in block")
   636  	}
   637  	lastConfigBlockNum, err := protoutil.GetLastConfigIndexFromBlock(block)
   638  	if err != nil {
   639  		return nil, err
   640  	}
   641  	lastConfigBlock := blockRetriever.Block(lastConfigBlockNum)
   642  	if lastConfigBlock == nil {
   643  		return nil, errors.Errorf("unable to retrieve last config block [%d]", lastConfigBlockNum)
   644  	}
   645  	return lastConfigBlock, nil
   646  }
   647  
   648  // StreamCountReporter reports the number of streams currently connected to this node
   649  type StreamCountReporter struct {
   650  	Metrics *Metrics
   651  	count   uint32
   652  }
   653  
   654  func (scr *StreamCountReporter) Increment() {
   655  	count := atomic.AddUint32(&scr.count, 1)
   656  	scr.Metrics.reportStreamCount(count)
   657  }
   658  
   659  func (scr *StreamCountReporter) Decrement() {
   660  	count := atomic.AddUint32(&scr.count, ^uint32(0))
   661  	scr.Metrics.reportStreamCount(count)
   662  }
   663  
   664  type certificateExpirationCheck struct {
   665  	minimumExpirationWarningInterval time.Duration
   666  	expiresAt                        time.Time
   667  	expirationWarningThreshold       time.Duration
   668  	lastWarning                      time.Time
   669  	nodeName                         string
   670  	endpoint                         string
   671  	alert                            func(string, ...interface{})
   672  }
   673  
   674  func (exp *certificateExpirationCheck) checkExpiration(currentTime time.Time, channel string) {
   675  	timeLeft := exp.expiresAt.Sub(currentTime)
   676  	if timeLeft > exp.expirationWarningThreshold {
   677  		return
   678  	}
   679  
   680  	timeSinceLastWarning := currentTime.Sub(exp.lastWarning)
   681  	if timeSinceLastWarning < exp.minimumExpirationWarningInterval {
   682  		return
   683  	}
   684  
   685  	exp.alert("Certificate of %s from %s for channel %s expires in less than %v",
   686  		exp.nodeName, exp.endpoint, channel, timeLeft)
   687  	exp.lastWarning = currentTime
   688  }