mt logoMyToken
总市值:
0%
恐慌指数:
0%
币种:--
交易所 --
ETH Gas:--
EN
USD
APP
Ap Store QR Code

Scan Download

hyperledger的智能合约demo解析

收藏
分享
本文地址: 原文链接
分享一下自己关于hyperledger智能合约的心得体会。
源码地址: chaincode_example2

之前的 SetFabricOnUbuntu 中,实现了无需virtualbox和vagrant直接部署Fabric,它的用处现在体现出来了~
智能合约chaincode的运行不需要本地启动多个节点,可以直接进行测试。那么我们可以在阿里云上直接测试现有的chaincode_example02项目。

参考本文,按照步骤依次启动CA、启动验证节点、在该单节点上部署chaincode,则可以进行智能合约的测试。
chaincode的测试有两种方式,一种是cli,一种是rest。

代码片

/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
//WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of
//calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has
//to be modified as well with the new ID of chaincode_example02.
//chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of
//hard-coding.
import (
"errors"
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
var A, B string    // Entities
var Aval, Bval int // Asset holdings
var err error
if len(args) != 4 {
return nil, errors.New("Incorrect number of arguments. Expecting 4")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return nil, errors.New("Expecting integer value for asset holding")
}
B = args[2]
Bval, err = strconv.Atoi(args[3])
if err != nil {
return nil, errors.New("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return nil, err
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return nil, err
}
return nil, nil
}
// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
if function == "delete" {
// Deletes an entity from its state
return t.delete(stub, args)
}
var A, B string    // Entities
var Aval, Bval int // Asset holdings
var X int          // Transaction value
var err error
if len(args) != 3 {
return nil, errors.New("Incorrect number of arguments. Expecting 3")
}
A = args[0]
B = args[1]
// Get the state from the ledger
// TODO: will be nice to have a GetAllState call to ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
return nil, errors.New("Failed to get state")
}
if Avalbytes == nil {
return nil, errors.New("Entity not found")
}
Aval, _ = strconv.Atoi(string(Avalbytes))
Bvalbytes, err := stub.GetState(B)
if err != nil {
return nil, errors.New("Failed to get state")
}
if Bvalbytes == nil {
return nil, errors.New("Entity not found")
}
Bval, _ = strconv.Atoi(string(Bvalbytes))
// Perform the execution
X, err = strconv.Atoi(args[2])
Aval = Aval - X
Bval = Bval + X
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state back to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return nil, err
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return nil, err
}
return nil, nil
}
// Deletes an entity from state
func (t *SimpleChaincode) delete(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
if len(args) != 1 {
return nil, errors.New("Incorrect number of arguments. Expecting 1")
}
A := args[0]
// Delete the key from the state in ledger
err := stub.DelState(A)
if err != nil {
return nil, errors.New("Failed to delete state")
}
return nil, nil
}
// Query callback representing the query of a chaincode
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
if function != "query" {
return nil, errors.New("Invalid query function name. Expecting \"query\"")
}
var A string // Entities
var err error
if len(args) != 1 {
return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
}
A = args[0]
// Get the state from the ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
return nil, errors.New(jsonResp)
}
if Avalbytes == nil {
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
return nil, errors.New(jsonResp)
}
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
fmt.Printf("Query Response:%s\n", jsonResp)
return Avalbytes, nil
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}

chaincode_example02  主要执行三个核心函数,init、invoke、query。
init函数在起始过程中初始化两个账户A,B,并且在A,B账户上发行一定数量的资产。
invoke函数在A、B上进行转账。
query函数查询A、B函数上的账户余额。
代码总体而言不是很复杂的,写类似的项目可以依着葫芦画瓢来做。

cli交互如下:

CORE_SECURITY_ENABLED=true CORE_SECURITY_PRIVACY=true peer chaincode deploy -u jim -n mycc -c '{"Function":"init", "Args": ["a","100", "b", "200"]}'

rest可以使用postman,交互如下,

POST host:port/chaincode
{
"jsonrpc": "2.0",
"method": "deploy",
"params": {
"type": 1,
"chaincodeID":{
"name": "mycc"
},
"ctorMsg": {
"function":"init",
"args":["a", "100", "b", "200"]
},
"secureContext": "jim"
},
"id": 1
}


cli与rest亲测可行。

免责声明:本文版权归原作者所有,不代表MyToken(www.mytokencap.com)观点和立场;如有关于内容、版权等问题,请与我们联系。
相关阅读