github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/orderer/common/follower/block_puller.go (about)

     1  /*
     2  Copyright hechain. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package follower
     8  
     9  import (
    10  	"encoding/pem"
    11  
    12  	"github.com/hechain20/hechain/bccsp"
    13  	"github.com/hechain20/hechain/common/flogging"
    14  	"github.com/hechain20/hechain/internal/pkg/identity"
    15  	"github.com/hechain20/hechain/orderer/common/cluster"
    16  	"github.com/hechain20/hechain/orderer/common/localconfig"
    17  	"github.com/hyperledger/fabric-protos-go/common"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  //go:generate counterfeiter -o mocks/channel_puller.go -fake-name ChannelPuller . ChannelPuller
    22  
    23  // ChannelPuller pulls blocks for a channel
    24  type ChannelPuller interface {
    25  	PullBlock(seq uint64) *common.Block
    26  	HeightsByEndpoints() (map[string]uint64, error)
    27  	UpdateEndpoints(endpoints []cluster.EndpointCriteria)
    28  	Close()
    29  }
    30  
    31  // BlockPullerCreator creates a ChannelPuller on demand.
    32  // It also maintains a link to a block signature verifier, and exposes a method to update it on incoming config blocks.
    33  // The ChannelPuller generated by this factory always accesses the updated verifier, since it is generated
    34  // with a link to the factory's VerifyBlockSequence method.
    35  type BlockPullerCreator struct {
    36  	channelID               string
    37  	bccsp                   bccsp.BCCSP
    38  	blockSigVerifierFactory cluster.VerifierFactory // Creates a new block signature verifier
    39  	blockSigVerifier        cluster.BlockVerifier   // The current block signature verifier, from the latest channel config
    40  	clusterConfig           localconfig.Cluster
    41  	signer                  identity.SignerSerializer
    42  	der                     *pem.Block
    43  	stdDialer               *cluster.StandardDialer
    44  	ClusterVerifyBlocks     ClusterVerifyBlocksFunc // Default: cluster.VerifyBlocks, or a mock for testing
    45  }
    46  
    47  // ClusterVerifyBlocksFunc is a function that matches the signature of cluster.VerifyBlocks, and allows mocks for testing.
    48  type ClusterVerifyBlocksFunc func(blockBuff []*common.Block, signatureVerifier cluster.BlockVerifier) error
    49  
    50  // NewBlockPullerCreator creates a new BlockPullerCreator, using the configuration details that do not change during
    51  // the life cycle of the orderer.
    52  func NewBlockPullerCreator(
    53  	channelID string,
    54  	logger *flogging.FabricLogger,
    55  	signer identity.SignerSerializer,
    56  	baseDialer *cluster.PredicateDialer,
    57  	clusterConfig localconfig.Cluster,
    58  	bccsp bccsp.BCCSP,
    59  ) (*BlockPullerCreator, error) {
    60  	stdDialer := &cluster.StandardDialer{
    61  		Config: baseDialer.Config,
    62  	}
    63  	stdDialer.Config.AsyncConnect = false
    64  	stdDialer.Config.SecOpts.VerifyCertificate = nil
    65  
    66  	der, _ := pem.Decode(stdDialer.Config.SecOpts.Certificate)
    67  	if der == nil {
    68  		return nil, errors.Errorf("client certificate isn't in PEM format: %v",
    69  			string(stdDialer.Config.SecOpts.Certificate))
    70  	}
    71  
    72  	factory := &BlockPullerCreator{
    73  		channelID: channelID,
    74  		bccsp:     bccsp,
    75  		blockSigVerifierFactory: &cluster.BlockVerifierAssembler{
    76  			Logger: logger,
    77  			BCCSP:  bccsp,
    78  		},
    79  		clusterConfig:       clusterConfig,
    80  		signer:              signer,
    81  		stdDialer:           stdDialer,
    82  		der:                 der,
    83  		ClusterVerifyBlocks: cluster.VerifyBlocks, // The default block sequence verification method.
    84  	}
    85  
    86  	return factory, nil
    87  }
    88  
    89  // BlockPuller creates a block puller on demand, taking the endpoints from the config block.
    90  func (creator *BlockPullerCreator) BlockPuller(configBlock *common.Block, stopChannel chan struct{}) (ChannelPuller, error) {
    91  	// Extract the TLS CA certs and endpoints from the join-block
    92  	endpoints, err := cluster.EndpointconfigFromConfigBlock(configBlock, creator.bccsp)
    93  	if err != nil {
    94  		return nil, errors.WithMessage(err, "error extracting endpoints from config block")
    95  	}
    96  
    97  	bp := &cluster.BlockPuller{
    98  		VerifyBlockSequence: creator.VerifyBlockSequence,
    99  		Logger:              flogging.MustGetLogger("orderer.common.cluster.puller").With("channel", creator.channelID),
   100  		RetryTimeout:        creator.clusterConfig.ReplicationRetryTimeout,
   101  		MaxTotalBufferBytes: creator.clusterConfig.ReplicationBufferSize,
   102  		MaxPullBlockRetries: uint64(creator.clusterConfig.ReplicationMaxRetries),
   103  		FetchTimeout:        creator.clusterConfig.ReplicationPullTimeout,
   104  		Endpoints:           endpoints,
   105  		Signer:              creator.signer,
   106  		TLSCert:             creator.der.Bytes,
   107  		Channel:             creator.channelID,
   108  		Dialer:              creator.stdDialer,
   109  		StopChannel:         stopChannel,
   110  	}
   111  
   112  	return bp, nil
   113  }
   114  
   115  // UpdateVerifierFromConfigBlock creates a new block signature verifier from the config block and updates the internal
   116  // link to said verifier.
   117  func (creator *BlockPullerCreator) UpdateVerifierFromConfigBlock(configBlock *common.Block) error {
   118  	configEnv, err := cluster.ConfigFromBlock(configBlock)
   119  	if err != nil {
   120  		return errors.WithMessage(err, "failed to extract config envelope from block")
   121  	}
   122  	verifier, err := creator.blockSigVerifierFactory.VerifierFromConfig(configEnv, creator.channelID)
   123  	if err != nil {
   124  		return errors.WithMessage(err, "failed to construct a block signature verifier from config envelope")
   125  	}
   126  	creator.blockSigVerifier = verifier
   127  	return nil
   128  }
   129  
   130  // VerifyBlockSequence verifies a sequence of blocks, using the internal block signature verifier. It also bootstraps
   131  // the block sig verifier form the genesis block if it does not exist, and skips verifying the genesis block.
   132  func (creator *BlockPullerCreator) VerifyBlockSequence(blocks []*common.Block, _ string) error {
   133  	if len(blocks) == 0 {
   134  		return errors.New("buffer is empty")
   135  	}
   136  	if blocks[0] == nil {
   137  		return errors.New("first block is nil")
   138  	}
   139  	if blocks[0].Header == nil {
   140  		return errors.New("first block header is nil")
   141  	}
   142  	if blocks[0].Header.Number == 0 {
   143  		configEnv, err := cluster.ConfigFromBlock(blocks[0])
   144  		if err != nil {
   145  			return errors.WithMessage(err, "failed to extract config envelope from genesis block")
   146  		}
   147  		// Bootstrap the verifier from the genesis block, as it will be used to verify
   148  		// the subsequent blocks in the batch.
   149  		creator.blockSigVerifier, err = creator.blockSigVerifierFactory.VerifierFromConfig(configEnv, creator.channelID)
   150  		if err != nil {
   151  			return errors.WithMessage(err, "failed to construct a block signature verifier from genesis block")
   152  		}
   153  		blocksAfterGenesis := blocks[1:]
   154  		if len(blocksAfterGenesis) == 0 {
   155  			return nil
   156  		}
   157  		return creator.ClusterVerifyBlocks(blocksAfterGenesis, creator.blockSigVerifier)
   158  	}
   159  
   160  	if creator.blockSigVerifier == nil {
   161  		return errors.New("nil block signature verifier")
   162  	}
   163  
   164  	return creator.ClusterVerifyBlocks(blocks, creator.blockSigVerifier)
   165  }