Skip to content

Commit

Permalink
configtxgen - bft + v_3 validation (#4239)
Browse files Browse the repository at this point in the history
Signed-off-by: Emil Elizarov <emil.elizarov@ibm.com>
Co-authored-by: Emil Elizarov <emil.elizarov@ibm.com>
  • Loading branch information
semil and Emil Elizarov authored Jun 6, 2023
1 parent bc1b51f commit 9e6efe9
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 13 deletions.
32 changes: 32 additions & 0 deletions cmd/configtxgen/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,35 @@ func TestPrintOrg(t *testing.T) {
require.Error(t, err, "Fake org")
require.Regexp(t, "bad org definition", err.Error())
}

func createBftOrdererConfig() *genesisconfig.Profile {
// Load the BFT config from the sample, and use some TLS CA Cert as crypto material
config := genesisconfig.Load(genesisconfig.SampleAppChannelSmartBftProfile, configtest.GetDevConfigDir())
tlsCertPath := filepath.Join(configtest.GetDevConfigDir(), "msp", "tlscacerts", "tlsroot.pem")
for _, consenter := range config.Orderer.ConsenterMapping {
consenter.Identity = tlsCertPath
consenter.ClientTLSCert = tlsCertPath
consenter.ServerTLSCert = tlsCertPath
}
return config
}

func TestBftOrdererTypeWithoutV3CapabilitiesShouldRaiseAnError(t *testing.T) {
// ### Arrange
blockDest := filepath.Join(tmpDir, "block")
config := createBftOrdererConfig()
config.Capabilities["V3_0"] = false

// ### Act & Assert
require.EqualError(t, doOutputBlock(config, "testChannelId", blockDest), "could not create bootstrapper: could not create channel group: could not create orderer group: orderer type BFT must be used with V3_0 capability")
}

func TestBftOrdererTypeWithV3CapabilitiesShouldNotRaiseAnError(t *testing.T) {
// ### Arrange
blockDest := filepath.Join(tmpDir, "block")
config := createBftOrdererConfig()
config.Capabilities["V3_0"] = true

// ### Act & Assert
require.NoError(t, doOutputBlock(config, "testChannelId", blockDest))
}
9 changes: 5 additions & 4 deletions integration/nwo/standard_networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,11 @@ func MultiNodeBFT() *Config {
}
config.Profiles = []*Profile{
{
Name: "TwoOrgsAppChannelBFT",
Consortium: "SampleConsortium",
Organizations: []string{"Org1", "Org2"},
Orderers: []string{"orderer1", "orderer2", "orderer3"},
Name: "TwoOrgsAppChannelBFT",
Consortium: "SampleConsortium",
Organizations: []string{"Org1", "Org2"},
Orderers: []string{"orderer1", "orderer2", "orderer3"},
ChannelCapabilities: []string{"V3_0"},
},
}
config.Channels = []*Channel{{Name: "testchannel", Profile: "TwoOrgsAppChannelBFT"}}
Expand Down
7 changes: 5 additions & 2 deletions internal/configtxgen/encoder/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func NewChannelGroup(conf *genesisconfig.Profile) (*cb.ConfigGroup, error) {

var err error
if conf.Orderer != nil {
channelGroup.Groups[channelconfig.OrdererGroupKey], err = NewOrdererGroup(conf.Orderer)
channelGroup.Groups[channelconfig.OrdererGroupKey], err = NewOrdererGroup(conf.Orderer, conf.Capabilities)
if err != nil {
return nil, errors.Wrap(err, "could not create orderer group")
}
Expand All @@ -181,7 +181,10 @@ func NewChannelGroup(conf *genesisconfig.Profile) (*cb.ConfigGroup, error) {
// NewOrdererGroup returns the orderer component of the channel configuration. It defines parameters of the ordering service
// about how large blocks should be, how frequently they should be emitted, etc. as well as the organizations of the ordering network.
// It sets the mod_policy of all elements to "Admins". This group is always present in any channel configuration.
func NewOrdererGroup(conf *genesisconfig.Orderer) (*cb.ConfigGroup, error) {
func NewOrdererGroup(conf *genesisconfig.Orderer, channelCapabilities map[string]bool) (*cb.ConfigGroup, error) {
if conf.OrdererType == "BFT" && !channelCapabilities["V3_0"] {
return nil, errors.New("orderer type BFT must be used with V3_0 capability")
}
ordererGroup := protoutil.NewConfigGroup()
if err := AddOrdererPolicies(ordererGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil {
return nil, errors.Wrapf(err, "error adding policies to orderer group")
Expand Down
18 changes: 11 additions & 7 deletions internal/configtxgen/encoder/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ var _ = Describe("Encoder", func() {

Describe("NewOrdererGroup", func() {
var conf *genesisconfig.Orderer
var channelCapabilities map[string]bool

BeforeEach(func() {
conf = &genesisconfig.Orderer{
Expand All @@ -362,10 +363,13 @@ var _ = Describe("Encoder", func() {
"FakeCapability": true,
},
}
channelCapabilities = map[string]bool{
"V3_0": true,
}
})

It("translates the config into a config group", func() {
cg, err := encoder.NewOrdererGroup(conf)
cg, err := encoder.NewOrdererGroup(conf, channelCapabilities)
Expect(err).NotTo(HaveOccurred())
Expect(len(cg.Policies)).To(Equal(4)) // BlockValidation automatically added
Expect(cg.Policies["Admins"]).NotTo(BeNil())
Expand All @@ -387,7 +391,7 @@ var _ = Describe("Encoder", func() {
})

It("wraps and returns the error", func() {
_, err := encoder.NewOrdererGroup(conf)
_, err := encoder.NewOrdererGroup(conf, channelCapabilities)
Expect(err).To(MatchError("error adding policies to orderer group: invalid implicit meta policy rule 'garbage': expected two space separated tokens, but got 1"))
})
})
Expand All @@ -403,7 +407,7 @@ var _ = Describe("Encoder", func() {
})

It("adds the raft metadata", func() {
cg, err := encoder.NewOrdererGroup(conf)
cg, err := encoder.NewOrdererGroup(conf, channelCapabilities)
Expect(err).NotTo(HaveOccurred())
Expect(len(cg.Values)).To(Equal(5))
consensusType := &ab.ConsensusType{}
Expand All @@ -426,7 +430,7 @@ var _ = Describe("Encoder", func() {
})

It("wraps and returns the error", func() {
_, err := encoder.NewOrdererGroup(conf)
_, err := encoder.NewOrdererGroup(conf, channelCapabilities)
Expect(err).To(MatchError("cannot marshal metadata for orderer type etcdraft: cannot load client cert for consenter :0: open : no such file or directory"))
})
})
Expand Down Expand Up @@ -456,7 +460,7 @@ var _ = Describe("Encoder", func() {
})

It("adds the Orderers key", func() {
cg, err := encoder.NewOrdererGroup(conf)
cg, err := encoder.NewOrdererGroup(conf, channelCapabilities)
Expect(err).NotTo(HaveOccurred())
Expect(len(cg.Values)).To(Equal(6))
Expect(cg.Values["Orderers"]).NotTo(BeNil())
Expand All @@ -479,7 +483,7 @@ var _ = Describe("Encoder", func() {
})

It("returns an error", func() {
_, err := encoder.NewOrdererGroup(conf)
_, err := encoder.NewOrdererGroup(conf, channelCapabilities)
Expect(err).To(MatchError("unknown orderer type: bad-type"))
})
})
Expand All @@ -490,7 +494,7 @@ var _ = Describe("Encoder", func() {
})

It("wraps and returns the error", func() {
_, err := encoder.NewOrdererGroup(conf)
_, err := encoder.NewOrdererGroup(conf, channelCapabilities)
Expect(err).To(MatchError("failed to create orderer org: 1 - Error loading MSP configuration for org: SampleOrg: unknown MSP type 'garbage'"))
})
})
Expand Down
1 change: 1 addition & 0 deletions sampleconfig/configtx.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ Profiles:
# that uses the etcd/raft-based orderer.
SampleAppChannelSmartBft:
<<: *ChannelDefaults
Consortium: SampleConsortium
Orderer:
<<: *OrdererDefaults
OrdererType: BFT
Expand Down

0 comments on commit 9e6efe9

Please sign in to comment.