diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index a905c0c5444..30a49ccf0ea 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -355,7 +355,7 @@ func (chaincodeSupport *ChaincodeSupport) sendReady(context context.Context, ccc } //if initOrReady succeeded, our responsibility to delete the context - chrte.handler.deleteTxContext(cccid.TxID) + chrte.handler.deleteTxContext(cccid.ChainID, cccid.TxID) return err } @@ -784,13 +784,13 @@ func (chaincodeSupport *ChaincodeSupport) Register(stream pb.ChaincodeSupport_Re } // createCCMessage creates a transaction message. -func createCCMessage(typ pb.ChaincodeMessage_Type, txid string, cMsg *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) { +func createCCMessage(typ pb.ChaincodeMessage_Type, cid string, txid string, cMsg *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) { payload, err := proto.Marshal(cMsg) if err != nil { fmt.Printf(err.Error()) return nil, err } - return &pb.ChaincodeMessage{Type: typ, Payload: payload, Txid: txid}, nil + return &pb.ChaincodeMessage{Type: typ, Payload: payload, Txid: txid, ChannelId: cid}, nil } // Execute executes a transaction and waits for it to complete until a timeout value. @@ -824,7 +824,7 @@ func (chaincodeSupport *ChaincodeSupport) Execute(ctxt context.Context, cccid *c } //our responsibility to delete transaction context if sendExecuteMessage succeeded - chrte.handler.deleteTxContext(msg.Txid) + chrte.handler.deleteTxContext(msg.ChannelId, msg.Txid) return ccresp, err } diff --git a/core/chaincode/chaincode_support_test.go b/core/chaincode/chaincode_support_test.go index aaa87870092..f1ce018151b 100644 --- a/core/chaincode/chaincode_support_test.go +++ b/core/chaincode/chaincode_support_test.go @@ -288,7 +288,7 @@ func execCC(t *testing.T, ctxt context.Context, ccSide *mockpeer.MockCCComm, ccc } //initialize cc support env and startup the chaincode -func startCC(t *testing.T, ccname string) (*mockpeer.MockCCComm, *mockpeer.MockCCComm) { +func startCC(t *testing.T, channelID string, ccname string) (*mockpeer.MockCCComm, *mockpeer.MockCCComm) { peerSide, ccSide := setupcc(ccname) defer mockPeerCCSupport.RemoveCC(ccname) theChaincodeSupport.userRunsCC = true @@ -313,7 +313,7 @@ func startCC(t *testing.T, ccname string) (*mockpeer.MockCCComm, *mockpeer.MockC ccSide.Run() }() - ccSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: putils.MarshalOrPanic(&pb.ChaincodeID{Name: ccname + ":0"}), Txid: "0"}) + ccSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: putils.MarshalOrPanic(&pb.ChaincodeID{Name: ccname + ":0"}), Txid: "0", ChannelId: channelID}) //wait for init processDone(t, done, false) @@ -382,7 +382,7 @@ func initializeCC(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCC mockAclProvider.On("CheckACL", aclmgmt.PROPOSE, chainID, sprop).Return(nil) //bad txid in response (should be "1"), should fail - resp := &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("init succeeded")}), Txid: "unknowntxid"}} + resp := &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("init succeeded")}), Txid: "unknowntxid", ChannelId: chainID}} respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{resp}} cccid := ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) @@ -406,11 +406,11 @@ func initializeCC(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCC // correct block number for ending sim respSet = &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("100")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("200")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "C", Value: []byte("300")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c2", Key: "C", Value: []byte("300")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), ChaincodeEvent: &pb.ChaincodeEvent{ChaincodeId: ccname}, Txid: txid}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("100")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("200")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "C", Value: []byte("300")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c2", Key: "C", Value: []byte("300")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), ChaincodeEvent: &pb.ChaincodeEvent{ChaincodeId: ccname}, Txid: txid, ChannelId: chainID}}}} cccid.Version = "1" execCC(t, ctxt, ccSide, cccid, false, false, done, cis, respSet) @@ -440,21 +440,21 @@ func invokeCC(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCComm) mockAclProvider.On("CheckACL", aclmgmt.PROPOSE, chainID, sprop).Return(nil) respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "A"}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "B"}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("90")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("210")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "TODEL", Value: []byte("-to-be-deleted-")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "A"}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "B"}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("90")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("210")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "", Key: "TODEL", Value: []byte("-to-be-deleted-")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}}} cccid := ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) execCC(t, ctxt, ccSide, cccid, false, false, done, cis, respSet) //delete the extra var respSet = &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "3"}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: putils.MarshalOrPanic(&pb.DelState{Collection: "", Key: "TODEL"}), Txid: "3"}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: "3"}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "3", ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: putils.MarshalOrPanic(&pb.DelState{Collection: "", Key: "TODEL"}), Txid: "3", ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: "3", ChannelId: chainID}}}} cccid.TxID = "3" execCC(t, ctxt, ccSide, cccid, false, false, done, cis, respSet) @@ -462,8 +462,8 @@ func invokeCC(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCComm) //get the extra var and delete it //NOTE- we are calling ExecuteWithErrorFilter which returns error if chaincode returns ERROR response respSet = &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "4"}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: "4"}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "4", ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: "4", ChannelId: chainID}}}} cccid.TxID = "4" execCC(t, ctxt, ccSide, cccid, false, true, done, cis, respSet) @@ -487,19 +487,19 @@ func invokePrivateDataGetPutDelCC(t *testing.T, chainID, ccname string, ccSide * ctxt, txsim, sprop, prop := startTx(t, chainID, cis, txid) respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "C"}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: txid}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "", Key: "C"}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: txid, ChannelId: chainID}}}} cccid := ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) execCC(t, ctxt, ccSide, cccid, false, true, done, cis, respSet) respSet = &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "c1", Key: "C"}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "C", Value: []byte("310")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "A", Value: []byte("100")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "B", Value: []byte("100")}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: putils.MarshalOrPanic(&pb.DelState{Collection: "c2", Key: "C"}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "c1", Key: "C"}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "C", Value: []byte("310")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "A", Value: []byte("100")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: putils.MarshalOrPanic(&pb.PutState{Collection: "c1", Key: "B", Value: []byte("100")}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: putils.MarshalOrPanic(&pb.DelState{Collection: "c2", Key: "C"}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}}} cccid = ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) execCC(t, ctxt, ccSide, cccid, false, false, done, cis, respSet) @@ -510,8 +510,8 @@ func invokePrivateDataGetPutDelCC(t *testing.T, chainID, ccname string, ccSide * ctxt, txsim, sprop, prop = startTx(t, chainID, cis, txid) respSet = &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "c2", Key: "C"}), Txid: txid}}, - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: txid}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: putils.MarshalOrPanic(&pb.GetState{Collection: "c2", Key: "C"}), Txid: txid, ChannelId: chainID}}, + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: txid, ChannelId: chainID}}}} cccid = ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) execCC(t, ctxt, ccSide, cccid, false, true, done, cis, respSet) @@ -544,25 +544,25 @@ func getQueryStateByRange(t *testing.T, collection, chainID, ccname string, ccSi queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { qr := &pb.QueryResponse{} proto.Unmarshal(reqMsg.Payload, qr) - return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: putils.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid} + return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: putils.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid, ChannelId: chainID} } queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { qr := &pb.QueryResponse{} proto.Unmarshal(reqMsg.Payload, qr) - return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: putils.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid} + return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: putils.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid, ChannelId: chainID} } var mkpeer []*mockpeer.MockResponse - mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Payload: putils.MarshalOrPanic(&pb.GetStateByRange{Collection: collection, StartKey: "A", EndKey: "B"}), Txid: txid}}) + mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Payload: putils.MarshalOrPanic(&pb.GetStateByRange{Collection: collection, StartKey: "A", EndKey: "B"}), Txid: txid, ChannelId: chainID}}) if collection == "" { mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, queryStateNextFunc}) mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, queryStateCloseFunc}) - mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid}}) + mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}) } else { // Range queries on private data is not yet implemented. - mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid}}) + mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid, ChannelId: chainID}}) } respSet := &mockpeer.MockResponseSet{errorFunc, nil, mkpeer} @@ -582,7 +582,7 @@ func getQueryStateByRange(t *testing.T, collection, chainID, ccname string, ccSi func cc2cc(t *testing.T, chainID, chainID2, ccname string, ccSide *mockpeer.MockCCComm) error { calledCC := "calledCC" //starts and registers the CC - _, calledCCSide := startCC(t, calledCC) + _, calledCCSide := startCC(t, chainID2, calledCC) if calledCCSide == nil { t.Fatalf("start up failed for called CC") } @@ -637,15 +637,15 @@ func cc2cc(t *testing.T, chainID, chainID2, ccname string, ccSide *mockpeer.Mock } sysCCVers := util.GetSysCCVersion() - //call a callable system CC, a regular cc, a regular cc on a different chain and an uncallable system cc and expect an error inthe last one + //call a callable system CC, a regular cc, a regular but different cc on a different chain, a regular but same cc on a different chain, and an uncallable system cc and expect an error inthe last one respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "lscc:" + sysCCVers}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID2}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "vscc:" + sysCCVers}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid}}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "lscc:" + sysCCVers}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid, ChannelId: chainID}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid, ChannelId: chainID}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID2}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid, ChannelId: chainID}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "vscc:" + sysCCVers}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid, ChannelId: chainID}}}} respSet2 := &mockpeer.MockResponseSet{nil, nil, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid}}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}}} calledCCSide.SetResponses(respSet2) cccid = ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) @@ -671,10 +671,10 @@ func cc2cc(t *testing.T, chainID, chainID2, ccname string, ccSide *mockpeer.Mock mockAclProvider.On("CheckACL", aclmgmt.PROPOSE, chainID, sprop).Return(nil) //call regular cc but without ACL on called CC respSet = &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid, ChannelId: chainID}}}} respSet2 = &mockpeer.MockResponseSet{nil, nil, []*mockpeer.MockResponse{ - &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid}}}} + &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}}} calledCCSide.SetResponses(respSet2) @@ -720,25 +720,25 @@ func getQueryResult(t *testing.T, collection, chainID, ccname string, ccSide *mo queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { qr := &pb.QueryResponse{} proto.Unmarshal(reqMsg.Payload, qr) - return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: putils.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid} + return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: putils.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid, ChannelId: chainID} } queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { qr := &pb.QueryResponse{} proto.Unmarshal(reqMsg.Payload, qr) - return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: putils.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid} + return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: putils.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid, ChannelId: chainID} } var mkpeer []*mockpeer.MockResponse - mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Payload: putils.MarshalOrPanic(&pb.GetQueryResult{Collection: "", Query: "goodquery"}), Txid: txid}}) + mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Payload: putils.MarshalOrPanic(&pb.GetQueryResult{Collection: "", Query: "goodquery"}), Txid: txid, ChannelId: chainID}}) if collection == "" { mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, queryStateNextFunc}) mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, queryStateCloseFunc}) - mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid}}) + mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}) } else { // Get query results on private data is not yet implemented. - mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid}}) + mkpeer = append(mkpeer, &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid, ChannelId: chainID}}) } respSet := &mockpeer.MockResponseSet{errorFunc, nil, mkpeer} @@ -797,11 +797,11 @@ func getHistory(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCCom } respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Payload: putils.MarshalOrPanic(&pb.GetQueryResult{Query: "goodquery"}), Txid: txid}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Payload: putils.MarshalOrPanic(&pb.GetQueryResult{Query: "goodquery"}), Txid: txid, ChannelId: chainID}}, {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, queryStateNextFunc}, {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, queryStateNextFunc}, {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, queryStateCloseFunc}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid}}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: putils.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}}} cccid := ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) execCC(t, ctxt, ccSide, cccid, false, false, done, cis, respSet) @@ -926,6 +926,64 @@ func TestLaunchAndWaitLaunchError(t *testing.T) { } } +func cc2SameCC(t *testing.T, chainID, chainID2, ccname string, ccSide *mockpeer.MockCCComm) { + //first deploy the CC on chainID2 + chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"} + ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("deploycc")}, Decorations: nil} + cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} + + txid := util.GenerateUUID() + ctxt, txsim, sprop, prop := startTx(t, chainID2, cis, txid) + + //setup CheckACL calls + mockAclProvider.Reset() + mockAclProvider.On("CheckACL", aclmgmt.CC2CC, chainID2, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.LSCC_GETDEPSPEC, chainID2, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.LSCC_GETCCDATA, chainID2, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.PROPOSE, chainID2, sprop).Return(nil) + + cccid := ccprovider.NewCCContext(chainID2, ccname, "0", txid, false, sprop, prop) + + deployCC(t, ctxt, cccid, cis.ChaincodeSpec) + + //commit + endTx(t, cccid, txsim, cis) + + done := setuperror() + + errorFunc := func(ind int, err error) { + done <- err + } + + //now for the test - call the same cc on a different channel(should succeed), call the same cc on the same channel(should fail) + //Note the error "Another request pending for this Txid. Cannot process." in the logs under TX "cctosamecctx" + ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} + cis = &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} + txid = util.GenerateUUID() + ctxt, txsim, sprop, prop = startTx(t, chainID, cis, txid) + + mockAclProvider.On("CheckACL", aclmgmt.CC2CC, chainID, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.LSCC_GETDEPSPEC, chainID, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.LSCC_GETCCDATA, chainID, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.PROPOSE, chainID, sprop).Return(nil) + + mockAclProvider.On("CheckACL", aclmgmt.CC2CC, chainID2, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.LSCC_GETDEPSPEC, chainID2, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.LSCC_GETCCDATA, chainID2, sprop).Return(nil) + mockAclProvider.On("CheckACL", aclmgmt.PROPOSE, chainID2, sprop).Return(nil) + + txid = "cctosamecctx" + respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: ccname + ":0/" + chainID2}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid, ChannelId: chainID}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: putils.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: ccname + ":0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte{}}}}), Txid: txid, ChannelId: chainID}}}} + + cccid = ccprovider.NewCCContext(chainID, ccname, "0", txid, false, sprop, prop) + + execCC(t, ctxt, ccSide, cccid, false, true, done, cis, respSet) + + endTx(t, cccid, txsim, cis) +} + func TestCCFramework(t *testing.T) { //register 2 channels chainID := "mockchainid" @@ -939,7 +997,7 @@ func TestCCFramework(t *testing.T) { ccname := "shimTestCC" //starts and registers the CC - _, ccSide := startCC(t, ccname) + _, ccSide := startCC(t, chainID, ccname) if ccSide == nil { t.Fatalf("start up failed") } @@ -966,6 +1024,9 @@ func TestCCFramework(t *testing.T) { //call's query state range getQueryStateByRange(t, "", chainID, ccname, ccSide) + //call's cc2cc on the same chaincode only call to chainID2 should succeed + cc2SameCC(t, chainID, chainID2, ccname, ccSide) + //call's cc2cc (variation with syscc calls) cc2cc(t, chainID, chainID2, ccname, ccSide) diff --git a/core/chaincode/exectransaction.go b/core/chaincode/exectransaction.go index a9c349627b6..5e830727a7b 100644 --- a/core/chaincode/exectransaction.go +++ b/core/chaincode/exectransaction.go @@ -50,7 +50,7 @@ func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{} cMsg.Decorations = cccid.ProposalDecorations var ccMsg *pb.ChaincodeMessage - ccMsg, err = createCCMessage(cctyp, cccid.TxID, cMsg) + ccMsg, err = createCCMessage(cctyp, cccid.ChainID, cccid.TxID, cMsg) if err != nil { return nil, nil, errors.WithMessage(err, "failed to create chaincode message") } diff --git a/core/chaincode/handler.go b/core/chaincode/handler.go index 0b265e27ccb..54815bc3e44 100644 --- a/core/chaincode/handler.go +++ b/core/chaincode/handler.go @@ -161,56 +161,66 @@ func (handler *Handler) serialSendAsync(msg *pb.ChaincodeMessage, errc chan erro }() } +//transaction context id should be composed of chainID and txid. While +//needed for CC-2-CC, it also allows users to concurrently send proposals +//with the same TXID to the SAME CC on multiple channels +func (handler *Handler) getTxCtxId(chainID string, txid string) string { + return chainID + txid +} + 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, errors.Errorf("cannot create notifier for txid: %s", txid) } handler.Lock() defer handler.Unlock() - if handler.txCtxs[txid] != nil { - return nil, errors.Errorf("txid: %s exists", txid) + txCtxID := handler.getTxCtxId(chainID, txid) + if handler.txCtxs[txCtxID] != nil { + return nil, errors.Errorf("txid: %s(%s) exists", txid, chainID) } txctx := &transactionContext{chainID: chainID, signedProp: signedProp, proposal: prop, responseNotifier: make(chan *pb.ChaincodeMessage, 1), queryIteratorMap: make(map[string]commonledger.ResultsIterator)} - handler.txCtxs[txid] = txctx + handler.txCtxs[txCtxID] = txctx txctx.txsimulator = getTxSimulator(ctxt) txctx.historyQueryExecutor = getHistoryQueryExecutor(ctxt) return txctx, nil } -func (handler *Handler) getTxContext(txid string) *transactionContext { +func (handler *Handler) getTxContext(chainID, txid string) *transactionContext { handler.Lock() defer handler.Unlock() - return handler.txCtxs[txid] + txCtxID := handler.getTxCtxId(chainID, txid) + return handler.txCtxs[txCtxID] } -func (handler *Handler) deleteTxContext(txid string) { +func (handler *Handler) deleteTxContext(chainID, txid string) { handler.Lock() defer handler.Unlock() + txCtxID := handler.getTxCtxId(chainID, txid) if handler.txCtxs != nil { - delete(handler.txCtxs, txid) + delete(handler.txCtxs, txCtxID) } } -func (handler *Handler) putQueryIterator(txContext *transactionContext, txid string, +func (handler *Handler) putQueryIterator(txContext *transactionContext, queryID string, queryIterator commonledger.ResultsIterator) { handler.Lock() defer handler.Unlock() - txContext.queryIteratorMap[txid] = queryIterator + txContext.queryIteratorMap[queryID] = queryIterator } -func (handler *Handler) getQueryIterator(txContext *transactionContext, txid string) commonledger.ResultsIterator { +func (handler *Handler) getQueryIterator(txContext *transactionContext, queryID string) commonledger.ResultsIterator { handler.Lock() defer handler.Unlock() - return txContext.queryIteratorMap[txid] + return txContext.queryIteratorMap[queryID] } -func (handler *Handler) deleteQueryIterator(txContext *transactionContext, txid string) { +func (handler *Handler) deleteQueryIterator(txContext *transactionContext, queryID string) { handler.Lock() defer handler.Unlock() - delete(txContext.queryIteratorMap, txid) + delete(txContext.queryIteratorMap, queryID) } // Check if the transactor is allow to call this chaincode on this channel @@ -431,26 +441,28 @@ func newChaincodeSupportHandler(chaincodeSupport *ChaincodeSupport, peerChatStre return v } -func (handler *Handler) createTXIDEntry(txid string) bool { +func (handler *Handler) createTXIDEntry(channelID, txid string) bool { if handler.txidMap == nil { return false } handler.Lock() defer handler.Unlock() - if handler.txidMap[txid] { + txCtxID := handler.getTxCtxId(channelID, txid) + if handler.txidMap[txCtxID] { return false } - handler.txidMap[txid] = true - return handler.txidMap[txid] + handler.txidMap[txCtxID] = true + return handler.txidMap[txCtxID] } -func (handler *Handler) deleteTXIDEntry(txid string) { +func (handler *Handler) deleteTXIDEntry(channelID, txid string) { handler.Lock() defer handler.Unlock() + txCtxID := handler.getTxCtxId(channelID, txid) if handler.txidMap != nil { - delete(handler.txidMap, txid) + delete(handler.txidMap, txCtxID) } else { - chaincodeLogger.Warningf("TXID %s not found!", txid) + chaincodeLogger.Warningf("TXID %s not found!", txCtxID) } } @@ -520,11 +532,12 @@ func (handler *Handler) beforeRegisterEvent(e *fsm.Event, state string) { func (handler *Handler) notify(msg *pb.ChaincodeMessage) { handler.Lock() defer handler.Unlock() - tctx := handler.txCtxs[msg.Txid] + txCtxID := handler.getTxCtxId(msg.ChannelId, msg.Txid) + tctx := handler.txCtxs[txCtxID] if tctx == nil { - chaincodeLogger.Debugf("notifier Txid:%s does not exist", msg.Txid) + chaincodeLogger.Debugf("notifier Txid:%s, channelID:%s does not exist", msg.Txid, msg.ChannelId) } else { - chaincodeLogger.Debugf("notifying Txid:%s", msg.Txid) + chaincodeLogger.Debugf("notifying Txid:%s, channelID:%s", msg.Txid, msg.ChannelId) tctx.responseNotifier <- msg // clean up queryIteratorMap @@ -560,13 +573,13 @@ func (handler *Handler) afterGetState(e *fsm.Event, state string) { } // is this a txid for which there is a valid txsim -func (handler *Handler) isValidTxSim(txid string, fmtStr string, args ...interface{}) (*transactionContext, *pb.ChaincodeMessage) { - txContext := handler.getTxContext(txid) +func (handler *Handler) isValidTxSim(channelID string, txid string, fmtStr string, args ...interface{}) (*transactionContext, *pb.ChaincodeMessage) { + txContext := handler.getTxContext(channelID, txid) if txContext == nil || txContext.txsimulator == nil { // Send error msg back to chaincode. No ledger context errStr := fmt.Sprintf(fmtStr, args...) chaincodeLogger.Errorf(errStr) - return nil, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(errStr), Txid: txid} + return nil, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(errStr), Txid: txid, ChannelId: channelID} } return txContext, nil } @@ -578,7 +591,7 @@ func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) { // the afterGetState function is exited. Interesting bug fix!! go func() { // Check if this is the unique state request from this chaincode txid - uniqueReq := handler.createTXIDEntry(msg.Txid) + uniqueReq := handler.createTXIDEntry(msg.ChannelId, msg.Txid) if !uniqueReq { // Drop this request chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.") @@ -587,11 +600,11 @@ func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) { var serialSendMsg *pb.ChaincodeMessage var txContext *transactionContext - txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, + txContext, serialSendMsg = handler.isValidTxSim(msg.ChannelId, msg.Txid, "[%s]No ledger context for GetState. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) defer func() { - handler.deleteTXIDEntry(msg.Txid) + handler.deleteTXIDEntry(msg.ChannelId, msg.Txid) chaincodeLogger.Debugf("[%s]handleGetState serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type) handler.serialSendAsync(serialSendMsg, nil) @@ -605,7 +618,7 @@ func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) { getState := &pb.GetState{} unmarshalErr := proto.Unmarshal(msg.Payload, getState) if unmarshalErr != nil { - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(unmarshalErr.Error()), Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(unmarshalErr.Error()), Txid: msg.Txid, ChannelId: msg.ChannelId} } chaincodeID := handler.getCCRootName() chaincodeLogger.Debugf("[%s] getting state for chaincode %s, key %s, channel %s", @@ -624,16 +637,16 @@ func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) { payload := []byte(err.Error()) chaincodeLogger.Errorf("[%s]Failed to get chaincode state(%s). Sending %s", shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} } else if res == nil { //The state object being requested does not exist chaincodeLogger.Debugf("[%s]No state associated with key: %s. Sending %s with an empty payload", shorttxid(msg.Txid), key, pb.ChaincodeMessage_RESPONSE) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId} } else { // Send response msg back to chaincode. GetState will not trigger event chaincodeLogger.Debugf("[%s]Got state. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_RESPONSE) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId} } }() @@ -660,7 +673,7 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) { // the afterGetStateByRange function is exited. Interesting bug fix!! go func() { // Check if this is the unique state request from this chaincode txid - uniqueReq := handler.createTXIDEntry(msg.Txid) + uniqueReq := handler.createTXIDEntry(msg.ChannelId, msg.Txid) if !uniqueReq { // Drop this request chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.") @@ -670,7 +683,7 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) { var serialSendMsg *pb.ChaincodeMessage defer func() { - handler.deleteTXIDEntry(msg.Txid) + handler.deleteTXIDEntry(msg.ChannelId, msg.Txid) chaincodeLogger.Debugf("[%s]handleGetStateByRange serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type) handler.serialSendAsync(serialSendMsg, nil) }() @@ -680,7 +693,7 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) { if unmarshalErr != nil { payload := []byte(unmarshalErr.Error()) chaincodeLogger.Errorf("Failed to unmarshall range query request. Sending %s", pb.ChaincodeMessage_ERROR) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} return } @@ -688,7 +701,7 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) { var txContext *transactionContext - txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for GetStateByRange. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) + txContext, serialSendMsg = handler.isValidTxSim(msg.ChannelId, msg.Txid, "[%s]No ledger context for GetStateByRange. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) if txContext == nil { return } @@ -701,7 +714,7 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) { } payload := []byte(err.Error()) chaincodeLogger.Errorf(errFmt, errArgs...) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} } var rangeIter commonledger.ResultsIterator var err error @@ -731,7 +744,7 @@ func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) { return } chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId} }() } @@ -797,7 +810,7 @@ func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) { // the afterGetStateByRange function is exited. Interesting bug fix!! go func() { // Check if this is the unique state request from this chaincode txid - uniqueReq := handler.createTXIDEntry(msg.Txid) + uniqueReq := handler.createTXIDEntry(msg.ChannelId, msg.Txid) if !uniqueReq { // Drop this request chaincodeLogger.Debug("Another state request pending for this Txid. Cannot process.") @@ -807,7 +820,7 @@ func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) { var serialSendMsg *pb.ChaincodeMessage defer func() { - handler.deleteTXIDEntry(msg.Txid) + handler.deleteTXIDEntry(msg.ChannelId, msg.Txid) chaincodeLogger.Debugf("[%s]handleQueryStateNext serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type) handler.serialSendAsync(serialSendMsg, nil) }() @@ -821,7 +834,7 @@ func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) { handler.deleteQueryIterator(txContext, queryStateNext.Id) } chaincodeLogger.Errorf(errFmt, errArgs...) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} } queryStateNext = &pb.QueryStateNext{} @@ -832,7 +845,7 @@ func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) { return } - txContext = handler.getTxContext(msg.Txid) + txContext = handler.getTxContext(msg.ChannelId, msg.Txid) if txContext == nil { errHandler([]byte("transaction context not found (timed out ?)"), nil, "[%s]Failed to get transaction context. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) return @@ -856,7 +869,7 @@ func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) { return } chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId} }() } @@ -882,7 +895,7 @@ func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) { // the afterGetStateByRange function is exited. Interesting bug fix!! go func() { // Check if this is the unique state request from this chaincode txid - uniqueReq := handler.createTXIDEntry(msg.Txid) + uniqueReq := handler.createTXIDEntry(msg.ChannelId, msg.Txid) if !uniqueReq { // Drop this request chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.") @@ -892,14 +905,14 @@ func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) { var serialSendMsg *pb.ChaincodeMessage defer func() { - handler.deleteTXIDEntry(msg.Txid) + handler.deleteTXIDEntry(msg.ChannelId, msg.Txid) chaincodeLogger.Debugf("[%s]handleQueryStateClose serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type) handler.serialSendAsync(serialSendMsg, nil) }() errHandler := func(payload []byte, errFmt string, errArgs ...interface{}) { chaincodeLogger.Errorf(errFmt, errArgs...) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} } queryStateClose := &pb.QueryStateClose{} @@ -909,7 +922,7 @@ func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) { return } - txContext := handler.getTxContext(msg.Txid) + txContext := handler.getTxContext(msg.ChannelId, msg.Txid) if txContext == nil { errHandler([]byte("transaction context not found (timed out ?)"), "[%s]Failed to get transaction context. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) return @@ -929,7 +942,7 @@ func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) { } chaincodeLogger.Debugf("Closed. Sending %s", pb.ChaincodeMessage_RESPONSE) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId} }() } @@ -955,7 +968,7 @@ func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage) { // the afterQueryState function is exited. Interesting bug fix!! go func() { // Check if this is the unique state request from this chaincode txid - uniqueReq := handler.createTXIDEntry(msg.Txid) + uniqueReq := handler.createTXIDEntry(msg.ChannelId, msg.Txid) if !uniqueReq { // Drop this request chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.") @@ -965,7 +978,7 @@ func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage) { var serialSendMsg *pb.ChaincodeMessage defer func() { - handler.deleteTXIDEntry(msg.Txid) + handler.deleteTXIDEntry(msg.ChannelId, msg.Txid) chaincodeLogger.Debugf("[%s]handleGetQueryResult serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type) handler.serialSendAsync(serialSendMsg, nil) }() @@ -979,7 +992,7 @@ func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage) { handler.deleteQueryIterator(txContext, iterID) } chaincodeLogger.Errorf(errFmt, errArgs...) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} } getQueryResult := &pb.GetQueryResult{} @@ -991,7 +1004,7 @@ func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage) { iterID = util.GenerateUUID() - txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for GetQueryResult. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) + txContext, serialSendMsg = handler.isValidTxSim(msg.ChannelId, msg.Txid, "[%s]No ledger context for GetQueryResult. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) if txContext == nil { return } @@ -1027,7 +1040,7 @@ func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage) { } chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId} }() } @@ -1053,7 +1066,7 @@ func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage) { // the afterQueryState function is exited. Interesting bug fix!! go func() { // Check if this is the unique state request from this chaincode txid - uniqueReq := handler.createTXIDEntry(msg.Txid) + uniqueReq := handler.createTXIDEntry(msg.ChannelId, msg.Txid) if !uniqueReq { // Drop this request chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.") @@ -1063,7 +1076,7 @@ func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage) { var serialSendMsg *pb.ChaincodeMessage defer func() { - handler.deleteTXIDEntry(msg.Txid) + handler.deleteTXIDEntry(msg.ChannelId, msg.Txid) chaincodeLogger.Debugf("[%s]handleGetHistoryForKey serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type) handler.serialSendAsync(serialSendMsg, nil) }() @@ -1077,7 +1090,7 @@ func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage) { handler.deleteQueryIterator(txContext, iterID) } chaincodeLogger.Errorf(errFmt, errArgs...) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} } getHistoryForKey := &pb.GetHistoryForKey{} @@ -1089,7 +1102,7 @@ func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage) { iterID = util.GenerateUUID() - txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for GetHistoryForKey. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) + txContext, serialSendMsg = handler.isValidTxSim(msg.ChannelId, msg.Txid, "[%s]No ledger context for GetHistoryForKey. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) if txContext == nil { return } @@ -1119,7 +1132,7 @@ func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage) { } chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) - serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid} + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId} }() } @@ -1137,20 +1150,20 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { msg, _ := e.Args[0].(*pb.ChaincodeMessage) chaincodeLogger.Debugf("[%s]state is %s", shorttxid(msg.Txid), state) // Check if this is the unique request from this chaincode txid - uniqueReq := handler.createTXIDEntry(msg.Txid) + uniqueReq := handler.createTXIDEntry(msg.ChannelId, msg.Txid) if !uniqueReq { // Drop this request - chaincodeLogger.Debug("Another request pending for this Txid. Cannot process.") + chaincodeLogger.Debugf("Another request pending for this CC: %s, Txid: %s, ChannelID: %s. Cannot process.", handler.ChaincodeID.Name, msg.Txid, msg.ChannelId) return } var triggerNextStateMsg *pb.ChaincodeMessage var txContext *transactionContext - txContext, triggerNextStateMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for %s. Sending %s", + txContext, triggerNextStateMsg = handler.isValidTxSim(msg.ChannelId, msg.Txid, "[%s]No ledger context for %s. Sending %s", shorttxid(msg.Txid), msg.Type.String(), pb.ChaincodeMessage_ERROR) defer func() { - handler.deleteTXIDEntry(msg.Txid) + handler.deleteTXIDEntry(msg.ChannelId, msg.Txid) chaincodeLogger.Debugf("[%s]enterBusyState trigger event %s", shorttxid(triggerNextStateMsg.Txid), triggerNextStateMsg.Type) handler.triggerNextState(triggerNextStateMsg, true) @@ -1162,7 +1175,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { errHandler := func(payload []byte, errFmt string, errArgs ...interface{}) { chaincodeLogger.Errorf(errFmt, errArgs...) - triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChannelId: msg.ChannelId} } chaincodeID := handler.getCCRootName() @@ -1234,13 +1247,13 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { if lgr == nil { payload := "Failed to find ledger for called channel " + calledCcIns.ChainID triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, - Payload: []byte(payload), Txid: msg.Txid} + Payload: []byte(payload), Txid: msg.Txid, ChannelId: msg.ChannelId} return } txsim2, err2 := lgr.NewTxSimulator(msg.Txid) if err2 != nil { triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, - Payload: []byte(err2.Error()), Txid: msg.Txid} + Payload: []byte(err2.Error()), Txid: msg.Txid, ChannelId: msg.ChannelId} return } defer txsim2.Done() @@ -1294,7 +1307,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { // TODO: Need to handle timeout correctly timeout := time.Duration(30000) * time.Millisecond - ccMsg, _ := createCCMessage(pb.ChaincodeMessage_TRANSACTION, msg.Txid, chaincodeInput) + ccMsg, _ := createCCMessage(pb.ChaincodeMessage_TRANSACTION, calledCcIns.ChainID, msg.Txid, chaincodeInput) // Execute the chaincode... this CANNOT be an init at least for now response, execErr := handler.chaincodeSupport.Execute(ctxt, cccid, ccMsg, timeout) @@ -1316,7 +1329,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { // Send response msg back to chaincode. chaincodeLogger.Debugf("[%s]Completed %s. Sending %s", shorttxid(msg.Txid), msg.Type.String(), pb.ChaincodeMessage_RESPONSE) - triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid} + triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId} }() } @@ -1371,7 +1384,7 @@ func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, } chaincodeLogger.Debug("sending READY") - ccMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: txid} + ccMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: txid, ChannelId: chainID} //if security is disabled the context elements will just be nil if err := handler.setChaincodeProposal(signedProp, prop, ccMsg); err != nil { diff --git a/core/chaincode/shim/chaincode.go b/core/chaincode/shim/chaincode.go index 9d91f8e6111..874ef46a12f 100644 --- a/core/chaincode/shim/chaincode.go +++ b/core/chaincode/shim/chaincode.go @@ -51,6 +51,7 @@ const ( // APIs. type ChaincodeStub struct { TxID string + ChannelId string chaincodeEvent *pb.ChaincodeEvent args [][]byte handler *Handler @@ -347,8 +348,9 @@ func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode // -- init stub --- // ChaincodeInvocation functionality -func (stub *ChaincodeStub) init(handler *Handler, txid string, input *pb.ChaincodeInput, signedProposal *pb.SignedProposal) error { +func (stub *ChaincodeStub) init(handler *Handler, channelId string, txid string, input *pb.ChaincodeInput, signedProposal *pb.SignedProposal) error { stub.TxID = txid + stub.ChannelId = channelId stub.args = input.Args stub.handler = handler stub.signedProposal = signedProposal @@ -380,11 +382,16 @@ func (stub *ChaincodeStub) init(handler *Handler, txid string, input *pb.Chainco return nil } -// GetTxID returns the transaction ID +// GetTxID returns the transaction ID for the proposal func (stub *ChaincodeStub) GetTxID() string { return stub.TxID } +// GetChannelID returns the channel for the proposal +func (stub *ChaincodeStub) GetChannelID() string { + return stub.ChannelId +} + func (stub *ChaincodeStub) GetDecorations() map[string][]byte { return stub.decorations } @@ -397,7 +404,7 @@ func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte, if channel != "" { chaincodeName = chaincodeName + "/" + channel } - return stub.handler.handleInvokeChaincode(chaincodeName, args, stub.TxID) + return stub.handler.handleInvokeChaincode(chaincodeName, args, stub.ChannelId, stub.TxID) } // --------- State functions ---------- @@ -406,7 +413,7 @@ func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte, func (stub *ChaincodeStub) GetState(key string) ([]byte, error) { // Access public data by setting the collection to empty string collection := "" - return stub.handler.handleGetState(collection, key, stub.TxID) + return stub.handler.handleGetState(collection, key, stub.ChannelId, stub.TxID) } // PutState documentation can be found in interfaces.go @@ -416,31 +423,32 @@ func (stub *ChaincodeStub) PutState(key string, value []byte) error { } // Access public data by setting the collection to empty string collection := "" - return stub.handler.handlePutState(collection, key, value, stub.TxID) + return stub.handler.handlePutState(collection, key, value, stub.ChannelId, stub.TxID) } // GetQueryResult documentation can be found in interfaces.go func (stub *ChaincodeStub) GetQueryResult(query string) (StateQueryIteratorInterface, error) { // Access public data by setting the collection to empty string collection := "" - response, err := stub.handler.handleGetQueryResult(collection, query, stub.TxID) + response, err := stub.handler.handleGetQueryResult(collection, query, stub.ChannelId, stub.TxID) if err != nil { return nil, err } - return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil + return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.ChannelId, stub.TxID, response, 0}}, nil } // DelState documentation can be found in interfaces.go func (stub *ChaincodeStub) DelState(key string) error { // Access public data by setting the collection to empty string collection := "" - return stub.handler.handleDelState(collection, key, stub.TxID) + return stub.handler.handleDelState(collection, key, stub.ChannelId, stub.TxID) } // CommonIterator documentation can be found in interfaces.go type CommonIterator struct { handler *Handler - uuid string + channelId string + txid string response *pb.QueryResponse currentLoc int } @@ -463,11 +471,11 @@ const ( ) func (stub *ChaincodeStub) handleGetStateByRange(collection, startKey, endKey string) (StateQueryIteratorInterface, error) { - response, err := stub.handler.handleGetStateByRange(collection, startKey, endKey, stub.TxID) + response, err := stub.handler.handleGetStateByRange(collection, startKey, endKey, stub.ChannelId, stub.TxID) if err != nil { return nil, err } - return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil + return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.ChannelId, stub.TxID, response, 0}}, nil } // GetStateByRange documentation can be found in interfaces.go @@ -484,11 +492,11 @@ func (stub *ChaincodeStub) GetStateByRange(startKey, endKey string) (StateQueryI // GetHistoryForKey documentation can be found in interfaces.go func (stub *ChaincodeStub) GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error) { - response, err := stub.handler.handleGetHistoryForKey(key, stub.TxID) + response, err := stub.handler.handleGetHistoryForKey(key, stub.ChannelId, stub.TxID) if err != nil { return nil, err } - return &HistoryQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil + return &HistoryQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.ChannelId, stub.TxID, response, 0}}, nil } //CreateCompositeKey documentation can be found in interfaces.go @@ -617,7 +625,7 @@ func (iter *CommonIterator) getResultFromBytes(queryResultBytes *pb.QueryResultB } func (iter *CommonIterator) fetchNextQueryResult() error { - if response, err := iter.handler.handleQueryStateNext(iter.response.Id, iter.uuid); err == nil { + if response, err := iter.handler.handleQueryStateNext(iter.response.Id, iter.channelId, iter.txid); err == nil { iter.currentLoc = 0 iter.response = response return nil @@ -660,7 +668,7 @@ func (iter *CommonIterator) nextResult(rType resultType) (commonledger.QueryResu // Close documentation can be found in interfaces.go func (iter *CommonIterator) Close() error { - _, err := iter.handler.handleQueryStateClose(iter.response.Id, iter.uuid) + _, err := iter.handler.handleQueryStateClose(iter.response.Id, iter.channelId, iter.txid) return err } diff --git a/core/chaincode/shim/chaincode_experimental.go b/core/chaincode/shim/chaincode_experimental.go index 3db423be221..bded1dc8b08 100644 --- a/core/chaincode/shim/chaincode_experimental.go +++ b/core/chaincode/shim/chaincode_experimental.go @@ -19,7 +19,7 @@ func (stub *ChaincodeStub) GetPrivateData(collection string, key string) ([]byte if collection == "" { return nil, fmt.Errorf("collection must not be an empty string") } - return stub.handler.handleGetState(collection, key, stub.TxID) + return stub.handler.handleGetState(collection, key, stub.ChannelId, stub.TxID) } // PutPrivateData documentation can be found in interfaces.go @@ -30,7 +30,7 @@ func (stub *ChaincodeStub) PutPrivateData(collection string, key string, value [ if key == "" { return fmt.Errorf("key must not be an empty string") } - return stub.handler.handlePutState(collection, key, value, stub.TxID) + return stub.handler.handlePutState(collection, key, value, stub.ChannelId, stub.TxID) } // DelPrivateData documentation can be found in interfaces.go @@ -38,7 +38,7 @@ func (stub *ChaincodeStub) DelPrivateData(collection string, key string) error { if collection == "" { return fmt.Errorf("collection must not be an empty string") } - return stub.handler.handleDelState(collection, key, stub.TxID) + return stub.handler.handleDelState(collection, key, stub.ChannelId, stub.TxID) } // GetPrivateDataByRange documentation can be found in interfaces.go @@ -72,9 +72,9 @@ func (stub *ChaincodeStub) GetPrivateDataQueryResult(collection, query string) ( if collection == "" { return nil, fmt.Errorf("collection must not be an empty string") } - response, err := stub.handler.handleGetQueryResult(collection, query, stub.TxID) + response, err := stub.handler.handleGetQueryResult(collection, query, stub.ChannelId, stub.TxID) if err != nil { return nil, err } - return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil + return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, stub.ChannelId, response, 0}}, nil } diff --git a/core/chaincode/shim/handler.go b/core/chaincode/shim/handler.go index 53b648213d3..fa95c224edf 100644 --- a/core/chaincode/shim/handler.go +++ b/core/chaincode/shim/handler.go @@ -90,17 +90,25 @@ func (handler *Handler) serialSendAsync(msg *pb.ChaincodeMessage, errc chan erro }() } -func (handler *Handler) createChannel(txid string) (chan pb.ChaincodeMessage, error) { +//transaction context id should be composed of chainID and txid. While +//needed for CC-2-CC, it also allows users to concurrently send proposals +//with the same TXID to a CC on two multiple channels +func (handler *Handler) getTxCtxId(chainID string, txid string) string { + return chainID + txid +} + +func (handler *Handler) createChannel(channelID, txid string) (chan pb.ChaincodeMessage, error) { handler.Lock() defer handler.Unlock() if handler.responseChannel == nil { return nil, errors.Errorf("[%s]cannot create response channel", shorttxid(txid)) } - if handler.responseChannel[txid] != nil { - return nil, errors.Errorf("[%s]channel exists", shorttxid(txid)) + txCtxID := handler.getTxCtxId(channelID, txid) + if handler.responseChannel[txCtxID] != nil { + return nil, errors.Errorf("[%s]channel exists", shorttxid(txCtxID)) } c := make(chan pb.ChaincodeMessage) - handler.responseChannel[txid] = c + handler.responseChannel[txCtxID] = c return c, nil } @@ -110,12 +118,13 @@ func (handler *Handler) sendChannel(msg *pb.ChaincodeMessage) error { if handler.responseChannel == nil { return errors.Errorf("[%s]Cannot send message response channel", shorttxid(msg.Txid)) } - if handler.responseChannel[msg.Txid] == nil { + txCtxID := handler.getTxCtxId(msg.ChannelId, msg.Txid) + if handler.responseChannel[txCtxID] == nil { return errors.Errorf("[%s]sendChannel does not exist", shorttxid(msg.Txid)) } chaincodeLogger.Debugf("[%s]before send", shorttxid(msg.Txid)) - handler.responseChannel[msg.Txid] <- *msg + handler.responseChannel[txCtxID] <- *msg chaincodeLogger.Debugf("[%s]after send", shorttxid(msg.Txid)) return nil @@ -149,11 +158,12 @@ func (handler *Handler) sendReceive(msg *pb.ChaincodeMessage, c chan pb.Chaincod } } -func (handler *Handler) deleteChannel(txid string) { +func (handler *Handler) deleteChannel(channelID, txid string) { handler.Lock() defer handler.Unlock() if handler.responseChannel != nil { - delete(handler.responseChannel, txid) + txCtxID := handler.getTxCtxId(channelID, txid) + delete(handler.responseChannel, txCtxID) } } @@ -222,7 +232,7 @@ func (handler *Handler) handleInit(msg *pb.ChaincodeMessage) { payload = []byte(err.Error()) } chaincodeLogger.Errorf(errFmt, args...) - return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChaincodeEvent: ce} + return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChaincodeEvent: ce, ChannelId: msg.ChannelId} } return nil } @@ -236,7 +246,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) - err := stub.init(handler, msg.Txid, input, msg.Proposal) + err := stub.init(handler, msg.ChannelId, msg.Txid, input, msg.Proposal) if nextStateMsg = errFunc(err, nil, stub.chaincodeEvent, "[%s]Init get error response [%s]. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR.String()); nextStateMsg != nil { return } @@ -257,7 +267,7 @@ func (handler *Handler) handleInit(msg *pb.ChaincodeMessage) { } // Send COMPLETED message to chaincode support and change state - nextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: resBytes, Txid: msg.Txid, ChaincodeEvent: stub.chaincodeEvent} + nextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: resBytes, Txid: msg.Txid, ChaincodeEvent: stub.chaincodeEvent, ChannelId: stub.ChannelId} chaincodeLogger.Debugf("[%s]Init succeeded. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_COMPLETED) }() } @@ -296,7 +306,7 @@ func (handler *Handler) handleTransaction(msg *pb.ChaincodeMessage) { if err != nil { payload := []byte(err.Error()) chaincodeLogger.Errorf(errStr, args...) - return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChaincodeEvent: ce} + return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid, ChaincodeEvent: ce, ChannelId: msg.ChannelId} } return nil } @@ -311,7 +321,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) - err := stub.init(handler, msg.Txid, input, msg.Proposal) + err := stub.init(handler, msg.ChannelId, msg.Txid, input, msg.Proposal) if nextStateMsg = errFunc(err, stub.chaincodeEvent, "[%s]Transaction execution failed. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR.String()); nextStateMsg != nil { return } @@ -326,7 +336,7 @@ func (handler *Handler) handleTransaction(msg *pb.ChaincodeMessage) { // Send COMPLETED message to chaincode support and change state chaincodeLogger.Debugf("[%s]Transaction completed. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_COMPLETED) - nextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: resBytes, Txid: msg.Txid, ChaincodeEvent: stub.chaincodeEvent} + nextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: resBytes, Txid: msg.Txid, ChaincodeEvent: stub.chaincodeEvent, ChannelId: stub.ChannelId} }() } @@ -378,29 +388,29 @@ func (handler *Handler) afterError(e *fsm.Event) { // callPeerWithChaincodeMsg sends a chaincode message (for e.g., GetState along with the key) to the peer for a given txid // and receives the response. -func (handler *Handler) callPeerWithChaincodeMsg(msg *pb.ChaincodeMessage, txid string) (pb.ChaincodeMessage, error) { +func (handler *Handler) callPeerWithChaincodeMsg(msg *pb.ChaincodeMessage, channelID, txid string) (pb.ChaincodeMessage, error) { // Create the channel on which to communicate the response from the peer var respChan chan pb.ChaincodeMessage var err error - if respChan, err = handler.createChannel(txid); err != nil { + if respChan, err = handler.createChannel(channelID, txid); err != nil { return pb.ChaincodeMessage{}, err } - defer handler.deleteChannel(txid) + defer handler.deleteChannel(channelID, txid) return handler.sendReceive(msg, respChan) } // TODO: Implement a method to get multiple keys at a time [FAB-1244] // handleGetState communicates with the peer to fetch the requested state information from the ledger. -func (handler *Handler) handleGetState(collection string, key string, txid string) ([]byte, error) { +func (handler *Handler) handleGetState(collection string, key string, channelId string, txid string) ([]byte, error) { // Construct payload for GET_STATE payloadBytes, _ := proto.Marshal(&pb.GetState{Collection: collection, Key: key}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_STATE) - responseMsg, err := handler.callPeerWithChaincodeMsg(msg, txid) + responseMsg, err := handler.callPeerWithChaincodeMsg(msg, channelId, txid) if err != nil { return nil, errors.WithMessage(err, fmt.Sprintf("[%s]error sending GET_STATE", shorttxid(txid))) } @@ -422,15 +432,15 @@ func (handler *Handler) handleGetState(collection string, key string, txid strin // TODO: Implement a method to set multiple keys at a time [FAB-1244] // handlePutState communicates with the peer to put state information into the ledger. -func (handler *Handler) handlePutState(collection string, key string, value []byte, txid string) error { +func (handler *Handler) handlePutState(collection string, key string, value []byte, channelId string, txid string) error { // Construct payload for PUT_STATE payloadBytes, _ := proto.Marshal(&pb.PutState{Collection: collection, Key: key, Value: value}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_PUT_STATE) // Execute the request and get response - responseMsg, err := handler.callPeerWithChaincodeMsg(msg, txid) + responseMsg, err := handler.callPeerWithChaincodeMsg(msg, channelId, txid) if err != nil { return errors.WithMessage(err, fmt.Sprintf("[%s]error sending PUT_STATE", msg.Txid)) } @@ -452,15 +462,15 @@ func (handler *Handler) handlePutState(collection string, key string, value []by } // handleDelState communicates with the peer to delete a key from the state in the ledger. -func (handler *Handler) handleDelState(collection string, key string, txid string) error { +func (handler *Handler) handleDelState(collection string, key string, channelId string, txid string) error { //payloadBytes, _ := proto.Marshal(&pb.GetState{Collection: collection, Key: key}) payloadBytes, _ := proto.Marshal(&pb.DelState{Collection: collection, Key: key}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_STATE) // Execute the request and get response - responseMsg, err := handler.callPeerWithChaincodeMsg(msg, txid) + responseMsg, err := handler.callPeerWithChaincodeMsg(msg, channelId, txid) if err != nil { return errors.Errorf("[%s]error sending DEL_STATE %s", shorttxid(msg.Txid), pb.ChaincodeMessage_DEL_STATE) } @@ -480,15 +490,15 @@ func (handler *Handler) handleDelState(collection string, key string, txid strin return errors.Errorf("[%s]incorrect chaincode message %s received. Expecting %s or %s", shorttxid(responseMsg.Txid), responseMsg.Type, pb.ChaincodeMessage_RESPONSE, pb.ChaincodeMessage_ERROR) } -func (handler *Handler) handleGetStateByRange(collection, startKey, endKey string, txid string) (*pb.QueryResponse, error) { +func (handler *Handler) handleGetStateByRange(collection, startKey, endKey string, channelId string, txid string) (*pb.QueryResponse, error) { // Send GET_STATE_BY_RANGE message to peer chaincode support //we constructed a valid object. No need to check for error payloadBytes, _ := proto.Marshal(&pb.GetStateByRange{Collection: collection, StartKey: startKey, EndKey: endKey}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_STATE_BY_RANGE) - responseMsg, err := handler.callPeerWithChaincodeMsg(msg, txid) + responseMsg, err := handler.callPeerWithChaincodeMsg(msg, channelId, txid) if err != nil { return nil, errors.Errorf("[%s]error sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_STATE_BY_RANGE) } @@ -514,21 +524,21 @@ func (handler *Handler) handleGetStateByRange(collection, startKey, endKey strin return nil, errors.Errorf("incorrect chaincode message %s received. Expecting %s or %s", responseMsg.Type, pb.ChaincodeMessage_RESPONSE, pb.ChaincodeMessage_ERROR) } -func (handler *Handler) handleQueryStateNext(id, txid string) (*pb.QueryResponse, error) { +func (handler *Handler) handleQueryStateNext(id, channelId, txid string) (*pb.QueryResponse, error) { // Create the channel on which to communicate the response from validating peer var respChan chan pb.ChaincodeMessage var err error - if respChan, err = handler.createChannel(txid); err != nil { + if respChan, err = handler.createChannel(channelId, txid); err != nil { return nil, err } - defer handler.deleteChannel(txid) + defer handler.deleteChannel(channelId, txid) // Send QUERY_STATE_NEXT message to peer chaincode support //we constructed a valid object. No need to check for error payloadBytes, _ := proto.Marshal(&pb.QueryStateNext{Id: id}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_QUERY_STATE_NEXT) var responseMsg pb.ChaincodeMessage @@ -558,21 +568,21 @@ func (handler *Handler) handleQueryStateNext(id, txid string) (*pb.QueryResponse return nil, errors.Errorf("incorrect chaincode message %s received. Expecting %s or %s", responseMsg.Type, pb.ChaincodeMessage_RESPONSE, pb.ChaincodeMessage_ERROR) } -func (handler *Handler) handleQueryStateClose(id, txid string) (*pb.QueryResponse, error) { +func (handler *Handler) handleQueryStateClose(id, channelId, txid string) (*pb.QueryResponse, error) { // Create the channel on which to communicate the response from validating peer var respChan chan pb.ChaincodeMessage var err error - if respChan, err = handler.createChannel(txid); err != nil { + if respChan, err = handler.createChannel(channelId, txid); err != nil { return nil, err } - defer handler.deleteChannel(txid) + defer handler.deleteChannel(channelId, txid) // Send QUERY_STATE_CLOSE message to peer chaincode support //we constructed a valid object. No need to check for error payloadBytes, _ := proto.Marshal(&pb.QueryStateClose{Id: id}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_QUERY_STATE_CLOSE) var responseMsg pb.ChaincodeMessage @@ -602,15 +612,15 @@ func (handler *Handler) handleQueryStateClose(id, txid string) (*pb.QueryRespons return nil, errors.Errorf("incorrect chaincode message %s received. Expecting %s or %s", responseMsg.Type, pb.ChaincodeMessage_RESPONSE, pb.ChaincodeMessage_ERROR) } -func (handler *Handler) handleGetQueryResult(collection string, query string, txid string) (*pb.QueryResponse, error) { +func (handler *Handler) handleGetQueryResult(collection string, query string, channelId string, txid string) (*pb.QueryResponse, error) { // Send GET_QUERY_RESULT message to peer chaincode support //we constructed a valid object. No need to check for error payloadBytes, _ := proto.Marshal(&pb.GetQueryResult{Collection: collection, Query: query}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_QUERY_RESULT) - responseMsg, err := handler.callPeerWithChaincodeMsg(msg, txid) + responseMsg, err := handler.callPeerWithChaincodeMsg(msg, channelId, txid) if err != nil { return nil, errors.Errorf("[%s]error sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_QUERY_RESULT) } @@ -636,21 +646,21 @@ func (handler *Handler) handleGetQueryResult(collection string, query string, tx return nil, errors.Errorf("incorrect chaincode message %s received. Expecting %s or %s", responseMsg.Type, pb.ChaincodeMessage_RESPONSE, pb.ChaincodeMessage_ERROR) } -func (handler *Handler) handleGetHistoryForKey(key string, txid string) (*pb.QueryResponse, error) { +func (handler *Handler) handleGetHistoryForKey(key string, channelId string, txid string) (*pb.QueryResponse, error) { // Create the channel on which to communicate the response from validating peer var respChan chan pb.ChaincodeMessage var err error - if respChan, err = handler.createChannel(txid); err != nil { + if respChan, err = handler.createChannel(channelId, txid); err != nil { return nil, err } - defer handler.deleteChannel(txid) + defer handler.deleteChannel(channelId, txid) // Send GET_HISTORY_FOR_KEY message to peer chaincode support //we constructed a valid object. No need to check for error payloadBytes, _ := proto.Marshal(&pb.GetHistoryForKey{Key: key}) - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_HISTORY_FOR_KEY) var responseMsg pb.ChaincodeMessage @@ -685,21 +695,21 @@ func (handler *Handler) createResponse(status int32, payload []byte) pb.Response } // handleInvokeChaincode communicates with the peer to invoke another chaincode. -func (handler *Handler) handleInvokeChaincode(chaincodeName string, args [][]byte, txid string) pb.Response { +func (handler *Handler) handleInvokeChaincode(chaincodeName string, args [][]byte, channelId string, txid string) pb.Response { //we constructed a valid object. No need to check for error payloadBytes, _ := proto.Marshal(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: chaincodeName}, Input: &pb.ChaincodeInput{Args: args}}) // Create the channel on which to communicate the response from validating peer var respChan chan pb.ChaincodeMessage var err error - if respChan, err = handler.createChannel(txid); err != nil { + if respChan, err = handler.createChannel(channelId, txid); err != nil { return handler.createResponse(ERROR, []byte(err.Error())) } - defer handler.deleteChannel(txid) + defer handler.deleteChannel(channelId, txid) // Send INVOKE_CHAINCODE message to peer chaincode support - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: payloadBytes, Txid: txid} + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: payloadBytes, Txid: txid, ChannelId: channelId} chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_INVOKE_CHAINCODE) var responseMsg pb.ChaincodeMessage @@ -747,7 +757,7 @@ func (handler *Handler) handleMessage(msg *pb.ChaincodeMessage) error { chaincodeLogger.Debugf("[%s]Handling ChaincodeMessage of type: %s(state:%s)", shorttxid(msg.Txid), msg.Type, handler.FSM.Current()) if handler.FSM.Cannot(msg.Type.String()) { err := errors.Errorf("[%s]chaincode handler FSM cannot handle message (%s) with payload size (%d) while in state: %s", msg.Txid, msg.Type.String(), len(msg.Payload), handler.FSM.Current()) - handler.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(err.Error()), Txid: msg.Txid}) + handler.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(err.Error()), Txid: msg.Txid, ChannelId: msg.ChannelId}) return err } err := handler.FSM.Event(msg.Type.String(), msg) diff --git a/core/chaincode/shim/interfaces_experimental.go b/core/chaincode/shim/interfaces_experimental.go index b3529dcd7fa..f8cb5af9550 100644 --- a/core/chaincode/shim/interfaces_experimental.go +++ b/core/chaincode/shim/interfaces_experimental.go @@ -55,6 +55,12 @@ type ChaincodeStubInterface interface { // in protos/common/common.proto) GetTxID() string + // GetChannelID returns the channel the proposal is sent to for chaincode to process. + // This would be the channel_id of the transaction proposal (see ChannelHeader + // in protos/common/common.proto) except where the chaincode is calling another on + // a different channel + GetChannelID() string + // InvokeChaincode locally calls the specified chaincode `Invoke` using the // same transaction context; that is, chaincode calling chaincode doesn't // create a new transaction message. diff --git a/core/chaincode/shim/interfaces_stable.go b/core/chaincode/shim/interfaces_stable.go index b629fa3b82e..0f36a34280f 100644 --- a/core/chaincode/shim/interfaces_stable.go +++ b/core/chaincode/shim/interfaces_stable.go @@ -55,6 +55,12 @@ type ChaincodeStubInterface interface { // in protos/common/common.proto) GetTxID() string + // GetChannelID returns the channel the proposal is sent to for chaincode to process. + // This would be the channel_id of the transaction proposal (see ChannelHeader + // in protos/common/common.proto) except where the chaincode is calling another on + // a different channel + GetChannelID() string + // InvokeChaincode locally calls the specified chaincode `Invoke` using the // same transaction context; that is, chaincode calling chaincode doesn't // create a new transaction message. diff --git a/core/chaincode/shim/mockstub.go b/core/chaincode/shim/mockstub.go index 52aff2c3c45..e0db3267eb7 100644 --- a/core/chaincode/shim/mockstub.go +++ b/core/chaincode/shim/mockstub.go @@ -54,12 +54,19 @@ type MockStub struct { // mocked signedProposal signedProposal *pb.SignedProposal + + // stores a channel ID of the proposal + ChannelID string } func (stub *MockStub) GetTxID() string { return stub.TxID } +func (stub *MockStub) GetChannelID() string { + return stub.ChannelID +} + func (stub *MockStub) GetArgs() [][]byte { return stub.args } diff --git a/core/chaincode/shim/mockstub_test.go b/core/chaincode/shim/mockstub_test.go index 6f511da9130..35390fa780e 100644 --- a/core/chaincode/shim/mockstub_test.go +++ b/core/chaincode/shim/mockstub_test.go @@ -249,6 +249,7 @@ func TestMockMock(t *testing.T) { stub.GetStringArgs() stub.GetFunctionAndParameters() stub.GetTxID() + stub.GetChannelID() stub.MockInvoke("id", nil) stub.MockInvokeWithSignedProposal("id", nil, nil) stub.DelState("dummy") diff --git a/core/chaincode/shim/shim_test.go b/core/chaincode/shim/shim_test.go index df7b220bbd4..8084e029aed 100644 --- a/core/chaincode/shim/shim_test.go +++ b/core/chaincode/shim/shim_test.go @@ -582,100 +582,102 @@ func TestInvoke(t *testing.T) { //wait for init processDone(t, done, false) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1"}) + channelId := "testchannel" + + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1", ChannelId: channelId}) ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("A"), []byte("100"), []byte("B"), []byte("200")}, Decorations: nil} payload := utils.MarshalOrPanic(ci) respSet := &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) //use the payload computed from prev init - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2", ChannelId: channelId}) //wait for done processDone(t, done, false) //good invoke respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("100"), Txid: "3"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("200"), Txid: "3"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "3"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "3"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("100"), Txid: "3", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("200"), Txid: "3", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "3", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "3", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3", ChannelId: channelId}) //wait for done processDone(t, done, false) //bad put respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("100"), Txid: "3a"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("200"), Txid: "3a"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "3a"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3a"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3a", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("100"), Txid: "3a", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3a", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("200"), Txid: "3a", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3a", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "3a", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3a", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3a"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3a", ChannelId: channelId}) //wait for done processDone(t, done, false) //bad get respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "3b"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3b"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3b", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "3b", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3b", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3b"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3b", ChannelId: channelId}) //wait for done processDone(t, done, false) //bad delete respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Txid: "4"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "4"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Txid: "4", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "4", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("delete"), []byte("A")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4", ChannelId: channelId}) //wait for done processDone(t, done, false) //good delete respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Txid: "4a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "4a"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4a"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Txid: "4a", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "4a", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4a", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("delete"), []byte("A")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4a"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4a", ChannelId: channelId}) //wait for done processDone(t, done, false) //bad invoke respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "5"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "5", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("badinvoke")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "5"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "5", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -693,15 +695,15 @@ func TestInvoke(t *testing.T) { rangeQueryNext := &pb.QueryResponse{Results: nil, HasMore: false} respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "6"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "6"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "6", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "6", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -710,13 +712,13 @@ func TestInvoke(t *testing.T) { //create the response respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: "6a"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6a"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6a", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: "6a", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6a", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6a"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6a", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -725,15 +727,15 @@ func TestInvoke(t *testing.T) { //create the response respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6b"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6b"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "6b"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6b"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6b", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6b", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6b", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6b", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6b", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "6b", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6b", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6b"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6b", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -742,15 +744,15 @@ func TestInvoke(t *testing.T) { //create the response respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6c"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6c"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6c"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6c"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6c"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6c"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6c"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6c", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6c", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6c", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6c", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6c", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6c", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6c", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6c"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6c", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -764,15 +766,15 @@ func TestInvoke(t *testing.T) { payload = utils.MarshalOrPanic(historyQueryResponse) respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Txid: "7"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payload, Txid: "7"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "7"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "7"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "7"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "7"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "7"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Txid: "7", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payload, Txid: "7", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "7", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "7", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "7", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "7", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "7", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("historyq"), []byte("A")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "7"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "7", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -781,13 +783,13 @@ func TestInvoke(t *testing.T) { //create the response respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Txid: "7a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: "7a"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "7a"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Txid: "7a", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: "7a", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "7a", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("historyq"), []byte("A")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "7a"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "7a", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -805,15 +807,15 @@ func TestInvoke(t *testing.T) { rangeQueryNext = &pb.QueryResponse{Results: nil, HasMore: false} respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Txid: "8"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: getQRRespPayload, Txid: "8"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "8"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "8"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "8"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "8"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "8"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Txid: "8", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: getQRRespPayload, Txid: "8", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "8", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "8", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "8", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "8", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "8", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("richq"), []byte("A")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "8"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "8", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -821,13 +823,13 @@ func TestInvoke(t *testing.T) { //query result error respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Txid: "8a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: nil, Txid: "8a"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "8a"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Txid: "8a", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: nil, Txid: "8a", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "8a", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("richq"), []byte("A")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "8a"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "8a", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -867,7 +869,8 @@ func TestStartInProc(t *testing.T) { //wait for init processDone(t, done, false) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1"}) + channelId := "testchannel" + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1", ChannelId: channelId}) time.Sleep(1 * time.Second) peerSide.Quit() @@ -904,18 +907,20 @@ func TestCC2CC(t *testing.T) { //wait for init processDone(t, done, false) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1"}) + channelId := "testchannel" + + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1", ChannelId: channelId}) ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("A"), []byte("100"), []byte("B"), []byte("200")}, Decorations: nil} payload := utils.MarshalOrPanic(ci) respSet := &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) //use the payload computed from prev init - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2", ChannelId: channelId}) //wait for done processDone(t, done, false) @@ -924,24 +929,24 @@ func TestCC2CC(t *testing.T) { innerResp := utils.MarshalOrPanic(&pb.Response{Status: OK, Payload: []byte("CC2CC rocks")}) cc2ccresp := utils.MarshalOrPanic(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: innerResp}) respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: cc2ccresp, Txid: "3"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Txid: "3", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: cc2ccresp, Txid: "3", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("cc2cc"), []byte("othercc"), []byte("arg1"), []byte("arg2")}, Decorations: nil} payload = utils.MarshalOrPanic(ci) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3", ChannelId: channelId}) //wait for done processDone(t, done, false) //error response cc2cc respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Txid: "4"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: cc2ccresp, Txid: "4"}}, - {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4"}, nil}}} + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Txid: "4", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: cc2ccresp, Txid: "4", ChannelId: channelId}}, + {&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4", ChannelId: channelId}, nil}}} peerSide.SetResponses(respSet) - peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4"}) + peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4", ChannelId: channelId}) //wait for done processDone(t, done, false) diff --git a/protos/peer/chaincode_shim.pb.go b/protos/peer/chaincode_shim.pb.go index 32403aa21ab..6304cdb334c 100644 --- a/protos/peer/chaincode_shim.pb.go +++ b/protos/peer/chaincode_shim.pb.go @@ -100,6 +100,8 @@ type ChaincodeMessage struct { // This event is then stored (currently) // with Block.NonHashData.TransactionResult ChaincodeEvent *ChaincodeEvent `protobuf:"bytes,6,opt,name=chaincode_event,json=chaincodeEvent" json:"chaincode_event,omitempty"` + // channel id + ChannelId string `protobuf:"bytes,7,opt,name=channel_id,json=channelId" json:"channel_id,omitempty"` } func (m *ChaincodeMessage) Reset() { *m = ChaincodeMessage{} } @@ -149,6 +151,13 @@ func (m *ChaincodeMessage) GetChaincodeEvent() *ChaincodeEvent { return nil } +func (m *ChaincodeMessage) GetChannelId() string { + if m != nil { + return m.ChannelId + } + return "" +} + type GetState struct { Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` Collection string `protobuf:"bytes,2,opt,name=collection" json:"collection,omitempty"` @@ -503,56 +512,57 @@ var _ChaincodeSupport_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("peer/chaincode_shim.proto", fileDescriptor3) } var fileDescriptor3 = []byte{ - // 807 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x95, 0xdf, 0x6e, 0xe2, 0x46, - 0x14, 0xc6, 0x97, 0x3f, 0x49, 0xcc, 0x21, 0x81, 0xd9, 0xc9, 0x36, 0xf5, 0x22, 0xb5, 0xa5, 0x56, - 0x2f, 0xe8, 0x8d, 0x69, 0x69, 0x2f, 0x7a, 0xb1, 0x52, 0x45, 0xf0, 0x84, 0x58, 0x21, 0x36, 0x3b, - 0x76, 0x56, 0x4b, 0x6f, 0x2c, 0x03, 0xb3, 0xc6, 0xaa, 0x61, 0x5c, 0x7b, 0x58, 0xad, 0x9f, 0xb0, - 0x2f, 0xd3, 0x87, 0xa8, 0xc6, 0xc6, 0x84, 0x25, 0x8a, 0x56, 0xda, 0x2b, 0xe6, 0x3b, 0xe7, 0x77, - 0xbe, 0x73, 0x0e, 0x1a, 0x06, 0x78, 0x1d, 0x33, 0x96, 0xf4, 0x17, 0x2b, 0x3f, 0xdc, 0x2c, 0xf8, - 0x92, 0x79, 0xe9, 0x2a, 0x5c, 0xeb, 0x71, 0xc2, 0x05, 0xc7, 0xa7, 0xf9, 0x47, 0xda, 0xe9, 0x1c, - 0x21, 0xec, 0x23, 0xdb, 0x88, 0x82, 0xe9, 0x5c, 0xe6, 0xb9, 0x38, 0xe1, 0x31, 0x4f, 0xfd, 0x68, - 0x17, 0xfc, 0x21, 0xe0, 0x3c, 0x88, 0x58, 0x3f, 0x57, 0xf3, 0xed, 0x87, 0xbe, 0x08, 0xd7, 0x2c, - 0x15, 0xfe, 0x3a, 0x2e, 0x00, 0xed, 0xbf, 0x3a, 0xa0, 0x51, 0xe9, 0x77, 0xcf, 0xd2, 0xd4, 0x0f, - 0x18, 0xfe, 0x15, 0xea, 0x22, 0x8b, 0x99, 0x5a, 0xe9, 0x56, 0x7a, 0xad, 0xc1, 0x77, 0x05, 0x9a, - 0xea, 0xc7, 0x9c, 0xee, 0x66, 0x31, 0xa3, 0x39, 0x8a, 0xff, 0x80, 0xc6, 0xde, 0x5a, 0xad, 0x76, - 0x2b, 0xbd, 0xe6, 0xa0, 0xa3, 0x17, 0xcd, 0xf5, 0xb2, 0xb9, 0xee, 0x96, 0x04, 0x7d, 0x84, 0xb1, - 0x0a, 0x67, 0xb1, 0x9f, 0x45, 0xdc, 0x5f, 0xaa, 0xb5, 0x6e, 0xa5, 0x77, 0x4e, 0x4b, 0x89, 0x31, - 0xd4, 0xc5, 0xa7, 0x70, 0xa9, 0xd6, 0xbb, 0x95, 0x5e, 0x83, 0xe6, 0x67, 0x3c, 0x00, 0xa5, 0x5c, - 0x51, 0x3d, 0xc9, 0xdb, 0x5c, 0x95, 0xe3, 0x39, 0x61, 0xb0, 0x61, 0xcb, 0xe9, 0x2e, 0x4b, 0xf7, - 0x1c, 0xfe, 0x13, 0xda, 0x47, 0x5f, 0x99, 0x7a, 0xfa, 0x79, 0xe9, 0x7e, 0x33, 0x22, 0xb3, 0xb4, - 0xb5, 0xf8, 0x4c, 0x6b, 0xff, 0x56, 0xa1, 0x2e, 0x77, 0xc5, 0x17, 0xd0, 0x78, 0xb0, 0x0c, 0x72, - 0x63, 0x5a, 0xc4, 0x40, 0x2f, 0xf0, 0x39, 0x28, 0x94, 0x8c, 0x4d, 0xc7, 0x25, 0x14, 0x55, 0x70, - 0x0b, 0xa0, 0x54, 0xc4, 0x40, 0x55, 0xac, 0x40, 0xdd, 0xb4, 0x4c, 0x17, 0xd5, 0x70, 0x03, 0x4e, - 0x28, 0x19, 0x1a, 0x33, 0x54, 0xc7, 0x6d, 0x68, 0xba, 0x74, 0x68, 0x39, 0xc3, 0x91, 0x6b, 0xda, - 0x16, 0x3a, 0x91, 0x96, 0x23, 0xfb, 0x7e, 0x3a, 0x21, 0x2e, 0x31, 0xd0, 0xa9, 0x44, 0x09, 0xa5, - 0x36, 0x45, 0x67, 0x32, 0x33, 0x26, 0xae, 0xe7, 0xb8, 0x43, 0x97, 0x20, 0x45, 0xca, 0xe9, 0x43, - 0x29, 0x1b, 0x52, 0x1a, 0x64, 0xb2, 0x93, 0x80, 0x5f, 0x01, 0x32, 0xad, 0x77, 0xf6, 0x1d, 0xf1, - 0x46, 0xb7, 0x43, 0xd3, 0x1a, 0xd9, 0x06, 0x41, 0xcd, 0x62, 0x40, 0x67, 0x6a, 0x5b, 0x0e, 0x41, - 0x17, 0xf8, 0x0a, 0xf0, 0xde, 0xd0, 0xbb, 0x9e, 0x79, 0x74, 0x68, 0x8d, 0x09, 0x6a, 0xc9, 0x5a, - 0x19, 0x7f, 0xfb, 0x40, 0xe8, 0xcc, 0xa3, 0xc4, 0x79, 0x98, 0xb8, 0xa8, 0x2d, 0xa3, 0x45, 0xa4, - 0xe0, 0x2d, 0xf2, 0xde, 0x45, 0x08, 0x7f, 0x03, 0x2f, 0x0f, 0xa3, 0xa3, 0x89, 0xed, 0x10, 0xf4, - 0x52, 0x4e, 0x73, 0x47, 0xc8, 0x74, 0x38, 0x31, 0xdf, 0x11, 0x84, 0xf1, 0xb7, 0x70, 0x29, 0x1d, - 0x6f, 0x4d, 0xc7, 0xb5, 0xe9, 0xcc, 0xbb, 0xb1, 0xa9, 0x77, 0x47, 0x66, 0xe8, 0x52, 0x7b, 0x03, - 0xca, 0x98, 0x09, 0x47, 0xf8, 0x82, 0x61, 0x04, 0xb5, 0xbf, 0x59, 0x96, 0x5f, 0xb2, 0x06, 0x95, - 0x47, 0xfc, 0x3d, 0xc0, 0x82, 0x47, 0x11, 0x5b, 0x88, 0x90, 0x6f, 0xf2, 0x5b, 0xd4, 0xa0, 0x07, - 0x11, 0x8d, 0x82, 0x32, 0xdd, 0x3e, 0x5b, 0xfd, 0x0a, 0x4e, 0x3e, 0xfa, 0xd1, 0x96, 0xe5, 0x85, - 0xe7, 0xb4, 0x10, 0x47, 0x9e, 0xb5, 0x27, 0x9e, 0x6f, 0x40, 0x31, 0x58, 0xf4, 0xb5, 0x13, 0x31, - 0x68, 0x97, 0xfb, 0x5c, 0x67, 0xd4, 0xdf, 0x04, 0x0c, 0x77, 0x40, 0x49, 0x85, 0x9f, 0x88, 0xbb, - 0xbd, 0xd3, 0x5e, 0xe3, 0x2b, 0x38, 0x65, 0x9b, 0xa5, 0xcc, 0x14, 0x56, 0x3b, 0xf5, 0xc5, 0x21, - 0x6f, 0xa0, 0x35, 0x66, 0xe2, 0xed, 0x96, 0x25, 0x19, 0x65, 0xe9, 0x36, 0x12, 0x72, 0xd9, 0x7f, - 0xa4, 0xdc, 0xb5, 0x28, 0xc4, 0x17, 0xc7, 0xfd, 0x09, 0xd0, 0x98, 0x89, 0xdb, 0x30, 0x15, 0x3c, - 0xc9, 0x6e, 0x78, 0x22, 0x7b, 0x3f, 0x59, 0x5a, 0xeb, 0x42, 0x2b, 0x6f, 0x95, 0xaf, 0x65, 0xb1, - 0x4f, 0x02, 0xb7, 0xa0, 0x1a, 0x2e, 0x77, 0x48, 0x35, 0x5c, 0x6a, 0x3f, 0x42, 0xfb, 0x91, 0x18, - 0x45, 0x3c, 0x65, 0x4f, 0x90, 0xdf, 0x01, 0x1d, 0xcc, 0x7b, 0x9d, 0x09, 0x96, 0xe2, 0x2e, 0x34, - 0x93, 0x47, 0x99, 0xc3, 0xe7, 0xf4, 0x30, 0xa4, 0x6d, 0xe0, 0xa2, 0xac, 0x8a, 0xf9, 0x26, 0x65, - 0x78, 0x00, 0x67, 0x45, 0x5e, 0xe2, 0xb5, 0x5e, 0x73, 0xa0, 0x96, 0xbf, 0xd9, 0x63, 0x77, 0x5a, - 0x82, 0xf8, 0x35, 0x28, 0x2b, 0x3f, 0xf5, 0xd6, 0x3c, 0x29, 0xee, 0x82, 0x42, 0xcf, 0x56, 0x7e, - 0x7a, 0xcf, 0x93, 0x72, 0xca, 0x5a, 0x39, 0xe5, 0xe0, 0xfd, 0xc1, 0xeb, 0xe7, 0x6c, 0xe3, 0x98, - 0x27, 0x02, 0x1b, 0xa0, 0x50, 0x16, 0x84, 0xa9, 0x60, 0x09, 0x56, 0x9f, 0x7b, 0xfb, 0x3a, 0xcf, - 0x66, 0xb4, 0x17, 0xbd, 0xca, 0x2f, 0x95, 0x6b, 0x1b, 0x34, 0x9e, 0x04, 0xfa, 0x2a, 0x8b, 0x59, - 0x12, 0xb1, 0x65, 0xc0, 0x12, 0xfd, 0x83, 0x3f, 0x4f, 0xc2, 0x45, 0x59, 0x27, 0x9f, 0xeb, 0xbf, - 0x7e, 0x0e, 0x42, 0xb1, 0xda, 0xce, 0xf5, 0x05, 0x5f, 0xf7, 0x0f, 0xd0, 0x7e, 0x81, 0x16, 0xcf, - 0x76, 0xda, 0x97, 0xe8, 0xbc, 0xf8, 0x0f, 0xf8, 0xed, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, - 0xba, 0x68, 0xc2, 0x27, 0x06, 0x00, 0x00, + // 825 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x95, 0x51, 0x6f, 0xe2, 0x46, + 0x10, 0xc7, 0x8f, 0x00, 0xc1, 0x0c, 0x09, 0xec, 0x6d, 0xae, 0xa9, 0x0f, 0xe9, 0x5a, 0x8a, 0xfa, + 0x40, 0x5f, 0xa0, 0xa5, 0x7d, 0xe8, 0xc3, 0x49, 0x15, 0xc1, 0x1b, 0x62, 0x85, 0xd8, 0xdc, 0xda, + 0x39, 0x1d, 0x7d, 0xb1, 0x1c, 0xbc, 0x67, 0xac, 0x1a, 0xaf, 0x6b, 0x2f, 0xa7, 0xf3, 0x67, 0xe8, + 0x07, 0xeb, 0xd7, 0xaa, 0xd6, 0xc6, 0x84, 0x23, 0x8a, 0x4e, 0xea, 0x13, 0xfe, 0xcf, 0xfc, 0x66, + 0xe6, 0x3f, 0xd6, 0xb2, 0x86, 0xd7, 0x31, 0x63, 0xc9, 0x68, 0xb5, 0x76, 0x83, 0x68, 0xc5, 0x3d, + 0xe6, 0xa4, 0xeb, 0x60, 0x33, 0x8c, 0x13, 0x2e, 0x38, 0x3e, 0xcd, 0x7f, 0xd2, 0x6e, 0xf7, 0x08, + 0x61, 0x9f, 0x58, 0x24, 0x0a, 0xa6, 0x7b, 0x91, 0xe7, 0xe2, 0x84, 0xc7, 0x3c, 0x75, 0xc3, 0x5d, + 0xf0, 0x7b, 0x9f, 0x73, 0x3f, 0x64, 0xa3, 0x5c, 0x3d, 0x6c, 0x3f, 0x8e, 0x44, 0xb0, 0x61, 0xa9, + 0x70, 0x37, 0x71, 0x01, 0xf4, 0xff, 0xa9, 0x03, 0x9a, 0x96, 0xfd, 0xee, 0x58, 0x9a, 0xba, 0x3e, + 0xc3, 0xbf, 0x40, 0x4d, 0x64, 0x31, 0x53, 0x2b, 0xbd, 0xca, 0xa0, 0x3d, 0x7e, 0x53, 0xa0, 0xe9, + 0xf0, 0x98, 0x1b, 0xda, 0x59, 0xcc, 0x68, 0x8e, 0xe2, 0xdf, 0xa1, 0xb9, 0x6f, 0xad, 0x9e, 0xf4, + 0x2a, 0x83, 0xd6, 0xb8, 0x3b, 0x2c, 0x86, 0x0f, 0xcb, 0xe1, 0x43, 0xbb, 0x24, 0xe8, 0x23, 0x8c, + 0x55, 0x68, 0xc4, 0x6e, 0x16, 0x72, 0xd7, 0x53, 0xab, 0xbd, 0xca, 0xe0, 0x8c, 0x96, 0x12, 0x63, + 0xa8, 0x89, 0xcf, 0x81, 0xa7, 0xd6, 0x7a, 0x95, 0x41, 0x93, 0xe6, 0xcf, 0x78, 0x0c, 0x4a, 0xb9, + 0xa2, 0x5a, 0xcf, 0xc7, 0x5c, 0x96, 0xf6, 0xac, 0xc0, 0x8f, 0x98, 0xb7, 0xd8, 0x65, 0xe9, 0x9e, + 0xc3, 0x7f, 0x40, 0xe7, 0xe8, 0x95, 0xa9, 0xa7, 0x5f, 0x96, 0xee, 0x37, 0x23, 0x32, 0x4b, 0xdb, + 0xab, 0x2f, 0x34, 0x7e, 0x03, 0xb0, 0x5a, 0xbb, 0x51, 0xc4, 0x42, 0x27, 0xf0, 0xd4, 0x46, 0x6e, + 0xa7, 0xb9, 0x8b, 0xe8, 0x5e, 0xff, 0xdf, 0x13, 0xa8, 0xc9, 0x57, 0x81, 0xcf, 0xa1, 0x79, 0x6f, + 0x68, 0xe4, 0x5a, 0x37, 0x88, 0x86, 0x5e, 0xe0, 0x33, 0x50, 0x28, 0x99, 0xe9, 0x96, 0x4d, 0x28, + 0xaa, 0xe0, 0x36, 0x40, 0xa9, 0x88, 0x86, 0x4e, 0xb0, 0x02, 0x35, 0xdd, 0xd0, 0x6d, 0x54, 0xc5, + 0x4d, 0xa8, 0x53, 0x32, 0xd1, 0x96, 0xa8, 0x86, 0x3b, 0xd0, 0xb2, 0xe9, 0xc4, 0xb0, 0x26, 0x53, + 0x5b, 0x37, 0x0d, 0x54, 0x97, 0x2d, 0xa7, 0xe6, 0xdd, 0x62, 0x4e, 0x6c, 0xa2, 0xa1, 0x53, 0x89, + 0x12, 0x4a, 0x4d, 0x8a, 0x1a, 0x32, 0x33, 0x23, 0xb6, 0x63, 0xd9, 0x13, 0x9b, 0x20, 0x45, 0xca, + 0xc5, 0x7d, 0x29, 0x9b, 0x52, 0x6a, 0x64, 0xbe, 0x93, 0x80, 0x5f, 0x01, 0xd2, 0x8d, 0xf7, 0xe6, + 0x2d, 0x71, 0xa6, 0x37, 0x13, 0xdd, 0x98, 0x9a, 0x1a, 0x41, 0xad, 0xc2, 0xa0, 0xb5, 0x30, 0x0d, + 0x8b, 0xa0, 0x73, 0x7c, 0x09, 0x78, 0xdf, 0xd0, 0xb9, 0x5a, 0x3a, 0x74, 0x62, 0xcc, 0x08, 0x6a, + 0xcb, 0x5a, 0x19, 0x7f, 0x77, 0x4f, 0xe8, 0xd2, 0xa1, 0xc4, 0xba, 0x9f, 0xdb, 0xa8, 0x23, 0xa3, + 0x45, 0xa4, 0xe0, 0x0d, 0xf2, 0xc1, 0x46, 0x08, 0x7f, 0x03, 0x2f, 0x0f, 0xa3, 0xd3, 0xb9, 0x69, + 0x11, 0xf4, 0x52, 0xba, 0xb9, 0x25, 0x64, 0x31, 0x99, 0xeb, 0xef, 0x09, 0xc2, 0xf8, 0x5b, 0xb8, + 0x90, 0x1d, 0x6f, 0x74, 0xcb, 0x36, 0xe9, 0xd2, 0xb9, 0x36, 0xa9, 0x73, 0x4b, 0x96, 0xe8, 0xa2, + 0xff, 0x16, 0x94, 0x19, 0x13, 0x96, 0x70, 0x05, 0xc3, 0x08, 0xaa, 0x7f, 0xb1, 0x2c, 0x3f, 0x83, + 0x4d, 0x2a, 0x1f, 0xf1, 0x77, 0x00, 0x2b, 0x1e, 0x86, 0x6c, 0x25, 0x02, 0x1e, 0xe5, 0x87, 0xac, + 0x49, 0x0f, 0x22, 0x7d, 0x0a, 0xca, 0x62, 0xfb, 0x6c, 0xf5, 0x2b, 0xa8, 0x7f, 0x72, 0xc3, 0x2d, + 0xcb, 0x0b, 0xcf, 0x68, 0x21, 0x8e, 0x7a, 0x56, 0x9f, 0xf4, 0x7c, 0x0b, 0x8a, 0xc6, 0xc2, 0xff, + 0xeb, 0x88, 0x41, 0xa7, 0xdc, 0xe7, 0x2a, 0xa3, 0x6e, 0xe4, 0x33, 0xdc, 0x05, 0x25, 0x15, 0x6e, + 0x22, 0x6e, 0xf7, 0x9d, 0xf6, 0x1a, 0x5f, 0xc2, 0x29, 0x8b, 0x3c, 0x99, 0x29, 0x5a, 0xed, 0xd4, + 0x57, 0x4d, 0x5e, 0x43, 0x7b, 0xc6, 0xc4, 0xbb, 0x2d, 0x4b, 0x32, 0xca, 0xd2, 0x6d, 0x28, 0xe4, + 0xb2, 0x7f, 0x4b, 0xb9, 0x1b, 0x51, 0x88, 0xaf, 0xda, 0xfd, 0x11, 0xd0, 0x8c, 0x89, 0x9b, 0x20, + 0x15, 0x3c, 0xc9, 0xae, 0x79, 0x22, 0x67, 0x3f, 0x59, 0xba, 0xdf, 0x83, 0x76, 0x3e, 0x2a, 0x5f, + 0xcb, 0x60, 0x9f, 0x05, 0x6e, 0xc3, 0x49, 0xe0, 0xed, 0x90, 0x93, 0xc0, 0xeb, 0xff, 0x00, 0x9d, + 0x47, 0x62, 0x1a, 0xf2, 0x94, 0x3d, 0x41, 0x7e, 0x03, 0x74, 0xe0, 0xf7, 0x2a, 0x13, 0x2c, 0xc5, + 0x3d, 0x68, 0x25, 0x8f, 0x32, 0x87, 0xcf, 0xe8, 0x61, 0xa8, 0x1f, 0xc1, 0x79, 0x59, 0x15, 0xf3, + 0x28, 0x65, 0x78, 0x0c, 0x8d, 0x22, 0x2f, 0xf1, 0xea, 0xa0, 0x35, 0x56, 0xcb, 0xbf, 0xf4, 0x71, + 0x77, 0x5a, 0x82, 0xf8, 0x35, 0x28, 0x6b, 0x37, 0x75, 0x36, 0x3c, 0x29, 0xce, 0x82, 0x42, 0x1b, + 0x6b, 0x37, 0xbd, 0xe3, 0x49, 0xe9, 0xb2, 0x5a, 0xba, 0x1c, 0x7f, 0x38, 0xb8, 0x1c, 0xad, 0x6d, + 0x1c, 0xf3, 0x44, 0x60, 0x0d, 0x14, 0xca, 0xfc, 0x20, 0x15, 0x2c, 0xc1, 0xea, 0x73, 0x57, 0x63, + 0xf7, 0xd9, 0x4c, 0xff, 0xc5, 0xa0, 0xf2, 0x73, 0xe5, 0xca, 0x84, 0x3e, 0x4f, 0xfc, 0xe1, 0x3a, + 0x8b, 0x59, 0x12, 0x32, 0xcf, 0x67, 0xc9, 0xf0, 0xa3, 0xfb, 0x90, 0x04, 0xab, 0xb2, 0x4e, 0xde, + 0xe6, 0x7f, 0xfe, 0xe4, 0x07, 0x62, 0xbd, 0x7d, 0x18, 0xae, 0xf8, 0x66, 0x74, 0x80, 0x8e, 0x0a, + 0xb4, 0xb8, 0xd5, 0xd3, 0x91, 0x44, 0x1f, 0x8a, 0x4f, 0xc4, 0xaf, 0xff, 0x05, 0x00, 0x00, 0xff, + 0xff, 0x18, 0x6a, 0x79, 0xe7, 0x46, 0x06, 0x00, 0x00, } diff --git a/protos/peer/chaincode_shim.proto b/protos/peer/chaincode_shim.proto index 4e3bf8a2569..79141a0032b 100644 --- a/protos/peer/chaincode_shim.proto +++ b/protos/peer/chaincode_shim.proto @@ -49,6 +49,9 @@ message ChaincodeMessage { // This event is then stored (currently) //with Block.NonHashData.TransactionResult ChaincodeEvent chaincode_event = 6; + + //channel id + string channel_id = 7; } // TODO: We need to finalize the design on chaincode container