Ejemplo n.º 1
0
// checks for a valid ChainHeader
func validateChainHeader(cHdr *common.ChainHeader) error {
	// check for nil argument
	if cHdr == nil {
		return fmt.Errorf("Nil ChainHeader provided")
	}

	// validate the header type
	if common.HeaderType(cHdr.Type) != common.HeaderType_ENDORSER_TRANSACTION &&
		common.HeaderType(cHdr.Type) != common.HeaderType_CONFIGURATION_ITEM &&
		common.HeaderType(cHdr.Type) != common.HeaderType_CONFIGURATION_TRANSACTION {
		return fmt.Errorf("invalid header type %s", common.HeaderType(cHdr.Type))
	}

	putilsLogger.Infof("validateChainHeader info: header type %d", common.HeaderType(cHdr.Type))

	// TODO: validate chainID in cHdr.ChainID

	// TODO: validate epoch in cHdr.Epoch

	// TODO: validate type in cHdr.Type

	// TODO: validate version in cHdr.Version

	return nil
}
Ejemplo n.º 2
0
// ValidateProposalMessage checks the validity of a SignedProposal message
// this function returns Header and ChaincodeHeaderExtension messages since they
// have been unmarshalled and validated
func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *common.Header, *pb.ChaincodeHeaderExtension, error) {
	putilsLogger.Infof("ValidateProposalMessage starts for signed proposal %p", signedProp)

	// extract the Proposal message from signedProp
	prop, err := utils.GetProposal(signedProp.ProposalBytes)
	if err != nil {
		return nil, nil, nil, err
	}

	// 1) look at the ProposalHeader
	hdr, err := utils.GetHeader(prop.Header)
	if err != nil {
		return nil, nil, nil, err
	}

	// validate the header
	err = validateCommonHeader(hdr)
	if err != nil {
		return nil, nil, nil, err
	}

	// validate the signature
	err = checkSignatureFromCreator(hdr.SignatureHeader.Creator, signedProp.Signature, signedProp.ProposalBytes, hdr.ChainHeader.ChainID)
	if err != nil {
		return nil, nil, nil, err
	}

	// TODO: ensure that creator can transact with us (some ACLs?) which set of APIs is supposed to give us this info?

	// TODO: perform a check against replay attacks

	// continue the validation in a way that depends on the type specified in the header
	switch common.HeaderType(hdr.ChainHeader.Type) {
	case common.HeaderType_ENDORSER_TRANSACTION:
		// validation of the proposal message knowing it's of type CHAINCODE
		chaincodeHdrExt, err := validateChaincodeProposalMessage(prop, hdr)
		if err != nil {
			return nil, nil, nil, err
		}

		return prop, hdr, chaincodeHdrExt, err
	default:
		return nil, nil, nil, fmt.Errorf("Unsupported proposal type %d", common.HeaderType(hdr.ChainHeader.Type))
	}
}
Ejemplo n.º 3
0
// ValidateTransaction checks that the transaction envelope is properly formed
func ValidateTransaction(e *common.Envelope) (*common.Payload, []*pb.TransactionAction, error) {
	putilsLogger.Infof("ValidateTransactionEnvelope starts for envelope %p", e)

	// check for nil argument
	if e == nil {
		return nil, nil, fmt.Errorf("Nil Envelope")
	}

	// get the payload from the envelope
	payload, err := utils.GetPayload(e)
	if err != nil {
		return nil, nil, fmt.Errorf("Could not extract payload from envelope, err %s", err)
	}

	putilsLogger.Infof("Header is %s", payload.Header)

	// validate the header
	err = validateCommonHeader(payload.Header)
	if err != nil {
		return nil, nil, err
	}

	// validate the signature in the envelope
	err = checkSignatureFromCreator(payload.Header.SignatureHeader.Creator, e.Signature, e.Payload, payload.Header.ChainHeader.ChainID)
	if err != nil {
		return nil, nil, err
	}

	// TODO: ensure that creator can transact with us (some ACLs?) which set of APIs is supposed to give us this info?

	// TODO: perform a check against replay attacks

	// continue the validation in a way that depends on the type specified in the header
	switch common.HeaderType(payload.Header.ChainHeader.Type) {
	case common.HeaderType_ENDORSER_TRANSACTION:
		rv, err := validateEndorserTransaction(payload.Data, payload.Header)
		putilsLogger.Infof("ValidateTransactionEnvelope returns %p, err %s", rv, err)
		return payload, rv, err
	default:
		return nil, nil, fmt.Errorf("Unsupported transaction payload type %d", common.HeaderType(payload.Header.ChainHeader.Type))
	}
}
Ejemplo n.º 4
0
// GetChaincodeHeaderExtension get chaincode header extension given header
func GetChaincodeHeaderExtension(hdr *common.Header) (*peer.ChaincodeHeaderExtension, error) {
	if common.HeaderType(hdr.ChainHeader.Type) != common.HeaderType_ENDORSER_TRANSACTION {
		return nil, fmt.Errorf("invalid proposal type expected ENDORSER_TRANSACTION")
	}

	chaincodeHdrExt := &peer.ChaincodeHeaderExtension{}
	err := proto.Unmarshal(hdr.ChainHeader.Extension, chaincodeHdrExt)
	if err != nil {
		return nil, err
	}

	return chaincodeHdrExt, nil
}
Ejemplo n.º 5
0
// GetChaincodeInvocationSpec get the ChaincodeInvocationSpec from the proposal
func GetChaincodeInvocationSpec(prop *peer.Proposal) (*peer.ChaincodeInvocationSpec, error) {
	txhdr := &common.Header{}
	err := proto.Unmarshal(prop.Header, txhdr)
	if err != nil {
		return nil, err
	}
	if common.HeaderType(txhdr.ChainHeader.Type) != common.HeaderType_ENDORSER_TRANSACTION {
		return nil, fmt.Errorf("invalid proposal type expected ENDORSER_TRANSACTION")
	}
	ccPropPayload := &peer.ChaincodeProposalPayload{}
	err = proto.Unmarshal(prop.Payload, ccPropPayload)
	if err != nil {
		return nil, err
	}
	cis := &peer.ChaincodeInvocationSpec{}
	err = proto.Unmarshal(ccPropPayload.Input, cis)
	if err != nil {
		return nil, err
	}
	return cis, nil
}
Ejemplo n.º 6
0
// SendProducerBlockEvent sends block event to clients
func SendProducerBlockEvent(block *common.Block) error {
	bevent := &common.Block{}
	bevent.Header = block.Header
	bevent.Metadata = block.Metadata
	bevent.Data = &common.BlockData{}
	for _, d := range block.Data.Data {
		if d != nil {
			if env, err := utils.GetEnvelopeFromBlock(d); err != nil {
				logger.Errorf("Error getting tx from block(%s)\n", err)
			} else if env != nil {
				// get the payload from the envelope
				payload, err := utils.GetPayload(env)
				if err != nil {
					return fmt.Errorf("Could not extract payload from envelope, err %s", err)
				}

				if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
					tx, err := utils.GetTransaction(payload.Data)
					if err != nil {
						logger.Errorf("Error unmarshalling transaction payload for block event: %s", err)
						continue
					}
					chaincodeActionPayload := &pb.ChaincodeActionPayload{}
					err = proto.Unmarshal(tx.Actions[0].Payload, chaincodeActionPayload)
					if err != nil {
						logger.Errorf("Error unmarshalling transaction action payload for block event: %s", err)
						continue
					}

					propRespPayload := &pb.ProposalResponsePayload{}
					err = proto.Unmarshal(chaincodeActionPayload.Action.ProposalResponsePayload, propRespPayload)
					if err != nil {
						logger.Errorf("Error unmarshalling proposal response payload for block event: %s", err)
						continue
					}
					//ENDORSER_ACTION, ProposalResponsePayload.Extension field contains ChaincodeAction
					caPayload := &pb.ChaincodeAction{}
					err = proto.Unmarshal(propRespPayload.Extension, caPayload)
					if err != nil {
						logger.Errorf("Error unmarshalling chaincode action for block event: %s", err)
						continue
					}
					// Drop read write set from transaction before sending block event
					caPayload.Results = nil
					propRespPayload.Extension, err = proto.Marshal(caPayload)
					if err != nil {
						logger.Errorf("Error marshalling tx proposal extension payload for block event: %s", err)
						continue
					}
					// Marshal Transaction again and append to block to be sent
					chaincodeActionPayload.Action.ProposalResponsePayload, err = proto.Marshal(propRespPayload)
					if err != nil {
						logger.Errorf("Error marshalling tx proposal payload for block event: %s", err)
						continue
					}
					tx.Actions[0].Payload, err = proto.Marshal(chaincodeActionPayload)
					if err != nil {
						logger.Errorf("Error marshalling tx action payload for block event: %s", err)
						continue
					}
					if t, err := proto.Marshal(tx); err == nil {
						bevent.Data.Data = append(bevent.Data.Data, t)
						logger.Infof("calling sendProducerBlockEvent\n")
					} else {
						logger.Infof("Cannot marshal transaction %s\n", err)
					}
				}
			}
		}
	}
	return Send(CreateBlockEvent(bevent))
}
// 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
}