第十五章 九析帶你輕鬆完爆 hyperledger fabric - chaincode 鏈碼調用

本系列文章:


第一章:九析帶你完爆 hyperledger fabric - 快速上手 basic-network 樣例

第二章:九析帶你完爆 hyperledger fabric - 快速搭建 GO 環境

第三章:九析帶你完爆 hyperledger fabric - 快速上手 first-network 樣例

第四章:九析帶你完爆 hyperledger fabric - 系統邏輯架構篇

第五章:九析帶你完爆 hyperledger fabirc - 網絡節點介紹

第六章:  九析帶你輕鬆完爆 hyperledger fabric - 區塊和區塊鏈介紹

第七章:  九析帶你輕鬆完爆 hyperledger fabric - 區塊鏈防篡改機制

第八章:九析帶你輕鬆完爆 hyperledger fabric - Couchdb 安裝

第九章:九析帶你輕鬆完爆 hyperledger fabric - NVM 和 Nodejs 安裝

第十章:九析帶你輕鬆完爆 hyperledger fabric - chaincode 生命週期介紹

第十一章: 九析帶你輕鬆完爆 hyperledger fabric - 創建聯盟

第十二章: 九析帶你輕鬆完爆 hyperledger fabric - configtxlator 嚐鮮

第十三章: 九析帶你輕鬆完爆 hyperledger fabric - 創建靜態組織

第十四章: 九析帶你輕鬆完爆 WARNING: The COMPOSE_PROJECT_NAME

第十五章: 九析帶你輕鬆完爆 hyperledger fabric - chaincode 鏈碼調用

目錄


1 前言

        在第十章九析帶你瞭解了 chaincode 是什麼以及它的生命週期都有哪些階段。本節將通過具體的實例來實際操作一下 chaincode。本文將採用 go 版本的 chaincode,如果你對 go 不瞭解也沒關係,你只需要根據我的記錄實際操作即可,當然前提是你必須正確配置了 go 運行環境。如果你對 go 環境配置也不清楚,可以參考本人的第二章


2 創建配置文件和目錄

2.1 創建工作目錄

mkdir  jiuxi

cd jiuxi

2.2 創建配置目錄和證書目錄

mkdir crypto-config config

2.3 創建創世區塊、通道、聯盟資源問題

touch configtx.yaml

        configtx.yaml 用來存放創世區塊、聯盟、通道、組織等配置信息。configtx.yaml 內容如下:

Organizations:

    - &OrdererOrg

        Name: OrdererOrg

        ID: OrdererMSP

        MSPDir: crypto-config/ordererOrganizations/jiuxi.org/msp

    - &Org1

        Name: Org1MSP

        ID: Org1MSP

        MSPDir: crypto-config/peerOrganizations/org1.jiuxi.org/msp

        AnchorPeers:

            - Host: peer0.org1.jiuxi.org

              Port: 11151

    - &Org2

        Name: Org2MSP

        ID: Org2MSP

        MSPDir: crypto-config/peerOrganizations/org2.jiuxi.org/msp

        AnchorPeers:

            - Host: peer0.org2.jiuxi.org

              Port: 12151

    - &Org3

        Name: Org3MSP

        ID: Org3MSP

        MSPDir: crypto-config/peerOrganizations/org3.jiuxi.org/msp

        AnchorPeers:

            - Host: peer0.org3.jiuxi.org

              Port: 13151

Orderer: &OrdererDefaults

    OrdererType: solo

    Addresses:

        - orderer.jiuxi.org:7050

    BatchTimeout: 2s

    BatchSize:

        MaxMessageCount: 10

        AbsoluteMaxBytes: 99 MB

        PreferredMaxBytes: 512 KB

    Kafka:

        Brokers:

            - 127.0.0.1:9092

    Organizations:

Application: &ApplicationDefaults

    Organizations:

