github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/core/scc/escc/endorser_onevalidsignature.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 escc
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/hyperledger/fabric/common/flogging"
    23  	"github.com/hyperledger/fabric/core/chaincode/shim"
    24  	pb "github.com/hyperledger/fabric/protos/peer"
    25  	"github.com/hyperledger/fabric/protos/utils"
    26  	putils "github.com/hyperledger/fabric/protos/utils"
    27  
    28  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    29  )
    30  
    31  var logger = flogging.MustGetLogger("escc")
    32  
    33  // EndorserOneValidSignature implements the default endorsement policy, which is to
    34  // sign the proposal hash and the read-write set
    35  type EndorserOneValidSignature struct {
    36  }
    37  
    38  // Init is called once when the chaincode started the first time
    39  func (e *EndorserOneValidSignature) Init(stub shim.ChaincodeStubInterface) pb.Response {
    40  	logger.Infof("Successfully initialized ESCC")
    41  
    42  	return shim.Success(nil)
    43  }
    44  
    45  // Invoke is called to endorse the specified Proposal
    46  // For now, we sign the input and return the endorsed result. Later we can expand
    47  // the chaincode to provide more sophisticate policy processing such as enabling
    48  // policy specification to be coded as a transaction of the chaincode and Client
    49  // could select which policy to use for endorsement using parameter
    50  // @return a marshalled proposal response
    51  // Note that Peer calls this function with 4 mandatory arguments (and 2 optional ones):
    52  // args[0] - function name (not used now)
    53  // args[1] - serialized Header object
    54  // args[2] - serialized ChaincodeProposalPayload object
    55  // args[3] - ChaincodeID of executing chaincode
    56  // args[4] - result of executing chaincode
    57  // args[5] - binary blob of simulation results
    58  // args[6] - serialized events
    59  // args[7] - payloadVisibility
    60  
    61  //
    62  // NOTE: this chaincode is meant to sign another chaincode's simulation
    63  // results. It should not manipulate state as any state change will be
    64  // silently discarded: the only state changes that will be persisted if
    65  // this endorsement is successful is what we are about to sign, which by
    66  // definition can't be a state change of our own.
    67  func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
    68  	args := stub.GetArgs()
    69  	if len(args) < 6 {
    70  		return shim.Error(fmt.Sprintf("Incorrect number of arguments (expected a minimum of 5, provided %d)", len(args)))
    71  	} else if len(args) > 8 {
    72  		return shim.Error(fmt.Sprintf("Incorrect number of arguments (expected a maximum of 7, provided %d)", len(args)))
    73  	}
    74  
    75  	logger.Debugf("ESCC starts: %d args", len(args))
    76  
    77  	// handle the header
    78  	var hdr []byte
    79  	if args[1] == nil {
    80  		return shim.Error("serialized Header object is null")
    81  	}
    82  
    83  	hdr = args[1]
    84  
    85  	// handle the proposal payload
    86  	var payl []byte
    87  	if args[2] == nil {
    88  		return shim.Error("serialized ChaincodeProposalPayload object is null")
    89  	}
    90  
    91  	payl = args[2]
    92  
    93  	// handle ChaincodeID
    94  	if args[3] == nil {
    95  		return shim.Error("ChaincodeID is null")
    96  	}
    97  
    98  	ccid, err := putils.UnmarshalChaincodeID(args[3])
    99  	if err != nil {
   100  		return shim.Error(err.Error())
   101  	}
   102  
   103  	// handle executing chaincode result
   104  	// Status code < 500 can be endorsed
   105  	if args[4] == nil {
   106  		return shim.Error("Response of chaincode executing is null")
   107  	}
   108  
   109  	response, err := putils.GetResponse(args[4])
   110  	if err != nil {
   111  		return shim.Error(fmt.Sprintf("Failed to get Response of executing chaincode: %s", err.Error()))
   112  	}
   113  
   114  	if response.Status >= shim.ERROR {
   115  		return shim.Error(fmt.Sprintf("Status code less than 500 will be endorsed, get status code: %d", response.Status))
   116  	}
   117  
   118  	// handle simulation results
   119  	var results []byte
   120  	if args[5] == nil {
   121  		return shim.Error("simulation results are null")
   122  	}
   123  
   124  	results = args[5]
   125  
   126  	// Handle serialized events if they have been provided
   127  	// they might be nil in case there's no events but there
   128  	// is a visibility field specified as the next arg
   129  	events := []byte("")
   130  	if len(args) > 6 && args[6] != nil {
   131  		events = args[6]
   132  	}
   133  
   134  	// Handle payload visibility (it's an optional argument)
   135  	// currently the fabric only supports full visibility: this means that
   136  	// there are no restrictions on which parts of the proposal payload will
   137  	// be visible in the final transaction; this default approach requires
   138  	// no additional instructions in the PayloadVisibility field; however
   139  	// the fabric may be extended to encode more elaborate visibility
   140  	// mechanisms that shall be encoded in this field (and handled
   141  	// appropriately by the peer)
   142  	var visibility []byte
   143  	if len(args) > 7 {
   144  		visibility = args[7]
   145  	}
   146  
   147  	// obtain the default signing identity for this peer; it will be used to sign this proposal response
   148  	localMsp := mspmgmt.GetLocalMSP()
   149  	if localMsp == nil {
   150  		return shim.Error("Nil local MSP manager")
   151  	}
   152  
   153  	signingEndorser, err := localMsp.GetDefaultSigningIdentity()
   154  	if err != nil {
   155  		return shim.Error(fmt.Sprintf("Could not obtain the default signing identity, err %s", err))
   156  	}
   157  
   158  	// obtain a proposal response
   159  	presp, err := utils.CreateProposalResponse(hdr, payl, response, results, events, ccid, visibility, signingEndorser)
   160  	if err != nil {
   161  		return shim.Error(err.Error())
   162  	}
   163  
   164  	// marshall the proposal response so that we return its bytes
   165  	prBytes, err := utils.GetBytesProposalResponse(presp)
   166  	if err != nil {
   167  		return shim.Error(fmt.Sprintf("Could not marshall ProposalResponse: err %s", err))
   168  	}
   169  
   170  	pResp, err := utils.GetProposalResponse(prBytes)
   171  	if err != nil {
   172  		return shim.Error(err.Error())
   173  	}
   174  	if pResp.Response == nil {
   175  		fmt.Println("GetProposalResponse get empty Response")
   176  	}
   177  
   178  	logger.Debugf("ESCC exits successfully")
   179  	return shim.Success(prBytes)
   180  }