@@ -17,7 +17,7 @@ limitations under the License.
17
17
package multichain
18
18
19
19
import (
20
- "sync "
20
+ "fmt "
21
21
22
22
"github.com/hyperledger/fabric/orderer/common/configtx"
23
23
"github.com/hyperledger/fabric/orderer/common/policies"
@@ -48,13 +48,18 @@ func init() {
48
48
type Manager interface {
49
49
// GetChain retrieves the chain support for a chain (and whether it exists)
50
50
GetChain (chainID string ) (ChainSupport , bool )
51
+
52
+ // ProposeChain accepts a configuration transaction for a chain which does not already exists
53
+ // The status returned is whether the proposal is accepted for consideration, only after consensus
54
+ // occurs will the proposal be committed or rejected
55
+ ProposeChain (env * cb.Envelope ) cb.Status
51
56
}
52
57
53
58
type multiLedger struct {
54
59
chains map [string ]* chainSupport
55
60
consenters map [string ]Consenter
56
61
ledgerFactory rawledger.Factory
57
- mutex sync. Mutex
62
+ sysChain * systemChain
58
63
}
59
64
60
65
// getConfigTx, this should ultimately be done more intelligently, but for now, we search the whole chain for txs and pick the last config one
@@ -104,6 +109,7 @@ func NewManagerImpl(ledgerFactory rawledger.Factory, consenters map[string]Conse
104
109
ml := & multiLedger {
105
110
chains : make (map [string ]* chainSupport ),
106
111
ledgerFactory : ledgerFactory ,
112
+ consenters : consenters ,
107
113
}
108
114
109
115
existingChains := ledgerFactory .ChainIDs ()
@@ -118,23 +124,43 @@ func NewManagerImpl(ledgerFactory rawledger.Factory, consenters map[string]Conse
118
124
}
119
125
configManager , policyManager , backingLedger , sharedConfigManager := ml .newResources (configTx )
120
126
chainID := configManager .ChainID ()
121
- ml .chains [chainID ] = newChainSupport (configManager , policyManager , backingLedger , sharedConfigManager , consenters )
122
- }
123
127
124
- for _ , cs := range ml .chains {
125
- cs .start ()
128
+ if sharedConfigManager .ChainCreators () != nil {
129
+ if ml .sysChain != nil {
130
+ logger .Fatalf ("There appear to be two system chains %x and %x" , ml .sysChain .support .ChainID (), chainID )
131
+ }
132
+ logger .Debugf ("Starting with system chain: %x" , chainID )
133
+ chain := newChainSupport (createSystemChainFilters (ml , configManager ), configManager , policyManager , backingLedger , sharedConfigManager , consenters )
134
+ ml .chains [string (chainID )] = chain
135
+ ml .sysChain = newSystemChain (chain )
136
+ // We delay starting this chain, as it might try to copy and replace the chains map via newChain before the map is fully built
137
+ defer chain .start ()
138
+ } else {
139
+ logger .Debugf ("Starting chain: %x" , chainID )
140
+ chain := newChainSupport (createStandardFilters (configManager ), configManager , policyManager , backingLedger , sharedConfigManager , consenters )
141
+ ml .chains [string (chainID )] = chain
142
+ chain .start ()
143
+ }
144
+
126
145
}
127
146
128
147
return ml
129
148
}
130
149
150
+ // ProposeChain accepts a configuration transaction for a chain which does not already exists
151
+ // The status returned is whether the proposal is accepted for consideration, only after consensus
152
+ // occurs will the proposal be committed or rejected
153
+ func (ml * multiLedger ) ProposeChain (env * cb.Envelope ) cb.Status {
154
+ return ml .sysChain .proposeChain (env )
155
+ }
156
+
131
157
// GetChain retrieves the chain support for a chain (and whether it exists)
132
158
func (ml * multiLedger ) GetChain (chainID string ) (ChainSupport , bool ) {
133
159
cs , ok := ml .chains [chainID ]
134
160
return cs , ok
135
161
}
136
162
137
- func ( ml * multiLedger ) newResources ( configTx * cb.Envelope ) (configtx.Manager , policies.Manager , rawledger. ReadWriter , sharedconfig.Manager ) {
163
+ func newConfigTxManagerAndHandlers ( configEnvelope * cb.ConfigurationEnvelope ) (configtx.Manager , policies.Manager , sharedconfig.Manager , error ) {
138
164
policyManager := policies .NewManagerImpl (xxxCryptoHelper {})
139
165
sharedConfigManager := sharedconfig .NewManagerImpl ()
140
166
configHandlerMap := make (map [cb.ConfigurationItem_ConfigurationType ]configtx.Handler )
@@ -150,6 +176,15 @@ func (ml *multiLedger) newResources(configTx *cb.Envelope) (configtx.Manager, po
150
176
}
151
177
}
152
178
179
+ configManager , err := configtx .NewConfigurationManager (configEnvelope , policyManager , configHandlerMap )
180
+ if err != nil {
181
+ return nil , nil , nil , fmt .Errorf ("Error unpacking configuration transaction: %s" , err )
182
+ }
183
+
184
+ return configManager , policyManager , sharedConfigManager , nil
185
+ }
186
+
187
+ func (ml * multiLedger ) newResources (configTx * cb.Envelope ) (configtx.Manager , policies.Manager , rawledger.ReadWriter , sharedconfig.Manager ) {
153
188
payload := & cb.Payload {}
154
189
err := proto .Unmarshal (configTx .Payload , payload )
155
190
if err != nil {
@@ -162,9 +197,10 @@ func (ml *multiLedger) newResources(configTx *cb.Envelope) (configtx.Manager, po
162
197
logger .Fatalf ("Error unmarshaling a config transaction to config envelope: %s" , err )
163
198
}
164
199
165
- configManager , err := configtx .NewConfigurationManager (configEnvelope , policyManager , configHandlerMap )
200
+ configManager , policyManager , sharedConfigManager , err := newConfigTxManagerAndHandlers (configEnvelope )
201
+
166
202
if err != nil {
167
- logger .Fatalf ("Error unpacking configuration transaction : %s" , err )
203
+ logger .Fatalf ("Error creating configtx manager and handlers : %s" , err )
168
204
}
169
205
170
206
chainID := configManager .ChainID ()
@@ -176,3 +212,28 @@ func (ml *multiLedger) newResources(configTx *cb.Envelope) (configtx.Manager, po
176
212
177
213
return configManager , policyManager , ledger , sharedConfigManager
178
214
}
215
+
216
+ func (ml * multiLedger ) systemChain () * systemChain {
217
+ return ml .sysChain
218
+ }
219
+
220
+ func (ml * multiLedger ) newChain (configtx * cb.Envelope ) {
221
+ configManager , policyManager , backingLedger , sharedConfig := ml .newResources (configtx )
222
+ backingLedger .Append ([]* cb.Envelope {configtx }, nil )
223
+
224
+ // Copy the map to allow concurrent reads from broadcast/deliver while the new chainSupport is
225
+ newChains := make (map [string ]* chainSupport )
226
+ for key , value := range ml .chains {
227
+ newChains [key ] = value
228
+ }
229
+
230
+ cs := newChainSupport (createStandardFilters (configManager ), configManager , policyManager , backingLedger , sharedConfig , ml .consenters )
231
+ chainID := configManager .ChainID ()
232
+
233
+ logger .Debugf ("Created and starting new chain %s" , chainID )
234
+
235
+ newChains [string (chainID )] = cs
236
+ cs .start ()
237
+
238
+ ml .chains = newChains
239
+ }
0 commit comments