Skip to content

Commit

Permalink
Passing SignedProposal the chaincode execution
Browse files Browse the repository at this point in the history
This change-set passes the SignedProposal to the chaincode
execution engine for two reasons:
1. being able to apply ACL on CC2CC
2. passing signed proposal to chaincode, if needed.

Change-Id: I994ee261e942b2714e2506a4ea417bd4004a5963
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Feb 19, 2017
1 parent 9b64e7e commit f61e6b2
Show file tree
Hide file tree
Showing 15 changed files with 88 additions and 75 deletions.
8 changes: 4 additions & 4 deletions core/chaincode/ccproviderimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,21 @@ func (c *ccProviderImpl) GetContext(ledger ledger.PeerLedger) (context.Context,
// GetCCContext returns an interface that encapsulates a
// chaincode context; the interface is required to avoid
// referencing the chaincode package from the interface definition
func (c *ccProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, prop *pb.Proposal) interface{} {
ctx := ccprovider.NewCCContext(cid, name, version, txid, syscc, prop)
func (c *ccProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) interface{} {
ctx := ccprovider.NewCCContext(cid, name, version, txid, syscc, signedProp, prop)
return &ccProviderContextImpl{ctx: ctx}
}

// GetCCValidationInfoFromLCCC returns the VSCC and the policy listed in LCCC for the supplied chaincode
func (c *ccProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) {
func (c *ccProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) {
// LCCC does not have any notion about its own
// endorsing policy - we should never call this
// function with lccc as the chaincodeID
if chaincodeID == "lccc" {
panic("GetCCValidationInfoFromLCCC invoke for LCCC")
}

data, err := GetChaincodeDataFromLCCC(ctxt, txid, prop, chainID, chaincodeID)
data, err := GetChaincodeDataFromLCCC(ctxt, txid, signedProp, prop, chainID, chaincodeID)
if err != nil {
return "", nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions core/chaincode/chaincode_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func (chaincodeSupport *ChaincodeSupport) sendReady(context context.Context, ccc

var notfy chan *pb.ChaincodeMessage
var err error
if notfy, err = chrte.handler.ready(context, cccid.ChainID, cccid.TxID, cccid.Proposal); err != nil {
if notfy, err = chrte.handler.ready(context, cccid.ChainID, cccid.TxID, cccid.SignedProposal, cccid.Proposal); err != nil {
return fmt.Errorf("Error sending %s: %s", pb.ChaincodeMessage_INIT, err)
}
if notfy != nil {
Expand Down Expand Up @@ -533,7 +533,7 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid
var depPayload []byte

//hopefully we are restarting from existing image and the deployed transaction exists
depPayload, err = GetCDSFromLCCC(context, cccid.TxID, cccid.Proposal, cccid.ChainID, cID.Name)
depPayload, err = GetCDSFromLCCC(context, cccid.TxID, cccid.SignedProposal, cccid.Proposal, cccid.ChainID, cID.Name)
if err != nil {
return cID, cMsg, fmt.Errorf("Could not get deployment transaction from LCCC for %s - %s", canName, err)
}
Expand Down Expand Up @@ -642,7 +642,7 @@ func (chaincodeSupport *ChaincodeSupport) Execute(ctxt context.Context, cccid *c

var notfy chan *pb.ChaincodeMessage
var err error
if notfy, err = chrte.handler.sendExecuteMessage(ctxt, cccid.ChainID, msg, cccid.Proposal); err != nil {
if notfy, err = chrte.handler.sendExecuteMessage(ctxt, cccid.ChainID, msg, cccid.SignedProposal, cccid.Proposal); err != nil {
return nil, fmt.Errorf("Error sending %s: %s", msg.Type.String(), err)
}
var ccresp *pb.ChaincodeMessage
Expand Down
8 changes: 4 additions & 4 deletions core/chaincode/chaincodeexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func createCIS(ccname string, args [][]byte) (*pb.ChaincodeInvocationSpec, error
}

// GetCDSFromLCCC gets chaincode deployment spec from LCCC
func GetCDSFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) ([]byte, error) {
func GetCDSFromLCCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) ([]byte, error) {
version := util.GetSysCCVersion()
cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, prop)
cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, signedProp, prop)
res, _, err := ExecuteChaincode(ctxt, cccid, [][]byte{[]byte("getdepspec"), []byte(chainID), []byte(chaincodeID)})
if err != nil {
return nil, fmt.Errorf("Execute getdepspec(%s, %s) of LCCC error: %s", chainID, chaincodeID, err)
Expand All @@ -54,9 +54,9 @@ func GetCDSFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainI
}

// GetChaincodeDataFromLCCC gets chaincode data from LCCC given name
func GetChaincodeDataFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) (*ccprovider.ChaincodeData, error) {
func GetChaincodeDataFromLCCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) (*ccprovider.ChaincodeData, error) {
version := util.GetSysCCVersion()
cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, prop)
cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, signedProp, prop)
res, _, err := ExecuteChaincode(ctxt, cccid, [][]byte{[]byte("getccdata"), []byte(chainID), []byte(chaincodeID)})
if err == nil {
if res.Status != shim.OK {
Expand Down
2 changes: 1 addition & 1 deletion core/chaincode/concurrency_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func TestExecuteConcurrentInvokes(t *testing.T) {

spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: chaincodeID, Input: &pb.ChaincodeInput{Args: args}}

cccid := ccprovider.NewCCContext(chainID, "nkpi", "0", "", false, nil)
cccid := ccprovider.NewCCContext(chainID, "nkpi", "0", "", false, nil, nil)

defer theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})

Expand Down
30 changes: 15 additions & 15 deletions core/chaincode/exectransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func deploy2(ctx context.Context, cccid *ccprovider.CCContext, chaincodeDeployme
ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec)

sysCCVers := util.GetSysCCVersion()
lcccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, nil)
lcccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, nil, nil)

//write to lccc
if _, _, err = ExecuteWithErrorFilter(ctx, lcccid, cis); err != nil {
Expand Down Expand Up @@ -331,7 +331,7 @@ func invokeWithVersion(ctx context.Context, chainID string, version string, spec
}
}()

cccid := ccprovider.NewCCContext(chainID, chaincodeInvocationSpec.ChaincodeSpec.ChaincodeId.Name, version, uuid, false, nil)
cccid := ccprovider.NewCCContext(chainID, chaincodeInvocationSpec.ChaincodeSpec.ChaincodeId.Name, version, uuid, false, nil, nil)
retval, ccevt, err = ExecuteWithErrorFilter(ctx, cccid, chaincodeInvocationSpec)
if err != nil {
return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s", err)
Expand Down Expand Up @@ -362,7 +362,7 @@ func executeDeployTransaction(t *testing.T, chainID string, name string, url str
args := util.ToChaincodeArgs(f, "a", "100", "b", "200")
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: &pb.ChaincodeID{Name: name, Path: url, Version: "0"}, Input: &pb.ChaincodeInput{Args: args}}

cccid := ccprovider.NewCCContext(chainID, name, "0", "", false, nil)
cccid := ccprovider.NewCCContext(chainID, name, "0", "", false, nil, nil)

_, err = deploy(ctxt, cccid, spec, 0)

Expand All @@ -389,7 +389,7 @@ func chaincodeQueryChaincode(chainID string, user string) error {

spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}}

cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil)
cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)

var nextBlockNumber uint64

Expand All @@ -413,7 +413,7 @@ func chaincodeQueryChaincode(chainID string, user string) error {

spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}

cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil)
cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil, nil)