Profiles:

    JiuxiOrdererGenesis:

        Orderer:

            <<: *OrdererDefaults

            Organizations:

                - *OrdererOrg

        Consortiums:

            JiuxiConsortium:

                Organizations:

                    - *Org1

                    - *Org2

                    - *Org3

    JiuxiChannel:

        Consortium: JiuxiConsortium

        Application:

            <<: *ApplicationDefaults

            Organizations:

                - *Org1

                - *Org2

                - *Org3

        如果你複製粘貼上面內容到 vim 中去的時候,可能會有空行出現,你可以在 vim 中執行命令操作 :g/^s*$/d 來刪除多餘的空行。

2.4 創建證書配置文件

touch crypto-config.yaml

        crypto-config.yaml 用來配置 orderer、peer 節點的信息,用來生成證書用,內容如下:

OrdererOrgs:

  - Name: Orderer

    Domain: jiuxi.org 

    Specs:

      - Hostname: orderer

PeerOrgs:

  - Name: Org1

    Domain: org1.jiuxi.org

    Template:

      Count: 2

    Users:

      Count: 1

  - Name: Org2

    Domain: org2.jiuxi.org

    Template:

      Count: 2

    Users:

      Count: 1

  - Name: Org3

    Domain: org3.jiuxi.org

    Template:

      Count: 2

    Users:

      Count: 1

2.5 創建 docker-compose.yaml 文件

touch docker-compose.yaml

        docker-compose.yaml 文件用來聲明容器編排和容器之間的依賴關係,內容如下:

version: '2'

networks:

  jiuxi:

