Skip to content

Commit

Permalink
[FAB-6080] Fix unset mod_policy in channel create
Browse files Browse the repository at this point in the history
For all channels created by the v1.0.x orderer, the Channel group's
mod_policy was left unset. Although the channel is functional, it is not
possible to add config elements to the channel level.

Although it would be nice to simply change this behavior in v1.1,
unfortunately, because the v1.0 orderers validate that the config
computed for the new channel is correct, based on this flawed generation
scheme, if a v1.1 accepts a channel creation tx and generates a new
channel config, the v1.0 orderer would see this new channel config as
flawed (because it tries to validate it using the old broken logic) and
reject it.  The same thing would occur if a v1.0 orderer generated the
flawed channel definition, causing the v1.1 orderer to reject it during
the validation phase.  This could allow the same channel name when
referenced on different orderers to have different backing blockchains
and is not acceptable.

Therefore, this fix uses the newly developed capabilities flags to
determine whether the incompatible behavior should be enabled for an
orderer or not.

Change-Id: I498ac5891eddeef0bc81a928ab8af7fa1ff8d798
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Oct 3, 2017
1 parent a50bd08 commit 361d609
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 2 deletions.
9 changes: 9 additions & 0 deletions common/capabilities/orderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@ import (

const (
ordererTypeName = "Orderer"
OrdererV11 = "V1.1"
)

// OrdererProvider provides capabilities information for orderer level config.
type OrdererProvider struct {
*registry
v11BugFixes bool
}

// NewOrdererProvider creates an orderer capabilities provider.
func NewOrdererProvider(capabilities map[string]*cb.Capability) *OrdererProvider {
cp := &OrdererProvider{}
cp.registry = newRegistry(cp, capabilities)
_, cp.v11BugFixes = capabilities[OrdererV11]
return cp
}

Expand All @@ -39,3 +42,9 @@ func (cp *OrdererProvider) HasCapability(capability string) bool {
return false
}
}

