配置文件
docker-compose-cli.yaml
version: '2'
volumes:
orderer.itcast.com:
peer0.orggo.itcast.com:
peer1.orggo.itcast.com:
peer0.orgcpp.itcast.com:
peer1.orgcpp.itcast.com:
networks:
byfn:
services:
orderer.itcast.com:
extends:
file: base/docker-compose-base.yaml
service: orderer.itcast.com
container_name: orderer.itcast.com
networks:
- byfn
peer0.orggo.itcast.com:
container_name: peer0.orggo.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer0.orggo.itcast.com
networks:
- byfn
peer1.orggo.itcast.com:
container_name: peer1.orggo.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer1.orggo.itcast.com
networks:
- byfn
peer0.orgcpp.itcast.com:
container_name: peer0.orgcpp.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer0.orgcpp.itcast.com
networks:
- byfn
peer1.orgcpp.itcast.com:
container_name: peer1.orgcpp.itcast.com
extends:
file: base/docker-compose-base.yaml
service: peer1.orgcpp.itcast.com
networks:
- byfn
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
- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.orggo.itcast.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.itcast.com/peers/peer0.orggo.itcast.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/orggo.itcast.com/users/Admin@orggo.itcast.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/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- orderer.itcast.com
- peer0.orggo.itcast.com
- peer1.orggo.itcast.com
- peer0.orgcpp.itcast.com
- peer1.orgcpp.itcast.com
networks:
- byfn
configtx.yaml
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/itcast.com/msp
- &org_go
Name: OrgGoMSP
ID: OrgGoMSP
MSPDir: crypto-config/peerOrganizations/orggo.itcast.com/msp
AnchorPeers:
- Host: peer0.orggo.itcast.com
Port: 7051
- &org_cpp
Name: OrgCppMSP
ID: OrgCppMSP
MSPDir: crypto-config/peerOrganizations/orgcpp.itcast.com/msp
AnchorPeers:
- Host: peer0.orgcpp.itcast.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.itcast.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 32 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Profiles:
ItcastOrgsOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *org_go
- *org_cpp
ItcastOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *org_go
- *org_cpp
Capabilities:
<<: *ApplicationCapabilities
crypton-config.yaml
OrdererOrgs:
- Name: Orderer
Domain: itcast.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: OrgGo
Domain: orggo.itcast.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 3
- Name: OrgCpp
Domain: orgcpp.itcast.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 3
docker-compose-base.yaml
version: '2'
services:
orderer.itcast.com:
container_name: orderer.itcast.com
image: hyperledger/fabric-orderer:latest
environment:
- ORDERER_GENERAL_LOGLEVEL=INFO
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
- 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/itcast.com/orderers/orderer.itcast.com/msp:/var/hyperledger/orderer/msp
- ../crypto-config/ordererOrganizations/itcast.com/orderers/orderer.itcast.com/tls/:/var/hyperledger/orderer/tls
- orderer.itcast.com:/var/hyperledger/production/orderer
ports:
- 7050:7050
peer0.orggo.itcast.com:
container_name: peer0.orggo.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.orggo.itcast.com
- CORE_PEER_ADDRESS=peer0.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orggo.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orggo.itcast.com/peers/peer0.orggo.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer0.orggo.itcast.com:/var/hyperledger/production
ports:
- 7051:7051
- 7053:7053
peer1.orggo.itcast.com:
container_name: peer1.orggo.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.orggo.itcast.com
- CORE_PEER_ADDRESS=peer1.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.orggo.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orggo.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgGoMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orggo.itcast.com/peers/peer1.orggo.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orggo.itcast.com/peers/peer1.orggo.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer1.orggo.itcast.com:/var/hyperledger/production
ports:
- 8051:7051
- 8053:7053
peer0.orgcpp.itcast.com:
container_name: peer0.orgcpp.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.orgcpp.itcast.com
- CORE_PEER_ADDRESS=peer0.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.orgcpp.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgCppMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orgcpp.itcast.com/peers/peer0.orgcpp.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orgcpp.itcast.com/peers/peer0.orgcpp.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer0.orgcpp.itcast.com:/var/hyperledger/production
ports:
- 9051:7051
- 9053:7053
peer1.orgcpp.itcast.com:
container_name: peer1.orgcpp.itcast.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.orgcpp.itcast.com
- CORE_PEER_ADDRESS=peer1.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.orgcpp.itcast.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.orgcpp.itcast.com:7051
- CORE_PEER_LOCALMSPID=OrgCppMSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/orgcpp.itcast.com/peers/peer1.orgcpp.itcast.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/orgcpp.itcast.com/peers/peer1.orgcpp.itcast.com/tls:/etc/hyperledger/fabric/tls
- peer1.orgcpp.itcast.com:/var/hyperledger/production
ports:
- 10051:7051
- 10053:7053
peer-base.yaml
version: '2'
services:
peer-base:
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=itcast_byfn
- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_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
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
生成相关文件
mkdir channel-artifacts
cryptogen generate --config=crypton-config.yaml
configtxgen -profile ItcastOrgsOrdererGenesis -outputBlock ./genesis.block
configtxgen -profile ItcastOrgsChannel -outputCreateChannelTx channel.tx -channelID itcastchannel
configtxgen -profile ItcastOrgsChannel -outputAnchorPeersUpdate GOMSPanchors.tx -channelID itcastchannel -asOrg OrgGoMSP
configtxgen -profile ItcastOrgsChannel -outputAnchorPeersUpdate CppMSPanchors.tx -channelID itcastchannel -asOrg OrgCppMSP
mv *.tx *.block channel-artifacts/
启动网络./startup.sh
#!/bin/bash
systemctl start docker
docker-compose -f docker-compose-cli.yaml up -d
docker exec -it cli /bin/bash
创建通道
peer channel create -o orderer.itcast.com:7050 -c itcastchannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/itcast.com/msp/tlscacerts/tlsca.itcast.com-cert.pem
加入通道
peer channel join -b itcastchannel.block
编写链代码
业务描述
主要实现四大功能:用户注册(userRgister)、用户注销(userDelete)、用户转账(userTransfer)、用户查询(userQuery)
导入包及结构体定义
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"strconv"
)
type User struct {
Name string `json:"name"`
Gender string `json:"gender"`
Age string `json:"age"`
Balance int `json:balnace`
Txs []string `json:txs`
}
type ChaincodeInterface struct {
}
Init()与Invoke()
链码必须实现Init()与Invoke(),不然main函数里面无法运行。这里我进行初始化的时候不要传参。简单理解Invoke():实现函数的导航功能,并将参数传入到对应函数中。
func (t *ChaincodeInterface) Init(stub shim.ChaincodeStubInterface) pb.Response{
return shim.Success(nil)
}
func (t *ChaincodeInterface) Invoke(stub shim.ChaincodeStubInterface) pb.Response{
function,args := stub.GetFunctionAndParameters()
switch function {
case "userRegister":
return t.userRegister(stub,args)
case "userDelete":
return t.userDelete(stub,args)
case "userQuery":
return t.userQuery(stub,args)
case "userTransfer":
return t.userTransfer(stub,args)
default:
return shim.Error("Unsupported function")
}
return shim.Success(nil)
}
userRegister
-
一般来说,链码的编写有一个普遍套路
- 0.明确需要用到什么参数
- 1.检查参数个数是否正确
- 2.验证参数正确性
- 3.验证存在性
- 4.写入状态
func (t *ChaincodeInterface) userRegister(stub shim.ChaincodeStubInterface,args []string)pb.Response{
if len(args) != 4{
return shim.Error("Incorrect number of args.Expecting 4")
}
name := args[0]
gender := args[1]
age := args[2]
val := args[3]
if name == "" || gender == "" || age == "" || val == ""{
return shim.Error("Invalid args.")
}
balanace,err := strconv.Atoi(val)
if err != nil{
return shim.Error("convert to Int error")
}
exByes,err := stub.GetState(name)
if err == nil && len(exByes) != 0{
return shim.Error("user already exists")
}
user := User{
Name: name,
Gender: gender,
Age: age,
Balance: balanace,
Txs: make([]string,0),
}
userByes,err := json.Marshal(user)
if err != nil{
return shim.Error("marshal user error")
}
if err = stub.PutState(name,userByes);err != nil{
return shim.Error("Failed to put state")
}
return shim.Success(nil)
}
userDelete
func (t *ChaincodeInterface) userDelete(stub shim.ChaincodeStubInterface,args []string) pb.Response{
if len(args) != 1{
return shim.Error("Incorrect number of args.Expecting 1")
}
name := args[0]
if err := stub.DelState(name);err != nil{
return shim.Error("Failed to delete user")
}
return shim.Success(nil)
}
userQuery
func (t *ChaincodeInterface) userQuery(stub shim.ChaincodeStubInterface,args []string) pb.Response{
if len(args) != 1{
return shim.Error("Incorrect number of args.Expecting 1")
}
name := args[0]
userBytes,err := stub.GetState(name)
if err != nil{
return shim.Error("Failed to get state")
}
return shim.Success(userBytes)
}
userTransfer
func (t *ChaincodeInterface) userTransfer(stub shim.ChaincodeStubInterface,args []string) pb.Response{
if len(args) != 3{
return shim.Error("Incorrect number of args.Expecting 3")
}
userFrom,userTo,val := args[0],args[1],args[2]
if userFrom == "" || userTo == "" || val == ""{
return shim.Error("Invalid args")
}
existFrom,err := stub.GetState(userFrom)
if err == nil && len(existFrom) == 0{
return shim.Error("sender does not exist")
}
existTo,err := stub.GetState(userTo)
if err == nil && len(existTo) == 0{
return shim.Error("receiver does not exist")
}
var from,to User
tx,err := strconv.Atoi(val)
if err != nil{
return shim.Error("convert to Int error")
}
userFromBytes,err := stub.GetState(userFrom)
if err != nil{
return shim.Error("Failed to get userFrom state")
}
if err = json.Unmarshal(userFromBytes,&from);err != nil{
return shim.Error("Failed to unmarshal userFrom")
}
userToByes,err := stub.GetState(userTo)
if err != nil{
return shim.Error("Failed to get userFrom state")
}
if err = json.Unmarshal(userToByes,&to);err != nil{
return shim.Error("Failed to unmarshal userFrom")
}
if (tx > from.Balance){
return shim.Error("Insufficient balance")
}
from.Balance = from.Balance - tx
to.Balance = to.Balance + tx
from.Txs = append(from.Txs,fmt.Sprintf("Transfer %d to %s \n",tx,to.Name))
to.Txs = append(to.Txs,fmt.Sprintf("Recive %d from %s \n",tx,from.Name))
newFrom,err := json.Marshal(from)
if err != nil{
return shim.Error("marshal user error")
}
newTo,err := json.Marshal(to)
if err != nil{
return shim.Error("marshal user error")
}
if err = stub.PutState(from.Name,newFrom);err != nil{
return shim.Error("Failed to put state")
}
if err = stub.PutState(to.Name,newTo);err != nil{
return shim.Error("Failed to put state")
}
return shim.Success(nil)
}
完整链码
package main
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"strconv"
)
type User struct {
Name string `json:"name"`
Gender string `json:"gender"`
Age string `json:"age"`
Balance int `json:balnace`
Txs []string `json:txs`
}
type ChaincodeInterface struct {
}
func (t *ChaincodeInterface) Init(stub shim.ChaincodeStubInterface) pb.Response{
return shim.Success(nil)
}
func (t *ChaincodeInterface) Invoke(stub shim.ChaincodeStubInterface) pb.Response{
function,args := stub.GetFunctionAndParameters()
switch function {
case "userRegister":
return t.userRegister(stub,args)
case "userDelete":
return t.userDelete(stub,args)
case "userQuery":
return t.userQuery(stub,args)
case "userTransfer":
return t.userTransfer(stub,args)
default:
return shim.Error("Unsupported function")
}
return shim.Success(nil)
}
func (t *ChaincodeInterface) userRegister(stub shim.ChaincodeStubInterface,args []string)pb.Response{
if len(args) != 4{
return shim.Error("Incorrect number of args.Expecting 4")
}
name := args[0]
gender := args[1]
age := args[2]
val := args[3]
if name == "" || gender == "" || age == "" || val == ""{
return shim.Error("Invalid args.")
}
balanace,err := strconv.Atoi(val)
if err != nil{
return shim.Error("convert to Int error")
}
exByes,err := stub.GetState(name)
if err == nil && len(exByes) != 0{
return shim.Error("user already exists")
}
user := User{
Name: name,
Gender: gender,
Age: age,
Balance: balanace,
Txs: make([]string,0),
}
userByes,err := json.Marshal(user)
if err != nil{
return shim.Error("marshal user error")
}
if err = stub.PutState(name,userByes);err != nil{
return shim.Error("Failed to put state")
}
return shim.Success(nil)
}
func (t *ChaincodeInterface) userDelete(stub shim.ChaincodeStubInterface,args []string) pb.Response{
if len(args) != 1{
return shim.Error("Incorrect number of args.Expecting 1")
}
name := args[0]
if err := stub.DelState(name);err != nil{
return shim.Error("Failed to delete user")
}
return shim.Success(nil)
}
func (t *ChaincodeInterface) userQuery(stub shim.ChaincodeStubInterface,args []string) pb.Response{
if len(args) != 1{
return shim.Error("Incorrect number of args.Expecting 1")
}
name := args[0]
userBytes,err := stub.GetState(name)
if err != nil{
return shim.Error("Failed to get state")
}
return shim.Success(userBytes)
}
func (t *ChaincodeInterface) userTransfer(stub shim.ChaincodeStubInterface,args []string) pb.Response{
if len(args) != 3{
return shim.Error("Incorrect number of args.Expecting 3")
}
userFrom,userTo,val := args[0],args[1],args[2]
existFrom,err := stub.GetState(userFrom)
if err == nil && len(existFrom) == 0{
return shim.Error("sender does not exist")
}
existTo,err := stub.GetState(userTo)
if err == nil && len(existTo) == 0{
return shim.Error("receiver does not exist")
}
var from,to User
if userFrom == "" || userTo == "" || val == ""{
return shim.Error("Invalid args")
}
tx,err := strconv.Atoi(val)
if err != nil{
return shim.Error("convert to Int error")
}
userFromBytes,err := stub.GetState(userFrom)
if err != nil{
return shim.Error("Failed to get userFrom state")
}
if err = json.Unmarshal(userFromBytes,&from);err != nil{
return shim.Error("Failed to unmarshal userFrom")
}
userToByes,err := stub.GetState(userTo)
if err != nil{
return shim.Error("Failed to get userFrom state")
}
if err = json.Unmarshal(userToByes,&to);err != nil{
return shim.Error("Failed to unmarshal userFrom")
}
if (tx > from.Balance){
return shim.Error("Insufficient balance")
}
from.Balance = from.Balance - tx
to.Balance = to.Balance + tx
from.Txs = append(from.Txs,fmt.Sprintf("Transfer %d to %s \n",tx,to.Name))
to.Txs = append(to.Txs,fmt.Sprintf("Recive %d from %s \n",tx,from.Name))
newFrom,err := json.Marshal(from)
if err != nil{
return shim.Error("marshal user error")
}
newTo,err := json.Marshal(to)
if err != nil{
return shim.Error("marshal user error")
}
if err = stub.PutState(from.Name,newFrom);err != nil{
return shim.Error("Failed to put state")
}
if err = stub.PutState(to.Name,newTo);err != nil{
return shim.Error("Failed to put state")
}
return shim.Success(nil)
}
func main(){
err := shim.Start(new(ChaincodeInterface))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
安装链码、链码初始化
安装链码
peer chaincode install -n testcc -v 1.0 -l golang -p github.com/chaincode
链码初始化
peer chaincode instantiate -o orderer.itcast.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/itcast.com/msp/tlscacerts/tlsca.itcast.com-cert.pem -C itcastchannel -n testcc -l golang -v 1.0 -c '{"Args":["init"}' -P " OR ('OrgGoMSP.member','OrgCppMSP.member')"
链码效果
userRegister测试
peer chaincode invoke -o orderer.itcast.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/itcast.com/msp/tlscacerts/tlsca.itcast.com-cert.pem -C itcastchannel -n testcc -c '{"Args":["userRegister","Bruce","M","23"]}'
userQuery测试
peer chaincode query -C itcastchannel -n testcc -c '{"Args":["userQuery","Bruce"]}'
userTransfer测试
再创建一个用户Alice,余额为800
peer chaincode invoke -o orderer.itcast.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/itcast.com/msp/tlscacerts/tlsca.itcast.com-cert.pem -C itcastchannel -n testcc -c '{"Args":["userTransfer","Bruce","Alice","150"]}'
userDelete测试
peer chaincode invoke -o orderer.itcast.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypt
o/ordererOrganizations/itcast.com/msp/tlscacerts/tlsca.itcast.com-cert.pem -C itcastchannel -n testcc -c '{"Args":["userDelete","Bruce"]}'
退出并关闭
exit
docker-compose -f docker-compose-cli.yaml down -v
目前的话,我试出来的土办法:更新链码都是删除docker容器然后重新启动、安装链码。不知道你们有没有比较规范的办法。
|