千家信息网

Hyperledger fabric Chaincode开发的示例分析

发表于:2025-02-08 作者:千家信息网编辑
千家信息网最后更新 2025年02月08日,这篇文章给大家分享的是有关Hyperledger fabric Chaincode开发的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Hyperledger fab
千家信息网最后更新 2025年02月08日Hyperledger fabric Chaincode开发的示例分析

这篇文章给大家分享的是有关Hyperledger fabric Chaincode开发的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

Hyperledger fabric Chaincode 开发

16.7. Chaincode 结构

shim.ChaincodeStubInterface 接口有三个方法,分别是:Init、Query 和 Invoke

16.7.1. 包

package main

16.7.2. 导入库

import (        "fmt"        "strconv"        "github.com/hyperledger/fabric/core/chaincode/shim"        pb "github.com/hyperledger/fabric/protos/peer")

16.7.3. 定义类

type SimpleChaincode struct {}

16.7.4. Init 方法

负责初始化工作,链码首次部署到区块链网络时调用,将由部署自己的链代码实例的每个对等节点执行。此方法可用于任何与初始化、引导或设置相关的任务。

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {}

16.7.5. Query

只要在区块链状态上执行任何读取/获取/查询操作,就需要调用 Query 方法。如果尝试在 Query 方法内修改区块链的状态,将会抛出异常。

16.7.6. Invoke

此方法主要是做修改操作,但是很多例子中一些用户也在 Invoke 做查询。

put, get, del 等操作都在可以在 Invoke 中运行

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {}

参考例子

func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) sc.Response {        // Retrieve the requested Smart Contract function and arguments        function, args := stub.GetFunctionAndParameters()        // Route to the appropriate handler function to interact with the ledger appropriately        if function == "balanceToken" {                return s.balanceToken(stub, args)        } else if function == "initLedger" {                return s.initLedger(stub)        } else if function == "transferToken" {                return s.transferToken(stub, args)        }        return shim.Error("Invalid Smart Contract function name.")}

在 Invoke 函数中,首先使用 stub.GetFunctionAndParameters() 获取合约函数 function, args := stub.GetFunctionAndParameters() 然后判断函数名称,实现对应的逻辑关系。 if function == "balanceToken" { return s.balanceToken(stub, args) } else if function == "initLedger" { return s.initLedger(stub) } else if function == "transferToken" { return s.transferToken(stub, args) }

16.7.7. func main()

任何 Go 程序的都需要 main 函数,他是程序的入口,因此该函数被用于引导/启动链代码。当对peer节点部署chaincode并实例化时,就会执行 main 函数。

func main() {        err := shim.Start(new(SimpleChaincode))        if err != nil {                fmt.Printf("Error starting Simple chaincode: %s", err)        }}

shim.Start(new(SampleChaincode)) 启动链代码并注册到peer 节点。

16.8. shim.ChaincodeStubInterface 接口

Hyperledger提供基于key/value的数据存储,其中key是字符串,value则是二进制字节数组,Hyperledger的Go API提供了三个方法用于数据存取:PutState(key, value)用于向Hyperledger中存储数据, GetState(key)用于从Hyperledger中提取数据,而DelState(key)则从Hyperledger中删除数据。

写入数据如果是 struct 结构体,需要序列化,通常使用 json,其他形式的序列化也可以,只要能反序列化即可。

16.8.1. 曾,删,查 操作

16.8.1.1. PutState(key, value)写入区块

写入区块联系

func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface) sc.Response {                token := &Token{                Owner: "netkiller",                TotalSupply: 10000,                TokenName: "代币通正",                TokenSymbol: "COIN",                BalanceOf: map[string]uint{}}                token.initialSupply()        tokenAsBytes, _ := json.Marshal(token)        stub.PutState("Token", tokenAsBytes)        fmt.Println("Added", tokenAsBytes)                return shim.Success(nil)}
16.8.1.2. GetState(key) 读取区块

通过key获取区块信息

