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