github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/multichain/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 multichain
    18  
    19  import (
    20  	configvaluesapi "github.com/hyperledger/fabric/common/configvalues"
    21  	"github.com/hyperledger/fabric/common/crypto"
    22  	"github.com/hyperledger/fabric/common/policies"
    23  	"github.com/hyperledger/fabric/common/util"
    24  	"github.com/hyperledger/fabric/orderer/common/blockcutter"
    25  	"github.com/hyperledger/fabric/orderer/common/broadcast"
    26  	"github.com/hyperledger/fabric/orderer/common/configtxfilter"
    27  	"github.com/hyperledger/fabric/orderer/common/filter"
    28  	"github.com/hyperledger/fabric/orderer/common/sigfilter"
    29  	"github.com/hyperledger/fabric/orderer/common/sizefilter"
    30  	ordererledger "github.com/hyperledger/fabric/orderer/ledger"
    31  	cb "github.com/hyperledger/fabric/protos/common"
    32  	"github.com/hyperledger/fabric/protos/utils"
    33  )
    34  
    35  // Consenter defines the backing ordering mechanism
    36  type Consenter interface {
    37  	// HandleChain should create a return a reference to a Chain for the given set of resources
    38  	// It will only be invoked for a given chain once per process.  In general, errors will be treated
    39  	// as irrecoverable and cause system shutdown.  See the description of Chain for more details
    40  	// The second argument to HandleChain is a pointer to the metadata stored on the `ORDERER` slot of
    41  	// the last block committed to the ledger of this Chain.  For a new chain, this metadata will be
    42  	// nil, as this field is not set on the genesis block
    43  	HandleChain(support ConsenterSupport, metadata *cb.Metadata) (Chain, error)
    44  }
    45  
    46  // Chain defines a way to inject messages for ordering
    47  // Note, that in order to allow flexibility in the implementation, it is the responsibility of the implementer
    48  // to take the ordered messages, send them through the blockcutter.Receiver supplied via HandleChain to cut blocks,
    49  // and ultimately write the ledger also supplied via HandleChain.  This flow allows for two primary flows
    50  // 1. Messages are ordered into a stream, the stream is cut into blocks, the blocks are committed (solo, kafka)
    51  // 2. Messages are cut into blocks, the blocks are ordered, then the blocks are committed (sbft)
    52  type Chain interface {
    53  	// Enqueue accepts a message and returns true on acceptance, or false on shutdown
    54  	Enqueue(env *cb.Envelope) bool
    55  
    56  	// Start should allocate whatever resources are needed for staying up to date with the chain
    57  	// Typically, this involves creating a thread which reads from the ordering source, passes those
    58  	// messages to a block cutter, and writes the resulting blocks to the ledger
    59  	Start()
    60  
    61  	// Halt frees the resources which were allocated for this Chain
    62  	Halt()
    63  }
    64  
    65  // ConsenterSupport provides the resources available to a Consenter implementation
    66  type ConsenterSupport interface {
    67  	crypto.LocalSigner
    68  	BlockCutter() blockcutter.Receiver
    69  	SharedConfig() configvaluesapi.Orderer
    70  	CreateNextBlock(messages []*cb.Envelope) *cb.Block
    71  	WriteBlock(block *cb.Block, committers []filter.Committer, encodedMetadataValue []byte) *cb.Block
    72  	ChainID() string // ChainID returns the chain ID this specific consenter instance is associated with
    73  }
    74  
    75  // ChainSupport provides a wrapper for the resources backing a chain
    76  type ChainSupport interface {
    77  	// This interface is actually the union with the deliver.Support but because of a golang
    78  	// limitation https://github.com/golang/go/issues/6977 the methods must be explicitly declared
    79  
    80  	// PolicyManager returns the current policy manager as specified by the chain config
    81  	PolicyManager() policies.Manager
    82  
    83  	// Reader returns the chain Reader for the chain
    84  	Reader() ordererledger.Reader
    85  
    86  	broadcast.Support
    87  	ConsenterSupport
    88  
    89  	// ProposeConfigUpdate applies a CONFIG_UPDATE to an existing config to produce a *cb.ConfigEnvelope
    90  	ProposeConfigUpdate(env *cb.Envelope) (*cb.ConfigEnvelope, error)
    91  }
    92  
    93  type chainSupport struct {
    94  	*ledgerResources
    95  	chain         Chain
    96  	cutter        blockcutter.Receiver
    97  	filters       *filter.RuleSet
    98  	signer        crypto.LocalSigner
    99  	lastConfig    uint64
   100  	lastConfigSeq uint64
   101  }
   102  
   103  func newChainSupport(
   104  	filters *filter.RuleSet,
   105  	ledgerResources *ledgerResources,
   106  	consenters map[string]Consenter,
   107  	signer crypto.LocalSigner,
   108  ) *chainSupport {
   109  
   110  	cutter := blockcutter.NewReceiverImpl(ledgerResources.SharedConfig(), filters)
   111  	consenterType := ledgerResources.SharedConfig().ConsensusType()
   112  	consenter, ok := consenters[consenterType]
   113  	if !ok {
   114  		logger.Fatalf("Error retrieving consenter of type: %s", consenterType)
   115  	}
   116  
   117  	cs := &chainSupport{
   118  		ledgerResources: ledgerResources,
   119  		cutter:          cutter,
   120  		filters:         filters,
   121  		signer:          signer,
   122  	}
   123  
   124  	var err error
   125  
   126  	lastBlock := ordererledger.GetBlock(cs.Reader(), cs.Reader().Height()-1)
   127  	metadata, err := utils.GetMetadataFromBlock(lastBlock, cb.BlockMetadataIndex_ORDERER)
   128  	// Assuming a block created with cb.NewBlock(), this should not
   129  	// error even if the orderer metadata is an empty byte slice
   130  	if err != nil {
   131  		logger.Fatalf("Error extracting orderer metadata for chain %x: %s", cs.ChainID(), err)
   132  	}
   133  	logger.Debugf("Retrieved metadata for tip of chain (block #%d): %+v", cs.Reader().Height()-1, metadata)
   134  
   135  	cs.chain, err = consenter.HandleChain(cs, metadata)
   136  	if err != nil {
   137  		logger.Fatalf("Error creating consenter for chain %x: %s", ledgerResources.ChainID(), err)
   138  	}
   139  
   140  	return cs
   141  }
   142  
   143  // createStandardFilters creates the set of filters for a normal (non-system) chain
   144  func createStandardFilters(ledgerResources *ledgerResources) *filter.RuleSet {
   145  	return filter.NewRuleSet([]filter.Rule{
   146  		filter.EmptyRejectRule,
   147  		sizefilter.MaxBytesRule(ledgerResources.SharedConfig().BatchSize().AbsoluteMaxBytes),
   148  		sigfilter.New(ledgerResources.SharedConfig().IngressPolicyNames, ledgerResources.PolicyManager()),
   149  		configtxfilter.NewFilter(ledgerResources),
   150  		filter.AcceptRule,
   151  	})
   152  
   153  }
   154  
   155  // createSystemChainFilters creates the set of filters for the ordering system chain
   156  func createSystemChainFilters(ml *multiLedger, ledgerResources *ledgerResources) *filter.RuleSet {
   157  	return filter.NewRuleSet([]filter.Rule{
   158  		filter.EmptyRejectRule,
   159  		sizefilter.MaxBytesRule(ledgerResources.SharedConfig().BatchSize().AbsoluteMaxBytes),
   160  		sigfilter.New(ledgerResources.SharedConfig().IngressPolicyNames, ledgerResources.PolicyManager()),
   161  		newSystemChainFilter(ledgerResources, ml),
   162  		configtxfilter.NewFilter(ledgerResources),
   163  		filter.AcceptRule,
   164  	})
   165  }
   166  
   167  func (cs *chainSupport) start() {
   168  	cs.chain.Start()
   169  }
   170  
   171  func (cs *chainSupport) NewSignatureHeader() (*cb.SignatureHeader, error) {
   172  	return cs.signer.NewSignatureHeader()
   173  }
   174  
   175  func (cs *chainSupport) Sign(message []byte) ([]byte, error) {
   176  	return cs.signer.Sign(message)
   177  }
   178  
   179  func (cs *chainSupport) Filters() *filter.RuleSet {
   180  	return cs.filters
   181  }
   182  
   183  func (cs *chainSupport) BlockCutter() blockcutter.Receiver {
   184  	return cs.cutter
   185  }
   186  
   187  func (cs *chainSupport) Reader() ordererledger.Reader {
   188  	return cs.ledger
   189  }
   190  
   191  func (cs *chainSupport) Enqueue(env *cb.Envelope) bool {
   192  	return cs.chain.Enqueue(env)
   193  }
   194  
   195  func (cs *chainSupport) CreateNextBlock(messages []*cb.Envelope) *cb.Block {
   196  	return ordererledger.CreateNextBlock(cs.ledger, messages)
   197  }
   198  
   199  func (cs *chainSupport) addBlockSignature(block *cb.Block) {
   200  	logger.Debugf("%+v", cs)
   201  	logger.Debugf("%+v", cs.signer)
   202  
   203  	blockSignature := &cb.MetadataSignature{
   204  		SignatureHeader: utils.MarshalOrPanic(utils.NewSignatureHeaderOrPanic(cs.signer)),
   205  	}
   206  
   207  	// Note, this value is intentionally nil, as this metadata is only about the signature, there is no additional metadata
   208  	// information required beyond the fact that the metadata item is signed.
   209  	blockSignatureValue := []byte(nil)
   210  
   211  	blockSignature.Signature = utils.SignOrPanic(cs.signer, util.ConcatenateBytes(blockSignatureValue, blockSignature.SignatureHeader, block.Header.Bytes()))
   212  
   213  	block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES] = utils.MarshalOrPanic(&cb.Metadata{
   214  		Value: blockSignatureValue,
   215  		Signatures: []*cb.MetadataSignature{
   216  			blockSignature,
   217  		},
   218  	})
   219  }
   220  
   221  func (cs *chainSupport) addLastConfigSignature(block *cb.Block) {
   222  	configSeq := cs.Sequence()
   223  	if configSeq > cs.lastConfigSeq {
   224  		cs.lastConfig = block.Header.Number
   225  		cs.lastConfigSeq = configSeq
   226  	}
   227  
   228  	lastConfigSignature := &cb.MetadataSignature{
   229  		SignatureHeader: utils.MarshalOrPanic(utils.NewSignatureHeaderOrPanic(cs.signer)),
   230  	}
   231  
   232  	lastConfigValue := utils.MarshalOrPanic(&cb.LastConfig{Index: cs.lastConfig})
   233  
   234  	lastConfigSignature.Signature = utils.SignOrPanic(cs.signer, util.ConcatenateBytes(lastConfigValue, lastConfigSignature.SignatureHeader, block.Header.Bytes()))
   235  
   236  	block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = utils.MarshalOrPanic(&cb.Metadata{
   237  		Value: lastConfigValue,
   238  		Signatures: []*cb.MetadataSignature{
   239  			lastConfigSignature,
   240  		},
   241  	})
   242  }
   243  
   244  func (cs *chainSupport) WriteBlock(block *cb.Block, committers []filter.Committer, encodedMetadataValue []byte) *cb.Block {
   245  	for _, committer := range committers {
   246  		committer.Commit()
   247  	}
   248  	// Set the orderer-related metadata field
   249  	if encodedMetadataValue != nil {
   250  		block.Metadata.Metadata[cb.BlockMetadataIndex_ORDERER] = utils.MarshalOrPanic(&cb.Metadata{Value: encodedMetadataValue})
   251  	}
   252  	cs.addBlockSignature(block)
   253  	cs.addLastConfigSignature(block)
   254  
   255  	err := cs.ledger.Append(block)
   256  	if err != nil {
   257  		logger.Panicf("Could not append block: %s", err)
   258  	}
   259  	return block
   260  }