// RegisterSysCC registers the given system chaincode with the peer func RegisterSysCC(syscc *SystemChaincode) error { if peer.SecurityEnabled() { sysccLogger.Warning(fmt.Sprintf("Currently system chaincode does support security(%s,%s)", syscc.Name, syscc.Path)) return nil } if !syscc.Enabled || !isWhitelisted(syscc) { sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s) disabled", syscc.Name, syscc.Path)) return nil } err := inproccontroller.Register(syscc.Path, syscc.Chaincode) if err != nil { errStr := fmt.Sprintf("could not register (%s,%v): %s", syscc.Path, syscc, err) sysccLogger.Error(errStr) return fmt.Errorf(errStr) } chaincodeID := &protos.ChaincodeID{Path: syscc.Path, Name: syscc.Name} spec := protos.ChaincodeSpec{Type: protos.ChaincodeSpec_Type(protos.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeID: chaincodeID, CtorMsg: &protos.ChaincodeInput{Args: syscc.InitArgs}} if deployErr := deploySysCC(context.Background(), &spec); deployErr != nil { errStr := fmt.Sprintf("deploy chaincode failed: %s", deployErr) sysccLogger.Error(errStr) return fmt.Errorf(errStr) } sysccLogger.Info("system chaincode %s(%s) registered", syscc.Name, syscc.Path) return err }
// chaincodeDeploy deploys the chaincode. On success, the chaincode name // (hash) is printed to STDOUT for use by subsequent chaincode-related CLI // commands. func chaincodeDeploy(cmd *cobra.Command, args []string) (err error) { if err = checkChaincodeCmdParams(cmd); err != nil { return } devopsClient, err := getDevopsClient(cmd) if err != nil { err = fmt.Errorf("Error building %s: %s", chainFuncName, err) return } // Build the spec input := &pb.ChaincodeInput{} if err = json.Unmarshal([]byte(chaincodeCtorJSON), &input); err != nil { err = fmt.Errorf("Chaincode argument error: %s", err) return } var attributes []string if err = json.Unmarshal([]byte(chaincodeAttributesJSON), &attributes); err != nil { err = fmt.Errorf("Chaincode argument error: %s", err) return } chaincodeLang = strings.ToUpper(chaincodeLang) spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value[chaincodeLang]), ChaincodeID: &pb.ChaincodeID{Path: chaincodePath, Name: chaincodeName}, CtorMsg: input, Attributes: attributes} // If security is enabled, add client login token if core.SecurityEnabled() { logger.Debug("Security is enabled. Include security context in deploy spec") if chaincodeUsr == undefinedParamValue { err = errors.New("Must supply username for chaincode when security is enabled") return } // Retrieve the CLI data storage path // Returns /var/openchain/production/client/ localStore := getCliFilePath() // Check if the user is logged in before sending transaction if _, err = os.Stat(localStore + "loginToken_" + chaincodeUsr); err == nil { logger.Infof("Local user '%s' is already logged in. Retrieving login token.\n", chaincodeUsr) // Read in the login token token, err := ioutil.ReadFile(localStore + "loginToken_" + chaincodeUsr) if err != nil { panic(fmt.Errorf("Fatal error when reading client login token: %s\n", err)) } // Add the login token to the chaincodeSpec spec.SecureContext = string(token) // If privacy is enabled, mark chaincode as confidential if viper.GetBool("security.privacy") { logger.Info("Set confidentiality level to CONFIDENTIAL.\n") spec.ConfidentialityLevel = pb.ConfidentialityLevel_CONFIDENTIAL } } else { // Check if the token is not there and fail if os.IsNotExist(err) { err = fmt.Errorf("User '%s' not logged in. Use the 'login' command to obtain a security token.", chaincodeUsr) return } // Unexpected error panic(fmt.Errorf("Fatal error when checking for client login token: %s\n", err)) } } else { if chaincodeUsr != undefinedParamValue { logger.Warning("Username supplied but security is disabled.") } if viper.GetBool("security.privacy") { panic(errors.New("Privacy cannot be enabled as requested because security is disabled")) } } chaincodeDeploymentSpec, err := devopsClient.Deploy(context.Background(), spec) if err != nil { err = fmt.Errorf("Error building %s: %s\n", chainFuncName, err) return } logger.Infof("Deploy result: %s", chaincodeDeploymentSpec.ChaincodeSpec) fmt.Println(chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name) return nil }
// chaincodeInvokeOrQuery invokes or queries the chaincode. If successful, the // INVOKE form prints the transaction ID on STDOUT, and the QUERY form prints // the query result on STDOUT. A command-line flag (-r, --raw) determines // whether the query result is output as raw bytes, or as a printable string. // The printable form is optionally (-x, --hex) a hexadecimal representation // of the query response. If the query response is NIL, nothing is output. func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err error) { if err = checkChaincodeCmdParams(cmd); err != nil { return } if chaincodeName == "" { err = errors.New("Name not given for invoke/query") return } devopsClient, err := getDevopsClient(cmd) if err != nil { err = fmt.Errorf("Error building %s: %s", chainFuncName, err) return } // Build the spec input := &pb.ChaincodeInput{} if err = json.Unmarshal([]byte(chaincodeCtorJSON), &input); err != nil { err = fmt.Errorf("Chaincode argument error: %s", err) return } var attributes []string if err = json.Unmarshal([]byte(chaincodeAttributesJSON), &attributes); err != nil { err = fmt.Errorf("Chaincode argument error: %s", err) return } chaincodeLang = strings.ToUpper(chaincodeLang) spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value[chaincodeLang]), ChaincodeID: &pb.ChaincodeID{Name: chaincodeName}, CtorMsg: input, Attributes: attributes} // If security is enabled, add client login token if core.SecurityEnabled() { if chaincodeUsr == undefinedParamValue { err = errors.New("Must supply username for chaincode when security is enabled") return } // Retrieve the CLI data storage path // Returns /var/openchain/production/client/ localStore := getCliFilePath() // Check if the user is logged in before sending transaction if _, err = os.Stat(localStore + "loginToken_" + chaincodeUsr); err == nil { logger.Infof("Local user '%s' is already logged in. Retrieving login token.\n", chaincodeUsr) // Read in the login token token, err := ioutil.ReadFile(localStore + "loginToken_" + chaincodeUsr) if err != nil { panic(fmt.Errorf("Fatal error when reading client login token: %s\n", err)) } // Add the login token to the chaincodeSpec spec.SecureContext = string(token) // If privacy is enabled, mark chaincode as confidential if viper.GetBool("security.privacy") { logger.Info("Set confidentiality level to CONFIDENTIAL.\n") spec.ConfidentialityLevel = pb.ConfidentialityLevel_CONFIDENTIAL } } else { // Check if the token is not there and fail if os.IsNotExist(err) { err = fmt.Errorf("User '%s' not logged in. Use the 'login' command to obtain a security token.", chaincodeUsr) return } // Unexpected error panic(fmt.Errorf("Fatal error when checking for client login token: %s\n", err)) } } else { if chaincodeUsr != undefinedParamValue { logger.Warning("Username supplied but security is disabled.") } if viper.GetBool("security.privacy") { panic(errors.New("Privacy cannot be enabled as requested because security is disabled")) } } // Build the ChaincodeInvocationSpec message invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} if customIDGenAlg != undefinedParamValue { invocation.IdGenerationAlg = customIDGenAlg } var resp *pb.Response if invoke { resp, err = devopsClient.Invoke(context.Background(), invocation) } else { resp, err = devopsClient.Query(context.Background(), invocation) } if err != nil { if invoke { err = fmt.Errorf("Error invoking %s: %s\n", chainFuncName, err) } else { err = fmt.Errorf("Error querying %s: %s\n", chainFuncName, err) } return } if invoke { transactionID := string(resp.Msg) logger.Infof("Successfully invoked transaction: %s(%s)", invocation, transactionID) fmt.Println(transactionID) } else { logger.Infof("Successfully queried transaction: %s", invocation) if resp != nil { if chaincodeQueryRaw { if chaincodeQueryHex { err = errors.New("Options --raw (-r) and --hex (-x) are not compatible\n") return } os.Stdout.Write(resp.Msg) } else { if chaincodeQueryHex { fmt.Printf("%x\n", resp.Msg) } else { fmt.Println(string(resp.Msg)) } } } } return nil }
// MakeGenesis creates the genesis block based on configuration in core.yaml // and adds it to the blockchain. func MakeGenesis() error { once.Do(func() { ledger, err := ledger.GetLedger() if err != nil { makeGenesisError = err return } var genesisBlockExists bool if ledger.GetBlockchainSize() == 0 { genesisLogger.Info("Creating genesis block.") ledger.BeginTxBatch(0) } else { genesisBlockExists = true } var genesisTransactions []*protos.Transaction defer func() { if !genesisBlockExists && makeGenesisError == nil { genesisLogger.Info("Adding %d system chaincodes to the genesis block.", len(genesisTransactions)) ledger.CommitTxBatch(0, genesisTransactions, nil, nil) } }() //We are disabling the validity period deployment for now, we shouldn't even allow it if it's enabled in the configuration allowDeployValidityPeriod := false if isDeploySystemChaincodeEnabled() && allowDeployValidityPeriod { vpTransaction, deployErr := deployUpdateValidityPeriodChaincode(genesisBlockExists) if deployErr != nil { genesisLogger.Error("Error deploying validity period system chaincode for genesis block.", deployErr) makeGenesisError = deployErr return } genesisTransactions = append(genesisTransactions, vpTransaction) } if getGenesis() == nil { genesisLogger.Info("No genesis block chaincodes defined.") } else { chaincodes, chaincodesOK := genesis["chaincodes"].(map[interface{}]interface{}) if !chaincodesOK { genesisLogger.Info("No genesis block chaincodes defined.") ledger.CommitTxBatch(0, genesisTransactions, nil, nil) return } genesisLogger.Debug("Genesis chaincodes are %s", chaincodes) for i := range chaincodes { name := i.(string) genesisLogger.Debug("Chaincode %s", name) chaincode := chaincodes[name] chaincodeMap, chaincodeMapOK := chaincode.(map[interface{}]interface{}) if !chaincodeMapOK { genesisLogger.Error("Invalid chaincode defined in genesis configuration:", chaincode) makeGenesisError = fmt.Errorf("Invalid chaincode defined in genesis configuration: %s", chaincode) return } path, pathOK := chaincodeMap["path"].(string) if !pathOK { genesisLogger.Error("Invalid chaincode URL defined in genesis configuration:", chaincodeMap["path"]) makeGenesisError = fmt.Errorf("Invalid chaincode URL defined in genesis configuration: %s", chaincodeMap["path"]) return } chaincodeType, chaincodeTypeOK := chaincodeMap["type"].(string) if !chaincodeTypeOK { genesisLogger.Error("Invalid chaincode type defined in genesis configuration:", chaincodeMap["type"]) makeGenesisError = fmt.Errorf("Invalid chaincode type defined in genesis configuration: %s", chaincodeMap["type"]) return } if chaincodeType == "" { chaincodeType = "GOLANG" } chaincodeID := &protos.ChaincodeID{Path: path, Name: name} genesisLogger.Debug("Genesis chaincodeID %s", chaincodeID) constructorMap, constructorMapOK := chaincodeMap["constructor"].(map[interface{}]interface{}) if !constructorMapOK { genesisLogger.Error("Invalid chaincode constructor defined in genesis configuration:", chaincodeMap["constructor"]) makeGenesisError = fmt.Errorf("Invalid chaincode constructor defined in genesis configuration: %s", chaincodeMap["constructor"]) return } var spec protos.ChaincodeSpec if constructorMap == nil { genesisLogger.Debug("Genesis chaincode has no constructor.") spec = protos.ChaincodeSpec{Type: protos.ChaincodeSpec_Type(protos.ChaincodeSpec_Type_value[chaincodeType]), ChaincodeID: chaincodeID} } else { _, ctorArgsOK := constructorMap["args"] if !ctorArgsOK { genesisLogger.Error("Invalid chaincode constructor args defined in genesis configuration:", constructorMap["args"]) makeGenesisError = fmt.Errorf("Invalid chaincode constructor args defined in genesis configuration: %s", constructorMap["args"]) return } ctorArgs, ctorArgsOK := constructorMap["args"].([]interface{}) var ctorArgsStringArray []string if ctorArgsOK { genesisLogger.Debug("Genesis chaincode constructor args %s", ctorArgs) for j := 0; j < len(ctorArgs); j++ { ctorArgsStringArray = append(ctorArgsStringArray, ctorArgs[j].(string)) } } spec = protos.ChaincodeSpec{Type: protos.ChaincodeSpec_Type(protos.ChaincodeSpec_Type_value[chaincodeType]), ChaincodeID: chaincodeID, CtorMsg: &protos.ChaincodeInput{Args: ctorArgsStringArray}} } transaction, _, deployErr := DeployLocal(context.Background(), &spec, genesisBlockExists) if deployErr != nil { genesisLogger.Error("Error deploying chaincode for genesis block.", deployErr) makeGenesisError = deployErr return } genesisTransactions = append(genesisTransactions, transaction) } //for } //else }) return makeGenesisError }