600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Hyperledger Fabric资产案例-链码实例

Hyperledger Fabric资产案例-链码实例

时间:2018-12-16 00:24:53

相关推荐

Hyperledger Fabric资产案例-链码实例

案例分析

功能

开户和销户资产登记,资产上链,与具体的用户绑定资产转让,资产所有权变更查询功能,用户查询,资产查询,资产变更的历史查询

业务实体

用户: 名字、身份证(标识)、资产列表

资产:名字、标识、特殊属性列表(车:排量、品牌、座位)

资产变更记录

资产标识资产的原始拥有者资产变更后的拥有者

交互方法

用户开户

参数:名字、标识用户销户

参数:标识资产登记

参数:名字、标识、特殊属性列表、拥有者资产转让

参数:拥有者、资产标识、受让者用户查询

参数:用户标识;返回值:用户实体资产查询

参数:资产标识;返回值:资产实体资产的变更历史查询

参数:资产标识;返回值:资产的变更记录列表

案例测试

创建通道的创世交易(channel名字不能有大写)

configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./config/assetschannel.tx -channelID assetschannel

启动网络

docker-compose up -d

交互执行

docker exec -it cli bash

创建通道

peer channel create -o :7050 -c assetschannel -f /etc/hyperledger/config/assetschannel.tx

加入通道(一个peer可以加入多个通道)

peer channel join -b assetschannel.block

安装链码

peer chaincode install -n assets -v 1.0.0 -l golang -p /chaincode/assetsExchange

实例化链码

peer chaincode instantiate -o :7050 -C assetschannel -n assets -v 1.0.0 -l golang -c'{"Args":["init"]}'

测试方法

用户开户

peer chaincode invoke -C assetschannel -n assets -c '{"Args":["userRegister","user1","user1"]}'

用户查询

peer chaincode query -C assetschannel -n assets -c '{"Args":["queryUser","user1"]}'

资产登记

peer chaincode invoke -C assetschannel -n assets -c '{"Args":["assetEnroll","asset1","asset1","metadate","user1"]}'

资产查询

peer chaincode query -C assetschannel -n assets -c '{"Args":["queryAsset","asset1"]}'

再查询用户,可以看到用户资产已经改变

peer chaincode query -C assetschannel -n assets -c '{"Args":["queryUser","user1"]}'

资产转让

新建用户user2

peer chaincode invoke -C assetschannel -n assets -c '{"Args":["userRegister","user2","user2"]}'

资产转让,user1的资产asset1转给user2

peer chaincode invoke -C assetschannel -n assets -c '{"Args":["assetExchange","user1","asset1","user2"]}'

查询资产变更历史

peer chaincode query -C assetschannel -n assets -c '{"Args":["queryAssetHistory","asset1"]}'

删除用户,用户的资产会被同时删除

peer chaincode invoke -C assetschannel -n assets -c '{"Args":["userDestroy","user2"]}'

案例代码

