Skip to content

Commit

Permalink
Merge "FAB-14158 Add OSN endpoints to orderer org config" into releas…
Browse files Browse the repository at this point in the history
…e-1.4
  • Loading branch information
Jason Yellick authored and Gerrit Code Review committed Jun 4, 2019
2 parents f27a4d4 + e7e317e commit ccaaba0
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 30 deletions.
14 changes: 9 additions & 5 deletions common/channelconfig/channel.go
Expand Up @@ -86,11 +86,12 @@ func NewChannelConfig(channelGroup *cb.ConfigGroup) (*ChannelConfig, error) {
return nil, errors.Wrap(err, "failed to deserialize values")
}

if err := cc.Validate(); err != nil {
capabilities := cc.Capabilities()

if err := cc.Validate(capabilities); err != nil {
return nil, err
}

capabilities := cc.Capabilities()
mspConfigHandler := NewMSPConfigHandler(capabilities.MSPVersion())

var err error
Expand All @@ -99,7 +100,7 @@ func NewChannelConfig(channelGroup *cb.ConfigGroup) (*ChannelConfig, error) {
case ApplicationGroupKey:
cc.appConfig, err = NewApplicationConfig(group, mspConfigHandler)
case OrdererGroupKey:
cc.ordererConfig, err = NewOrdererConfig(group, mspConfigHandler)
cc.ordererConfig, err = NewOrdererConfig(group, mspConfigHandler, capabilities)
case ConsortiumsGroupKey:
cc.consortiumsConfig, err = NewConsortiumsConfig(group, mspConfigHandler)
default:
Expand Down Expand Up @@ -163,17 +164,20 @@ func (cc *ChannelConfig) Capabilities() ChannelCapabilities {
}

// Validate inspects the generated configuration protos and ensures that the values are correct
func (cc *ChannelConfig) Validate() error {
func (cc *ChannelConfig) Validate(channelCapabilities ChannelCapabilities) error {
for _, validator := range []func() error{
cc.validateHashingAlgorithm,
cc.validateBlockDataHashingStructure,
cc.validateOrdererAddresses,
} {
if err := validator(); err != nil {
return err
}
}

if !channelCapabilities.OrgSpecificOrdererEndpoints() {
return cc.validateOrdererAddresses()
}

return nil
}

Expand Down
58 changes: 50 additions & 8 deletions common/channelconfig/orderer.go
Expand Up @@ -39,6 +39,9 @@ const (

// KafkaBrokersKey is the cb.ConfigItem type key name for the KafkaBrokers message.
KafkaBrokersKey = "KafkaBrokers"

// EndpointsKey is the cb.COnfigValue key name for the Endpoints message in the OrdererOrgGroup.
EndpointsKey = "Endpoints"
)

// OrdererProtos is used as the source of the OrdererConfig.
Expand All @@ -59,26 +62,65 @@ type OrdererConfig struct {
batchTimeout time.Duration
}

// OrdererOrgProtos are deserialized from the Orderer org config values
type OrdererOrgProtos struct {
Endpoints *cb.OrdererAddresses
}

// OrdererOrgConfig defines the configuration for an orderer org
type OrdererOrgConfig struct {
*OrganizationConfig
protos *OrdererOrgProtos
name string
}

func (*OrdererOrgConfig) Endpoints() []string {
panic("implement me")
// Endpoints returns the set of addresses this ordering org exposes as orderers
func (oc *OrdererOrgConfig) Endpoints() []string {
return oc.protos.Endpoints.Addresses
}

// NewOrdererOrgConfig returns an orderer org config built from the given ConfigGroup.
func NewOrdererOrgConfig(orgName string, orgGroup *cb.ConfigGroup, mspConfigHandler *MSPConfigHandler) (*OrdererOrgConfig, error) {
orgConf, err := NewOrganizationConfig(orgName, orgGroup, mspConfigHandler)
if err != nil {
func NewOrdererOrgConfig(orgName string, orgGroup *cb.ConfigGroup, mspConfigHandler *MSPConfigHandler, channelCapabilities ChannelCapabilities) (*OrdererOrgConfig, error) {
if len(orgGroup.Groups) > 0 {
return nil, fmt.Errorf("OrdererOrg config does not allow sub-groups")
}

if !channelCapabilities.OrgSpecificOrdererEndpoints() {
if _, ok := orgGroup.Values[EndpointsKey]; ok {
return nil, errors.Errorf("Orderer Org %s cannot contain endpoints value until V2_0+ capabilities have been enabled", orgName)
}
}

protos := &OrdererOrgProtos{}
orgProtos := &OrganizationProtos{}

if err := DeserializeProtoValuesFromGroup(orgGroup, protos, orgProtos); err != nil {
return nil, errors.Wrap(err, "failed to deserialize values")
}

ooc := &OrdererOrgConfig{
name: orgName,
protos: protos,
OrganizationConfig: &OrganizationConfig{
name: orgName,
protos: orgProtos,
mspConfigHandler: mspConfigHandler,
},
}

if err := ooc.Validate(); err != nil {
return nil, err
}
return &OrdererOrgConfig{OrganizationConfig: orgConf}, nil

return ooc, nil
}

func (ooc *OrdererOrgConfig) Validate() error {
return ooc.OrganizationConfig.Validate()
}

// NewOrdererConfig creates a new instance of the orderer config.
func NewOrdererConfig(ordererGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler) (*OrdererConfig, error) {
func NewOrdererConfig(ordererGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler, channelCapabilities ChannelCapabilities) (*OrdererConfig, error) {
oc := &OrdererConfig{
protos: &OrdererProtos{},
orgs: make(map[string]OrdererOrg),
Expand All @@ -94,7 +136,7 @@ func NewOrdererConfig(ordererGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler)

for orgName, orgGroup := range ordererGroup.Groups {
var err error
if oc.orgs[orgName], err = NewOrdererOrgConfig(orgName, orgGroup, mspConfig); err != nil {
if oc.orgs[orgName], err = NewOrdererOrgConfig(orgName, orgGroup, mspConfig, channelCapabilities); err != nil {
return nil, err
}
}
Expand Down
47 changes: 45 additions & 2 deletions common/channelconfig/realconfig_test.go
Expand Up @@ -9,7 +9,7 @@ package channelconfig_test
import (
"testing"

newchannelconfig "github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/tools/configtxgen/configtxgentest"
"github.com/hyperledger/fabric/common/tools/configtxgen/encoder"
genesisconfig "github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
Expand All @@ -36,6 +36,49 @@ func TestWithRealConfigtx(t *testing.T) {
}
gb := encoder.New(conf).GenesisBlockForChannel("foo")
env := utils.ExtractEnvelopeOrPanic(gb, 0)
_, err := newchannelconfig.NewBundleFromEnvelope(env)
_, err := channelconfig.NewBundleFromEnvelope(env)
assert.NoError(t, err)
}

func TestOrgSpecificOrdererEndpoints(t *testing.T) {
t.Run("Without_Capability", func(t *testing.T) {
conf := configtxgentest.Load(genesisconfig.SampleDevModeSoloProfile)
conf.Capabilities = map[string]bool{"V1_3": true}

cg, err := encoder.NewChannelGroup(conf)
assert.NoError(t, err)

_, err = channelconfig.NewChannelConfig(cg)
assert.EqualError(t, err, "could not create channel Orderer sub-group config: Orderer Org SampleOrg cannot contain endpoints value until V2_0+ capabilities have been enabled")
})

t.Run("Without_Capability_NoOSNs", func(t *testing.T) {
conf := configtxgentest.Load(genesisconfig.SampleDevModeSoloProfile)
conf.Capabilities = map[string]bool{"V1_3": true}
conf.Orderer.Organizations[0].OrdererEndpoints = nil
conf.Orderer.Addresses = []string{}

cg, err := encoder.NewChannelGroup(conf)
assert.NoError(t, err)

_, err = channelconfig.NewChannelConfig(cg)
assert.EqualError(t, err, "Must set some OrdererAddresses")
})

t.Run("With_Capability", func(t *testing.T) {
conf := configtxgentest.Load(genesisconfig.SampleDevModeSoloProfile)
conf.Capabilities = map[string]bool{"V1_4_2": true}
assert.NotEmpty(t, conf.Orderer.Organizations[0].OrdererEndpoints)

cg, err := encoder.NewChannelGroup(conf)
assert.NoError(t, err)

cc, err := channelconfig.NewChannelConfig(cg)
assert.NoError(t, err)

err = cc.Validate(cc.Capabilities())
assert.NoError(t, err)

assert.NotEmpty(t, cc.OrdererConfig().Organizations()["SampleOrg"].Endpoints)
})
}
11 changes: 11 additions & 0 deletions common/channelconfig/util.go
Expand Up @@ -188,6 +188,17 @@ func CapabilitiesValue(capabilities map[string]bool) *StandardConfigValue {
}
}

// EndpointsValue returns the config definition for the orderer addresses at an org scoped level.
// It is a value for the /Channel/Orderer/<OrgName> group.
func EndpointsValue(addresses []string) *StandardConfigValue {
return &StandardConfigValue{
key: EndpointsKey,
value: &cb.OrdererAddresses{
Addresses: addresses,
},
}
}

// AnchorPeersValue returns the config definition for an org's anchor peers.
// It is a value for the /Channel/Application/*.
func AnchorPeersValue(anchorPeers []*pb.AnchorPeer) *StandardConfigValue {
Expand Down
39 changes: 33 additions & 6 deletions common/tools/configtxgen/encoder/encoder.go
Expand Up @@ -141,11 +141,9 @@ func NewChannelGroup(conf *genesisconfig.Profile) (*cb.ConfigGroup, error) {

addValue(channelGroup, channelconfig.HashingAlgorithmValue(), channelconfig.AdminsPolicyKey)
addValue(channelGroup, channelconfig.BlockDataHashingStructureValue(), channelconfig.AdminsPolicyKey)
ordererAddresses := []string{}
if conf.Orderer != nil {
ordererAddresses = conf.Orderer.Addresses
if conf.Orderer != nil && len(conf.Orderer.Addresses) > 0 {
addValue(channelGroup, channelconfig.OrdererAddressesValue(conf.Orderer.Addresses), ordererAdminsPolicyName)
}
addValue(channelGroup, channelconfig.OrdererAddressesValue(ordererAddresses), ordererAdminsPolicyName)

if conf.Consortium != "" {
addValue(channelGroup, channelconfig.ConsortiumValue(conf.Consortium), channelconfig.AdminsPolicyKey)
Expand Down Expand Up @@ -239,6 +237,31 @@ func NewOrdererGroup(conf *genesisconfig.Orderer) (*cb.ConfigGroup, error) {
return ordererGroup, nil
}

// NewConsortiumsGroup returns an org component of the channel configuration. It defines the crypto material for the
// organization (its MSP). It sets the mod_policy of all elements to "Admins".
func NewConsortiumOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) {
mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID, conf.MSPType)
if err != nil {
return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org: %s", conf.Name)
}

consortiumOrgGroup := cb.NewConfigGroup()
if len(conf.Policies) == 0 {
logger.Warningf("Default policy emission is deprecated, please include policy specifications for the orderer org group %s in configtx.yaml", conf.Name)
addSignaturePolicyDefaults(consortiumOrgGroup, conf.ID, conf.AdminPrincipal != genesisconfig.AdminRoleAdminPrincipal)
} else {
if err := addPolicies(consortiumOrgGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil {
return nil, errors.Wrapf(err, "error adding policies to orderer org group '%s'", conf.Name)
}
}

addValue(consortiumOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey)

consortiumOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey

return consortiumOrgGroup, nil
}

// NewOrdererOrgGroup returns an orderer org component of the channel configuration. It defines the crypto material for the
// organization (its MSP). It sets the mod_policy of all elements to "Admins".
func NewOrdererOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) {
Expand All @@ -260,6 +283,11 @@ func NewOrdererOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, erro
addValue(ordererOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey)

ordererOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey

if len(conf.OrdererEndpoints) > 0 {
addValue(ordererOrgGroup, channelconfig.EndpointsValue(conf.OrdererEndpoints), channelconfig.AdminsPolicyKey)
}

return ordererOrgGroup, nil
}

Expand Down Expand Up @@ -362,8 +390,7 @@ func NewConsortiumGroup(conf *genesisconfig.Consortium) (*cb.ConfigGroup, error)

for _, org := range conf.Organizations {
var err error
// Note, NewOrdererOrgGroup is correct here, as the structure is identical
consortiumGroup.Groups[org.Name], err = NewOrdererOrgGroup(org)
consortiumGroup.Groups[org.Name], err = NewConsortiumOrgGroup(org)
if err != nil {
return nil, errors.Wrap(err, "failed to create consortium org")
}
Expand Down

0 comments on commit ccaaba0

Please sign in to comment.