func (s *SmartContract) balanceToken(stub shim.ChaincodeStubInterface, args []string) sc.Response {        if len(args) != 1 {                return shim.Error("Incorrect number of arguments. Expecting 1")        }        tokenAsBytes, _ := stub.GetState(args[0])        token := Token{}        json.Unmarshal(tokenAsBytes, &token)        amount := token.balance(args[1])        return shim.Success(amount)}
16.8.1.3. DelState(key) 删除区块

删除区块信息

func (s *SmartContract) deleteData(stub shim.ChaincodeStubInterface, args []string) sc.Response {        if len(args) != 1 {                return shim.Error("Incorrect number of arguments. Expecting 1")        }        err= stub.DelState(args[0])        if err != nil {           return shim.Error("Failed to delete Student from DB, key is: "+key)        }        return shim.Success(nil)}
16.8.1.4. 修改数据

State 数据库并没有提供修改功能,修改数据可以先读取,再修改,最后写入

func (s *SmartContract) transferToken(stub shim.ChaincodeStubInterface, args []string) sc.Response {        if len(args) != 3 {                return shim.Error("Incorrect number of arguments. Expecting 2")        }        tokenAsBytes, _ := stub.GetState(args[0])        token := Token{}        json.Unmarshal(tokenAsBytes, &token)        token.transfer(args[1],args[2],args[3])        tokenAsBytes, _ = json.Marshal(token)        stub.PutState(args[0], tokenAsBytes)        return shim.Success(nil)}
16.8.1.5. GetStateByRange(startKey, endKey) 范围查找

区块链是一个线性的数据结构,只要知道开始位置,结束位置,就能够取出中间部分的数据。

func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {        startKey := "CAR0"        endKey := "CAR999"        resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)        if err != nil {                return shim.Error(err.Error())        }        defer resultsIterator.Close()        // buffer is a JSON array containing QueryResults        var buffer bytes.Buffer        buffer.WriteString("[")        bArrayMemberAlreadyWritten := false        for resultsIterator.HasNext() {                queryResponse, err := resultsIterator.Next()                if err != nil {                        return shim.Error(err.Error())                }                // Add a comma before array members, suppress it for the first array member                if bArrayMemberAlreadyWritten == true {                        buffer.WriteString(",")                }                buffer.WriteString("{\"Key\":")                buffer.WriteString("\"")                buffer.WriteString(queryResponse.Key)                buffer.WriteString("\"")                buffer.WriteString(", \"Record\":")                // Record is a JSON object, so we write as-is                buffer.WriteString(string(queryResponse.Value))                buffer.WriteString("}")                bArrayMemberAlreadyWritten = true        }        buffer.WriteString("]")        fmt.Printf("- queryAllCars:\n%s\n", buffer.String())        return shim.Success(buffer.Bytes())}
16.8.1.6. GetQueryResult(query string) CouchDB 查询

GetQueryResult 能查询 json 里面的数据

下面例子是 Name = Neo Chen 的所有数据。

