github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/committer/committer_impl.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package committer 18 19 import ( 20 "fmt" 21 22 "github.com/hyperledger/fabric/common/flogging" 23 "github.com/hyperledger/fabric/core/committer/txvalidator" 24 "github.com/hyperledger/fabric/core/ledger" 25 "github.com/hyperledger/fabric/events/producer" 26 "github.com/hyperledger/fabric/protos/common" 27 "github.com/hyperledger/fabric/protos/utils" 28 "github.com/op/go-logging" 29 ) 30 31 //--------!!!IMPORTANT!!-!!IMPORTANT!!-!!IMPORTANT!!--------- 32 // This is used merely to complete the loop for the "skeleton" 33 // path so we can reason about and modify committer component 34 // more effectively using code. 35 36 var logger *logging.Logger // package-level logger 37 38 func init() { 39 logger = flogging.MustGetLogger("committer") 40 } 41 42 // LedgerCommitter is the implementation of Committer interface 43 // it keeps the reference to the ledger to commit blocks and retrieve 44 // chain information 45 type LedgerCommitter struct { 46 ledger ledger.PeerLedger 47 validator txvalidator.Validator 48 eventer ConfigBlockEventer 49 } 50 51 // ConfigBlockEventer callback function proto type to define action 52 // upon arrival on new configuaration update block 53 type ConfigBlockEventer func(block *common.Block) error 54 55 // NewLedgerCommitter is a factory function to create an instance of the committer 56 // which passes incoming blocks via validation and commits them into the ledger. 57 func NewLedgerCommitter(ledger ledger.PeerLedger, validator txvalidator.Validator) *LedgerCommitter { 58 return NewLedgerCommitterReactive(ledger, validator, func(_ *common.Block) error { return nil }) 59 } 60 61 // NewLedgerCommitterReactive is a factory function to create an instance of the committer 62 // same as way as NewLedgerCommitter, while also provides an option to specify callback to 63 // be called upon new configuration block arrival and commit event 64 func NewLedgerCommitterReactive(ledger ledger.PeerLedger, validator txvalidator.Validator, eventer ConfigBlockEventer) *LedgerCommitter { 65 return &LedgerCommitter{ledger: ledger, validator: validator, eventer: eventer} 66 } 67 68 // Commit commits block to into the ledger 69 // Note, it is important that this always be called serially 70 func (lc *LedgerCommitter) Commit(block *common.Block) error { 71 72 // Validate and mark invalid transactions 73 logger.Debug("Validating block") 74 if err := lc.validator.Validate(block); err != nil { 75 return err 76 } 77 78 // Updating CSCC with new configuration block 79 if utils.IsConfigBlock(block) { 80 logger.Debug("Received configuration update, calling CSCC ConfigUpdate") 81 if err := lc.eventer(block); err != nil { 82 return fmt.Errorf("Could not update CSCC with new configuration update due to %s", err) 83 } 84 } 85 86 if err := lc.ledger.Commit(block); err != nil { 87 return err 88 } 89 90 // send block event *after* the block has been committed 91 if err := producer.SendProducerBlockEvent(block); err != nil { 92 logger.Errorf("Error publishing block %d, because: %v", block.Header.Number, err) 93 } 94 95 return nil 96 } 97 98 // LedgerHeight returns recently committed block sequence number 99 func (lc *LedgerCommitter) LedgerHeight() (uint64, error) { 100 var info *common.BlockchainInfo 101 var err error 102 if info, err = lc.ledger.GetBlockchainInfo(); err != nil { 103 logger.Errorf("Cannot get blockchain info, %s\n", info) 104 return uint64(0), err 105 } 106 107 return info.Height, nil 108 } 109 110 // GetBlocks used to retrieve blocks with sequence numbers provided in the slice 111 func (lc *LedgerCommitter) GetBlocks(blockSeqs []uint64) []*common.Block { 112 var blocks []*common.Block 113 114 for _, seqNum := range blockSeqs { 115 if blck, err := lc.ledger.GetBlockByNumber(seqNum); err != nil { 116 logger.Errorf("Not able to acquire block num %d, from the ledger skipping...\n", seqNum) 117 continue 118 } else { 119 logger.Debug("Appending next block with seqNum = ", seqNum, " to the resulting set") 120 blocks = append(blocks, blck) 121 } 122 } 123 124 return blocks 125 } 126 127 // Close the ledger 128 func (lc *LedgerCommitter) Close() { 129 lc.ledger.Close() 130 }