_, err = deploy(ctxt, cccid2, spec2, nextBlockNumber)
nextBlockNumber++
Expand Down Expand Up @@ -618,7 +618,7 @@ func TestExecuteInvokeTransaction(t *testing.T) {

var ctxt = context.Background()

cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil)
cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)
url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url, Version: "0"}

Expand Down Expand Up @@ -652,7 +652,7 @@ func TestExecuteInvokeInvalidTransaction(t *testing.T) {
url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url, Version: "0"}

cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil)
cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)

//FAIL, FAIL!
args := []string{"x", "-1"}
Expand Down Expand Up @@ -709,7 +709,7 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er

spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}}

cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil)
cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)

var nextBlockNumber uint64

Expand All @@ -736,7 +736,7 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er

spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}

cccid2 := ccprovider.NewCCContext(chainID, "example04", "0", "", false, nil)
cccid2 := ccprovider.NewCCContext(chainID, "example04", "0", "", false, nil, nil)

_, err = deploy(ctxt, cccid2, spec2, nextBlockNumber)
nextBlockNumber++
Expand Down Expand Up @@ -812,7 +812,7 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {

spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}}

cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil)
cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)

var nextBlockNumber uint64

Expand All @@ -837,7 +837,7 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {

spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}

cccid2 := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, nil)
cccid2 := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, nil, nil)

