天天看點

fabric contract鍊碼案例

    fabric提供了合約的操作接口,這些接口從原來的源代碼裡獨立出來了,變成fabric-contract-api-go,這裡以fabric v1.4.8 + fabric-contract-api-go v1.0.0為例進行說明。

1、環境

  • Ubuntu 16.04
  • fabric v1.4.8
  • fabric-sample v1.4.8
  • fabric-contract-api-go v1.0.0
  • go 1.14.12

    a) 拉取fabric源碼,并切換到v1.4.8分支;

## 建立目錄
mkdir -p $GOPATH/src/github.com/hyperledger
cd $GOPATH/src/github.com/hyperledger

## 拉取源碼
git clone https://github.com/hyperledger/fabric.git

## 切換到v1.4.8分支
cd fabric 
git branch -a 
git checkout v1.4.8

           

    b) 拉取fabric-sample源碼,并切換到v1.4.8分支;

cd $GOPATH/src/github.com/hyperledger

## 拉取源碼
git clone https://github.com/hyperledger/fabric-samples.git

## 切換到v1.4.8分支
cd fabric 
git branch -a 
git checkout -b sample v1.4.3
           

    c) 下載下傳fabric-contract-api-go v1.0.0源碼;

cd $GOPATH/src/github.com/hyperledger

wget https://github.com/hyperledger/fabric-contract-api-go/archive/refs/tags/v1.0.0.tar.gz
tar -zxvf fabric-contract-api-go-1.0.0.tar.gz
           

2、編寫contracttwo工程

    a) 建立一個檔案夾夾名稱為contracttwo,然後對該檔案夾進行go mod init

mkdir contracttwo
go mod init contracttwo
           

    b)修改contracttwo/go.mod檔案,并拉取fabric-contract-api-go v1.0.0

//go.mod

module contracttwo

go 1.13

require github.com/hyperledger/fabric-contract-api-go v1.0.0

           

    拉取fabric-contract-api-go v1.0.0

go env -w GOPROXY=https://goproxy.cn,direct
go get -u github.com/hyperledger/[email protected]
           

    c) 建立contracttwo.go檔案,并編譯

//contracttwo.go

package main


import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// SimpleContract contract for handling writing and reading from the world state
type SimpleContract struct {
	contractapi.Contract
}

// Create adds a new key with value to the world state
func (sc *SimpleContract) Create(ctx contractapi.TransactionContextInterface, key string, value string) error {
	existing, err := ctx.GetStub().GetState(key)

	if err != nil {
		return errors.New("Unable to interact with world state")
	}

	if existing != nil {
		return fmt.Errorf("Cannot create world state pair with key %s. Already exists", key)
	}

	err = ctx.GetStub().PutState(key, []byte(value))

	if err != nil {
		return errors.New("Unable to interact with world state")
	}

	return nil
}

// Update changes the value with key in the world state
func (sc *SimpleContract) Update(ctx contractapi.TransactionContextInterface, key string, value string) error {
	existing, err := ctx.GetStub().GetState(key)

	if err != nil {
		return errors.New("Unable to interact with world state")
	}

	if existing == nil {
		return fmt.Errorf("Cannot update world state pair with key %s. Does not exist", key)
	}

	err = ctx.GetStub().PutState(key, []byte(value))

	if err != nil {
		return errors.New("Unable to interact with world state")
	}

	return nil
}

// Read returns the value at key in the world state
func (sc *SimpleContract) Read(ctx contractapi.TransactionContextInterface, key string) (string, error) {
	existing, err := ctx.GetStub().GetState(key)

	if err != nil {
		return "", errors.New("Unable to interact with world state")
	}

	if existing == nil {
		return "", fmt.Errorf("Cannot read world state pair with key %s. Does not exist", key)
	}

	return string(existing), nil
}



func main() {
	simpleContract := new(SimpleContract)

	cc, err := contractapi.NewChaincode(simpleContract)

	if err != nil {
		panic(err.Error())
	}

	if err := cc.Start(); err != nil {
		panic(err.Error())
	}
}

           
go build contracttwo
           

    d)在$GOPATH/src/github.com/hyperledger/fabric-samples/chaincode-docker-devmode目錄下,建立一個檔案夾名稱為chaincode,然後把contracttwo拷貝到該目錄。