services:

  couchdb:

    container_name: couchdb

    image: hyperledger/fabric-couchdb

    environment:

      - COUCHDB_USER=

      - COUCHDB_PASSWORD=

    ports:

      - 5984:5984

    networks:

      - jiuxi

  orderer.jiuxi.org:

    container_name: orderer.jiuxi.org

    image: hyperledger/fabric-orderer

    environment:

      - FABRIC_LOGGING_SPEC=info

      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0

      - ORDERER_GENERAL_GENESISMETHOD=file

      - ORDERER_GENERAL_GENESISFILE=/etc/hyperledger/configtx/genesis.block

      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP

      - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp/orderer/msp

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/orderer

    command: orderer

    ports:

      - 7050:7050

    volumes:

        - ./config/:/etc/hyperledger/configtx

        - ./crypto-config/ordererOrganizations/jiuxi.org/orderers/orderer.jiuxi.org/:/etc/hyperledger/msp/orderer

        - ./crypto-config/peerOrganizations/org1.jiuxi.org/peers/peer0.org1.jiuxi.org/:/etc/hyperledger/msp/peerOrg1

    networks:

      - jiuxi

  peer0.org1.jiuxi.org:

    container_name: peer0.org1.jiuxi.org

    image: hyperledger/fabric-peer

    environment:

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_PEER_ID=peer0.org1.jiuxi.org

      - FABRIC_LOGGING_SPEC=info

      - CORE_CHAINCODE_LOGGING_LEVEL=info

      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/

      - CORE_PEER_ADDRESS=peer0.org1.jiuxi.org:7051

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_jiuxi

      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=

      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric

    command: peer node start

    ports:

      - 11151:7051

      - 11153:7053

    volumes:

        - /var/run/:/host/var/run/

        - ./crypto-config/peerOrganizations/org1.jiuxi.org/peers/peer0.org1.jiuxi.org/msp:/etc/hyperledger/msp/peer

        - ./crypto-config/peerOrganizations/org1.jiuxi.org/users:/etc/hyperledger/msp/users

        - ./config:/etc/hyperledger/configtx

    depends_on:

      - orderer.jiuxi.org

      - couchdb

    networks:

      - jiuxi

  peer1.org1.jiuxi.org:

    container_name: peer1.org1.jiuxi.org

    image: hyperledger/fabric-peer

    environment:

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_PEER_ID=peer1.org1.jiuxi.org

      - FABRIC_LOGGING_SPEC=info

      - CORE_CHAINCODE_LOGGING_LEVEL=info

      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/

      - CORE_PEER_ADDRESS=peer1.org1.jiuxi.org:7051

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_jiuxi

      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=

      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric

    command: peer node start

    ports:

      - 11251:7051

      - 11253:7053

    volumes:

        - /var/run/:/host/var/run/

        - ./crypto-config/peerOrganizations/org1.jiuxi.org/peers/peer1.org1.jiuxi.org/msp:/etc/hyperledger/msp/peer

        - ./crypto-config/peerOrganizations/org1.jiuxi.org/users:/etc/hyperledger/msp/users

        - ./config:/etc/hyperledger/configtx

    depends_on:

      - orderer.jiuxi.org

      - couchdb

    networks:

      - jiuxi

  peer0.org2.jiuxi.org:

    container_name: peer0.org2.jiuxi.org

    image: hyperledger/fabric-peer

    environment:

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_PEER_ID=peer0.org2.jiuxi.org

      - FABRIC_LOGGING_SPEC=info

      - CORE_CHAINCODE_LOGGING_LEVEL=info

      - CORE_PEER_LOCALMSPID=Org2MSP

      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/

      - CORE_PEER_ADDRESS=peer0.org2.jiuxi.org:7051

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_jiuxi

      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=

      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric

    command: peer node start

    ports:

      - 12151:7051

      - 12153:7053

    volumes:

        - /var/run/:/host/var/run/

        - ./crypto-config/peerOrganizations/org2.jiuxi.org/peers/peer0.org2.jiuxi.org/msp:/etc/hyperledger/msp/peer

        - ./crypto-config/peerOrganizations/org2.jiuxi.org/users:/etc/hyperledger/msp/users

        - ./config:/etc/hyperledger/configtx

    depends_on:

      - orderer.jiuxi.org

      - couchdb

    networks:

      - jiuxi

  peer1.org2.jiuxi.org:

    container_name: peer1.org2.jiuxi.org

    image: hyperledger/fabric-peer

    environment:

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_PEER_ID=peer1.org2.jiuxi.org

      - FABRIC_LOGGING_SPEC=info

      - CORE_CHAINCODE_LOGGING_LEVEL=info

      - CORE_PEER_LOCALMSPID=Org2MSP

      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/

      - CORE_PEER_ADDRESS=peer1.org2.jiuxi.org:7051

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_jiuxi

      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=

      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric

    command: peer node start

    ports:

      - 12251:7051

      - 12253:7053

    volumes:

        - /var/run/:/host/var/run/

        - ./crypto-config/peerOrganizations/org2.jiuxi.org/peers/peer1.org2.jiuxi.org/msp:/etc/hyperledger/msp/peer

        - ./crypto-config/peerOrganizations/org2.jiuxi.org/users:/etc/hyperledger/msp/users

        - ./config:/etc/hyperledger/configtx

    depends_on:

      - orderer.jiuxi.org

      - couchdb

    networks:

      - jiuxi

  peer0.org3.jiuxi.org:

    container_name: peer0.org3.jiuxi.org

    image: hyperledger/fabric-peer

    environment:

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_PEER_ID=peer0.org3.jiuxi.org

      - FABRIC_LOGGING_SPEC=info

      - CORE_CHAINCODE_LOGGING_LEVEL=info

      - CORE_PEER_LOCALMSPID=Org3MSP

      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/

      - CORE_PEER_ADDRESS=peer0.org3.jiuxi.org:7051

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_jiuxi

      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=

      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric

    command: peer node start

    ports:

      - 13151:7051

      - 13153:7053

    volumes:

        - /var/run/:/host/var/run/

        - ./crypto-config/peerOrganizations/org3.jiuxi.org/peers/peer0.org3.jiuxi.org/msp:/etc/hyperledger/msp/peer

        - ./crypto-config/peerOrganizations/org3.jiuxi.org/users:/etc/hyperledger/msp/users

        - ./config:/etc/hyperledger/configtx

    depends_on:

      - orderer.jiuxi.org

      - couchdb

    networks:

      - jiuxi

  peer1.org3.jiuxi.org:

    container_name: peer1.org3.jiuxi.org

    image: hyperledger/fabric-peer

    environment:

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_PEER_ID=peer1.org3.jiuxi.org

      - FABRIC_LOGGING_SPEC=info

      - CORE_CHAINCODE_LOGGING_LEVEL=info

      - CORE_PEER_LOCALMSPID=Org3MSP

      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/

      - CORE_PEER_ADDRESS=peer1.org3.jiuxi.org:7051

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_jiuxi

      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=

      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric

    command: peer node start

    ports:

      - 13251:7051

      - 13253:7053

    volumes:

        - /var/run/:/host/var/run/

        - ./crypto-config/peerOrganizations/org3.jiuxi.org/peers/peer1.org3.jiuxi.org/msp:/etc/hyperledger/msp/peer

        - ./crypto-config/peerOrganizations/org3.jiuxi.org/users:/etc/hyperledger/msp/users

        - ./config:/etc/hyperledger/configtx

    depends_on:

      - orderer.jiuxi.org

      - couchdb

    networks:

      - jiuxi

  cli:

    container_name: cli

    image: hyperledger/fabric-tools

    tty: true

    environment:

      - GOPATH=/opt/gopath

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - FABRIC_LOGGING_SPEC=debug

      - CORE_PEER_ID=cli

      - CORE_PEER_ADDRESS=peer0.org1.jiuxi.org:7051

- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_jiuxi

      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.jiuxi.org/users/[email protected]/msp

      - CORE_CHAINCODE_KEEPALIVE=10

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer

    command: /bin/bash

    volumes:

        - /var/run/:/host/var/run/

        - ./chaincode/jiuxi/:/opt/gopath/src/github.com/

        - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/

    networks:

        - jiuxi

2.6 創建環境配置文件 .env

touch .env

echo "COMPOSE_PROJECT_NAME=jiuxi" > .env

        全部創建完畢之後的目錄結構如下:image3.png


3 生成證書

cryptogen generate --config=./crypto-config.yaml

        命令執行成功會在 crypto-config 目錄下生成各個組織節點的證書文件。


4 生成創世區塊

configtxgen -profile JiuxiOrdererGenesis -outputBlock ./config/genesis.block

        命令執行成功會在 config 目錄下生成創世區塊 genesis.block。


5 生成通道交易文件

configtxgen -profile JiuxiChannel -outputCreateChannelTx ./config/channel1.tx -channelID channel1

        命令執行成功會在 config 目錄下生成通道交易文件 channel1.tx。


6 創建 Anchor 節點的 MSP 會話文件

configtxgen -profile JiuxiChannel -outputAnchorPeersUpdate ./config/channel1Org1MSPanchors.tx -channelID channel1 -asOrg Org1MSP

configtxgen -profile JiuxiChannel -outputAnchorPeersUpdate ./config/channel1Org2MSPanchors.tx -channelID channel1 -asOrg Org2MSP


7 初始化容器

        啓動 docker-compose.yaml 配置文件生成容器:

docker-compose -f docker-compose.yaml up &

docker ps -a

        執行到此步驟完成了區塊鏈的搭建、orderer、peer、cli、couchdb 節點的啓動,但是目前組織的 peer 節點還沒有處於通道之中,下一步需要開始創建通道和將節點加入到通道之中了。


8 創建通道

        在 peer0.org1.jiuxi.org 節點上創建通道 channel1,通道創建成功後,會生成通道區塊文件 .block,並將自身組織加入到通道中:

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer0.org1.jiuxi.org peer channel create -o orderer.jiuxi.org:7050 -c channel1 -f /etc/hyperledger/configtx/channel1.tx

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer0.org1.jiuxi.org ls

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer0.org1.jiuxi.org peer channel join -b channel1.block

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer0.org1.jiuxi.org peer channel list

        將 peer0.org2.jiuxi.org 節點也加入到通道 channel1 中:

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer1.org1.jiuxi.org peer channel fetch 0 channel1.block -o orderer.jiuxi.org:7050 -c channel1

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer1.org1.jiuxi.org ls

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer1.org1.jiuxi.org peer channel join -b channel1.block

docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/[email protected]/msp" peer1.org1.jiuxi.org peer channel list

        自此,區塊鏈網絡、聯盟、組織、通道都創建完成,並且將組織 org1 加入到了通道 channel1 中。下一步就可以編寫鏈碼、安裝鏈碼、初始化鏈碼、調用鏈碼了。