_, err = deploy(ctxt, cccid2, spec2, nextBlockNumber)
nextBlockNumber++
Expand Down Expand Up @@ -903,7 +903,7 @@ func TestQueries(t *testing.T) {

spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}}

cccid := ccprovider.NewCCContext(chainID, "tmap", "0", "", false, nil)
cccid := ccprovider.NewCCContext(chainID, "tmap", "0", "", false, nil, nil)

var nextBlockNumber uint64
_, err = deploy(ctxt, cccid, spec, nextBlockNumber)
Expand Down Expand Up @@ -1003,7 +1003,7 @@ func TestGetEvent(t *testing.T) {
f := "init"
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(f)}}

cccid := ccprovider.NewCCContext(chainID, "esender", "0", "", false, nil)
cccid := ccprovider.NewCCContext(chainID, "esender", "0", "", false, nil, nil)
var nextBlockNumber uint64
_, err = deploy(ctxt, cccid, spec, nextBlockNumber)
nextBlockNumber++
Expand Down Expand Up @@ -1073,7 +1073,7 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) {

spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}}

cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil)
cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)
var nextBlockNumber uint64
_, err = deploy(ctxt, cccid1, spec1, nextBlockNumber)
nextBlockNumber++
Expand All @@ -1096,7 +1096,7 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) {

spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}}

cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil)
cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil, nil)

