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

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package onboarding
     8  
     9  import (
    10  	"os"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	"github.com/hechain20/hechain/bccsp"
    16  	"github.com/hechain20/hechain/common/channelconfig"
    17  	"github.com/hechain20/hechain/common/flogging"
    18  	"github.com/hechain20/hechain/common/ledger/blockledger"
    19  	"github.com/hechain20/hechain/internal/pkg/comm"
    20  	"github.com/hechain20/hechain/internal/pkg/identity"
    21  	"github.com/hechain20/hechain/orderer/common/cluster"
    22  	"github.com/hechain20/hechain/orderer/common/localconfig"
    23  	"github.com/hechain20/hechain/orderer/consensus/etcdraft"
    24  	"github.com/hechain20/hechain/protoutil"
    25  	"github.com/hyperledger/fabric-config/protolator"
    26  	"github.com/hyperledger/fabric-protos-go/common"
    27  	"github.com/pkg/errors"
    28  )
    29  
    30  const (
    31  	DefaultReplicationBackgroundRefreshInterval = time.Minute * 5
    32  	replicationBackgroundInitialRefreshInterval = time.Second * 10
    33  )
    34  
    35  var logger = flogging.MustGetLogger("orderer.common.onboarding")
    36  
    37  type ReplicationInitiator struct {
    38  	RegisterChain func(chain string)
    39  	ChannelLister cluster.ChannelLister
    40  
    41  	verifierRetriever cluster.VerifierRetriever
    42  	logger            *flogging.FabricLogger
    43  	secOpts           comm.SecureOptions
    44  	conf              *localconfig.TopLevel
    45  	lf                cluster.LedgerFactory
    46  	signer            identity.SignerSerializer
    47  	cryptoProvider    bccsp.BCCSP
    48  }
    49  
    50  func NewReplicationInitiator(
    51  	lf blockledger.Factory,
    52  	bootstrapBlock *common.Block,
    53  	conf *localconfig.TopLevel,
    54  	secOpts comm.SecureOptions,
    55  	signer identity.SignerSerializer,
    56  	bccsp bccsp.BCCSP,
    57  ) *ReplicationInitiator {
    58  	logger := flogging.MustGetLogger("orderer.common.cluster")
    59  
    60  	vl := &verifierLoader{
    61  		verifierFactory: &cluster.BlockVerifierAssembler{Logger: logger, BCCSP: bccsp},
    62  		onFailure: func(block *common.Block) {
    63  			protolator.DeepMarshalJSON(os.Stdout, block)
    64  		},
    65  		ledgerFactory: lf,
    66  		logger:        logger,
    67  	}
    68  
    69  	systemChannelName, err := protoutil.GetChannelIDFromBlock(bootstrapBlock)
    70  	if err != nil {
    71  		logger.Panicf("Failed extracting system channel name from bootstrap block: %v", err)
    72  	}
    73  
    74  	// System channel is not verified because we trust the bootstrap block
    75  	// and use backward hash chain verification.
    76  	verifiersByChannel := vl.loadVerifiers()
    77  	verifiersByChannel[systemChannelName] = &cluster.NoopBlockVerifier{}
    78  
    79  	vr := &cluster.VerificationRegistry{
    80  		LoadVerifier:       vl.loadVerifier,
    81  		Logger:             logger,
    82  		VerifiersByChannel: verifiersByChannel,
    83  		VerifierFactory:    &cluster.BlockVerifierAssembler{Logger: logger, BCCSP: bccsp},
    84  	}
    85  
    86  	ledgerFactory := &ledgerFactory{
    87  		Factory:       lf,
    88  		onBlockCommit: vr.BlockCommitted,
    89  	}
    90  	return &ReplicationInitiator{
    91  		RegisterChain:     vr.RegisterVerifier,
    92  		verifierRetriever: vr,
    93  		logger:            logger,
    94  		secOpts:           secOpts,
    95  		conf:              conf,
    96  		lf:                ledgerFactory,
    97  		signer:            signer,
    98  		cryptoProvider:    bccsp,
    99  	}
   100  }
   101  
   102  func (ri *ReplicationInitiator) ReplicateIfNeeded(bootstrapBlock *common.Block) {
   103  	if bootstrapBlock.Header.Number == 0 {
   104  		ri.logger.Debug("Booted with a genesis block, replication isn't an option")
   105  		return
   106  	}
   107  	ri.replicateNeededChannels(bootstrapBlock)
   108  }
   109  
   110  func (ri *ReplicationInitiator) createReplicator(bootstrapBlock *common.Block, filter func(string) bool) *cluster.Replicator {
   111  	consenterCert := &etcdraft.ConsenterCertificate{
   112  		Logger:               ri.logger,
   113  		ConsenterCertificate: ri.secOpts.Certificate,
   114  		CryptoProvider:       ri.cryptoProvider,
   115  	}
   116  
   117  	systemChannelName, err := protoutil.GetChannelIDFromBlock(bootstrapBlock)
   118  	if err != nil {
   119  		ri.logger.Panicf("Failed extracting system channel name from bootstrap block: %v", err)
   120  	}
   121  	pullerConfig := cluster.PullerConfigFromTopLevelConfig(systemChannelName, ri.conf, ri.secOpts.Key, ri.secOpts.Certificate, ri.signer)
   122  	puller, err := cluster.BlockPullerFromConfigBlock(pullerConfig, bootstrapBlock, ri.verifierRetriever, ri.cryptoProvider)
   123  	if err != nil {
   124  		ri.logger.Panicf("Failed creating puller config from bootstrap block: %v", err)
   125  	}
   126  	puller.MaxPullBlockRetries = uint64(ri.conf.General.Cluster.ReplicationMaxRetries)
   127  	puller.RetryTimeout = ri.conf.General.Cluster.ReplicationRetryTimeout
   128  
   129  	replicator := &cluster.Replicator{
   130  		Filter:           filter,
   131  		LedgerFactory:    ri.lf,
   132  		SystemChannel:    systemChannelName,
   133  		BootBlock:        bootstrapBlock,
   134  		Logger:           ri.logger,
   135  		AmIPartOfChannel: consenterCert.IsConsenterOfChannel,
   136  		Puller:           puller,
   137  		ChannelLister: &cluster.ChainInspector{
   138  			Logger:          ri.logger,
   139  			Puller:          puller,
   140  			LastConfigBlock: bootstrapBlock,
   141  		},
   142  	}
   143  
   144  	// If a custom channel lister is requested, use it
   145  	if ri.ChannelLister != nil {
   146  		replicator.ChannelLister = ri.ChannelLister
   147  	}
   148  
   149  	return replicator
   150  }
   151  
   152  func (ri *ReplicationInitiator) replicateNeededChannels(bootstrapBlock *common.Block) {
   153  	replicator := ri.createReplicator(bootstrapBlock, cluster.AnyChannel)
   154  	defer replicator.Puller.Close()
   155  	replicationNeeded, err := replicator.IsReplicationNeeded()
   156  	if err != nil {
   157  		ri.logger.Panicf("Failed determining whether replication is needed: %v", err)
   158  	}
   159  
   160  	if !replicationNeeded {
   161  		ri.logger.Info("Replication isn't needed")
   162  		return
   163  	}
   164  
   165  	ri.logger.Info("Will now replicate chains")
   166  	replicator.ReplicateChains()
   167  }
   168  
   169  // ReplicateChains replicates the given chains with the assistance of the given last system channel config block,
   170  // and returns the names of the chains that were successfully replicated.
   171  func (ri *ReplicationInitiator) ReplicateChains(lastConfigBlock *common.Block, chains []string) []string {
   172  	ri.logger.Info("Will now replicate chains", chains)
   173  	wantedChannels := make(map[string]struct{})
   174  	for _, chain := range chains {
   175  		wantedChannels[chain] = struct{}{}
   176  	}
   177  	filter := func(channelName string) bool {
   178  		_, exists := wantedChannels[channelName]
   179  		return exists
   180  	}
   181  	replicator := ri.createReplicator(lastConfigBlock, filter)
   182  	replicator.DoNotPanicIfClusterNotReachable = true
   183  	defer replicator.Puller.Close()
   184  	return replicator.ReplicateChains()
   185  }
   186  
   187  type ledgerFactory struct {
   188  	blockledger.Factory
   189  	onBlockCommit cluster.BlockCommitFunc
   190  }
   191  
   192  func (lf *ledgerFactory) GetOrCreate(chainID string) (cluster.LedgerWriter, error) {
   193  	ledger, err := lf.Factory.GetOrCreate(chainID)
   194  	if err != nil {
   195  		return nil, err
   196  	}
   197  	interceptedLedger := &cluster.LedgerInterceptor{
   198  		LedgerWriter:         ledger,
   199  		Channel:              chainID,
   200  		InterceptBlockCommit: lf.onBlockCommit,
   201  	}
   202  	return interceptedLedger, nil
   203  }
   204  
   205  //go:generate mockery -dir . -name ChainReplicator -case underscore -output mocks
   206  
   207  // ChainReplicator replicates chains
   208  type ChainReplicator interface {
   209  	// ReplicateChains replicates the given chains using the given last system channel config block.
   210  	// It returns the names of the chains that were successfully replicated.
   211  	ReplicateChains(lastConfigBlock *common.Block, chains []string) []string
   212  }
   213  
   214  // InactiveChainReplicator tracks disabled chains and replicates them upon demand
   215  type InactiveChainReplicator struct {
   216  	registerChain                     func(chain string)
   217  	logger                            *flogging.FabricLogger
   218  	retrieveLastSysChannelConfigBlock func() *common.Block
   219  	replicator                        ChainReplicator
   220  	scheduleChan                      <-chan time.Time
   221  	quitChan                          chan struct{}
   222  	doneChan                          chan struct{}
   223  	lock                              sync.RWMutex
   224  	chains2CreationCallbacks          map[string]chainCreation
   225  }
   226  
   227  func NewInactiveChainReplicator(
   228  	chainReplicator ChainReplicator,
   229  	getSysChannelConfigBlockFunc func() *common.Block,
   230  	registerChainFunc func(chain string),
   231  	replicationRefreshInterval time.Duration,
   232  ) *InactiveChainReplicator {
   233  	if replicationRefreshInterval == 0 {
   234  		replicationRefreshInterval = DefaultReplicationBackgroundRefreshInterval
   235  	}
   236  	exponentialSleep := exponentialDurationSeries(replicationBackgroundInitialRefreshInterval, replicationRefreshInterval)
   237  	ticker := newTicker(exponentialSleep)
   238  
   239  	icr := &InactiveChainReplicator{
   240  		logger:                            logger,
   241  		scheduleChan:                      ticker.C,
   242  		quitChan:                          make(chan struct{}),
   243  		doneChan:                          make(chan struct{}),
   244  		replicator:                        chainReplicator,
   245  		chains2CreationCallbacks:          make(map[string]chainCreation),
   246  		retrieveLastSysChannelConfigBlock: getSysChannelConfigBlockFunc,
   247  		registerChain:                     registerChainFunc,
   248  	}
   249  
   250  	return icr
   251  }
   252  
   253  func (i *InactiveChainReplicator) Channels() []cluster.ChannelGenesisBlock {
   254  	i.lock.RLock()
   255  	defer i.lock.RUnlock()
   256  
   257  	var res []cluster.ChannelGenesisBlock
   258  	for name, chain := range i.chains2CreationCallbacks {
   259  		res = append(res, cluster.ChannelGenesisBlock{
   260  			ChannelName:  name,
   261  			GenesisBlock: chain.genesisBlock,
   262  		})
   263  	}
   264  	return res
   265  }
   266  
   267  func (i *InactiveChainReplicator) Close() {}
   268  
   269  type chainCreation struct {
   270  	create       func()
   271  	genesisBlock *common.Block
   272  }
   273  
   274  // TrackChain tracks a chain with the given name, and calls the given callback
   275  // when this chain should be activated.
   276  func (i *InactiveChainReplicator) TrackChain(chain string, genesisBlock *common.Block, createChainCallback func()) {
   277  	i.lock.Lock()
   278  	defer i.lock.Unlock()
   279  
   280  	i.logger.Infof("Adding %s to the set of chains to track", chain)
   281  	i.chains2CreationCallbacks[chain] = chainCreation{
   282  		genesisBlock: genesisBlock,
   283  		create:       createChainCallback,
   284  	}
   285  }
   286  
   287  func (i *InactiveChainReplicator) Run() {
   288  	for {
   289  		select {
   290  		case <-i.scheduleChan:
   291  			i.replicateDisabledChains()
   292  		case <-i.quitChan:
   293  			close(i.doneChan)
   294  			return
   295  		}
   296  	}
   297  }
   298  
   299  func (i *InactiveChainReplicator) replicateDisabledChains() {
   300  	chains := i.listInactiveChains()
   301  	if len(chains) == 0 {
   302  		i.logger.Debugf("No inactive chains to try to replicate")
   303  		return
   304  	}
   305  
   306  	// For each chain, ensure we registered it into the verifier registry, otherwise
   307  	// we won't be able to verify its blocks.
   308  	for _, chain := range chains {
   309  		i.registerChain(chain)
   310  	}
   311  
   312  	i.logger.Infof("Found %d inactive chains: %v", len(chains), chains)
   313  	lastSystemChannelConfigBlock := i.retrieveLastSysChannelConfigBlock()
   314  	replicatedChains := i.replicator.ReplicateChains(lastSystemChannelConfigBlock, chains)
   315  	i.logger.Infof("Successfully replicated %d chains: %v", len(replicatedChains), replicatedChains)
   316  	i.lock.Lock()
   317  	defer i.lock.Unlock()
   318  	for _, chainName := range replicatedChains {
   319  		chain := i.chains2CreationCallbacks[chainName]
   320  		delete(i.chains2CreationCallbacks, chainName)
   321  		chain.create()
   322  	}
   323  }
   324  
   325  // Stop stops the inactive chain replicator. This is used when removing the
   326  // system channel.
   327  func (i *InactiveChainReplicator) Stop() {
   328  	close(i.quitChan)
   329  	<-i.doneChan
   330  }
   331  
   332  func (i *InactiveChainReplicator) listInactiveChains() []string {
   333  	i.lock.RLock()
   334  	defer i.lock.RUnlock()
   335  	var chains []string
   336  	for chain := range i.chains2CreationCallbacks {
   337  		chains = append(chains, chain)
   338  	}
   339  	return chains
   340  }
   341  
   342  type blockGetter struct {
   343  	ledger blockledger.Reader
   344  }
   345  
   346  func (bg *blockGetter) Block(number uint64) *common.Block {
   347  	return blockledger.GetBlock(bg.ledger, number)
   348  }
   349  
   350  type verifierLoader struct {
   351  	ledgerFactory   blockledger.Factory
   352  	verifierFactory cluster.VerifierFactory
   353  	logger          *flogging.FabricLogger
   354  	onFailure       func(block *common.Block)
   355  }
   356  
   357  type verifiersByChannel map[string]cluster.BlockVerifier
   358  
   359  func (vl *verifierLoader) loadVerifiers() verifiersByChannel {
   360  	res := make(verifiersByChannel)
   361  
   362  	for _, channel := range vl.ledgerFactory.ChannelIDs() {
   363  		v := vl.loadVerifier(channel)
   364  		if v == nil {
   365  			continue
   366  		}
   367  		res[channel] = v
   368  	}
   369  
   370  	return res
   371  }
   372  
   373  func (vl *verifierLoader) loadVerifier(chain string) cluster.BlockVerifier {
   374  	ledger, err := vl.ledgerFactory.GetOrCreate(chain)
   375  	if err != nil {
   376  		vl.logger.Panicf("Failed obtaining ledger for channel %s", chain)
   377  	}
   378  
   379  	blockRetriever := &blockGetter{ledger: ledger}
   380  	height := ledger.Height()
   381  	if height == 0 {
   382  		vl.logger.Errorf("Channel %s has no blocks, skipping it", chain)
   383  		return nil
   384  	}
   385  	lastBlockIndex := height - 1
   386  	lastBlock := blockRetriever.Block(lastBlockIndex)
   387  	if lastBlock == nil {
   388  		vl.logger.Panicf("Failed retrieving block [%d] for channel %s", lastBlockIndex, chain)
   389  	}
   390  
   391  	lastConfigBlock, err := cluster.LastConfigBlock(lastBlock, blockRetriever)
   392  	if err != nil {
   393  		vl.logger.Panicf("Failed retrieving config block [%d] for channel %s", lastBlockIndex, chain)
   394  	}
   395  	conf, err := cluster.ConfigFromBlock(lastConfigBlock)
   396  	if err != nil {
   397  		vl.onFailure(lastConfigBlock)
   398  		vl.logger.Panicf("Failed extracting configuration for channel %s from block [%d]: %v",
   399  			chain, lastConfigBlock.Header.Number, err)
   400  	}
   401  
   402  	verifier, err := vl.verifierFactory.VerifierFromConfig(conf, chain)
   403  	if err != nil {
   404  		vl.onFailure(lastConfigBlock)
   405  		vl.logger.Panicf("Failed creating verifier for channel %s from block [%d]: %v", chain, lastBlockIndex, err)
   406  	}
   407  	vl.logger.Infof("Loaded verifier for channel %s from config block at index %d", chain, lastBlockIndex)
   408  	return verifier
   409  }
   410  
   411  // ValidateBootstrapBlock returns whether this block can be used as a bootstrap block.
   412  // A bootstrap block is a block of a system channel, and needs to have a ConsortiumsConfig.
   413  func ValidateBootstrapBlock(block *common.Block, bccsp bccsp.BCCSP) error {
   414  	if block == nil {
   415  		return errors.New("nil block")
   416  	}
   417  
   418  	if block.Data == nil || len(block.Data.Data) == 0 {
   419  		return errors.New("empty block data")
   420  	}
   421  
   422  	firstTransaction := &common.Envelope{}
   423  	if err := proto.Unmarshal(block.Data.Data[0], firstTransaction); err != nil {
   424  		return errors.Wrap(err, "failed extracting envelope from block")
   425  	}
   426  
   427  	bundle, err := channelconfig.NewBundleFromEnvelope(firstTransaction, bccsp)
   428  	if err != nil {
   429  		return err
   430  	}
   431  
   432  	_, exists := bundle.ConsortiumsConfig()
   433  	if !exists {
   434  		return errors.New("the block isn't a system channel block because it lacks ConsortiumsConfig")
   435  	}
   436  	return nil
   437  }