Skip to content

Commit

Permalink
[FAB-17663] Update a consortium group's channel creation policy value
Browse files Browse the repository at this point in the history
Signed-off-by: xu wu <wuxu1103@163.com>
  • Loading branch information
wuxuer authored and sykesm committed Mar 28, 2020
1 parent 23ebd79 commit d7c1796
Show file tree
Hide file tree
Showing 3 changed files with 285 additions and 0 deletions.
168 changes: 168 additions & 0 deletions pkg/config/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,36 @@ import (
. "github.com/onsi/gomega"
)

func fetchSystemChannelConfig() *cb.Config {
return &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
config.ConsortiumsGroupKey: {
Groups: map[string]*cb.ConfigGroup{
"SampleConsortium": {
Groups: map[string]*cb.ConfigGroup{},
Values: map[string]*cb.ConfigValue{
config.ChannelCreationPolicyKey: {
ModPolicy: "/Channel/Orderer/Admins",
Value: marshalOrPanic(&cb.Policy{
Type: 3,
Value: marshalOrPanic(&cb.ImplicitMetaPolicy{
Rule: cb.ImplicitMetaPolicy_ANY,
SubPolicy: config.AdminsPolicyKey,
}),
}),
},
},
},
},
Values: map[string]*cb.ConfigValue{},
Policies: map[string]*cb.ConfigPolicy{},
},
},
},
}
}

// fetchChannelConfig mocks retrieving the config transaction from the most recent configuration block.
func fetchChannelConfig() *cb.Config {
return &cb.Config{
Expand Down Expand Up @@ -461,6 +491,144 @@ func baseMSP(t *testing.T) config.MSP {
}
}

func Example_systemChannel() {
baseConfig := fetchSystemChannelConfig()
c := config.New(baseConfig)

err := c.UpdateConsortiumChannelCreationPolicy("SampleConsortium",
config.Policy{Type: config.ImplicitMetaPolicyType, Rule: "MAJORITY Admins"})
if err != nil {
panic(err)
}

// Compute the delta
configUpdate, err := c.ComputeUpdate("testsyschannel")
if err != nil {
panic(err)
}

// Collect the necessary signatures
// The example respresents a 2 peer 1 org channel, to meet the policies defined
// the transaction will be signed by both peers
configSignatures := []*cb.ConfigSignature{}

peer1SigningIdentity := createSigningIdentity()
peer2SigningIdentity := createSigningIdentity()

signingIdentities := []config.SigningIdentity{
peer1SigningIdentity,
peer2SigningIdentity,
}

for _, si := range signingIdentities {
// Sign the config update with the specified signer identity
configSignature, err := config.SignConfigUpdate(configUpdate, si)
if err != nil {
panic(err)
}

configSignatures = append(configSignatures, configSignature)
}

// Sign the envelope with the list of signatures
envelope, err := config.CreateSignedConfigUpdateEnvelope(configUpdate, peer1SigningIdentity, configSignatures...)
if err != nil {
panic(err)
}

// The below logic outputs the signed envelope in JSON format

// The timestamps of the ChannelHeader varies so this comparison only considers the ConfigUpdateEnvelope JSON.
payload := &cb.Payload{}

err = proto.Unmarshal(envelope.Payload, payload)
if err != nil {
panic(err)
}

data := &cb.ConfigUpdateEnvelope{}

err = proto.Unmarshal(payload.Data, data)
if err != nil {
panic(err)
}

// Signature and nonce is different on every example run
data.Signatures = nil

err = protolator.DeepMarshalJSON(os.Stdout, data)
if err != nil {
panic(err)
}

// Output:
// {
// "config_update": {
// "channel_id": "testsyschannel",
// "isolated_data": {},
// "read_set": {
// "groups": {
// "Consortiums": {
// "groups": {
// "SampleConsortium": {
// "groups": {},
// "mod_policy": "",
// "policies": {},
// "values": {},
// "version": "0"
// }
// },
// "mod_policy": "",
// "policies": {},
// "values": {},
// "version": "0"
// }
// },
// "mod_policy": "",
// "policies": {},
// "values": {},
// "version": "0"
// },
// "write_set": {
// "groups": {
// "Consortiums": {
// "groups": {
// "SampleConsortium": {
// "groups": {},
// "mod_policy": "",
// "policies": {},
// "values": {
// "ChannelCreationPolicy": {
// "mod_policy": "/Channel/Orderer/Admins",
// "value": {
// "type": 3,
// "value": {
// "rule": "MAJORITY",
// "sub_policy": "Admins"
// }
// },
// "version": "1"
// }
// },
// "version": "0"
// }
// },
// "mod_policy": "",
// "policies": {},
// "values": {},
// "version": "0"
// }
// },
// "mod_policy": "",
// "policies": {},
// "values": {},
// "version": "0"
// }
// },
// "signatures": []
// }
}

func Example_usage() {
// Retrieve the config for the channel
baseConfig := fetchChannelConfig()
Expand Down
25 changes: 25 additions & 0 deletions pkg/config/policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,31 @@ import (
"github.com/hyperledger/fabric/common/policydsl"
)

// UpdateConsortiumChannelCreationPolicy update a consortium group's channel creation policy value
func (c *ConfigTx) UpdateConsortiumChannelCreationPolicy(consortiumName string, policy Policy) error {
consortium, ok := c.updated.ChannelGroup.Groups[ConsortiumsGroupKey].Groups[consortiumName]
if !ok {
return fmt.Errorf("consortium %s does not exist in channel config", consortiumName)
}

imp, err := implicitMetaFromString(policy.Rule)
if err != nil {
return fmt.Errorf("invalid implicit meta policy rule '%s': %v", policy.Rule, err)
}

implicitMetaPolicy, err := implicitMetaPolicy(imp.SubPolicy, imp.Rule)
if err != nil {
return fmt.Errorf("failed to make implicit meta policy: %v", err)
}

// update channel creation policy value back to consortium
if err = addValue(consortium, channelCreationPolicyValue(implicitMetaPolicy), ordererAdminsPolicyName); err != nil {
return fmt.Errorf("failed to update channel creation policy to consortium %s: %v", consortiumName, err)
}

return nil
}

// GetPoliciesForConsortiums returns a map of policies for channel consortiums.
func (c *ConfigTx) GetPoliciesForConsortiums() (map[string]Policy, error) {
consortiums, ok := c.base.ChannelGroup.Groups[ConsortiumsGroupKey]
Expand Down
92 changes: 92 additions & 0 deletions pkg/config/policies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package config
import (
"testing"

"github.com/golang/protobuf/proto"
cb "github.com/hyperledger/fabric-protos-go/common"
. "github.com/onsi/gomega"
)
Expand Down Expand Up @@ -799,3 +800,94 @@ func TestRemoveOrdererOrgPolicyFailures(t *testing.T) {
err = c.RemoveOrdererOrgPolicy("bad-org", "TestPolicy")
gt.Expect(err).To(MatchError("orderer org bad-org does not exist in channel config"))
}

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

gt := NewGomegaWithT(t)

consortiums := baseConsortiums(t)

consortiumsGroup, err := newConsortiumsGroup(consortiums)
gt.Expect(err).NotTo(HaveOccurred())

config := &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
ConsortiumsGroupKey: consortiumsGroup,
},
},
}
c := &ConfigTx{
base: config,
updated: config,
}

