github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/msgprocessor/standardchannel.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package msgprocessor 8 9 import ( 10 cb "github.com/hyperledger/fabric-protos-go/common" 11 "github.com/hyperledger/fabric-protos-go/orderer" 12 "github.com/hyperledger/fabric/bccsp" 13 "github.com/hyperledger/fabric/common/channelconfig" 14 "github.com/hyperledger/fabric/common/policies" 15 "github.com/hyperledger/fabric/internal/pkg/identity" 16 "github.com/hyperledger/fabric/protoutil" 17 18 "github.com/hyperledger/fabric/orderer/common/localconfig" 19 "github.com/pkg/errors" 20 ) 21 22 //go:generate counterfeiter -o mocks/signer_serializer.go --fake-name SignerSerializer . signerSerializer 23 24 type signerSerializer interface { 25 identity.SignerSerializer 26 } 27 28 // StandardChannelSupport includes the resources needed for the StandardChannel processor. 29 type StandardChannelSupport interface { 30 // Sequence should return the current configSeq 31 Sequence() uint64 32 33 // ChannelID returns the ChannelID 34 ChannelID() string 35 36 // Signer returns the signer for this orderer 37 Signer() identity.SignerSerializer 38 39 // ProposeConfigUpdate takes in an Envelope of type CONFIG_UPDATE and produces a 40 // ConfigEnvelope to be used as the Envelope Payload Data of a CONFIG message 41 ProposeConfigUpdate(configtx *cb.Envelope) (*cb.ConfigEnvelope, error) 42 43 OrdererConfig() (channelconfig.Orderer, bool) 44 } 45 46 // StandardChannel implements the Processor interface for standard extant channels 47 type StandardChannel struct { 48 support StandardChannelSupport 49 filters *RuleSet // Rules applicable to both normal and config messages 50 maintenanceFilter Rule // Rule applicable only to config messages 51 } 52 53 // NewStandardChannel creates a new standard message processor 54 func NewStandardChannel(support StandardChannelSupport, filters *RuleSet, bccsp bccsp.BCCSP) *StandardChannel { 55 return &StandardChannel{ 56 filters: filters, 57 support: support, 58 maintenanceFilter: NewMaintenanceFilter(support, bccsp), 59 } 60 } 61 62 // CreateStandardChannelFilters creates the set of filters for a normal (non-system) chain. 63 // 64 // In maintenance mode, require the signature of /Channel/Orderer/Writer. This will filter out configuration 65 // changes that are not related to consensus-type migration (e.g on /Channel/Application). 66 func CreateStandardChannelFilters(filterSupport channelconfig.Resources, config localconfig.TopLevel) *RuleSet { 67 rules := []Rule{ 68 EmptyRejectRule, 69 NewSizeFilter(filterSupport), 70 NewSigFilter(policies.ChannelWriters, policies.ChannelOrdererWriters, filterSupport), 71 } 72 73 if !config.General.Authentication.NoExpirationChecks { 74 expirationRule := NewExpirationRejectRule(filterSupport) 75 // In case of DoS, expiration is inserted before SigFilter, so it is evaluated first 76 rules = append(rules[:2], append([]Rule{expirationRule}, rules[2:]...)...) 77 } 78 79 return NewRuleSet(rules) 80 } 81 82 // ClassifyMsg inspects the message to determine which type of processing is necessary 83 func (s *StandardChannel) ClassifyMsg(chdr *cb.ChannelHeader) Classification { 84 switch chdr.Type { 85 case int32(cb.HeaderType_CONFIG_UPDATE): 86 return ConfigUpdateMsg 87 case int32(cb.HeaderType_ORDERER_TRANSACTION): 88 // In order to maintain backwards compatibility, we must classify these messages 89 return ConfigMsg 90 case int32(cb.HeaderType_CONFIG): 91 // In order to maintain backwards compatibility, we must classify these messages 92 return ConfigMsg 93 default: 94 return NormalMsg 95 } 96 } 97 98 // ProcessNormalMsg will check the validity of a message based on the current configuration. It returns the current 99 // configuration sequence number and nil on success, or an error if the message is not valid 100 func (s *StandardChannel) ProcessNormalMsg(env *cb.Envelope) (configSeq uint64, err error) { 101 oc, ok := s.support.OrdererConfig() 102 if !ok { 103 logger.Panicf("Missing orderer config") 104 } 105 if oc.Capabilities().ConsensusTypeMigration() { 106 if oc.ConsensusState() != orderer.ConsensusType_STATE_NORMAL { 107 return 0, errors.WithMessage( 108 ErrMaintenanceMode, "normal transactions are rejected") 109 } 110 } 111 112 configSeq = s.support.Sequence() 113 err = s.filters.Apply(env) 114 return 115 } 116 117 // ProcessConfigUpdateMsg will attempt to apply the config impetus msg to the current configuration, and if successful 118 // return the resulting config message and the configSeq the config was computed from. If the config impetus message 119 // is invalid, an error is returned. 120 func (s *StandardChannel) ProcessConfigUpdateMsg(env *cb.Envelope) (config *cb.Envelope, configSeq uint64, err error) { 121 logger.Debugf("Processing config update message for exisitng channel %s", s.support.ChannelID()) 122 123 // Call Sequence first. If seq advances between proposal and acceptance, this is okay, and will cause reprocessing 124 // however, if Sequence is called last, then a success could be falsely attributed to a newer configSeq 125 seq := s.support.Sequence() 126 err = s.filters.Apply(env) 127 if err != nil { 128 return nil, 0, errors.WithMessage(err, "config update for existing channel did not pass initial checks") 129 } 130 131 configEnvelope, err := s.support.ProposeConfigUpdate(env) 132 if err != nil { 133 return nil, 0, errors.WithMessagef(err, "error applying config update to existing channel '%s'", s.support.ChannelID()) 134 } 135 136 config, err = protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG, s.support.ChannelID(), s.support.Signer(), configEnvelope, msgVersion, epoch) 137 if err != nil { 138 return nil, 0, err 139 } 140 141 // We re-apply the filters here, especially for the size filter, to ensure that the transaction we 142 // just constructed is not too large for our consenter. It additionally reapplies the signature 143 // check, which although not strictly necessary, is a good sanity check, in case the orderer 144 // has not been configured with the right cert material. The additional overhead of the signature 145 // check is negligible, as this is the reconfig path and not the normal path. 146 err = s.filters.Apply(config) 147 if err != nil { 148 return nil, 0, errors.WithMessage(err, "config update for existing channel did not pass final checks") 149 } 150 151 err = s.maintenanceFilter.Apply(config) 152 if err != nil { 153 return nil, 0, errors.WithMessage(err, "config update for existing channel did not pass maintenance checks") 154 } 155 156 return config, seq, nil 157 } 158 159 // ProcessConfigMsg takes an envelope of type `HeaderType_CONFIG`, unpacks the `ConfigEnvelope` from it 160 // extracts the `ConfigUpdate` from `LastUpdate` field, and calls `ProcessConfigUpdateMsg` on it. 161 func (s *StandardChannel) ProcessConfigMsg(env *cb.Envelope) (config *cb.Envelope, configSeq uint64, err error) { 162 logger.Debugf("Processing config message for channel %s", s.support.ChannelID()) 163 164 configEnvelope := &cb.ConfigEnvelope{} 165 _, err = protoutil.UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, configEnvelope) 166 if err != nil { 167 return 168 } 169 170 return s.ProcessConfigUpdateMsg(configEnvelope.LastUpdate) 171 }