开发规范
防止出现panic后链代码容器异常
该内容仅适用于Go语言链代码开发。
为避免出现panic异常时链代码容器异常重启,找不到日志,导致问题无法及时定位,可在Invoke函数入口处添加defer语句时,出现panic异常时返回错误给客户端。
// 定义命名返回值,发生panic在defer里面赋值,确保客户端可以收到返回值 // 使用debug.PrintStack()将错误的堆栈信息打印到标准输出,方便问题定位 func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) (pr pb.Response) { defer func() { if err:=recover(); err != nil { fmt.Println("recover from invoke:", err) debug.PrintStack() pr = shim.Error(fmt.Sprintf("invoke painc. err: %v",err)) } }() fmt.Println("ex02 Invoke") function, args := stub.GetFunctionAndParameters() if function == "invoke" { // Make payment of X units from A to B return t.invoke(stub, args) } else if function == "delete" { // Deletes an entity from its state return t.delete(stub, args) } else if function == "query" { // the old "Query" is now implemented in invoke return t.query(stub, args) } pr = shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"") return pr }
分批次查询数据
查询账本数据时,如果在一次查询中返回过多的数据,会导致资源占用过多,接口延时较长(超过30s时peer会中断任务),应预先估计数据量,分批次进行查询。
修改或删除账本数据调用链代码时,同样也需要根据数据量大小确定是否采取分批次操作的方式处理。
合理使用索引(账本数据存储方式为CouchDB)
对于CouchDB来说,使用索引功能,写入数据时会消耗时间,但可明显提高数据查询速度。因此可以根据业务需要,合理的在某些字段上建立索引。
添加权限验证
对智能合约执行者的权限进行验证,防止无权限的用户执行链代码。
如果业务上不要求确定的某个组织进行背书,为确保链代码上的数据不被任意组织恶意修改(自己安装非法链代码,操作数据等),建议至少两个或两个以上组织共同参与背书。
参数校验
参数(包括入参和代码中定义的各种参数)在使用前需对其个数、类型、长度、取值范围等做校验,验证其合法性,防止出现数组越界等问题。
日志处理
开发时需要对业务逻辑复杂、容易出错的地方,使用fmt打印日志,便于调测。但是在开发调测结束后,需要将其删除,因为fmt会消耗时间和资源。
依赖配置
该内容仅适用于Java语言链代码开发。
请使用Gradle或Maven构建管理工具组织链代码项目。若链代码项目中包含非本地依赖,请确保对应区块链实例的节点均绑定了弹性ip。若链代码容器将运行在受限网络环境,请确保项目中的所有依赖已配置为本地依赖。示例链代码获取方法:登录区块链服务BCS控制台,进入“应用案例”,单击“Java示例Demo-Java SDK Demo”中“Chaincode_Java_Local_Demo”的“下载”按钮。