A complete tutorial of project construction based on hyperledger fabric alliance chain + vue cli
Four, go language development chaincode
1. chaincode (based on Go language implementation)
Write trail.go and place it in the trail folder of the chaincode folder.
Statement
package main
import(
"fmt"
//"encoding/json"
"bytes"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)
Define the structure of blockchain storage
type point struct{
locationx float64 `json:"locationx"`
locationy float64 `json:"locationy"`
speed float64 `json:"speed"`
locatetime int `json:"locatetime"`
direction float64 `json:"direction"`
height float64 `json:"height"`
}
type Trail struct {
username string `json:"username"`
userid string `json:"userid"`
devid string `json:"devid"`
devstr string`json:"devstr"`
trid string `json:"trid"`
points [100]point `json:"points"`
mile float64 `json:"mile"`
state bool `json:"state"`
}
Init function of the contract
func (t *TrailChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
return shim.Success(nil)
}
Modify the Invoke function and add the contract function you need to call
func (t *TrailChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
fn , args := stub.GetFunctionAndParameters()
if fn == "insertTrail" {
return t.insertTrail(stub,args)
} else if fn == "searchAllTrail" {
return t.searchAllTrail(stub,args)
} else if fn == "searchOneTrail" {
return t.searchOneTrail(stub,args)
} else if fn == "deleteTrail" {
return t.deleteTrail(stub,args)
}
return shim.Error("Invoke 调用方法有误!")
}
Add data to the ledger: add car trajectories and write them into the ledger. Here we use json storage (couchDB storage)
func (t *TrailChaincode) insertTrail(stub shim.ChaincodeStubInterface , args []string) peer.Response{
//序列化
// trail := Trail{}
// jsonStr := args[0]
// err := json.Unmarshal([]byte(jsonStr), &trail)
// if err != nil {
// return shim.Error(err.Error())
// }
// accBytes, err := json.Marshal(trail)
// if err != nil {
// return shim.Error(err.Error())
// }
//保存数据
// err = stub.PutState(trail.trid, accBytes)
Trid := args[0]
jsonStr := args[1]
err := stub.PutState(Trid, []byte(jsonStr))
if err != nil {
shim.Error(err.Error())
}
return shim.Success([]byte("insert 写入账本成功!"))
}
//插入指定轨迹
Delete data from the ledger: delete the track of the car and delete it from the ledger
func (t *TrailChaincode) deleteTrail(stub shim.ChaincodeStubInterface , args []string) peer.Response{
Trid := args[0]
err := stub.DelState(Trid)
if err != nil {
shim.Error(err.Error())
}
return shim.Success([]byte("delete 删除账本成功!"))
}
//删除指定轨迹
Ledger query all tracks: execute all data query from the ledger
func (t *TrailChaincode) searchAllTrail(stub shim.ChaincodeStubInterface, args []string) peer.Response{
fmt.Println("start searchAllTrail")
// 获取所有用户的票数
resultIterator, err := stub.GetStateByRange("","")
if err != nil {
return shim.Error("查询所有的轨迹失败!")
}
defer resultIterator.Close()
var buffer bytes.Buffer
buffer.WriteString("[")
isWritten := false
for resultIterator.HasNext() {
queryResult , err := resultIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
if isWritten == true {
buffer.WriteString(",")
}
buffer.WriteString(string(queryResult.Value))
isWritten = true
}
buffer.WriteString("]")
fmt.Printf("查询结果:\n%s\n",buffer.String())
fmt.Println("end searchAllTrail")
return shim.Success(buffer.Bytes())
}
//查询所有的轨迹
Query important tracks based on Id
func (t *TrailChaincode) searchOneTrail(stub shim.ChaincodeStubInterface, args []string) peer.Response{
fmt.Println("start searchOneTrail")
// 获取所有用户的票数
trid := args[0]
result, err := stub.GetState(trid)
if err != nil {
return shim.Error("查询所有的轨迹失败!")
}
return shim.Success(result)
}
2. Installation of chain code
Docker: docker-compose.yml configuration (note the path correspondence, and enable the configuration couchDB)
#
# Copyright IBM Corp All Rights Reserved
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
networks:
basic:
services:
ca.example.com:
image: hyperledger/fabric-ca
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca.example.com
- FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
- FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/4239aa0dcd76daeeb8ba0cda701851d14504d31aad1b2ddddbac6a57365e497c_sk
ports:
- "7054:7054"
command: sh -c 'fabric-ca-server start -b admin:adminpw -d'
volumes:
- ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
container_name: ca.example.com
networks:
- basic
orderer.example.com:
container_name: orderer.example.com
image: hyperledger/fabric-orderer
environment:
- ORDERER_GENERAL_LOGLEVEL=debug
- 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/example.com/orderers/orderer.example.com/:/etc/hyperledger/msp/orderer
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/:/etc/hyperledger/msp/peerOrg1
networks:
- basic
peer0.org1.example.com:
container_name: peer0.org1.example.com
image: hyperledger/fabric-peer
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer0.org1.example.com
- CORE_LOGGING_PEER=debug
- CORE_CHAINCODE_LOGGING_LEVEL=DEBUG
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
# # the following setting starts chaincode containers on the same
# # bridge network as the peers
# # https://docs.docker.com/compose/networking/
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${
COMPOSE_PROJECT_NAME}_basic
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984
# The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
# provide the credentials for ledger to connect to CouchDB. The username and password must
# match the username and password set for the associated CouchDB.
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
working_dir: /opt/gopath/src/github.com/hyperledger/fabric
command: peer node start
# command: peer node start --peer-chaincodedev=true
ports:
- 7051:7051
- 7053:7053
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/msp/peer
- ./crypto-config/peerOrganizations/org1.example.com/users:/etc/hyperledger/msp/users
- ./config:/etc/hyperledger/configtx
depends_on:
- orderer.example.com
- couchdb
networks:
- basic
couchdb:
container_name: couchdb
image: hyperledger/fabric-couchdb
# Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
# for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode.
environment:
- COUCHDB_USER=
- COUCHDB_PASSWORD=
ports:
- 5984:5984
networks:
- basic
cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/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/:/opt/gopath/src/github.com/
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
networks:
- basic
#depends_on:
# - orderer.example.com
# - peer0.org1.example.com
# - couchdb
startFabric.sh shell command to install the chain code (the chain code path is located in /opt/gopath/src/github.com/)
Note that every time the chain code is upgraded, change the chain code version number before reinstalling
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp" cli peer chaincode install -n trail -v 1.0 -p github.com/trail
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp" cli peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n trail -v 1.0 -c '{"Args":[""]}' -P "OR ('Org1MSP.member','Org2MSP.member')"
After finishing chain code editing and installation, we can start node call code writing