type Chaincode interface
func Init(stub ChaincodeStubInterface) peer.Respone
func Invoke(stub ChaincodeStubInterface) peer.Respone
GetFunctionAndParameters() (function string, params []string):返回调用链码时在交易提案中指定提供的被调用的函数名称及其参数列表
GetState(key string) ([]byte, error) :根据指定的 Key 查询相应的数据状态。
PutState(key string, value []byte) error:根据指定的 key,将对应的 value 保存在分类账本中。
DelState(key string) error:根据指定的 key 将对应的数据状态删除
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error):根据指定的 key 查询所有的历史记录信息。
GetPrivateDataQueryResult(collection, query string) (StateQueryIteratorInterface, error):根据指定的查询字符串执行富查询 (只支持支持富查询的 CouchDB)。
shim.Error(msg string) 是一个用于返回错误的函数
shim.Success(payload []byte) 是一个用于返回成功响应的函数。
Start(obj Chaincode) 是一个链码启动函数。在Hyperledger Fabric中,链码是通过容器化的方式运行的,而Start方法用于指定链码的入口点。
定义一个名为PaymentChaincode的结构体,声明Init与Invoke两个属于PaymentChaincode的方法。
type PaymentChaincode struct {
}
实现Init方法
func(account *PaymentChaincode) Init(stub shim.ChaincodeStubInterface)peer.Response {
// 初始化账户a的余额为100,账户b的余额为200
err:=stub.PutState("a",[]byte("100"))
if err != nil {
return shim.Error("初始化a发生错误"+ err.Error())
}
err=stub.PutState("b",[]byte("200"))
if err != nil {
return shim.Error("初始化b发生错误"+ err.Error())
}
//返回执行结果
return shim.Success(nil)
}
实现Invoke方法
func (account *PaymentChaincode) Invoke(stub shim.ChaincodeStubInterface)peer.Response {
funName,args := stub.GetFunctionAndParameters()
if funName =="find"{
return find(stub,args)
}else if funName =="transfer"{
return transfer(stub,args)
}
return shim.Error("不支持的操作")
}
自定义为find方法
//find方法表示查询余额功能实现
func find(stub shim.ChaincodeStubInterface,args []string)peer.Response{
if len(args)!=1{
return shim.Error("参数错误")
}
balance,err :=stub.GetState(args[0])
if err!=nil{
return shim.Error("获取账户"+args[0]+"余额发生错误:"+err.Error())
}
return shim.Success(balance)
}
自定义transfer方法(需要判断账户是否存在,转账是否成功)
//transfer方法表示转账功能实现
func transfer(stub shim.ChaincodeStubInterface,args []string)peer.Response{
if len(args)!=3{
return shim.Error("参数数量不正确")
}
//获取接收到的参数
fromAccount:=args[0]
toAccount:=args[1]
amount,_:=strconv.Atoi(args[2])
//获取俩个账户的余额信息
// 获取发送方和接收方的余额
fromBalanceBytes, err := stub.GetState(fromAccount)
if err != nil {
return shim.Error(fmt.Sprintf("获取账户 %s 余额失败:%s", fromAccount, err))
}
if fromBalanceBytes == nil {
return shim.Error(fmt.Sprintf("账户 %s 不存在", fromAccount))
}
toBalanceBytes, err := stub.GetState(toAccount)
if err != nil {
return shim.Error(fmt.Sprintf("获取账户 %s 余额失败:%s", toAccount, err))
}
if toBalanceBytes == nil {
return shim.Error(fmt.Sprintf("账户 %s 不存在", toAccount))
}
// 将字节转换为整数
fromBalance := int(fromBalanceBytes [0])
toBalance := int(toBalanceBytes[0])
//检查转账金额是否超过发送方余额
if fromBalance < amount {
return shim.Error("转账金额超过发送方余额")
}
// 更新发送方和接收方的余额
fromBalance -= amount
toBalance += amount
// 将更新后的余额写回账本中
err = stub.PutState(fromAccount, []byte(strconv.Itoa(fromBalance)))
if err != nil {
return shim.Error(fmt.Sprintf("更新账户 %s 余额失败:%s", fromAccount, err))
}
err = stub.PutState(toAccount, []byte(strconv.Itoa(toBalance)))
if err != nil {
return shim.Error(fmt.Sprintf("更新账户 %s 余额失败:%s", toAccount, err))
}
return shim.Success(nil)
}
调用Start方法启动
func main() {
err := shim.Start(new(PaymentChaincode))
if err != nil {
fmt.Printf("Error starting")
}
}