9 編寫鏈碼

cd jiuxi

mkdir -p chaincode/jiuxi

touch jiuxi.go

        jiuxi.go 的源碼如下:

/*

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 (

"fmt"

"strconv"


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

pb "github.com/hyperledger/fabric/protos/peer"

)


// SimpleChaincode example simple Chaincode implementation

type SimpleChaincode struct {

}


func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {

fmt.Println("ex02 Init")

_, args := stub.GetFunctionAndParameters()

var A, B string    // Entities

var Aval, Bval int // Asset holdings

var err error


if len(args) != 4 {

return shim.Error("Incorrect number of arguments. Expecting 4")

}


// Initialize the chaincode

A = args[0]

Aval, err = strconv.Atoi(args[1])

if err != nil {

return shim.Error("Expecting integer value for asset holding")

}

B = args[2]

Bval, err = strconv.Atoi(args[3])

if err != nil {

return shim.Error("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 shim.Error(err.Error())

}


err = stub.PutState(B, []byte(strconv.Itoa(Bval)))

if err != nil {

return shim.Error(err.Error())

}


return shim.Success(nil)

}


func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {

fmt.Println("ex02 Invoke")

function, args := stub.GetFunctionAndParameters()

if function == "invoke" {

// Make payment of X units from A to B

return t.invoke(stub, args)

} else if function == "delete" {

// Deletes an entity from its state

return t.delete(stub, args)

} else if function == "query" {

// the old "Query" is now implemtned in invoke

return t.query(stub, args)

}


return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")

}


// Transaction makes payment of X units from A to B

func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {

var A, B string    // Entities

var Aval, Bval int // Asset holdings

var X int          // Transaction value

var err error


if len(args) != 3 {

return shim.Error("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 shim.Error("Failed to get state")

}

if Avalbytes == nil {

return shim.Error("Entity not found")

}

Aval, _ = strconv.Atoi(string(Avalbytes))


Bvalbytes, err := stub.GetState(B)

if err != nil {

return shim.Error("Failed to get state")

}

if Bvalbytes == nil {

return shim.Error("Entity not found")

}

Bval, _ = strconv.Atoi(string(Bvalbytes))


// Perform the execution

X, err = strconv.Atoi(args[2])

if err != nil {

return shim.Error("Invalid transaction amount, expecting a integer value")

}

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 shim.Error(err.Error())

}


err = stub.PutState(B, []byte(strconv.Itoa(Bval)))

if err != nil {

return shim.Error(err.Error())

}


return shim.Success(nil)

}


// Deletes an entity from state

func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {

if len(args) != 1 {

return shim.Error("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 shim.Error("Failed to delete state")

}


return shim.Success(nil)

}


// query callback representing the query of a chaincode

func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {

var A string // Entities

var err error


if len(args) != 1 {

return shim.Error("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 shim.Error(jsonResp)

}


if Avalbytes == nil {

jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"

return shim.Error(jsonResp)

}


jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"

fmt.Printf("Query Response:%s\n", jsonResp)

return shim.Success(Avalbytes)

}


func main() {

err := shim.Start(new(SimpleChaincode))

if err != nil {

fmt.Printf("Error starting Simple chaincode: %s", err)

}

}


10 安裝鏈碼

        安裝和初始化鏈碼在 cli 容器中進行,首先進入 cli 容器:

docker exec -it cli /bin/bash

        執行如下語句安裝鏈碼:

peer chaincode install -n jiuxi -v 1.0.0 -p github.com/jiuxi

        鏈碼安裝成功截圖如下:image1.png


11 實例化鏈碼

        執行如下語句實例化鏈碼:

peer chaincode instantiate -o orderer.jiuxi.org:7050 -C channel1 -n jiuxi -v 1.0.0 -c '{"Args": ["init", "a", "100", "b", "200"]}'

        鏈碼執行成功後,會生成鏈碼容器,如下圖所示:image2.png


12 調用鏈碼

        執行如下語句調用鏈碼:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章