hyperledger的智能合约demo解析

hyperledger的智能合约demo解析

等一轮残月 海盗王 船龄 9.3年 来源 SWBSkyrim
 36001  0
本文地址:原文链接
分享一下自己关于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亲测可行。

  • 全部
  • 最佳
登录 账号发表你的看法,还没有账号?立即免费 注册
推荐教程
换一批