HyperLedger Fabric链码开发及测试

本文详细介绍了如何开发HyperLedger Fabric的链码,包括设计简单应用场景,定义School和Student结构体,实现添加、删除、查询和更新学校及学生信息的业务逻辑。还讲解了单元测试,利用shim.MockStub进行链码调试,以及在开发环境中测试链码的步骤,如启动网络、部署和调用链码。
摘要由CSDN通过智能技术生成

1.链码开发

先设计一个简单的应用场景,假设有这样的业务需求:

  1. 可以添加学校,信息包括学校名称、学校ID;
  2. 添加该学校的学生,信息包括姓名,用户ID,所在学校ID,所在班级名称;
  3. 更新学生信息;
  4. 根据学生ID查询学生信息;
  5. 根据学生ID删除学生信息;
  6. 根据学校ID删除学校信息,包括该学校下的所有学生。

接下来开发满足这些需求的链码。关键代码如下
1.1 定义School,Student结构体

type StudentChaincode struct {
}

type Student struct {
    UserId      int    `json:"user_id"` //学生id
    Name        string `json:"name"` //姓名
    SchoolId    string `json:"school_id"` //学校id
    Class       string `jsong:"class"` //班级名称
}

type School struct {
    SchoolId    string `json:"id"` //学校id
    School      string `json:"name"` //学校名称
}

1.2 部分业务需求的实现
1.2.1 添加学校
这里用到了shim.ChaincodeStubInterface的CreateCompositeKey,来创建联合主键。其实Fabric就是用U+0000来把各个联合主键的字段拼接起来,因为这个字符太特殊,所以很适合,对应的拆分联合主键的字段的方法是SplitCompositeKey

func (t *StudentChaincode) initSchool(stub shim.ChaincodeStubInterface, args []string) pd.Response {
    if len(args) != 2 {
        return shim.Error("Incorrect number of arguments. Expecting 2(school_id, school_name)")
    }

    schoolId := args[0]
    schoolName := args[1] 
    school := &School{schoolId, schoolName}

    //这里利用联合主键,使得查询school时,可以通过主键的“school”前缀找到所有school
    schoolKey, err := stub.CreateCompositeKey("School", []string{
  "school", schoolId})
    if err != nil {
        return shim.Error(err.Error())
    }

    //结构体转json字符串
    schoolJSONasBytes, err := json.Marshal(school)
    if err != nil {
        return shim.Error(err.Error())
    }
    //保存
    err = stub.PutState(schoolKey, schoolJSONasBytes)
    if err != nil {
        return shim.Error(err.Error())
    }
    return shim.Success(schoolJSONasBytes)
}

1.2.2 添加学生,需要检查所属学校是否已经存在。
抽出来的工具类方法querySchoolIds 中用到的GetStateByPartialCompositeKey 是对联合主键进行前缀匹配的查询

func (t *StudentChaincode) addStudent(stub shim.ChaincodeStubInterface, args []string) pd.Response {
    st, err := studentByArgs(args)
    if err != nil {
        return shim.Error(err.Error())
    }

    useridAsString := strconv.Itoa(st.UserId)

    //检查学校是否存在,不存在则添加失败
    schools := querySchoolIds(stub)
    if len(schools) > 0 {
        for _, schoolId := range schools {
            if schoolId == st.SchoolId {
                goto SchoolExists;
            }
        }
        fmt.Println("school " + st.SchoolId+ " does not exist")
        return shim.Error("school " + st.SchoolId+ " does not exist&
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值