Skip to content

Commit

Permalink
chaincode life-cycle system chaincode for a chain
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
Srinivasan Muralidharan committed Sep 17, 2016
1 parent f6a6003 commit a3687a1
Show file tree
Hide file tree
Showing 7 changed files with 624 additions and 20 deletions.
8 changes: 4 additions & 4 deletions bddtests/endorser.feature
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ Feature: Endorser
Scenario Outline: Basic deploy endorsement for chaincode through GRPC to multiple endorsers

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

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
| funcName | arg1 | arg2 | arg3 | arg4 |
| init | a | 100 | b | 200 |
And user "binhn" creates a deployment proposal "proposal1" using chaincode spec "cc_spec"
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "2" seconds:
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "20" seconds:
| vp0 | vp1 | vp2 | vp3 |
And user "binhn" stores their last result as "proposal1Responses"
Then user "binhn" expects proposal responses "proposal1Responses" with status "200" from endorsers:
Expand All @@ -54,7 +54,7 @@ Feature: Endorser
| init | a | 100 | b | 200 |
And user "binhn" sets ESCC to "my_escc" for chaincode spec "cc_spec"
And user "binhn" creates a deployment proposal "proposal1" using chaincode spec "cc_spec"
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "2" seconds:
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "20" seconds:
| vp0 | vp1 | vp2 | vp3 |
And user "binhn" stores their last result as "proposal1Responses"
Then user "binhn" expects proposal responses "proposal1Responses" with status "200" from endorsers:
Expand All @@ -77,7 +77,7 @@ Feature: Endorser
| init | a | 100 | b | 200 |
And user "binhn" sets VSCC to "my_vscc" for chaincode spec "cc_spec"
And user "binhn" creates a deployment proposal "proposal1" using chaincode spec "cc_spec"
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "2" seconds:
And user "binhn" sends proposal "proposal1" to endorsers with timeout of "20" seconds:
| vp0 | vp1 | vp2 | vp3 |
And user "binhn" stores their last result as "proposal1Responses"
Then user "binhn" expects proposal responses "proposal1Responses" with status "200" from endorsers:
Expand Down
25 changes: 12 additions & 13 deletions core/chaincode/shim/chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,14 @@ import (
// Logger for the shim package.
var chaincodeLogger = logging.MustGetLogger("shim")

// Handler to shim that handles all control logic.
var handler *Handler

// ChaincodeStub is an object passed to chaincode for shim side handling of
// APIs.
type ChaincodeStub struct {
UUID string
securityContext *pb.ChaincodeSecurityContext
chaincodeEvent *pb.ChaincodeEvent
args [][]byte
handler *Handler
}

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

// Create the shim handler responsible for all control logic
handler = newChaincodeHandler(stream, cc)
handler := newChaincodeHandler(stream, cc)

defer stream.CloseSend()
// Send the ChaincodeID during register.
Expand Down Expand Up @@ -232,7 +230,7 @@ func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode
// -- init stub ---
// ChaincodeInvocation functionality

func (stub *ChaincodeStub) init(uuid string, secContext *pb.ChaincodeSecurityContext) {
func (stub *ChaincodeStub) init(handler *Handler, uuid string, secContext *pb.ChaincodeSecurityContext) {
stub.UUID = uuid
stub.securityContext = secContext
stub.args = [][]byte{}
Expand All @@ -243,14 +241,15 @@ func (stub *ChaincodeStub) init(uuid string, secContext *pb.ChaincodeSecurityCon
} else {
panic("Arguments cannot be unmarshalled.")
}
stub.handler = handler
}

func InitTestStub(funargs ...string) *ChaincodeStub {
stub := ChaincodeStub{}
allargs := util.ToChaincodeArgs(funargs...)
newCI := pb.ChaincodeInput{Args: allargs}
pl, _ := proto.Marshal(&newCI)
stub.init("TEST-uuid", &pb.ChaincodeSecurityContext{Payload: pl})
stub.init(&Handler{}, "TEST-uuid", &pb.ChaincodeSecurityContext{Payload: pl})
return &stub
}

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

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

// --------- State functions ----------

// GetState returns the byte array value specified by the `key`.
func (stub *ChaincodeStub) GetState(key string) ([]byte, error) {
return handler.handleGetState(key, stub.UUID)
return stub.handler.handleGetState(key, stub.UUID)
}

// PutState writes the specified `value` and `key` into the ledger.
func (stub *ChaincodeStub) PutState(key string, value []byte) error {
return handler.handlePutState(key, value, stub.UUID)
return stub.handler.handlePutState(key, value, stub.UUID)
}

// DelState removes the specified `key` and its value from the ledger.
func (stub *ChaincodeStub) DelState(key string) error {
return handler.handleDelState(key, stub.UUID)
return stub.handler.handleDelState(key, stub.UUID)
}

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

// HasNext returns true if the range query iterator contains additional keys
Expand Down
6 changes: 3 additions & 3 deletions core/chaincode/shim/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func (handler *Handler) handleInit(msg *pb.ChaincodeMessage) {
// Call chaincode's Run
// Create the ChaincodeStub which the chaincode can use to callback
stub := new(ChaincodeStub)
stub.init(msg.Txid, msg.SecurityContext)
stub.init(handler, msg.Txid, msg.SecurityContext)
res, err := handler.cc.Init(stub)

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

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

// delete isTransaction entry
Expand Down
8 changes: 8 additions & 0 deletions core/system_chaincode/importsysccs.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/hyperledger/fabric/core/system_chaincode/api"
//import system chain codes here
"github.com/hyperledger/fabric/bddtests/syschaincode/noop"
"github.com/hyperledger/fabric/core/system_chaincode/lccc"
)

//see systemchaincode_test.go for an example using "sample_syscc"
Expand All @@ -30,6 +31,13 @@ var systemChaincodes = []*api.SystemChaincode{
Path: "github.com/hyperledger/fabric/bddtests/syschaincode/noop",
InitArgs: [][]byte{},
Chaincode: &noop.SystemChaincode{},
},
{
Enabled: true,
Name: "lccc",
Path: "github.com/hyperledger/fabric/core/system_chaincode/lccc",
InitArgs: [][]byte{[]byte("")},
Chaincode: &lccc.LifeCycleSysCC{},
}}

//RegisterSysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric
Expand Down
Loading

0 comments on commit a3687a1

Please sign in to comment.