Skip to content

Commit

Permalink
[FAB-1242] Reject messages larger than AbsoluteMaxSize
Browse files Browse the repository at this point in the history
 - Add MaxBytesRule()
 - Add MaxBytesRule to default standard & system chain
   filters.

Change-Id: I82b74cf8727278867e032f24c9b828c9563c7896
Signed-off-by: Luis Sanchez <sanchezl@us.ibm.com>
  • Loading branch information
Luis Sanchez committed Jan 14, 2017
1 parent f68a97e commit 012f0b5
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 3 deletions.
6 changes: 3 additions & 3 deletions orderer/common/filter/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const (
Forward
)

// Rule defines a filter function which accepts, rejects, or forwards (to the next rule) a Envelope
// Rule defines a filter function which accepts, rejects, or forwards (to the next rule) an Envelope
type Rule interface {
// Apply applies the rule to the given Envelope, replying with the Action to take for the message
// If the filter Accepts a message, it should provide a committer to use when writing the message to the chain
Expand All @@ -55,7 +55,7 @@ type noopCommitter struct{}
func (nc noopCommitter) Commit() {}
func (nc noopCommitter) Isolated() bool { return false }

// NoopCommitter does nothing on commit and is not isolate
// NoopCommitter does nothing on commit and is not isolated
var NoopCommitter = Committer(noopCommitter{})

// EmptyRejectRule rejects empty messages
Expand Down Expand Up @@ -91,7 +91,7 @@ func NewRuleSet(rules []Rule) *RuleSet {
}
}

// Filter applies the rules given for this set in order, returning the committer, nil on valid, or nil, err on invalid
// Apply applies the rules given for this set in order, returning the committer, nil on valid, or nil, err on invalid
func (rs *RuleSet) Apply(message *ab.Envelope) (Committer, error) {
for _, rule := range rs.rules {
action, committer := rule.Apply(message)
Expand Down
46 changes: 46 additions & 0 deletions orderer/common/sizefilter/sizefilter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package sizefilter

import (
"github.com/hyperledger/fabric/orderer/common/filter"
ab "github.com/hyperledger/fabric/protos/common"
logging "github.com/op/go-logging"
)

var logger = logging.MustGetLogger("orderer/common/sizefilter")

// MaxBytesRule rejects messages larger than maxBytes
func MaxBytesRule(maxBytes uint32) filter.Rule {
return &maxBytesRule{maxBytes: maxBytes}
}

type maxBytesRule struct {
maxBytes uint32
}

func (r *maxBytesRule) Apply(message *ab.Envelope) (filter.Action, filter.Committer) {
if size := messageByteSize(message); size > r.maxBytes {
logger.Warningf("%d byte message payload exceeds maximum allowed %d bytes", size, r.maxBytes)
return filter.Reject, nil
}
return filter.Forward, nil
}

func messageByteSize(message *ab.Envelope) uint32 {
return uint32(len(message.Payload) + len(message.Signature))
}
62 changes: 62 additions & 0 deletions orderer/common/sizefilter/sizefilter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package sizefilter

import (
"testing"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/orderer/common/filter"
cb "github.com/hyperledger/fabric/protos/common"
)

func TestMaxBytesRule(t *testing.T) {
dataSize := uint32(100)
maxBytes := calcMessageBytesForPayloadDataSize(dataSize)
rs := filter.NewRuleSet([]filter.Rule{MaxBytesRule(maxBytes), filter.AcceptRule})

t.Run("LessThan", func(t *testing.T) {
_, err := rs.Apply(makeMessage(make([]byte, dataSize-1)))
if err != nil {
t.Fatalf("Should have accepted")
}
})
t.Run("Exact", func(t *testing.T) {
_, err := rs.Apply(makeMessage(make([]byte, dataSize)))
if err != nil {
t.Fatalf("Should have accepted")
}
})
t.Run("TooBig", func(t *testing.T) {
_, err := rs.Apply(makeMessage(make([]byte, dataSize+1)))
if err == nil {
t.Fatalf("Should have rejected")
}
})
}

func calcMessageBytesForPayloadDataSize(dataSize uint32) uint32 {
return messageByteSize(makeMessage(make([]byte, dataSize)))
}

func makeMessage(data []byte) *cb.Envelope {
data, err := proto.Marshal(&cb.Payload{Data: data})
if err != nil {
panic(err)
}
return &cb.Envelope{Payload: data}
}
3 changes: 3 additions & 0 deletions orderer/multichain/chainsupport.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/hyperledger/fabric/orderer/common/filter"
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
"github.com/hyperledger/fabric/orderer/common/sigfilter"
"github.com/hyperledger/fabric/orderer/common/sizefilter"
"github.com/hyperledger/fabric/orderer/rawledger"
cb "github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/utils"
Expand Down Expand Up @@ -138,6 +139,7 @@ func newChainSupport(
func createStandardFilters(configManager configtx.Manager, policyManager policies.Manager, sharedConfig sharedconfig.Manager) *filter.RuleSet {
return filter.NewRuleSet([]filter.Rule{
filter.EmptyRejectRule,
sizefilter.MaxBytesRule(sharedConfig.BatchSize().AbsoluteMaxBytes),
sigfilter.New(sharedConfig.IngressPolicy, policyManager),
configtx.NewFilter(configManager),
filter.AcceptRule,
Expand All @@ -149,6 +151,7 @@ func createStandardFilters(configManager configtx.Manager, policyManager policie
func createSystemChainFilters(ml *multiLedger, configManager configtx.Manager, policyManager policies.Manager, sharedConfig sharedconfig.Manager) *filter.RuleSet {
return filter.NewRuleSet([]filter.Rule{
filter.EmptyRejectRule,
sizefilter.MaxBytesRule(sharedConfig.BatchSize().AbsoluteMaxBytes),
sigfilter.New(sharedConfig.IngressPolicy, policyManager),
newSystemChainFilter(ml),
configtx.NewFilter(configManager),
Expand Down

0 comments on commit 012f0b5

Please sign in to comment.