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  }