github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/bootstrap/file/bootstrap.go (about)

     1  // Copyright IBM Corp. All Rights Reserved.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package file
     5  
     6  import (
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  
    11  	"github.com/golang/protobuf/proto"
    12  	cb "github.com/hyperledger/fabric-protos-go/common"
    13  	"github.com/hyperledger/fabric/orderer/common/bootstrap"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  type fileBootstrapper struct {
    18  	GenesisBlockFile string
    19  }
    20  
    21  // New returns a new static bootstrap helper.
    22  func New(fileName string) bootstrap.Helper {
    23  	return &fileBootstrapper{
    24  		GenesisBlockFile: fileName,
    25  	}
    26  }
    27  
    28  // NewReplacer returns a new bootstrap replacer.
    29  func NewReplacer(fileName string) bootstrap.Replacer {
    30  	return &fileBootstrapper{
    31  		GenesisBlockFile: fileName,
    32  	}
    33  }
    34  
    35  // GenesisBlock returns the genesis block to be used for bootstrapping.
    36  func (b *fileBootstrapper) GenesisBlock() *cb.Block {
    37  	bootstrapFile, fileErr := ioutil.ReadFile(b.GenesisBlockFile)
    38  	if fileErr != nil {
    39  		panic(errors.Errorf("unable to bootstrap orderer. Error reading genesis block file: %v", fileErr))
    40  	}
    41  	genesisBlock := &cb.Block{}
    42  	unmarshallErr := proto.Unmarshal(bootstrapFile, genesisBlock)
    43  	if unmarshallErr != nil {
    44  		panic(errors.Errorf("unable to bootstrap orderer. Error unmarshalling genesis block: %v", unmarshallErr))
    45  
    46  	}
    47  	return genesisBlock
    48  } // GenesisBlock
    49  
    50  // ReplaceGenesisBlockFile creates a backup of the genesis block file, and then replaces
    51  // it with the content of the given block.
    52  // This is used during consensus-type migration in order to generate a bootstrap file that
    53  // specifies the new consensus-type.
    54  func (b *fileBootstrapper) ReplaceGenesisBlockFile(block *cb.Block) error {
    55  	buff, marshalErr := proto.Marshal(block)
    56  	if marshalErr != nil {
    57  		return errors.Wrap(marshalErr, "could not marshal block into a []byte")
    58  	}
    59  
    60  	genFileStat, statErr := os.Stat(b.GenesisBlockFile)
    61  	if statErr != nil {
    62  		return errors.Wrapf(statErr, "could not get the os.Stat of the genesis block file: %s", b.GenesisBlockFile)
    63  	}
    64  
    65  	if !genFileStat.Mode().IsRegular() {
    66  		return errors.Errorf("genesis block file: %s, is not a regular file", b.GenesisBlockFile)
    67  	}
    68  
    69  	backupFile := b.GenesisBlockFile + ".bak"
    70  	if err := backupGenesisFile(b.GenesisBlockFile, backupFile); err != nil {
    71  		return errors.Wrapf(err, "could not copy genesis block file (%s) into backup file: %s",
    72  			b.GenesisBlockFile, backupFile)
    73  	}
    74  
    75  	if err := ioutil.WriteFile(b.GenesisBlockFile, buff, genFileStat.Mode()); err != nil {
    76  		return errors.Wrapf(err, "could not write new genesis block into file: %s; use backup if necessary: %s",
    77  			b.GenesisBlockFile, backupFile)
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  func backupGenesisFile(src, dst string) error {
    84  	source, err := os.Open(src)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	defer source.Close()
    89  
    90  	destination, err := os.Create(dst)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	defer destination.Close()
    95  
    96  	_, err = io.Copy(destination, source)
    97  	return err
    98  }
    99  
   100  func (b *fileBootstrapper) CheckReadWrite() error {
   101  	genFileStat, statErr := os.Stat(b.GenesisBlockFile)
   102  	if statErr != nil {
   103  		return errors.Wrapf(statErr, "could not get the os.Stat of the genesis block file: %s", b.GenesisBlockFile)
   104  	}
   105  
   106  	if !genFileStat.Mode().IsRegular() {
   107  		return errors.Errorf("genesis block file: %s, is not a regular file", b.GenesisBlockFile)
   108  	}
   109  
   110  	genFile, openErr := os.OpenFile(b.GenesisBlockFile, os.O_RDWR, genFileStat.Mode().Perm())
   111  	if openErr != nil {
   112  		if os.IsPermission(openErr) {
   113  			return errors.Wrapf(openErr, "genesis block file: %s, cannot be opened for read-write, check permissions", b.GenesisBlockFile)
   114  		} else {
   115  			return errors.Wrapf(openErr, "genesis block file: %s, cannot be opened for read-write", b.GenesisBlockFile)
   116  		}
   117  	}
   118  	genFile.Close()
   119  
   120  	return nil
   121  }