Skip to content

Commit 975dc82

Browse files
author
Jason Yellick
committed
[FAB-3727] Orderer restart broken
There was a programming error introduced during the consortium refactoring which caused an interface return value to be checked for nil, which returns false even when the underlying value is nil because the dynamic type is a pointer kind. This error caused the orderer to recognize all channels as the system channel, and would cause a fatal error at startup. This changeset modifies the config interface to return a boolean along with the interface value, indicating whether the interface value was populated. Change-Id: Ia9bb89b765c7e8f35742895d2ac1dd2396d03908 Signed-off-by: Jason Yellick <[email protected]>
1 parent f533ae6 commit 975dc82

File tree

5 files changed

+40
-15
lines changed

5 files changed

+40
-15
lines changed

common/configtx/api/api.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ type Resources interface {
6262
OrdererConfig() config.Orderer
6363

6464
// ConsortiumsConfig() returns the config.Consortiums for the channel
65-
ConsortiumsConfig() config.Consortiums
65+
// and whether the consortiums config exists
66+
ConsortiumsConfig() (config.Consortiums, bool)
6667

6768
// ApplicationConfig returns the configtxapplication.SharedConfig for the channel
6869
ApplicationConfig() config.Application

common/configtx/initializer.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ func (r *resources) ApplicationConfig() config.Application {
5656
return r.configRoot.Application()
5757
}
5858

59-
// ConsortiumsConfig returns the api.ConsortiumsConfig for the chain
60-
func (r *resources) ConsortiumsConfig() config.Consortiums {
61-
return r.configRoot.Consortiums()
59+
// ConsortiumsConfig returns the api.ConsortiumsConfig for the chain and whether or not
60+
// this channel contains consortiums config
61+
func (r *resources) ConsortiumsConfig() (config.Consortiums, bool) {
62+
result := r.configRoot.Consortiums()
63+
if result == nil {
64+
return nil, false
65+
}
66+
67+
return result, true
6268
}
6369

6470
// MSPManager returns the msp.MSPManager for the chain

common/mocks/configtx/configtx.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ func (r *Resources) ApplicationConfig() config.Application {
6666
return r.ApplicationConfigVal
6767
}
6868

69-
func (r *Resources) ConsortiumsConfig() config.Consortiums {
70-
return r.ConsortiumsConfigVal
69+
func (r *Resources) ConsortiumsConfig() (config.Consortiums, bool) {
70+
return r.ConsortiumsConfigVal, r.ConsortiumsConfigVal != nil
7171
}
7272

7373
// Returns the MSPManagerVal

orderer/multichain/manager.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -100,18 +100,18 @@ func NewManagerImpl(ledgerFactory ledger.Factory, consenters map[string]Consente
100100
for _, chainID := range existingChains {
101101
rl, err := ledgerFactory.GetOrCreate(chainID)
102102
if err != nil {
103-
logger.Fatalf("Ledger factory reported chainID %s but could not retrieve it: %s", chainID, err)
103+
logger.Panicf("Ledger factory reported chainID %s but could not retrieve it: %s", chainID, err)
104104
}
105105
configTx := getConfigTx(rl)
106106
if configTx == nil {
107-
logger.Fatalf("Could not find config transaction for chain %s", chainID)
107+
logger.Panicf("Could not find config transaction for chain %s", chainID)
108108
}
109109
ledgerResources := ml.newLedgerResources(configTx)
110110
chainID := ledgerResources.ChainID()
111111

112-
if ledgerResources.ConsortiumsConfig() != nil {
112+
if _, ok := ledgerResources.ConsortiumsConfig(); ok {
113113
if ml.systemChannelID != "" {
114-
logger.Fatalf("There appear to be two system chains %s and %s", ml.systemChannelID, chainID)
114+
logger.Panicf("There appear to be two system chains %s and %s", ml.systemChannelID, chainID)
115115
}
116116
chain := newChainSupport(createSystemChainFilters(ml, ledgerResources),
117117
ledgerResources,
@@ -156,14 +156,14 @@ func (ml *multiLedger) newLedgerResources(configTx *cb.Envelope) *ledgerResource
156156
initializer := configtx.NewInitializer()
157157
configManager, err := configtx.NewManagerImpl(configTx, initializer, nil)
158158
if err != nil {
159-
logger.Fatalf("Error creating configtx manager and handlers: %s", err)
159+
logger.Panicf("Error creating configtx manager and handlers: %s", err)
160160
}
161161

162162
chainID := configManager.ChainID()
163163

164164
ledger, err := ml.ledgerFactory.GetOrCreate(chainID)
165165
if err != nil {
166-
logger.Fatalf("Error getting ledger for %s", chainID)
166+
logger.Panicf("Error getting ledger for %s", chainID)
167167
}
168168

169169
return &ledgerResources{
@@ -237,8 +237,8 @@ func (ml *multiLedger) NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxa
237237
}
238238

239239
applicationGroup := cb.NewConfigGroup()
240-
consortiumsConfig := ml.systemChannel.ConsortiumsConfig()
241-
if consortiumsConfig == nil {
240+
consortiumsConfig, ok := ml.systemChannel.ConsortiumsConfig()
241+
if !ok {
242242
return nil, fmt.Errorf("The ordering system channel does not appear to support creating channels")
243243
}
244244

orderer/multichain/manager_test.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func TestGetConfigTxFailure(t *testing.T) {
133133

134134
}
135135

136-
// This test essentially brings the entire system up and is ultimately what main.go will replicate
136+
// This test checks to make sure the orderer refuses to come up if it cannot find a system channel
137137
func TestNoSystemChain(t *testing.T) {
138138
defer func() {
139139
if recover() == nil {
@@ -149,6 +149,24 @@ func TestNoSystemChain(t *testing.T) {
149149
NewManagerImpl(lf, consenters, mockCrypto())
150150
}
151151

152+
// This test checks to make sure that the orderer refuses to come up if there are multiple system channels
153+
func TestMultiSystemChannel(t *testing.T) {
154+
lf := ramledger.New(10)
155+
156+
for _, id := range []string{"foo", "bar"} {
157+
rl, err := lf.GetOrCreate(id)
158+
assert.NoError(t, err)
159+
160+
err = rl.Append(provisional.New(conf).GenesisBlockForChannel(id))
161+
assert.NoError(t, err)
162+
}
163+
164+
consenters := make(map[string]Consenter)
165+
consenters[conf.Orderer.OrdererType] = &mockConsenter{}
166+
167+
assert.Panics(t, func() { NewManagerImpl(lf, consenters, mockCrypto()) }, "Two system channels should have caused panic")
168+
}
169+
152170
// This test essentially brings the entire system up and is ultimately what main.go will replicate
153171
func TestManagerImpl(t *testing.T) {
154172
lf, rl := NewRAMLedgerAndFactory(10)

0 commit comments

Comments
 (0)