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