@@ -21,9 +21,7 @@ import (
21
21
"regexp"
22
22
23
23
"github.com/hyperledger/fabric/common/configtx/api"
24
- "github.com/hyperledger/fabric/common/policies"
25
24
cb "github.com/hyperledger/fabric/protos/common"
26
- "github.com/hyperledger/fabric/protos/utils"
27
25
28
26
logging "github.com/op/go-logging"
29
27
)
43
41
// NewConfigItemPolicyKey is the ID of the policy used when no other policy can be resolved, for instance when attempting to create a new config item
44
42
const NewConfigItemPolicyKey = "NewConfigItemPolicy"
45
43
46
- type configResult struct {
47
- handler api.Transactional
48
- subResults []* configResult
49
- }
50
-
51
- func (cr * configResult ) commit () {
52
- for _ , subResult := range cr .subResults {
53
- subResult .commit ()
54
- }
55
- cr .handler .CommitConfig ()
56
- }
57
-
58
- func (cr * configResult ) rollback () {
59
- for _ , subResult := range cr .subResults {
60
- subResult .rollback ()
61
- }
62
- cr .handler .RollbackConfig ()
63
- }
64
-
65
44
type configManager struct {
66
45
api.Resources
67
46
sequence uint64
@@ -166,213 +145,6 @@ func (cm *configManager) commitCallbacks() {
166
145
}
167
146
}
168
147
169
- // proposeGroup proposes a group configuration with a given handler
170
- // it will in turn recursively call itself until all groups have been exhausted
171
- // at each call, it returns the handler that was passed in, plus any handlers returned
172
- // by recursive calls into proposeGroup
173
- func (cm * configManager ) proposeGroup (name string , group * cb.ConfigGroup , handler api.Handler ) (* configResult , error ) {
174
- subGroups := make ([]string , len (group .Groups ))
175
- i := 0
176
- for subGroup := range group .Groups {
177
- subGroups [i ] = subGroup
178
- i ++
179
- }
180
-
181
- logger .Debugf ("Beginning new config for channel %s and group %s" , cm .chainID , name )
182
- subHandlers , err := handler .BeginConfig (subGroups )
183
- if err != nil {
184
- return nil , err
185
- }
186
-
187
- if len (subHandlers ) != len (subGroups ) {
188
- return nil , fmt .Errorf ("Programming error, did not return as many handlers as groups %d vs %d" , len (subHandlers ), len (subGroups ))
189
- }
190
-
191
- result := & configResult {
192
- handler : handler ,
193
- subResults : make ([]* configResult , 0 , len (subGroups )),
194
- }
195
-
196
- for i , subGroup := range subGroups {
197
- subResult , err := cm .proposeGroup (name + "/" + subGroup , group .Groups [subGroup ], subHandlers [i ])
198
- if err != nil {
199
- result .rollback ()
200
- return nil , err
201
- }
202
- result .subResults = append (result .subResults , subResult )
203
- }
204
-
205
- for key , value := range group .Values {
206
- if err := handler .ProposeConfig (key , value ); err != nil {
207
- result .rollback ()
208
- return nil , err
209
- }
210
- }
211
-
212
- return result , nil
213
- }
214
-
215
- func (cm * configManager ) proposePolicies (rootGroup * cb.ConfigGroup ) (* configResult , error ) {
216
- cm .initializer .PolicyHandler ().BeginConfig (nil ) // XXX temporary workaround until policy manager is adapted with sub-policies
217
-
218
- for key , policy := range rootGroup .Policies {
219
- logger .Debugf ("Proposing policy: %s" , key )
220
- if err := cm .initializer .PolicyHandler ().ProposePolicy (key , []string {RootGroupKey }, policy ); err != nil {
221
- cm .initializer .PolicyHandler ().RollbackConfig ()
222
- return nil , err
223
- }
224
- }
225
-
226
- return & configResult {handler : cm .initializer .PolicyHandler ()}, nil
227
- }
228
-
229
- // authorizeUpdate validates that all modified config has the corresponding modification policies satisfied by the signature set
230
- // it returns a map of the modified config
231
- func (cm * configManager ) authorizeUpdate (configUpdateEnv * cb.ConfigUpdateEnvelope ) (map [string ]comparable , error ) {
232
- if configUpdateEnv == nil {
233
- return nil , fmt .Errorf ("Cannot process nil ConfigUpdateEnvelope" )
234
- }
235
-
236
- config , err := UnmarshalConfigUpdate (configUpdateEnv .ConfigUpdate )
237
- if err != nil {
238
- return nil , err
239
- }
240
-
241
- if config .Header == nil {
242
- return nil , fmt .Errorf ("Must have header set" )
243
- }
244
-
245
- seq := computeSequence (config .WriteSet )
246
- if err != nil {
247
- return nil , err
248
- }
249
-
250
- signedData , err := configUpdateEnv .AsSignedData ()
251
- if err != nil {
252
- return nil , err
253
- }
254
-
255
- // Verify config is a sequential update to prevent exhausting sequence numbers
256
- if seq != cm .sequence + 1 {
257
- return nil , fmt .Errorf ("Config sequence number jumped from %d to %d" , cm .sequence , seq )
258
- }
259
-
260
- // Verify config is intended for this globally unique chain ID
261
- if config .Header .ChannelId != cm .chainID {
262
- return nil , fmt .Errorf ("Config is for the wrong chain, expected %s, got %s" , cm .chainID , config .Header .ChannelId )
263
- }
264
-
265
- configMap , err := mapConfig (config .WriteSet )
266
- if err != nil {
267
- return nil , err
268
- }
269
- for key , value := range configMap {
270
- logger .Debugf ("Processing key %s with value %v" , key , value )
271
- if key == "[Groups] /Channel" {
272
- // XXX temporary hack to prevent group evaluation for modification
273
- continue
274
- }
275
-
276
- // Ensure the config sequence numbers are correct to prevent replay attacks
277
- var isModified bool
278
-
279
- oldValue , ok := cm .config [key ]
280
- if ok {
281
- isModified = ! value .equals (oldValue )
282
- } else {
283
- if value .version () != seq {
284
- return nil , fmt .Errorf ("Key %v was new, but had an older Sequence %d set" , key , value .version ())
285
- }
286
- isModified = true
287
- }
288
-
289
- // If a config item was modified, its Version must be set correctly, and it must satisfy the modification policy
290
- if isModified {
291
- logger .Debugf ("Proposed config item %s on channel %s has been modified" , key , cm .chainID )
292
-
293
- if value .version () != seq {
294
- return nil , fmt .Errorf ("Key %s was modified, but its Version %d does not equal current configtx Sequence %d" , key , value .version (), seq )
295
- }
296
-
297
- // Get the modification policy for this config item if one was previously specified
298
- // or accept it if it is new, as the group policy will be evaluated for its inclusion
299
- var policy policies.Policy
300
- if ok {
301
- policy , _ = cm .PolicyManager ().GetPolicy (oldValue .modPolicy ())
302
- // Ensure the policy is satisfied
303
- if err = policy .Evaluate (signedData ); err != nil {
304
- return nil , err
305
- }
306
- }
307
-
308
- }
309
- }
310
-
311
- // Ensure that any config items which used to exist still exist, to prevent implicit deletion
312
- for key , _ := range cm .config {
313
- _ , ok := configMap [key ]
314
- if ! ok {
315
- return nil , fmt .Errorf ("Missing key %v in new config" , key )
316
- }
317
-
318
- }
319
-
320
- return cm .computeUpdateResult (configMap ), nil
321
- }
322
-
323
- // computeUpdateResult takes a configMap generated by an update and produces a new configMap overlaying it onto the old config
324
- func (cm * configManager ) computeUpdateResult (updatedConfig map [string ]comparable ) map [string ]comparable {
325
- newConfigMap := make (map [string ]comparable )
326
- for key , value := range cm .config {
327
- newConfigMap [key ] = value
328
- }
329
-
330
- for key , value := range updatedConfig {
331
- newConfigMap [key ] = value
332
- }
333
- return newConfigMap
334
- }
335
-
336
- func (cm * configManager ) processConfig (channelGroup * cb.ConfigGroup ) (* configResult , error ) {
337
- helperGroup := cb .NewConfigGroup ()
338
- helperGroup .Groups [RootGroupKey ] = channelGroup
339
- groupResult , err := cm .proposeGroup ("" , helperGroup , cm .initializer )
340
- if err != nil {
341
- return nil , err
342
- }
343
-
344
- policyResult , err := cm .proposePolicies (channelGroup )
345
- if err != nil {
346
- groupResult .rollback ()
347
- return nil , err
348
- }
349
- policyResult .subResults = []* configResult {groupResult }
350
-
351
- return policyResult , nil
352
- }
353
-
354
- func envelopeToConfigUpdate (configtx * cb.Envelope ) (* cb.ConfigUpdateEnvelope , error ) {
355
- payload , err := utils .UnmarshalPayload (configtx .Payload )
356
- if err != nil {
357
- return nil , err
358
- }
359
-
360
- if payload .Header == nil || payload .Header .ChannelHeader == nil {
361
- return nil , fmt .Errorf ("Envelope must have ChannelHeader" )
362
- }
363
-
364
- if payload .Header == nil || payload .Header .ChannelHeader .Type != int32 (cb .HeaderType_CONFIG_UPDATE ) {
365
- return nil , fmt .Errorf ("Not a tx of type CONFIG_UPDATE" )
366
- }
367
-
368
- configUpdateEnv , err := UnmarshalConfigUpdateEnvelope (payload .Data )
369
- if err != nil {
370
- return nil , fmt .Errorf ("Error unmarshaling ConfigUpdateEnvelope: %s" , err )
371
- }
372
-
373
- return configUpdateEnv , nil
374
- }
375
-
376
148
// Validate attempts to validate a new configtx against the current config state
377
149
func (cm * configManager ) Validate (configtx * cb.Envelope ) error {
378
150
configUpdateEnv , err := envelopeToConfigUpdate (configtx )
0 commit comments