Skip to content

Commit a3687a1

Browse files
author
Srinivasan Muralidharan
committed
chaincode life-cycle system chaincode for a chain
The life-cycle system chaincode (lccc) manages chaincodes for a chain in an endorser. The life-cycle is basically the "deploy", "upgrade", "stop" and "start" actions. This changeset provides the basic chaincode for creating the table of chaincodes and implements just the "deploy" command. This work will be developed till the basic endorser functions are fully implemented. This driver for this chaincode will be checked in the next changeset. NOTE - this change also fixes the limitation where only one system chaincode can be running at a time. This is part of the feature development of FAB-181, FAB-182, FAB-183. Change-Id: Iff36fee7c5b9a9ce4658910db73304a6bcd7e3d4 Signed-off-by: Srinivasan Muralidharan <[email protected]>
1 parent f6a6003 commit a3687a1

File tree

7 files changed

+624
-20
lines changed

7 files changed

+624
-20
lines changed

bddtests/endorser.feature

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ Feature: Endorser
2121
Scenario Outline: Basic deploy endorsement for chaincode through GRPC to multiple endorsers
2222

2323
Given we compose "<ComposeFile>"
24-
And I wait "1" seconds
24+
And I wait "5" seconds
2525
And I register with CA supplying username "binhn" and secret "7avZQLwcUe9q" on peers:
2626
| vp0 |
2727

2828
When user "binhn" creates a chaincode spec of type "GOLANG" for chaincode "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" aliased as "cc_spec" with args
2929
| funcName | arg1 | arg2 | arg3 | arg4 |
3030
| init | a | 100 | b | 200 |
3131
And user "binhn" creates a deployment proposal "proposal1" using chaincode spec "cc_spec"
32-
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "2" seconds:
32+
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "20" seconds:
3333
| vp0 | vp1 | vp2 | vp3 |
3434
And user "binhn" stores their last result as "proposal1Responses"
3535
Then user "binhn" expects proposal responses "proposal1Responses" with status "200" from endorsers:
@@ -54,7 +54,7 @@ Feature: Endorser
5454
| init | a | 100 | b | 200 |
5555
And user "binhn" sets ESCC to "my_escc" for chaincode spec "cc_spec"
5656
And user "binhn" creates a deployment proposal "proposal1" using chaincode spec "cc_spec"
57-
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "2" seconds:
57+
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "20" seconds:
5858
| vp0 | vp1 | vp2 | vp3 |
5959
And user "binhn" stores their last result as "proposal1Responses"
6060
Then user "binhn" expects proposal responses "proposal1Responses" with status "200" from endorsers:
@@ -77,7 +77,7 @@ Feature: Endorser
7777
| init | a | 100 | b | 200 |
7878
And user "binhn" sets VSCC to "my_vscc" for chaincode spec "cc_spec"
7979
And user "binhn" creates a deployment proposal "proposal1" using chaincode spec "cc_spec"
80-
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "2" seconds:
80+
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "20" seconds:
8181
| vp0 | vp1 | vp2 | vp3 |
8282
And user "binhn" stores their last result as "proposal1Responses"
8383
Then user "binhn" expects proposal responses "proposal1Responses" with status "200" from endorsers:

core/chaincode/shim/chaincode.go

