Skip to content

Commit 26dcef1

Browse files
author
Jason Yellick
committed
[FAB-2202] Initialize configtx.Manager from Config
https://jira.hyperledger.org/browse/FAB-2202 As a transitional mechanism, the config currently depends on the WriteSet containing the entire configuration. Instead, the config as written in the config envelope needs to be utilized. This CR makes the configtx.Manager utilize the config envelope at instantiation time, but the orderer multichannel support still needs to be updated to generate the config envelope based on a WriteSet for instantiation. Change-Id: I35c069cfd1ca523fe6c80f6acccfabb0e5ed8ad0 Signed-off-by: Jason Yellick <[email protected]>
1 parent cf887e5 commit 26dcef1

File tree

5 files changed

+121
-136
lines changed

5 files changed

+121
-136
lines changed

common/configtx/manager.go

+35-62
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package configtx
1818

1919
import (
20-
"errors"
2120
"fmt"
2221
"regexp"
2322

@@ -77,32 +76,6 @@ func computeSequence(configGroup *cb.ConfigGroup) uint64 {
7776
return max
7877
}
7978

80-
// computeChannelIdAndSequence returns the chain id and the sequence number for a config envelope
81-
// or an error if there is a problem with the config envelope
82-
func computeChannelIdAndSequence(config *cb.ConfigUpdate) (string, uint64, error) {
83-
if config.WriteSet == nil {
84-
return "", 0, errors.New("Empty envelope unsupported")
85-
}
86-
87-
if config.Header == nil {
88-
return "", 0, fmt.Errorf("Header not set")
89-
}
90-
91-
if config.Header.ChannelId == "" {
92-
return "", 0, fmt.Errorf("Header chainID was not set")
93-
}
94-
95-
chainID := config.Header.ChannelId
96-
97-
if err := validateChainID(chainID); err != nil {
98-
return "", 0, err
99-
}
100-
101-
m := computeSequence(config.WriteSet)
102-
103-
return chainID, m, nil
104-
}
105-
10679
// validateChainID makes sure that proposed chain IDs (i.e. channel names)
10780
// comply with the following restrictions:
10881
// 1. Contain only ASCII alphanumerics, dots '.', dashes '-'
@@ -133,36 +106,43 @@ func validateChainID(chainID string) error {
133106
return nil
134107
}
135108

136-
func NewManagerImpl(configtx *cb.ConfigEnvelope, initializer api.Initializer, callOnUpdate []func(api.Manager)) (api.Manager, error) {
137-
// XXX as a temporary hack to get the new protos working, we assume entire config is always in the ConfigUpdate.WriteSet
109+
func NewManagerImpl(configEnv *cb.ConfigEnvelope, initializer api.Initializer, callOnUpdate []func(api.Manager)) (api.Manager, error) {
110+
if configEnv == nil {
111+
return nil, fmt.Errorf("Nil config envelope")
112+
}
138113

139-
if configtx.LastUpdate == nil {
140-
return nil, fmt.Errorf("Must have ConfigEnvelope.LastUpdate set")
114+
if configEnv.Config == nil {
115+
return nil, fmt.Errorf("Nil config envelope Config")
141116
}
142117

143-
config, err := UnmarshalConfigUpdate(configtx.LastUpdate.ConfigUpdate)
144-
if err != nil {
145-
return nil, err
118+
if configEnv.Config.Header == nil {
119+
return nil, fmt.Errorf("Nil config envelop Config Header")
146120
}
147121

148-
chainID, seq, err := computeChannelIdAndSequence(config)
122+
if err := validateChainID(configEnv.Config.Header.ChannelId); err != nil {
123+
return nil, fmt.Errorf("Bad channel id: %s", err)
124+
}
125+
126+
configMap, err := mapConfig(configEnv.Config.Channel)
149127
if err != nil {
150-
return nil, fmt.Errorf("Error computing chain ID and sequence: %s", err)
128+
return nil, fmt.Errorf("Error converting config to map: %s", err)
151129
}
152130

153131
cm := &configManager{
154132
Resources: initializer,
155133
initializer: initializer,
156-
sequence: seq - 1,
157-
chainID: chainID,
158-
config: make(map[string]comparable),
134+
sequence: computeSequence(configEnv.Config.Channel),
135+
chainID: configEnv.Config.Header.ChannelId,
136+
config: configMap,
159137
callOnUpdate: callOnUpdate,
160138
}
161139

162-
err = cm.Apply(configtx.LastUpdate)
163-
if err != nil {
164-
return nil, fmt.Errorf("Error applying config transaction: %s", err)
140+
cm.beginHandlers()
141+
if err := cm.proposeConfig(configMap); err != nil {
142+
cm.rollbackHandlers()
143+
return nil, err
165144
}
145+
cm.commitHandlers()
166146

167147
return cm, nil
168148
}
@@ -213,8 +193,6 @@ func (cm *configManager) proposeConfig(config map[string]comparable) error {
213193
// authorizeUpdate validates that all modified config has the corresponding modification policies satisfied by the signature set
214194
// it returns a map of the modified config
215195
func (cm *configManager) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelope) (map[string]comparable, error) {
216-
// XXX as a temporary hack to get the new protos working, we assume entire config is always in the ConfigUpdate.WriteSet
217-
218196
if configUpdateEnv == nil {
219197
return nil, fmt.Errorf("Cannot process nil ConfigUpdateEnvelope")
220198
}
@@ -224,7 +202,11 @@ func (cm *configManager) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelop
224202
return nil, err
225203
}
226204

227-
chainID, seq, err := computeChannelIdAndSequence(config)
205+
if config.Header == nil {
206+
return nil, fmt.Errorf("Must have header set")
207+
}
208+
209+
seq := computeSequence(config.WriteSet)
228210
if err != nil {
229211
return nil, err
230212
}
@@ -240,15 +222,8 @@ func (cm *configManager) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelop
240222
}
241223

242224
// Verify config is intended for this globally unique chain ID
243-
if chainID != cm.chainID {
244-
return nil, fmt.Errorf("Config is for the wrong chain, expected %s, got %s", cm.chainID, chainID)
245-
}
246-
247-
defaultModificationPolicy, defaultPolicySet := cm.PolicyManager().GetPolicy(NewConfigItemPolicyKey)
248-
249-
// If the default modification policy is not set, it indicates this is an uninitialized chain, so be permissive of modification
250-
if !defaultPolicySet {
251-
defaultModificationPolicy = &acceptAllPolicy{}
225+
if config.Header.ChannelId != cm.chainID {
226+
return nil, fmt.Errorf("Config is for the wrong chain, expected %s, got %s", cm.chainID, config.Header.ChannelId)
252227
}
253228

254229
configMap, err := mapConfig(config.WriteSet)
@@ -277,25 +252,23 @@ func (cm *configManager) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelop
277252

278253
// If a config item was modified, its Version must be set correctly, and it must satisfy the modification policy
279254
if isModified {
280-
logger.Debugf("Proposed config item %s on channel %s has been modified", key, chainID)
255+
logger.Debugf("Proposed config item %s on channel %s has been modified", key, cm.chainID)
281256

282257
if value.version() != seq {
283258
return nil, fmt.Errorf("Key %s was modified, but its Version %d does not equal current configtx Sequence %d", key, value.version(), seq)
284259
}
285260

286261
// Get the modification policy for this config item if one was previously specified
287-
// or the default if this is a new config item
262+
// or accept it if it is new, as the group policy will be evaluated for its inclusion
288263
var policy policies.Policy
289264
if ok {
290265
policy, _ = cm.PolicyManager().GetPolicy(oldValue.modPolicy())
291-
} else {
292-
policy = defaultModificationPolicy
266+
// Ensure the policy is satisfied
267+
if err = policy.Evaluate(signedData); err != nil {
268+
return nil, err
269+
}
293270
}
294271

295-
// Ensure the policy is satisfied
296-
if err = policy.Evaluate(signedData); err != nil {
297-
return nil, err
298-
}
299272
}
300273
}
301274

0 commit comments

Comments
 (0)