_, err = deploy(ctxt, cccid2, spec2, nextBlockNumber)
nextBlockNumber++
Expand Down
34 changes: 21 additions & 13 deletions core/chaincode/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type MessageHandler interface {

type transactionContext struct {
chainID string
signedProp *pb.SignedProposal
proposal *pb.Proposal
responseNotifier chan *pb.ChaincodeMessage

Expand Down Expand Up @@ -181,7 +182,7 @@ func (handler *Handler) serialSendAsync(msg *pb.ChaincodeMessage, errc chan erro
}()
}

func (handler *Handler) createTxContext(ctxt context.Context, chainID string, txid string, prop *pb.Proposal) (*transactionContext, error) {
func (handler *Handler) createTxContext(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (*transactionContext, error) {
if handler.txCtxs == nil {
return nil, fmt.Errorf("cannot create notifier for txid:%s", txid)
}
Expand All @@ -190,7 +191,7 @@ func (handler *Handler) createTxContext(ctxt context.Context, chainID string, tx
if handler.txCtxs[txid] != nil {
return nil, fmt.Errorf("txid:%s exists", txid)
}
txctx := &transactionContext{chainID: chainID, proposal: prop, responseNotifier: make(chan *pb.ChaincodeMessage, 1),
txctx := &transactionContext{chainID: chainID, signedProp: signedProp, proposal: prop, responseNotifier: make(chan *pb.ChaincodeMessage, 1),
queryIteratorMap: make(map[string]commonledger.ResultsIterator)}
handler.txCtxs[txid] = txctx
txctx.txsimulator = getTxSimulator(ctxt)
Expand Down Expand Up @@ -233,7 +234,7 @@ func (handler *Handler) deleteQueryIterator(txContext *transactionContext, txid
}

// Check if the transactor is allow to call this chaincode on this channel
func (handler *Handler) checkACL(proposal *pb.Proposal, calledCC *ccParts) *pb.ChaincodeMessage {
func (handler *Handler) checkACL(signedProp *pb.SignedProposal, proposal *pb.Proposal, calledCC *ccParts) *pb.ChaincodeMessage {
// TODO: Decide what to pass in to verify that this transactor can access this
// channel (chID) and chaincode (ccID). Very likely we need the signedProposal
// which contains the sig and creator cert
Expand Down Expand Up @@ -1249,7 +1250,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
shorttxid(msg.Txid), calledCcParts.name, calledCcParts.suffix)
}

triggerNextStateMsg = handler.checkACL(txContext.proposal, calledCcParts)
triggerNextStateMsg = handler.checkACL(txContext.signedProp, txContext.proposal, calledCcParts)
if triggerNextStateMsg != nil {
return
}
Expand Down Expand Up @@ -1286,15 +1287,15 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) {

//Call LCCC to get the called chaincode artifacts
var cd *ccprovider.ChaincodeData
cd, err = GetChaincodeDataFromLCCC(ctxt, msg.Txid, txContext.proposal, calledCcParts.suffix, calledCcParts.name)
cd, err = GetChaincodeDataFromLCCC(ctxt, msg.Txid, txContext.signedProp, txContext.proposal, calledCcParts.suffix, calledCcParts.name)
if err != nil {
payload := []byte(err.Error())
chaincodeLogger.Debugf("[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s",
shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR)
triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
return
}
cccid := ccprovider.NewCCContext(calledCcParts.suffix, calledCcParts.name, cd.Version, msg.Txid, false, txContext.proposal)
cccid := ccprovider.NewCCContext(calledCcParts.suffix, calledCcParts.name, cd.Version, msg.Txid, false, txContext.signedProp, txContext.proposal)

// Launch the new chaincode if not already running
if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
Expand Down Expand Up @@ -1373,27 +1374,33 @@ func (handler *Handler) enterEndState(e *fsm.Event, state string) {
e.Cancel(fmt.Errorf("Entered end state"))
}

func (handler *Handler) setChaincodeProposal(prop *pb.Proposal, msg *pb.ChaincodeMessage) error {
func (handler *Handler) setChaincodeProposal(signedProp *pb.SignedProposal, prop *pb.Proposal, msg *pb.ChaincodeMessage) error {
chaincodeLogger.Debug("Setting chaincode proposal context...")
if prop != nil {
chaincodeLogger.Debug("Proposal different from nil. Creating chaincode proposal context...")

// Check that also signedProp is different from nil
if signedProp == nil {
return fmt.Errorf("Failed getting proposal context. Signed proposal is nil.")
}

msg.Proposal = prop
}
return nil
}

//move to ready
func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) {
txctx, funcErr := handler.createTxContext(ctxt, chainID, txid, prop)
func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) {
txctx, funcErr := handler.createTxContext(ctxt, chainID, txid, signedProp, prop)
if funcErr != nil {
return nil, funcErr
}

chaincodeLogger.Debug("sending READY")
ccMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: txid}

if err := handler.setChaincodeProposal(prop, ccMsg); err != nil {
//if security is disabled the context elements will just be nil
if err := handler.setChaincodeProposal(signedProp, prop, ccMsg); err != nil {
return nil, err
}

Expand Down Expand Up @@ -1448,16 +1455,17 @@ func filterError(errFromFSMEvent error) error {
return nil
}

func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *pb.ChaincodeMessage, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) {
txctx, err := handler.createTxContext(ctxt, chainID, msg.Txid, prop)
func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *pb.ChaincodeMessage, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) {
txctx, err := handler.createTxContext(ctxt, chainID, msg.Txid, signedProp, prop)
if err != nil {
return nil, err
}
if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
chaincodeLogger.Debugf("[%s]Inside sendExecuteMessage. Message %s", shorttxid(msg.Txid), msg.Type.String())
}

if err = handler.setChaincodeProposal(prop, msg); err != nil {
//if security is disabled the context elements will just be nil
if err = handler.setChaincodeProposal(signedProp, prop, msg); err != nil {
return nil, err
}

Expand Down
2 changes: 1 addition & 1 deletion core/chaincode/multichains_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestExecuteInvokeOnManyChains(t *testing.T) {

args := []string{"a", "b", "10"}
for _, c := range chains {
cccid := ccprovider.NewCCContext(c, "example02", "0", "", false, nil)
cccid := ccprovider.NewCCContext(c, "example02", "0", "", false, nil, nil)
err = invokeExample02Transaction(ctxt, cccid, chaincodeID, args, false)
if err != nil {
t.Fail()
Expand Down
2 changes: 1 addition & 1 deletion core/chaincode/systemchaincode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func deploySampleSysCC(t *testing.T, ctxt context.Context, chainID string) error
_, _, _, err := invokeWithVersion(ctxt, chainID, sysCCVers, spec, nextBlockNumber)
nextBlockNumber++

cccid := ccprovider.NewCCContext(chainID, "sample_syscc", sysCCVers, "", true, nil)
cccid := ccprovider.NewCCContext(chainID, "sample_syscc", sysCCVers, "", true, nil, nil)
cdsforStop := &pb.ChaincodeDeploymentSpec{ExecEnv: 1, ChaincodeSpec: spec}
if err != nil {
theChaincodeSupport.Stop(ctxt, cccid, cdsforStop)
Expand Down
Loading

0 comments on commit f61e6b2

Please sign in to comment.