概述
一、链码
1.1 什么是链码
链代码也称智能合约,是控制区块链网络中相关方相互交互的业务逻辑。链代码将业务网络交易封装在代码中,最终在一个 Docker 容器内运行。
链代码即一个Go文件,创建好文件后进行函数开发等操作。关于链码的详细信息,可以参考官方提供的链代码教程。
1.2 链码开发
链码使用Go语言开发,因此在编写链码前需要准备好Go语言环境,以及需要下载Fabric库文件。
1.2.1 链码的实现步骤
第一步:在%GOPATH%/src目录下新建一个chaincode文件夹。
第二步:进入chaincode文件夹,然后新建一个Go文件,并导入shim包。
shim包提供了一些 API,以便您的链代码与底层区块链网络交互来访问状态变量、交易上下文、调用方证书和属性,并调用其他链代码和执行其他操作。
第三步:定义一个结构体,然后提供main函数。
package main
import (
"fmt"
"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric-protos-go/peer"
)
# 定义结构体
type Constract struct {}
#
func main() {
shim.Start(new(Constract ))
}
第四步:为结构体提供Init函数。该函数用于任何与初始化、引导或设置相关的任务。
func (c* Constract)Init();
Init函数在链代码首次部署到区块链网络时调用,将由部署自己的链代码实例的每个对等节点执行。
第五步:为结构体提供Invoke函数。只要修改区块链的状态,就会调用该方法。简而言之,所有创建、更新和删除操作都应封装在Invoke方法内。对此方法的所有调用都会在区块链上记录为交易,这些交易最终被写入区块中。
func (c* Constract)Invoke();
1.2.2 链码操作相关的API
(1)shim包的核心方法:
shim包主要负责和客户端进行通信。如果在链码中使用该包的方法,需要手动进行引入github.com/hyperledger/fabric/core/chaincode/shim
。
关于shim包里面更多的方法,可以查看shim文档。
(2)ChaincodeStubInterface接口的核心方法:
在shim包中有一个接口ChaincodeStubInterface,该接口提供了一组用于操作Fabric中账本数据的方法。ChaincodeStubInterface接口的核心方法大概可以分为四大类:系统管理、存储管理、交易管理、调用外部chaincode。
- 系统管理:
方法名 | 方法描述 |
---|---|
GetFunctionAndParameters | 获取chaincode客户端传递过来的参数 |
- 存储管理:
方法名 | 方法描述 |
---|---|
PutState | 把客户端传递过来的数据保存到Fabric中 |
GetState | 从Fabric中取出数据 |
GetStateByRange | 根据范围查询数据,该方法返回一个迭代器接口 |
GetHistoryForKey | 查询某个键的历史记录 |
DelState | 从Fabric中删除数据 |
CreateCompositeKey | 给定一组属性,将这些属性组合起来构造一个复合键 |
GetStateByPartialCompositeKey | 根据局部的复合键返回所有的匹配的键值 |
SplitCompositeKey | 给定一个复合键,将其拆分为复合键所有的属性 |
- 交易管理:
方法名 | 方法描述 |
---|---|
GetTxTimestamp | 获取当前客户端发送的交易时间戳 |
GetTxID | 获取客户端发送的交易编号 |
- 调用外部chaincode:
方法名 | 方法描述 |
---|---|
InvokeChaincode | 调用另一个链码中的Invoke方法 |
1.2.3 链码示例
下面官方提供的链码示例,以供大家学习使用。
mport (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// 链码结构体
type SimpleChaincode struct {
}
// 实例化链码时候调用该方法
// 调用格式为:{"Args":["init","a","100","b","200"]}
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
// 获取要调用的方法名(init)和参数数组(['a','100','b','200'])
_, args := stub.GetFunctionAndParameters()
var A, B string // 该变量用于存储实体
var Aval, Bval int // 该变量用于存储实体资产
var err error
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// 初始化链码
A = args[0] // a
Aval, err = strconv.Atoi(args[1]) // 100
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
B = args[2] // b
Bval, err = strconv.Atoi(args[3]) // 200
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
// 把数据写入区块链中
err = stub.PutState(A, []byte(strconv.Itoa(Aval))) // a = 100
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval))) // b = 200
if err != nil {
return shim.Error(err.Error())
}
// 返回响应结果
return shim.Success(nil)
}
// 执行交易时候调用
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
// 获取调用的方法名和参数数组
function, args := stub.GetFunctionAndParameters()
// 根据方法名进行不同的处理
if function == "invoke" {
// 执行转账
return t.invoke(stub, args)
} else if function == "delete" {
// 从区块链中删除实体
return t.delete(stub, args)
} else if function == "query" {
// 查询数据
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting "invoke" "delete" "query"")
}
// 转账交易
// 调用格式:{"Args":["invoke","a","b","10"]}
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A, B string // 存储实体的变量
var Aval, Bval int // 存储实体资产的变量
var X int // 转账金额
var err error
if len(args) != 3 {
return shim.Error("Incorrect number of arguments. Expecting 3")
}
A = args[0] // a
B = args[1] // b
// 从区块链中获取a的数据
Avalbytes, err := stub.GetState(A)
// 如果获取失败,返回错误信息`Failed to get state`
if err != nil {
return shim.Error("Failed to get state")
}
// 如果实体不存在,返回错误信息`Entity not found`
if Avalbytes == nil {
return shim.Error("Entity not found")
}
Aval, _ = strconv.Atoi(string(Avalbytes)) // 100
// 从区块链中获取b的数据
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)) // 200
// 执行转账
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 = %dn", Aval, Bval)
// 将数据写入区块链中
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) 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)
}
// 查询
// 调用格式:查询数据-{"Args":["query","a"]}
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // 该变量存储要查询的实体
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
A = args[0] // a
// 从区块链中读取a的数据,该数据为字节数据
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)
}
// 将读取到的数据封装成json后返回调用者
jsonResp := "{"Name":"" + A + "","Amount":"" + string(Avalbytes) + ""}"
fmt.Printf("Query Response:%sn", jsonResp)
return shim.Success(Avalbytes)
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
二、交易背书Endorse
在Fabric中有一个非常重要的概念称为Endorsement,中文名为背书。背书的过程是一笔交易被确认的过程。而背书策略被用来指示对相关的参与方如何对交易讲行确认。当一个节点接收到一个交易请求的时候,会调用VSCC(系统Chaincode,专门负责处理背书相关的操作)与交易的chaincode共同来验证交易的合法性。在VSCC和交易的Chaincode共同对交易的确认中, 通常会做以下的校验:
- 参与背书的签名是否有效。
- 参与背书的数量是否满足要求。
- 所有背书参与方是否满足要求。
书策略的设置是通过部署时instantiate
命令中-P
-参数来设置的。
peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C testchannel -n testcc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND('OrgGoMSP.member','OrgJavaMSG.member')"
上面-P参数说明的是当前Chaincode发起的交易,需要组织编号为OrgGoMSP
和组织编号为OrgJavaMSP
的组织中的任何一个用户共同参与交易的确认并且同意,这样交易才能生效并被记录到区块链中。通过上述背书策略的实例我们可以知道背书策略是通过一定的关键字和系统的属性组成的。
除了可以使用AND关键字以外,Fabric还提供了OR关键字,表示参与方的任何一方参与背书即完成交易的确认。
"OR ('Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')"
另外,Fabric还支持AND和OR关键字的混合使用,例如:
"OR ('Org1MSP.member', AND('Org2MSP.member', 'Org3MSP.member'))"
上面背书策略有两种办法让交易生效。
1)组织Org1MSP中的某个成员对交易进行验证;
2)组织Org2MSP和组织Org3MSP中的成员共同就交易进行验证;
值得注意的是,背书规则只针对chaincode中写入数据的操作进行校验,对于查询类操作不背书。
三、solo多机多节点部署
3.1 环境准备
第一步:准备三台主机。
名称 | IP | hostname | 组织机构 |
---|---|---|---|
orderer | 192.168.31.20 | orderer.test.com | OrdererOrg |
peer0 | 192.168.31.21 | peer0.orggo.test.com | OrgGo |
peer0 | 192.168.31.22 | peer0.orgcpp.test.com | OrgCpp |
第二步:在每台主机主目录下新建一个文件夹作为工作目录。
# 192.168.31.20
mkdir ~/testwork
# 192.168.31.21
mkdir ~/testwork
# 192.168.31.22
mkdir ~/testwork
3.2 部署orderer节点
3.2.1 编写证书配置文件
crypto-config.yaml
OrdererOrgs:
- Name: Orderer
Domain: test.com
Specs:
- Hostname: orderer
-
PeerOrgs:
- Name: OrgGo
Domain: orggo.test.com
EnableNodeOUs: false
Template:
Count: 1
Users:
Count: 1
- Name: OrgCpp
Domain: orgcpp.test.com
EnableNodeOUs: false
Template:
Count: 1
Users:
Count: 1
3.2.2 编写通道和创世块配置文件
configtx.yaml
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/test.com/msp
- &OrgGo
Name: OrgGoMSP
ID: OrgGoMSP
MSPDir: crypto-config/peerOrganizations/orggo.test.com/msp
AnchorPeers:
- Host: peer0.orggo.test.com
Port: 7051
- &OrgCpp
Name: OrgCppMSP
ID: OrgCppMSP
MSPDir: crypto-config/peerOrganizations/orgcpp.test.com/msp
AnchorPeers:
- Host: peer0.orgcpp.test.com
Port: 7051
Capabilities:
Global: &ChannelCapabilities
V1_1: true
Orderer: &OrdererCapabilities
V1_1: true
Application: &ApplicationCapabilities
V1_2: true
Application: &ApplicationDefaults
Organizations:
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.test.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Profiles:
TwoOrgsOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *OrgGo
- *OrgCpp
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *OrgGo
- *OrgCpp
Capabilities:
<<: *ApplicationCapabilities
3.2.3 生成配置文件
# 生成证书文件
cryptogen generate --config=crypto-config.yaml
# 生成创世块文件
mkdir ./channel-artifacts
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
# 生成通道文件
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID testchannel
3.2.4 编写docker-compse
version: '2'
services:
orderer.test.com:
container_name: orderer.test.com
image: hyperledger/fabric-orderer:latest
environment:
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=testwork_default
- ORDERER_GENERAL_LOGLEVEL=DEBUG
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_LISTENPORT=7050
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
# enabled TLS
- ORDERER_GENERAL_TLS_ENABLED=true
- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
working_dir: /opt/gopath/src/github.com/hyperledger/fabric
command: orderer
volumes:
- ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ./crypto-config/ordererOrganizations/test.com/orderers/orderer.test.com/msp:/var/hyperledger/orderer/msp
- ./crypto-config/ordererOrganizations/test.com/orderers/orderer.test.com/tls/:/var/hyperledger/orderer/tls
networks:
default:
aliases:
- testwork
ports:
- 7050:7050
完成上面所有工作后,启动docker容器。
docker-compose up -d
3.3 部署peer0.orggo节点
3.3.1 拷贝文件
将上面生成的证书目录拷贝到当前主机的testwork工作目录下。
3.3.2 准备chaincode文件
在工作目录下新建chaincode目录,该目录用于存放chaincode文件。
进入chaincode目录,然后将官方提供的chaincode示例文件拷贝到这里。
hyperledge-fabric安装包提供的chaincode示例文件在hyperledger-febric/fabric-samples/chaincode/chaincode_example02/go目录下。
3.3.3 编写docker-compose文件
version: '2'
services:
peer0.orggo.test.com:
container_name: peer0.orggo.test.com
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=testwork_default
- FABRIC_LOGGING_SPEC=DEBUG
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_LOCALMSPID=OrgGoMSP
- CORE_PEER_ID=peer0.orggo.test.com
- CORE_PEER_ADDRESS=peer0.orggo.test.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orggo.test.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orggo.test.com:7051
# TLS
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/orggo.test.com/peers/peer0.orggo.test.com/msp:/etc/hyperledger/fabric/msp
- ./crypto-config/peerOrganizations/orggo.test.com/peers/peer0.orggo.test.com/tls:/etc/hyperledger/fabric/tls
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
networks:
default:
aliases:
- testwork
ports:
- 7051:7051
- 7053:7053
extra_hosts:
- "orderer.test.com:192.168.31.20"
- "orgcpp.test.com:192.168.31.22"
cli:
container_name: cli
image: hyperledger/fabric-tools:latest
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.orggo.test.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.test.com/peers/peer0.orggo.test.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.test.com/peers/peer0.orggo.test.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.test.com/peers/peer0.orggo.test.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.test.com/users/Admin@orggo.test.com/msp
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/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- peer0.orggo.test.com
networks:
default:
aliases:
- testwork
extra_hosts:
- "orderer.test.com:192.168.31.20"
- "peer0.orggo.test.com:192.168.31.21"
- "peer0.orgcpp.test.com:192.168.31.22"
上面工作完成后启动容器:
docker-compose up -d
3.3.4 在节点中进行相关操作
第一步:进入cli容器;
docker exec -it cli bash
第二步:创建通道;
peer channel create -o orderer.test.com:7050 -c testchannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/msp/tlscacerts/tlsca.test.com-cert.pem
第三步:将生成的通道文件移入channel-artifacts目录中;
mv testchannel.block ./channel-artifacts
第四步:加入通道;
peer channel join -b ./channel-artifacts/testchannel.block
第五步:安装链码;
peer chaincode install -n testcc -v 1.0 -l golang -p github.com/chaincode
第六步:将链码进行打包;
peer chaincode package -n testcc -p github.com/chaincode -v 1.0 testcc.1.0.out
打包完成后,将生成的testcc.1.0.out
文件移入到channel-artifacts文件夹里面。
3.4 部署peer0.orgcpp节点
3.4.1 拷贝文件
将上面生成的testchannel.block、testcc.1.0.out、以及证书文件夹拷贝到当前主机的testwork工作目录下。
3.4.2 编写docker-compose文件
version: '2'
services:
peer0.orgcpp.test.com:
container_name: peer0.orgcpp.test.com
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=testwork_default
- FABRIC_LOGGING_SPEC=DEBUG
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_LOCALMSPID=OrgCppMSP
- CORE_PEER_ID=peer0.orgcpp.test.com
- CORE_PEER_ADDRESS=peer0.orgcpp.test.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orgcpp.test.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orgcpp.test.com:7051
# TLS
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/orgcpp.test.com/peers/peer0.orgcpp.test.com/msp:/etc/hyperledger/fabric/msp
- ./crypto-config/peerOrganizations/orgcpp.test.com/peers/peer0.orgcpp.test.com/tls:/etc/hyperledger/fabric/tls
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
networks:
default:
aliases:
- testwork
ports:
- 7051:7051
- 7053:7053
extra_hosts:
- "orderer.test.com:192.168.31.20"
- "peer0.orggo.test.com:192.168.31.21"
cli:
container_name: cliCpp
image: hyperledger/fabric-tools:latest
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=INFO
- CORE_PEER_ID=cliCpp
- CORE_PEER_ADDRESS=peer0.orgcpp.test.com:7051
- CORE_PEER_LOCALMSPID=OrgCppMSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.test.com/peers/peer0.orgcpp.test.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.test.com/peers/peer0.orgcpp.test.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.test.com/peers/peer0.orgcpp.test.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.test.com/users/Admin@orgcpp.test.com/msp
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/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- peer0.orgcpp.test.com
networks:
default:
aliases:
- testwork
extra_hosts:
- "orderer.test.com:192.168.31.20"
- "peer0.orggo.test.com:192.168.31.21"
- "peer0.orgcpp.test.com:192.168.31.22"
完成后启动docker容器:
docker-compose up -d
3.4.3 节点相关操作
第一步:进入cliCpp容器;
docker exec -it cliCpp bash
第二步:加入通道;
peer channel join -b ./channel-artifacts/testchannel.block
第三步:安装链码;
peer chaincode install ./channel-artifacts/testcc.1.0.out
第四步:实例化链码;
peer chaincode instantiate -o orderer.test.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/msp/tlscacerts/tlsca.test.com-cert.pem -C testchannel -n testcc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND('OrgGoMSP.member', 'OrgCppMSP.member')"
3.5 测试
- 查询
peer chaincode query -C testchannel -n testcc -c '{"Args":["query","a"]}'
- 交易
peer chaincode invoke -o orderer.test.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/test.com/msp/tlscacerts/tlsca.test.com-cert.pem -C testchannel -n testcc --peerAddresses peer0.orggo.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.test.com/peers/peer0.orggo.test.com/tls/ca.crt --peerAddresses peer0.orgcpp.test.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orgcpp.test.com/peers/peer0.orgcpp.test.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
3.6 可能遇到的问题
问题一:链码指纹不匹配
原因分析:由于安装链码文件时候生成的hash值不相同。
解决办法:在第一个安装链码的节点上对链码文件进行打包,然后把打包后的文件发给其他节点进行安装即可。
# 打包链码
peer chaincode package -n testcc -p github.com/chaincode -v 1.0 testcc.1.0.out
# 安装链码
peer chaincode install ./channel-artifacts/testcc.1.0.out
问题二:连接orderer.test.com:7050失败
原因分析:由于不同主机的docker容器网络互相隔离所导致。
解决办法:
1)分别为每个节点的docker容器设置网段。
修改配置文件/etc/docker/daemon.json,添加以下配置:
# 192.168.31.20
{
"debug" : true,
"default-address-pools" : [
{
"base" : "172.17.0.1/16",
"size" : 24
}
]
}
# 192.168.31.21
{
"debug" : true,
"default-address-pools" : [
{
"base" : "172.18.0.1/16",
"size" : 24
}
]
}
# 192.168.31.22
{
"debug" : true,
"default-address-pools" : [
{
"base" : "172.19.0.1/16",
"size" : 24
}
]
}
上面12.11.0.0/16
可以根据实际情况自行指定。配置完成后重启docker服务。
systemctl restart docker
2)查看orderer容器的ip地址(比如:172.17.0.1)。
3)给peer0.orggo.test.com和peer0.orgcpp.test.com节点上添加静态路由。IP地址是orderer节点容器的IP和order节点宿主机IP的对应关系
ip route add 172.17.0.1 via 192.168.31.20
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -L -n
最后
以上就是自由斑马为你收集整理的区块链开源实现Hyperledge Fabric(三)一、链码二、交易背书Endorse三、solo多机多节点部署的全部内容,希望文章能够帮你解决区块链开源实现Hyperledge Fabric(三)一、链码二、交易背书Endorse三、solo多机多节点部署所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复