처음 하이퍼레저 패브릭을 시작할 때, fabric/fabric-samples
의 byfn.sh
를 사용하여 네트워크를 구축하였다. 여기에 쓰이는 체인코드는 chaincode_example02
인데, 그저 A, B 사이에 돈을 송금하는 간단한 코드이다. fabric-sdk-py
를 사용하여 트랜잭션을 생성하였고, 실험 또한 이 환경에서 진행되었다.
그러나 chaincode_example02
체인코드는 너무 간단하여 좀 더 범용적인 체인코드를 써야겠다고 생각했고, 여러 체인코드들 중 선택한 것이 바로 fabcar
이다. fabcar
에는 다음과 같은 함수들이 있다.
- initLedger
- queryCar
- queryAllCars
- createCar
- changeCarOwner
fabcar
체인코드를 사용하려면 기존 설정 파일에서 체인코드 설정 부분만 바꿔주면 되는것 아닌가?라는 생각에서 byfn 관련 스크립트는 이리저리 고쳐보았는데, 알 수 없는 오류 투성이였고, byfn 스크립트가 basic-network 스크립트보다 훨씬 복잡했다. 따라서, 복잡한 것을 먼저 고치기보다 fabcar
의 startFabric.sh
(basic-network의 스크립트 사용) 파일을 먼저 수정해보자는 생각이 들어서 바로 유턴을 했다.
우선 fabcar
의 startFabric.sh
은 fabric/fabric-samples/basic-network
를 기반으로 실행되었고, 기본 네트워크 컴포넌트들은 다음과 같다.
- ca.example.com
- orderer.example.com
- peer0.org1.example.com
- couchdb
조직 1개, 피어 1개로, 오더러 1개로 비교적 간단한 구성이고, 이를 조직 2개, 피어 2개, 오더러 1개로 바꾸려고 시도했다. 다음은 앞선 내용과 같이 바꾸는데 있어서의 오류를 정리한 내용이다.
fabcar
의 startFabric.sh
를 실행함으로써 일련의 네트워크 구축이 진행되니, 이 파일부터 천천히 살펴보도록 하겠다.
set -e
# don't rewrite paths for Windows Git Bash users
export MSYS_NO_PATHCONV=1
starttime=$(date +%s)
CC_SRC_LANGUAGE=${1:-"go"}
CC_SRC_LANGUAGE=`echo "$CC_SRC_LANGUAGE" | tr [:upper:] [:lower:]`
if [ "$CC_SRC_LANGUAGE" = "go" -o "$CC_SRC_LANGUAGE" = "golang" ]; then
CC_RUNTIME_LANGUAGE=golang
CC_SRC_PATH=github.com/fabcar/go
elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then
CC_RUNTIME_LANGUAGE=node # chaincode runtime language is node.js
CC_SRC_PATH=/opt/gopath/src/github.com/fabcar/javascript
elif [ "$CC_SRC_LANGUAGE" = "typescript" ]; then
CC_RUNTIME_LANGUAGE=node # chaincode runtime language is node.js
CC_SRC_PATH=/opt/gopath/src/github.com/fabcar/typescript
echo Compiling TypeScript code into JavaScript ...
pushd ../chaincode/fabcar/typescript
npm install
npm run build
popd
echo Finished compiling TypeScript code into JavaScript
else
echo The chaincode language ${CC_SRC_LANGUAGE} is not supported by this script
echo Supported chaincode languages are: go, javascript, and typescript
exit 1
fi
# clean the keystore
rm -rf ./hfc-key-store
# launch network; create channel and join peer to channel
cd ../basic-network
./start.sh
# Now launch the CLI container in order to install, instantiate chaincode
# and prime the ledger with our 10 cars
docker-compose -f ./docker-compose.yml up -d cli
docker ps -a
윗 부분은 어떤 언어를 사용하고 체인코드 위치에 대한 설정이고, 하단 cd ../basic-network
부분을 보면, 디렉터리를 basic-network
로 옮긴 후 start.sh
파일을 통해 새로운 스크립트를 실행한다.
start.sh
파일을 살펴보기 전에 generate.sh
파일을 먼저 살펴보자. 여기는 configtx
관련 내용들이 있는데, 여기서도 수정할 파일이 2가지 있다.
- configtx.yaml
- crypto-config.yaml
configtx.yaml
을 보자.
나는 기존 configtx.yaml
사용하지 않고 fabric-samples/first-network
의 configtx.yaml
을 사용하였다. 그리고 편의에 맞게 파일을 수정했다. (대부분의 주석은 삭제함)
################################################################################
# Section: Organizations
################################################################################
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Writers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Admins:
Type: Signature
Rule: "OR('OrdererMSP.admin')"
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org1MSP.admin')"
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org2MSP.admin')"
AnchorPeers:
- Host: peer0.org2.example.com
Port: 9051
################################################################################
# SECTION: Capabilities
################################################################################
Capabilities:
Channel: &ChannelCapabilities
V1_3: true
Orderer: &OrdererCapabilities
V1_1: true
Application: &ApplicationCapabilities
V1_3: true
V1_2: false
V1_1: false
################################################################################
# SECTION: Application
################################################################################
Application: &ApplicationDefaults
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ApplicationCapabilities
#################################################################################
# SECTION: Orderer
################################################################################
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
BlockValidation:
Type: ImplicitMeta
Rule: "ANY Writers"
################################################################################
# CHANNEL
################################################################################
Channel: &ChannelDefaults
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ChannelCapabilities
################################################################################
# Profile
################################################################################
Profiles:
TwoOrgsOrdererGenesis:
<<: *ChannelDefaults
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel:
Consortium: SampleConsortium
<<: *ChannelDefaults
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
위와 같이 설정한 다음, crypto-config.yaml
파일을 수정했다.
# ---------------------------------------------------------------------------
# "OrdererOrgs" - Definition of organizations managing orderer nodes
# ---------------------------------------------------------------------------
OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
# ---------------------------------------------------------------------------
# Org1
# ---------------------------------------------------------------------------
- Name: Org1
Domain: org1.example.com
Template:
Count: 2
Users:
Count: 1
# ---------------------------------------------------------------------------
# Org2
# ---------------------------------------------------------------------------
- Name: Org2
Domain: org2.example.com
Template:
Count: 2
Users:
Count: 1
이렇게 작성한 뒤, generate.sh
파일에 다음 내용을 추가한다. (startFabric.sh
를 실행하기 전에 이 과정이 먼저 진행되어야 한다.)
# generate genesis block for orderer
configtxgen -profile TwoOrgOrdererGenesis -outputBlock ./config/genesis.block
if [ "$?" -ne 0 ]; then
echo "Failed to generate orderer genesis block..."
exit 1
fi
# generate channel configuration transaction
configtxgen -profile TwoOrgChannel -outputCreateChannelTx ./config/channel.tx -channelID $CHANNEL_NAME
if [ "$?" -ne 0 ]; then
echo "Failed to generate channel configuration transaction..."
exit 1
fi
# generate anchor peer transaction
configtxgen -profile TwoOrgChannel -outputAnchorPeersUpdate ./config/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
if [ "$?" -ne 0 ]; then
echo "Failed to generate anchor peer update for Org1MSP..."
exit 1
fi
# generate anchor peer transaction
configtxgen -profile TwoOrgChannel -outputAnchorPeersUpdate ./config/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
if [ "$?" -ne 0 ]; then
echo "Failed to generate anchor peer update for Org2MSP..."
exit 1
fi
그리고 generate.sh
를 실행한다. 그럼 genesis.block
등 관련 파일들이 basic-network/config
디렉터리에 생성된다.
start.sh
파일로 넘어가보도록 하겠다.
set -ev
# don't rewrite paths for Windows Git Bash users
export MSYS_NO_PATHCONV=1
docker-compose -f docker-compose.yml down
docker-compose -f docker-compose.yml up -d ca.example.com orderer.example.com peer0.org1.example.com couchdb
docker ps -a
# wait for Hyperledger Fabric to start
# incase of errors when running later commands, issue export FABRIC_START_TIMEOUT=<larger number>
export FABRIC_START_TIMEOUT=10
#echo ${FABRIC_START_TIMEOUT}
sleep ${FABRIC_START_TIMEOUT}
# Create the channel
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel create -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/channel.tx
# Join peer0.org1.example.com to the channel.
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel join -b mychannel.block
여기서 docker-compose
를 통해 네트워크 구축이 시작된다. 이제 필요한 건 docker-compose.yml
파일 수정, 추가한 피어들을 채널에 추가시키는 내용 스크립트에 추가 등이 있었다. 그래서 docker-compose.yml
에 다음 내용을 추가하였다.
...
orderer.example.com:
container_name: orderer.example.com
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/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
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/:/etc/hyperledger/msp/peerOrg1
- ./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/:/etc/hyperledger/msp/peerOrg2
- ./crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/:/etc/hyperledger/msp/peerOrg2
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
- FABRIC_LOGGING_SPEC=info
- CORE_CHAINCODE_LOGGING_LEVEL=debug
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LISTENADDRESS=peer0.org1.example.com:7051
# - CORE_PEER_GOSSIP_ENDPOINT=peer0.org1.example.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:8051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
- CORE_VM_DOCKER_ATTACHSTDOUT=true
#jyk
- CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
# # 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=couchdb0: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
- couchdb0
networks:
- basic
peer1.org1.example.com:
container_name: peer1.org1.example.com
image: hyperledger/fabric-peer
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer1.org1.example.com
- 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.example.com:8051
- CORE_PEER_LISTENADDRESS=peer1.org1.example.com:8051
# - CORE_PEER_GOSSIP_ENDPOINT=peer1.org1.example.com:8051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:8051
- CORE_VM_DOCKER_ATTACHSTDOUT=true
#jyk
- CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:8052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:8052
# # 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=couchdb1: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:
- 8051:8051
- 8053:8053
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.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
- couchdb1
networks:
- basic
...
위와 같이 peer0.org1,example.com 이외에, peer1.org1.example.com, peer0.org2.example.com, peer1.org2.example.com 피어를 추가했고 피어당 하나의 couchdb를 생성하였다. (내용을 추가할 때 기존 파일에 peer0.org1.example.com
관련된 내용을 검색하며 새로운 내용을 추가하면 훨씬 수월하다.)
잠깐 지금까지 해온 내용을 정리해보자.
startFabric.sh
를 타고 basic-network 스크립트 파일로 넘어왔다.- basic-network의
configtx.yaml
,crypto-config.yaml
,generate.sh
파일을 수정하였다. - basic-network의
docker-compose.yml
파일 수정
start.sh
로 돌아가서 다음 내용을 추가한다.
# Add peer1.org1, peer0.org2, peer1.org2 and couchDBs
docker-compose -f docker-compose.yml up -d ca.example.com orderer.example.com peer0.org1.example.com peer1.org1.example.com peer0.org2.example.com peer1.org2.example.com couchdb0 couchdb1 couchdb2 couchdb3
...
# Create the channel
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel create -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/channel.tx
# Copy mychannel.block to Org2
docker cp peer0.org1.example.com:/opt/gopath/src/github.com/hyperledger/fabric/mychannel.block .
docker cp mychannel.block peer0.org2.example.com:/opt/gopath/src/github.com/hyperledger/fabric/mychannel.block
# Join peer0.org1.example.com to the channel.
docker exec -e "CORE_PEER_ADDRESS=peer0.org1.example.com:7051" -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel join -b mychannel.block
# Join peer1.org1.example.com to the channel.
docker exec -e "CORE_PEER_ADDRESS=peer1.org1.example.com:8051" -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel join -b mychannel.block
# Join peer0.org2.example.com to the channel.
docker exec -e "CORE_PEER_ADDRESS=peer0.org2.example.com:9051" -e "CORE_PEER_LOCALMSPID=Org2MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org2.example.com/msp" peer0.org2.example.com peer channel join -b mychannel.block
# Join peer1.org2.example.com to the channel.
docker exec -e "CORE_PEER_ADDRESS=peer1.org2.example.com:10051" -e "CORE_PEER_LOCALMSPID=Org2MSP" -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org2.example.com/msp" peer0.org2.example.com peer channel join -b mychannel.block
채널 생성 후 docker cp ~
가 있는데, 이는 mychannel.block
파일을 Org2의 앵커 피어인 peer0.org2.example.com
로 복사하는 과정이다. (peer0.org2.example.com 이 채널에 조인할 때, mychannel.block 을 찾지 못한다는 오류가 발생하여 추가하였음)
-e "CORE_PEER_ADDRESS"
옵션을 추가하였다. 그리고 peer1.org1.example.com
은 앵커 피어 peer0.org1.example.com
를 통해 채널에 조인하고, peer1.org2.example.com
은 앵커 피어 peer0.org2.example.com
를 통해 채널에 조인하게끔 하였다.
basic-network 에서의 설정은 다 끝난 것 같다. (혹여나 빠진 부분이 있다면 댓글 부탁드립니다..^^)
다시 startFabric.sh
로 돌아오자.
...
# Install chaincode on peer0.org1.example.com
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_ADDRESS=peer0.org1.example.com:7051" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" cli peer chaincode install -n fabcar -v 1.0 -p "$CC_SRC_PATH" -l "$CC_RUNTIME_LANGUAGE"
# Install chaincode on peer1.org1.example.com
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_ADDRESS=peer1.org1.example.com:8051" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" cli peer chaincode install -n fabcar -v 1.0 -p "$CC_SRC_PATH" -l "$CC_RUNTIME_LANGUAGE"
# Install chaincode on peer0.org2.example.com
docker exec -e "CORE_PEER_LOCALMSPID=Org2MSP" -e "CORE_PEER_ADDRESS=peer0.org2.example.com:9051" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp" cli peer chaincode install -n fabcar -v 1.0 -p "$CC_SRC_PATH" -l "$CC_RUNTIME_LANGUAGE"
# Install chaincode on peer1.org2.example.com
docker exec -e "CORE_PEER_LOCALMSPID=Org2MSP" -e "CORE_PEER_ADDRESS=peer1.org2.example.com:10051" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp" cli peer chaincode install -n fabcar -v 1.0 -p "$CC_SRC_PATH" -l "$CC_RUNTIME_LANGUAGE"
echo "************************* CHAINCODE INSTALLED ****************************"
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_ADDRESS=peer0.org1.example.com:7051" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" cli peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n fabcar -l "$CC_RUNTIME_LANGUAGE" -v 1.0 -c '{"Args":[]}' -P "OR ('Org1MSP.member', 'Org2MSP.member')"
sleep 10
echo "************************ CHAINCODE INSTANTIATED **************************"
# Call initLedger
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/Admin@org1.example.com/msp" cli peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n fabcar -c '{"function":"initLedger","Args":[]}'
# Call queryCar to peer1.org1.example.com
docker exec -e "CORE_PEER_ADDRESS=peer1.org1.example.com:8051" -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" cli peer chaincode query -o orderer.example.com:7050 -C mychannel -n fabcar -c '{"function":"queryCar","Args":["CAR1"]}'
# Call queryCar to peer0.org2.example.com
docker exec -e "CORE_PEER_ADDRESS=peer0.org2.example.com:9051" -e "CORE_PEER_LOCALMSPID=Org2MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp" cli peer chaincode query -o orderer.example.com:7050 -C mychannel -n fabcar -c '{"function":"queryCar","Args":["CAR2"]}'
# Call queryCar to peer1.org2.example.com
docker exec -e "CORE_PEER_ADDRESS=peer1.org2.example.com:10051" -e "CORE_PEER_LOCALMSPID=Org2MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp" cli peer chaincode query -o orderer.example.com:7050 -C mychannel -n fabcar -c '{"function":"queryCar","Args":["CAR3"]}'
cat <<EOF
...
위와 같이 모든 피어에 체인코드를 설치하고, 각 피어에 query를 보냄으로써 해당 피어의 체인코드가 컨테이너로 올라가도록 했다. 이렇게 수정한 다음 startFabric.sh
를 실행하면 조직 2개, 피어 4개, 오더러 1개, couchDB 4개로 구성된 패브릭 네트워크를 구성할 수 있다.
패브릭 관련 질문이 stackoverflow에 많이 없어서 조금 헤맸다. 조직 1개에 피어 하나 추가해도 오류가 나고, 뭘 하나 추가해도 계속 오류가 나서 다소 시간이 걸렸지만 그래도 직접 구축하여 사용하니 뿌듯했다. 사실 byfn.sh 를 돌리면 편하지만 어떻게 구축되는지 잘 모르고 사용했었는데 이번 기회를 통해서 대략적인 흐름을 알았다.
이제 여기에 grpc + fabric-sdk-py 를 사용한 내용을 정리하려 한다...