github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/filter/filter.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 filter
    18  
    19  import (
    20  	"fmt"
    21  
    22  	ab "github.com/hyperledger/fabric/protos/common"
    23  )
    24  
    25  // Action is used to express the output of a rule
    26  type Action int
    27  
    28  const (
    29  	// Accept indicates that the message should be processed
    30  	Accept = iota
    31  	// Reject indicates that the message should not be processed
    32  	Reject
    33  	// Forward indicates that the rule could not determine the correct course of action
    34  	Forward
    35  )
    36  
    37  // Rule defines a filter function which accepts, rejects, or forwards (to the next rule) an Envelope
    38  type Rule interface {
    39  	// Apply applies the rule to the given Envelope, replying with the Action to take for the message
    40  	// If the filter Accepts a message, it should provide a committer to use when writing the message to the chain
    41  	Apply(message *ab.Envelope) (Action, Committer)
    42  }
    43  
    44  // Committer is returned by postfiltering and should be invoked once the message has been written to the blockchain
    45  type Committer interface {
    46  	// Commit performs whatever action should be performed upon committing of a message
    47  	Commit()
    48  
    49  	// Isolated returns whether this transaction should have a block to itself or may be mixed with other transactions
    50  	Isolated() bool
    51  }
    52  
    53  type noopCommitter struct{}
    54  
    55  func (nc noopCommitter) Commit()        {}
    56  func (nc noopCommitter) Isolated() bool { return false }
    57  
    58  // NoopCommitter does nothing on commit and is not isolated
    59  var NoopCommitter = Committer(noopCommitter{})
    60  
    61  // EmptyRejectRule rejects empty messages
    62  var EmptyRejectRule = Rule(emptyRejectRule{})
    63  
    64  type emptyRejectRule struct{}
    65  
    66  func (a emptyRejectRule) Apply(message *ab.Envelope) (Action, Committer) {
    67  	if message.Payload == nil {
    68  		return Reject, nil
    69  	}
    70  	return Forward, nil
    71  }
    72  
    73  // AcceptRule always returns Accept as a result for Apply
    74  var AcceptRule = Rule(acceptRule{})
    75  
    76  type acceptRule struct{}
    77  
    78  func (a acceptRule) Apply(message *ab.Envelope) (Action, Committer) {
    79  	return Accept, NoopCommitter
    80  }
    81  
    82  // RuleSet is used to apply a collection of rules
    83  type RuleSet struct {
    84  	rules []Rule
    85  }
    86  
    87  // NewRuleSet creates a new RuleSet with the given ordered list of Rules
    88  func NewRuleSet(rules []Rule) *RuleSet {
    89  	return &RuleSet{
    90  		rules: rules,
    91  	}
    92  }
    93  
    94  // Apply applies the rules given for this set in order, returning the committer, nil on valid, or nil, err on invalid
    95  func (rs *RuleSet) Apply(message *ab.Envelope) (Committer, error) {
    96  	for _, rule := range rs.rules {
    97  		action, committer := rule.Apply(message)
    98  		switch action {
    99  		case Accept:
   100  			return committer, nil
   101  		case Reject:
   102  			return nil, fmt.Errorf("Rejected by rule: %T", rule)
   103  		default:
   104  		}
   105  	}
   106  	return nil, fmt.Errorf("No matching filter found")
   107  }