func (t *SimpleChaincode) getQueryResult(stub shim.ChaincodeStubInterface, args []string) pb.Response{   name:="Neo Chen"       //需要查询的名字   queryString := fmt.Sprintf("{\"selector\":{\"Name\":\"%s\"}}", name)   resultsIterator,err:= stub.GetQueryResult(queryString)//必须是CouchDB才行   if err!=nil{      return shim.Error("query failed")   }   person,err:=getListResult(resultsIterator)   if err!=nil{      return shim.Error("query failed")   }   return shim.Success(person)}
16.8.1.7. stub.GetHistoryForKey

通过key获取历史数据

func (t *SimpleChaincode) historyQuery(stub shim.ChaincodeStubInterface, args []string) pb.Response{        if len(args) != 1 {                return shim.Error("Incorrect number of arguments. Expecting 1")        }      it,err:= stub.GetHistoryForKey(args[0])   if err!=nil{      return shim.Error(err.Error())   }   var result,_= getHistoryListResult(it)   return shim.Success(result)}
16.8.1.8. shim.HistoryQueryIteratorInterface 接口
func getHistoryListResult(resultsIterator shim.HistoryQueryIteratorInterface) ([]byte,error){   defer resultsIterator.Close()   // buffer is a JSON array containing QueryRecords   var buffer bytes.Buffer   buffer.WriteString("[")   bArrayMemberAlreadyWritten := false   for resultsIterator.HasNext() {      queryResponse, err := resultsIterator.Next()      if err != nil {         return nil, err      }      // Add a comma before array members, suppress it for the first array member      if bArrayMemberAlreadyWritten == true {         buffer.WriteString(",")      }      item,_:= json.Marshal( queryResponse)      buffer.Write(item)      bArrayMemberAlreadyWritten = true   }   buffer.WriteString("]")   fmt.Printf("queryResult:\n%s\n", buffer.String())   return buffer.Bytes(), nil}

16.8.2. 复合键

16.8.2.1. 创建复合键
// maintain the index        indexName := "color~name"        colorNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{marbleJSON.Color, marbleJSON.Name})        if err != nil {                return shim.Error(err.Error())        }        //  Delete index entry to state.        err = stub.DelState(colorNameIndexKey)        if err != nil {                return shim.Error("Failed to delete state:" + err.Error())        }
16.8.2.2. 分解复合键
// get the color and name from color~name composite key                objectType, compositeKeyParts, err := stub.SplitCompositeKey(responseRange.Key)                if err != nil {                        return shim.Error(err.Error())                }                returnedColor := compositeKeyParts[0]                returnedMarbleName := compositeKeyParts[1]

16.8.3. stub.SetEvent(key, value) 事件

Hyperledger Fabic 事件实现了发布/订阅消息队列。您可以自由地在链码中创建和发出自定义事件。例如,区块链的状态发生改变,就会生成一个事件。通过向区块链上的事件中心注册一个事件适配器,客户端应用程序可以订阅和使用这些事件。

func (t *SimpleChaincode) testEvent(stub shim.ChaincodeStubInterface, args []string) pb.Response{   message := "Event send data is here!"   err := stub.SetEvent("evtsender", []byte(message))   if err != nil {      return shim.Error(err.Error())   }   return shim.Success(nil)}               func (t *SimpleChaincode) testEvent(stub shim.ChaincodeStubInterface, args []string) pb.Response{        event := &Token{                Owner: "netkiller",                TotalSupply: 10000,                TokenName: "代币通正",                TokenSymbol: "COIN",                BalanceOf: map[string]uint{}}                    eventBytes, err ;= json.Marshal(&event)    if err != nil {            return nil, err    }    err := stub.SetEvent("evtSender", eventBytes)    if err != nil {        fmt.Println("Could not set event for loan application creation", err)    }}

16.8.4. 调用其他链码

在当前连码中调用另一个连码,调用连码需要提供连码名和通道名 stub.InvokeChaincode("连码名",调用函数,"通道")

func (t *SimpleChaincode) testInvokeChainCode(stub shim.ChaincodeStubInterface, args []string) pb.Response{   trans:=[][]byte{[]byte("invoke"),[]byte("transfer"),[]byte("netkiller"),[]byte("neo"),[]byte("100")}   response:= stub.InvokeChaincode("token",trans,"mychannel")   fmt.Println(response.Message)   return shim.Success([]byte( response.Message))}               16.9. 案例16.9.1. 模仿以太坊 ERC20 规范的 Hyperledger Fabric 实现                package mainimport (        "bytes"        "encoding/json"        "fmt"        "strconv"        "github.com/hyperledger/fabric/core/chaincode/shim"        sc "github.com/hyperledger/fabric/protos/peer")// Define the Smart Contract structuretype SmartContract struct {}type Token struct {        Owner                   string  `json:"Owner"`        TotalSupply        uint    `json:"TotalSupply"`        TokenName          string  `json:"TokenName"`        TokenSymbol        string  `json:"TokenSymbol"`        BalanceOf               map[string]uint `json:"BalanceOf"`}func (token *Token) initialSupply(){        token.BalanceOf[token.Owner] = token.TotalSupply;}func (token *Token) transfer (_from string, _to string, _value uint){        if(token.BalanceOf[_from] >= _value){                token.BalanceOf[_from] -= _value;                token.BalanceOf[_to] += _value;        }}func (token *Token) balance (_from string) uint{        return token.BalanceOf[_from]}func (token *Token) burn(_value uint) {        if(token.BalanceOf[token.Owner] >= _value){                token.BalanceOf[token.Owner] -= _value;                token.TotalSupply -= _value;        }}func (token *Token) burnFrom(_from string, _value uint) {        if(token.BalanceOf[_from] >= _value){                token.BalanceOf[_from] -= _value;                token.TotalSupply -= _value;        }}func (token *Token) mint(_value uint) {                token.BalanceOf[token.Owner] += _value;        token.TotalSupply += _value;        }func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) sc.Response {        return shim.Success(nil)}func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface) sc.Response {                token := &Token{                Owner: "netkiller",                TotalSupply: 10000,                TokenName: "代币通正",                TokenSymbol: "COIN",                BalanceOf: map[string]uint{}}                token.initialSupply()        tokenAsBytes, _ := json.Marshal(token)        stub.PutState("Token", tokenAsBytes)        fmt.Println("Added", tokenAsBytes)                return shim.Success(nil)}func (s *SmartContract) transferToken(stub shim.ChaincodeStubInterface, args []string) sc.Response {        if len(args) != 3 {                return shim.Error("Incorrect number of arguments. Expecting 2")        }        tokenAsBytes, _ := stub.GetState(args[0])        token := Token{}        json.Unmarshal(tokenAsBytes, &token)        token.transfer(args[1],args[2],args[3])        tokenAsBytes, _ = json.Marshal(token)        stub.PutState(args[0], tokenAsBytes)        return shim.Success(nil)}func (s *SmartContract) balanceToken(stub shim.ChaincodeStubInterface, args []string) sc.Response {        if len(args) != 1 {                return shim.Error("Incorrect number of arguments. Expecting 1")        }        tokenAsBytes, _ := stub.GetState(args[0])        token := Token{}        json.Unmarshal(tokenAsBytes, &token)        amount := token.balance(args[1])        return shim.Success(amount)}func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) sc.Response {        // Retrieve the requested Smart Contract function and arguments        function, args := stub.GetFunctionAndParameters()        // Route to the appropriate handler function to interact with the ledger appropriately        if function == "balanceToken" {                return s.balanceToken(stub, args)        } else if function == "initLedger" {                return s.initLedger(stub)        } else if function == "transferToken" {                return s.transferToken(stub, args)        }        return shim.Error("Invalid Smart Contract function name.")}// The main function is only relevant in unit test mode. Only included here for completeness.func main() {        // Create a new Smart Contract        err := shim.Start(new(SmartContract))        if err != nil {                fmt.Printf("Error creating new Smart Contract: %s", err)        }}

感谢各位的阅读!关于"Hyperledger fabric Chaincode开发的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

数据 区块 事件 函数 方法 查询 开发 代码 例子 序列 接口 状态 程序 结构 节点 代币 示例 分析 三个 位置 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 win kms服务器地址 分析电子商务网络安全要素 kettle中的数据库驱动包 软件开发结项研究报告 多功能网络技术参考价格 护苗网络安全宣传信息 国家网络安全法的重要意义 苏州达内网络技术培训 碳交易系统软件开发上市公司 财富互联网科技 怎么让多台电脑访问同一个数据库 软件开发工程量如何确定 中央网信委网络安全局局长 我国高精度土壤数据库建造 知道ip地址怎么破解数据库 泛微服务器维修公司有哪些 换了wifi后无法连接到服务器 胸痛中心数据库填报ppt 魔兽怀旧服服务器里有哪些 主服务器连接 微信号查手机数据库 戴尔服务器主机如何安装系统 军事领域网络安全股 电大计算机网络技术实践 世纪云涿州互联网科技有限公司 软件开发工程量如何确定 软件开发企业税点 企业用服务器维修报价表 网络安全与隐私保护官 上海咸蛋网络技术手机
0