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 }
// 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 }
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 }
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 }
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 }
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 }
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 }
// 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} }() }
// 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} }() }
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 }