// SetChannelModPolicyDuringCreate specifies whether the v1.0 undesirable behavior of setting the /Channel
// group's mod_policy to "" should be fixed or not.
func (cp *OrdererProvider) SetChannelModPolicyDuringCreate() bool {
return cp.v11BugFixes
}
4 changes: 4 additions & 0 deletions common/channelconfig/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ type ApplicationCapabilities interface {

// OrdererCapabilities defines the capabilities for the orderer portion of a channel
type OrdererCapabilities interface {
// SetChannelModPolicyDuringCreate specifies whether the v1.0 undesirable behavior of setting the /Channel
// group's mod_policy to "" should be fixed or not.
SetChannelModPolicyDuringCreate() bool

// Supported returns an error if there are unknown capabilities in this channel which are required
Supported() error
}
Expand Down
8 changes: 8 additions & 0 deletions common/mocks/config/orderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,17 @@ func (scm *Orderer) Capabilities() channelconfig.OrdererCapabilities {
type OrdererCapabilities struct {
// SupportedErr is returned by Supported()
SupportedErr error

// SetChannelModPolicyDuringCreateVal is returned by SetChannelModPolicyDuringCreate()
SetChannelModPolicyDuringCreateVal bool
}

// Supported returns SupportedErr
func (oc *OrdererCapabilities) Supported() error {
return oc.SupportedErr
}

// SetChannelModPolicyDuringCreate returns SetChannelModPolicyDuringCreateVal
func (oc *OrdererCapabilities) SetChannelModPolicyDuringCreate() bool {
return oc.SetChannelModPolicyDuringCreateVal
}
9 changes: 9 additions & 0 deletions orderer/common/msgprocessor/systemchannel.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ type DefaultTemplatorSupport interface {
// ConsortiumsConfig returns the ordering system channel's Consortiums config.
ConsortiumsConfig() (channelconfig.Consortiums, bool)

// OrdererConfig returns the ordering configuration and whether the configuration exists
OrdererConfig() (channelconfig.Orderer, bool)

// ConfigtxManager returns the configtx manager corresponding to the system channel's current config.
ConfigtxManager() configtxapi.Manager

Expand Down Expand Up @@ -315,6 +318,12 @@ func (dt *DefaultTemplator) NewChannelConfig(envConfigUpdate *cb.Envelope) (chan
channelGroup.Groups[channelconfig.ApplicationGroupKey] = applicationGroup
channelGroup.Values[channelconfig.ConsortiumKey] = channelconfig.TemplateConsortium(consortium.Name).Values[channelconfig.ConsortiumKey]

// Non-backwards compatible bugfix introduced in v1.1
// The capability check should be removed once v1.0 is deprecated
if oc, ok := dt.support.OrdererConfig(); ok && oc.Capabilities().SetChannelModPolicyDuringCreate() {
channelGroup.ModPolicy = systemChannelGroup.ModPolicy
}

bundle, err := channelconfig.NewBundle(channelHeader.ChannelId, &cb.Config{
ChannelGroup: channelGroup,
})
Expand Down
10 changes: 8 additions & 2 deletions orderer/common/msgprocessor/systemchannel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"testing"

"github.com/hyperledger/fabric/common/capabilities"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/configtx"
"github.com/hyperledger/fabric/common/crypto"
Expand Down Expand Up @@ -408,7 +409,11 @@ func (mdts *mockDefaultTemplatorSupport) Signer() crypto.LocalSigner {

func TestNewChannelConfig(t *testing.T) {
channelID := "foo"
singleMSPGenesisBlock := provisional.New(genesisconfig.Load(genesisconfig.SampleSingleMSPSoloProfile)).GenesisBlockForChannel(channelID)
gConf := genesisconfig.Load(genesisconfig.SampleSingleMSPSoloProfile)
gConf.Orderer.Capabilities = map[string]bool{
capabilities.OrdererV11: true,
}
singleMSPGenesisBlock := provisional.New(gConf).GenesisBlockForChannel(channelID)
configEnv := configtx.UnmarshalConfigEnvelopeOrPanic(
utils.UnmarshalPayloadOrPanic(
utils.ExtractEnvelopeOrPanic(singleMSPGenesisBlock, 0).Payload,
Expand Down Expand Up @@ -673,7 +678,8 @@ func TestNewChannelConfig(t *testing.T) {
t.Run("Success", func(t *testing.T) {
createTx, err := channelconfig.MakeChainCreationTransaction("foo", genesisconfig.SampleConsortiumName, nil, genesisconfig.SampleOrgName)
assert.Nil(t, err)
_, err = templator.NewChannelConfig(createTx)
res, err := templator.NewChannelConfig(createTx)
assert.Nil(t, err)
assert.NotEmpty(t, res.ConfigtxManager().ConfigEnvelope().Config.ChannelGroup.ModPolicy)
})
}
12 changes: 12 additions & 0 deletions sampleconfig/configtx.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -290,16 +290,28 @@ Capabilities:
# Global capabilities apply to both the orderers and the peers and must be
# supported by both. Set the value of the capability to true to require it.
Global: &GlobalCapabilities
# V1.1 for Global is a catchall flag for behavior which has been
# determined to be desired for all orderers and peers running v1.0.x,
# but the modification of which would cause imcompatibilities. Users
# should leave this flag set to true.
"V1.1": true

# Orderer capabilities apply only to the orderers, and may be safely
# manipulated without concern for upgrading peers. Set the value of the
# capability to true to require it.
Orderer: &OrdererCapabilities
# V1.1 for Order is a catchall flag for behavior which has been
# determined to be desired for all orderers running v1.0.x, but the
# modification of which would cause imcompatibilities. Users should
# leave this flag set to true.
"V1.1": true

# Application capabilities apply only to the peer network, and may be safely
# manipulated without concern for upgrading orderers. Set the value of the
# capability to true to require it.
Application: &ApplicationCapabilities
# V1.1 for Application is a catchall flag for behavior which has been
# determined to be desired for all peers running v1.0.x, but the
# modification of which would cause imcompatibilities. Users should
# leave this flag set to true.
"V1.1": true

0 comments on commit 361d609

Please sign in to comment.