@@ -22,11 +22,11 @@ limitations under the License.
22
22
package cscc
23
23
24
24
import (
25
- "errors"
26
25
"fmt"
27
26
28
27
"github.com/golang/protobuf/proto"
29
28
"github.com/hyperledger/fabric/common/channelconfig"
29
+ "github.com/hyperledger/fabric/common/config"
30
30
"github.com/hyperledger/fabric/common/flogging"
31
31
"github.com/hyperledger/fabric/core/aclmgmt"
32
32
"github.com/hyperledger/fabric/core/chaincode/shim"
@@ -37,22 +37,26 @@ import (
37
37
"github.com/hyperledger/fabric/protos/common"
38
38
pb "github.com/hyperledger/fabric/protos/peer"
39
39
"github.com/hyperledger/fabric/protos/utils"
40
+ "github.com/pkg/errors"
40
41
)
41
42
42
43
// PeerConfiger implements the configuration handler for the peer. For every
43
44
// configuration transaction coming in from the ordering service, the
44
45
// committer calls this system chaincode to process the transaction.
45
46
type PeerConfiger struct {
46
47
policyChecker policy.PolicyChecker
48
+ configMgr config.Manager
47
49
}
48
50
49
51
var cnflogger = flogging .MustGetLogger ("cscc" )
50
52
51
53
// These are function names from Invoke first parameter
52
54
const (
53
- JoinChain string = "JoinChain"
54
- GetConfigBlock string = "GetConfigBlock"
55
- GetChannels string = "GetChannels"
55
+ JoinChain string = "JoinChain"
56
+ GetConfigBlock string = "GetConfigBlock"
57
+ GetChannels string = "GetChannels"
58
+ GetConfigTree string = "GetConfigTree"
59
+ SimulateConfigTreeUpdate string = "SimulateConfigTreeUpdate"
56
60
)
57
61
58
62
// Init is called once per chain when the chain is created.
@@ -67,7 +71,7 @@ func (e *PeerConfiger) Init(stub shim.ChaincodeStubInterface) pb.Response {
67
71
mgmt .GetLocalMSP (),
68
72
mgmt .NewLocalMSPPrincipalGetter (),
69
73
)
70
-
74
+ e . configMgr = peer . NewConfigSupport ()
71
75
return shim .Success (nil )
72
76
}
73
77
@@ -140,6 +144,19 @@ func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
140
144
}
141
145
142
146
return getConfigBlock (args [1 ])
147
+ case GetConfigTree :
148
+ // 2. check policy
149
+ if err = aclmgmt .GetACLProvider ().CheckACL (aclmgmt .CSCC_GetConfigTree , string (args [1 ]), sp ); err != nil {
150
+ return shim .Error (fmt .Sprintf ("\" GetConfigTree\" request failed authorization check for channel [%s]: [%s]" , args [1 ], err ))
151
+ }
152
+
153
+ return e .getConfigTree (args [1 ])
154
+ case SimulateConfigTreeUpdate :
155
+ // Check policy
156
+ if err = aclmgmt .GetACLProvider ().CheckACL (aclmgmt .CSCC_SimulateConfigTreeUpdate , string (args [1 ]), sp ); err != nil {
157
+ return shim .Error (fmt .Sprintf ("\" SimulateConfigTreeUpdate\" request failed authorization check for channel [%s]: [%s]" , args [1 ], err ))
158
+ }
159
+ return e .simulateConfigTreeUpdate (args [1 ], args [2 ])
143
160
case GetChannels :
144
161
// 2. check local MSP Members policy
145
162
// TODO: move to ACLProvider once it will support chainless ACLs
@@ -157,13 +174,13 @@ func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
157
174
func validateConfigBlock (block * common.Block ) error {
158
175
envelopeConfig , err := utils .ExtractEnvelope (block , 0 )
159
176
if err != nil {
160
- return errors .New ( fmt . Sprintf ( "Failed to %s" , err ) )
177
+ return errors .Errorf ( "Failed to %s" , err )
161
178
}
162
179
163
180
configEnv := & common.ConfigEnvelope {}
164
181
_ , err = utils .UnmarshalEnvelopeOfType (envelopeConfig , common .HeaderType_CONFIG , configEnv )
165
182
if err != nil {
166
- return errors .New ( fmt . Sprintf ( "Bad configuration envelope: %s" , err ) )
183
+ return errors .Errorf ( "Bad configuration envelope: %s" , err )
167
184
}
168
185
169
186
if configEnv .Config == nil {
@@ -180,8 +197,8 @@ func validateConfigBlock(block *common.Block) error {
180
197
181
198
_ , exists := configEnv .Config .ChannelGroup .Groups [channelconfig .ApplicationGroupKey ]
182
199
if ! exists {
183
- return errors .New ( fmt . Sprintf ("Invalid configuration block, missing %s " +
184
- "configuration group" , channelconfig .ApplicationGroupKey ))
200
+ return errors .Errorf ("Invalid configuration block, missing %s " +
201
+ "configuration group" , channelconfig .ApplicationGroupKey )
185
202
}
186
203
187
204
return nil
@@ -227,6 +244,72 @@ func getConfigBlock(chainID []byte) pb.Response {
227
244
return shim .Success (blockBytes )
228
245
}
229
246
247
+ // getConfigTree returns the current channel and resources configuration for the specified chainID.
248
+ // If the peer doesn't belong to the chain, returns error
249
+ func (e * PeerConfiger ) getConfigTree (chainID []byte ) pb.Response {
250
+ if chainID == nil {
251
+ return shim .Error ("Chain ID must not be nil" )
252
+ }
253
+ channelCfg := e .configMgr .GetChannelConfig (string (chainID )).ConfigProto ()
254
+ if channelCfg == nil {
255
+ return shim .Error (fmt .Sprintf ("Unknown chain ID, %s" , string (chainID )))
256
+ }
257
+ resCfg := e .configMgr .GetResourceConfig (string (chainID )).ConfigProto ()
258
+ if resCfg == nil {
259
+ return shim .Error (fmt .Sprintf ("Unknown chain ID, %s" , string (chainID )))
260
+ }
261
+ agCfg := & pb.ConfigTree {ChannelConfig : channelCfg , ResourcesConfig : resCfg }
262
+ configBytes , err := utils .Marshal (agCfg )
263
+ if err != nil {
264
+ return shim .Error (err .Error ())
265
+ }
266
+ return shim .Success (configBytes )
267
+ }
268
+
269
+ func (e * PeerConfiger ) simulateConfigTreeUpdate (chainID []byte , envb []byte ) pb.Response {
270
+ if chainID == nil {
271
+ return shim .Error ("Chain ID must not be nil" )
272
+ }
273
+ if envb == nil {
274
+ return shim .Error ("Config delta bytes must not be nil" )
275
+ }
276
+ env := & common.Envelope {}
277
+ err := proto .Unmarshal (envb , env )
278
+ if err != nil {
279
+ return shim .Error (err .Error ())
280
+ }
281
+ cfg , err := supportByType (e , chainID , env )
282
+ if err != nil {
283
+ return shim .Error (err .Error ())
284
+ }
285
+ _ , err = cfg .ProposeConfigUpdate (env )
286
+ if err != nil {
287
+ return shim .Error (err .Error ())
288
+ }
289
+ return shim .Success ([]byte ("Simulation is successful" ))
290
+ }
291
+
292
+ func supportByType (pc * PeerConfiger , chainID []byte , env * common.Envelope ) (config.Config , error ) {
293
+ payload := & common.Payload {}
294
+
295
+ if err := proto .Unmarshal (env .Payload , payload ); err != nil {
296
+ return nil , errors .Errorf ("failed unmarshaling payload: %v" , err )
297
+ }
298
+
299
+ channelHdr := & common.ChannelHeader {}
300
+ if err := proto .Unmarshal (payload .Header .ChannelHeader , channelHdr ); err != nil {
301
+ return nil , errors .Errorf ("failed unmarshaling payload header: %v" , err )
302
+ }
303
+
304
+ switch common .HeaderType (channelHdr .Type ) {
305
+ case common .HeaderType_CONFIG_UPDATE :
306
+ return pc .configMgr .GetChannelConfig (string (chainID )), nil
307
+ case common .HeaderType_PEER_RESOURCE_UPDATE :
308
+ return pc .configMgr .GetResourceConfig (string (chainID )), nil
309
+ }
310
+ return nil , errors .Errorf ("invalid payload header type: %d" , channelHdr .Type )
311
+ }
312
+
230
313
// getChannels returns information about all channels for this peer
231
314
func getChannels () pb.Response {
232
315
channelInfoArray := peer .GetChannelsInfo ()
0 commit comments