hyperledger fabric 1.0 源码分析之peer chaincode package

package命令的定义

func packageCmd(cf *ChaincodeCmdFactory, cdsFact ccDepSpecFactory) *cobra.Command {
	chaincodePackageCmd = &cobra.Command{
		Use:       "package",
		Short:     packageDesc,
		Long:      packageDesc,
		ValidArgs: []string{"1"},
		RunE: func(cmd *cobra.Command, args []string) error {
            //package命令入口
            //该命令必需且只有一个参数,指明输出文件
			if len(args) != 1 {
				return fmt.Errorf("output file not specified or invalid number of args (filename should be the only arg)")
			}
			//提供获取ChaincodeDeploymentSpec接口
			if cdsFact == nil {
				cdsFact = defaultCDSFactory
			}
			return chaincodePackage(cmd, args, cdsFact, cf)
		},
	}
    //加入以下标记
	flagList := []string{
		"lang",
		"ctor",
		"path",
		"name",
		"version",
	}
	attachFlags(chaincodePackageCmd, flagList)
    //额外绑定以下标记
	chaincodePackageCmd.Flags().BoolVarP(&createSignedCCDepSpec, "cc-package", "s", false, "create CC deployment spec for owner endorsements instead of raw CC deployment spec")
	chaincodePackageCmd.Flags().BoolVarP(&signCCDepSpec, "sign", "S", false, "if creating CC deployment spec package for owner endorsements, also sign it with local MSP")
	chaincodePackageCmd.Flags().StringVarP(&instantiationPolicy, "instantiate-policy", "i", "", "instantiation policy for the chaincode")

	return chaincodePackageCmd
}

chaincodePackage()

func chaincodePackage(cmd *cobra.Command, args []string, cdsFact ccDepSpecFactory, cf *ChaincodeCmdFactory) error {
	if cdsFact == nil {
		return fmt.Errorf("Error chaincode deployment spec factory not specified")
	}

	var err error
    //如果ChaincodeCmdFactory为空,者初始化
	if cf == nil {
		cf, err = InitCmdFactory(false, false)
		if err != nil {
			return err
		}
	}
    //获取ChaincodeSpec
	spec, err := getChaincodeSpec(cmd)
	if err != nil {
		return err
	}
    //cdsFact的定义
    //type ccDepSpecFactory func(spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error)
    //GO语言接口机制的不常见特性。它不仅是一个函数类型,还拥有自己的方法
    //ccDepSpecFactory是一个让函数值满足接口的一个适配器
    //获取ChaincodeDeploymentSpec
	cds, err := cdsFact(spec)
	if err != nil {
		return fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err)
	}

	var bytesToWrite []byte
    //命令绑定为false
	if createSignedCCDepSpec {    
		bytesToWrite, err = getChaincodeInstallPackage(cds, cf)
		if err != nil {
			return err
		}
	} else {
        //获取到chaincode字节流
		bytesToWrite = utils.MarshalOrPanic(cds)
	}

	logger.Debugf("Packaged chaincode into deployment spec of size <%d>, with args = %v", len(bytesToWrite), args)
    //将chaincode字节流写入指定参数
	fileToWrite := args[0]
	err = ioutil.WriteFile(fileToWrite, bytesToWrite, 0700)
	if err != nil {
		logger.Errorf("Failed writing deployment spec to file [%s]: [%s]", fileToWrite, err)
		return err
	}

	return err
}

方法详解

getChaincodeSpec()

func getChaincodeSpec(cmd *cobra.Command) (*pb.ChaincodeSpec, error) {
	spec := &pb.ChaincodeSpec{}
	if err := checkChaincodeCmdParams(cmd); err != nil {
		return spec, err
	}

	//将传入的参数反序列化
	input := &pb.ChaincodeInput{}
	if err := json.Unmarshal([]byte(chaincodeCtorJSON), &input); err != nil {
		return spec, fmt.Errorf("Chaincode argument error: %s", err)
	}
    //语言判断,chaincode不可为java
	chaincodeLang = strings.ToUpper(chaincodeLang)
	if pb.ChaincodeSpec_Type_value[chaincodeLang] == int32(pb.ChaincodeSpec_JAVA) {
		return nil, fmt.Errorf("Java chaincode is work-in-progress and disabled")
	}
    //返回ChaincodeSpec
	spec = &pb.ChaincodeSpec{
		Type:        pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value[chaincodeLang]),
		ChaincodeId: &pb.ChaincodeID{Path: chaincodePath, Name: chaincodeName, Version: chaincodeVersion},
		Input:       input,
	}
	return spec, nil
}

func checkChaincodeCmdParams(cmd *cobra.Command) error {
	//验证链码名称是否为空
	if chaincodeName == common.UndefinedParamValue {
		return fmt.Errorf("Must supply value for %s name parameter.", chainFuncName)
	}
    //验证链码版本
	if cmd.Name() == instantiateCmdName || cmd.Name() == installCmdName ||
		cmd.Name() == upgradeCmdName || cmd.Name() == packageCmdName {
		if chaincodeVersion == common.UndefinedParamValue {
			return fmt.Errorf("Chaincode version is not provided for %s", cmd.Name())
		}
	}
    //验证是否使用escc
	if escc != common.UndefinedParamValue {
		logger.Infof("Using escc %s", escc)
	} else {
		logger.Info("Using default escc")
		escc = "escc"
	}
    //验证是否使用vscc
	if vscc != common.UndefinedParamValue {
		logger.Infof("Using vscc %s", vscc)
	} else {
		logger.Info("Using default vscc")
		vscc = "vscc"
	}
    //验证策略是否有效
	if policy != common.UndefinedParamValue {
		p, err := cauthdsl.FromString(policy)
		if err != nil {
			return fmt.Errorf("Invalid policy %s", policy)
		}
		policyMarhsalled = putils.MarshalOrPanic(p)
	}

	//根据传入的参数,进行序列化
	if chaincodeCtorJSON != "{}" {
		var f interface{}
		err := json.Unmarshal([]byte(chaincodeCtorJSON), &f)
		if err != nil {
			return fmt.Errorf("Chaincode argument error: %s", err)
		}
		m := f.(map[string]interface{})
		sm := make(map[string]interface{})
		for k := range m {
			sm[strings.ToLower(k)] = m[k]
		}
        //获取到参数,和执行的方法invoke或query
		_, argsPresent := sm["args"]
		_, funcPresent := sm["function"]
		if !argsPresent || (len(m) == 2 && !funcPresent) || len(m) > 2 {
			return errors.New("Non-empty JSON chaincode parameters must contain the following keys: 'Args' or 'Function' and 'Args'")
		}
	} else {
		if cmd == nil || (cmd != chaincodeInstallCmd && cmd != chaincodePackageCmd) {
			return errors.New("Empty JSON chaincode parameters must contain the following keys: 'Args' or 'Function' and 'Args'")
		}
	}

	return nil
}

 

你可能感兴趣的:(区块链)