一.fabric开发流程:
- 让什么数据上链:所有节点备份数据耗费空间,视频等不要上链
- 如何交互:-c “Args”[“方法名”,参数]
- 编写合约
- Init
- Invoke
- 拖到linux运行,基于配置好的网络去部署运行(安装和实例化)
- 合约交互
- SDK调用(页面点击或输入信息)
二.需求分析:
1.开发转让资产
2.功能
- 用户开户和销户
- 资产登记,资产上链,与具体的用户绑定
- 资产转让,资产所有权变更
- 查询功能,用户查询,资产查询,资产变更的历史查询
3.业务实体
- 用户
- 名字
- 身份证(标识)
- 资产列表
- 资产
- 名字
- 标识
- 特殊属性列表(车:排量、品牌、座位)
- 资产变更记录
- 资产标识
- 资产的原始拥有者
- 资产变更后的拥有者
4.交互方法
- 用户开户:参数:名字、标识
- 用户销户:标识
- 资产登记:名字、标识、特殊属性列表,拥有者
- 资产转让:拥有者、资产标识、受让者
- 用户查询:参数:标识;返回值:用户实体
- 资产查询:参数:标识;返回值:资产实体
- 资产的变更记录查询:参数:资产标识;返回值:资产的变更列表
合约编写和部署:
- 合约编写完成,传到linux对应目录
package main
import (
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"fmt"
"encoding/json"
)
//定义链码
type AssertsExchangeCC struct {
}
//资产默认的原始拥有者
const (
originOwner = "originOwnerPlaceholder"
)
//资产
type Asset struct {
Name string `json:"name"`
Id string `json:"id"`
Metadata string `json:"metadata"`
}
//用户
type User struct {
Name string `json:"name"`
Id string `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 *AssertsExchangeCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
//链码交互
func (c *AssertsExchangeCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
//得到方法名
funcName, args := stub.GetFunctionAndParameters()
//根据不同方法去判断
switch funcName {
case "userRegister":
//用户开户
return userRegister(stub, args)
case "userDestory":
//用户销户
return userDestory(stub, args)
case "assetEnroll":
//资产登记
return assetEnroll(stub, args)
case "assetExchange":
//资产转让
return assertExchange(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("参数个数不对")
}
//判断传过来的参数是否为空 ""
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 :&#