github.com/defanghe/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 }