// Invoke is called for the following: // # to process joining a chain (called by app as a transaction proposal) // # to get the current configuration block (called by app) // # to update the configuration block (called by commmitter) // Peer calls this function with 2 arguments: // # args[0] is the function name, which must be JoinChain, GetConfigBlock or // UpdateConfigBlock // # args[1] is a configuration Block if args[0] is JoinChain or // UpdateConfigBlock; otherwise it is the chain id // TODO: Improve the scc interface to avoid marshal/unmarshal args func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) { args := stub.GetArgs() if len(args) < 2 { return nil, fmt.Errorf("Incorrect number of arguments, %d", len(args)) } fname := string(args[0]) logger.Debugf("Invoke function: %s", fname) // TODO: Handle ACL if fname == JoinChain { return joinChain(args[1]) } else if fname == GetConfigBlock { return getConfigBlock(args[1]) } else if fname == UpdateConfigBlock { return updateConfigBlock(args[1]) } return nil, fmt.Errorf("Requested function %s not found.", fname) }
// Invoke is called to endorse the specified Proposal // For now, we sign the input and return the endorsed result. Later we can expand // the chaincode to provide more sophisticate policy processing such as enabling // policy specification to be coded as a transaction of the chaincode and Client // could select which policy to use for endorsement using parameter // @return a marshalled proposal response // Note that Peer calls this function with 4 mandatory arguments (and 2 optional ones): // args[0] - function name (not used now) // args[1] - serialized Header object // args[2] - serialized ChaincodeProposalPayload object // args[3] - binary blob of simulation results // args[4] - serialized events (optional) // args[5] - payloadVisibility (optional) // // NOTE: this chaincode is meant to sign another chaincode's simulation // results. It should not manipulate state as any state change will be // silently discarded: the only state changes that will be persisted if // this endorsement is successful is what we are about to sign, which by // definition can't be a state change of our own. func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) { args := stub.GetArgs() if len(args) < 4 { return nil, fmt.Errorf("Incorrect number of arguments (expected a minimum of 4, provided %d)", len(args)) } else if len(args) > 6 { return nil, fmt.Errorf("Incorrect number of arguments (expected a maximum of 6, provided %d)", len(args)) } logger.Infof("ESCC starts: %d args", len(args)) // handle the header var hdr []byte if args[1] == nil { return nil, errors.New("serialized Header object is null") } hdr = args[1] // handle the proposal payload var payl []byte if args[2] == nil { return nil, errors.New("serialized ChaincodeProposalPayload object is null") } payl = args[2] // handle simulation results var results []byte if args[3] == nil { return nil, errors.New("simulation results are null") } results = args[3] // Handle serialized events if they have been provided // they might be nil in case there's no events but there // is a visibility field specified as the next arg events := []byte("") if len(args) > 4 && args[4] != nil { events = args[4] } // Handle payload visibility (it's an optional argument) visibility := []byte("") // TODO: when visibility is properly defined, replace with the default if len(args) > 5 { if args[5] == nil { return nil, errors.New("serialized events are null") } visibility = args[5] } // obtain the default signing identity for this peer; it will be used to sign this proposal response localMsp := mspmgmt.GetLocalMSP() if localMsp == nil { return nil, fmt.Errorf("Nil local MSP manager") } signingEndorser, err := localMsp.GetDefaultSigningIdentity() if err != nil { return nil, fmt.Errorf("Could not obtain the default signing identity, err %s", err) } // obtain a proposal response presp, err := utils.CreateProposalResponse(hdr, payl, results, events, visibility, signingEndorser) if err != nil { return nil, err } // marshall the proposal response so that we return its bytes prBytes, err := utils.GetBytesProposalResponse(presp) if err != nil { return nil, fmt.Errorf("Could not marshall ProposalResponse: err %s", err) } logger.Infof("ESCC exits successfully") return prBytes, nil }
// Invoke is called to validate the specified block of transactions // This validation system chaincode will check the read-write set validity and at least 1 // correct endorsement. Later we can create more validation system // chaincodes to provide more sophisticated policy processing such as enabling // policy specification to be coded as a transaction of the chaincode and the client // selecting which policy to use for validation using parameter function // @return serialized Block of valid and invalid transactions indentified // Note that Peer calls this function with 2 arguments, where args[0] is the // function name and args[1] is the Envelope func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) { // args[0] - function name (not used now) // args[1] - serialized Envelope args := stub.GetArgs() if len(args) < 2 { return nil, errors.New("Incorrect number of arguments") } if args[1] == nil { return nil, errors.New("No block to validate") } logger.Infof("VSCC invoked") // get the envelope... env, err := utils.GetEnvelope(args[1]) if err != nil { logger.Errorf("VSCC error: GetEnvelope failed, err %s", err) return nil, err } // ...and the payload... payl, err := utils.GetPayload(env) if err != nil { logger.Errorf("VSCC error: GetPayload failed, err %s", err) return nil, err } // validate the payload type if common.HeaderType(payl.Header.ChainHeader.Type) != common.HeaderType_ENDORSER_TRANSACTION { logger.Errorf("Only Endorser Transactions are supported, provided type %d", payl.Header.ChainHeader.Type) return nil, fmt.Errorf("Only Endorser Transactions are supported, provided type %d", payl.Header.ChainHeader.Type) } // ...and the transaction... tx, err := utils.GetTransaction(payl.Data) if err != nil { logger.Errorf("VSCC error: GetTransaction failed, err %s", err) return nil, err } // loop through each of the actions within for _, act := range tx.Actions { cap, err := utils.GetChaincodeActionPayload(act.Payload) if err != nil { logger.Errorf("VSCC error: GetChaincodeActionPayload failed, err %s", err) return nil, err } // this is what is being signed prespBytes := cap.Action.ProposalResponsePayload // loop through each of the endorsements for _, endorsement := range cap.Action.Endorsements { // extract the identity of the signer end, err := mspmgmt.GetManagerForChain(payl.Header.ChainHeader.ChainID).DeserializeIdentity(endorsement.Endorser) if err != nil { logger.Errorf("VSCC error: DeserializeIdentity failed, err %s", err) return nil, err } // validate it err = end.Validate() if err != nil { return nil, fmt.Errorf("Invalid endorser identity, err %s", err) } // verify the signature err = end.Verify(append(prespBytes, endorsement.Endorser...), endorsement.Signature) if err != nil { return nil, fmt.Errorf("Invalid signature, err %s", err) } } } logger.Infof("VSCC exists successfully") return nil, nil }