Skip to content

Commit b225806

Browse files
author
Jason Yellick
committed
[FAB-1856] Add configtx callback events
https://jira.hyperledger.org/browse/FAB-1856 The gossip team requires a way to be notified when the channel configuration changes. This changeset allows the configtx manager to be constructed with a slice of functions to call when a new configuration is committed. Change-Id: Ib318e271b7c00685117d10d0982ccc8a09a9801e Signed-off-by: Jason Yellick <[email protected]>
1 parent 9f07b96 commit b225806

File tree

5 files changed

+47
-22
lines changed

5 files changed

+47
-22
lines changed

common/configtx/manager.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ type configurationManager struct {
7676
sequence uint64
7777
chainID string
7878
configuration map[cb.ConfigurationItem_ConfigurationType]map[string]*cb.ConfigurationItem
79+
callOnUpdate []func(Manager)
7980
}
8081

8182
// computeChainIDAndSequence returns the chain id and the sequence number for a configuration envelope
@@ -119,8 +120,9 @@ func computeChainIDAndSequence(configtx *cb.ConfigurationEnvelope) (string, uint
119120
return chainID, m, nil
120121
}
121122

122-
// NewManagerImpl creates a new Manager unless an error is encountered
123-
func NewManagerImpl(configtx *cb.ConfigurationEnvelope, initializer Initializer) (Manager, error) {
123+
// NewManagerImpl creates a new Manager unless an error is encountered, each element of the callOnUpdate slice
124+
// is invoked when a new configuration is committed
125+
func NewManagerImpl(configtx *cb.ConfigurationEnvelope, initializer Initializer, callOnUpdate []func(Manager)) (Manager, error) {
124126
for ctype := range cb.ConfigurationItem_ConfigurationType_name {
125127
if _, ok := initializer.Handlers()[cb.ConfigurationItem_ConfigurationType(ctype)]; !ok {
126128
return nil, errors.New("Must supply a handler for all known types")
@@ -137,6 +139,7 @@ func NewManagerImpl(configtx *cb.ConfigurationEnvelope, initializer Initializer)
137139
sequence: seq - 1,
138140
chainID: chainID,
139141
configuration: makeConfigMap(),
142+
callOnUpdate: callOnUpdate,
140143
}
141144

142145
err = cm.Apply(configtx)
@@ -175,6 +178,9 @@ func (cm *configurationManager) commitHandlers() {
175178
for ctype := range cb.ConfigurationItem_ConfigurationType_name {
176179
cm.Initializer.Handlers()[cb.ConfigurationItem_ConfigurationType(ctype)].CommitConfig()
177180
}
181+
for _, callback := range cm.callOnUpdate {
182+
callback(cm)
183+
}
178184
}
179185

180186
func (cm *configurationManager) processConfig(configtx *cb.ConfigurationEnvelope) (configMap map[cb.ConfigurationItem_ConfigurationType]map[string]*cb.ConfigurationItem, err error) {

common/configtx/manager_test.go

+36-17
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,37 @@ func makeSignedConfigurationItem(id, modificationPolicy string, lastModified uin
9292
func TestOmittedHandler(t *testing.T) {
9393
_, err := NewManagerImpl(&cb.ConfigurationEnvelope{
9494
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
95-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: map[cb.ConfigurationItem_ConfigurationType]Handler{}})
95+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: map[cb.ConfigurationItem_ConfigurationType]Handler{}}, nil)
9696

9797
if err == nil {
9898
t.Fatal("Should have failed to construct manager because handlers were missing")
9999
}
100100
}
101101

102+
func TestCallback(t *testing.T) {
103+
var calledBack Manager
104+
callback := func(m Manager) {
105+
calledBack = m
106+
}
107+
108+
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
109+
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
110+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, []func(Manager){callback})
111+
112+
if err != nil {
113+
t.Fatalf("Error constructing configuration manager: %s", err)
114+
}
115+
116+
if calledBack != cm {
117+
t.Fatalf("Should have called back with the correct manager")
118+
}
119+
}
120+
102121
// TestWrongChainID tests that a configuration update for a different chain ID fails
103122
func TestWrongChainID(t *testing.T) {
104123
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
105124
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
106-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
125+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
107126

108127
if err != nil {
109128
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -128,7 +147,7 @@ func TestWrongChainID(t *testing.T) {
128147
func TestOldConfigReplay(t *testing.T) {
129148
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
130149
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
131-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
150+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
132151

133152
if err != nil {
134153
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -155,7 +174,7 @@ func TestInvalidInitialConfigByStructure(t *testing.T) {
155174
entries[0].ConfigurationItem = []byte("Corrupted")
156175
_, err := NewManagerImpl(&cb.ConfigurationEnvelope{
157176
Items: entries,
158-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
177+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
159178

160179
if err == nil {
161180
t.Fatal("Should have failed to construct configuration by policy")
@@ -166,7 +185,7 @@ func TestInvalidInitialConfigByStructure(t *testing.T) {
166185
func TestValidConfigChange(t *testing.T) {
167186
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
168187
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
169-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
188+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
170189

171190
if err != nil {
172191
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -192,7 +211,7 @@ func TestValidConfigChange(t *testing.T) {
192211
func TestConfigChangeRegressedSequence(t *testing.T) {
193212
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
194213
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 1, []byte("foo"), defaultChain)},
195-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
214+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
196215

197216
if err != nil {
198217
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -221,7 +240,7 @@ func TestConfigChangeRegressedSequence(t *testing.T) {
221240
func TestConfigChangeOldSequence(t *testing.T) {
222241
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
223242
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 1, []byte("foo"), defaultChain)},
224-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
243+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
225244

226245
if err != nil {
227246
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -253,7 +272,7 @@ func TestConfigImplicitDelete(t *testing.T) {
253272
makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain),
254273
makeSignedConfigurationItem("bar", "bar", 0, []byte("bar"), defaultChain),
255274
},
256-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
275+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
257276

258277
if err != nil {
259278
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -280,7 +299,7 @@ func TestConfigImplicitDelete(t *testing.T) {
280299
func TestEmptyConfigUpdate(t *testing.T) {
281300
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
282301
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
283-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
302+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
284303

285304
if err != nil {
286305
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -308,7 +327,7 @@ func TestSilentConfigModification(t *testing.T) {
308327
makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain),
309328
makeSignedConfigurationItem("bar", "bar", 0, []byte("bar"), defaultChain),
310329
},
311-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()})
330+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: defaultHandlers()}, nil)
312331

313332
if err != nil {
314333
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -337,7 +356,7 @@ func TestSilentConfigModification(t *testing.T) {
337356
func TestInvalidInitialConfigByPolicy(t *testing.T) {
338357
_, err := NewManagerImpl(&cb.ConfigurationEnvelope{
339358
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
340-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{policyResult: fmt.Errorf("err")}}, HandlersVal: defaultHandlers()})
359+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{policyResult: fmt.Errorf("err")}}, HandlersVal: defaultHandlers()}, nil)
341360

342361
if err == nil {
343362
t.Fatal("Should have failed to construct configuration by policy")
@@ -350,7 +369,7 @@ func TestConfigChangeViolatesPolicy(t *testing.T) {
350369
mpm := &mockPolicyManager{}
351370
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
352371
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
353-
}, &mockconfigtx.Initializer{PolicyManagerVal: mpm, HandlersVal: defaultHandlers()})
372+
}, &mockconfigtx.Initializer{PolicyManagerVal: mpm, HandlersVal: defaultHandlers()}, nil)
354373

355374
if err != nil {
356375
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -379,7 +398,7 @@ func TestUnchangedConfigViolatesPolicy(t *testing.T) {
379398
mpm := &mockPolicyManager{}
380399
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
381400
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
382-
}, &mockconfigtx.Initializer{PolicyManagerVal: mpm, HandlersVal: defaultHandlers()})
401+
}, &mockconfigtx.Initializer{PolicyManagerVal: mpm, HandlersVal: defaultHandlers()}, nil)
383402

384403
if err != nil {
385404
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -424,7 +443,7 @@ func TestInvalidProposal(t *testing.T) {
424443
initializer := &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: handlers}
425444
cm, err := NewManagerImpl(&cb.ConfigurationEnvelope{
426445
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), defaultChain)},
427-
}, initializer)
446+
}, initializer, nil)
428447

429448
if err != nil {
430449
t.Fatalf("Error constructing configuration manager: %s", err)
@@ -455,7 +474,7 @@ func TestMissingHeader(t *testing.T) {
455474
data, _ := proto.Marshal(configItem)
456475
_, err := NewManagerImpl(&cb.ConfigurationEnvelope{
457476
Items: []*cb.SignedConfigurationItem{&cb.SignedConfigurationItem{ConfigurationItem: data}},
458-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: handlers})
477+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: handlers}, nil)
459478

460479
if err == nil {
461480
t.Error("Should have errored creating the configuration manager because of the missing header")
@@ -467,7 +486,7 @@ func TestMissingChainID(t *testing.T) {
467486
handlers := defaultHandlers()
468487
_, err := NewManagerImpl(&cb.ConfigurationEnvelope{
469488
Items: []*cb.SignedConfigurationItem{makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), "")},
470-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: handlers})
489+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: handlers}, nil)
471490

472491
if err == nil {
473492
t.Error("Should have errored creating the configuration manager because of the missing header")
@@ -482,7 +501,7 @@ func TestMismatchedChainID(t *testing.T) {
482501
makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), "chain1"),
483502
makeSignedConfigurationItem("foo", "foo", 0, []byte("foo"), "chain2"),
484503
},
485-
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: handlers})
504+
}, &mockconfigtx.Initializer{PolicyManagerVal: &mockPolicyManager{&mockPolicy{}}, HandlersVal: handlers}, nil)
486505

