Skip to content

Commit

Permalink
[FAB-17660] Retrieve Channel configuration (hyperledger#962)
Browse files Browse the repository at this point in the history
* Added retrieve channel configuration from config.
* Added retrieve consortiums from config.
* Moved channelID out of Channel struct.

Signed-off-by: Chongxin Luo <[email protected]>
  • Loading branch information
DereckLuo authored Apr 3, 2020
1 parent 77eda6c commit 22fd313
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 34 deletions.
4 changes: 2 additions & 2 deletions integration/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ var _ = Describe("Config", func() {

By("setting up the channel")
channel := config.Channel{
ChannelID: "testchannel",
Consortium: "SampleConsortium",
Application: config.Application{
Organizations: []config.Organization{
Expand Down Expand Up @@ -115,7 +114,8 @@ var _ = Describe("Config", func() {
},
}

envelope, err := config.NewCreateChannelTx(channel)
channelID := "testchannel"
envelope, err := config.NewCreateChannelTx(channel, channelID)
Expect(err).NotTo(HaveOccurred())
envBytes, err := proto.Marshal(envelope)
Expect(err).NotTo(HaveOccurred())
Expand Down
105 changes: 83 additions & 22 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ type Channel struct {
Consortiums []Consortium
Capabilities []string
Policies map[string]Policy
ChannelID string
}

// Policy is an expression used to define rules for access to channels, chaincodes, etc.
Expand Down Expand Up @@ -95,13 +94,91 @@ func (c *ConfigTx) Updated() *cb.Config {
return c.updated
}

// ComputeUpdate computes the ConfigUpdate from a base and modified config transaction.
func (c *ConfigTx) ComputeUpdate(channelID string) (*cb.ConfigUpdate, error) {
if channelID == "" {
return nil, errors.New("channel ID is required")
}

updt, err := computeConfigUpdate(c.base, c.updated)
if err != nil {
return nil, fmt.Errorf("failed to compute update: %v", err)
}

updt.ChannelId = channelID

return updt, nil
}

// ChannelConfiguration returns a channel configuration value from a config transaction.
func (c *ConfigTx) ChannelConfiguration() (Channel, error) {
channelGroup := c.base.ChannelGroup
var (
err error
consortium string
application Application
orderer Orderer
consortiums []Consortium
capabilities []string
)

if _, ok := channelGroup.Values[ConsortiumKey]; ok {
consortiumProto := &cb.Consortium{}
err := unmarshalConfigValueAtKey(channelGroup, ConsortiumKey, consortiumProto)
if err != nil {
return Channel{}, err
}
consortium = consortiumProto.Name
}

if _, ok := channelGroup.Groups[ApplicationGroupKey]; ok {
application, err = c.GetApplicationConfiguration()
if err != nil {
return Channel{}, err
}
}

if _, ok := channelGroup.Groups[OrdererGroupKey]; ok {
orderer, err = c.GetOrdererConfiguration()
if err != nil {
return Channel{}, err
}
}

if _, ok := channelGroup.Groups[ConsortiumsGroupKey]; ok {
consortiums, err = c.Consortiums()
if err != nil {
return Channel{}, err
}
}

if _, ok := channelGroup.Values[CapabilitiesKey]; ok {
capabilities, err = c.GetChannelCapabilities()
if err != nil {
return Channel{}, err
}
}

policies, err := c.GetPoliciesForChannel()
if err != nil {
return Channel{}, err
}

return Channel{
Consortium: consortium,
Application: application,
Orderer: orderer,
Consortiums: consortiums,
Capabilities: capabilities,
Policies: policies,
}, nil
}

// NewCreateChannelTx creates a create channel tx using the provided application channel
// configuration and returns an unsigned envelope for an application channel creation transaction.
func NewCreateChannelTx(channelConfig Channel) (*cb.Envelope, error) {
func NewCreateChannelTx(channelConfig Channel, channelID string) (*cb.Envelope, error) {
var err error

channelID := channelConfig.ChannelID

if channelID == "" {
return nil, errors.New("profile's channel ID is required")
}
Expand Down Expand Up @@ -189,22 +266,6 @@ func CreateSignedConfigUpdateEnvelope(configUpdate *cb.ConfigUpdate, signingIden
return signedEnvelope, nil
}

// ComputeUpdate computes the ConfigUpdate from a base and modified config transaction.
func (c *ConfigTx) ComputeUpdate(channelID string) (*cb.ConfigUpdate, error) {
if channelID == "" {
return nil, errors.New("channel ID is required")
}

updt, err := computeConfigUpdate(c.base, c.updated)
if err != nil {
return nil, fmt.Errorf("failed to compute update: %v", err)
}

updt.ChannelId = channelID

return updt, nil
}

func signatureHeader(signingIdentity SigningIdentity) (*cb.SignatureHeader, error) {
buffer := bytes.NewBuffer(nil)

Expand Down Expand Up @@ -273,7 +334,7 @@ func newSystemChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) {
return nil, fmt.Errorf("failed to add system channel policies: %v", err)
}

if len(channelConfig.Orderer.Addresses) <= 0 {
if len(channelConfig.Orderer.Addresses) == 0 {
return nil, errors.New("orderer endpoints is not defined in channel config")
}

Expand All @@ -291,7 +352,7 @@ func newSystemChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) {
return nil, err
}

if len(channelConfig.Capabilities) <= 0 {
if len(channelConfig.Capabilities) == 0 {
return nil, errors.New("capabilities is not defined in channel config")
}

Expand Down
108 changes: 102 additions & 6 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func TestNewCreateChannelTx(t *testing.T) {
profile := baseProfile(t)

// creating a create channel transaction
envelope, err := NewCreateChannelTx(profile)
envelope, err := NewCreateChannelTx(profile, "testchannel")
gt.Expect(err).ToNot(HaveOccurred())
gt.Expect(envelope).ToNot(BeNil())

Expand Down Expand Up @@ -276,6 +276,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
tests := []struct {
testName string
profileMod func() Channel
channelID string
err error
}{
{
Expand All @@ -285,6 +286,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
delete(profile.Application.Policies, AdminsPolicyKey)
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: failed to create application group: " +
"no Admins policy defined"),
},
Expand All @@ -295,6 +297,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
delete(profile.Application.Policies, ReadersPolicyKey)
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: failed to create application group: " +
"no Readers policy defined"),
},
Expand All @@ -305,6 +308,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
delete(profile.Application.Policies, WritersPolicyKey)
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: failed to create application group: " +
"no Writers policy defined"),
},
Expand All @@ -318,6 +322,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
}
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: failed to create application group: " +
"invalid implicit meta policy rule: 'ALL': expected two space separated " +
"tokens, but got 1"),
Expand All @@ -332,6 +337,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
}
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: failed to create application group: " +
"invalid implicit meta policy rule: 'ANYY Readers': unknown rule type " +
"'ANYY', expected ALL, ANY, or MAJORITY"),
Expand All @@ -346,6 +352,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
}
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: failed to create application group: " +
"invalid signature policy rule: 'ANYY Readers': Cannot transition " +
"token types from VARIABLE [ANYY] to VARIABLE [Readers]"),
Expand All @@ -360,17 +367,18 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
}
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: failed to create application group: " +
"unknown policy type: GreenPolicy"),
},
{
testName: "When channel ID is not specified in config",
profileMod: func() Channel {
profile := baseProfile(t)
profile.ChannelID = ""
return profile
},
err: errors.New("profile's channel ID is required"),
channelID: "",
err: errors.New("profile's channel ID is required"),
},
{
testName: "When creating the application group fails",
Expand All @@ -379,6 +387,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {
profile.Application.Policies = nil
return profile
},
channelID: "testchannel",
err: errors.New("creating default config template: " +
"failed to create application group: no policies defined"),
},
Expand All @@ -393,7 +402,7 @@ func TestNewCreateChannelTxFailure(t *testing.T) {

profile := tt.profileMod()

env, err := NewCreateChannelTx(profile)
env, err := NewCreateChannelTx(profile, tt.channelID)
gt.Expect(env).To(BeNil())
gt.Expect(err).To(MatchError(tt.err))
})
Expand Down Expand Up @@ -590,9 +599,97 @@ func TestComputeUpdateFailures(t *testing.T) {
}
}

