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 }