fabric智能合约

package main
//首先需要准备好必备的Go 编程样板,与所有的智能合约一样,它实现了Chaincode 接
//口,特别是实现了In it 和Invoke 方法。因此,需要给智能合约添加impo口语句,以获得必要
//的依赖项。这里将导入chaincode shim 包和peer protobuf 包。接下来,继续添加一个名为
//SimpleAsset 的struct 作为Chaincode shim 方法的接收方。
import (
    "fmt"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"

)

// SimpleAsset实现一个简单的智能合约来管理资产。
type SimpleAsset struct {

}


// Init在智能合约实例化过程中被调用初始化任何数据。

//智能合约升级也调用这个函数。在编写将妥升级的现有版本的智能合约时,请确保
//适当地修改Init 函数。特别是,如果没有“迁移”或者没有什么东西可以作为升级的一部分进
//行初始化,那么就提供一个空的“ Init”方法。
//func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response{
//}


//接下来,将使用ChaincodeStublnterface.GetStringArgs 方法检索Init所需要的参数,并核
//实其参数数量的有效性。在这个例子中,需要传入的是一个键值对,即两个参数。

//Init在智能合约实例化过程中被调用来初始化任何数据。
//注意,智能合约升级也调用这个方法来重置或迁移数据,
//所以要小心避免在无意中破坏了账本数据的情况!
func (t *SimpleAsset) Init(stub shim.ChaincodeStubinterface) peer.Response {
    //从交易请求中获取请求参数数组。
    args := stub.GetStringArgs()
    if len(args) != 2 {
        return shim.Error("Incorrect arguments. Expecting a key and a value")
    }

    //接下来,既然己经确定了调用是否具备有效性,那么在调用时传入参数有效的情况下,将把初始状态存储在账本中。
    //为了达到上述目的,这里将调用ChaincodeStubinterface.PutState 作为参数传递的键和值。
    //假设一切顺利,返回一个Peer响应对象。表示初始化的操作是成功的。具体示例代码如下:

    //在这里通过调用stub.PutState()方法来存入资产信息。

    //将资产的value和相关联key存入账本。
    err := stub.PutState(args[0], []byte(args[1]))
    if err != nil {
        return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
    }
    return shim.Success(nil)
}


//与上面的Init 方法一样,这里需要从ChaincodeStublnterface 接口中提取参数.Invoke 方法
//的参数是将要调用的智能合约应用程序方法的名称。在这个例子中,所编写的应用程序只有两
//个功能: set 和get ,它允许设定一个资产的值,或者检索它的当前状态。
//首先调用ChaincodeStublnterface.GetFunctionAndParameters 方法,提取方法名和该智能合
//约应用程序功能的参数。具体示例如下:


//在智能合约上的每笔交易都会调用Invoke 。
//每一个事务都是由Init 方法创建的资产的“ get ”或“ set ”。
//“ set "方法可以通过指定新的键, 值对来创建新资产。
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStublnterface) peer.Response {
    //从交易请求中获取方法名和请求参数数组。
    fn, args := stub.GetFunctionAndParameters()

    //接下来,将继续验证方法名是否为set 或get ,并调用那些智能合约应用程序的方法,通过
    //shim.Success 或shim.Error 方法返回适当的响应,这些方法将响应序列化成gRPC protobuf 消
    //息。具体示例代码如下:

    var result string
    var err error
    if fn == "set"{
        result, err = set(stub, args)
    } else { // assume 'get ’ even if fn is nil
        result, err = get(stub, args)
    }
    if err != nil {
        return shim.Error(err.Error())
    }
    //返回成功结果。
    return shim.Success([]byte(result))
}

//将资产(包括key 和lvalue )存储在账本上。
//如果key存在, 它会用新key覆盖value 。
func set(stub shim.ChaincodeStubinterface, args []string) (string, error) {
    if len(args) != 2 {
        return "", fmt.Errorf("Incorrect arguments . Expecting a key and a value")
    }
    err := stub.PutState(args[0], []byte(args[1]))
    if err != nil {
        return "", fmt.Errorf("Failed to set asset: %s", args[0])
    }
    return args[1], nil
}

//获取指定资产key的value
func get(stub shim.ChaincodeStubinterface, args []string) (string, error) {
    if  len(args) != 1 {
        return "", fmt.Errorf("Incorrect arguments. Expecting a key")
    }
    value, err := stub.GetState(args[0])
    if err != nil {
        return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)
    }
    if value == nil {
        return "", fmt.Errorf("Asset not found : %s ", args[0])
    }
    return string(value), nil
}