func TestChannelConfiguration(t *testing.T) {
t.Parallel()

baseApplication := baseApplication(t)
baseConsortiums := baseConsortiums(t)
baseOrderer := baseSoloOrderer(t)
policies := standardPolicies()

tests := []struct {
name string
configMod func(gt *GomegaWithT) *cb.Config
expectedChannel Channel
}{
{
name: "retrieve application channel",
configMod: func(gt *GomegaWithT) *cb.Config {
channelGroup := newConfigGroup()

applicationGroup, err := newApplicationGroup(baseApplication)
gt.Expect(err).NotTo(HaveOccurred())
for _, org := range baseApplication.Organizations {
orgGroup, err := newOrgConfigGroup(org)
gt.Expect(err).NotTo(HaveOccurred())
applicationGroup.Groups[org.Name] = orgGroup
}
channelGroup.Groups[ApplicationGroupKey] = applicationGroup
err = addPolicies(channelGroup, standardPolicies(), AdminsPolicyKey)
gt.Expect(err).NotTo(HaveOccurred())

return &cb.Config{
ChannelGroup: channelGroup,
}
},
expectedChannel: Channel{
Application: baseApplication,
Policies: standardPolicies(),
},
},
{
name: "retrieve system channel",
configMod: func(gt *GomegaWithT) *cb.Config {
channel := Channel{
Consortiums: baseConsortiums,
Orderer: baseOrderer,
Capabilities: []string{"V2_0"},
Policies: policies,
Consortium: "testconsortium",
}
channelGroup, err := newSystemChannelGroup(channel)
gt.Expect(err).NotTo(HaveOccurred())

return &cb.Config{
ChannelGroup: channelGroup,
}
},
expectedChannel: Channel{
Consortiums: baseConsortiums,
Orderer: baseOrderer,
Capabilities: []string{"V2_0"},
Policies: policies,
Consortium: "testconsortium",
},
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

config := tt.configMod(gt)
c := New(config)

channel, err := c.ChannelConfiguration()
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(channel.Consortium).To(Equal(tt.expectedChannel.Consortium))
gt.Expect(channel.Application.Organizations).To(ContainElements(tt.expectedChannel.Application.Organizations))
gt.Expect(channel.Application.Capabilities).To(Equal(tt.expectedChannel.Application.Capabilities))
gt.Expect(channel.Application.Policies).To(Equal(tt.expectedChannel.Application.Policies))
gt.Expect(channel.Application.ACLs).To(Equal(tt.expectedChannel.Application.ACLs))
gt.Expect(channel.Orderer).To(Equal(tt.expectedChannel.Orderer))
gt.Expect(len(channel.Consortiums)).To(Equal(len(tt.expectedChannel.Consortiums)))
gt.Expect(channel.Capabilities).To(Equal(tt.expectedChannel.Capabilities))
gt.Expect(channel.Policies).To(Equal(tt.expectedChannel.Policies))
})
}
}

func baseProfile(t *testing.T) Channel {
return Channel{
ChannelID: "testchannel",
Consortium: "SampleConsortium",
Application: baseApplication(t),
Capabilities: []string{"V2_0"},
Expand All @@ -601,7 +698,6 @@ func baseProfile(t *testing.T) Channel {

func baseSystemChannelProfile(t *testing.T) Channel {
return Channel{
ChannelID: "testsystemchannel",
Consortiums: baseConsortiums(t),
Orderer: baseSoloOrderer(t),
Capabilities: []string{"V2_0"},
Expand Down
Loading

0 comments on commit 22fd313

Please sign in to comment.