diff --git a/common/configtx/config.go b/common/configtx/config.go index 85a3595cad2..a7e43f31841 100644 --- a/common/configtx/config.go +++ b/common/configtx/config.go @@ -40,6 +40,7 @@ func NewConfigResult(config *cb.ConfigGroup, proposer api.Proposer) (ConfigResul type configResult struct { tx interface{} groupName string + groupKey string group *cb.ConfigGroup valueHandler config.ValueProposer policyHandler policies.Proposer @@ -51,7 +52,7 @@ type configResult struct { func (cr *configResult) JSON() string { var buffer bytes.Buffer buffer.WriteString("{") - cr.bufferJSON(&buffer) + cr.subResults[0].bufferJSON(&buffer) buffer.WriteString("}") return buffer.String() @@ -70,7 +71,7 @@ func (cr *configResult) bufferJSON(buffer *bytes.Buffer) { // "GroupName": { buffer.WriteString("\"") - buffer.WriteString(cr.groupName) + buffer.WriteString(cr.groupKey) buffer.WriteString("\": {") // "Values": { @@ -229,6 +230,7 @@ func proposeGroup(result *configResult) error { for i, subGroup := range subGroups { result.subResults = append(result.subResults, &configResult{ tx: result.tx, + groupKey: subGroup, groupName: result.groupName + "/" + subGroup, group: result.group.Groups[subGroup], valueHandler: subValueHandlers[i], @@ -243,12 +245,6 @@ func proposeGroup(result *configResult) error { } } - err = result.preCommit() - if err != nil { - result.rollback() - return err - } - return nil } @@ -271,5 +267,16 @@ func processConfig(channelGroup *cb.ConfigGroup, proposer api.Proposer) (*config func (cm *configManager) processConfig(channelGroup *cb.ConfigGroup) (*configResult, error) { logger.Debugf("Beginning new config for channel %s", cm.current.channelID) - return processConfig(channelGroup, cm.initializer) + configResult, err := processConfig(channelGroup, cm.initializer) + if err != nil { + return nil, err + } + + err = configResult.preCommit() + if err != nil { + configResult.rollback() + return nil, err + } + + return configResult, nil } diff --git a/common/configtx/config_test.go b/common/configtx/config_test.go index 3010272db01..5e68aa83045 100644 --- a/common/configtx/config_test.go +++ b/common/configtx/config_test.go @@ -31,7 +31,7 @@ import ( func TestJSON(t *testing.T) { cr := &configResult{ - groupName: "rootGroup", + groupKey: "rootGroup", group: &cb.ConfigGroup{ Values: map[string]*cb.ConfigValue{ "outer": &cb.ConfigValue{Version: 1, ModPolicy: "mod1"}, @@ -39,7 +39,7 @@ func TestJSON(t *testing.T) { }, subResults: []*configResult{ &configResult{ - groupName: "innerGroup1", + groupKey: "innerGroup1", group: &cb.ConfigGroup{ Values: map[string]*cb.ConfigValue{ "inner1": &cb.ConfigValue{ModPolicy: "mod3"}, @@ -56,7 +56,7 @@ func TestJSON(t *testing.T) { }, }, &configResult{ - groupName: "innerGroup2", + groupKey: "innerGroup2", group: &cb.ConfigGroup{ Values: map[string]*cb.ConfigValue{ "inner2": &cb.ConfigValue{ModPolicy: "mod3"}, @@ -78,8 +78,10 @@ func TestJSON(t *testing.T) { }, } + crWrapper := &configResult{subResults: []*configResult{cr}} + buffer := &bytes.Buffer{} - assert.NoError(t, json.Indent(buffer, []byte(cr.JSON()), "", ""), "JSON should parse nicely") + assert.NoError(t, json.Indent(buffer, []byte(crWrapper.JSON()), "", ""), "JSON should parse nicely") expected := "{\"rootGroup\":{\"Values\":{\"outer\":{\"Version\":\"1\",\"ModPolicy\":\"mod1\",\"Value\":{\"type\":\"outer\"}}},\"Policies\":{},\"Groups\":{\"innerGroup1\":{\"Values\":{\"inner1\":{\"Version\":\"0\",\"ModPolicy\":\"mod3\",\"Value\":{\"type\":\"inner1\"}}},\"Policies\":{\"policy1\":{\"Version\":\"0\",\"ModPolicy\":\"mod1\",\"Policy\":{\"PolicyType\":\"0\",\"Policy\":{\"type\":\"policy1\"}}}},\"Groups\":{}},\"innerGroup2\":{\"Values\":{\"inner2\":{\"Version\":\"0\",\"ModPolicy\":\"mod3\",\"Value\":{\"type\":\"inner2\"}}},\"Policies\":{\"policy2\":{\"Version\":\"0\",\"ModPolicy\":\"mod2\",\"Policy\":{\"PolicyType\":\"1\",\"Policy\":{\"type\":\"policy2\"}}}},\"Groups\":{}}}}}" diff --git a/common/configtx/configmap.go b/common/configtx/configmap.go index bdf4f8b03f1..398b5c37e63 100644 --- a/common/configtx/configmap.go +++ b/common/configtx/configmap.go @@ -33,9 +33,9 @@ const ( PathSeparator = "/" ) -// mapConfig is intended to be called outside this file +// MapConfig is intended to be called outside this file // it takes a ConfigGroup and generates a map of fqPath to comparables (or error on invalid keys) -func mapConfig(channelGroup *cb.ConfigGroup) (map[string]comparable, error) { +func MapConfig(channelGroup *cb.ConfigGroup) (map[string]comparable, error) { result := make(map[string]comparable) if channelGroup != nil { err := recurseConfig(result, []string{RootGroupKey}, channelGroup) @@ -46,7 +46,7 @@ func mapConfig(channelGroup *cb.ConfigGroup) (map[string]comparable, error) { return result, nil } -// addToMap is used only internally by mapConfig +// addToMap is used only internally by MapConfig func addToMap(cg comparable, result map[string]comparable) error { var fqPath string @@ -77,7 +77,7 @@ func addToMap(cg comparable, result map[string]comparable) error { return nil } -// recurseConfig is used only internally by mapConfig +// recurseConfig is used only internally by MapConfig func recurseConfig(result map[string]comparable, path []string, group *cb.ConfigGroup) error { if err := addToMap(comparable{key: path[len(path)-1], path: path[:len(path)-1], ConfigGroup: group}, result); err != nil { return err diff --git a/common/configtx/configmap_test.go b/common/configtx/configmap_test.go index d884abafc42..776360290da 100644 --- a/common/configtx/configmap_test.go +++ b/common/configtx/configmap_test.go @@ -38,7 +38,7 @@ func TestConfigMap(t *testing.T) { config.Groups["0DeepGroup"].Groups["1DeepGroup"] = cb.NewConfigGroup() config.Groups["0DeepGroup"].Groups["1DeepGroup"].Values["2DeepValue"] = &cb.ConfigValue{} - confMap, err := mapConfig(config) + confMap, err := MapConfig(config) assert.NoError(t, err, "Should not have errored building map") assert.Len(t, confMap, 7, "There should be 7 entries in the config map") @@ -68,7 +68,7 @@ func TestMapConfigBack(t *testing.T) { config.Groups["0DeepGroup"].Groups["1DeepGroup"] = cb.NewConfigGroup() config.Groups["0DeepGroup"].Groups["1DeepGroup"].Values["2DeepValue"] = &cb.ConfigValue{} - confMap, err := mapConfig(config) + confMap, err := MapConfig(config) assert.NoError(t, err, "Should not have errored building map") newConfig, err := configMapToConfig(confMap) diff --git a/common/configtx/manager.go b/common/configtx/manager.go index c31e1be4897..a982f4305fd 100644 --- a/common/configtx/manager.go +++ b/common/configtx/manager.go @@ -102,7 +102,7 @@ func NewManagerImpl(envConfig *cb.Envelope, initializer api.Initializer, callOnU return nil, fmt.Errorf("Bad channel id: %s", err) } - configMap, err := mapConfig(configEnv.Config.ChannelGroup) + configMap, err := MapConfig(configEnv.Config.ChannelGroup) if err != nil { return nil, fmt.Errorf("Error converting config to map: %s", err) } diff --git a/common/configtx/tool/configtxgen/main.go b/common/configtx/tool/configtxgen/main.go index dcfa382491a..ccec611209a 100644 --- a/common/configtx/tool/configtxgen/main.go +++ b/common/configtx/tool/configtxgen/main.go @@ -195,21 +195,29 @@ func doInspectBlock(inspectBlock string) error { return fmt.Errorf("ConfigEnvelope contained no config") } - configResult, err := configtx.NewConfigResult(configEnvelope.Config.ChannelGroup, configtx.NewInitializer()) + configAsJSON, err := configGroupAsJSON(configEnvelope.Config.ChannelGroup) if err != nil { - return fmt.Errorf("Error parsing configuration: %s", err) + return err + } + + fmt.Printf("Config for channel: %s at sequence %d\n", header.ChannelId, configEnvelope.Config.Sequence) + fmt.Println(configAsJSON) + + return nil +} + +func configGroupAsJSON(group *cb.ConfigGroup) (string, error) { + configResult, err := configtx.NewConfigResult(group, configtx.NewInitializer()) + if err != nil { + return "", fmt.Errorf("Error parsing config: %s", err) } buffer := &bytes.Buffer{} err = json.Indent(buffer, []byte(configResult.JSON()), "", " ") if err != nil { - return fmt.Errorf("Error in output JSON (usually a programming bug): %s", err) + return "", fmt.Errorf("Error in output JSON (usually a programming bug): %s", err) } - - fmt.Printf("Config for channel: %s at sequence %d\n", header.ChannelId, configEnvelope.Config.Sequence) - - fmt.Println(buffer.String()) - return nil + return buffer.String(), nil } func doInspectChannelCreateTx(inspectChannelCreateTx string) error { @@ -253,21 +261,48 @@ func doInspectChannelCreateTx(inspectChannelCreateTx string) error { return fmt.Errorf("ConfigUpdateEnvelope was for different channel than envelope: %s vs %s", configUpdate.ChannelId, header.ChannelId) } + fmt.Printf("\nChannel creation for channel: %s\n", header.ChannelId) + fmt.Println() + + if configUpdate.ReadSet == nil { + fmt.Println("Read Set: empty") + } else { + fmt.Println("Read Set:") + readSetAsJSON, err := configGroupAsJSON(configUpdate.ReadSet) + if err != nil { + return err + } + fmt.Println(readSetAsJSON) + } + fmt.Println() + if configUpdate.WriteSet == nil { return fmt.Errorf("Empty WriteSet") } - if configUpdate.WriteSet.Groups[config.ApplicationGroupKey] == nil { - return fmt.Errorf("Empty Application group") + fmt.Println("Write Set:") + writeSetAsJSON, err := configGroupAsJSON(configUpdate.WriteSet) + if err != nil { + return err } + fmt.Println(writeSetAsJSON) + fmt.Println() - var orgs []string - - for name := range configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups { - orgs = append(orgs, name) + readSetMap, err := configtx.MapConfig(configUpdate.ReadSet) + if err != nil { + return fmt.Errorf("Error mapping read set: %s", err) + } + writeSetMap, err := configtx.MapConfig(configUpdate.WriteSet) + if err != nil { + return fmt.Errorf("Error mapping write set: %s", err) } - fmt.Printf("\nChannel creation for channel: %s with orgs %v\n\n", header.ChannelId, orgs) + fmt.Println("Delta Set:") + deltaSet := configtx.ComputeDeltaSet(readSetMap, writeSetMap) + for key := range deltaSet { + fmt.Println(key) + } + fmt.Println() return nil } diff --git a/common/configtx/update.go b/common/configtx/update.go index cba78fa727b..bdb3b6f4797 100644 --- a/common/configtx/update.go +++ b/common/configtx/update.go @@ -38,7 +38,7 @@ func (c *configSet) verifyReadSet(readSet map[string]comparable) error { return nil } -func computeDeltaSet(readSet, writeSet map[string]comparable) map[string]comparable { +func ComputeDeltaSet(readSet, writeSet map[string]comparable) map[string]comparable { result := make(map[string]comparable) for key, value := range writeSet { readVal, ok := readSet[key] @@ -107,7 +107,7 @@ func (cm *configManager) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelop return nil, fmt.Errorf("Update not for correct channel: %s for %s", configUpdate.ChannelId, cm.current.channelID) } - readSet, err := mapConfig(configUpdate.ReadSet) + readSet, err := MapConfig(configUpdate.ReadSet) if err != nil { return nil, fmt.Errorf("Error mapping ReadSet: %s", err) } @@ -116,12 +116,12 @@ func (cm *configManager) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelop return nil, fmt.Errorf("Error validating ReadSet: %s", err) } - writeSet, err := mapConfig(configUpdate.WriteSet) + writeSet, err := MapConfig(configUpdate.WriteSet) if err != nil { return nil, fmt.Errorf("Error mapping WriteSet: %s", err) } - deltaSet := computeDeltaSet(readSet, writeSet) + deltaSet := ComputeDeltaSet(readSet, writeSet) signedData, err := configUpdateEnv.AsSignedData() if err != nil { return nil, err diff --git a/common/configtx/update_test.go b/common/configtx/update_test.go index 4f85f77ea4e..cf3922fe051 100644 --- a/common/configtx/update_test.go +++ b/common/configtx/update_test.go @@ -66,7 +66,7 @@ func TestComputeDeltaSet(t *testing.T) { writeSet["2"] = comparable{ConfigValue: &cb.ConfigValue{Version: 1}} writeSet["3"] = comparable{} - result := computeDeltaSet(readSet, writeSet) + result := ComputeDeltaSet(readSet, writeSet) assert.Len(t, result, 2, "Should have two values in the delta set") assert.NotNil(t, result["2"], "Element had version increased") assert.NotNil(t, result["3"], "Element was new")