在開發環境中測試Hyperledger Fabric Chaincodes

買賣虛擬貨幣
Happyledger這是我hyperledger fabric系列文章的第四部分——happyledgerblog系列:)。在這篇文章中,我將展示如何在本地開發機器中構建、執行和測試(除錯)鏈程式碼。正常的鏈程式碼是安裝和執行在對等點上的。但是使用chaincode開發模式,我們可以在本地開發機器上執行和測試它們。在真正的網路上部署鏈程式碼之前,編譯、執行和測試它們是值得的。與本文相關的所有部署檔案和配置都是athlf-chaincode-dev gitlab repo。簽出儲存庫並遵循以下步驟。1. 設定fabric開發網路首先,我們需要使用預先生成的orderer和channel構件部署dev mode docker容器。以下是在這個目錄中找到的預生成工件。
1.myc.block – 引導塊2.myc.tx – 引導連線事物3.orderer.block – 預定塊

您可以像下面這樣部署服務。它將啟動並執行orderer、peer、cli和chaincode容器。Orderer以SingleSampleMSPSoloprofile開始,peer以dev-mode開始。


# deploy following containers
#   1. orderer
#   2. peer
#   3. cli
#   4. chaincode
docker-compose up -d

2. 構建和執行鏈程式碼

接下來我們需要在鏈程式碼容器中構建和執行鏈程式碼。我已經放了我的rahasak。進入chaincode/rahasak目錄中的鏈程式碼。這個鏈程式碼具有使用者建立、獲取、搜尋功能。

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/protos/peer"
)

type RahasakContract struct {
}

type User struct {
	Id    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

func (s *RahasakContract) Init(stub shim.ChaincodeStubInterface) peer.Response {
	args := stub.GetStringArgs()
	fmt.Printf("INFO: init chaincode args: %s\n", args)

	return shim.Success(nil)
}

func (s *RahasakContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	// Retrieve the requested Smart Contract function and arguments
	function, args := stub.GetFunctionAndParameters()
	fmt.Printf("INFO: invoke function: %s, args: %s\n", function, args)

	if function == "create" {
		return s.Create(stub, args)
	} else if function == "get" {
		return s.Get(stub, args)
	} else if function == "search" {
		return s.Search(stub, args)
	}

	return shim.Error("Invalid smart contract function")
}

func (s *RahasakContract) Create(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	fmt.Printf("INFO: create with args: %s\n", args)

	// user
	usr := User{
		Id:    args[0],
		Name:  args[1],
		Email: args[2],
	}
	usrJsn, _ := json.Marshal(usr)
	err := stub.PutState(args[0], usrJsn)
	if err != nil {
		fmt.Printf("ERROR: error PutState: %s\n", err.Error())
		shim.Error("error PutState: " + err.Error())
	}

	return shim.Success(nil)
}

func (s *RahasakContract) Get(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	fmt.Printf("INFO: get with args: %s\n", args)

	usr, _ := stub.GetState(args[0])
	if usr == nil {
		return shim.Error("Could not get user with id: " + args[0])
	}

	return shim.Success(usr)
}

func (s *RahasakContract) Search(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	fmt.Printf("INFO: search with args: %s\n", args)

	// from, to range comes with args
	frm := args[0]
	to := args[1]

	// search by range
	iterator, err := stub.GetStateByRange(frm, to)
	if err != nil {
		return shim.Error("Error search by range: " + err.Error())
	}
	defer iterator.Close()

	// build json respone
	buffer, err := buildResponse(iterator)
	if err != nil {
		return shim.Error("Error constract response: " + err.Error())
	}
	fmt.Printf("INFO: search response:%s\n", buffer.String())

	return shim.Success(buffer.Bytes())
}

func buildResponse(iterator shim.StateQueryIteratorInterface) (*bytes.Buffer, error) {
	// buffer is a JSON array containing query results
	var buffer bytes.Buffer
	buffer.WriteString("[")

	written := false
	for iterator.HasNext() {
		resp, err := iterator.Next()
		if err != nil {
			return nil, err
		}

		// add a comma before array members, suppress it for the first array member
		if written == true {
			buffer.WriteString(",")
		}

		// record is a JSON object, so we write as it is
		buffer.WriteString(string(resp.Value))
		written = true
	}
	buffer.WriteString("]")

	return &buffer, nil
}

func main() {
	err := shim.Start(new(RahasakContract))
	if err != nil {
		fmt.Printf("ERROR: error creating rahasak contact: %s\n", err.Error())
	}
}
下面是在chaincode容器中構建和執行這個鏈程式碼的命令。

# connect to chaincode container
docker exec -it chaincode bash

# build chaincode
cd rahasak
go build -o rahasak

# run chaincode
# when running we are specifying the chaincode name and version
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=rahasak1:0 ./rahasak

在執行chaincode時,我們指定了chaincode的唯一名稱和版本(rahasak1.0)。現在chaincode已經在鏈程式碼容器中啟動了。

3.安裝並例項化chaincode

下一步是在peer中安裝和例項化鏈程式碼(就像我們在真實fabric叢集中安裝和例項化鏈程式碼一樣)。下面是這樣做的方法。
# install chaincode
# we are given unique name and version of the chaincode
peer chaincode install -p chaincodedev/chaincode/rahasak -n rahasak1 -v 0

# instantiate chaincode
# we are giving channel name and chaincode name
peer chaincode instantiate -n rahasak1 -v 0 -c '{"Args":[]}' -C myc

在安裝和例項化時,我們需要指定chaincode的名稱。在這裡,我將rahasak1作為名稱,0作為版本。現在,我們的chaincode設定已經準備好進行測試。

4.測試chaincode

要測試chaincode,我們可以執行呼叫、查詢事務。下面是這樣做的方法。

# invoke transactions with 'create'  
peer chaincode invoke -n rahasak1 -c '{"Args":["create", "001", "lambda", "admin@chaindaily"]}' -C myc
peer chaincode invoke -n rahasak1 -c '{"Args":["create", "002", "ops", "admin@chaindaily"]}' -C myc

# query transactions with 'get'
# output - {"id":"001","name":"lambda","email":"admin@chaindaily"}
peer chaincode query -n rahasak1 -c '{"Args":["get", "001"]}' -C myc

# query transactions with 'search'
# output
[{"id":"001","name":"lambda","email":"admin@chaindaily"},{"id":"002","name":"ops","email":"admin@chaindaily"}]
peer chaincode query -n rahasak1 -c '{"Args":["search", "001", "005"]}' -C myc

更多區塊鏈資訊:www.qukuaiwang.com.cn/news

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;