updatedPolicy := Policy{Type: ImplicitMetaPolicyType, Rule: "MAJORITY Admins"}

err = c.UpdateConsortiumChannelCreationPolicy("Consortium1", updatedPolicy)
gt.Expect(err).NotTo(HaveOccurred())

consortium := c.updated.ChannelGroup.Groups[ConsortiumsGroupKey].Groups["Consortium1"]
creationPolicy := consortium.Values[ChannelCreationPolicyKey]
policy := &cb.Policy{}
err = proto.Unmarshal(creationPolicy.Value, policy)
gt.Expect(err).NotTo(HaveOccurred())
imp := &cb.ImplicitMetaPolicy{}
err = proto.Unmarshal(policy.Value, imp)
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(imp.Rule).To(Equal(cb.ImplicitMetaPolicy_MAJORITY))
gt.Expect(imp.SubPolicy).To(Equal("Admins"))
}

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

gt := NewGomegaWithT(t)

consortiums := baseConsortiums(t)

consortiumsGroup, err := newConsortiumsGroup(consortiums)
gt.Expect(err).NotTo(HaveOccurred())

config := &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
ConsortiumsGroupKey: consortiumsGroup,
},
},
}
c := &ConfigTx{
base: config,
updated: config,
}

tests := []struct {
name string
consortiumName string
updatedpolicy Policy
expectedErr string
}{
{
name: "when consortium does not exist in channel config",
consortiumName: "badConsortium",
updatedpolicy: Policy{Type: ImplicitMetaPolicyType, Rule: "MAJORITY Admins"},
expectedErr: "consortium badConsortium does not exist in channel config",
},
{
name: "when policy is invalid",
consortiumName: "Consortium1",
updatedpolicy: Policy{Type: ImplicitMetaPolicyType, Rule: "Bad Admins"},
expectedErr: "invalid implicit meta policy rule 'Bad Admins': unknown rule type 'Bad', expected ALL, ANY, or MAJORITY",
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
gt := NewGomegaWithT(t)
err := c.UpdateConsortiumChannelCreationPolicy(tt.consortiumName, tt.updatedpolicy)
gt.Expect(err).To(MatchError(tt.expectedErr))
})
}
}

0 comments on commit d7c1796

Please sign in to comment.