package mainimport ("encoding/json""fmt""/hyperledger/fabric/core/chaincode/shim"pb "/hyperledger/fabric/protos/peer")//定义链码type AssetsExchangeCC struct {}//资产默认的原始拥有者const (originOwner = "originOwnerPlaceholder")//资产type Asset struct {Namestring `json:"name"`Id string `json:"id"`Metadata string `json:"metadata"`}//用户type User struct {Name string `json:"name"`Idstring `json:"id"`Assets []string `json:"assets"`}//资产变更记录type AssetHistory struct {//资产标识AssetId string `json:"asset_id"`//资产的原始拥有者OriginOwnerId string `json:"origin_owner_id"`//变更后的拥有者CurrentOwnerId string `json:"current_owner_id"`}//链码的初始化func (c *AssetsExchangeCC) Init(stub shim.ChaincodeStubInterface) pb.Response {return shim.Success(nil)}//链码交互func (c *AssetsExchangeCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {//得到方法名funcName, args := stub.GetFunctionAndParameters()//根据不同方法去判断switch funcName {case "userRegister"://用户开户return userRegister(stub, args)case "userDestroy"://用户销户return userDestroy(stub, args)case "assetEnroll"://资产登记return assetEnroll(stub, args)case "assetExchange"://资产转让return assetExchange(stub, args)case "queryUser"://用户查询return queryUser(stub, args)case "queryAsset"://资产查询return queryAsset(stub, args)case "queryAssetHistory"://资产变更历史查询return queryAssetHistory(stub, args)default:return shim.Error(fmt.Sprintf("不支持的方法:%s", funcName))}}//用户开户func userRegister(stub shim.ChaincodeStubInterface, args []string) pb.Response {//判断个数必须为2个if len(args) != 2 {return shim.Error("参数个数错误")}//判断传过来的参数是a否为空name := args[0]id := args[1]if name == "" || id == "" {return shim.Error("无效的参数")}//判断用户是否存在,若存在,则报错if userBytes, err := stub.GetState(constructUserKey(id)); err == nil && len(userBytes) != 0 {return shim.Error("用户已存在")}//写入世界状态,传过来的是用户的名字和id,绑定User结构体 make([]string,0)user := &User{Name: name,Id:id,Assets: make([]string, 0),}//序列化userBytes, err := json.Marshal(user)if err != nil {return shim.Error(fmt.Sprintf("序列化与用户失败 %s", err))}//将对象状态写入数据库if err := stub.PutState(constructUserKey(id), userBytes); err != nil {return shim.Error(fmt.Sprintf("存入用户失败 %s", err))}//返回成功return shim.Success(nil)}func constructUserKey(userId string) string {return fmt.Sprintf("user_%s", userId)}//用户销户func userDestroy(stub shim.ChaincodeStubInterface, args []string) pb.Response {//参数个数1个if len(args) != 1 {return shim.Error("参数个数不对")}//校验参数正确性id := args[0]if id == "" {return shim.Error("无效的参数")}//判断用户是否存在userBytes, err := stub.GetState(constructUserKey(id))if err != nil && len(userBytes) == 0 {return shim.Error("找不到用户")}//写入状态if err := stub.DelState(constructUserKey(id)); err != nil {return shim.Error(fmt.Sprintf("删除用户失败 %s", err))}//删除用户名下的资产user := new(User)if err := json.Unmarshal(userBytes, user); err != nil {return shim.Error(fmt.Sprintf("反序列化失败 %s", err))}for _, assetid := range user.Assets {if err := stub.DelState(constructAssetKey(assetid)); err != nil {return shim.Error(fmt.Sprintf("删除资产失败 %s", err))}}return shim.Success(nil)}//使用组合键来区分//所有的资产,用asset开头func constructAssetKey(assetId string) string {return fmt.Sprintf("asset_%s", assetId)}//资产登记func assetEnroll(stub shim.ChaincodeStubInterface, args []string) pb.Response {if len(args) != 4 {return shim.Error("参数个数不对")}//验证正确性assetName := args[0]assetId := args[1]metadata := args[2]ownerId := args[3]//metadata可以为空if assetName == "" || assetId == "" || ownerId == "" {return shim.Error("无效的参数")}//验证拥有者是否存在,拥有者必须存在userBytes, err := stub.GetState(constructUserKey(ownerId))if err != nil || len(userBytes) == 0 {return shim.Error("找不到用户")}//验证资产是否存在,资产必须不存在if assetBytes, err := stub.GetState(constructAssetKey(assetId)); err == nil && len(assetBytes) != 0 {return shim.Error("资产已经存在")}//写入状态asset := &Asset{Name:assetName,Id: assetId,Metadata: metadata,}//序列化assetBytes, err := json.Marshal(asset)if err != nil {return shim.Error(fmt.Sprintf("序列化失败 %s", err))}//保存资产if err := stub.PutState(constructAssetKey(assetId), assetBytes); err != nil {return shim.Error(fmt.Sprintf("保存失败 %s", err))}//拥有者user := new(User)if err := json.Unmarshal(userBytes, user); err != nil {return shim.Error(fmt.Sprintf("反序列化失败 %s", err))}user.Assets = append(user.Assets, assetId)if userBytes, err = json.Marshal(user); err != nil {return shim.Error(fmt.Sprintf("序列化用户失败 %s", err))}//存储用户状态if err := stub.PutState(constructUserKey(user.Id), userBytes); err != nil {return shim.Error(fmt.Sprintf("保存用户失败 %s", err))}//资产历史变更history := &AssetHistory{AssetId: assetId,OriginOwnerId: originOwner,CurrentOwnerId: ownerId,}historyBytes, err := json.Marshal(history)if err != nil {return shim.Error(fmt.Sprintf("序列化失败 %s", err))}//使用fabric内置的组合键机制historyKey, err := stub.CreateCompositeKey("history", []string{assetId,originOwner,ownerId,})if err != nil {return shim.Error(fmt.Sprintf("创建key失败 %s", err))}//资产变更存储if err := stub.PutState(historyKey, historyBytes); err != nil {return shim.Error(fmt.Sprintf("保存变更历史失败 %s", err))}return shim.Success(nil)}//资产转让func assetExchange(stub shim.ChaincodeStubInterface, args []string) pb.Response {//参数个数为3个if len(args) != 3 {return shim.Error("参数个数不对")}//参数校验ownerId := args[0]assetId := args[1]currentOwnerId := args[2]if ownerId == "" || assetId == "" || currentOwnerId == "" {return shim.Error("无效的参数")}//验证当前和受让后的用户是否存在originOwnerBytes, err := stub.GetState(constructUserKey(ownerId))if err != nil || len(originOwnerBytes) == 0 {return shim.Error("用户找不到")}currentOwnerBytes, err := stub.GetState(constructUserKey(currentOwnerId))if err != nil || len(currentOwnerBytes) == 0 {return shim.Error("用户找不到")}//验证资产存在assetBytes, err := stub.GetState(constructAssetKey(assetId))if err != nil || len(assetBytes) == 0 {return shim.Error("资产找不到")}//校验原始拥有者确实拥有当前变更的资产originOwner := new(User)if err := json.Unmarshal(originOwnerBytes, originOwner); err != nil {return shim.Error(fmt.Sprintf("反序列化失败 %s", err))}//定义标记,标识资产是否存在aidexist := falsefor _, aid := range originOwner.Assets {if aid == assetId {//若找到该资产,则变更状态,结束循环aidexist = truebreak}}if !aidexist {return shim.Error("资产所有者不匹配")}//写入状态//1.将资产的原始拥有者资产id删除//2.新拥有者写入资产id,资产绑定//3.资产变更记录assetIds := make([]string, 0)for _, aid := range originOwner.Assets {if aid == assetId {//遍历到了要转让的资产continue}assetIds = append(assetIds, aid)}originOwner.Assets = assetIds//序列化originOwnerBytes, err = json.Marshal(originOwner)if err != nil {return shim.Error(fmt.Sprintf("序列化失败 %s", err))}//存储原始拥有者if err := stub.PutState(constructUserKey(ownerId), originOwnerBytes); err != nil {return shim.Error(fmt.Sprintf("存储用户失败 %s", err))}//当前拥有者currentOwner := new(User)if err := json.Unmarshal(currentOwnerBytes, currentOwner); err != nil {return shim.Error(fmt.Sprintf("反序列化失败 %s", err))}//绑定资产currentOwner.Assets = append(currentOwner.Assets, assetId)currentOwnerBytes, err = json.Marshal(currentOwner)if err != nil {return shim.Error(fmt.Sprintf("序列化失败 %s", err))}//存储if err := stub.PutState(constructUserKey(currentOwnerId), currentOwnerBytes); err != nil {return shim.Error("保存用户失败")}//插入资产变更记录history := &AssetHistory{AssetId: assetId,OriginOwnerId: ownerId,CurrentOwnerId: currentOwnerId,}historyBytes, err := json.Marshal(history)if err != nil {return shim.Error(fmt.Sprintf("序列化失败 %s", err))}historyKey, err := stub.CreateCompositeKey("history", []string{assetId,ownerId,currentOwnerId,})if err != nil {return shim.Error(fmt.Sprintf("创建key失败 %s", err))}//存储历史变更记录if err := stub.PutState(historyKey, historyBytes); err != nil {return shim.Error(fmt.Sprintf("保存失败 %s", err))}return shim.Success(nil)}//用户查询func queryUser(stub shim.ChaincodeStubInterface, args []string) pb.Response {//参数个数1个if len(args) != 1 {return shim.Error("参数个数不对")}//校验正确性ownerId := args[0]if ownerId == "" {return shim.Error("无效的参数")}userBytes, err := stub.GetState(constructUserKey(ownerId))if err != nil || len(userBytes) == 0 {return shim.Error("找不到用户")}return shim.Success(userBytes)}//资产查询func queryAsset(stub shim.ChaincodeStubInterface, args []string) pb.Response {//参数个数1个if len(args) != 1 {return shim.Error("参数个数不对")}//校验正确性assetId := args[0]if assetId == "" {return shim.Error("无效的参数")}assetBytes, err := stub.GetState(constructAssetKey(assetId))if err != nil || len(assetBytes) == 0 {return shim.Error("找不到资产")}return shim.Success(assetBytes)}//资产历史变更查询func queryAssetHistory(stub shim.ChaincodeStubInterface, args []string) pb.Response {//参数个数1个if len(args) != 1 && len(args) != 2 {return shim.Error("参数个数不对")}//校验参数的正确性assetId := args[0]if assetId == "" {return shim.Error("无效的参数")}//queryType:all//默认为allqueryType := "all"if len(args) == 2 {//变为用户传的值queryType = args[1]}//参数校验if queryType != "all" && queryType != "exchange" && queryType != "enroll" {return shim.Error(fmt.Sprintf("未知的查询类型 %s", queryType))}//校验资产是否存在assetBytes, err := stub.GetState(constructAssetKey(assetId))if err != nil || len(assetBytes) == 0 {return shim.Error("资产找不到")}keys := make([]string, 0)keys = append(keys, assetId)switch queryType {case "enroll"://资产登记keys = append(keys, originOwner)case "exchange", "all":default:return shim.Error(fmt.Sprintf("不支持的类型 %s", queryType))}//组合键//得到迭代器result, err := stub.GetStateByPartialCompositeKey("history", keys)if err != nil {return shim.Error(fmt.Sprintf("查询历史错误 %s", err))}//关闭defer result.Close()histories := make([]*AssetHistory, 0)for result.HasNext() {historyVal, err := result.Next()if err != nil {return shim.Error(fmt.Sprintf("查询错误 %s", err))}history := new(AssetHistory)if err := json.Unmarshal(historyVal.GetValue(), history); err != nil {return shim.Error(fmt.Sprintf("反序列化失败 %s", err))}//过滤,不是资产转让的记录过滤if queryType == "exchange" && history.OriginOwnerId == originOwner {continue}histories = append(histories, history)}historiesBytes, err := json.Marshal(histories)if err != nil {return shim.Error(fmt.Sprintf("序列化失败 %s", err))}return shim.Success(historiesBytes)}func main() {err := shim.Start(new(AssetsExchangeCC))if err != nil {fmt.Println("启动链码失败")}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。