- 第 1 章 区块链
- 第 2 章 以太坊
- 第 3 章 以太坊私链入门
- 第 4 章 以太坊网络
- 第 5 章 geth v1.8.16 命令详解
- 第 6 章 Wallet
- 第 7 章 Token
- 第 8 章 智能合约语言 Solidity v0.5.0
- 第 9 章 Truffle v4.1.8 开发框架
- 第 10 章 web3.js - 1.0.0
- 第 11 章 web3j v3.4.0 - Jave Client
- 11.2. 启动以太坊
- 11.3. Maven pom.xml 文件
- 11.4. Java 与 Solidity 数据类型映射关系
- 11.5. 常量
- 11.6. 连接到服务器获取版本号
- 11.7. 获得以太坊状态信息
- 11.8. 单位转换
- 11.9. 账号管理
- 11.10. Credentials
- 11.11. 交易
- 11.12. 钱包
- 11.13. 智能合约
- 11.14. ERC20合约
- 11.15. Infura
- 11.16. 助记词
- 11.17. 过滤器 (Filter)
- 11.18. Subscription
- 11.19. 解锁账号
- 11.20. IBAN (International Bank Account Number)
- 11.21. Springboot with Ethereum (web3j)
- 第 12 章 web3.py - A python interface for interacting with the Ethereum blockchain and ecosystem.
- 第 14 章 Ethereum Developer APIs
- 第 15 章 infura
- 第 16 章 以太坊案例
- 第 17 章 FAQ
- 17.3. Error: authentication needed: password or unlock
- 17.4. 新增节点后不生效
- 17.5. Unhandled rejection Error: Returned error: The method personal_unlockAccount does not exist/is not available
- 17.6. Error: exceeds block gas limit
- 17.7. Migrations.sol:11:3: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(…) { … }" instead.
- 17.8. Exception in thread "main" rx.exceptions.OnErrorNotImplementedException: Invalid response received: okhttp3.internal.http.RealResponseBody@6c25e6c4
- 17.9. 旧版本 Remix(browser-solidity) 本地安装
- 第 18 章 Hyperledger Fabric v2.0.0
- 第 19 章 Hyperledger Fabric 运维
- 第 20 章 Chaincode 链码(智能合约)
- 第 21 章 Hyperledger Fabric Client SDK for Node.js
- 第 22 章 fabric-sdk-java
- 第 24 章 已知 Hyperledger 落地案例
- 第 25 章 Fabric Command
- 第 26 章 Fabric FAQ
- 第 27 章 IPFS(InterPlanetary File System,星际文件系统)
- 第 28 章 IPFS 命令
- 第 29 章 IPFS WebUI
- 第 30 章 IPFS 集群配置
- 第 31 章 IPFS API
- 第 32 章 IPFS Faq
- 第 33 章 EOS
- 第 34 章 EOS 安装
- 第 35 章 CLEOS
- 第 36 章 智能合约开发
- 第 37 章 EOS Dapp 开发
- 第 38 章 FAQ
- 第 39 章 BaaS (Blockchain as a Service) 平台
- 第 40 章 BitCoin
- 第 41 章 其他区块链相关
- 附录 1. 附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
20.3. shim.ChaincodeStubInterface 接口
20.3. shim.ChaincodeStubInterface 接口
Hyperledger提供基于key/value的数据存储,其中key是字符串,value则是二进制字节数组,Hyperledger的Go API提供了三个方法用于数据存取:PutState(key, value)用于向Hyperledger中存储数据, GetState(key)用于从Hyperledger中提取数据,而DelState(key)则从Hyperledger中删除数据。
写入数据如果是 struct 结构体,需要序列化,通常使用 json,其他形式的序列化也可以,只要能反序列化即可。
20.3.1. State 数据库曾,删,查 操作
20.3.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) }
20.3.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) }
20.3.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) }
20.3.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) }
20.3.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()) }
20.3.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) }
20.3.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) }
20.3.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 }
20.3.2. 复合键
20.3.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()) }
20.3.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]
20.3.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) } }
20.3.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)) }
parms1 := []string{"query","a"} queryArgs := make([][]byte, len(parms1)) for i, arg := range parms1 { queryArgs[i] = []byte(arg) } response := stub.InvokeChaincode("cc_endfinlshed",queryArgs,"roberttestchannel12") if response.Status != shim.OK { errStr := fmt.Sprintf("Failed to query chaincode. Got error: %s", response.Payload) fmt.Printf(errStr) return shim.Error(errStr) } result := string(response.Payload) fmt.Printf(" invoke chaincode %s " ,result) return shim.Success([]byte("success InvokeChaincode and Not opter !!!!!!!! " + result))
import ( "encoding/json" "fmt" "strconv" "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" ) // Invoke func (am *accountManagement) Invoke(stub shim.ChaincodeStubInterface) peer.Response { actionName, params := stub.GetFunctionAndParameters() if actionName == "callAnotherCC" { chainCodeArgs := util.ToChaincodeArgs("anotherCCFunc", "paramA") response := stub.InvokeChaincode("anotherCCName", chainCodeArgs, "channelName") if response.Status != shim.OK { return shim.Error(response.Message) } return shim.Success(nil) } // NOTE: This is an example, hence assuming only valid call is to call another chaincode return shim.Error(fmt.Sprintf("[ERROR] No <%s> action defined", actionName)) }
20.3.5. stub.GetCreator() 获得证书资料
func (t *SimpleChaincode) certificate(stub shim.ChaincodeStubInterface, args []string) pb.Response{ creatorByte,_:= stub.GetCreator() certStart := bytes.IndexAny(creatorByte, "-----BEGIN") if certStart == -1 { fmt.Errorf("No certificate found") } certText := creatorByte[certStart:] bl, _ := pem.Decode(certText) if bl == nil { fmt.Errorf("Could not decode the PEM structure") } cert, err := x509.ParseCertificate(bl.Bytes) if err != nil { fmt.Errorf("ParseCertificate failed") } uname:=cert.Subject.CommonName fmt.Println("Name:"+uname) return shim.Success([]byte("Called testCertificate "+uname)) }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论