示例#1
0
func (d *Devops) createExecTx(spec *pb.ChaincodeInvocationSpec, uuid string, invokeTx bool, sec crypto.Client) (*pb.Transaction, error) {
	var tx *pb.Transaction
	var err error
	if nil != sec {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating secure invocation transaction %s", uuid)
		}
		if invokeTx {
			tx, err = sec.NewChaincodeExecute(spec, uuid)
		} else {
			tx, err = sec.NewChaincodeQuery(spec, uuid)
		}
		if nil != err {
			return nil, err
		}
	} else {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating invocation transaction (%s)", uuid)
		}
		var t pb.Transaction_Type
		if invokeTx {
			t = pb.Transaction_CHAINCODE_EXECUTE
		} else {
			t = pb.Transaction_CHAINCODE_QUERY
		}
		tx, err = pb.NewChaincodeExecute(spec, uuid, t)
		if nil != err {
			return nil, err
		}
	}
	return tx, nil
}
示例#2
0
// Invoke or query a chaincode.
func invoke(ctx context.Context, spec *pb.ChaincodeSpec, typ pb.Transaction_Type) (string, []byte, error) {
	chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}

	// Now create the Transactions message and send to Peer.
	uuid := util.GenerateUUID()

	transaction, err := pb.NewChaincodeExecute(chaincodeInvocationSpec, uuid, typ)
	if err != nil {
		return uuid, nil, fmt.Errorf("Error invoking chaincode: %s ", err)
	}

	var retval []byte
	var execErr error
	if typ == pb.Transaction_CHAINCODE_QUERY {
		retval, execErr = Execute(ctx, GetChain(DefaultChain), transaction)
	} else {
		ledger, _ := ledger.GetLedger()
		ledger.BeginTxBatch("1")
		retval, execErr = Execute(ctx, GetChain(DefaultChain), transaction)
		if err != nil {
			return uuid, nil, fmt.Errorf("Error invoking chaincode: %s ", err)
		}
		ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil)
	}

	return uuid, retval, execErr
}
示例#3
0
func createConfidentialECertHQueryTransaction(t *testing.T) (*obc.Transaction, *obc.Transaction, error) {
	uuid, err := util.GenerateUUID()
	if err != nil {
		return nil, nil, err
	}

	cis := &obc.ChaincodeInvocationSpec{
		ChaincodeSpec: &obc.ChaincodeSpec{
			Type:                 obc.ChaincodeSpec_GOLANG,
			ChaincodeID:          &obc.ChaincodeID{Path: "Contract001"},
			CtorMsg:              nil,
			ConfidentialityLevel: obc.ConfidentialityLevel_CONFIDENTIAL,
		},
	}

	otx, err := obc.NewChaincodeExecute(cis, uuid, obc.Transaction_CHAINCODE_QUERY)
	if err != nil {
		return nil, nil, err
	}
	handler, err := invoker.GetEnrollmentCertificateHandler()
	if err != nil {
		return nil, nil, err
	}
	txHandler, err := handler.GetTransactionHandler()
	if err != nil {
		return nil, nil, err
	}
	tx, err := txHandler.NewChaincodeQuery(cis, uuid)

	// Check binding consistency
	binding, _ := txHandler.GetBinding()
	if !reflect.DeepEqual(binding, utils.Hash(append(handler.GetCertificate(), tx.Nonce...))) {
		t.Fatal("Binding is malformed!")
	}

	// Check confidentiality level
	if tx.ConfidentialityLevel != cis.ChaincodeSpec.ConfidentialityLevel {
		t.Fatal("Failed setting confidentiality level")
	}

	// Check metadata
	if !reflect.DeepEqual(cis.ChaincodeSpec.Metadata, tx.Metadata) {
		t.Fatal("Failed copying metadata")
	}

	return otx, tx, err
}
// Invoke or query a chaincode.
func invoke(ctx context.Context, spec *pb.ChaincodeSpec, typ pb.Transaction_Type) (string, []byte, error) {
	chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}

	// Now create the Transactions message and send to Peer.
	uuid, uuidErr := util.GenerateUUID()
	if uuidErr != nil {
		return "", nil, uuidErr
	}

	transaction, err := pb.NewChaincodeExecute(chaincodeInvocationSpec, uuid, typ)
	if err != nil {
		return uuid, nil, fmt.Errorf("Error deploying chaincode: %s ", err)
	}

	retval, err := Execute(ctx, GetChain(DefaultChain), transaction, nil)

	return uuid, retval, err
}
示例#5
0
func (d *Devops) createExecTx(spec *pb.ChaincodeInvocationSpec, uuid string, invokeTx bool) (*pb.Transaction, error) {
	var tx *pb.Transaction
	var err error
	if viper.GetBool("security.enabled") {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Initializing secure devops using context %s", spec.ChaincodeSpec.SecureContext)
		}
		sec, err := crypto.InitClient(spec.ChaincodeSpec.SecureContext, nil)
		defer crypto.CloseClient(sec)

		// remove the security context since we are no longer need it down stream
		spec.ChaincodeSpec.SecureContext = ""

		if nil != err {
			return nil, err
		}
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating secure invocation transaction %s", uuid)
		}
		if invokeTx {
			tx, err = sec.NewChaincodeExecute(spec, uuid)
		} else {
			tx, err = sec.NewChaincodeQuery(spec, uuid)
		}
		if nil != err {
			return nil, err
		}
	} else {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating invocation transaction (%s)", uuid)
		}
		var t pb.Transaction_Type
		if invokeTx {
			t = pb.Transaction_CHAINCODE_EXECUTE
		} else {
			t = pb.Transaction_CHAINCODE_QUERY
		}
		tx, err = pb.NewChaincodeExecute(spec, uuid, t)
		if nil != err {
			return nil, err
		}
	}
	return tx, nil
}
示例#6
0
func createPublicQueryTransaction(t *testing.T) (*obc.Transaction, *obc.Transaction, error) {
	uuid := util.GenerateUUID()

	cis := &obc.ChaincodeInvocationSpec{
		ChaincodeSpec: &obc.ChaincodeSpec{
			Type:                 obc.ChaincodeSpec_GOLANG,
			ChaincodeID:          &obc.ChaincodeID{Path: "Contract001"},
			CtorMsg:              nil,
			ConfidentialityLevel: obc.ConfidentialityLevel_PUBLIC,
		},
	}

	otx, err := obc.NewChaincodeExecute(cis, uuid, obc.Transaction_CHAINCODE_QUERY)
	if err != nil {
		return nil, nil, err
	}
	tx, err := invoker.NewChaincodeQuery(cis, uuid)
	return otx, tx, err
}
示例#7
0
func (client *clientImpl) createExecuteTx(chaincodeInvocation *obc.ChaincodeInvocationSpec, uuid string, nonce []byte) (*obc.Transaction, error) {
	/// Create a new transaction
	tx, err := obc.NewChaincodeExecute(chaincodeInvocation, uuid, obc.Transaction_CHAINCODE_EXECUTE)
	if err != nil {
		client.error("Failed creating new transaction [%s].", err.Error())
		return nil, err
	}

	// Copy metadata from ChaincodeSpec
	tx.Metadata = chaincodeInvocation.ChaincodeSpec.Metadata

	if nonce == nil {
		tx.Nonce, err = utils.GetRandomBytes(utils.NonceSize)
		if err != nil {
			client.error("Failed creating nonce [%s].", err.Error())
			return nil, err
		}
	} else {
		// TODO: check that it is a well formed nonce
		tx.Nonce = nonce
	}

	// Handle confidentiality
	if chaincodeInvocation.ChaincodeSpec.ConfidentialityLevel == obc.ConfidentialityLevel_CONFIDENTIAL {
		// 1. set confidentiality level and nonce
		tx.ConfidentialityLevel = obc.ConfidentialityLevel_CONFIDENTIAL

		// 2. set confidentiality protocol version
		tx.ConfidentialityProtocolVersion = "1.2"

		// 3. encrypt tx
		err = client.encryptTx(tx)
		if err != nil {
			client.error("Failed encrypting payload [%s].", err.Error())
			return nil, err

		}
	}

	return tx, nil
}
示例#8
0
func createConfidentialExecuteTransaction(t *testing.T) (*obc.Transaction, *obc.Transaction, error) {
	uuid, err := util.GenerateUUID()
	if err != nil {
		return nil, nil, err
	}

	cis := &obc.ChaincodeInvocationSpec{
		ChaincodeSpec: &obc.ChaincodeSpec{
			Type:                 obc.ChaincodeSpec_GOLANG,
			ChaincodeID:          &obc.ChaincodeID{Path: "Contract001"},
			CtorMsg:              nil,
			ConfidentialityLevel: obc.ConfidentialityLevel_CONFIDENTIAL,
		},
	}

	otx, err := obc.NewChaincodeExecute(cis, uuid, obc.Transaction_CHAINCODE_EXECUTE)
	if err != nil {
		return nil, nil, err
	}
	tx, err := invoker.NewChaincodeExecute(cis, uuid)
	return otx, tx, err
}
示例#9
0
// Handles request to query another chaincode
func (handler *Handler) handleQueryChaincode(msg *pb.ChaincodeMessage) {
	go func() {
		// Check if this is the unique request from this chaincode uuid
		uniqueReq := handler.createUUIDEntry(msg.Uuid)
		if !uniqueReq {
			// Drop this request
			chaincodeLogger.Debug("[%s]Another request pending for this Uuid. Cannot process.", shortuuid(msg.Uuid))
			return
		}

		var serialSendMsg *pb.ChaincodeMessage

		defer func() {
			handler.deleteUUIDEntry(msg.Uuid)
			handler.serialSend(serialSendMsg)
		}()

		chaincodeSpec := &pb.ChaincodeSpec{}
		unmarshalErr := proto.Unmarshal(msg.Payload, chaincodeSpec)
		if unmarshalErr != nil {
			payload := []byte(unmarshalErr.Error())
			chaincodeLogger.Debug("[%s]Unable to decipher payload. Sending %s", shortuuid(msg.Uuid), pb.ChaincodeMessage_ERROR)
			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
			return
		}

		// Get the chaincodeID to invoke
		newChaincodeID := chaincodeSpec.ChaincodeID.Name

		// Create the transaction object
		chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: chaincodeSpec}
		transaction, _ := pb.NewChaincodeExecute(chaincodeInvocationSpec, msg.Uuid, pb.Transaction_CHAINCODE_QUERY)

		// Launch the new chaincode if not already running
		_, chaincodeInput, launchErr := handler.chaincodeSupport.LaunchChaincode(context.Background(), transaction)
		if launchErr != nil {
			payload := []byte(launchErr.Error())
			chaincodeLogger.Debug("[%s]Failed to launch invoked chaincode. Sending %s", shortuuid(msg.Uuid), pb.ChaincodeMessage_ERROR)
			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
			return
		}

		// TODO: Need to handle timeout correctly
		timeout := time.Duration(30000) * time.Millisecond

		ccMsg, _ := createQueryMessage(transaction.Uuid, chaincodeInput)

		// Query the chaincode
		//TODOOOOOOOOOOOOOOOOOOOOOOOOO - pass transaction to Execute
		response, execErr := handler.chaincodeSupport.Execute(context.Background(), newChaincodeID, ccMsg, timeout, nil)

		if execErr != nil {
			// Send error msg back to chaincode and trigger event
			payload := []byte(execErr.Error())
			chaincodeLogger.Debug("[%s]Failed to handle %s. Sending %s", shortuuid(msg.Uuid), msg.Type.String(), pb.ChaincodeMessage_ERROR)
			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
			return
		}

		// Send response msg back to chaincode.
		chaincodeLogger.Debug("[%s]Completed %s. Sending %s", shortuuid(msg.Uuid), msg.Type.String(), pb.ChaincodeMessage_RESPONSE)
		serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: response.Payload, Uuid: msg.Uuid}
	}()
}
示例#10
0
// Handles request to ledger to put state
func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
	go func() {
		msg, _ := e.Args[0].(*pb.ChaincodeMessage)
		// First check if this UUID is a transaction; error otherwise
		if !handler.isTransaction[msg.Uuid] {
			payload := []byte(fmt.Sprintf("Cannot handle %s in query context", msg.Type.String()))
			chaincodeLogger.Debug("[%s]Cannot handle %s in query context. Sending %s", shortuuid(msg.Uuid), msg.Type.String(), pb.ChaincodeMessage_ERROR)
			errMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
			handler.triggerNextState(errMsg, true)
			return
		}

		chaincodeLogger.Debug("[%s]state is %s", shortuuid(msg.Uuid), state)
		// Check if this is the unique request from this chaincode uuid
		uniqueReq := handler.createUUIDEntry(msg.Uuid)
		if !uniqueReq {
			// Drop this request
			chaincodeLogger.Debug("Another request pending for this Uuid. Cannot process.")
			return
		}

		var triggerNextStateMsg *pb.ChaincodeMessage

		defer func() {
			handler.deleteUUIDEntry(msg.Uuid)
			chaincodeLogger.Debug("[%s]enterBusyState trigger event %s", shortuuid(triggerNextStateMsg.Uuid), triggerNextStateMsg.Type)
			handler.triggerNextState(triggerNextStateMsg, true)
		}()

		ledgerObj, ledgerErr := ledger.GetLedger()
		if ledgerErr != nil {
			// Send error msg back to chaincode and trigger event
			payload := []byte(ledgerErr.Error())
			chaincodeLogger.Debug("[%s]Failed to handle %s. Sending %s", shortuuid(msg.Uuid), msg.Type.String(), pb.ChaincodeMessage_ERROR)
			triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
			return
		}

		chaincodeID := handler.ChaincodeID.Name
		var err error
		var res []byte

		if msg.Type.String() == pb.ChaincodeMessage_PUT_STATE.String() {
			putStateInfo := &pb.PutStateInfo{}
			unmarshalErr := proto.Unmarshal(msg.Payload, putStateInfo)
			if unmarshalErr != nil {
				payload := []byte(unmarshalErr.Error())
				chaincodeLogger.Debug("[%s]Unable to decipher payload. Sending %s", shortuuid(msg.Uuid), pb.ChaincodeMessage_ERROR)
				triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
				return
			}

			var pVal []byte
			// Encrypt the data if the confidential is enabled
			if pVal, err = handler.encrypt(msg.Uuid, putStateInfo.Value); err == nil {
				// Invoke ledger to put state
				err = ledgerObj.SetState(chaincodeID, putStateInfo.Key, pVal)
			}
		} else if msg.Type.String() == pb.ChaincodeMessage_DEL_STATE.String() {
			// Invoke ledger to delete state
			key := string(msg.Payload)
			err = ledgerObj.DeleteState(chaincodeID, key)
		} else if msg.Type.String() == pb.ChaincodeMessage_INVOKE_CHAINCODE.String() {
			chaincodeSpec := &pb.ChaincodeSpec{}
			unmarshalErr := proto.Unmarshal(msg.Payload, chaincodeSpec)
			if unmarshalErr != nil {
				payload := []byte(unmarshalErr.Error())
				chaincodeLogger.Debug("[%s]Unable to decipher payload. Sending %s", shortuuid(msg.Uuid), pb.ChaincodeMessage_ERROR)
				triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
				return
			}

			// Get the chaincodeID to invoke
			newChaincodeID := chaincodeSpec.ChaincodeID.Name

			// Create the transaction object
			chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: chaincodeSpec}
			transaction, _ := pb.NewChaincodeExecute(chaincodeInvocationSpec, msg.Uuid, pb.Transaction_CHAINCODE_EXECUTE)

			// Launch the new chaincode if not already running
			_, chaincodeInput, launchErr := handler.chaincodeSupport.LaunchChaincode(context.Background(), transaction)
			if launchErr != nil {
				payload := []byte(launchErr.Error())
				chaincodeLogger.Debug("[%s]Failed to launch invoked chaincode. Sending %s", shortuuid(msg.Uuid), pb.ChaincodeMessage_ERROR)
				triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
				return
			}

			// TODO: Need to handle timeout correctly
			timeout := time.Duration(30000) * time.Millisecond

			ccMsg, _ := createTransactionMessage(transaction.Uuid, chaincodeInput)

			// Execute the chaincode
			//TODOOOOOOOOOOOOOOOOOOOOOOOOO - pass transaction to Execute
			response, execErr := handler.chaincodeSupport.Execute(context.Background(), newChaincodeID, ccMsg, timeout, nil)
			err = execErr
			res = response.Payload
		}

		if err != nil {
			// Send error msg back to chaincode and trigger event
			payload := []byte(err.Error())
			chaincodeLogger.Debug("[%s]Failed to handle %s. Sending %s", shortuuid(msg.Uuid), msg.Type.String(), pb.ChaincodeMessage_ERROR)
			triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Uuid: msg.Uuid}
			return
		}

		// Send response msg back to chaincode.
		chaincodeLogger.Debug("[%s]Completed %s. Sending %s", shortuuid(msg.Uuid), msg.Type.String(), pb.ChaincodeMessage_RESPONSE)
		triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Uuid: msg.Uuid}
	}()
}
示例#11
0
func (client *clientImpl) NewChaincodeQuery(chaincodeInvocation *obc.ChaincodeInvocationSpec, uuid string) (*obc.Transaction, error) {
	// Verify that the client is initialized
	if !client.isInitialized {
		return nil, utils.ErrNotInitialized
	}

	/// Create a new transaction
	tx, err := obc.NewChaincodeExecute(chaincodeInvocation, uuid, obc.Transaction_CHAINCODE_QUERY)
	if err != nil {
		client.node.log.Error("Failed creating new transaction [%s].", err.Error())
		return nil, err
	}

	if chaincodeInvocation.ChaincodeSpec.ConfidentialityLevel == obc.ConfidentialityLevel_CONFIDENTIAL {
		// 1. set confidentiality level and nonce
		tx.ConfidentialityLevel = obc.ConfidentialityLevel_CONFIDENTIAL
		tx.Nonce, err = utils.GetRandomBytes(utils.NonceSize)
		if err != nil {
			client.node.log.Error("Failed creating nonce [%s].", err.Error())
			return nil, err
		}

		// 2. encrypt tx
		err = client.encryptTx(tx)
		if err != nil {
			client.node.log.Error("Failed encrypting payload [%s].", err.Error())
			return nil, err

		}
	}

	// Sign the transaction

	// Implement like this: getNextTCert returns only a TCert
	// Then, invoke signWithTCert to sign the signature

	// Get next available (not yet used) transaction certificate
	// with the relative signing key.
	rawTCert, err := client.getNextTCert()
	if err != nil {
		client.node.log.Error("Failed getting next transaction certificate [%s].", err.Error())
		return nil, err
	}

	// Append the certificate to the transaction
	client.node.log.Debug("Appending certificate [%s].", utils.EncodeBase64(rawTCert))
	tx.Cert = rawTCert

	// Sign the transaction and append the signature
	// 1. Marshall tx to bytes
	rawTx, err := proto.Marshal(tx)
	if err != nil {
		client.node.log.Error("Failed marshaling tx [%s].", err.Error())
		return nil, err
	}

	// 2. Sign rawTx and check signature
	client.node.log.Debug("Signing tx [%s].", utils.EncodeBase64(rawTx))
	rawSignature, err := client.signWithTCert(rawTCert, rawTx)
	if err != nil {
		client.node.log.Error("Failed creating signature [%s].", err.Error())
		return nil, err
	}

	// 3. Append the signature
	tx.Signature = rawSignature

	client.node.log.Debug("Appending signature [%s].", utils.EncodeBase64(rawSignature))

	return tx, nil
}