Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Hyperledger fabric Chaincode Development

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article shares with you the content of a sample analysis of Hyperledger fabric Chaincode development. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

Hyperledger fabric Chaincode developer 16.7. Chaincode structure

There are three methods for shim.ChaincodeStubInterface interface: Init, Query and Invoke

16.7.1. Package package main16.7.2. Import the library import ("fmt"strconv"github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer") 16.7.3. Define the class type SimpleChaincode struct {} 16.7.4. Init method

Responsible for initialization, which is called when the chain code is first deployed to the blockchain network, and will be executed by each peer node that deploys its own instance of the chain code. This method can be used for any task related to initialization, booting, or setup.

Func (t * SimpleChaincode) Init (stub shim.ChaincodeStubInterface) pb.Response {} 16.7.5. Query

The Query method needs to be called whenever any read / fetch / query operations are performed on the blockchain state. If you try to change the state of the blockchain within the Query method, an exception will be thrown.

16.7.6. Invoke

The main purpose of this method is to make changes, but in many cases, some users also do queries in Invoke.

Put, get, del and other operations can be run in Invoke

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

Reference example

Func (s * SmartContract) Invoke (stub shim.ChaincodeStubInterface) sc.Response {/ / Retrieve the requested SmartContract 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.")}

In the Invoke function, we first use stub.GetFunctionAndParameters () to get the contract function function, args: = stub.GetFunctionAndParameters (), and then judge the function name and implement the corresponding logical relationship. 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 ()

Any Go program needs the main function, which is the entrance to the program, so it is used to boot / start the chain code. When chaincode is deployed and instantiated to the peer node, the main function is executed.

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

Shim.Start (new (SampleChaincode)) starts the chain code and registers with the peer node.

16.8. Shim.ChaincodeStubInterface interface

Hyperledger provides key/value-based data storage, where key is a string and value is a binary byte array. Hyperledger's Go API provides three methods for data access: PutState (key, value) for storing data in Hyperledger, GetState (key) for extracting data from Hyperledger, and DelState (key) for deleting data from Hyperledger.

If the written data is a struct structure, it needs to be serialized, usually using json, or other forms of serialization, as long as it can be deserialized.

16.8.1. Zeng, delete, check operation 16.8.1.1. PutState (key, value) write block

Write block contact

Func (s * SmartContract) initLedger (stub shim.ChaincodeStubInterface) sc.Response {token: = & Token {Owner: "netkiller", TotalSupply: 10000, TokenName: "token Tongzheng", 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) read block

Get block information through 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) delete block

Delete block information

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. Modify data

State database does not provide modification function. Modified data can be read first, then modified, and finally written.

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) range lookup

Block chain is a linear data structure, as long as you know the start position and the end position, you can take out the middle part of the data.

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 query

GetQueryResult can query the data in json.

The following example is all the data for Name = Neo Chen.

Func (t * SimpleChaincode) getQueryResult (stub shim.ChaincodeStubInterface, args [] string) pb.Response {name:= "Neo Chen" / / the name of the query to be queried queryString: = fmt.Sprintf ("{\" selector\ ": {\" Name\ ":\"% s\ "}}", name) resultsIterator,err:= stub.GetQueryResult (queryString) / / must be CouchDB to if erratic query nil {return shim.Error ("query failed")} person Err:=getListResult (resultsIterator) if erratic roomnil {return shim.Error ("query failed")} return shim.Success (person)} 16.8.1.7. Stub.GetHistoryForKey

Obtain historical data through 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 erratic ambigunil {return shim.Error (err.Error ())} var result,_= getHistoryListResult (it) return shim.Success (result)} 16.8.1.8. Shim.HistoryQueryIteratorInterface interface 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. Compound bond 16.8.2.1. Create the compound key / / 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. Decompose the compound key / / 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) event

The Hyperledger Fabic event implements publish / subscribe message queues. You are free to create and emit custom events in the chain code. For example, when the state of a blockchain changes, an event is generated. Client applications can subscribe to and use these events by registering an event adapter with the event center on the blockchain.

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: "token Tongzheng", 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. Call other chain codes

To call another concatenation code in the current concatenation code, you need to provide the concatenation name and channel name stub.InvokeChaincode ("concatenation name", calling function, "channel").

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))} Case 16.9.1. Implement package mainimport ("bytes", "encoding/json", "fmt", "strconv", "github.com/hyperledger/fabric/core/chaincode/shim" sc "github.com/hyperledger/fabric/protos/peer") / / Define the SmartContract structuretype SmartContract struct {} type Token struct {Owner by imitating the Hyperledger Fabric of Etay Square ERC20 specification 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: "tokens", 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 SmartContract 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 SmartContract err: = shim.Start (new (SmartContract)) if err! = nil {fmt.Printf ("Error creating new SmartContract:% s", err)}} Thank you for reading! This is the end of this article on "sample Analysis of Hyperledger fabric Chaincode Development". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report