//需要添加一个main 方法,它将调用shim.Start 方法。这是整个智能合约应用程序的入口方法。
//main方法在实例化过程中启动容器中的智能合约。
func main() {
    if err := shim.Start(new(SimpleAsset)); err != nil {
        fmt.Printf("Error sta 「ting SimpleAsset chaincode: %s", err)
    }
}

构建智能合约环境

这一步开始编译之前所写的智能合约代码。
具体执行如下命令:

go get -u github.com/hyperledger/fabric/core/chaincode/shim
go build

安装Hyperledger Fabric Samples

在服务器上确定任意一个位置用来放置Hyperledger Fabric Samples 仓库, 并在终端窗口中进入该目录。下面的命令将执行以下步骤:

  • 步骤1 : 如果需要, 克隆hyperledger/fabric- samples 仓库。
  • 步骤2 :切换合适的版本标签。
  • 步骤3 :为指定到fabric-samples 仓库根目录的版本安装Hyperledger Fabric 特定于平台的
    二进制文件和配置文件(具体可参考第3.1 节)。
  • 步骤4 :下载用于指定版本的Hyperledger Fabric 的Docker 镜像(具体可参考第2.4 . 2节)。
    如果上述工作都准备完成了,并且在通过终端进入了将要安装Fabric Samples 和二进制文
    件的目录中, 继续执行下面的命令:
    curl -sSL https://goo.gl/6wtTN5 | bash -s 1.1.0

注意: 如果在上面的curl 命令中遇到了一个错误,那么可能是curl 版本太低了,它不能处
理重定向或不受环境的支持。可以进入curl 官网,地址为https ://curl.haxx.se/download.html ,找到符合服务器环境的最新版的curl 并下载安装。另外,可以将上述地址替换未缩短的链接
https://github.com/hyperledger/fabric/blob/master/scripts/boot.sh

上面的命令下载并执行一个bash 脚本, 它将下载并提取需要设置Fabric 网络的所有特定
于平台的二进制文件,并将它们放入上面创建的克隆仓库中。它检索六个特定于平台的二进制文件: Cryptogen 、configtxgen 、configtx lator 、peer 、orderer 以及fabric-ca client 。
并将它们放置在当前工作目录的b n 子目录中。
也可以将其添加到PATH 环境变量中,这样就可以在不完全限定每一个二进制文件路径
的情况下获得这些变量。例如执行如下命令:
export PATH=<path to download location >/bin:$PATH
最后,该脚本将把Docker Hub 中的Docker 镜像从Docker Hub 下载到本地并将其标记为" latest " 。

测试智能合约

接下来,通过终端进入到克隆到本地的fabric-samples 仓库的chaincode-docker-devmode 目录下。此过程我们需要开启三个terminal

Terminal 1启动网络

执行如下命令:

docker-compose -f docker-compose-simple.yaml up

上面的内容以SingleSampleMSPSoloorderer配置文件启动网络,并以“dev模式”启动对等体。它还启动了两个额外的容器 - 一个用于chaincode环境,一个用于与chaincode交互的CLI。创建和加入通道的命令被嵌入到CLI容器中,因此我们可以立即跳转到链式代码调用。

Terminal 2建立并启动链码

首先将$GOPATH/src/fcc复制到chaincode目录下。

docker exec -it chaincode bash 

进入chaincode容器,你会看到下面的结果:
root@d2629980e76b:/opt/gopath/src/chaincode#
现在让我们来编译chaincode:

cd fcc 
go build

现在来运行智能合约

CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./fcc 

上述命令没有与任何channel建立连接,所以接下来让我们去第三个终端看看该怎么使用chaincode

Terminal 3使用链码

Hyperledger Fabric 1.1官方文档提示尽管我们在–peer-chaincodedev模式下,但是仍然需要我们自己来安装链码,以便系统链码的生命周期可以正常的进行检查,不过,在将来可能会删除此要求。

docker exec -it cli bash

进入cli容器

peer chaincode install -p chaincodedev/chaincode/fcc -n mycc -v 0 

peer chaincode instantiate -n mycc -v 0 -C myc -c '{"Args":["a","10"]}' 

接下来发出一个invoke 来改变“ a ”的值到“ 20”,执行如下命令:

peer chaincode invoke -n mycc -c  '{”Args":["set ", "a", "20"]}' -C myc

最后, 查询a。应该看到值为20 ,执行如下命令:

peer chaincode query -n mycc -c '{"Args": ["query", "a"]}'-C myc

在默认情况下,只安装并实例化了sacc。但是,可以通过将它们添加到智能合约子目录并重新启动这个网络来轻松测试不同的智能合约。在这一点上,它们将在智能合约容器中访问。

转载于:https://www.jianshu.com/p/715963cde34e

猜你喜欢

转载自blog.csdn.net/weixin_34023863/article/details/91115590