cd $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode-docker-devmode
mkdir chaincode

cp -r /home/tools/contrattwo chaincode/
           

    e) 将chaincode-docker-devmode/docker-compose-simple.yaml複制一份,重命名為docker-compose.yaml檔案,修改如下:

//docker-compose.yaml

## cli容器 增加挂載目錄
    volumes:
        - /usr/local/gocode/src/github.com/hyperledger:/opt/gopath/src/github.com/hyperledger

## peer容器 既增加挂載目錄,又增加7052端口
    volumes:
        - /usr/local/gocode/src/github.com/hyperledger:/opt/gopath/src/github.com/hyperledger
    ports:
      - 7052:7052
           

    修改路徑chaincode的相對路徑:

sed -i "s|./../chaincode|./chaincode|g" docker-compose.yaml
           
fabric contract鍊碼案例

圖(1) 在cli容器裡,設定hyperledger挂載目錄

fabric contract鍊碼案例

圖(2) 在peer容器裡,設定hyperledger挂載目錄和7052端口

    目錄結構如下:

fabric contract鍊碼案例

圖(3) chaincode-docker-devmode的目錄結構

3、初始化鍊碼

    a) 啟動docker服務

cd fabric-samples/chaincode-docker-devmode
docker-compose up -d 
           

    b) 打開一個新的終端2,依次輸入如下指令,進入chaincode容器,編譯contracttwo.go源檔案

## 進入contracttwo.go所在的目錄
cd fabric-samples/chaincode-docker-devmode/chaincode/contracttwo
sudo docker exec -it chaincode bash
go env -w GOPROXY=https://goproxy.cn,direct
go build contracttwo.go
           

    c) 啟動鍊碼

CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=contracttwo:1.0 CORE_PEER_TLS_ENABLED=false ./contracttwo -peer.address peer:7052
           

    該語句的含義是,在7052端口,啟動一個contracttwo鍊碼,版本為1.0。

fabric contract鍊碼案例

圖(4) 初始化鍊碼

4、安裝和執行個體化鍊碼

    a) 進入chaincode-docker-devmode目錄,再打開一個新的終端3,然後,進入cli容器

cd $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode-docker-devmode
sudo docker exec -it cli bash
           

    b) 安裝鍊碼

    将contracttwo 1.0鍊碼,安裝到節點裡

peer chaincode install -v 1.0 -n contracttwo -p chaincodedev/chaincode/contracttwo
           

    c) 執行個體化鍊碼

peer chaincode instantiate -C myc -n contracttwo -v 1.0 -c '{"Args":[]}'
           

5、調用鍊碼

    調用Create(),把tom的值設為80kg,指令如下:

peer chaincode invoke -C myc -n contracttwo -c '{"Args":["Create","tom","80kg"]}'
           
fabric contract鍊碼案例

圖(5) 傳回200,說明鍊碼調用成功

    列印status=200,說明鍊碼調用Create()函數成功。

6、查詢鍊碼裡的key-value

    查詢key(“tom”)對應的狀态資料

peer chaincode query -C myc -n contracttwo -c '{"Args":["Read","tom"]}'
           

    效果如下:

fabric contract鍊碼案例

圖(6) 查詢tom的值

7、更新key對應的value

    更新tom的值

peer chaincode invoke -C myc -n contracttwo -c '{"Args":["Update", "tom", "100kg"]}' 
           

    再次查詢tom的值,發現tom = 100kg,說明更新成功。

peer chaincode query -C myc -n contracttwo -c '{"Args":["Read","tom"]}'
           
fabric contract鍊碼案例

圖(7) 更新tom的值

8、關閉fabric網絡

當不再使用fabric時,請關閉fabric網絡

cd $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode-docker-devmode
docker-compose down
           

9、完整工程

    contracttwo完整工程 提取碼:uka9

繼續閱讀