+12-13
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,14 @@ import (
4545
// Logger for the shim package.
4646
var chaincodeLogger = logging.MustGetLogger("shim")
4747

48-
// Handler to shim that handles all control logic.
49-
var handler *Handler
50-
5148
// ChaincodeStub is an object passed to chaincode for shim side handling of
5249
// APIs.
5350
type ChaincodeStub struct {
5451
UUID string
5552
securityContext *pb.ChaincodeSecurityContext
5653
chaincodeEvent *pb.ChaincodeEvent
5754
args [][]byte
55+
handler *Handler
5856
}
5957

6058
// Peer address derived from command line or env var
@@ -150,7 +148,7 @@ func newPeerClientConnection() (*grpc.ClientConn, error) {
150148
func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode) error {
151149

152150
// Create the shim handler responsible for all control logic
153-
handler = newChaincodeHandler(stream, cc)
151+
handler := newChaincodeHandler(stream, cc)
154152

155153
defer stream.CloseSend()
156154
// Send the ChaincodeID during register.
@@ -232,7 +230,7 @@ func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode
232230
// -- init stub ---
233231
// ChaincodeInvocation functionality
234232

235-
func (stub *ChaincodeStub) init(uuid string, secContext *pb.ChaincodeSecurityContext) {
233+
func (stub *ChaincodeStub) init(handler *Handler, uuid string, secContext *pb.ChaincodeSecurityContext) {
236234
stub.UUID = uuid
237235
stub.securityContext = secContext
238236
stub.args = [][]byte{}
@@ -243,14 +241,15 @@ func (stub *ChaincodeStub) init(uuid string, secContext *pb.ChaincodeSecurityCon
243241
} else {
244242
panic("Arguments cannot be unmarshalled.")
245243
}
244+
stub.handler = handler
246245
}
247246

248247
func InitTestStub(funargs ...string) *ChaincodeStub {
249248
stub := ChaincodeStub{}
250249
allargs := util.ToChaincodeArgs(funargs...)
251250
newCI := pb.ChaincodeInput{Args: allargs}
252251
pl, _ := proto.Marshal(&newCI)
253-
stub.init("TEST-uuid", &pb.ChaincodeSecurityContext{Payload: pl})
252+
stub.init(&Handler{}, "TEST-uuid", &pb.ChaincodeSecurityContext{Payload: pl})
254253
return &stub
255254
}
256255

@@ -263,31 +262,31 @@ func InitTestStub(funargs ...string) *ChaincodeStub {
263262
// same transaction context; that is, chaincode calling chaincode doesn't
264263
// create a new transaction message.
265264
func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte) ([]byte, error) {
266-
return handler.handleInvokeChaincode(chaincodeName, args, stub.UUID)
265+
return stub.handler.handleInvokeChaincode(chaincodeName, args, stub.UUID)
267266
}
268267

269268
// QueryChaincode locally calls the specified chaincode `Query` using the
270269
// same transaction context; that is, chaincode calling chaincode doesn't
271270
// create a new transaction message.
272271
func (stub *ChaincodeStub) QueryChaincode(chaincodeName string, args [][]byte) ([]byte, error) {
273-
return handler.handleQueryChaincode(chaincodeName, args, stub.UUID)
272+
return stub.handler.handleQueryChaincode(chaincodeName, args, stub.UUID)
274273
}
275274

276275
// --------- State functions ----------
277276

278277
// GetState returns the byte array value specified by the `key`.
279278
func (stub *ChaincodeStub) GetState(key string) ([]byte, error) {
280-
return handler.handleGetState(key, stub.UUID)
279+
return stub.handler.handleGetState(key, stub.UUID)
281280
}
282281

283282
// PutState writes the specified `value` and `key` into the ledger.
284283
func (stub *ChaincodeStub) PutState(key string, value []byte) error {
285-
return handler.handlePutState(key, value, stub.UUID)
284+
return stub.handler.handlePutState(key, value, stub.UUID)
286285
}
287286

288287
// DelState removes the specified `key` and its value from the ledger.
289288
func (stub *ChaincodeStub) DelState(key string) error {
290-
return handler.handleDelState(key, stub.UUID)
289+
return stub.handler.handleDelState(key, stub.UUID)
291290
}
292291

293292
//ReadCertAttribute is used to read an specific attribute from the transaction certificate, *attributeName* is passed as input parameter to this function.
@@ -338,11 +337,11 @@ type StateRangeQueryIterator struct {
338337
// between the startKey and endKey, inclusive. The order in which keys are
339338
// returned by the iterator is random.
340339
func (stub *ChaincodeStub) RangeQueryState(startKey, endKey string) (StateRangeQueryIteratorInterface, error) {
341-
response, err := handler.handleRangeQueryState(startKey, endKey, stub.UUID)
340+
response, err := stub.handler.handleRangeQueryState(startKey, endKey, stub.UUID)
342341
if err != nil {
343342
return nil, err
344343
}
345-
return &StateRangeQueryIterator{handler, stub.UUID, response, 0}, nil
344+
return &StateRangeQueryIterator{stub.handler, stub.UUID, response, 0}, nil
346345
}
347346

348347
// HasNext returns true if the range query iterator contains additional keys

core/chaincode/shim/handler.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ func (handler *Handler) handleInit(msg *pb.ChaincodeMessage) {
222222
// Call chaincode's Run
223223
// Create the ChaincodeStub which the chaincode can use to callback
224224
stub := new(ChaincodeStub)
225-
stub.init(msg.Txid, msg.SecurityContext)
225+
stub.init(handler, msg.Txid, msg.SecurityContext)
226226
res, err := handler.cc.Init(stub)
227227

228228
// delete isTransaction entry
@@ -289,7 +289,7 @@ func (handler *Handler) handleTransaction(msg *pb.ChaincodeMessage) {
289289
// Call chaincode's Run
290290
// Create the ChaincodeStub which the chaincode can use to callback
291291
stub := new(ChaincodeStub)
292-
stub.init(msg.Txid, msg.SecurityContext)
292+
stub.init(handler, msg.Txid, msg.SecurityContext)
293293
res, err := handler.cc.Invoke(stub)
294294

295295
// delete isTransaction entry
@@ -336,7 +336,7 @@ func (handler *Handler) handleQuery(msg *pb.ChaincodeMessage) {
336336
// Call chaincode's Query
337337
// Create the ChaincodeStub which the chaincode can use to callback
338338
stub := new(ChaincodeStub)
339-
stub.init(msg.Txid, msg.SecurityContext)
339+
stub.init(handler, msg.Txid, msg.SecurityContext)
340340
res, err := handler.cc.Query(stub)
341341

342342
// delete isTransaction entry

core/system_chaincode/importsysccs.go

+8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/hyperledger/fabric/core/system_chaincode/api"
2121
//import system chain codes here
2222
"github.com/hyperledger/fabric/bddtests/syschaincode/noop"
23+
"github.com/hyperledger/fabric/core/system_chaincode/lccc"
2324
)
2425

2526
//see systemchaincode_test.go for an example using "sample_syscc"
@@ -30,6 +31,13 @@ var systemChaincodes = []*api.SystemChaincode{
3031
Path: "github.com/hyperledger/fabric/bddtests/syschaincode/noop",
3132
InitArgs: [][]byte{},
3233
Chaincode: &noop.SystemChaincode{},
34+
},
35+
{
36+
Enabled: true,
37+
Name: "lccc",
38+
Path: "github.com/hyperledger/fabric/core/system_chaincode/lccc",
39+
InitArgs: [][]byte{[]byte("")},
40+
Chaincode: &lccc.LifeCycleSysCC{},
3341
}}
3442

3543
//RegisterSysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric

0 commit comments

Comments
 (0)