github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/chaincode/exectransaction.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package chaincode
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/golang/protobuf/proto"
    23  	"github.com/hyperledger/fabric/core/chaincode/shim"
    24  	"github.com/hyperledger/fabric/core/common/ccprovider"
    25  	pb "github.com/hyperledger/fabric/protos/peer"
    26  	"golang.org/x/net/context"
    27  )
    28  
    29  //Execute - execute proposal, return original response of chaincode
    30  func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error) {
    31  	var err error
    32  	var cds *pb.ChaincodeDeploymentSpec
    33  	var ci *pb.ChaincodeInvocationSpec
    34  
    35  	//init will call the Init method of a on a chain
    36  	cctyp := pb.ChaincodeMessage_INIT
    37  	if cds, _ = spec.(*pb.ChaincodeDeploymentSpec); cds == nil {
    38  		if ci, _ = spec.(*pb.ChaincodeInvocationSpec); ci == nil {
    39  			panic("Execute should be called with deployment or invocation spec")
    40  		}
    41  		cctyp = pb.ChaincodeMessage_TRANSACTION
    42  	}
    43  
    44  	_, cMsg, err := theChaincodeSupport.Launch(ctxt, cccid, spec)
    45  	if err != nil {
    46  		return nil, nil, fmt.Errorf("%s", err)
    47  	}
    48  
    49  	var ccMsg *pb.ChaincodeMessage
    50  	ccMsg, err = createCCMessage(cctyp, cccid.TxID, cMsg)
    51  	if err != nil {
    52  		return nil, nil, fmt.Errorf("Failed to transaction message(%s)", err)
    53  	}
    54  
    55  	resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, theChaincodeSupport.executetimeout)
    56  	if err != nil {
    57  		// Rollback transaction
    58  		return nil, nil, fmt.Errorf("Failed to execute transaction (%s)", err)
    59  	} else if resp == nil {
    60  		// Rollback transaction
    61  		return nil, nil, fmt.Errorf("Failed to receive a response for (%s)", cccid.TxID)
    62  	}
    63  
    64  	if resp.ChaincodeEvent != nil {
    65  		resp.ChaincodeEvent.ChaincodeId = cccid.Name
    66  		resp.ChaincodeEvent.TxId = cccid.TxID
    67  	}
    68  
    69  	if resp.Type == pb.ChaincodeMessage_COMPLETED {
    70  		res := &pb.Response{}
    71  		unmarshalErr := proto.Unmarshal(resp.Payload, res)
    72  		if unmarshalErr != nil {
    73  			return nil, nil, fmt.Errorf("Failed to unmarshal response for (%s): %s", cccid.TxID, unmarshalErr)
    74  		}
    75  
    76  		// Success
    77  		return res, resp.ChaincodeEvent, nil
    78  	} else if resp.Type == pb.ChaincodeMessage_ERROR {
    79  		// Rollback transaction
    80  		return nil, resp.ChaincodeEvent, fmt.Errorf("Transaction returned with failure: %s", string(resp.Payload))
    81  	}
    82  
    83  	//TODO - this should never happen ... a panic is more appropriate but will save that for future
    84  	return nil, nil, fmt.Errorf("receive a response for (%s) but in invalid state(%d)", cccid.TxID, resp.Type)
    85  }
    86  
    87  // ExecuteWithErrorFilter is similar to Execute, but filters error contained in chaincode response and returns Payload of response only.
    88  // Mostly used by unit-test.
    89  func ExecuteWithErrorFilter(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}) ([]byte, *pb.ChaincodeEvent, error) {
    90  	res, event, err := Execute(ctxt, cccid, spec)
    91  	if err != nil {
    92  		chaincodeLogger.Errorf("ExecuteWithErrorFilter %s error: %s", cccid.Name, err)
    93  		return nil, nil, err
    94  	}
    95  
    96  	if res == nil {
    97  		chaincodeLogger.Errorf("ExecuteWithErrorFilter %s get nil response without error", cccid.Name)
    98  		return nil, nil, err
    99  	}
   100  
   101  	if res.Status != shim.OK {
   102  		return nil, nil, fmt.Errorf("%s", res.Message)
   103  	}
   104  
   105  	return res.Payload, event, nil
   106  }