Skip to content

Commit 3c10c46

Browse files
author
Jason Yellick
committed
[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 <[email protected]>
1 parent 514db40 commit 3c10c46

13 files changed

+453
-95
lines changed

common/configtx/manager.go

+12
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/hyperledger/fabric/common/policies"
2626
cb "github.com/hyperledger/fabric/protos/common"
27+
"github.com/hyperledger/fabric/protos/utils"
2728

2829
logging "github.com/op/go-logging"
2930
)
@@ -151,6 +152,17 @@ func validateChainID(chainID string) error {
151152
return nil
152153
}
153154

155+
func NewManagerImplNext(configtx *cb.ConfigEnvelope, initializer Initializer, callOnUpdate []func(Manager)) (Manager, error) {
156+
configNext, err := UnmarshalConfigNext(configtx.Config)
157+
if err != nil {
158+
return nil, err
159+
}
160+
161+
config := ConfigNextToConfig(configNext)
162+
163+
return NewManagerImpl(&cb.ConfigEnvelope{Config: utils.MarshalOrPanic(config), Signatures: configtx.Signatures}, initializer, callOnUpdate)
164+
}
165+
154166
// NewManagerImpl creates a new Manager unless an error is encountered, each element of the callOnUpdate slice
155167
// is invoked when a new config is committed
156168
func NewManagerImpl(configtx *cb.ConfigEnvelope, initializer Initializer, callOnUpdate []func(Manager)) (Manager, error) {

common/configtx/template.go

+99-6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const (
3232
CreationPolicyKey = "CreationPolicy"
3333
msgVersion = int32(0)
3434
epoch = 0
35+
36+
ApplicationGroup = "Application"
37+
OrdererGroup = "Orderer"
38+
MSPKey = "MSP"
3539
)
3640

3741
// Template can be used to faciliate creation of config transactions
@@ -45,18 +49,59 @@ type simpleTemplate struct {
4549
}
4650

4751
// NewSimpleTemplate creates a Template using the supplied items
52+
// XXX This signature will change soon, leaving as is for backwards compatibility
4853
func NewSimpleTemplate(items ...*cb.ConfigItem) Template {
4954
return &simpleTemplate{items: items}
5055
}
5156

5257
// Items returns a set of ConfigEnvelopes for the given chainID, and errors only on marshaling errors
5358
func (st *simpleTemplate) Envelope(chainID string) (*cb.ConfigEnvelope, error) {
54-
marshaledConfig, err := proto.Marshal(&cb.Config{
59+
channel := cb.NewConfigGroup()
60+
channel.Groups[ApplicationGroup] = cb.NewConfigGroup()
61+
channel.Groups[OrdererGroup] = cb.NewConfigGroup()
62+
63+
for _, item := range st.items {
64+
var values map[string]*cb.ConfigValue
65+
switch item.Type {
66+
case cb.ConfigItem_Peer:
67+
values = channel.Groups[ApplicationGroup].Values
68+
case cb.ConfigItem_Orderer:
69+
values = channel.Groups[OrdererGroup].Values
70+
case cb.ConfigItem_Chain:
71+
values = channel.Values
72+
case cb.ConfigItem_Policy:
73+
logger.Debugf("Templating about policy %s", item.Key)
74+
policy := &cb.Policy{}
75+
err := proto.Unmarshal(item.Value, policy)
76+
if err != nil {
77+
return nil, err
78+
}
79+
channel.Policies[item.Key] = &cb.ConfigPolicy{
80+
Policy: policy,
81+
}
82+
continue
83+
case cb.ConfigItem_MSP:
84+
group := cb.NewConfigGroup()
85+
channel.Groups[ApplicationGroup].Groups[item.Key] = group
86+
channel.Groups[OrdererGroup].Groups[item.Key] = group
87+
group.Values[MSPKey] = &cb.ConfigValue{
88+
Value: item.Value,
89+
}
90+
continue
91+
}
92+
93+
// For Peer, Orderer, Chain, types
94+
values[item.Key] = &cb.ConfigValue{
95+
Value: item.Value,
96+
}
97+
}
98+
99+
marshaledConfig, err := proto.Marshal(&cb.ConfigNext{
55100
Header: &cb.ChainHeader{
56101
ChainID: chainID,
57102
Type: int32(cb.HeaderType_CONFIGURATION_ITEM),
58103
},
59-
Items: st.items,
104+
Channel: channel,
60105
})
61106
if err != nil {
62107
return nil, err
@@ -74,22 +119,70 @@ func NewCompositeTemplate(templates ...Template) Template {
74119
return &compositeTemplate{templates: templates}
75120
}
76121

122+
func copyGroup(source *cb.ConfigGroup, target *cb.ConfigGroup) error {
123+
for key, value := range source.Values {
124+
_, ok := target.Values[key]
125+
if ok {
126+
return fmt.Errorf("Duplicate key: %s", key)
127+
}
128+
target.Values[key] = value
129+
}
130+
131+
for key, policy := range source.Policies {
132+
_, ok := target.Policies[key]
133+
if ok {
134+
return fmt.Errorf("Duplicate policy: %s", key)
135+
}
136+
target.Policies[key] = policy
137+
}
138+
139+
for key, group := range source.Groups {
140+
_, ok := target.Groups[key]
141+
if !ok {
142+
target.Groups[key] = cb.NewConfigGroup()
143+
}
144+
145+
err := copyGroup(group, target.Groups[key])
146+
if err != nil {
147+
return fmt.Errorf("Error copying group %s: %s", key, err)
148+
}
149+
}
150+
return nil
151+
}
152+
77153
// Items returns a set of ConfigEnvelopes for the given chainID, and errors only on marshaling errors
78154
func (ct *compositeTemplate) Envelope(chainID string) (*cb.ConfigEnvelope, error) {
79-
items := make([][]*cb.ConfigItem, len(ct.templates))
155+
channel := cb.NewConfigGroup()
156+
channel.Groups[ApplicationGroup] = cb.NewConfigGroup()
157+
channel.Groups[OrdererGroup] = cb.NewConfigGroup()
158+
80159
for i := range ct.templates {
81160
configEnv, err := ct.templates[i].Envelope(chainID)
82161
if err != nil {
83162
return nil, err
84163
}
85-
config, err := UnmarshalConfig(configEnv.Config)
164+
config, err := UnmarshalConfigNext(configEnv.Config)
165+
if err != nil {
166+
return nil, err
167+
}
168+
err = copyGroup(config.Channel, channel)
86169
if err != nil {
87170
return nil, err
88171
}
89-
items[i] = config.Items
90172
}
91173

92-
return NewSimpleTemplate(join(items...)...).Envelope(chainID)
174+
marshaledConfig, err := proto.Marshal(&cb.ConfigNext{
175+
Header: &cb.ChainHeader{
176+
ChainID: chainID,
177+
Type: int32(cb.HeaderType_CONFIGURATION_ITEM),
178+
},
179+
Channel: channel,
180+
})
181+
if err != nil {
182+
return nil, err
183+
}
184+
185+
return &cb.ConfigEnvelope{Config: marshaledConfig}, nil
93186
}
94187

95188
// NewChainCreationTemplate takes a CreationPolicy and a Template to produce a Template which outputs an appropriately

common/configtx/template_test.go

+44-20
Original file line numberDiff line numberDiff line change
@@ -32,37 +32,45 @@ func verifyItemsResult(t *testing.T, template Template, count int) {
3232
t.Fatalf("Should not have errored: %s", err)
3333
}
3434

35-
config, err := UnmarshalConfig(configEnv.Config)
35+
configNext, err := UnmarshalConfigNext(configEnv.Config)
3636
if err != nil {
3737
t.Fatalf("Should not have errored: %s", err)
3838
}
39+
config := ConfigNextToConfig(configNext)
3940

4041
if len(config.Items) != count {
4142
t.Errorf("Expected %d items, but got %d", count, len(config.Items))
4243
}
4344

44-
for i, item := range config.Items {
45-
expected := fmt.Sprintf("%d", i)
46-
assert.Equal(t, expected, string(item.Value), "Expected %s but got %s", expected, item.Value)
45+
for i, _ := range config.Items {
46+
count := 0
47+
for _, item := range config.Items {
48+
key := fmt.Sprintf("%d", i)
49+
if key == item.Key {
50+
count++
51+
}
52+
}
53+
expected := 1
54+
assert.Equal(t, expected, count, "Expected %d but got %d for %d", expected, count, i)
4755
}
4856
}
4957

5058
func TestSimpleTemplate(t *testing.T) {
5159
simple := NewSimpleTemplate(
52-
&cb.ConfigItem{Value: []byte("0")},
53-
&cb.ConfigItem{Value: []byte("1")},
60+
&cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "0"},
61+
&cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "1"},
5462
)
5563
verifyItemsResult(t, simple, 2)
5664
}
5765

5866
func TestCompositeTemplate(t *testing.T) {
5967
composite := NewCompositeTemplate(
6068
NewSimpleTemplate(
61-
&cb.ConfigItem{Value: []byte("0")},
62-
&cb.ConfigItem{Value: []byte("1")},
69+
&cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "0"},
70+
&cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "1"},
6371
),
6472
NewSimpleTemplate(
65-
&cb.ConfigItem{Value: []byte("2")},
73+
&cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "2"},
6674
),
6775
)
6876

@@ -71,8 +79,8 @@ func TestCompositeTemplate(t *testing.T) {
7179

7280
func TestNewChainTemplate(t *testing.T) {
7381
simple := NewSimpleTemplate(
74-
&cb.ConfigItem{Value: []byte("1")},
75-
&cb.ConfigItem{Value: []byte("2")},
82+
&cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "0"},
83+
&cb.ConfigItem{Type: cb.ConfigItem_Orderer, Key: "1"},
7684
)
7785

7886
creationPolicy := "Test"
@@ -84,24 +92,40 @@ func TestNewChainTemplate(t *testing.T) {
8492
t.Fatalf("Error creation a chain creation config")
8593
}
8694

87-
config, err := UnmarshalConfig(configEnv.Config)
95+
configNext, err := UnmarshalConfigNext(configEnv.Config)
8896
if err != nil {
8997
t.Fatalf("Should not have errored: %s", err)
9098
}
99+
config := ConfigNextToConfig(configNext)
91100

92101
if expected := 3; len(config.Items) != expected {
93102
t.Fatalf("Expected %d items, but got %d", expected, len(config.Items))
94103
}
95104

96-
for i, item := range config.Items {
97-
if i == 0 {
98-
if item.Key != CreationPolicyKey {
99-
t.Errorf("First item should have been the creation policy")
100-
}
101-
} else {
102-
if expected := fmt.Sprintf("%d", i); string(item.Value) != expected {
103-
t.Errorf("Expected %s but got %s", expected, item.Value)
105+
for i, _ := range config.Items {
106+
if i == len(config.Items)-1 {
107+
break
108+
}
109+
count := 0
110+
for _, item := range config.Items {
111+
key := fmt.Sprintf("%d", i)
112+
if key == item.Key {
113+
count++
104114
}
105115
}
116+
expected := 1
117+
assert.Equal(t, expected, count, "Expected %d but got %d for %d", expected, count, i)
118+
}
119+
120+
foundCreationPolicy := false
121+
for _, item := range config.Items {
122+
if item.Key == CreationPolicyKey {
123+
foundCreationPolicy = true
124+
continue
125+
}
126+
}
127+
128+
if !foundCreationPolicy {
129+
t.Errorf("Should have found the creation policy")
106130
}
107131
}

common/configtx/util.go

+70
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,75 @@ func UnmarshalConfig(data []byte) (*cb.Config, error) {
3535
return config, nil
3636
}
3737

38+
// UnmarshalConfigNext attempts to unmarshal bytes to a *cb.ConfigNext
39+
func UnmarshalConfigNext(data []byte) (*cb.ConfigNext, error) {
40+
config := &cb.ConfigNext{}
41+
err := proto.Unmarshal(data, config)
42+
if err != nil {
43+
return nil, err
44+
}
45+
return config, nil
46+
}
47+
48+
// ConfigNextToConfig is a XXX temporary method for use in the change series converting the configtx protos
49+
// so error handling and testing is omitted as it will be removed shortly
50+
func ConfigNextToConfig(config *cb.ConfigNext) *cb.Config {
51+
result := &cb.Config{
52+
Header: config.Header,
53+
}
54+
55+
channel := config.Channel
56+
57+
for key, value := range channel.Values {
58+
result.Items = append(result.Items, &cb.ConfigItem{
59+
Key: key,
60+
Type: cb.ConfigItem_Chain,
61+
Value: value.Value,
62+
})
63+
}
64+
65+
for key, value := range channel.Groups[OrdererGroup].Values {
66+
result.Items = append(result.Items, &cb.ConfigItem{
67+
Key: key,
68+
Type: cb.ConfigItem_Orderer,
69+
Value: value.Value,
70+
})
71+
}
72+
73+
for key, value := range channel.Groups[ApplicationGroup].Values {
74+
result.Items = append(result.Items, &cb.ConfigItem{
75+
Key: key,
76+
Type: cb.ConfigItem_Peer,
77+
Value: value.Value,
78+
})
79+
}
80+
81+
logger.Debugf("Processing polices %v", channel.Policies)
82+
for key, value := range channel.Policies {
83+
logger.Debugf("Reversing policy %s", key)
84+
result.Items = append(result.Items, &cb.ConfigItem{
85+
Key: key,
86+
Type: cb.ConfigItem_Policy,
87+
Value: utils.MarshalOrPanic(value.Policy),
88+
})
89+
}
90+
91+
// Note, for now, all MSPs are encoded in both ApplicationGroup and OrdererGroup, so we only need to pick one
92+
for key, group := range channel.Groups[ApplicationGroup].Groups {
93+
msp, ok := group.Values[MSPKey]
94+
if !ok {
95+
panic("Expected MSP defined")
96+
}
97+
result.Items = append(result.Items, &cb.ConfigItem{
98+
Key: key,
99+
Type: cb.ConfigItem_MSP,
100+
Value: msp.Value,
101+
})
102+
}
103+
104+
return result
105+
}
106+
38107
// UnmarshalConfigEnvelope attempts to unmarshal bytes to a *cb.ConfigEnvelope
39108
func UnmarshalConfigEnvelope(data []byte) (*cb.ConfigEnvelope, error) {
40109
configEnv := &cb.ConfigEnvelope{}
@@ -45,6 +114,7 @@ func UnmarshalConfigEnvelope(data []byte) (*cb.ConfigEnvelope, error) {
45114
return configEnv, nil
46115
}
47116

117+
// ConfigEnvelopeFromBlock extract the config envelope from a config block
48118
func ConfigEnvelopeFromBlock(block *cb.Block) (*cb.ConfigEnvelope, error) {
49119
if block.Data == nil || len(block.Data.Data) != 1 {
50120
return nil, fmt.Errorf("Not a config block, must contain exactly one tx")

core/peer/peer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error {
172172

173173
configtxInitializer := configtx.NewInitializer()
174174
configtxInitializer.Handlers()[common.ConfigItem_Peer] = sharedConfigHandler
175-
configtxManager, err := configtx.NewManagerImpl(
175+
configtxManager, err := configtx.NewManagerImplNext(
176176
configEnvelope,
177177
configtxInitializer,
178178
[]func(cm configtx.Manager){gossipCallbackWrapper},

orderer/multichain/manager.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func newConfigResources(configEnvelope *cb.ConfigEnvelope) (*configResources, er
151151
initializer := configtx.NewInitializer()
152152
initializer.Handlers()[cb.ConfigItem_Orderer] = sharedConfigManager
153153

154-
configManager, err := configtx.NewManagerImpl(configEnvelope, initializer, nil)
154+
configManager, err := configtx.NewManagerImplNext(configEnvelope, initializer, nil)
155155
if err != nil {
156156
return nil, fmt.Errorf("Error unpacking config transaction: %s", err)
157157
}

0 commit comments

Comments
 (0)