487506
if err == nil {
488507
t.Error("Should have errored creating the configuration manager because of the missing header")

common/configtx/template.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func MakeChainCreationTransaction(creationPolicy string, chainID string, signer
162162
return nil, err
163163
}
164164

165-
manager, err := NewManagerImpl(&cb.ConfigurationEnvelope{Items: items}, NewInitializer())
165+
manager, err := NewManagerImpl(&cb.ConfigurationEnvelope{Items: items}, NewInitializer(), nil)
166166

167167
newChainTemplate := NewChainCreationTemplate(creationPolicy, manager.ChainConfig().HashingAlgorithm(), composite)
168168
signedConfigItems, err := newChainTemplate.Items(chainID)

core/peer/peer.go

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

166166
configtxInitializer := configtx.NewInitializer()
167167
configtxInitializer.Handlers()[common.ConfigurationItem_Peer] = sharedConfigHandler
168-
configtxManager, err := configtx.NewManagerImpl(configEnvelope, configtxInitializer)
168+
configtxManager, err := configtx.NewManagerImpl(configEnvelope, configtxInitializer, nil)
169169
if err != nil {
170170
return err
171171
}

orderer/multichain/manager.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func newConfigResources(configEnvelope *cb.ConfigurationEnvelope) (*configResour
167167
initializer := configtx.NewInitializer()
168168
initializer.Handlers()[cb.ConfigurationItem_Orderer] = sharedConfigManager
169169

170-
configManager, err := configtx.NewManagerImpl(configEnvelope, initializer)
170+
configManager, err := configtx.NewManagerImpl(configEnvelope, initializer, nil)
171171
if err != nil {
172172
return nil, fmt.Errorf("Error unpacking configuration transaction: %s", err)
173173
}

0 commit comments

Comments
 (0)