Example #1
0
// 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
}