在fabric2.2.1環境下部署智慧合約

2020-10-16 12:00:58

1.開啟網路
沒啥好說的,之前要下samples,二進位制和映象

cd fabric-samples/test-network

把之前網路關閉了

./network.sh down

用下面的指令開啟測試網路:

./network.sh up createChannel

createchannel指令創造了一個叫mychannel的channel(兩個組織org1和2)。

成功的畫面8說了,就是channel successfully joined。

這會可以用peer cli來部署asset-transfer (basic)鏈碼到通道了。

第0步:開啟Logspout
這就是一個監測鏈碼的工具了,也可以不開啟。

cd fabric-samples/test-network
cp ../commercial-paper/organization/digibank/configuration/cli/monitordocker.sh 

官方第一行指令多了一個.,刪掉。接著執行它:

./monitordocker.sh net_test

顯示 Starting monitoring on all containers on the network net_basic,就ok了

第一步:打包智慧合約
在安裝到我們peer節點之前我們要打包。用go,js, Typescript步驟略有不同,我這邊用的是go

在打包鏈碼之前,要安裝鏈碼的依賴。導航到go版本的那個資料夾(包含the asset-transfer (basic) chaincode.)

cd fabric-samples/asset-transfer-basic/chaincode-go

案例用的是go 模組來安裝鏈碼依賴。依賴都在go.mod檔案中。(程式碼不貼了)

go.mod檔案把fabric 合約api輸出到智慧合約包了。
開啟asset-transfer-basic/chaincode-go/chaincode/smartcontract.go,能夠看到合約api是怎麼用來定義smartcontract型別的:

// SmartContract provides functions for managing an Asset
type SmartContract struct {
    contractapi.Contract
}

這個smartcontract type用於為智慧合約中定義的函數建立事務上下文,這些函數用於向區塊鏈分類賬讀寫資料。

// CreateAsset issues a new asset to the world state with given details.
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error {
    exists, err := s.AssetExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the asset %s already exists", id)
    }

    asset := Asset{
        ID:             id,
        Color:          color,
        Size:           size,
        Owner:          owner,
        AppraisedValue: appraisedValue,
    }
    assetJSON, err := json.Marshal(asset)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, assetJSON)
}

說了那麼多,接下來搞依賴,在asset-transfer-basic/chaincode-go目錄下執行:

GO111MODULE=on go mod vendor

成功的話,目錄裡會有vendor資料夾。

接下來就是搞環境變數,複製貼上就完事了:

export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/

這兩段話我直接就在:

vim ~/.bashrc
source ~/.bashrc

裡面搞了,我不知道直接在終端打有沒有效果,應該是有的

接下來就打包就完事了

peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_1.0

–lang:用於定義鏈碼語言
–path:提供智慧合約程式碼位置
–label:用來定義鏈碼的標籤

js我就不貼出來了,我電腦deploy cc js一直會很慢有時候都會超時,不知道為什麼????

第二步:安裝鏈碼包
要把鏈碼裝到peer節點上去

先把鏈碼裝到org1的peer上去。設定環境變數:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

直接在終端上面打!!!!!!!!
注意:如果你打上去了,然後你把這個終端關了,接下來你要進行的鏈碼操作都需要你在新開啟的終端再打一遍!!!!!!!

接下來就是安裝

peer lifecycle chaincode install basic.tar.gz

終端顯示:

2020-07-16 10:09:57.534 CDT [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJbasic_1.0:e2db7f693d4aa6156e652741d5606e9c5f0de9ebb88c5721cb8248c3aead8123\022\tbasic_1.0" >
2020-07-16 10:09:57.534 CDT [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: basic_1.0:e2db7f693d4aa6156e652741d5606e9c5f0de9ebb88c5721cb8248c3aead8123

就ok

同理,org2上的peer不多說

export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
peer lifecycle chaincode install basic.tar.gz

沒問題就第三步:同意鏈碼定義(改:這步以後的同意全都改成批准)
在安裝完後,需要為你的組織同意一個鏈碼定義。定義包括:鏈碼管理的重要引數:名字版本,背書政策。

需要在部署鏈碼之前批准鏈碼的通道成員集由Application/Channel/lifeycleEndorsement進行管理。預設情況下,此策略要求大多數通道成員需要批准鏈碼,然後才能在通道上使用該鏈碼。因為我們只有兩個組織在渠道上,大多數2是2,我們需要批准一個鏈碼定義的資產轉移(基本)為Org1和Org2。
如果一個組織已在peer上安裝了鏈碼,則需要將packageID包括在其組織批准的鏈碼定義中。包(package)ID用於將安裝在對等點上的鏈碼與已批准的鏈碼定義關聯起來,並允許組織使用鏈碼來支援事務。你可以通過使用peer lifecycle chaincode queryinstalled命令來查詢你的peer來找到一個鏈碼的包ID。(這兩段直接機翻再改,我覺得挺重要但我懶得打字)

peer lifecycle chaincode queryinstalled

得到id

Installed chaincodes on peer:
Package ID: basic_1.0:69de748301770f6ef64b42aa6bb6cb291df20aa39542c3ef94008615704007f3, Label: basic_1.0

然後用上面的,label 前面的id來設定環境變數:

export CC_PACKAGE_ID=basic_1.0:69de748301770f6ef64b42aa6bb6cb291df20aa39542c3ef94008615704007f3

(id每個人都不一樣,別把我這個id用到你上面去了)

因為環境變數已經被設定,我們可以為組織2同意鏈碼定義。鏈碼在組織層被同意,所以指令只需要target一個peer節點。這個同意事項是組織用gossip來分發給其他節點。同意的指令:

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

--package-id:包含package identifier(這裡翻譯成包身份鑑定者)
--sequence:一個能夠追蹤一個鏈碼被定義或者更新多少次的指數

這邊我覺得他重複了,不知道為什麼
We still need to approve the chaincode definition as Org1. Set the following environment variables to operate as the Org1 admin:

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051

You can now approve the chaincode definition as Org1:

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

這不是上面重複過了嗎!!!!

我們現在有大多數(我們需要部署資產轉移(基本)鏈碼到通道)。雖然只有大多陣列織需要批准鏈碼定義(使用預設策略),但所有組織都需要批准鏈碼定義,以便在peer上啟動鏈碼。如果在通道成員批准鏈碼之前提交定義,該組織將無法背書事務。因此,建議所有通道成員在提交鏈碼定義之前先批准一個鏈碼。

第四步:把鏈碼定義提交到通道
用下面的指令來確認是否通道成員同意了相同的鏈碼定義

peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json

結果應該是這樣:

 {
            "Approvals": {
                    "Org1MSP": true,
                    "Org2MSP": true
            }
    }

用如下指令來把鏈碼定義提交到通道:

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

--peerAddresse:確定目標peer0.org1.example.com from Org1 peer0.org2.example.com from Org2.
commit提交到peer節點。peer節點加入通道來查詢被組織同意的鏈碼定義。

用以下指令來確認鏈碼定義被提交到通道:

peer lifecycle chaincode querycommitted --channelID mychannel --name basic --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

成功的標誌:

Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]

呼叫鏈碼就不說了,複製貼上就完事了,之前都對的不會出錯

下面一步我這邊跑不起來,更新鏈碼:之前用的是go語言,這個官方要我用js來搞,其實都一樣,但是我這邊跑js就一直會timeout,非常奇怪。但是流程和之前是一模一樣,而且我個人認為更新鏈碼沒有很大的意義,一般都是重新從頭部署就完事了

最後,清理一下環境

docker stop logspout
docker rm logspout
./network.sh down

本章結束