@@ -57,6 +57,7 @@ type configManager struct {
57
57
config map [string ]comparable
58
58
callOnUpdate []func (api.Manager )
59
59
initializer api.Initializer
60
+ configEnv * cb.ConfigEnvelope
60
61
}
61
62
62
63
func computeSequence (configGroup * cb.ConfigGroup ) uint64 {
@@ -158,8 +159,7 @@ func NewManagerImpl(configtx *cb.ConfigEnvelope, initializer api.Initializer, ca
158
159
callOnUpdate : callOnUpdate ,
159
160
}
160
161
161
- err = cm .Apply (configtx )
162
-
162
+ err = cm .Apply (configtx .LastUpdate )
163
163
if err != nil {
164
164
return nil , fmt .Errorf ("Error applying config transaction: %s" , err )
165
165
}
@@ -210,14 +210,16 @@ func (cm *configManager) proposeConfig(config map[string]comparable) error {
210
210
return nil
211
211
}
212
212
213
- func (cm * configManager ) processConfig (configtx * cb.ConfigEnvelope ) (map [string ]comparable , error ) {
213
+ // authorizeUpdate validates that all modified config has the corresponding modification policies satisfied by the signature set
214
+ // it returns a map of the modified config
215
+ func (cm * configManager ) authorizeUpdate (configUpdateEnv * cb.ConfigUpdateEnvelope ) (map [string ]comparable , error ) {
214
216
// XXX as a temporary hack to get the new protos working, we assume entire config is always in the ConfigUpdate.WriteSet
215
217
216
- if configtx . LastUpdate == nil {
217
- return nil , fmt .Errorf ("Must have ConfigEnvelope.LastUpdate set " )
218
+ if configUpdateEnv == nil {
219
+ return nil , fmt .Errorf ("Cannot process nil ConfigUpdateEnvelope " )
218
220
}
219
221
220
- config , err := UnmarshalConfigUpdate (configtx . LastUpdate .ConfigUpdate )
222
+ config , err := UnmarshalConfigUpdate (configUpdateEnv .ConfigUpdate )
221
223
if err != nil {
222
224
return nil , err
223
225
}
@@ -227,7 +229,7 @@ func (cm *configManager) processConfig(configtx *cb.ConfigEnvelope) (map[string]
227
229
return nil , err
228
230
}
229
231
230
- signedData , err := configtx . LastUpdate .AsSignedData ()
232
+ signedData , err := configUpdateEnv .AsSignedData ()
231
233
if err != nil {
232
234
return nil , err
233
235
}
@@ -253,14 +255,12 @@ func (cm *configManager) processConfig(configtx *cb.ConfigEnvelope) (map[string]
253
255
if err != nil {
254
256
return nil , err
255
257
}
256
- delete (configMap , "[Groups] /Channel" ) // XXX temporary hack to prevent evaluating groups for modification
257
-
258
- if err := cm .proposeConfig (configMap ); err != nil {
259
- return nil , err
260
- }
261
-
262
258
for key , value := range configMap {
263
259
logger .Debugf ("Processing key %s with value %v" , key , value )
260
+ if key == "[Groups] /Channel" {
261
+ // XXX temporary hack to prevent group evaluation for modification
262
+ continue
263
+ }
264
264
265
265
// Ensure the config sequence numbers are correct to prevent replay attacks
266
266
var isModified bool
@@ -309,20 +309,43 @@ func (cm *configManager) processConfig(configtx *cb.ConfigEnvelope) (map[string]
309
309
}
310
310
311
311
return configMap , nil
312
+ }
313
+
314
+ // computeUpdateResult takes a configMap generated by an update and produces a new configMap overlaying it onto the old config
315
+ func (cm * configManager ) computeUpdateResult (updatedConfig map [string ]comparable ) map [string ]comparable {
316
+ newConfigMap := make (map [string ]comparable )
317
+ for key , value := range cm .config {
318
+ newConfigMap [key ] = value
319
+ }
312
320
321
+ for key , value := range updatedConfig {
322
+ newConfigMap [key ] = value
323
+ }
324
+ return newConfigMap
313
325
}
314
326
315
- // Validate attempts to validate a new configtx against the current config state
316
- func (cm * configManager ) Validate (configtx * cb.ConfigEnvelope ) error {
327
+ func (cm * configManager ) processConfig (configtx * cb.ConfigUpdateEnvelope ) (map [string ]comparable , error ) {
317
328
cm .beginHandlers ()
329
+ configMap , err := cm .authorizeUpdate (configtx )
330
+ if err != nil {
331
+ return nil , err
332
+ }
333
+ computedResult := cm .computeUpdateResult (configMap )
334
+ if err := cm .proposeConfig (computedResult ); err != nil {
335
+ return nil , err
336
+ }
337
+ return computedResult , nil
338
+ }
339
+
340
+ // Validate attempts to validate a new configtx against the current config state
341
+ func (cm * configManager ) Validate (configtx * cb.ConfigUpdateEnvelope ) error {
318
342
_ , err := cm .processConfig (configtx )
319
343
cm .rollbackHandlers ()
320
344
return err
321
345
}
322
346
323
347
// Apply attempts to apply a configtx to become the new config
324
- func (cm * configManager ) Apply (configtx * cb.ConfigEnvelope ) error {
325
- cm .beginHandlers ()
348
+ func (cm * configManager ) Apply (configtx * cb.ConfigUpdateEnvelope ) error {
326
349
configMap , err := cm .processConfig (configtx )
327
350
if err != nil {
328
351
cm .rollbackHandlers ()
@@ -331,9 +354,26 @@ func (cm *configManager) Apply(configtx *cb.ConfigEnvelope) error {
331
354
cm .config = configMap
332
355
cm .sequence ++
333
356
cm .commitHandlers ()
357
+ channelGroup , err := configMapToConfig (configMap )
358
+ if err != nil {
359
+ logger .Panicf ("Config was validated and applied, but could not be transformed back into proto form: %s" , err )
360
+ }
361
+
362
+ cm .configEnv = & cb.ConfigEnvelope {
363
+ Config : & cb.Config {
364
+ // XXX add header
365
+ Channel : channelGroup ,
366
+ },
367
+ LastUpdate : configtx ,
368
+ }
334
369
return nil
335
370
}
336
371
372
+ // ConfigEnvelope retrieve the current ConfigEnvelope, generated after the last successfully applied configuration
373
+ func (cm * configManager ) ConfigEnvelope () * cb.ConfigEnvelope {
374
+ return cm .configEnv
375
+ }
376
+
337
377
// ChainID retrieves the chain ID associated with this manager
338
378
func (cm * configManager ) ChainID () string {
339
379
return cm .chainID
0 commit comments