github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/multichannel/chainsupport.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 multichannel 18 19 import ( 20 "fmt" 21 22 "github.com/hyperledger/fabric/common/config" 23 "github.com/hyperledger/fabric/common/crypto" 24 "github.com/hyperledger/fabric/common/policies" 25 "github.com/hyperledger/fabric/common/util" 26 "github.com/hyperledger/fabric/orderer/common/blockcutter" 27 "github.com/hyperledger/fabric/orderer/common/broadcast" 28 "github.com/hyperledger/fabric/orderer/common/configtxfilter" 29 "github.com/hyperledger/fabric/orderer/common/deliver" 30 "github.com/hyperledger/fabric/orderer/common/filter" 31 "github.com/hyperledger/fabric/orderer/common/ledger" 32 "github.com/hyperledger/fabric/orderer/common/sigfilter" 33 "github.com/hyperledger/fabric/orderer/common/sizefilter" 34 cb "github.com/hyperledger/fabric/protos/common" 35 "github.com/hyperledger/fabric/protos/utils" 36 ) 37 38 // MsgClassification represents the types of possible messages. 39 type MsgClassification int 40 41 const ( 42 // NormalMsg is the class of standard (endorser or otherwise non-config) messages. 43 // Messages of this type should be processed by ProcessNormalMsg. 44 NormalMsg MsgClassification = iota 45 46 // ConfigUpdateMsg is the class of configuration related messages. 47 // Messages of this type should be processed by ProcessConfigUpdateMsg. 48 ConfigUpdateMsg 49 ) 50 51 // Consenter defines the backing ordering mechanism 52 type Consenter interface { 53 // HandleChain should create and return a reference to a Chain for the given set of resources 54 // It will only be invoked for a given chain once per process. In general, errors will be treated 55 // as irrecoverable and cause system shutdown. See the description of Chain for more details 56 // The second argument to HandleChain is a pointer to the metadata stored on the `ORDERER` slot of 57 // the last block committed to the ledger of this Chain. For a new chain, this metadata will be 58 // nil, as this field is not set on the genesis block 59 HandleChain(support ConsenterSupport, metadata *cb.Metadata) (Chain, error) 60 } 61 62 // Chain defines a way to inject messages for ordering 63 // Note, that in order to allow flexibility in the implementation, it is the responsibility of the implementer 64 // to take the ordered messages, send them through the blockcutter.Receiver supplied via HandleChain to cut blocks, 65 // and ultimately write the ledger also supplied via HandleChain. This flow allows for two primary flows 66 // 1. Messages are ordered into a stream, the stream is cut into blocks, the blocks are committed (solo, kafka) 67 // 2. Messages are cut into blocks, the blocks are ordered, then the blocks are committed (sbft) 68 type Chain interface { 69 // Enqueue accepts a message and returns true on acceptance, or false on failure 70 Enqueue(env *cb.Envelope) bool 71 72 // Errored returns a channel which will close when an error has occurred 73 // This is especially useful for the Deliver client, who must terminate waiting 74 // clients when the consenter is not up to date 75 Errored() <-chan struct{} 76 77 // Start should allocate whatever resources are needed for staying up to date with the chain 78 // Typically, this involves creating a thread which reads from the ordering source, passes those 79 // messages to a block cutter, and writes the resulting blocks to the ledger 80 Start() 81 82 // Halt frees the resources which were allocated for this Chain 83 Halt() 84 } 85 86 // ConsenterSupport provides the resources available to a Consenter implementation 87 type ConsenterSupport interface { 88 crypto.LocalSigner 89 MsgProcessor 90 BlockCutter() blockcutter.Receiver 91 SharedConfig() config.Orderer 92 CreateNextBlock(messages []*cb.Envelope) *cb.Block 93 WriteBlock(block *cb.Block, encodedMetadataValue []byte) *cb.Block 94 WriteConfigBlock(block *cb.Block, encodedMetadataValue []byte) *cb.Block 95 ChainID() string // ChainID returns the chain ID this specific consenter instance is associated with 96 Height() uint64 // Returns the number of blocks on the chain this specific consenter instance is associated with 97 } 98 99 // MsgProcessor defines the methods necessary to interact with Broadcast messages. 100 type MsgProcessor interface { 101 // ClassifyMsg inspects the message to determine which type of processing is necessary. 102 ClassifyMsg(env *cb.Envelope) (MsgClassification, error) 103 104 // ProcessNormalMsg will check the validity of a message based on the current configuration. It returns the current 105 // configuration sequence number and nil on success, or an error if the message is not valid 106 ProcessNormalMsg(env *cb.Envelope) (configSeq uint64, err error) 107 108 // ProcessConfigUpdateMsg will attempt to apply the config impetus msg to the current configuration, and if successful 109 // return the resulting config message and the configSeq the config was computed from. If the config impetus message 110 // is invalid, an error is returned. 111 ProcessConfigUpdateMsg(env *cb.Envelope) (config *cb.Envelope, configSeq uint64, err error) 112 } 113 114 // ChainSupport provides a wrapper for the resources backing a chain 115 type ChainSupport interface { 116 broadcast.Support 117 deliver.Support 118 ConsenterSupport 119 120 // ProposeConfigUpdate applies a CONFIG_UPDATE to an existing config to produce a *cb.ConfigEnvelope 121 ProposeConfigUpdate(env *cb.Envelope) (*cb.ConfigEnvelope, error) 122 } 123 124 type chainSupport struct { 125 *ledgerResources 126 chain Chain 127 cutter blockcutter.Receiver 128 filters *filter.RuleSet 129 signer crypto.LocalSigner 130 lastConfig uint64 131 lastConfigSeq uint64 132 } 133 134 func newChainSupport( 135 filters *filter.RuleSet, 136 ledgerResources *ledgerResources, 137 consenters map[string]Consenter, 138 signer crypto.LocalSigner, 139 ) *chainSupport { 140 141 cutter := blockcutter.NewReceiverImpl(ledgerResources.SharedConfig(), filters) 142 consenterType := ledgerResources.SharedConfig().ConsensusType() 143 consenter, ok := consenters[consenterType] 144 if !ok { 145 logger.Fatalf("Error retrieving consenter of type: %s", consenterType) 146 } 147 148 cs := &chainSupport{ 149 ledgerResources: ledgerResources, 150 cutter: cutter, 151 filters: filters, 152 signer: signer, 153 } 154 155 cs.lastConfigSeq = cs.Sequence() 156 157 var err error 158 159 lastBlock := ledger.GetBlock(cs.Reader(), cs.Reader().Height()-1) 160 161 // If this is the genesis block, the lastconfig field may be empty, and, the last config is necessary 0 162 // so no need to initialize lastConfig 163 if lastBlock.Header.Number != 0 { 164 cs.lastConfig, err = utils.GetLastConfigIndexFromBlock(lastBlock) 165 if err != nil { 166 logger.Fatalf("[channel: %s] Error extracting last config block from block metadata: %s", cs.ChainID(), err) 167 } 168 } 169 170 metadata, err := utils.GetMetadataFromBlock(lastBlock, cb.BlockMetadataIndex_ORDERER) 171 // Assuming a block created with cb.NewBlock(), this should not 172 // error even if the orderer metadata is an empty byte slice 173 if err != nil { 174 logger.Fatalf("[channel: %s] Error extracting orderer metadata: %s", cs.ChainID(), err) 175 } 176 logger.Debugf("[channel: %s] Retrieved metadata for tip of chain (blockNumber=%d, lastConfig=%d, lastConfigSeq=%d): %+v", cs.ChainID(), lastBlock.Header.Number, cs.lastConfig, cs.lastConfigSeq, metadata) 177 178 cs.chain, err = consenter.HandleChain(cs, metadata) 179 if err != nil { 180 logger.Fatalf("[channel: %s] Error creating consenter: %s", cs.ChainID(), err) 181 } 182 183 return cs 184 } 185 186 // createStandardFilters creates the set of filters for a normal (non-system) chain 187 func createStandardFilters(ledgerResources *ledgerResources) *filter.RuleSet { 188 return filter.NewRuleSet([]filter.Rule{ 189 filter.EmptyRejectRule, 190 sizefilter.MaxBytesRule(ledgerResources.SharedConfig()), 191 sigfilter.New(policies.ChannelWriters, ledgerResources.PolicyManager()), 192 configtxfilter.NewFilter(ledgerResources), 193 filter.AcceptRule, 194 }) 195 196 } 197 198 // createSystemChainFilters creates the set of filters for the ordering system chain 199 func createSystemChainFilters(ml *multiLedger, ledgerResources *ledgerResources) *filter.RuleSet { 200 return filter.NewRuleSet([]filter.Rule{ 201 filter.EmptyRejectRule, 202 sizefilter.MaxBytesRule(ledgerResources.SharedConfig()), 203 sigfilter.New(policies.ChannelWriters, ledgerResources.PolicyManager()), 204 newSystemChainFilter(ledgerResources, ml), 205 configtxfilter.NewFilter(ledgerResources), 206 filter.AcceptRule, 207 }) 208 } 209 210 func (cs *chainSupport) start() { 211 cs.chain.Start() 212 } 213 214 func (cs *chainSupport) NewSignatureHeader() (*cb.SignatureHeader, error) { 215 return cs.signer.NewSignatureHeader() 216 } 217 218 func (cs *chainSupport) Sign(message []byte) ([]byte, error) { 219 return cs.signer.Sign(message) 220 } 221 222 func (cs *chainSupport) Filters() *filter.RuleSet { 223 return cs.filters 224 } 225 226 func (cs *chainSupport) BlockCutter() blockcutter.Receiver { 227 return cs.cutter 228 } 229 230 // ClassifyMsg inspects the message to determine which type of processing is necessary 231 func (cs *chainSupport) ClassifyMsg(env *cb.Envelope) (MsgClassification, error) { 232 payload, err := utils.UnmarshalPayload(env.Payload) 233 if err != nil { 234 return 0, fmt.Errorf("bad payload: %s", err) 235 } 236 237 if payload.Header == nil { 238 return 0, fmt.Errorf("bad payload: missing header") 239 } 240 241 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 242 if err != nil { 243 return 0, fmt.Errorf("bad channelheader: %s", err) 244 } 245 246 switch chdr.Type { 247 case int32(cb.HeaderType_CONFIG_UPDATE): 248 return ConfigUpdateMsg, nil 249 case int32(cb.HeaderType_ORDERER_TRANSACTION): 250 return ConfigUpdateMsg, nil 251 // XXX Eventually, these types cannot be allowed to be submitted directly 252 // return 0, fmt.Errorf("Transactions of type ORDERER_TRANSACTION cannot be Broadcast") 253 case int32(cb.HeaderType_CONFIG): 254 return ConfigUpdateMsg, nil 255 // XXX Eventually, these types cannot be allowed to be submitted directly 256 // return 0, fmt.Errorf("Transactions of type CONFIG cannot be Broadcast") 257 default: 258 return NormalMsg, nil 259 } 260 } 261 262 // ProcessNormalMsg will check the validity of a message based on the current configuration. It returns the current 263 // configuration sequence number and nil on success, or an error if the message is not valid 264 func (cs *chainSupport) ProcessNormalMsg(env *cb.Envelope) (configSeq uint64, err error) { 265 configSeq = cs.Sequence() 266 _, err = cs.filters.Apply(env) 267 return 268 } 269 270 // ProcessConfigUpdateMsg will attempt to apply the config update msg to the current configuration, and if successful 271 // return the resulting config message and the configSeq the config was computed from. If the config update message 272 // is invalid, an error is returned. 273 func (cs *chainSupport) ProcessConfigUpdateMsg(env *cb.Envelope) (config *cb.Envelope, configSeq uint64, err error) { 274 return nil, cs.Sequence(), fmt.Errorf("Config update message not yet implemented") 275 } 276 277 func (cs *chainSupport) Reader() ledger.Reader { 278 return cs.ledger 279 } 280 281 func (cs *chainSupport) Enqueue(env *cb.Envelope) bool { 282 return cs.chain.Enqueue(env) 283 } 284 285 func (cs *chainSupport) Errored() <-chan struct{} { 286 return cs.chain.Errored() 287 } 288 289 func (cs *chainSupport) CreateNextBlock(messages []*cb.Envelope) *cb.Block { 290 return ledger.CreateNextBlock(cs.ledger, messages) 291 } 292 293 func (cs *chainSupport) addBlockSignature(block *cb.Block) { 294 logger.Debugf("%+v", cs) 295 logger.Debugf("%+v", cs.signer) 296 297 blockSignature := &cb.MetadataSignature{ 298 SignatureHeader: utils.MarshalOrPanic(utils.NewSignatureHeaderOrPanic(cs.signer)), 299 } 300 301 // Note, this value is intentionally nil, as this metadata is only about the signature, there is no additional metadata 302 // information required beyond the fact that the metadata item is signed. 303 blockSignatureValue := []byte(nil) 304 305 blockSignature.Signature = utils.SignOrPanic(cs.signer, util.ConcatenateBytes(blockSignatureValue, blockSignature.SignatureHeader, block.Header.Bytes())) 306 307 block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES] = utils.MarshalOrPanic(&cb.Metadata{ 308 Value: blockSignatureValue, 309 Signatures: []*cb.MetadataSignature{ 310 blockSignature, 311 }, 312 }) 313 } 314 315 func (cs *chainSupport) addLastConfigSignature(block *cb.Block) { 316 configSeq := cs.Sequence() 317 if configSeq > cs.lastConfigSeq { 318 logger.Debugf("[channel: %s] Detected lastConfigSeq transitioning from %d to %d, setting lastConfig from %d to %d", cs.ChainID(), cs.lastConfigSeq, configSeq, cs.lastConfig, block.Header.Number) 319 cs.lastConfig = block.Header.Number 320 cs.lastConfigSeq = configSeq 321 } 322 323 lastConfigSignature := &cb.MetadataSignature{ 324 SignatureHeader: utils.MarshalOrPanic(utils.NewSignatureHeaderOrPanic(cs.signer)), 325 } 326 327 lastConfigValue := utils.MarshalOrPanic(&cb.LastConfig{Index: cs.lastConfig}) 328 logger.Debugf("[channel: %s] About to write block, setting its LAST_CONFIG to %d", cs.ChainID(), cs.lastConfig) 329 330 lastConfigSignature.Signature = utils.SignOrPanic(cs.signer, util.ConcatenateBytes(lastConfigValue, lastConfigSignature.SignatureHeader, block.Header.Bytes())) 331 332 block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = utils.MarshalOrPanic(&cb.Metadata{ 333 Value: lastConfigValue, 334 Signatures: []*cb.MetadataSignature{ 335 lastConfigSignature, 336 }, 337 }) 338 } 339 340 func (cs *chainSupport) WriteConfigBlock(block *cb.Block, encodedMetadataValue []byte) *cb.Block { 341 // XXX This hacky path is temporary and will be removed by the end of this change series 342 // The panics here are just fine 343 committer, err := cs.filters.Apply(utils.UnmarshalEnvelopeOrPanic(block.Data.Data[0])) 344 if err != nil { 345 logger.Panicf("Config should have already been validated") 346 } 347 committer.Commit() 348 349 return cs.WriteBlock(block, encodedMetadataValue) 350 } 351 352 func (cs *chainSupport) WriteBlock(block *cb.Block, encodedMetadataValue []byte) *cb.Block { 353 // Set the orderer-related metadata field 354 if encodedMetadataValue != nil { 355 block.Metadata.Metadata[cb.BlockMetadataIndex_ORDERER] = utils.MarshalOrPanic(&cb.Metadata{Value: encodedMetadataValue}) 356 } 357 cs.addBlockSignature(block) 358 cs.addLastConfigSignature(block) 359 360 err := cs.ledger.Append(block) 361 if err != nil { 362 logger.Panicf("[channel: %s] Could not append block: %s", cs.ChainID(), err) 363 } 364 logger.Debugf("[channel: %s] Wrote block %d", cs.ChainID(), block.GetHeader().Number) 365 366 return block 367 } 368 369 func (cs *chainSupport) Height() uint64 { 370 return cs.Reader().Height() 371 }