From 3c10c4636f4ac491bf4ed44c31e81e385992df1c Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Tue, 7 Feb 2017 13:29:24 -0500 Subject: [PATCH] [FAB-2097] Add config next proto https://jira.hyperledger.org/browse/FAB-2097 Rather than modify the config protos and the config producers, parsing, and consumers all at once, this CR adds only the new protos, without removing the old, and makes the minimal changes required only to use the new proto format while on the wire. Change-Id: I3fa2b92461a5f1e4418a59d1256c00a2fadcd49a Signed-off-by: Jason Yellick --- common/configtx/manager.go | 12 ++ common/configtx/template.go | 105 ++++++++++++++- common/configtx/template_test.go | 64 +++++++--- common/configtx/util.go | 70 ++++++++++ core/peer/peer.go | 2 +- orderer/multichain/manager.go | 2 +- orderer/multichain/systemchain.go | 5 +- orderer/multichain/systemchain_test.go | 36 ++---- orderer/multichain/util_test.go | 22 ++-- protos/common/common.pb.go | 4 + protos/common/configtx.go | 25 ++++ protos/common/configtx.pb.go | 169 ++++++++++++++++++++----- protos/common/configtx.proto | 32 ++++- 13 files changed, 453 insertions(+), 95 deletions(-) create mode 100644 protos/common/configtx.go diff --git a/common/configtx/manager.go b/common/configtx/manager.go index 32efd7b46ad..dea7d301555 100644 --- a/common/configtx/manager.go +++ b/common/configtx/manager.go @@ -24,6 +24,7 @@ import ( "github.com/hyperledger/fabric/common/policies" cb "github.com/hyperledger/fabric/protos/common" + "github.com/hyperledger/fabric/protos/utils" logging "github.com/op/go-logging" ) @@ -151,6 +152,17 @@ func validateChainID(chainID string) error { return nil } +func NewManagerImplNext(configtx *cb.ConfigEnvelope, initializer Initializer, callOnUpdate []func(Manager)) (Manager, error) { + configNext, err := UnmarshalConfigNext(configtx.Config) + if err != nil { + return nil, err + } + + config := ConfigNextToConfig(configNext) + + return NewManagerImpl(&cb.ConfigEnvelope{Config: utils.MarshalOrPanic(config), Signatures: configtx.Signatures}, initializer, callOnUpdate) +} + // NewManagerImpl creates a new Manager unless an error is encountered, each element of the callOnUpdate slice // is invoked when a new config is committed func NewManagerImpl(configtx *cb.ConfigEnvelope, initializer Initializer, callOnUpdate []func(Manager)) (Manager, error) { diff --git a/common/configtx/template.go b/common/configtx/template.go index 55c13698a53..554e85a4cb4 100644 --- a/common/configtx/template.go +++ b/common/configtx/template.go @@ -32,6 +32,10 @@ const ( CreationPolicyKey = "CreationPolicy" msgVersion = int32(0) epoch = 0 + + ApplicationGroup = "Application" + OrdererGroup = "Orderer" + MSPKey = "MSP" ) // Template can be used to faciliate creation of config transactions @@ -45,18 +49,59 @@ type simpleTemplate struct { } // NewSimpleTemplate creates a Template using the supplied items +// XXX This signature will change soon, leaving as is for backwards compatibility func NewSimpleTemplate(items ...*cb.ConfigItem) Template { return &simpleTemplate{items: items} } // Items returns a set of ConfigEnvelopes for the given chainID, and errors only on marshaling errors func (st *simpleTemplate) Envelope(chainID string) (*cb.ConfigEnvelope, error) { - marshaledConfig, err := proto.Marshal(&cb.Config{ + channel := cb.NewConfigGroup() + channel.Groups[ApplicationGroup] = cb.NewConfigGroup() + channel.Groups[OrdererGroup] = cb.NewConfigGroup() + + for _, item := range st.items { + var values map[string]*cb.ConfigValue + switch item.Type { + case cb.ConfigItem_Peer: + values = channel.Groups[ApplicationGroup].Values + case cb.ConfigItem_Orderer: + values = channel.Groups[OrdererGroup].Values + case cb.ConfigItem_Chain: + values = channel.Values + case cb.ConfigItem_Policy: + logger.Debugf("Templating about policy %s", item.Key) + policy := &cb.Policy{} + err := proto.Unmarshal(item.Value, policy) + if err != nil { + return nil, err + } + channel.Policies[item.Key] = &cb.ConfigPolicy{ + Policy: policy, + } + continue + case cb.ConfigItem_MSP: + group := cb.NewConfigGroup() + channel.Groups[ApplicationGroup].Groups[item.Key] = group + channel.Groups[OrdererGroup].Groups[item.Key] = group + group.Values[MSPKey] = &cb.ConfigValue{ + Value: item.Value, + } + continue + } + + // For Peer, Orderer, Chain, types + values[item.Key] = &cb.ConfigValue{ + Value: item.Value, + } + } + + marshaledConfig, err := proto.Marshal(&cb.ConfigNext{ Header: &cb.ChainHeader{ ChainID: chainID, Type: int32(cb.HeaderType_CONFIGURATION_ITEM), }, - Items: st.items, + Channel: channel, }) if err != nil { return nil, err @@ -74,22 +119,70 @@ func NewCompositeTemplate(templates ...Template) Template { return &compositeTemplate{templates: templates} } +func copyGroup(source *cb.ConfigGroup, target *cb.ConfigGroup) error { + for key, value := range source.Values { + _, ok := target.Values[key] + if ok { + return fmt.Errorf("Duplicate key: %s", key) + } + target.Values[key] = value + } + + for key, policy := range source.Policies { + _, ok := target.Policies[key] + if ok { + return fmt.Errorf("Duplicate policy: %s", key) + } + target.Policies[key] = policy + } + + for key, group := range source.Groups { + _, ok := target.Groups[key] + if !ok { + target.Groups[key] = cb.NewConfigGroup() + } + + err := copyGroup(group, target.Groups[key]) + if err != nil { + return fmt.Errorf("Error copying group %s: %s", key, err) + } + } + return nil +} + // Items returns a set of ConfigEnvelopes for the given chainID, and errors only on marshaling errors func (ct *compositeTemplate) Envelope(chainID string) (*cb.ConfigEnvelope, error) { - items := make([][]*cb.ConfigItem, len(ct.templates)) + channel := cb.NewConfigGroup() + channel.Groups[ApplicationGroup] = cb.NewConfigGroup() + channel.Groups[OrdererGroup] = cb.NewConfigGroup() + for i := range ct.templates { configEnv, err := ct.templates[i].Envelope(chainID) if err != nil { return nil, err } - config, err := UnmarshalConfig(configEnv.Config) + config, err := UnmarshalConfigNext(configEnv.Config) + if err != nil { + return nil, err + } + err = copyGroup(config.Channel, channel) if err != nil { return nil, err } - items[i] = config.Items } - return NewSimpleTemplate(join(items...)...).Envelope(chainID) + marshaledConfig, err := proto.Marshal(&cb.ConfigNext{ + Header: &cb.ChainHeader{ + ChainID: chainID, + Type: int32(cb.HeaderType_CONFIGURATION_ITEM), + }, + Channel: channel, + }) + if err != nil { + return nil, err + } + + return &cb.ConfigEnvelope{Config: marshaledConfig}, nil } // NewChainCreationTemplate takes a CreationPolicy and a Template to produce a Template which outputs an appropriately diff --git a/common/configtx/template_test.go b/common/configtx/template_test.go index 69b10709e99..06baf31e9d6 100644 --- a/common/configtx/template_test.go +++ b/common/configtx/template_test.go @@ -32,25 +32,33 @@ func verifyItemsResult(t *testing.T, template Template, count int) { t.Fatalf("Should not have errored: %s", err) } - config, err := UnmarshalConfig(configEnv.Config) + configNext, err := UnmarshalConfigNext(configEnv.Config) if err != nil { t.Fatalf("Should not have errored: %s", err) } + config := ConfigNextToConfig(configNext) if len(config.Items) != count { t.Errorf("Expected %d items, but got %d", count, len(config.Items)) } - for i, item := range config.Items { - expected := fmt.Sprintf("%d", i) - assert.Equal(t, expected, string(item.Value), "Expected %s but got %s", expected, item.Value) + for i, _ := range config.Items { + count := 0 + for _, item := range config.Items { + key := fmt.Sprintf("%d", i) + if key == item.Key { + count++ + } + } + expected := 1 + assert.Equal(t, expected, count, "Expected %d but got %d for %d", expected, count, i) } } func TestSimpleTemplate(t *testing.T) { simple := NewSimpleTemplate( - &cb.ConfigItem{Value: []byte("0")}, - &cb.ConfigItem{Value: []byte("1")}, + &cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "0"}, + &cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "1"}, ) verifyItemsResult(t, simple, 2) } @@ -58,11 +66,11 @@ func TestSimpleTemplate(t *testing.T) { func TestCompositeTemplate(t *testing.T) { composite := NewCompositeTemplate( NewSimpleTemplate( - &cb.ConfigItem{Value: []byte("0")}, - &cb.ConfigItem{Value: []byte("1")}, + &cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "0"}, + &cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "1"}, ), NewSimpleTemplate( - &cb.ConfigItem{Value: []byte("2")}, + &cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "2"}, ), ) @@ -71,8 +79,8 @@ func TestCompositeTemplate(t *testing.T) { func TestNewChainTemplate(t *testing.T) { simple := NewSimpleTemplate( - &cb.ConfigItem{Value: []byte("1")}, - &cb.ConfigItem{Value: []byte("2")}, + &cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "0"}, + &cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "1"}, ) creationPolicy := "Test" @@ -84,24 +92,40 @@ func TestNewChainTemplate(t *testing.T) { t.Fatalf("Error creation a chain creation config") } - config, err := UnmarshalConfig(configEnv.Config) + configNext, err := UnmarshalConfigNext(configEnv.Config) if err != nil { t.Fatalf("Should not have errored: %s", err) } + config := ConfigNextToConfig(configNext) if expected := 3; len(config.Items) != expected { t.Fatalf("Expected %d items, but got %d", expected, len(config.Items)) } - for i, item := range config.Items { - if i == 0 { - if item.Key != CreationPolicyKey { - t.Errorf("First item should have been the creation policy") - } - } else { - if expected := fmt.Sprintf("%d", i); string(item.Value) != expected { - t.Errorf("Expected %s but got %s", expected, item.Value) + for i, _ := range config.Items { + if i == len(config.Items)-1 { + break + } + count := 0 + for _, item := range config.Items { + key := fmt.Sprintf("%d", i) + if key == item.Key { + count++ } } + expected := 1 + assert.Equal(t, expected, count, "Expected %d but got %d for %d", expected, count, i) + } + + foundCreationPolicy := false + for _, item := range config.Items { + if item.Key == CreationPolicyKey { + foundCreationPolicy = true + continue + } + } + + if !foundCreationPolicy { + t.Errorf("Should have found the creation policy") } } diff --git a/common/configtx/util.go b/common/configtx/util.go index 22209b3246a..01c469c1082 100644 --- a/common/configtx/util.go +++ b/common/configtx/util.go @@ -35,6 +35,75 @@ func UnmarshalConfig(data []byte) (*cb.Config, error) { return config, nil } +// UnmarshalConfigNext attempts to unmarshal bytes to a *cb.ConfigNext +func UnmarshalConfigNext(data []byte) (*cb.ConfigNext, error) { + config := &cb.ConfigNext{} + err := proto.Unmarshal(data, config) + if err != nil { + return nil, err + } + return config, nil +} + +// ConfigNextToConfig is a XXX temporary method for use in the change series converting the configtx protos +// so error handling and testing is omitted as it will be removed shortly +func ConfigNextToConfig(config *cb.ConfigNext) *cb.Config { + result := &cb.Config{ + Header: config.Header, + } + + channel := config.Channel + + for key, value := range channel.Values { + result.Items = append(result.Items, &cb.ConfigItem{ + Key: key, + Type: cb.ConfigItem_Chain, + Value: value.Value, + }) + } + + for key, value := range channel.Groups[OrdererGroup].Values { + result.Items = append(result.Items, &cb.ConfigItem{ + Key: key, + Type: cb.ConfigItem_Orderer, + Value: value.Value, + }) + } + + for key, value := range channel.Groups[ApplicationGroup].Values { + result.Items = append(result.Items, &cb.ConfigItem{ + Key: key, + Type: cb.ConfigItem_Peer, + Value: value.Value, + }) + } + + logger.Debugf("Processing polices %v", channel.Policies) + for key, value := range channel.Policies { + logger.Debugf("Reversing policy %s", key) + result.Items = append(result.Items, &cb.ConfigItem{ + Key: key, + Type: cb.ConfigItem_Policy, + Value: utils.MarshalOrPanic(value.Policy), + }) + } + + // Note, for now, all MSPs are encoded in both ApplicationGroup and OrdererGroup, so we only need to pick one + for key, group := range channel.Groups[ApplicationGroup].Groups { + msp, ok := group.Values[MSPKey] + if !ok { + panic("Expected MSP defined") + } + result.Items = append(result.Items, &cb.ConfigItem{ + Key: key, + Type: cb.ConfigItem_MSP, + Value: msp.Value, + }) + } + + return result +} + // UnmarshalConfigEnvelope attempts to unmarshal bytes to a *cb.ConfigEnvelope func UnmarshalConfigEnvelope(data []byte) (*cb.ConfigEnvelope, error) { configEnv := &cb.ConfigEnvelope{} @@ -45,6 +114,7 @@ func UnmarshalConfigEnvelope(data []byte) (*cb.ConfigEnvelope, error) { return configEnv, nil } +// ConfigEnvelopeFromBlock extract the config envelope from a config block func ConfigEnvelopeFromBlock(block *cb.Block) (*cb.ConfigEnvelope, error) { if block.Data == nil || len(block.Data.Data) != 1 { return nil, fmt.Errorf("Not a config block, must contain exactly one tx") diff --git a/core/peer/peer.go b/core/peer/peer.go index 9329e9cf593..d6a547495c8 100644 --- a/core/peer/peer.go +++ b/core/peer/peer.go @@ -172,7 +172,7 @@ func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error { configtxInitializer := configtx.NewInitializer() configtxInitializer.Handlers()[common.ConfigItem_Peer] = sharedConfigHandler - configtxManager, err := configtx.NewManagerImpl( + configtxManager, err := configtx.NewManagerImplNext( configEnvelope, configtxInitializer, []func(cm configtx.Manager){gossipCallbackWrapper}, diff --git a/orderer/multichain/manager.go b/orderer/multichain/manager.go index 9c4b8942789..d332a2dd8d6 100644 --- a/orderer/multichain/manager.go +++ b/orderer/multichain/manager.go @@ -151,7 +151,7 @@ func newConfigResources(configEnvelope *cb.ConfigEnvelope) (*configResources, er initializer := configtx.NewInitializer() initializer.Handlers()[cb.ConfigItem_Orderer] = sharedConfigManager - configManager, err := configtx.NewManagerImpl(configEnvelope, initializer, nil) + configManager, err := configtx.NewManagerImplNext(configEnvelope, initializer, nil) if err != nil { return nil, fmt.Errorf("Error unpacking config transaction: %s", err) } diff --git a/orderer/multichain/systemchain.go b/orderer/multichain/systemchain.go index b44239a82d0..8a96b5664b9 100644 --- a/orderer/multichain/systemchain.go +++ b/orderer/multichain/systemchain.go @@ -148,12 +148,13 @@ func (sc *systemChain) proposeChain(configTx *cb.Envelope) cb.Status { } func (sc *systemChain) authorize(configEnvelope *cb.ConfigEnvelope) cb.Status { - config := &cb.Config{} - err := proto.Unmarshal(configEnvelope.Config, config) + configNext := &cb.ConfigNext{} + err := proto.Unmarshal(configEnvelope.Config, configNext) if err != nil { logger.Debugf("Failing to validate chain creation because of unmarshaling error: %s", err) return cb.Status_BAD_REQUEST } + config := configtx.ConfigNextToConfig(configNext) var creationConfigItem *cb.ConfigItem for _, item := range config.Items { diff --git a/orderer/multichain/systemchain_test.go b/orderer/multichain/systemchain_test.go index 3782f41522a..370737e4b3a 100644 --- a/orderer/multichain/systemchain_test.go +++ b/orderer/multichain/systemchain_test.go @@ -29,7 +29,6 @@ import ( "github.com/hyperledger/fabric/orderer/common/sharedconfig" mocksharedconfig "github.com/hyperledger/fabric/orderer/mocks/sharedconfig" cb "github.com/hyperledger/fabric/protos/common" - ab "github.com/hyperledger/fabric/protos/orderer" "github.com/hyperledger/fabric/protos/utils" ) @@ -116,14 +115,12 @@ func TestGoodProposal(t *testing.T) { mcc.ms.msc.ChainCreationPolicyNamesVal = []string{provisional.AcceptAllPolicyKey} mcc.ms.mpm.mp = &mockPolicy{} - chainCreateTx := &cb.ConfigItem{ - Key: configtx.CreationPolicyKey, - Type: cb.ConfigItem_Orderer, - Value: utils.MarshalOrPanic(&ab.CreationPolicy{ - Policy: provisional.AcceptAllPolicyKey, - }), + configEnv, err := configtx.NewChainCreationTemplate(provisional.AcceptAllPolicyKey, configtx.NewCompositeTemplate()).Envelope(newChainID) + if err != nil { + t.Fatalf("Error constructing configtx") } - ingressTx := makeConfigTxWithItems(newChainID, chainCreateTx) + ingressTx := makeConfigTxFromConfigEnvelope(newChainID, configEnv) + status := mcc.sysChain.proposeChain(ingressTx) if status != cb.Status_SUCCESS { t.Fatalf("Should have successfully proposed chain") @@ -171,15 +168,11 @@ func TestProposalWithBadPolicy(t *testing.T) { mcc := newMockChainCreator() mcc.ms.mpm.mp = &mockPolicy{} - chainCreateTx := &cb.ConfigItem{ - Key: configtx.CreationPolicyKey, - Type: cb.ConfigItem_Orderer, - - Value: utils.MarshalOrPanic(&ab.CreationPolicy{ - Policy: provisional.AcceptAllPolicyKey, - }), + configEnv, err := configtx.NewChainCreationTemplate(provisional.AcceptAllPolicyKey, configtx.NewCompositeTemplate()).Envelope(newChainID) + if err != nil { + t.Fatalf("Error constructing configtx") } - ingressTx := makeConfigTxWithItems(newChainID, chainCreateTx) + ingressTx := makeConfigTxFromConfigEnvelope(newChainID, configEnv) status := mcc.sysChain.proposeChain(ingressTx) @@ -194,14 +187,11 @@ func TestProposalWithMissingPolicy(t *testing.T) { mcc := newMockChainCreator() mcc.ms.msc.ChainCreationPolicyNamesVal = []string{provisional.AcceptAllPolicyKey} - chainCreateTx := &cb.ConfigItem{ - Key: configtx.CreationPolicyKey, - Type: cb.ConfigItem_Orderer, - Value: utils.MarshalOrPanic(&ab.CreationPolicy{ - Policy: provisional.AcceptAllPolicyKey, - }), + configEnv, err := configtx.NewChainCreationTemplate(provisional.AcceptAllPolicyKey, configtx.NewCompositeTemplate()).Envelope(newChainID) + if err != nil { + t.Fatalf("Error constructing configtx") } - ingressTx := makeConfigTxWithItems(newChainID, chainCreateTx) + ingressTx := makeConfigTxFromConfigEnvelope(newChainID, configEnv) status := mcc.sysChain.proposeChain(ingressTx) diff --git a/orderer/multichain/util_test.go b/orderer/multichain/util_test.go index 446e15bb66f..44c87cf8c99 100644 --- a/orderer/multichain/util_test.go +++ b/orderer/multichain/util_test.go @@ -19,6 +19,7 @@ package multichain import ( "fmt" + "github.com/hyperledger/fabric/common/configtx" "github.com/hyperledger/fabric/orderer/common/blockcutter" cb "github.com/hyperledger/fabric/protos/common" "github.com/hyperledger/fabric/protos/utils" @@ -80,12 +81,19 @@ func (mlw *mockLedgerWriter) Append(blockContents []*cb.Envelope, metadata [][]b } func makeConfigTx(chainID string, i int) *cb.Envelope { - return makeConfigTxWithItems(chainID, &cb.ConfigItem{ + configTemplate := configtx.NewSimpleTemplate(&cb.ConfigItem{ + Type: cb.ConfigItem_Orderer, + Key: fmt.Sprintf("%d", i), Value: []byte(fmt.Sprintf("%d", i)), }) + configEnv, err := configTemplate.Envelope(chainID) + if err != nil { + panic(err) + } + return makeConfigTxFromConfigEnvelope(chainID, configEnv) } -func makeConfigTxWithItems(chainID string, items ...*cb.ConfigItem) *cb.Envelope { +func makeConfigTxFromConfigEnvelope(chainID string, configEnv *cb.ConfigEnvelope) *cb.Envelope { payload := &cb.Payload{ Header: &cb.Header{ ChainHeader: &cb.ChainHeader{ @@ -94,15 +102,7 @@ func makeConfigTxWithItems(chainID string, items ...*cb.ConfigItem) *cb.Envelope }, SignatureHeader: &cb.SignatureHeader{}, }, - Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{ - Config: utils.MarshalOrPanic(&cb.Config{ - Items: items, - Header: &cb.ChainHeader{ - Type: int32(cb.HeaderType_CONFIGURATION_ITEM), - ChainID: chainID, - }, - }), - }), + Data: utils.MarshalOrPanic(configEnv), } return &cb.Envelope{ Payload: utils.MarshalOrPanic(payload), diff --git a/protos/common/common.pb.go b/protos/common/common.pb.go index 30885bd74ca..cbc64de4c1b 100644 --- a/protos/common/common.pb.go +++ b/protos/common/common.pb.go @@ -29,6 +29,10 @@ It has these top-level messages: ConfigEnvelope ConfigTemplate Config + ConfigNext + ConfigGroup + ConfigValue + ConfigPolicy ConfigItem ConfigSignature HashingAlgorithm diff --git a/protos/common/configtx.go b/protos/common/configtx.go new file mode 100644 index 00000000000..6d15f439a1d --- /dev/null +++ b/protos/common/configtx.go @@ -0,0 +1,25 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package common + +func NewConfigGroup() *ConfigGroup { + return &ConfigGroup{ + Groups: make(map[string]*ConfigGroup), + Values: make(map[string]*ConfigValue), + Policies: make(map[string]*ConfigPolicy), + } +} diff --git a/protos/common/configtx.pb.go b/protos/common/configtx.pb.go index 62d64ce2c7f..93747e9fb17 100644 --- a/protos/common/configtx.pb.go +++ b/protos/common/configtx.pb.go @@ -41,7 +41,7 @@ var ConfigItem_ConfigType_value = map[string]int32{ func (x ConfigItem_ConfigType) String() string { return proto.EnumName(ConfigItem_ConfigType_name, int32(x)) } -func (ConfigItem_ConfigType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{3, 0} } +func (ConfigItem_ConfigType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{7, 0} } // ConfigEnvelope is designed to contain _all_ configuration for a chain with no dependency // on previous configuration transactions. @@ -125,6 +125,97 @@ func (m *Config) GetItems() []*ConfigItem { return nil } +// XXX this structure is to allow us to minimize the diffs in this change series +// it will be renamed Config once the original is ready to be removed +type ConfigNext struct { + Header *ChainHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` + Channel *ConfigGroup `protobuf:"bytes,2,opt,name=channel" json:"channel,omitempty"` +} + +func (m *ConfigNext) Reset() { *m = ConfigNext{} } +func (m *ConfigNext) String() string { return proto.CompactTextString(m) } +func (*ConfigNext) ProtoMessage() {} +func (*ConfigNext) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *ConfigNext) GetHeader() *ChainHeader { + if m != nil { + return m.Header + } + return nil +} + +func (m *ConfigNext) GetChannel() *ConfigGroup { + if m != nil { + return m.Channel + } + return nil +} + +// ConfigGroup is the hierarchical data structure for holding config +type ConfigGroup struct { + Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` + Groups map[string]*ConfigGroup `protobuf:"bytes,2,rep,name=groups" json:"groups,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Values map[string]*ConfigValue `protobuf:"bytes,3,rep,name=values" json:"values,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Policies map[string]*ConfigPolicy `protobuf:"bytes,4,rep,name=policies" json:"policies,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + ModPolicy string `protobuf:"bytes,5,opt,name=mod_policy,json=modPolicy" json:"mod_policy,omitempty"` +} + +func (m *ConfigGroup) Reset() { *m = ConfigGroup{} } +func (m *ConfigGroup) String() string { return proto.CompactTextString(m) } +func (*ConfigGroup) ProtoMessage() {} +func (*ConfigGroup) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *ConfigGroup) GetGroups() map[string]*ConfigGroup { + if m != nil { + return m.Groups + } + return nil +} + +func (m *ConfigGroup) GetValues() map[string]*ConfigValue { + if m != nil { + return m.Values + } + return nil +} + +func (m *ConfigGroup) GetPolicies() map[string]*ConfigPolicy { + if m != nil { + return m.Policies + } + return nil +} + +// ConfigValue represents an individual piece of config data +type ConfigValue struct { + Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + ModPolicy string `protobuf:"bytes,3,opt,name=mod_policy,json=modPolicy" json:"mod_policy,omitempty"` +} + +func (m *ConfigValue) Reset() { *m = ConfigValue{} } +func (m *ConfigValue) String() string { return proto.CompactTextString(m) } +func (*ConfigValue) ProtoMessage() {} +func (*ConfigValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +type ConfigPolicy struct { + Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` + Policy *Policy `protobuf:"bytes,2,opt,name=policy" json:"policy,omitempty"` + ModPolicy string `protobuf:"bytes,3,opt,name=mod_policy,json=modPolicy" json:"mod_policy,omitempty"` +} + +func (m *ConfigPolicy) Reset() { *m = ConfigPolicy{} } +func (m *ConfigPolicy) String() string { return proto.CompactTextString(m) } +func (*ConfigPolicy) ProtoMessage() {} +func (*ConfigPolicy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +func (m *ConfigPolicy) GetPolicy() *Policy { + if m != nil { + return m.Policy + } + return nil +} + type ConfigItem struct { Type ConfigItem_ConfigType `protobuf:"varint,1,opt,name=Type,enum=common.ConfigItem_ConfigType" json:"Type,omitempty"` LastModified uint64 `protobuf:"varint,2,opt,name=LastModified" json:"LastModified,omitempty"` @@ -136,7 +227,7 @@ type ConfigItem struct { func (m *ConfigItem) Reset() { *m = ConfigItem{} } func (m *ConfigItem) String() string { return proto.CompactTextString(m) } func (*ConfigItem) ProtoMessage() {} -func (*ConfigItem) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } +func (*ConfigItem) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } type ConfigSignature struct { SignatureHeader []byte `protobuf:"bytes,1,opt,name=signature_header,json=signatureHeader,proto3" json:"signature_header,omitempty"` @@ -146,12 +237,16 @@ type ConfigSignature struct { func (m *ConfigSignature) Reset() { *m = ConfigSignature{} } func (m *ConfigSignature) String() string { return proto.CompactTextString(m) } func (*ConfigSignature) ProtoMessage() {} -func (*ConfigSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } +func (*ConfigSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } func init() { proto.RegisterType((*ConfigEnvelope)(nil), "common.ConfigEnvelope") proto.RegisterType((*ConfigTemplate)(nil), "common.ConfigTemplate") proto.RegisterType((*Config)(nil), "common.Config") + proto.RegisterType((*ConfigNext)(nil), "common.ConfigNext") + proto.RegisterType((*ConfigGroup)(nil), "common.ConfigGroup") + proto.RegisterType((*ConfigValue)(nil), "common.ConfigValue") + proto.RegisterType((*ConfigPolicy)(nil), "common.ConfigPolicy") proto.RegisterType((*ConfigItem)(nil), "common.ConfigItem") proto.RegisterType((*ConfigSignature)(nil), "common.ConfigSignature") proto.RegisterEnum("common.ConfigItem_ConfigType", ConfigItem_ConfigType_name, ConfigItem_ConfigType_value) @@ -160,31 +255,45 @@ func init() { func init() { proto.RegisterFile("common/configtx.proto", fileDescriptor1) } var fileDescriptor1 = []byte{ - // 409 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x52, 0x4d, 0x6f, 0xd3, 0x40, - 0x10, 0xc5, 0x1f, 0x71, 0xc9, 0x24, 0x6a, 0xad, 0x29, 0x1f, 0x16, 0x02, 0x29, 0xf2, 0xc9, 0xa8, - 0x22, 0x11, 0xe1, 0x80, 0xc4, 0x91, 0x0a, 0x09, 0x04, 0x15, 0xd1, 0xb6, 0xe2, 0xd0, 0x4b, 0xb5, - 0xb1, 0x27, 0xf6, 0x4a, 0xb6, 0xd7, 0x5a, 0x6f, 0x10, 0xbe, 0xf1, 0xd3, 0x91, 0x77, 0x1d, 0xb7, - 0x05, 0x7a, 0xf2, 0xcc, 0x7b, 0x6f, 0xe6, 0x8d, 0x67, 0x16, 0x9e, 0xa6, 0xb2, 0xaa, 0x64, 0xbd, - 0x4a, 0x65, 0xbd, 0x13, 0xb9, 0xfe, 0xb5, 0x6c, 0x94, 0xd4, 0x12, 0x03, 0x0b, 0xbf, 0x38, 0x1d, - 0xe9, 0xfe, 0x63, 0xc9, 0x98, 0xc3, 0xf1, 0xb9, 0x91, 0x7f, 0xaa, 0x7f, 0x52, 0x29, 0x1b, 0xc2, - 0x67, 0x10, 0xd8, 0x06, 0x91, 0xb3, 0x70, 0x92, 0x39, 0x1b, 0x32, 0x7c, 0x0f, 0xd0, 0x8a, 0xbc, - 0xe6, 0x7a, 0xaf, 0xa8, 0x8d, 0xdc, 0x85, 0x97, 0xcc, 0xd6, 0xcf, 0x97, 0x43, 0x33, 0xdb, 0xe3, - 0xf2, 0xc0, 0xb3, 0x3b, 0xd2, 0xf8, 0xc3, 0xc1, 0xe2, 0x8a, 0xaa, 0xa6, 0xe4, 0x9a, 0x30, 0x81, - 0xc9, 0x17, 0x4d, 0x55, 0x1b, 0x39, 0xa6, 0x0b, 0xde, 0xef, 0xd2, 0x53, 0xcc, 0x0a, 0xe2, 0x1b, - 0x08, 0x2c, 0x88, 0x67, 0x10, 0x14, 0xc4, 0x33, 0x52, 0x66, 0xac, 0xd9, 0xfa, 0x74, 0x2c, 0x2a, - 0xb8, 0xa8, 0x3f, 0x1b, 0x8a, 0x0d, 0x92, 0xde, 0x40, 0x18, 0x03, 0xf7, 0x61, 0x03, 0x23, 0x88, - 0x7f, 0xbb, 0x00, 0xb7, 0x28, 0xbe, 0x05, 0xff, 0xaa, 0x6b, 0xc8, 0x78, 0x1c, 0xaf, 0x5f, 0xfd, - 0x5b, 0x37, 0x84, 0xbd, 0x88, 0x19, 0x29, 0xc6, 0x30, 0xff, 0xc6, 0x5b, 0x7d, 0x21, 0x33, 0xb1, - 0x13, 0x94, 0x45, 0xee, 0xc2, 0x49, 0x7c, 0x76, 0x0f, 0xc3, 0x25, 0xa0, 0x8d, 0x53, 0xae, 0x85, - 0xac, 0x37, 0xb2, 0x14, 0x69, 0x17, 0x79, 0x0b, 0x27, 0x99, 0xb2, 0xff, 0x30, 0x18, 0x82, 0xf7, - 0x95, 0xba, 0xc8, 0x37, 0x82, 0x3e, 0xc4, 0x27, 0x30, 0xf9, 0xc1, 0xcb, 0x3d, 0x45, 0x13, 0x73, - 0x14, 0x9b, 0xc4, 0xe7, 0x87, 0xe1, 0xcd, 0x24, 0x00, 0x81, 0xad, 0x0f, 0x1f, 0xe1, 0x14, 0x26, - 0x66, 0x31, 0xa1, 0x83, 0x33, 0x38, 0xfa, 0xae, 0x32, 0x52, 0xa4, 0x42, 0x17, 0x1f, 0x83, 0xbf, - 0x21, 0x52, 0xa1, 0x87, 0x47, 0xe0, 0x5d, 0x5c, 0x6e, 0x42, 0x3f, 0xbe, 0x86, 0x93, 0xbf, 0xce, - 0x87, 0xaf, 0x21, 0x1c, 0x0f, 0x78, 0x73, 0x67, 0xed, 0x73, 0x76, 0x32, 0xe2, 0x76, 0xe5, 0xf8, - 0x12, 0xa6, 0x23, 0x64, 0xfe, 0x7d, 0xce, 0x6e, 0x81, 0x8f, 0x6f, 0xae, 0xcf, 0x72, 0xa1, 0x8b, - 0xfd, 0xb6, 0xdf, 0xe4, 0xaa, 0xe8, 0x1a, 0x52, 0x25, 0x65, 0x39, 0xa9, 0xd5, 0x8e, 0x6f, 0x95, - 0x48, 0x57, 0xe6, 0x15, 0xb6, 0xc3, 0x9b, 0xdc, 0x06, 0x26, 0x7d, 0xf7, 0x27, 0x00, 0x00, 0xff, - 0xff, 0x9a, 0x2b, 0x43, 0x4d, 0xca, 0x02, 0x00, 0x00, + // 637 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0x51, 0x4f, 0x13, 0x41, + 0x10, 0xb6, 0xbd, 0xeb, 0x95, 0x4e, 0x2b, 0x5c, 0x16, 0xd4, 0x0b, 0x91, 0x88, 0xf7, 0x60, 0x8a, + 0x84, 0x36, 0xe2, 0x03, 0x86, 0xc4, 0x17, 0x09, 0x51, 0x83, 0x60, 0x5d, 0x88, 0x0f, 0xc4, 0x84, + 0x1c, 0xbd, 0xa1, 0xbd, 0xd8, 0xde, 0x5e, 0xf6, 0xae, 0x84, 0x7b, 0xf3, 0xf7, 0xfa, 0x2b, 0xcc, + 0xce, 0xee, 0xd5, 0x6b, 0x2d, 0x35, 0xbc, 0xb4, 0xbb, 0x33, 0xdf, 0x7c, 0xdf, 0xb7, 0xb3, 0xb7, + 0x03, 0x4f, 0xfa, 0x62, 0x3c, 0x16, 0x71, 0xb7, 0x2f, 0xe2, 0x9b, 0x68, 0x90, 0xdd, 0x75, 0x12, + 0x29, 0x32, 0xc1, 0x1c, 0x1d, 0xde, 0x5c, 0x9f, 0xa6, 0xd5, 0x9f, 0x4e, 0x6e, 0x16, 0x35, 0x89, + 0x18, 0x45, 0xfd, 0x08, 0x53, 0x1d, 0xf6, 0x03, 0x58, 0x3d, 0x22, 0x96, 0xe3, 0xf8, 0x16, 0x47, + 0x22, 0x41, 0xf6, 0x14, 0x1c, 0xcd, 0xeb, 0x55, 0xb6, 0x2b, 0xed, 0x16, 0x37, 0x3b, 0x76, 0x00, + 0x90, 0x46, 0x83, 0x38, 0xc8, 0x26, 0x12, 0x53, 0xaf, 0xba, 0x6d, 0xb5, 0x9b, 0xfb, 0xcf, 0x3a, + 0x46, 0x43, 0x73, 0x9c, 0x17, 0x79, 0x5e, 0x82, 0xfa, 0x87, 0x85, 0xc4, 0x05, 0x8e, 0x93, 0x51, + 0x90, 0x21, 0x6b, 0x43, 0xed, 0x73, 0x86, 0xe3, 0xd4, 0xab, 0x10, 0x0b, 0x9b, 0x65, 0x51, 0x29, + 0xae, 0x01, 0xfe, 0x15, 0x38, 0x3a, 0xc8, 0x76, 0xc1, 0x19, 0x62, 0x10, 0xa2, 0x24, 0x5b, 0xcd, + 0xfd, 0xf5, 0x69, 0xd1, 0x30, 0x88, 0xe2, 0x4f, 0x94, 0xe2, 0x06, 0xa2, 0x04, 0x22, 0x12, 0xa8, + 0xde, 0x2f, 0x40, 0x00, 0x7f, 0x08, 0xa0, 0x83, 0x67, 0x78, 0x97, 0x3d, 0x4c, 0x64, 0x0f, 0xea, + 0xfd, 0x61, 0x10, 0xc7, 0x38, 0xf2, 0xaa, 0x73, 0x68, 0x62, 0xfc, 0x28, 0xc5, 0x24, 0xe1, 0x05, + 0xc6, 0xff, 0x6d, 0x41, 0xb3, 0x94, 0x60, 0x1e, 0xd4, 0x6f, 0x51, 0xa6, 0x91, 0x88, 0x49, 0xcc, + 0xe6, 0xc5, 0x96, 0x1d, 0x80, 0x33, 0x50, 0x90, 0xc2, 0xfe, 0x8b, 0x05, 0xbc, 0x1d, 0xfa, 0x4d, + 0x8f, 0xe3, 0x4c, 0xe6, 0xdc, 0xc0, 0x55, 0xe1, 0x6d, 0x30, 0x9a, 0x60, 0xea, 0x59, 0xf7, 0x17, + 0x7e, 0x27, 0x84, 0x29, 0xd4, 0x70, 0xf6, 0x1e, 0x56, 0x8a, 0xef, 0xc2, 0xb3, 0xa9, 0xf4, 0xe5, + 0xa2, 0xd2, 0x9e, 0xc1, 0xe8, 0xe2, 0x69, 0x09, 0xdb, 0x02, 0x18, 0x8b, 0xf0, 0x8a, 0xf6, 0xb9, + 0x57, 0xdb, 0xae, 0xb4, 0x1b, 0xbc, 0x31, 0x16, 0x21, 0xe1, 0xf3, 0xcd, 0x33, 0x68, 0x96, 0xdc, + 0x32, 0x17, 0xac, 0x9f, 0x98, 0xd3, 0xa1, 0x1b, 0x5c, 0x2d, 0xd9, 0x0e, 0xd4, 0xc8, 0xc8, 0xb2, + 0x3e, 0x6a, 0xc4, 0x61, 0xf5, 0x5d, 0x45, 0xf1, 0x95, 0x0e, 0xf1, 0x60, 0x3e, 0xaa, 0x2d, 0xf3, + 0x7d, 0x83, 0xc7, 0x33, 0x27, 0x5b, 0xc0, 0xf8, 0x7a, 0x96, 0x71, 0x63, 0x96, 0x51, 0x9f, 0xb3, + 0x44, 0xe9, 0xff, 0x28, 0xee, 0x9a, 0xc4, 0x96, 0xdc, 0xf5, 0x46, 0x99, 0xb8, 0x65, 0x28, 0xe6, + 0x1a, 0x6a, 0xcd, 0x35, 0xd4, 0x17, 0xd0, 0x2a, 0x0b, 0x2f, 0xa1, 0x7f, 0x05, 0x8e, 0x21, 0xd1, + 0xc6, 0x57, 0x0b, 0xe3, 0xc6, 0xb2, 0xc9, 0xfe, 0x4f, 0xf0, 0x57, 0xb5, 0x78, 0x26, 0xea, 0xed, + 0xb0, 0x37, 0x60, 0x5f, 0xe4, 0x09, 0x92, 0xd8, 0xea, 0xfe, 0xd6, 0xbf, 0xaf, 0xcb, 0x2c, 0x15, + 0x88, 0x13, 0x94, 0xf9, 0xd0, 0xfa, 0x12, 0xa4, 0xd9, 0xa9, 0x08, 0xa3, 0x9b, 0x08, 0x43, 0xb2, + 0x63, 0xf3, 0x99, 0x18, 0xeb, 0x00, 0xd3, 0xeb, 0x7e, 0x90, 0x45, 0x22, 0xee, 0x95, 0xcd, 0x2c, + 0xc8, 0xa8, 0x6b, 0x3a, 0xc1, 0xdc, 0xb3, 0xf5, 0x35, 0x9d, 0x60, 0xae, 0xba, 0x49, 0x0d, 0xa7, + 0x6f, 0xb0, 0xc5, 0xf5, 0xc6, 0x3f, 0x2a, 0xcc, 0x93, 0x13, 0x00, 0x47, 0xd7, 0xbb, 0x8f, 0x58, + 0x03, 0x6a, 0xf4, 0xb2, 0xdd, 0x0a, 0x6b, 0x42, 0xfd, 0xab, 0x0c, 0x51, 0xa2, 0x74, 0xab, 0x6c, + 0x05, 0xec, 0x1e, 0xa2, 0x74, 0x2d, 0x56, 0x07, 0xeb, 0xf4, 0xbc, 0xe7, 0xda, 0xfe, 0x25, 0xac, + 0xcd, 0x0d, 0x39, 0xb6, 0x03, 0xee, 0x74, 0xcc, 0x5d, 0x95, 0xe6, 0x46, 0x8b, 0xaf, 0x4d, 0xe3, + 0x7a, 0x66, 0xb0, 0xe7, 0xd0, 0x98, 0x86, 0xcc, 0x55, 0xff, 0x0d, 0x7c, 0xd8, 0xbb, 0xdc, 0x1d, + 0x44, 0xd9, 0x70, 0x72, 0xad, 0x3a, 0xd9, 0x1d, 0xe6, 0x09, 0xca, 0x11, 0x86, 0x03, 0x94, 0xdd, + 0x9b, 0xe0, 0x5a, 0x46, 0xfd, 0x2e, 0xcd, 0xea, 0xd4, 0x0c, 0xf4, 0x6b, 0x87, 0xb6, 0x6f, 0xff, + 0x04, 0x00, 0x00, 0xff, 0xff, 0x79, 0xf6, 0x9c, 0x49, 0x07, 0x06, 0x00, 0x00, } diff --git a/protos/common/configtx.proto b/protos/common/configtx.proto index 9ee150c7de0..168aa2704d2 100644 --- a/protos/common/configtx.proto +++ b/protos/common/configtx.proto @@ -20,6 +20,7 @@ limitations under the License. syntax = "proto3"; import "common/common.proto"; +import "common/policies.proto"; option go_package = "github.com/hyperledger/fabric/protos/common"; @@ -47,7 +48,7 @@ package common; // 4. All configuration changes have a LastModification of one more than the last configuration's highest LastModification number // 5. All configuration changes satisfy the corresponding modification policy message ConfigEnvelope { - bytes config = 1; // A marshaled Config structure + bytes config = 1; // A marshaled ConfigNext structure repeated ConfigSignature signatures = 2; // Signatures over the config } @@ -64,6 +65,35 @@ message Config { repeated ConfigItem items = 2; } +// XXX this structure is to allow us to minimize the diffs in this change series +// it will be renamed Config once the original is ready to be removed +message ConfigNext { + ChainHeader header = 1; + ConfigGroup channel = 2; +} + +// ConfigGroup is the hierarchical data structure for holding config +message ConfigGroup { + uint64 version = 1; + map groups = 2; + map values = 3; + map policies = 4; + string mod_policy = 5; +} + +// ConfigValue represents an individual piece of config data +message ConfigValue { + uint64 version = 1; + bytes value = 2; + string mod_policy = 3; +} + +message ConfigPolicy { + uint64 version = 1; + Policy policy = 2; + string mod_policy = 3; +} + message ConfigItem { enum ConfigType { Policy = 0; // Implies that the Value is a marshaled Policy message, and may be referred to by Key as a ModificationPolicy