SlideShare a Scribd company logo
1 of 170
Download to read offline
HyperLedger Fabric V2.5
Practice
한국폴리텍대학
스마트금융과
Prerequisites on this practice
• Install Ubuntu 22.04 LTS
• For this exercise only, all libraries will be installed under a root account.
-----------------------------------------------------------------------------------------------------
• apt-get -y install docker-compose
docker --version
docker-compose –version
• systemctl start docker
• systemctl enable docker
https://hyperledger-fabric.readthedocs.io/en/release-2.5/prereqs.html
ㅅ 설치
• curl -sSLO
https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-
fabric.sh && chmod +x install-fabric.sh
• ./install-fabric.sh
https://hyperledger-fabric.readthedocs.io/en/release-2.5/install.html
Fabric Contract APIs and Application APIs
• Fabric Contract APIs
Smart Contract(ChainCode) APIs are available for Go, Node.js, Java
• Fabric Application APIs
Hyperledger Fabric offers a Fabric Gateway client API for Go, Node.js, Java
https://hyperledger.github.io/fabric-gateway/
https://hyperledger-fabric.readthedocs.io/en/release-2.5/sdk_chaincode.html
나중에 다뤄 봅시다.
첫 번째 튜토리얼
Using the Fabric test network
목표
- 전반적인 아키텍처의 이해(DOCKER)
- 체인코드 배포과정 체험
Using the Fabric test network
• It includes two peer organizations and an ordering organization.
• For simplicity, a single node Raft ordering service is configured.
• To reduce complexity, a TLS Certificate Authority (CA) is not deployed. All
certificates are issued by the root CAs.
• The sample network deploys a Fabric network with Docker Compose. Because the
nodes are isolated within a Docker Compose network, the test network is not
configured to connect to other running Fabric nodes.
https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
Using the Fabric test network
• at fabric-samples/test-network
• ./network.sh up
• docker ps –a
2 peer, 1 orderer will be listed
- Peer
• Peers store the blockchain ledger and validate transactions before they are
committed to the ledger.
• Peers run the smart contracts.
• Every peer in the network needs to belong to an organization
- peer0.org1.example.com
- peer0.org2.example.com
https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
Using the Fabric test network
- Orderer
• After ordering nodes receive endorsed transactions from clients, they come to
consensus on the order of transactions and then add them to blocks. The blocks are
then distributed to peer nodes, which add the blocks to the blockchain ledger.
- orderer.example.com
• It would use the Raft consensus algorithm to come to agreement on the order of
transactions across the network
https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
Using the Fabric test network
- creating a channel
• Channels are a private layer of communication between specific network
members.
• ./network.sh createChannel
Using the Fabric test network
channel ledger
https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
Generating channel genesis block 'mychannel.block'
+ configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/mychannel.block -channelID mychannel
Creating channel mychannel
Using organization 1
+ osnadmin channel join --channelID mychannel --config-block ./channel-artifacts/mychannel.block -o localhost:7053 --ca-file
/root/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
--client-cert /root/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
--client-key /root/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
+ res=0
Status: 201
{
"name": "mychannel",
"url": "/participation/v1/channels/mychannel",
"consensusRelation": "consenter",
"status": "active",
"height": 1
}
Channel 'mychannel' created
Joining org1 peer to the channel...
Using organization 1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2023-03-19 10:55:44.556 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-03-19 10:55:45.007 UTC 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel
Joining org2 peer to the channel...
Using organization 2
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2023-03-19 10:55:48.116 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-03-19 10:55:48.188 UTC 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel
- creating a channel
Using the Fabric test network
Setting anchor peer for org1...
Using organization 1
Fetching channel config for channel mychannel
Using organization 1
Fetching the most recent configuration block for the channel
Generating anchor peer update transaction for Org1 on channel mychannel
Anchor peer set for org 'Org1MSP' on channel 'mychannel'
Setting anchor peer for org2...
Using organization 2
Fetching channel config for channel mychannel
Using organization 2
Fetching the most recent configuration block for the channel
Generating anchor peer update transaction for Org2 on channel mychannel
Anchor peer set for org 'Org2MSP' on channel 'mychannel'
Channel 'mychannel' joined
- Creating a channel
Using the Fabric test network
- Starting a chaincode on the channel
• apt install jq
• apt-get install openjdk-11-jdk
• ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java -ccl java
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
export PATH=$PATH:$JAVA_HOME/bin
vi ~/.bashrc
source ~/.bashrc
Using the Fabric test network
https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
- Interacting with the network
Using the Fabric test network
vi ~/.bashrc
source ~/.bashrc
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
- Interacting with the network
Using the Fabric test network
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C
mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --
tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c
'{"function":"InitLedger","Args":[]}'
Because the endorsement policy for the asset-transfer (basic) chaincode requires the transaction to be signed by Org1 and Org2, the chaincode invoke command needs
to target both peer0.org1.example.com and peer0.org2.example.com using the --peerAddresses flag. Because TLS is enabled for the network, the command also
needs to reference the TLS certificate for each peer using the --tlsRootCertFiles flag.
- Interacting with the network
Using the Fabric test network
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C
mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --
tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c
'{"function":"TransferAsset","Args":["asset6","Christopher"]}'
- Interacting with the network
Using the Fabric test network
Ledger check by Org2, it should be same as Org1
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'
Fabric CA를 사용하여 구동
• ./network.sh up –ca
• 노드와 사용자ID를 등록
• MSP 폴더를 생성
https://hyperledger-fabric.readthedocs.io/en/release-2.5/membership/membership.html
https://hyperledger-fabric-ca.readthedocs.io/en/latest/operations_guide.html
org1의 CA
org1.exampl.com의 CA
org1.exampl.com의 MSP
=
ca.org1 이 발급한 admin 인증서
Fabric CA를 사용하여 구동
cryptogen 으로 생성 Fabric CA로 생성
org1.example.com의 CA
peer0.org1.exampl.com의 msp
peer0 peer1
cryptogen 으로 생성 Fabric CA로 생성
Fabric CA를 사용하여 구동
예전 교육 자료에서…(HLF 2.0)
예전 교육 자료에서…(HLF 2.0)
두 번째 튜토리얼
Deploying a smart contract to a channel
이번 튜토리얼은
첫 번째 튜토리얼에서 아래의 명령을 통해 체인코드를 패키징~배포~커밋한 내용을 하나씩 단계별로
체인코드를 배포하는 튜토리얼
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
준비
• cd fabric-samples/test-network
• ./network.sh down
• ./network.sh up createChannel
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Docker 모니터링
• 별도 터미널 쉘에서 실행
• cd fabric-samples/test-network
• ./monitordocker.sh fabric_test
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Install and define a chaincode
https://hyperledger-fabric.readthedocs.io/en/release-2.5/chaincode_lifecycle.html
Package the smart contract
• 패키지 명령 형식
peer lifecycle chaincode package ${CC_NAME}.tar.gz --path ${CC_SRC_PATH} --lang
${CC_RUNTIME_LANGUAGE} --label ${CC_NAME}_${CC_VERSION} >&log.txt
• 자바 체인코드 패키지 생성
peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-java/ --lang
java --label basic_1.0
tar는 해당 자바 디렉토리를 target 디렉토리만 빼고 단순 압축한 형태임
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Install the chaincode package
• Org1과 Org2 모두에 설치
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
root@koposvr:~/fabric-samples/test-network# peer lifecycle chaincode install basic.tar.gz
2023-03-21 07:02:07.236 UTC 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200
payload:"nJbasic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e022tbasic_1.0" >
2023-03-21 07:02:07.270 UTC 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier:
basic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e
root@koposvr:~/fabric-samples/test-network# export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
root@koposvr:~/fabric-samples/test-network# peer lifecycle chaincode install basic.tar.gz
2023-03-21 07:06:08.573 UTC 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200
payload:"nJbasic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e022tbasic_1.0" >
2023-03-21 07:06:08.573 UTC 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier:
basic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e
Org1
Org2
두 개의 조직이 같은 식별자를 리턴함
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Approve a chaincode definition
peer lifecycle chaincode queryinstalled
export CC_PACKAGE_ID=basic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e
echo $CC_PACKAGE_ID
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --
name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export
CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --
name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
Org1과 Org2 모두에 승인 요청
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Committing the chaincode definition to the
channel (1/2)
• peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls --
cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam
ple.com-cert.pem" --output json
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Committing the chaincode definition to the
channel (2/2)
root@koposvr:~/fabric-samples/test-network# peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --
channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --
peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --
tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt”
2023-03-21 07:27:06.356 UTC 0001 INFO [chaincodeCmd] ClientWait -> txid [e5f9ad97cbb2821fbb0b906543469fc8f272098b5d436183cbb7c86b7b69959e]
committed with status (VALID) at localhost:9051
2023-03-21 07:27:06.360 UTC 0002 INFO [chaincodeCmd] ClientWait -> txid [e5f9ad97cbb2821fbb0b906543469fc8f272098b5d436183cbb7c86b7b69959e]
committed with status (VALID) at localhost:7051
peer lifecycle chaincode querycommitted --channelID mychannel --name basic --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Invoking the chaincode
• peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.
com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses
localhost:9051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c
'{"function":"InitLedger","Args":[]}'
• 2023-03-21 07:39:33.399 UTC 0001 INFO [chaincodeCmd] chaincodeInvokeOrQuery -> Chaincode invoke successful. result:
status:200
• peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
• [{"appraisedValue":300,"assetID":"asset1","color":"blue","owner":"Tomoko","size":5},{"appraisedValue":400,"assetID":"asset2","color":
"red","owner":"Brad","size":5},{"appraisedValue":500,"assetID":"asset3","color":"green","owner":"Jin
Soo","size":10},{"appraisedValue":600,"assetID":"asset4","color":"yellow","owner":"Max","size":10},{"appraisedValue":700,"assetID":"a
sset5","color":"black","owner":"Adrian","size":15},{"appraisedValue":700,"assetID":"asset6","color":"white","owner":"Michel","size":15}]
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Upgrading a smart contract (1/7)
• 준비
apt intall npm
• cd ../asset-transfer-basic/chaincode-javascript
• npm install
• cd ../../test-network
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Upgrading a smart contract (2/7)
• 패키징
• export PATH=${PWD}/../bin:$PATH
• export FABRIC_CFG_PATH=$PWD/../config/
• export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
• peer lifecycle chaincode package basic_2.tar.gz --path ../asset-transfer-basic/chaincode-javascript/ --lang node --label basic_2.0
• 패키지 설치 (Org1)
• export CORE_PEER_TLS_ENABLED=true
• export CORE_PEER_LOCALMSPID="Org1MSP"
• export
CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
• export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
• export CORE_PEER_ADDRESS=localhost:7051
• peer lifecycle chaincode install basic_2.tar.gz
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Upgrading a smart contract (3/7)
• 패키지 설치 확인 (Org1)
• peer lifecycle chaincode queryinstalled
• 체인코드 승인 요청 (Org1)
• export NEW_CC_PACKAGE_ID=basic_2.0:1d559f9fb3dd879601ee17047658c7e0c84eab732dca7c841102f20e42a9e7d4
• peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name
basic --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
• Org2 에도 동일하게 체인코드 설치
• export CORE_PEER_LOCALMSPID="Org2MSP"
• export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
• export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
• export CORE_PEER_ADDRESS=localhost:9051
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Upgrading a smart contract (4/7)
• 체인코드 설치 (Org2)
• peer lifecycle chaincode install basic_2.tar.gz
• 체인코드 승인 요청 (Org2)
• peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --
channelID mychannel --name basic --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam
ple.com-cert.pem“
• 커밋 가능여부 확인 (Org2)
• peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 2.0 --sequence 2 --tls --
cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam
ple.com-cert.pem" --output json
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Upgrading a smart contract (5/7)
• 체인코드 커밋 (Org1, Org2)
• peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID
mychannel --name basic --version 2.0 --sequence 2 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam
ple.com-cert.pem" --peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --
peerAddresses localhost:9051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
Upgrading a smart contract (6/7)
Upgrading a smart contract (7/7)
세 번째 튜토리얼
Running a Fabric Application
Fabric 어플리케이션와 블록체인 네트워크간 상호작용 데모
스마트 컨트랙트의 함수 호출을 위해 Fabric Gateway client API를 사용
시나리오
Java Application 에서 사전 배포한 스마트 컨트랙트를
Fabric Gateway API를 사용하여 호출하는 시나리오
사전 준비
• cd fabric-samples/test-network
• ./network.sh down
• ./network.sh up createChannel -c mychannel -ca
스마트 컨트랙트 배포(자바)
• ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/
-ccl java
스마트 컨트랙트를 호출할 어플리케이션 구동(자바)
• 새 터미널 열고, $FABRIC_HOME으로 이동하여...
• cd asset-transfer-basic/application-gateway-java
• ./gradlew build
• ./gradlew run
예> VB에서 25GB의 공간을 VDI로 할당하였는데, 우부투에서
df –h 로 확인한 공간이 12GB로 절반이하로 할당된 상황
$ lvm
lvm> lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
lvm> exit
$ resize2fs /dev/ubuntu-vg/ubuntu-lv
<Tip> 우분투에서 VirtualBox에서 할당한 공간보다
하드디스크 공간이 부족하게 잡히는 경우
Gateway에 대한 gRPC 연결을 설정
게이트웨이 연결 준비
호출할 스마트 계약에 액세스 gRPC 연결 및 Gateway 연결 준비 설정이
끝나고 호출된다.
블록체인에 호출할 함수 순서
임의 데이터로 블록체인 원장을 채우기
트랜잭션 기능을 호출하여 조회
• The application uses evaluateTransaction() to query the ledger by performing
a read-only transaction invocatio
트랜잭션 기능을 호출하여 생성
트랜잭션 기능을 호출하여 갱신
• This time the transaction is invoked using submitAsync(), which returns after successfully submitting the endorsed transaction to the ordering
service instead of waiting until the transaction is committed to the ledger.
갱신된 정보 확인
오류 케이스 확인
[참고] 전체 수행 로그
oot@koposvr:~/fabric-samples/asset-transfer-basic/application-gateway-java# ./gradlew
run
> Task :run
--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger
*** Transaction committed successfully
--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger
*** Result: [
{
"appraisedValue": 300,
"assetID": "asset1",
"color": "blue",
"owner": "Tomoko",
"size": 5
},
{
"appraisedValue": 400,
"assetID": "asset2",
"color": "red",
"owner": "Brad",
"size": 5
},
{
"appraisedValue": 500,
"assetID": "asset3",
"color": "green",
"owner": "Jin Soo",
"size": 10
},
{
"appraisedValue": 600,
"assetID": "asset4",
"color": "yellow",
"owner": "Max",
"size": 10
},
{
"appraisedValue": 700,
"assetID": "asset5",
"color": "black",
"owner": "Adrian",
"size": 15
},
{
"appraisedValue": 700,
"assetID": "asset6",
"color": "white",
"owner": "Michel",
"size": 15
}
]
--> Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments
*** Transaction committed successfully
--> Async Submit Transaction: TransferAsset, updates existing asset owner
*** Successfully submitted transaction to transfer ownership from Tom to Saptha
*** Waiting for transaction commit
*** Transaction committed successfully
--> Evaluate Transaction: ReadAsset, function returns asset attributes
*** Result:{
"owner": "Saptha",
"color": "yellow",
"size": 5,
"appraisedValue": 1300,
"assetID": "asset1679492916126"
}
--> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error
*** Successfully caught the error:
org.hyperledger.fabric.client.EndorseException: io.grpc.StatusRuntimeException: ABORTED: failed to endorse transaction, see attached details for more
info
at org.hyperledger.fabric.client.GatewayClient.endorse(GatewayClient.java:73)
at org.hyperledger.fabric.client.ProposalImpl.endorse(ProposalImpl.java:74)
at org.hyperledger.fabric.client.Proposal.endorse(Proposal.java:65)
at org.hyperledger.fabric.client.ContractImpl.submitTransaction(ContractImpl.java:47)
at App.updateNonExistentAsset(App.java:225)
at App.run(App.java:132)
at App.main(App.java:71)
Caused by: io.grpc.StatusRuntimeException: ABORTED: failed to endorse transaction, see attached details for more info
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:271)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:252)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:165)
at org.hyperledger.fabric.protos.gateway.GatewayGrpc$GatewayBlockingStub.endorse(GatewayGrpc.java:472)
at org.hyperledger.fabric.client.GatewayClient.endorse(GatewayClient.java:71)
... 6 more
Transaction ID: 0c4d10e9dd4b2573f9a06f9a8ac594f1c2098d3e65f3561dc05a8494761cf2ea
Error Details:
- address: peer0.org1.example.com:7051, mspId: Org1MSP, message: chaincode response 500, Asset asset70 does not exist
BUILD SUCCESSFUL in 20s
2 actionable tasks: 1 executed, 1 up-to-date
root@koposvr:~/fabric-samples/asset-transfer-basic/application-gateway-java#
네 번째 튜토리얼
Running External Chaincode Builders
- chaincode as a service
개요
• 기존
the peer to orchestrate the complete lifecycle of the chaincode
체인코드 빌드와 시작을 어떻게 할지, 체인코드 언어도 Peer에 전달해야 함
쿠버네티스 등 가상화된 환경이나 체인코드 재빌드를 위해 외부망 접속이 필요한
경우 등 복잡한 이슈가 있을 수 있음
• 따라서, Separation of Concern 관점에서 이를 서비스化 하자.
• 무엇으로? 도커로!
• 이미 ccaasbuiler라는 도커 이미지가 준비되어 있음
https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
준비
• cd test-network
• ./network.sh up createChannel
• 새로운 터미널에서 도커 모니터링을 위하여
./test-network/monitordocker.sh
https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
실행
• ./network.sh deployCCAAS -ccn basicj -ccp ../asset-transfer-basic/chaincode-java
• 빌드 오류 발생시, 하단 슬라이드 노트 참고
• 순서
① 체인코드 컨테이너를 빌드(Dockerfile)
② 체인코드 설치~커밋을 Peer에 실행
(이때, peer는 체인코드의 위치(host, port, tls인증서 정보를 획득하고 rpc로
peer <-> peer0org1_basicj_ccaas 또는 peer0org2_basicj_ccaas 와 통신하게 됨)
③ 도커 컨테이너 실행
https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
결과 확인
• 도커 프로세스 확인 → 두 개의 컨테이너를 확인
컨테이너 이름에 조직, 피어 및 체인코드 이름이 포함됨
☞ docker 모니터링 로그는 하단 슬라이드 노트 참조
https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
테스트
• export CORE_PEER_TLS_ENABLED=true
• export CORE_PEER_LOCALMSPID="Org1MSP"
• export
CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/tl
sca/tlsca.org1.example.com-cert.pem
• export
CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users
/Admin@org1.example.com/msp
• export CORE_PEER_ADDRESS=localhost:7051
• export PATH=${PWD}/../bin:$PATH
• export FABRIC_CFG_PATH=${PWD}/../config
• peer chaincode query -C mychannel -n basicj -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}' | jq
쉘에서 peer로 요청한 내용이 by rpc로 체인코드 컨테이너(peer0org1_basicj_ccaas 또는 peer0org2_basicj_ccaas)
로 전달되어 그 결과를 정상 수신하는지 확인하기 위한 테스트
https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
다섯 번째 튜토리얼
Using Private Data in Fabric
개요
• assetCollection
• Org1MSPPrivateCollection
• AgreeToTransfer
• Org2MSPPrivateCollection
• TransferAsset
시나리오
fabric_samples/asset-transfer-private-data/chaincode-java/collections_config.json
① Org1의 소유자가 데이터 생성
- (assetID, color, size, appraisedValue) = asset1, green, 20, 100
그런데 100에 해당하는 appraisedValue 속성은 비공개 데이터로 assetID, closer, size와
별도 저장됨
② Org1, Org2 모두 assetID, color, size에 대해서는 조회 가능
③ Org1의 구성원(소유자限)는 appraisedValue 조회 가능
④ Org2의 구성원은 appraisedValue 조회 : Org1으로 조회시 접근 불가, Org2로 조회시 Null
⑤ Org2의 구성원은 (assetID, color, size) 조회 가능
⑥ 이후, Org1의 소유자가 asset 을 이관하게 되면 기존 소유자는 appraisedValue조회가 안됨
AssetTransfer.java
../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
계약 생성 및 조회
Asset Transfer
Asset.java AssetPrivateDetails.java TransferAgreement.java
Public State의 기초자료 클래스
Private State의 기초자료 클래스
Asset 구매이관 기초자료 클래스
AssetTransfer.java ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
AssetTransfer.java
Public State 조회
Private State 조회
../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
AssetTransfer.java - ① CreateAsset
Public State 저장
Private State 저장
스마트 컨트랙트 함수 호출 주체가 해당 조직의 MSP ID와 같은지 검사
ex> clientMSPID == peerMSPID
다음 장…
../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
AssetTransfer.java - ② AgreeToTransfer
export ASSET_VALUE=$(echo -n "{"assetID":"asset1","appraisedValue":100}" | base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n private -c
'{"function":"AgreeToTransfer","Args":[]}' --transient "{"asset_value":"$ASSET_VALUE"}"
Org2MSPPrivateCollection에
구매하려는 assetID와 가격을 저장
-> 뒤의 TransferAsset에서 이 저장된 값을 검증에 사용(p72)
TransferAsset에서 aggKey로 조회하여 거래 종료후,
해당 키로 거래데이터 삭제
../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
implicit private data collection에 저장된다.
AssetTransfer.java – ③ ReadTransferAgreement ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
AssetTransfer.java - ④ TransferAsset
다음 장…
조건이 충족되면 양도 계약에서 구매자의 클라이언트 ID를
가져와 구매자를 자산의 새로운 소유자로 만듭니다.
그리고, 이전 소유자의 컬렉션에서 Asset을 삭제하고 이전
계약을 제거합니다
AgreeToTransfer에서 aggKey형태로 저장했음
../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
AssetTransfer.java - ⑤ VerifyAgreement
이 함수 호출 이전에
agreeToTransfer함수 호출을 통해
구매자가 특정가격에 구매를 하겠다고 등록한 상황
스마트 컨트랙트는 GetPrivateDataHash()를 사용하여
Org1MSPPrivateCollection감정가의 해시와 Org2MSPPrivateCollection이
일치하는지 확인합니다. 해시가 같으면 소유자와 관심있는 구매자가 동일한
자산 가치에 동의했음을 확인합니다.
../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
프라이빗 데이터 스마트 계약을 채널에 배포
./network.sh deployCC -ccn private -ccp ../asset-transfer-private-data/chaincode-java/ -ccl java -
ccep "OR('Org1MSP.peer','Org2MSP.peer')" -cccg ../asset-transfer-private-data/chaincode-
java/collections_config.json
위 명령 수행 결과 출력되는 로그중,
체인코드 승인, 커밋에 –collections-config 에 private data collection 파일의 경로가 같이 포함됨
go 체인코드는 잘 되는데, 자바 체인코드는 TLS 에러 발생
- openJDK 11.0.4 관련 이슈로 추정
• Go 설치
https://go.dev/doc/install
• 체인코드 배포를 Java에서 Go로 변경
• ./network.sh down
• ./network.sh deployCC -ccn private -ccp ../asset-transfer-private-
data/chaincode-go/ -ccl go -ccep "OR('Org1MSP.peer','Org2MSP.peer')" -
cccg ../asset-transfer-private-data/chaincode-go/collections_config.json
신원 등록 (Org1의 owner)
• Org1 CA를 사용하여 ID 자산 소유자를 생성
• Fabric CA 클라이언트 홈을 Org1 CA 관리자의 MSP로 설정합니다
• fabric-ca-client 도구를 사용하여 새 소유자 클라이언트 ID를 등록
fabric-ca-client register --caname ca-org1 --id.name owner --id.secret ownerpw --id.type client --
tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem"
• enroll명령에 등록 이름과 pw을 제공하여 ID 인증서 및 MSP 폴더를 생성
fabric-ca-client enroll -u https://owner:ownerpw@localhost:7054 --caname ca-org1 -M
"${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp"
--tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem"
• Node OU 구성 파일을 소유자 ID MSP 폴더에 복사
cp "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml"
"${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp/config.yaml"
org1 -> users -> owner
신원 등록 (Org2의 buyer)
• Org2 CA를 사용하여 구매자 ID를 생성
• Fabric CA 클라이언트 홈을 Org2 CA 관리자로 설정
• fabric-ca-client 도구를 사용하여 새 소유자 클라이언트 ID를 등록
fabric-ca-client register --caname ca-org2 --id.name buyer --id.secret buyerpw --id.type client --tls.certfiles
"${PWD}/organizations/fabric-ca/org2/tls-cert.pem“
• ID MSP 폴더를 생성
fabric-ca-client enroll -u https://buyer:buyerpw@localhost:8054 --caname ca-org2 -M
"${PWD}/organizations/peerOrganizations/org2.example.com/users/buyer@org2.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-
ca/org2/tls-cert.pem"
• Node OU 구성 파일을 구매자 ID MSP 폴더에 복사
cp "${PWD}/organizations/peerOrganizations/org2.example.com/msp/config.yaml"
"${PWD}/organizations/peerOrganizations/org2.example.com/users/buyer@org2.example.com/msp/config.yaml"
Create an asset in private data
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
Org1의 owner 클라이언트로 설정
export ASSET_PROPERTIES=$(echo -n "{"objectType":"asset","assetID":"asset1","color":"green","size":20,"appraisedValue":100}" |
base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C
mychannel -n private -c '{"function":"CreateAsset","Args":[]}' --transient "{"asset_properties":"$ASSET_PROPERTIES"}"
Query the private data as an authorized peer
query the assetCollection collection as Org1
peer chaincode query -C mychannel -n private -c '{"function":"ReadAsset","Args":["asset1"]}'
결과 : {"objectType":"asset","assetID":"asset1","color":"green","size":20,"owner":"x509::CN=appUser1,OU=admin,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US"}
Query for the appraisedValue private data of asset1 as a member of Org1.
peer chaincode query -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org1MSPPrivateCollection","asset1"]}'
결과 : {"assetID":"asset1","appraisedValue":100}
Query the private data as an unauthorized peer (1/3)
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/buyer@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
Org2의 buyer 클라이언트로 설정
Query private data Org2 is authorized to
peer chaincode query -C mychannel -n private -c '{"function":"ReadAsset","Args":["asset1"]}'
결과 : {"objectType":"asset","assetID":"asset1","color":"green","size":20,
"owner":"x509::CN=appUser1,OU=admin,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US" }
Query private data Org2 is not authorized to
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-
cert.pem" -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org2MSPPrivateCollection","asset1"]}'
결과 : empty response
Query the private data as an unauthorized peer (2/3)
Query private data Org2 is not authorized to
peer chaincode query -C mychannel -n private -c
'{"function":"ReadAssetPrivateDetails","Args":["Org1MSPPrivateCollection","asset1"]}'
결과 :
Query the private data as an unauthorized peer (3/3)
Transfer the Asset
agree to the appraised value of 100 as Org2
export ASSET_VALUE=$(echo -n "{"assetID":"asset1","appraisedValue":100}" | base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-
cert.pem" -C mychannel -n private -c '{"function":"AgreeToTransfer","Args":[]}' --transient "{"asset_value":"$ASSET_VALUE"}"
query the value they agreed to in the Org2 private data collection
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-
cert.pem" -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org2MSPPrivateCollection","asset1"]}'
상기와 같이 구매자가 구매 동의를 완료하였으니, 이제는 원 소유자가 이를 확인하여 Asset를 이관하는 시나리오
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
The owner from Org1 can read the data added by the AgreeToTransfer transaction to view the buyer identity:
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-
cert.pem" -C mychannel -n private -c '{"function":"ReadTransferAgreement","Args":["asset1"]}'
Transfer the Asset
체인코드의 GetPrivateDataHash()를 통해Org1MSPPrivateCollection 감정가의 해시와 Org2MSPPrivateCollection의 해시가 일치하는지 확인
조건이 충족되면 구매자의 클라이언트 ID를 가져와 구매자를 자산의 새로운 소유자로 설정
Run the following commands to transfer the asset
export ASSET_OWNER=$(echo -n "{"assetID":"asset1","buyerMSP":"Org2MSP"}" | base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
private -c '{"function":"TransferAsset","Args":[]}' --transient "{"asset_owner":"$ASSET_OWNER"}" --peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
query asset1 to see the results of the transfer
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
private -c '{"function":"ReadAsset","Args":["asset1"]}'
confirm that transfer removed the private details from the Org1 collection
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
private -c '{"function":"ReadAssetPrivateDetails","Args":["Org1MSPPrivateCollection","asset1"]}'
결과 : empty
Purge Private Data
• 3개의 블록이 생성되면 데이터가 자동으로
삭제되는 것을 테스트하는 섹션
• CreateAsset 함수를 3번 호출하여 3개의
블록이 생성되도록 환경을 조성한 수,
데이터를 조회해 보면,
기존에 asset1의 appraisedValue가 100으로 출력되던 데이터가
조회되지 않음을 확인할 수 있음
여섯 번째 튜토리얼
Secured asset transfer in Fabric
시나리오
• 자산 발행(Org1)
• 자산 식별자는 자산의 불변 속성의 해시이며 현재 소유자와 함께 모든 채널 구성원이 볼 수 있는 공개
채널 데이터로 저장
• 그러나 자산 불변 속성은 자산 소유자(및 이전 소유자)에게만 알려진 Private Information
• 관심 있는 구매자는 구매하기 전에 해시된 자산 ID에 대해 자산의 사유 재산을 확인하기를 원할
것입니다. 이는 구매자가 올바른 자산 설명을 가지고 있음을 확인
• 자산 양도 위한 구매자와 판매자가 먼저 자산의 속성과 판매 가격 합의
• 현재 소유자만 자산을 다른 조직으로 이전 가능
• 구매자와 판매자 모두 양도를 승인
준비
• ./network.sh up createChannel -c mychannel
• ./network.sh deployCC -ccn secured -ccp ../asset-transfer-secured-
agreement/chaincode-go/ -ccl go -ccep "OR('Org1MSP.peer','Org2MSP.peer')"
• 2개의 터미널창 준비
at Terminal #1
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:9051
at Terminal #2
Create an asset
• 모든 채널 구성원은 스마트 계약을 사용하여 조직이 소유한 자산을 생성할 수 있습니다. 자산의 세부
정보는 개인 데이터 컬렉션에 저장되며 자산을 소유한 조직에서만 액세스할 수 있습니다. 자산, 소유자 및
공개 설명의 공개 기록은 채널 원장에 저장됩니다. 모든 채널 구성원은 자산 소유자를 확인하기 위해 공공
소유권 기록에 액세스할 수 있으며 자산이 판매용인지 확인하기 위해 설명을 읽을 수 있습니다.
at Terminal #1
export ASSET_PROPERTIES=$(echo -n "{"object_type":"asset_properties","color":"blue","size":35,"salt":"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"}" | base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
'{"function":"CreateAsset","Args":["A new asset for Org1MSP"]}' --transient "{"asset_properties":"$ASSET_PROPERTIES"}"
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"GetAssetPrivateProperties","Args":["$ASSET_ID"]}"
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"ReadAsset","Args":["$ASSET_ID"]}"
생성후 리턴되는 해시값이 자산 ID가 됨
at Terminal #1
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"ChangePublicDescription","Args":["$ASSET_ID","This asset is for sale"]}"
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"ReadAsset","Args":["$ASSET_ID"]}"
Org1에서만 가능, Org2에서는 endorsement failure 500에러 발생
at Terminal #2
export ASSET_ID=d9923f21b770adbc79cbcc47a3aeecc81dc7f030bd129155301ce3932be7fbcc
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"ReadAsset","Args":["$ASSET_ID"]}"
Agree to sell as Org1
자산을 판매하려면 구매자와 판매자 모두 자산 가격에 동의하고 각자의 개인 데이터 컬렉션에 동일한 자산
속성이 있는지 확인해야 합니다. 각 당사자는 자신의 개인 데이터 컬렉션에 동의한 가격을 저장합니다.
개인 자산 전송 스마트 계약은 자산을 전송하기 전에 양 당사자가 동일한 가격과 자산 속성에 동의해야 한
다고 강제합니다.
at Terminal #1
export ASSET_PRICE=$(echo -n "{"asset_id":"$ASSET_ID","trade_id":"109f4b3c50d7b0df729d299bc6f8e9ef9066971f","price":110}" | base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"AgreeToSell","Args":["$ASSET_ID"]}" --transient "{"asset_price":"$ASSET_PRICE"}"
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"GetAssetSalesPrice","Args":["$ASSET_ID"]}"
구매자나 판매자가 아닌 채널 구성원이 가격을 추측하는 것을 방지하기 위해 사용
Agree to buy as Org2
구매에 동의하기 전에 다음 명령을 실행하여 자산 속성을 확인하십시오. 자산 속성과 salt는 구매자와
판매자 사이에서 이메일 또는 기타 통신을 통해 대역외로 전달됩니다.
at Terminal #2
export ASSET_PROPERTIES=$(echo -n "{"object_type":"asset_properties","color":"blue","size":35,"salt":"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"}" | base64 | tr -d n)
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"VerifyAssetProperties","Args":["$ASSET_ID"]}" --transient "{"asset_properties":"$ASSET_PROPERTIES"}"
다음 명령을 실행하여 100달러에 asset1 구매에 동의합니다. 현재 Org2는 Org1과 다른 가격에 동의합니다.
걱정하지 마십시오. 두 조직은 향후 단계에서 동일한 가격에 동의할 것입니다. 그러나 우리는 구매자와 판
매자가 다른 가격에 동의할 경우 어떤 일이 발생하는지 테스트하기 위해 이 일시적인 불일치를 사용할 수
있습니다. Org2는 Org1과 동일하게 사용해야 합니다
export ASSET_PRICE=$(echo -n "{"asset_id":"$ASSET_ID","trade_id":"109f4b3c50d7b0df729d299bc6f8e9ef9066971f","price":100}" | base64 | tr -d n)
export ASSET_PROPERTIES=$(echo -n "{"object_type":"asset_properties","color":"blue","size":35,"salt":"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"}" | base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"AgreeToBuy","Args":["$ASSET_ID"]}" --transient "{"asset_price":"$ASSET_PRICE", "asset_properties":"$ASSET_PROPERTIES"}"
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"GetAssetBidPrice","Args":["$ASSET_ID"]}"
Org1과 Org2가 자산 이전에 동의한 후 각 조직에서 동의한 가격이 Private data collection에 저장됩니다. 자산내역과 자산소유기록이 충돌
하는 것을 방지하기 위해 판매자와 구매자를 위한 복합키를 사용합니다. 합의된 가격은 각 조직의 피어에만 저장됩니다. 그러나 두 계약의
해시는 채널에 가입한 모든 피어의 Channel World State저장됩니다.
Transfer the asset from Org1 to Org2
두 조직이 가격 및 자산 속성에 동의한 후 Org1은 자산을 Org2로 이전하려고 시도할 수 있습니다. 스마트
계약의 개인 자산 이전 기능은 원장의 해시를 사용하여 두 조직이 동일한 가격에 동의했는지 확인합니다.
이 기능은 또한 판매자 및 구매자 개인 컬렉션의 자산 속성 해시를 확인하여 전송된 자산이 Org1이 소유한
자산과 동일한지 확인합니다.
at Terminal #1
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"TransferAsset","Args":["$ASSET_ID","Org2MSP"]}" --transient "{"asset_price":"$ASSET_PRICE"}" --peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
결과적으로 Org1과 Org2는 자산을 구매할 가격에 대해 새로운 합의에 도달합니다. Org1은 자산 가격을 100으로 떨어뜨립니다.
export ASSET_PRICE=$(echo -n "{"asset_id":"$ASSET_ID","trade_id":"109f4b3c50d7b0df729d299bc6f8e9ef9066971f","price":100}" | base64 | tr -d n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"AgreeToSell","Args":["$ASSET_ID","Org2MSP"]}" --transient "{"asset_price":"$ASSET_PRICE"}"
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"TransferAsset","Args":["$ASSET_ID","Org2MSP"]}" --transient "{"asset_price":"$ASSET_PRICE"}" --peerAddresses localhost:7051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"ReadAsset","Args":["$ASSET_ID"]}"
자산이 전송된 후 자산 세부 정보는 Org2 암시적 데이터 컬렉션에 배치되고 Org1 암시적 데이터 컬렉션에서 삭제됩니다. 결과적으로 자산
세부 정보는 이제 Org2 피어에만 저장됩니다. 원장의 자산 소유권 레코드는 Org2가 자산을 소유하고 있음을 반영하도록 업데이트됩니다.
Update the asset description as Org2
Org2 터미널에서 작동합니다. 이제 Org2가 자산을 소유하고 있으므로 Org2 암시적 데이터 컬렉션에서 자
산 세부 정보를 읽을 수 있습니다.
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"GetAssetPrivateProperties","Args":["$ASSET_ID"]}"
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"ChangePublicDescription","Args":["$ASSET_ID","This asset is not for sale"]}"
peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c
"{"function":"ReadAsset","Args":["$ASSET_ID"]}"
일곱 번째 튜토리얼
Using CouchDB
개요
• A Docker image of CouchDB is available and we recommend that it be run on
the same server as the peer.
• If a rich query includes a sort specification, then an index on that field is
required
• When using CouchDB, each chaincode is represented as its own CouchDB
database, that is, each chaincode has its own namespace for keys.
개요
docType is used to identify that this JSON document represents an asset. Potentially there could be
other JSON document types in the chaincode namespace
Create an index
When defining an index for use in chaincode queries
- each one must be defined in its own text file with the extension *.json
- the index definition must be formatted in the CouchDB index JSON format.
ddoc선택적으로 색인 정의에 디자인 문서 속성을 지정할 수 있습니다. 디자
인 문서는 인덱스를 포함하도록 설계된 CouchDB 구조입니다. 색인은 효율
성을 위해 설계 문서로 그룹화할 수 있지만 CouchDB는 설계 문서당 하나의
색인을 권장합니다.
Create an index
• 예시
Add the index to your chaincode folder
JSON 인덱스 파일은 체인코드가 위치한 디렉토리의
META-INF/statedb/couchdb/indexes 에 준비해야 함
Start the network
• cd ../asset-transfer-ledger-queries/chaincode-go
• GO111MODULE=on go mod vendor
• cd ../../test-network
• ./network.sh up createChannel -s couchdb
• ./network.sh deployCC -ccn ledger -ccp ../asset-transfer-ledger-
queries/chaincode-go/ -ccl go -ccep "OR('Org1MSP.peer','Org2MSP.peer')"
• docker logs peer0.org1.example.com 2>&1 | grep "CouchDB index" Verify index was deployed
Query the CouchDB State Database
• use_index 키워드를 사용하여 쿼리에 인덱스 이름을 명시적으로 포함하는 것을 권고
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
ledger -c '{"Args":["CreateAsset","asset1","blue","5","tom","35"]}'
peer chaincode query -C mychannel -n ledger -c '{"Args":["QueryAssets", "{"selector":{"docType":"asset","owner":"tom"},
"use_index":["_design/indexOwnerDoc", "indexOwner"]}"]}'
SHIM API 호출
체인코드의 CreateAsset함수 내에서 하드코딩으로 DocType을 "asset"으로 설정했었음
Use best practices for queries and indexes
// Example one: query fully supported by the index
export CHANNEL_NAME=mychannel
peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"docType":"asset","owner":"tom"},
"use_index":["indexOwnerDoc", "indexOwner"]}"]}'
peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"docType":"asset","owner":"tom","color":"blue"},
"use_index":["/indexOwnerDoc", "indexOwner"]}"]}'
peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"owner":"tom"}, "use_index":["indexOwnerDoc",
"indexOwner"]}"]}'
peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"$or":[{"docType":"asset"},{"owner":"tom"}]},
"use_index":["indexOwnerDoc", "indexOwner"]}"]}'
peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets",
"{"selector":{"$or":[{"docType":"asset","owner":"tom"},{"color":"yellow"}]}, "use_index":["indexOwnerDoc", "indexOwner"]}"]}'
인덱스 사용
인덱스 사용, 응답시간 지연
인덱스 미사용
인덱스 사용, 응답시간 지연
인덱스 미사용
블록체인 데이터 구조는 거래를 검증하고 확인하는 데 최적화되어 있음
데이터 분석이나 보고에는 적합하지 않음
Query the CouchDB State Database With Pagination
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
ledger -c '{"Args":["CreateAsset","asset2","yellow","5","tom","35"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
ledger -c '{"Args":["CreateAsset","asset3","green","6","tom","20"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
ledger -c '{"Args":["CreateAsset","asset4","purple","7","tom","20"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n
ledger -c '{"Args":["CreateAsset","asset5","blue","8","tom","40"]}'
// Rich Query with index name explicitly specified and a page size of 3:
peer chaincode query -C mychannel -n ledger -c '{"Args":["QueryAssetsWithPagination", "{"selector":{"docType":"asset","owner":"tom"},
"use_index":["_design/indexOwnerDoc", "indexOwner"]}","3",""]}'
SHIM API 호출
Pagination 사이즈 : 3
시작페이지 : default(1)
Query the CouchDB State Database With Pagination
peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssetsWithPagination", "{"selector":{"docType":"asset","owner":"tom"},
"use_index":["_design/indexOwnerDoc",
"indexOwner"]}","3","g1AAAABJeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqzJRYXp5YYg2Q5YLI5IPUgSVawJIjFXJKfm5UFANozE8s"]}'
peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssetsWithPagination", "{"selector":{"docType":"asset","owner":"tom"},
"use_index":["_design/indexOwnerDoc",
"indexOwner"]}","3","g1AAAABJeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqzJRYXp5aYgmQ5YLI5IPUgSVawJIjFXJKfm5UFANqBE80"]}'
앞 장에 이어서, 다음 페이지 조회
조회결과를 북마크 인덱스를 리턴하는데, 이 값을 이용하여 다음 페이지 조회에 사용함
Range Query Pagination 기능도 지원함
- GetStateByRangeWithPagination
Update an Index
• http://localhost:5984/_utils 접속 (admin/adminpw)
Update an Index
Update an Index
아래 방법도 가능
Delete an Index
curl -X DELETE
http://admin:adminpw@localhost:5984/mychannel_ledger/_index/indexOwnerDoc/json/indexOwner -H
"accept: */*" -H "Host: localhost:5984"
여덟 번째 튜토리얼
Create a channel the test network
• 어플리케이션 채널 생성하고 오더링 노드에 조인하는 튜토리얼
• In this tutorial,
① we use the configtxgen tool to create a channel genesis block
② and then use the osnadmin channel command to create the channel.(application channel)
준비
• ./network.sh up
By default, when you start the test network, it does not contain any channels.
채널을 생성하기 위해서, 다음 장의 configtxgen 사용
Set up the configtxgen tool
• 채널은 제네시스 블록에 채널 생성 정보를 오더링 서비스에 전달함으로써 생성된다.
• configex.yaml에 채널 명세를 해야 한다.
• configtxgen은 fabric-sample/bin 디렉토리에 있다.
• export PATH=${PWD}/../bin:$PATH
• export FABRIC_CFG_PATH=${PWD}/configtx
• configtxgen --help
The configtx.yaml file
• Organizations
• Ordering service : 합의 방식/프로토콜
• Channel policies
• Channel profiles
Step one: Generate the genesis block of the channel
• configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-
artifacts/channel1.block -channelID channel1
Step two: Create the application channel
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert
"$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
Join peers to the channel
• view the channels
• Join peers to the channel
osnadmin channel list -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key
"$ORDERER_ADMIN_TLS_PRIVATE_KEY"
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
export FABRIC_CFG_PATH=$PWD/../config/
peer channel join -b ./channel-artifacts/channel1.block
peer CLI를 사용하기 위해 환경변수 재설정
acting as the Org1 admin and targeting the Org1 peer
Join peers to the channel
• Join peers to the channel
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
export FABRIC_CFG_PATH=$PWD/../config/
peer channel join -b ./channel-artifacts/channel1.block
acting as the Org2 admin and targeting the Org2 peer
→ Joined their peers to the channel
Set anchor peer
• We will use the configtxlator tool to update the channel configuration and
select an anchor peer for Org1 and Org2.
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
acting as the Org1 admin
peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile
"$ORDERER_CA"
fetch the channel configuration
cd channel-artifacts
configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
jq '.data.data[0].payload.data.config' config_block.json > config.json
cp config.json config_copy.json
jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host":
"peer0.org1.example.com","port": 7051}]},"version": "0"}}' config_copy.json > modified_config.json
decode the block from protobuf into a JSON objec
Set anchor peer
configtxlator proto_encode --input config.json --type common.Config --output config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output config_update.pb
채널 구성 파일(원본, 수정본)을 protobuf 형식으로 변경하고 변경분을 계산
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"channel1", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb
cd ..
peer channel update -f channel-artifacts/config_update_in_envelope.pb -c channel1 -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
채널 헤더와 타입의 정보(K:V)를 앞에 추가(JSON 형태)하고, 이를 pb형식으로 다시 변환
Set anchor peer
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
cd channel-artifacts
configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
jq '.data.data[0].payload.data.config' config_block.json > config.json
cp config.json config_copy.json
jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port":
9051}]},"version": "0"}}' config_copy.json > modified_config.json
configtxlator proto_encode --input config.json --type common.Config --output config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output config_update.pb
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"channel1", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb
cd ..
peer channel update -f channel-artifacts/config_update_in_envelope.pb -c channel1 -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
peer channel getinfo -c channel1
Org2의 Peer에도 동일 적용하고 블록 수가 최종적으로 3으로 증가되었는지 확인
Deploy a chaincode to the new channel
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go -c channel1
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" -C channel1 -n basic --
peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --
peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c
'{"function":"InitLedger","Args":[]}'
peer chaincode query -C channel1 -n basic -c '{"Args":["getAllAssets"]}'
채널 정상여부 확인을 위한 체인코드 배포 및 테스트
아홉 번째 튜토리얼
Adding an Org to a Channel
Bring Org3 into the Channel with the Script
• 채널 생성후 Org3 조직을 Join
• ./network.sh down
• ./network.sh up createChannel -c channel1
• cd addOrg3
• ./addOrg3.sh up -c channel1 인증서 등 생성 이후, 채널에 조인함
Bring Org3 into the Channel Manually
• ./network.sh down
• ./network.sh up createChannel -c channel1
• cd addOrg3
• 기 구성된 채널(channel1)에 업데이트를 하기 때문에, CA를 사용하지 않고
cryptogen 도구를 사용한다.
• ../../bin/cryptogen generate --config=org3-crypto.yaml --
output="../organizations"
앞 장에서 했던 내용을
하나씩 수행하면서, 원리를 알아보자.
기존 조직 Org1, Org2에
Org3 조직 추가됨
• configtxgen 도구를 사용하여 Org3 조직를 출력
• export FABRIC_CFG_PATH=$PWD
• ../../bin/configtxgen -printOrg
Org3MSP > ../organizations/peerOrganizations/org3.example.com/org3.json
Bring Org3 into the Channel Manually
configtxgen로 하여금 현재 디렉토리의 configtx.yaml을 참조하게 함
위 수행의 결과로 org3.json 파일이 생성되고, 이 파일에는 조직의 정책 정의 내용과
CA 루트 인증서, TLS 루트 인증서가 포함된다. 이후, 이 파일을 채널에 추가하게 된다.
Bring up Org3 components
• From the addOrg3 directory,
• docker-compose -f compose/compose-org3.yaml -f compose/docker/docker-
compose-org3.yaml up -d
볼륨 마운트 대상 디렉토리 표기시 뒤에 슬래쉬 기호를 추가해야 아래와 같은 오류가 발생하지 않는다.
Fetch the Configuration
• 현재 채널의 설정 블록을 불러온다.
• From the test-network directory
• Org3가 아직 채널 멤버가 아니기 때문에, Org1의 Admin으로 환경변수를 설정하여
작업을 진행한다.
• 현재 채널(channel1)의 구성 정보를 불러와서, config_block.pb 파일로 저장
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls
--cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
Convert the Configuration to JSON and Trim It Down
• cd channel-artifacts
• 앞장에서 생성한 config_block.pb파일을 json으로 형식을 변경하고 불필요한 정보를
제외하여 config.json파일로 출력
• configtxlator proto_decode --input config_block.pb --type common.Block --
output config_block.json
• jq ".data.data[0].payload.data.config" config_block.json > config.json
Add the Org3 Crypto Material
• 이전에 생성한 org3.json(organization/peer~/org3.peer~) 파일 내용을 앞장에서 생성한 json파일에
추가하여 modified_config.json으로 생성
• jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}'
config.json ../organizations/peerOrganizations/org3.example.com/org3.json > modified_config.json
• 작업 순서
① Org1/2 만 있는 기존의 config.json을 protobuf형식으로 변경
② Org3까지 포함하고 있는 modified_config.json을 protobuf형식으로 변경
③ 상기 2개의 pb 파일을 configtxlator 도구를 이용하여 변경분을 계산(org3_update.pb)
④ 상기 변경분을 json 형식으로 변환(org3_update.json)
⑤ org3 정보 + header 추가한 json 파일을 생성(org3_update_in_envelope.json)
(☞ 앞장에서 config.json을 생성할때 채널 설정을 읽어서 헤더를 제거했었음)
⑥ configtxlator 도구를 이용 상기 json파일을 pb로 포맷 변경(org3_update_in_envelope.pb)
헤더
org3_update.json
org3_update_in_envelope.json
jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ../organizations/peerOrganizations/org3.example.com/org3.json > modified_config.json
configtxlator proto_encode --input config.json --type common.Config --output config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output org3_update.pb
configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate --output org3_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"'channel1'", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json
configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb
Sign and Submit the Config Update
• 수정 정책(mod_policy)는 과반 이상 동의해야 하기 때문에, Org1/Org2 두 조직의
signature가 필요한 상황
• Org1으로 사인하고, 환경설정 변수를 Org2로 변경하고 peer channel update로
렛져에 반영(Org2는 peer channel update시 자동으로 사인이 추가되기 때문에
별도로 사인할 필요 없음)
• From the test-network directory
• peer channel signconfigtx -f channel-artifacts/org3_update_in_envelope.pb
• peer channel update -f channel-artifacts/org3_update_in_envelope.pb -c
channel1 -o localhost:7050 --ordererTLSHostnameOverride
orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.e
xample.com/msp/tlscacerts/tlsca.example.com-cert.pem"
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
Join Org3 to the Channel
• 환경변수를 Org3 Admin으로 설정하고, 제네시스 블록을 요청한다.
(신규 조직이 채널에 참가하는 방법: 제네시스 블록 또는 스냅샷으로 생성)
• 제네시스 블록을 기반으로 peer channel join 명령으로 채널에 참가한다.
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:11051
peer channel fetch 0 channel-artifacts/channel1.block -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
peer channel join -b channel-artifacts/channel1.block
Configuring Leader Election
Install, define, and invoke chaincode
새 터미널을 열어서 체인코드를 배포(아래 명령을 통해 Org1과 Org2에 체인코드가 배포됨)
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go -c channel1
이제는 Org3로 환경설정하고, 체인코드(동일) 배포하여 사용한다.
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:11051
peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_1
peer lifecycle chaincode install basic.tar.gz
peer lifecycle chaincode queryinstalled
export CC_PACKAGE_ID=basic_1:5443b5b557efd3faece8723883d28d6f7026c0bf12245de109b89c5c4fe64887
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --channelID channel1 --name basic --version 1.0 --
package-id $CC_PACKAGE_ID --sequence 1
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --channelID channel1 --name basic --version 1.0 --
package-id $CC_PACKAGE_ID --sequence 1
peer lifecycle chaincode querycommitted --channelID channel1 --name basic
Org3 can use the basic chaincode after it approves the chaincode definition that was committed to the channel
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile
"${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C channel1 -n basic --peerAddresses localhost:9051
--tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" --peerAddresses localhost:11051 --tlsRootCertFiles
"${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt" -c '{"function":"InitLedger","Args":[]}'
peer chaincode query -C channel1 -n basic -c '{"Args":["GetAllAssets"]}'
기존 채널 구성원이 이미 체인코드 정의를 채널에 커밋한 경우 새 조직은 체인코드 정의를 승인하여 체인코드 사용을 시작할 수 있습니다.
과반 이상 승인 (2/3)
Writing Your First
Chaincode
https://hyperledger-
fabric.readthedocs.io/en/latest/chaincode4ade.html
Hyperledger
Deployment Practice
docker-swarm
host #2
192.168.56.41
koposlave1
Deployment Environment
host #1
192.168.56.40
kopomaster
host #3
192.168.56.42
koposlave2
host #4
192.168.56.43
koposlave3
Orderer1 Orderer2 Orderer3 Orderer4
Orderer5
Peer0
Peer1
Peer0
Peer1
Org1 Org2
Gateway
CA_Orderer
CA_Org1
CA_Org2
setting a network address
setting a network address
vi /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
ethernets:
enp0s3:
dhcp4: true
enp0s8:
addresses:
- 192.168.56.40/24
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
version: 2
192.168.56.40 → kopomaster
192.168.56.41 → koposlave1
192.168.56.42 → koposlave2
192.168.56.43 → koposlave3
netplan apply
docker installation
• apt-get -y install docker-compose
• docker --version
• docker-compose --version
• systemctl start docker
• systemctl enable docker
Go 설치
• rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.2.linux-amd64.tar.gz
• vi /etc/profile
• 상기 파일에 환경변수 추가 export PATH=$PATH:/usr/local/go/bin
• source /etc/profile
• go version
etc.
• apt install tree
• apt install jq
• apt install net-tools
• apt-get install openjdk-11-jdk
vi ~/.bashrc
상기 파일에 환경변수 추가
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
export PATH=$PATH:$JAVA_HOME/bin
• source ~/.bashrc
• java -version
hostnamectl set-hostname kopomaster
192.168.56.40 → kopomaster
192.168.56.41 → koposlave1
192.168.56.42 → koposlave2
192.168.56.43 → koposlave3
[참조] 기본 아이디어 (1/2)
https://kctheservant.medium.com/multi-host-setup-with-raft-based-ordering-service-29730788b171
https://kctheservant.medium.com/multi-host-deployment-for-first-network-hyperledger-fabric-v2-273b794ff3d
docker swarm을 이용한 멀티 호스트 예제
- 인증서는 cryptogen을 이용해 생성
- v2.2 기준
다음과 같이 재구성 해보자.
- Hyperledger fabric CA 서버로 인증서 생성
- 최신 예제와 환경으로 프로젝트 재구성(v2.5)
v1.4기준 멀티호스트 예제
v2.2 기준 멀티호스트 예제
[참조] 기본 아이디어 (2/2)
1. 앞 장의 2개의 가이드를 수행 테스트
https://github.com/wonyongHwang/4host-swarm
https://kctheservant.medium.com/a-companion-guide-to-fabric-ca-
operation-guide-c81591ef0321
https://kctheservant.medium.com/add-a-peer-to-an-organization-in-
test-network-hyperledger-fabric-v2-2-4a08cb901c98
CA 서버 가이드 참조
peer 추가 가이드 참조
docker swarm
at host 1 :
docker swarm init --advertise-addr 192.168.56.40
# docker swarm join
at host2~4:
docker swam join as below:
ex> docker swarm join --token <토큰> 192.168.56.40:2377
at host 1:
docker network create --attachable --driver overlay kopo-network
docker node promote koposlave2
docker node promote koposlave3
docker node promote koposlave4
준비작업 - 인증서 발급
1번 서버 :
cd fabric-samples/kopo-network
./network.sh up -ca
인증서(organizations) 디렉토리 복사 및 2~4번 서버 폴더에 복사(kopo-network/organizations)
./network down
인증서(organizations) 디렉토리 복사 및 1번 서버 폴더에 복사(kopo-network/organizations)
기동
1,4번 서버 :
cd fabric-samples/kopo-network
./kopo-network.sh up
2,3번 서버 :
cd fabric-samples/kopo-network
./kopo-network.sh up -s couchdb
[참고] 1번 서버에서 차후에 별도로 CA서버 기동할 시
docker-compose -f compose/compose-ca.yaml -f compose/docker/docker-compose-ca.yaml up -d
채널 생성
1번 서버 :
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/configtx
configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/channel1.block -channelID channel1
# 여기서 생성된 channel-artifacts 디렉토리를 2~4번 서버의 kopo-network/ 에 복사한다.
(다른 오더러들도 채널에 조인하기 위함)
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-
cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert
"$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
2번 서버 :
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/configtx
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/msp/tlscacerts/tlsca.example.com-
cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.key
osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:8053 --ca-file "$ORDERER_CA" --client-cert
"$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
3번 서버 :
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/configtx
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer3.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.key
osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:9053 --ca-file "$ORDERER_CA" --client-cert
"$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
4번 서버 :
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/configtx
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer4.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.key
osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:10053 --ca-file "$ORDERER_CA" --client-cert
"$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer5.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.key
osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:11053 --ca-file "$ORDERER_CA" --client-cert
"$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
채널 생성
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf
HyperLedger Fabric V2.5.pdf

More Related Content

What's hot

What's hot (20)

Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)
 
FD.io VPP事始め
FD.io VPP事始めFD.io VPP事始め
FD.io VPP事始め
 
FIWARE Wednesday Webinars - FIWARE Overview
FIWARE Wednesday Webinars - FIWARE OverviewFIWARE Wednesday Webinars - FIWARE Overview
FIWARE Wednesday Webinars - FIWARE Overview
 
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
 
[OpenInfra Days Korea 2018] (Track 4) - Grafana를 이용한 OpenStack 클라우드 성능 모니터링
[OpenInfra Days Korea 2018] (Track 4) - Grafana를 이용한 OpenStack 클라우드 성능 모니터링[OpenInfra Days Korea 2018] (Track 4) - Grafana를 이용한 OpenStack 클라우드 성능 모니터링
[OpenInfra Days Korea 2018] (Track 4) - Grafana를 이용한 OpenStack 클라우드 성능 모니터링
 
Openstack Magnum: Container-as-a-Service
Openstack Magnum: Container-as-a-ServiceOpenstack Magnum: Container-as-a-Service
Openstack Magnum: Container-as-a-Service
 
BPF & Cilium - Turning Linux into a Microservices-aware Operating System
BPF  & Cilium - Turning Linux into a Microservices-aware Operating SystemBPF  & Cilium - Turning Linux into a Microservices-aware Operating System
BPF & Cilium - Turning Linux into a Microservices-aware Operating System
 
Scale Kubernetes to support 50000 services
Scale Kubernetes to support 50000 servicesScale Kubernetes to support 50000 services
Scale Kubernetes to support 50000 services
 
Bare Metal Cluster with Kubernetes, Istio and Metallb | Nguyen Phuong An, Ngu...
Bare Metal Cluster with Kubernetes, Istio and Metallb | Nguyen Phuong An, Ngu...Bare Metal Cluster with Kubernetes, Istio and Metallb | Nguyen Phuong An, Ngu...
Bare Metal Cluster with Kubernetes, Istio and Metallb | Nguyen Phuong An, Ngu...
 
Here Be Dragons: The Unexplored Land of Active Directory ACLs
Here Be Dragons: The Unexplored Land of Active Directory ACLsHere Be Dragons: The Unexplored Land of Active Directory ACLs
Here Be Dragons: The Unexplored Land of Active Directory ACLs
 
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
 
Kubernetes From Scratch .pdf
Kubernetes From Scratch .pdfKubernetes From Scratch .pdf
Kubernetes From Scratch .pdf
 
클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar
클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar
클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar
 
Docker Container Security
Docker Container SecurityDocker Container Security
Docker Container Security
 
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
[MeetUp][1st] 오리뎅이의_쿠버네티스_네트워킹
 
Deep Dive into Building a Secure & Multi-tenant SaaS Solution with NATS
Deep Dive into Building a Secure & Multi-tenant SaaS Solution with NATSDeep Dive into Building a Secure & Multi-tenant SaaS Solution with NATS
Deep Dive into Building a Secure & Multi-tenant SaaS Solution with NATS
 
Kubernetes Introduction
Kubernetes IntroductionKubernetes Introduction
Kubernetes Introduction
 
Common issues with Apache Kafka® Producer
Common issues with Apache Kafka® ProducerCommon issues with Apache Kafka® Producer
Common issues with Apache Kafka® Producer
 
Introduction to eBPF and XDP
Introduction to eBPF and XDPIntroduction to eBPF and XDP
Introduction to eBPF and XDP
 
Kubernetes security
Kubernetes securityKubernetes security
Kubernetes security
 

Similar to HyperLedger Fabric V2.5.pdf

WSO2 Dep Sync for Artifact Synchronization of Cluster Nodes
WSO2 Dep Sync for Artifact Synchronization of Cluster NodesWSO2 Dep Sync for Artifact Synchronization of Cluster Nodes
WSO2 Dep Sync for Artifact Synchronization of Cluster Nodes
WSO2
 
[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...
[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...
[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...
Kasun Gajasinghe
 

Similar to HyperLedger Fabric V2.5.pdf (20)

Dockerizing the Hard Services: Neutron and Nova
Dockerizing the Hard Services: Neutron and NovaDockerizing the Hard Services: Neutron and Nova
Dockerizing the Hard Services: Neutron and Nova
 
OTRS
OTRSOTRS
OTRS
 
Container orchestration from theory to practice
Container orchestration from theory to practiceContainer orchestration from theory to practice
Container orchestration from theory to practice
 
WSO2 Dep Sync for Artifact Synchronization of Cluster Nodes
WSO2 Dep Sync for Artifact Synchronization of Cluster NodesWSO2 Dep Sync for Artifact Synchronization of Cluster Nodes
WSO2 Dep Sync for Artifact Synchronization of Cluster Nodes
 
[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...
[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...
[WSO2] Deployment Synchronizer for Deployment Artifact Synchronization Betwee...
 
What's new in Docker - InfraKit - Docker Meetup Berlin 2016
What's new in Docker - InfraKit - Docker Meetup Berlin 2016What's new in Docker - InfraKit - Docker Meetup Berlin 2016
What's new in Docker - InfraKit - Docker Meetup Berlin 2016
 
Boris Stoyanov - Troubleshooting the Virtual Router - Run and Get Diagnostics
Boris Stoyanov - Troubleshooting the Virtual Router - Run and Get DiagnosticsBoris Stoyanov - Troubleshooting the Virtual Router - Run and Get Diagnostics
Boris Stoyanov - Troubleshooting the Virtual Router - Run and Get Diagnostics
 
Demystifying puppet
Demystifying puppetDemystifying puppet
Demystifying puppet
 
Collabnix Online Webinar - Demystifying Docker & Kubernetes Networking by Bal...
Collabnix Online Webinar - Demystifying Docker & Kubernetes Networking by Bal...Collabnix Online Webinar - Demystifying Docker & Kubernetes Networking by Bal...
Collabnix Online Webinar - Demystifying Docker & Kubernetes Networking by Bal...
 
Continuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierContinuous Delivery: The Next Frontier
Continuous Delivery: The Next Frontier
 
Managing Large-scale Networks with Trigger
Managing Large-scale Networks with TriggerManaging Large-scale Networks with Trigger
Managing Large-scale Networks with Trigger
 
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
 
containerD
containerDcontainerD
containerD
 
Demystfying container-networking
Demystfying container-networkingDemystfying container-networking
Demystfying container-networking
 
Docker 1.11 Presentation
Docker 1.11 PresentationDocker 1.11 Presentation
Docker 1.11 Presentation
 
moscmy2016: Extending Docker
moscmy2016: Extending Dockermoscmy2016: Extending Docker
moscmy2016: Extending Docker
 
Manchester MuleSoft Meetup #6 - Runtime Fabric with Mulesoft
Manchester MuleSoft Meetup #6 - Runtime Fabric with Mulesoft Manchester MuleSoft Meetup #6 - Runtime Fabric with Mulesoft
Manchester MuleSoft Meetup #6 - Runtime Fabric with Mulesoft
 
Introduction to istio
Introduction to istioIntroduction to istio
Introduction to istio
 
CICD Azure DevOps
CICD Azure DevOpsCICD Azure DevOps
CICD Azure DevOps
 
Managing multicast/igmp stream on Docker
Managing multicast/igmp stream on DockerManaging multicast/igmp stream on Docker
Managing multicast/igmp stream on Docker
 

More from wonyong hwang

More from wonyong hwang (20)

Hyperledger Explorer.pptx
Hyperledger Explorer.pptxHyperledger Explorer.pptx
Hyperledger Explorer.pptx
 
하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회
 
토큰 증권 개요.pptx
토큰 증권 개요.pptx토큰 증권 개요.pptx
토큰 증권 개요.pptx
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptx
 
Deploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptxDeploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptx
 
k8s practice 2023.pptx
k8s practice 2023.pptxk8s practice 2023.pptx
k8s practice 2023.pptx
 
Ngrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptxNgrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptx
 
Nginx Https 적용하기.pptx
Nginx Https 적용하기.pptxNginx Https 적용하기.pptx
Nginx Https 적용하기.pptx
 
Kafka JDBC Connect Guide(Postgres Sink).pptx
Kafka JDBC Connect Guide(Postgres Sink).pptxKafka JDBC Connect Guide(Postgres Sink).pptx
Kafka JDBC Connect Guide(Postgres Sink).pptx
 
Nginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptxNginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptx
 
Kafka Rest.pptx
Kafka Rest.pptxKafka Rest.pptx
Kafka Rest.pptx
 
Kafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and GrafanaKafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and Grafana
 
주가 정보 다루기.pdf
주가 정보 다루기.pdf주가 정보 다루기.pdf
주가 정보 다루기.pdf
 
KAFKA 3.1.0.pdf
KAFKA 3.1.0.pdfKAFKA 3.1.0.pdf
KAFKA 3.1.0.pdf
 
App development with quasar (pdf)
App development with quasar (pdf)App development with quasar (pdf)
App development with quasar (pdf)
 
kubernetes practice
kubernetes practicekubernetes practice
kubernetes practice
 
Docker practice
Docker practiceDocker practice
Docker practice
 
Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)
 
Hyperledger composer
Hyperledger composerHyperledger composer
Hyperledger composer
 
Kafka slideshare
Kafka   slideshareKafka   slideshare
Kafka slideshare
 

Recently uploaded

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 

Recently uploaded (20)

%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 

HyperLedger Fabric V2.5.pdf

  • 2. Prerequisites on this practice • Install Ubuntu 22.04 LTS • For this exercise only, all libraries will be installed under a root account. ----------------------------------------------------------------------------------------------------- • apt-get -y install docker-compose docker --version docker-compose –version • systemctl start docker • systemctl enable docker https://hyperledger-fabric.readthedocs.io/en/release-2.5/prereqs.html
  • 3. ㅅ 설치 • curl -sSLO https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install- fabric.sh && chmod +x install-fabric.sh • ./install-fabric.sh https://hyperledger-fabric.readthedocs.io/en/release-2.5/install.html
  • 4. Fabric Contract APIs and Application APIs • Fabric Contract APIs Smart Contract(ChainCode) APIs are available for Go, Node.js, Java • Fabric Application APIs Hyperledger Fabric offers a Fabric Gateway client API for Go, Node.js, Java https://hyperledger.github.io/fabric-gateway/ https://hyperledger-fabric.readthedocs.io/en/release-2.5/sdk_chaincode.html
  • 6. 첫 번째 튜토리얼 Using the Fabric test network 목표 - 전반적인 아키텍처의 이해(DOCKER) - 체인코드 배포과정 체험
  • 7. Using the Fabric test network • It includes two peer organizations and an ordering organization. • For simplicity, a single node Raft ordering service is configured. • To reduce complexity, a TLS Certificate Authority (CA) is not deployed. All certificates are issued by the root CAs. • The sample network deploys a Fabric network with Docker Compose. Because the nodes are isolated within a Docker Compose network, the test network is not configured to connect to other running Fabric nodes. https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
  • 8. Using the Fabric test network • at fabric-samples/test-network • ./network.sh up • docker ps –a 2 peer, 1 orderer will be listed
  • 9. - Peer • Peers store the blockchain ledger and validate transactions before they are committed to the ledger. • Peers run the smart contracts. • Every peer in the network needs to belong to an organization - peer0.org1.example.com - peer0.org2.example.com https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html Using the Fabric test network
  • 10. - Orderer • After ordering nodes receive endorsed transactions from clients, they come to consensus on the order of transactions and then add them to blocks. The blocks are then distributed to peer nodes, which add the blocks to the blockchain ledger. - orderer.example.com • It would use the Raft consensus algorithm to come to agreement on the order of transactions across the network https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html Using the Fabric test network
  • 11. - creating a channel • Channels are a private layer of communication between specific network members. • ./network.sh createChannel Using the Fabric test network channel ledger https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
  • 12. Generating channel genesis block 'mychannel.block' + configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/mychannel.block -channelID mychannel Creating channel mychannel Using organization 1 + osnadmin channel join --channelID mychannel --config-block ./channel-artifacts/mychannel.block -o localhost:7053 --ca-file /root/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --client-cert /root/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt --client-key /root/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key + res=0 Status: 201 { "name": "mychannel", "url": "/participation/v1/channels/mychannel", "consensusRelation": "consenter", "status": "active", "height": 1 } Channel 'mychannel' created Joining org1 peer to the channel... Using organization 1 + peer channel join -b ./channel-artifacts/mychannel.block + res=0 2023-03-19 10:55:44.556 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized 2023-03-19 10:55:45.007 UTC 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel Joining org2 peer to the channel... Using organization 2 + peer channel join -b ./channel-artifacts/mychannel.block + res=0 2023-03-19 10:55:48.116 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized 2023-03-19 10:55:48.188 UTC 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel - creating a channel Using the Fabric test network
  • 13. Setting anchor peer for org1... Using organization 1 Fetching channel config for channel mychannel Using organization 1 Fetching the most recent configuration block for the channel Generating anchor peer update transaction for Org1 on channel mychannel Anchor peer set for org 'Org1MSP' on channel 'mychannel' Setting anchor peer for org2... Using organization 2 Fetching channel config for channel mychannel Using organization 2 Fetching the most recent configuration block for the channel Generating anchor peer update transaction for Org2 on channel mychannel Anchor peer set for org 'Org2MSP' on channel 'mychannel' Channel 'mychannel' joined - Creating a channel Using the Fabric test network
  • 14. - Starting a chaincode on the channel • apt install jq • apt-get install openjdk-11-jdk • ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java -ccl java export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java)))) export PATH=$PATH:$JAVA_HOME/bin vi ~/.bashrc source ~/.bashrc Using the Fabric test network https://hyperledger-fabric.readthedocs.io/en/release-2.5/test_network.html
  • 15. - Interacting with the network Using the Fabric test network vi ~/.bashrc source ~/.bashrc export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051
  • 16. - Interacting with the network Using the Fabric test network peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 -- tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"InitLedger","Args":[]}' Because the endorsement policy for the asset-transfer (basic) chaincode requires the transaction to be signed by Org1 and Org2, the chaincode invoke command needs to target both peer0.org1.example.com and peer0.org2.example.com using the --peerAddresses flag. Because TLS is enabled for the network, the command also needs to reference the TLS certificate for each peer using the --tlsRootCertFiles flag.
  • 17. - Interacting with the network Using the Fabric test network peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 -- tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"TransferAsset","Args":["asset6","Christopher"]}'
  • 18. - Interacting with the network Using the Fabric test network Ledger check by Org2, it should be same as Org1 export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'
  • 19. Fabric CA를 사용하여 구동 • ./network.sh up –ca • 노드와 사용자ID를 등록 • MSP 폴더를 생성 https://hyperledger-fabric.readthedocs.io/en/release-2.5/membership/membership.html https://hyperledger-fabric-ca.readthedocs.io/en/latest/operations_guide.html
  • 20. org1의 CA org1.exampl.com의 CA org1.exampl.com의 MSP = ca.org1 이 발급한 admin 인증서 Fabric CA를 사용하여 구동 cryptogen 으로 생성 Fabric CA로 생성
  • 21. org1.example.com의 CA peer0.org1.exampl.com의 msp peer0 peer1 cryptogen 으로 생성 Fabric CA로 생성 Fabric CA를 사용하여 구동
  • 24. 두 번째 튜토리얼 Deploying a smart contract to a channel 이번 튜토리얼은 첫 번째 튜토리얼에서 아래의 명령을 통해 체인코드를 패키징~배포~커밋한 내용을 하나씩 단계별로 체인코드를 배포하는 튜토리얼 ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
  • 25. 준비 • cd fabric-samples/test-network • ./network.sh down • ./network.sh up createChannel https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 26. Docker 모니터링 • 별도 터미널 쉘에서 실행 • cd fabric-samples/test-network • ./monitordocker.sh fabric_test https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 27. Install and define a chaincode https://hyperledger-fabric.readthedocs.io/en/release-2.5/chaincode_lifecycle.html
  • 28. Package the smart contract • 패키지 명령 형식 peer lifecycle chaincode package ${CC_NAME}.tar.gz --path ${CC_SRC_PATH} --lang ${CC_RUNTIME_LANGUAGE} --label ${CC_NAME}_${CC_VERSION} >&log.txt • 자바 체인코드 패키지 생성 peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-java/ --lang java --label basic_1.0 tar는 해당 자바 디렉토리를 target 디렉토리만 빼고 단순 압축한 형태임 https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 29. Install the chaincode package • Org1과 Org2 모두에 설치 export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 root@koposvr:~/fabric-samples/test-network# peer lifecycle chaincode install basic.tar.gz 2023-03-21 07:02:07.236 UTC 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"nJbasic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e022tbasic_1.0" > 2023-03-21 07:02:07.270 UTC 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e root@koposvr:~/fabric-samples/test-network# export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 root@koposvr:~/fabric-samples/test-network# peer lifecycle chaincode install basic.tar.gz 2023-03-21 07:06:08.573 UTC 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"nJbasic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e022tbasic_1.0" > 2023-03-21 07:06:08.573 UTC 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e Org1 Org2 두 개의 조직이 같은 식별자를 리턴함 https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 30. Approve a chaincode definition peer lifecycle chaincode queryinstalled export CC_PACKAGE_ID=basic_1.0:7ac9411f0ac3d33a79007b3d3307ee7b246e2ea95bd29467a0331e5997378b6e echo $CC_PACKAGE_ID peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel -- name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_ADDRESS=localhost:7051 peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel -- name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" Org1과 Org2 모두에 승인 요청 https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 31. Committing the chaincode definition to the channel (1/2) • peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls -- cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam ple.com-cert.pem" --output json https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 32. Committing the chaincode definition to the channel (2/2) root@koposvr:~/fabric-samples/test-network# peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -- channelID mychannel --name basic --version 1.0 --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -- peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 -- tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt” 2023-03-21 07:27:06.356 UTC 0001 INFO [chaincodeCmd] ClientWait -> txid [e5f9ad97cbb2821fbb0b906543469fc8f272098b5d436183cbb7c86b7b69959e] committed with status (VALID) at localhost:9051 2023-03-21 07:27:06.360 UTC 0002 INFO [chaincodeCmd] ClientWait -> txid [e5f9ad97cbb2821fbb0b906543469fc8f272098b5d436183cbb7c86b7b69959e] committed with status (VALID) at localhost:7051 peer lifecycle chaincode querycommitted --channelID mychannel --name basic --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" Committed chaincode definition for chaincode 'basic' on channel 'mychannel': Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true] https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 33. Invoking the chaincode • peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example. com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"InitLedger","Args":[]}' • 2023-03-21 07:39:33.399 UTC 0001 INFO [chaincodeCmd] chaincodeInvokeOrQuery -> Chaincode invoke successful. result: status:200 • peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' • [{"appraisedValue":300,"assetID":"asset1","color":"blue","owner":"Tomoko","size":5},{"appraisedValue":400,"assetID":"asset2","color": "red","owner":"Brad","size":5},{"appraisedValue":500,"assetID":"asset3","color":"green","owner":"Jin Soo","size":10},{"appraisedValue":600,"assetID":"asset4","color":"yellow","owner":"Max","size":10},{"appraisedValue":700,"assetID":"a sset5","color":"black","owner":"Adrian","size":15},{"appraisedValue":700,"assetID":"asset6","color":"white","owner":"Michel","size":15}] https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 34. Upgrading a smart contract (1/7) • 준비 apt intall npm • cd ../asset-transfer-basic/chaincode-javascript • npm install • cd ../../test-network https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 35. Upgrading a smart contract (2/7) • 패키징 • export PATH=${PWD}/../bin:$PATH • export FABRIC_CFG_PATH=$PWD/../config/ • export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp • peer lifecycle chaincode package basic_2.tar.gz --path ../asset-transfer-basic/chaincode-javascript/ --lang node --label basic_2.0 • 패키지 설치 (Org1) • export CORE_PEER_TLS_ENABLED=true • export CORE_PEER_LOCALMSPID="Org1MSP" • export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt • export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp • export CORE_PEER_ADDRESS=localhost:7051 • peer lifecycle chaincode install basic_2.tar.gz https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 36. Upgrading a smart contract (3/7) • 패키지 설치 확인 (Org1) • peer lifecycle chaincode queryinstalled • 체인코드 승인 요청 (Org1) • export NEW_CC_PACKAGE_ID=basic_2.0:1d559f9fb3dd879601ee17047658c7e0c84eab732dca7c841102f20e42a9e7d4 • peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" • Org2 에도 동일하게 체인코드 설치 • export CORE_PEER_LOCALMSPID="Org2MSP" • export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt • export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp • export CORE_PEER_ADDRESS=localhost:9051 https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 37. Upgrading a smart contract (4/7) • 체인코드 설치 (Org2) • peer lifecycle chaincode install basic_2.tar.gz • 체인코드 승인 요청 (Org2) • peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -- channelID mychannel --name basic --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam ple.com-cert.pem“ • 커밋 가능여부 확인 (Org2) • peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 2.0 --sequence 2 --tls -- cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam ple.com-cert.pem" --output json https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 38. Upgrading a smart contract (5/7) • 체인코드 커밋 (Org1, Org2) • peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 2.0 --sequence 2 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.exam ple.com-cert.pem" --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" -- peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" https://hyperledger-fabric.readthedocs.io/en/release-2.5/deploy_chaincode.html
  • 39. Upgrading a smart contract (6/7)
  • 40. Upgrading a smart contract (7/7)
  • 41. 세 번째 튜토리얼 Running a Fabric Application Fabric 어플리케이션와 블록체인 네트워크간 상호작용 데모 스마트 컨트랙트의 함수 호출을 위해 Fabric Gateway client API를 사용
  • 42. 시나리오 Java Application 에서 사전 배포한 스마트 컨트랙트를 Fabric Gateway API를 사용하여 호출하는 시나리오
  • 43. 사전 준비 • cd fabric-samples/test-network • ./network.sh down • ./network.sh up createChannel -c mychannel -ca
  • 44. 스마트 컨트랙트 배포(자바) • ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
  • 45. 스마트 컨트랙트를 호출할 어플리케이션 구동(자바) • 새 터미널 열고, $FABRIC_HOME으로 이동하여... • cd asset-transfer-basic/application-gateway-java • ./gradlew build • ./gradlew run 예> VB에서 25GB의 공간을 VDI로 할당하였는데, 우부투에서 df –h 로 확인한 공간이 12GB로 절반이하로 할당된 상황 $ lvm lvm> lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv lvm> exit $ resize2fs /dev/ubuntu-vg/ubuntu-lv <Tip> 우분투에서 VirtualBox에서 할당한 공간보다 하드디스크 공간이 부족하게 잡히는 경우
  • 46. Gateway에 대한 gRPC 연결을 설정
  • 48. 호출할 스마트 계약에 액세스 gRPC 연결 및 Gateway 연결 준비 설정이 끝나고 호출된다.
  • 50. 임의 데이터로 블록체인 원장을 채우기
  • 51. 트랜잭션 기능을 호출하여 조회 • The application uses evaluateTransaction() to query the ledger by performing a read-only transaction invocatio
  • 53. 트랜잭션 기능을 호출하여 갱신 • This time the transaction is invoked using submitAsync(), which returns after successfully submitting the endorsed transaction to the ordering service instead of waiting until the transaction is committed to the ledger.
  • 56. [참고] 전체 수행 로그 oot@koposvr:~/fabric-samples/asset-transfer-basic/application-gateway-java# ./gradlew run > Task :run --> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger *** Transaction committed successfully --> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger *** Result: [ { "appraisedValue": 300, "assetID": "asset1", "color": "blue", "owner": "Tomoko", "size": 5 }, { "appraisedValue": 400, "assetID": "asset2", "color": "red", "owner": "Brad", "size": 5 }, { "appraisedValue": 500, "assetID": "asset3", "color": "green", "owner": "Jin Soo", "size": 10 }, { "appraisedValue": 600, "assetID": "asset4", "color": "yellow", "owner": "Max", "size": 10 }, { "appraisedValue": 700, "assetID": "asset5", "color": "black", "owner": "Adrian", "size": 15 }, { "appraisedValue": 700, "assetID": "asset6", "color": "white", "owner": "Michel", "size": 15 } ] --> Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments *** Transaction committed successfully --> Async Submit Transaction: TransferAsset, updates existing asset owner *** Successfully submitted transaction to transfer ownership from Tom to Saptha *** Waiting for transaction commit *** Transaction committed successfully --> Evaluate Transaction: ReadAsset, function returns asset attributes *** Result:{ "owner": "Saptha", "color": "yellow", "size": 5, "appraisedValue": 1300, "assetID": "asset1679492916126" } --> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error *** Successfully caught the error: org.hyperledger.fabric.client.EndorseException: io.grpc.StatusRuntimeException: ABORTED: failed to endorse transaction, see attached details for more info at org.hyperledger.fabric.client.GatewayClient.endorse(GatewayClient.java:73) at org.hyperledger.fabric.client.ProposalImpl.endorse(ProposalImpl.java:74) at org.hyperledger.fabric.client.Proposal.endorse(Proposal.java:65) at org.hyperledger.fabric.client.ContractImpl.submitTransaction(ContractImpl.java:47) at App.updateNonExistentAsset(App.java:225) at App.run(App.java:132) at App.main(App.java:71) Caused by: io.grpc.StatusRuntimeException: ABORTED: failed to endorse transaction, see attached details for more info at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:271) at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:252) at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:165) at org.hyperledger.fabric.protos.gateway.GatewayGrpc$GatewayBlockingStub.endorse(GatewayGrpc.java:472) at org.hyperledger.fabric.client.GatewayClient.endorse(GatewayClient.java:71) ... 6 more Transaction ID: 0c4d10e9dd4b2573f9a06f9a8ac594f1c2098d3e65f3561dc05a8494761cf2ea Error Details: - address: peer0.org1.example.com:7051, mspId: Org1MSP, message: chaincode response 500, Asset asset70 does not exist BUILD SUCCESSFUL in 20s 2 actionable tasks: 1 executed, 1 up-to-date root@koposvr:~/fabric-samples/asset-transfer-basic/application-gateway-java#
  • 57. 네 번째 튜토리얼 Running External Chaincode Builders - chaincode as a service
  • 58. 개요 • 기존 the peer to orchestrate the complete lifecycle of the chaincode 체인코드 빌드와 시작을 어떻게 할지, 체인코드 언어도 Peer에 전달해야 함 쿠버네티스 등 가상화된 환경이나 체인코드 재빌드를 위해 외부망 접속이 필요한 경우 등 복잡한 이슈가 있을 수 있음 • 따라서, Separation of Concern 관점에서 이를 서비스化 하자. • 무엇으로? 도커로! • 이미 ccaasbuiler라는 도커 이미지가 준비되어 있음 https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
  • 59. 준비 • cd test-network • ./network.sh up createChannel • 새로운 터미널에서 도커 모니터링을 위하여 ./test-network/monitordocker.sh https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
  • 60. 실행 • ./network.sh deployCCAAS -ccn basicj -ccp ../asset-transfer-basic/chaincode-java • 빌드 오류 발생시, 하단 슬라이드 노트 참고 • 순서 ① 체인코드 컨테이너를 빌드(Dockerfile) ② 체인코드 설치~커밋을 Peer에 실행 (이때, peer는 체인코드의 위치(host, port, tls인증서 정보를 획득하고 rpc로 peer <-> peer0org1_basicj_ccaas 또는 peer0org2_basicj_ccaas 와 통신하게 됨) ③ 도커 컨테이너 실행 https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
  • 61. 결과 확인 • 도커 프로세스 확인 → 두 개의 컨테이너를 확인 컨테이너 이름에 조직, 피어 및 체인코드 이름이 포함됨 ☞ docker 모니터링 로그는 하단 슬라이드 노트 참조 https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
  • 62. 테스트 • export CORE_PEER_TLS_ENABLED=true • export CORE_PEER_LOCALMSPID="Org1MSP" • export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/tl sca/tlsca.org1.example.com-cert.pem • export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users /Admin@org1.example.com/msp • export CORE_PEER_ADDRESS=localhost:7051 • export PATH=${PWD}/../bin:$PATH • export FABRIC_CFG_PATH=${PWD}/../config • peer chaincode query -C mychannel -n basicj -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}' | jq 쉘에서 peer로 요청한 내용이 by rpc로 체인코드 컨테이너(peer0org1_basicj_ccaas 또는 peer0org2_basicj_ccaas) 로 전달되어 그 결과를 정상 수신하는지 확인하기 위한 테스트 https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_basic.html
  • 63. 다섯 번째 튜토리얼 Using Private Data in Fabric
  • 64. 개요 • assetCollection • Org1MSPPrivateCollection • AgreeToTransfer • Org2MSPPrivateCollection • TransferAsset
  • 65. 시나리오 fabric_samples/asset-transfer-private-data/chaincode-java/collections_config.json ① Org1의 소유자가 데이터 생성 - (assetID, color, size, appraisedValue) = asset1, green, 20, 100 그런데 100에 해당하는 appraisedValue 속성은 비공개 데이터로 assetID, closer, size와 별도 저장됨 ② Org1, Org2 모두 assetID, color, size에 대해서는 조회 가능 ③ Org1의 구성원(소유자限)는 appraisedValue 조회 가능 ④ Org2의 구성원은 appraisedValue 조회 : Org1으로 조회시 접근 불가, Org2로 조회시 Null ⑤ Org2의 구성원은 (assetID, color, size) 조회 가능 ⑥ 이후, Org1의 소유자가 asset 을 이관하게 되면 기존 소유자는 appraisedValue조회가 안됨
  • 66. AssetTransfer.java ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰 계약 생성 및 조회 Asset Transfer Asset.java AssetPrivateDetails.java TransferAgreement.java Public State의 기초자료 클래스 Private State의 기초자료 클래스 Asset 구매이관 기초자료 클래스
  • 68. AssetTransfer.java Public State 조회 Private State 조회 ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
  • 69. AssetTransfer.java - ① CreateAsset Public State 저장 Private State 저장 스마트 컨트랙트 함수 호출 주체가 해당 조직의 MSP ID와 같은지 검사 ex> clientMSPID == peerMSPID 다음 장… ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
  • 70. AssetTransfer.java - ② AgreeToTransfer export ASSET_VALUE=$(echo -n "{"assetID":"asset1","appraisedValue":100}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n private -c '{"function":"AgreeToTransfer","Args":[]}' --transient "{"asset_value":"$ASSET_VALUE"}" Org2MSPPrivateCollection에 구매하려는 assetID와 가격을 저장 -> 뒤의 TransferAsset에서 이 저장된 값을 검증에 사용(p72) TransferAsset에서 aggKey로 조회하여 거래 종료후, 해당 키로 거래데이터 삭제 ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰 implicit private data collection에 저장된다.
  • 71. AssetTransfer.java – ③ ReadTransferAgreement ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
  • 72. AssetTransfer.java - ④ TransferAsset 다음 장… 조건이 충족되면 양도 계약에서 구매자의 클라이언트 ID를 가져와 구매자를 자산의 새로운 소유자로 만듭니다. 그리고, 이전 소유자의 컬렉션에서 Asset을 삭제하고 이전 계약을 제거합니다 AgreeToTransfer에서 aggKey형태로 저장했음 ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
  • 73. AssetTransfer.java - ⑤ VerifyAgreement 이 함수 호출 이전에 agreeToTransfer함수 호출을 통해 구매자가 특정가격에 구매를 하겠다고 등록한 상황 스마트 컨트랙트는 GetPrivateDataHash()를 사용하여 Org1MSPPrivateCollection감정가의 해시와 Org2MSPPrivateCollection이 일치하는지 확인합니다. 해시가 같으면 소유자와 관심있는 구매자가 동일한 자산 가치에 동의했음을 확인합니다. ../asset-transfer-private-data/chaincode-java/ 체인코드 리뷰
  • 74. 프라이빗 데이터 스마트 계약을 채널에 배포 ./network.sh deployCC -ccn private -ccp ../asset-transfer-private-data/chaincode-java/ -ccl java - ccep "OR('Org1MSP.peer','Org2MSP.peer')" -cccg ../asset-transfer-private-data/chaincode- java/collections_config.json 위 명령 수행 결과 출력되는 로그중, 체인코드 승인, 커밋에 –collections-config 에 private data collection 파일의 경로가 같이 포함됨
  • 75. go 체인코드는 잘 되는데, 자바 체인코드는 TLS 에러 발생 - openJDK 11.0.4 관련 이슈로 추정 • Go 설치 https://go.dev/doc/install
  • 76. • 체인코드 배포를 Java에서 Go로 변경 • ./network.sh down • ./network.sh deployCC -ccn private -ccp ../asset-transfer-private- data/chaincode-go/ -ccl go -ccep "OR('Org1MSP.peer','Org2MSP.peer')" - cccg ../asset-transfer-private-data/chaincode-go/collections_config.json
  • 77. 신원 등록 (Org1의 owner) • Org1 CA를 사용하여 ID 자산 소유자를 생성 • Fabric CA 클라이언트 홈을 Org1 CA 관리자의 MSP로 설정합니다 • fabric-ca-client 도구를 사용하여 새 소유자 클라이언트 ID를 등록 fabric-ca-client register --caname ca-org1 --id.name owner --id.secret ownerpw --id.type client -- tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem" • enroll명령에 등록 이름과 pw을 제공하여 ID 인증서 및 MSP 폴더를 생성 fabric-ca-client enroll -u https://owner:ownerpw@localhost:7054 --caname ca-org1 -M "${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org1/tls-cert.pem" • Node OU 구성 파일을 소유자 ID MSP 폴더에 복사 cp "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp/config.yaml" org1 -> users -> owner
  • 78. 신원 등록 (Org2의 buyer) • Org2 CA를 사용하여 구매자 ID를 생성 • Fabric CA 클라이언트 홈을 Org2 CA 관리자로 설정 • fabric-ca-client 도구를 사용하여 새 소유자 클라이언트 ID를 등록 fabric-ca-client register --caname ca-org2 --id.name buyer --id.secret buyerpw --id.type client --tls.certfiles "${PWD}/organizations/fabric-ca/org2/tls-cert.pem“ • ID MSP 폴더를 생성 fabric-ca-client enroll -u https://buyer:buyerpw@localhost:8054 --caname ca-org2 -M "${PWD}/organizations/peerOrganizations/org2.example.com/users/buyer@org2.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric- ca/org2/tls-cert.pem" • Node OU 구성 파일을 구매자 ID MSP 폴더에 복사 cp "${PWD}/organizations/peerOrganizations/org2.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org2.example.com/users/buyer@org2.example.com/msp/config.yaml"
  • 79. Create an asset in private data export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=$PWD/../config/ export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 Org1의 owner 클라이언트로 설정 export ASSET_PROPERTIES=$(echo -n "{"objectType":"asset","assetID":"asset1","color":"green","size":20,"appraisedValue":100}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n private -c '{"function":"CreateAsset","Args":[]}' --transient "{"asset_properties":"$ASSET_PROPERTIES"}"
  • 80. Query the private data as an authorized peer query the assetCollection collection as Org1 peer chaincode query -C mychannel -n private -c '{"function":"ReadAsset","Args":["asset1"]}' 결과 : {"objectType":"asset","assetID":"asset1","color":"green","size":20,"owner":"x509::CN=appUser1,OU=admin,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US"} Query for the appraisedValue private data of asset1 as a member of Org1. peer chaincode query -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org1MSPPrivateCollection","asset1"]}' 결과 : {"assetID":"asset1","appraisedValue":100}
  • 81. Query the private data as an unauthorized peer (1/3) export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/buyer@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 Org2의 buyer 클라이언트로 설정 Query private data Org2 is authorized to peer chaincode query -C mychannel -n private -c '{"function":"ReadAsset","Args":["asset1"]}' 결과 : {"objectType":"asset","assetID":"asset1","color":"green","size":20, "owner":"x509::CN=appUser1,OU=admin,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US" }
  • 82. Query private data Org2 is not authorized to peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com- cert.pem" -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org2MSPPrivateCollection","asset1"]}' 결과 : empty response Query the private data as an unauthorized peer (2/3)
  • 83. Query private data Org2 is not authorized to peer chaincode query -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org1MSPPrivateCollection","asset1"]}' 결과 : Query the private data as an unauthorized peer (3/3)
  • 84. Transfer the Asset agree to the appraised value of 100 as Org2 export ASSET_VALUE=$(echo -n "{"assetID":"asset1","appraisedValue":100}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com- cert.pem" -C mychannel -n private -c '{"function":"AgreeToTransfer","Args":[]}' --transient "{"asset_value":"$ASSET_VALUE"}" query the value they agreed to in the Org2 private data collection peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com- cert.pem" -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org2MSPPrivateCollection","asset1"]}' 상기와 같이 구매자가 구매 동의를 완료하였으니, 이제는 원 소유자가 이를 확인하여 Asset를 이관하는 시나리오 export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/owner@org1.example.com/msp export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_ADDRESS=localhost:7051 The owner from Org1 can read the data added by the AgreeToTransfer transaction to view the buyer identity: peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com- cert.pem" -C mychannel -n private -c '{"function":"ReadTransferAgreement","Args":["asset1"]}'
  • 85. Transfer the Asset 체인코드의 GetPrivateDataHash()를 통해Org1MSPPrivateCollection 감정가의 해시와 Org2MSPPrivateCollection의 해시가 일치하는지 확인 조건이 충족되면 구매자의 클라이언트 ID를 가져와 구매자를 자산의 새로운 소유자로 설정 Run the following commands to transfer the asset export ASSET_OWNER=$(echo -n "{"assetID":"asset1","buyerMSP":"Org2MSP"}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n private -c '{"function":"TransferAsset","Args":[]}' --transient "{"asset_owner":"$ASSET_OWNER"}" --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" query asset1 to see the results of the transfer peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n private -c '{"function":"ReadAsset","Args":["asset1"]}' confirm that transfer removed the private details from the Org1 collection peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n private -c '{"function":"ReadAssetPrivateDetails","Args":["Org1MSPPrivateCollection","asset1"]}' 결과 : empty
  • 86. Purge Private Data • 3개의 블록이 생성되면 데이터가 자동으로 삭제되는 것을 테스트하는 섹션 • CreateAsset 함수를 3번 호출하여 3개의 블록이 생성되도록 환경을 조성한 수, 데이터를 조회해 보면, 기존에 asset1의 appraisedValue가 100으로 출력되던 데이터가 조회되지 않음을 확인할 수 있음
  • 87. 여섯 번째 튜토리얼 Secured asset transfer in Fabric
  • 88. 시나리오 • 자산 발행(Org1) • 자산 식별자는 자산의 불변 속성의 해시이며 현재 소유자와 함께 모든 채널 구성원이 볼 수 있는 공개 채널 데이터로 저장 • 그러나 자산 불변 속성은 자산 소유자(및 이전 소유자)에게만 알려진 Private Information • 관심 있는 구매자는 구매하기 전에 해시된 자산 ID에 대해 자산의 사유 재산을 확인하기를 원할 것입니다. 이는 구매자가 올바른 자산 설명을 가지고 있음을 확인 • 자산 양도 위한 구매자와 판매자가 먼저 자산의 속성과 판매 가격 합의 • 현재 소유자만 자산을 다른 조직으로 이전 가능 • 구매자와 판매자 모두 양도를 승인
  • 89. 준비 • ./network.sh up createChannel -c mychannel • ./network.sh deployCC -ccn secured -ccp ../asset-transfer-secured- agreement/chaincode-go/ -ccl go -ccep "OR('Org1MSP.peer','Org2MSP.peer')" • 2개의 터미널창 준비
  • 90. at Terminal #1 export PATH=${PWD}/../bin:${PWD}:$PATH export FABRIC_CFG_PATH=$PWD/../config/ export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_ADDRESS=localhost:7051 export PATH=${PWD}/../bin:${PWD}:$PATH export FABRIC_CFG_PATH=$PWD/../config/ export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_ADDRESS=localhost:9051 at Terminal #2
  • 91. Create an asset • 모든 채널 구성원은 스마트 계약을 사용하여 조직이 소유한 자산을 생성할 수 있습니다. 자산의 세부 정보는 개인 데이터 컬렉션에 저장되며 자산을 소유한 조직에서만 액세스할 수 있습니다. 자산, 소유자 및 공개 설명의 공개 기록은 채널 원장에 저장됩니다. 모든 채널 구성원은 자산 소유자를 확인하기 위해 공공 소유권 기록에 액세스할 수 있으며 자산이 판매용인지 확인하기 위해 설명을 읽을 수 있습니다. at Terminal #1 export ASSET_PROPERTIES=$(echo -n "{"object_type":"asset_properties","color":"blue","size":35,"salt":"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c '{"function":"CreateAsset","Args":["A new asset for Org1MSP"]}' --transient "{"asset_properties":"$ASSET_PROPERTIES"}" peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"GetAssetPrivateProperties","Args":["$ASSET_ID"]}" peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"ReadAsset","Args":["$ASSET_ID"]}" 생성후 리턴되는 해시값이 자산 ID가 됨
  • 92. at Terminal #1 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"ChangePublicDescription","Args":["$ASSET_ID","This asset is for sale"]}" peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"ReadAsset","Args":["$ASSET_ID"]}" Org1에서만 가능, Org2에서는 endorsement failure 500에러 발생 at Terminal #2 export ASSET_ID=d9923f21b770adbc79cbcc47a3aeecc81dc7f030bd129155301ce3932be7fbcc peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"ReadAsset","Args":["$ASSET_ID"]}"
  • 93. Agree to sell as Org1 자산을 판매하려면 구매자와 판매자 모두 자산 가격에 동의하고 각자의 개인 데이터 컬렉션에 동일한 자산 속성이 있는지 확인해야 합니다. 각 당사자는 자신의 개인 데이터 컬렉션에 동의한 가격을 저장합니다. 개인 자산 전송 스마트 계약은 자산을 전송하기 전에 양 당사자가 동일한 가격과 자산 속성에 동의해야 한 다고 강제합니다. at Terminal #1 export ASSET_PRICE=$(echo -n "{"asset_id":"$ASSET_ID","trade_id":"109f4b3c50d7b0df729d299bc6f8e9ef9066971f","price":110}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"AgreeToSell","Args":["$ASSET_ID"]}" --transient "{"asset_price":"$ASSET_PRICE"}" peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"GetAssetSalesPrice","Args":["$ASSET_ID"]}" 구매자나 판매자가 아닌 채널 구성원이 가격을 추측하는 것을 방지하기 위해 사용
  • 94. Agree to buy as Org2 구매에 동의하기 전에 다음 명령을 실행하여 자산 속성을 확인하십시오. 자산 속성과 salt는 구매자와 판매자 사이에서 이메일 또는 기타 통신을 통해 대역외로 전달됩니다. at Terminal #2 export ASSET_PROPERTIES=$(echo -n "{"object_type":"asset_properties","color":"blue","size":35,"salt":"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"}" | base64 | tr -d n) peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"VerifyAssetProperties","Args":["$ASSET_ID"]}" --transient "{"asset_properties":"$ASSET_PROPERTIES"}" 다음 명령을 실행하여 100달러에 asset1 구매에 동의합니다. 현재 Org2는 Org1과 다른 가격에 동의합니다. 걱정하지 마십시오. 두 조직은 향후 단계에서 동일한 가격에 동의할 것입니다. 그러나 우리는 구매자와 판 매자가 다른 가격에 동의할 경우 어떤 일이 발생하는지 테스트하기 위해 이 일시적인 불일치를 사용할 수 있습니다. Org2는 Org1과 동일하게 사용해야 합니다 export ASSET_PRICE=$(echo -n "{"asset_id":"$ASSET_ID","trade_id":"109f4b3c50d7b0df729d299bc6f8e9ef9066971f","price":100}" | base64 | tr -d n) export ASSET_PROPERTIES=$(echo -n "{"object_type":"asset_properties","color":"blue","size":35,"salt":"a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"AgreeToBuy","Args":["$ASSET_ID"]}" --transient "{"asset_price":"$ASSET_PRICE", "asset_properties":"$ASSET_PROPERTIES"}" peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"GetAssetBidPrice","Args":["$ASSET_ID"]}"
  • 95. Org1과 Org2가 자산 이전에 동의한 후 각 조직에서 동의한 가격이 Private data collection에 저장됩니다. 자산내역과 자산소유기록이 충돌 하는 것을 방지하기 위해 판매자와 구매자를 위한 복합키를 사용합니다. 합의된 가격은 각 조직의 피어에만 저장됩니다. 그러나 두 계약의 해시는 채널에 가입한 모든 피어의 Channel World State저장됩니다.
  • 96. Transfer the asset from Org1 to Org2 두 조직이 가격 및 자산 속성에 동의한 후 Org1은 자산을 Org2로 이전하려고 시도할 수 있습니다. 스마트 계약의 개인 자산 이전 기능은 원장의 해시를 사용하여 두 조직이 동일한 가격에 동의했는지 확인합니다. 이 기능은 또한 판매자 및 구매자 개인 컬렉션의 자산 속성 해시를 확인하여 전송된 자산이 Org1이 소유한 자산과 동일한지 확인합니다. at Terminal #1 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"TransferAsset","Args":["$ASSET_ID","Org2MSP"]}" --transient "{"asset_price":"$ASSET_PRICE"}" --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" 결과적으로 Org1과 Org2는 자산을 구매할 가격에 대해 새로운 합의에 도달합니다. Org1은 자산 가격을 100으로 떨어뜨립니다. export ASSET_PRICE=$(echo -n "{"asset_id":"$ASSET_ID","trade_id":"109f4b3c50d7b0df729d299bc6f8e9ef9066971f","price":100}" | base64 | tr -d n) peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"AgreeToSell","Args":["$ASSET_ID","Org2MSP"]}" --transient "{"asset_price":"$ASSET_PRICE"}" peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"TransferAsset","Args":["$ASSET_ID","Org2MSP"]}" --transient "{"asset_price":"$ASSET_PRICE"}" --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"ReadAsset","Args":["$ASSET_ID"]}"
  • 97. 자산이 전송된 후 자산 세부 정보는 Org2 암시적 데이터 컬렉션에 배치되고 Org1 암시적 데이터 컬렉션에서 삭제됩니다. 결과적으로 자산 세부 정보는 이제 Org2 피어에만 저장됩니다. 원장의 자산 소유권 레코드는 Org2가 자산을 소유하고 있음을 반영하도록 업데이트됩니다.
  • 98. Update the asset description as Org2 Org2 터미널에서 작동합니다. 이제 Org2가 자산을 소유하고 있으므로 Org2 암시적 데이터 컬렉션에서 자 산 세부 정보를 읽을 수 있습니다. peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"GetAssetPrivateProperties","Args":["$ASSET_ID"]}" peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"ChangePublicDescription","Args":["$ASSET_ID","This asset is not for sale"]}" peer chaincode query -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n secured -c "{"function":"ReadAsset","Args":["$ASSET_ID"]}"
  • 100. 개요 • A Docker image of CouchDB is available and we recommend that it be run on the same server as the peer. • If a rich query includes a sort specification, then an index on that field is required • When using CouchDB, each chaincode is represented as its own CouchDB database, that is, each chaincode has its own namespace for keys.
  • 101. 개요 docType is used to identify that this JSON document represents an asset. Potentially there could be other JSON document types in the chaincode namespace
  • 102. Create an index When defining an index for use in chaincode queries - each one must be defined in its own text file with the extension *.json - the index definition must be formatted in the CouchDB index JSON format. ddoc선택적으로 색인 정의에 디자인 문서 속성을 지정할 수 있습니다. 디자 인 문서는 인덱스를 포함하도록 설계된 CouchDB 구조입니다. 색인은 효율 성을 위해 설계 문서로 그룹화할 수 있지만 CouchDB는 설계 문서당 하나의 색인을 권장합니다.
  • 104. Add the index to your chaincode folder JSON 인덱스 파일은 체인코드가 위치한 디렉토리의 META-INF/statedb/couchdb/indexes 에 준비해야 함
  • 105. Start the network • cd ../asset-transfer-ledger-queries/chaincode-go • GO111MODULE=on go mod vendor • cd ../../test-network • ./network.sh up createChannel -s couchdb • ./network.sh deployCC -ccn ledger -ccp ../asset-transfer-ledger- queries/chaincode-go/ -ccl go -ccep "OR('Org1MSP.peer','Org2MSP.peer')" • docker logs peer0.org1.example.com 2>&1 | grep "CouchDB index" Verify index was deployed
  • 106. Query the CouchDB State Database • use_index 키워드를 사용하여 쿼리에 인덱스 이름을 명시적으로 포함하는 것을 권고 export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n ledger -c '{"Args":["CreateAsset","asset1","blue","5","tom","35"]}' peer chaincode query -C mychannel -n ledger -c '{"Args":["QueryAssets", "{"selector":{"docType":"asset","owner":"tom"}, "use_index":["_design/indexOwnerDoc", "indexOwner"]}"]}' SHIM API 호출 체인코드의 CreateAsset함수 내에서 하드코딩으로 DocType을 "asset"으로 설정했었음
  • 107. Use best practices for queries and indexes // Example one: query fully supported by the index export CHANNEL_NAME=mychannel peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"docType":"asset","owner":"tom"}, "use_index":["indexOwnerDoc", "indexOwner"]}"]}' peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"docType":"asset","owner":"tom","color":"blue"}, "use_index":["/indexOwnerDoc", "indexOwner"]}"]}' peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"owner":"tom"}, "use_index":["indexOwnerDoc", "indexOwner"]}"]}' peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"$or":[{"docType":"asset"},{"owner":"tom"}]}, "use_index":["indexOwnerDoc", "indexOwner"]}"]}' peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssets", "{"selector":{"$or":[{"docType":"asset","owner":"tom"},{"color":"yellow"}]}, "use_index":["indexOwnerDoc", "indexOwner"]}"]}' 인덱스 사용 인덱스 사용, 응답시간 지연 인덱스 미사용 인덱스 사용, 응답시간 지연 인덱스 미사용 블록체인 데이터 구조는 거래를 검증하고 확인하는 데 최적화되어 있음 데이터 분석이나 보고에는 적합하지 않음
  • 108. Query the CouchDB State Database With Pagination export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n ledger -c '{"Args":["CreateAsset","asset2","yellow","5","tom","35"]}' peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n ledger -c '{"Args":["CreateAsset","asset3","green","6","tom","20"]}' peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n ledger -c '{"Args":["CreateAsset","asset4","purple","7","tom","20"]}' peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n ledger -c '{"Args":["CreateAsset","asset5","blue","8","tom","40"]}' // Rich Query with index name explicitly specified and a page size of 3: peer chaincode query -C mychannel -n ledger -c '{"Args":["QueryAssetsWithPagination", "{"selector":{"docType":"asset","owner":"tom"}, "use_index":["_design/indexOwnerDoc", "indexOwner"]}","3",""]}' SHIM API 호출 Pagination 사이즈 : 3 시작페이지 : default(1)
  • 109. Query the CouchDB State Database With Pagination peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssetsWithPagination", "{"selector":{"docType":"asset","owner":"tom"}, "use_index":["_design/indexOwnerDoc", "indexOwner"]}","3","g1AAAABJeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqzJRYXp5YYg2Q5YLI5IPUgSVawJIjFXJKfm5UFANozE8s"]}' peer chaincode query -C $CHANNEL_NAME -n ledger -c '{"Args":["QueryAssetsWithPagination", "{"selector":{"docType":"asset","owner":"tom"}, "use_index":["_design/indexOwnerDoc", "indexOwner"]}","3","g1AAAABJeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqzJRYXp5aYgmQ5YLI5IPUgSVawJIjFXJKfm5UFANqBE80"]}' 앞 장에 이어서, 다음 페이지 조회 조회결과를 북마크 인덱스를 리턴하는데, 이 값을 이용하여 다음 페이지 조회에 사용함 Range Query Pagination 기능도 지원함 - GetStateByRangeWithPagination
  • 110. Update an Index • http://localhost:5984/_utils 접속 (admin/adminpw)
  • 112. Update an Index 아래 방법도 가능
  • 113. Delete an Index curl -X DELETE http://admin:adminpw@localhost:5984/mychannel_ledger/_index/indexOwnerDoc/json/indexOwner -H "accept: */*" -H "Host: localhost:5984"
  • 114. 여덟 번째 튜토리얼 Create a channel the test network
  • 115. • 어플리케이션 채널 생성하고 오더링 노드에 조인하는 튜토리얼 • In this tutorial, ① we use the configtxgen tool to create a channel genesis block ② and then use the osnadmin channel command to create the channel.(application channel)
  • 116. 준비 • ./network.sh up By default, when you start the test network, it does not contain any channels. 채널을 생성하기 위해서, 다음 장의 configtxgen 사용
  • 117. Set up the configtxgen tool • 채널은 제네시스 블록에 채널 생성 정보를 오더링 서비스에 전달함으로써 생성된다. • configex.yaml에 채널 명세를 해야 한다. • configtxgen은 fabric-sample/bin 디렉토리에 있다. • export PATH=${PWD}/../bin:$PATH • export FABRIC_CFG_PATH=${PWD}/configtx • configtxgen --help
  • 118. The configtx.yaml file • Organizations • Ordering service : 합의 방식/프로토콜 • Channel policies • Channel profiles
  • 119. Step one: Generate the genesis block of the channel • configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel- artifacts/channel1.block -channelID channel1
  • 120. Step two: Create the application channel export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
  • 121. Join peers to the channel • view the channels • Join peers to the channel osnadmin channel list -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 export FABRIC_CFG_PATH=$PWD/../config/ peer channel join -b ./channel-artifacts/channel1.block peer CLI를 사용하기 위해 환경변수 재설정 acting as the Org1 admin and targeting the Org1 peer
  • 122. Join peers to the channel • Join peers to the channel export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 export FABRIC_CFG_PATH=$PWD/../config/ peer channel join -b ./channel-artifacts/channel1.block acting as the Org2 admin and targeting the Org2 peer → Joined their peers to the channel
  • 123. Set anchor peer • We will use the configtxlator tool to update the channel configuration and select an anchor peer for Org1 and Org2. export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 acting as the Org1 admin peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile "$ORDERER_CA" fetch the channel configuration cd channel-artifacts configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json jq '.data.data[0].payload.data.config' config_block.json > config.json cp config.json config_copy.json jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' config_copy.json > modified_config.json decode the block from protobuf into a JSON objec
  • 124. Set anchor peer configtxlator proto_encode --input config.json --type common.Config --output config.pb configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output config_update.pb 채널 구성 파일(원본, 수정본)을 protobuf 형식으로 변경하고 변경분을 계산 configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json echo '{"payload":{"header":{"channel_header":{"channel_id":"channel1", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb cd .. peer channel update -f channel-artifacts/config_update_in_envelope.pb -c channel1 -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" 채널 헤더와 타입의 정보(K:V)를 앞에 추가(JSON 형태)하고, 이를 pb형식으로 다시 변환
  • 125. Set anchor peer export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" cd channel-artifacts configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json jq '.data.data[0].payload.data.config' config_block.json > config.json cp config.json config_copy.json jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' config_copy.json > modified_config.json configtxlator proto_encode --input config.json --type common.Config --output config.pb configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output config_update.pb configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json echo '{"payload":{"header":{"channel_header":{"channel_id":"channel1", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb cd .. peer channel update -f channel-artifacts/config_update_in_envelope.pb -c channel1 -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" peer channel getinfo -c channel1 Org2의 Peer에도 동일 적용하고 블록 수가 최종적으로 3으로 증가되었는지 확인
  • 126. Deploy a chaincode to the new channel ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go -c channel1 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" -C channel1 -n basic -- peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" -- peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"InitLedger","Args":[]}' peer chaincode query -C channel1 -n basic -c '{"Args":["getAllAssets"]}' 채널 정상여부 확인을 위한 체인코드 배포 및 테스트
  • 127. 아홉 번째 튜토리얼 Adding an Org to a Channel
  • 128. Bring Org3 into the Channel with the Script • 채널 생성후 Org3 조직을 Join • ./network.sh down • ./network.sh up createChannel -c channel1 • cd addOrg3 • ./addOrg3.sh up -c channel1 인증서 등 생성 이후, 채널에 조인함
  • 129. Bring Org3 into the Channel Manually • ./network.sh down • ./network.sh up createChannel -c channel1 • cd addOrg3 • 기 구성된 채널(channel1)에 업데이트를 하기 때문에, CA를 사용하지 않고 cryptogen 도구를 사용한다. • ../../bin/cryptogen generate --config=org3-crypto.yaml -- output="../organizations" 앞 장에서 했던 내용을 하나씩 수행하면서, 원리를 알아보자. 기존 조직 Org1, Org2에 Org3 조직 추가됨
  • 130. • configtxgen 도구를 사용하여 Org3 조직를 출력 • export FABRIC_CFG_PATH=$PWD • ../../bin/configtxgen -printOrg Org3MSP > ../organizations/peerOrganizations/org3.example.com/org3.json Bring Org3 into the Channel Manually configtxgen로 하여금 현재 디렉토리의 configtx.yaml을 참조하게 함 위 수행의 결과로 org3.json 파일이 생성되고, 이 파일에는 조직의 정책 정의 내용과 CA 루트 인증서, TLS 루트 인증서가 포함된다. 이후, 이 파일을 채널에 추가하게 된다.
  • 131. Bring up Org3 components • From the addOrg3 directory, • docker-compose -f compose/compose-org3.yaml -f compose/docker/docker- compose-org3.yaml up -d 볼륨 마운트 대상 디렉토리 표기시 뒤에 슬래쉬 기호를 추가해야 아래와 같은 오류가 발생하지 않는다.
  • 132. Fetch the Configuration • 현재 채널의 설정 블록을 불러온다. • From the test-network directory • Org3가 아직 채널 멤버가 아니기 때문에, Org1의 Admin으로 환경변수를 설정하여 작업을 진행한다. • 현재 채널(channel1)의 구성 정보를 불러와서, config_block.pb 파일로 저장 export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=${PWD}/../config/ export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
  • 133. Convert the Configuration to JSON and Trim It Down • cd channel-artifacts • 앞장에서 생성한 config_block.pb파일을 json으로 형식을 변경하고 불필요한 정보를 제외하여 config.json파일로 출력 • configtxlator proto_decode --input config_block.pb --type common.Block -- output config_block.json • jq ".data.data[0].payload.data.config" config_block.json > config.json
  • 134. Add the Org3 Crypto Material • 이전에 생성한 org3.json(organization/peer~/org3.peer~) 파일 내용을 앞장에서 생성한 json파일에 추가하여 modified_config.json으로 생성 • jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ../organizations/peerOrganizations/org3.example.com/org3.json > modified_config.json • 작업 순서 ① Org1/2 만 있는 기존의 config.json을 protobuf형식으로 변경 ② Org3까지 포함하고 있는 modified_config.json을 protobuf형식으로 변경 ③ 상기 2개의 pb 파일을 configtxlator 도구를 이용하여 변경분을 계산(org3_update.pb) ④ 상기 변경분을 json 형식으로 변환(org3_update.json) ⑤ org3 정보 + header 추가한 json 파일을 생성(org3_update_in_envelope.json) (☞ 앞장에서 config.json을 생성할때 채널 설정을 읽어서 헤더를 제거했었음) ⑥ configtxlator 도구를 이용 상기 json파일을 pb로 포맷 변경(org3_update_in_envelope.pb) 헤더 org3_update.json org3_update_in_envelope.json jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ../organizations/peerOrganizations/org3.example.com/org3.json > modified_config.json configtxlator proto_encode --input config.json --type common.Config --output config.pb configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output org3_update.pb configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate --output org3_update.json echo '{"payload":{"header":{"channel_header":{"channel_id":"'channel1'", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb
  • 135. Sign and Submit the Config Update • 수정 정책(mod_policy)는 과반 이상 동의해야 하기 때문에, Org1/Org2 두 조직의 signature가 필요한 상황 • Org1으로 사인하고, 환경설정 변수를 Org2로 변경하고 peer channel update로 렛져에 반영(Org2는 peer channel update시 자동으로 사인이 추가되기 때문에 별도로 사인할 필요 없음) • From the test-network directory • peer channel signconfigtx -f channel-artifacts/org3_update_in_envelope.pb • peer channel update -f channel-artifacts/org3_update_in_envelope.pb -c channel1 -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.e xample.com/msp/tlscacerts/tlsca.example.com-cert.pem" export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051
  • 136. Join Org3 to the Channel • 환경변수를 Org3 Admin으로 설정하고, 제네시스 블록을 요청한다. (신규 조직이 채널에 참가하는 방법: 제네시스 블록 또는 스냅샷으로 생성) • 제네시스 블록을 기반으로 peer channel join 명령으로 채널에 참가한다. export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org3MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp export CORE_PEER_ADDRESS=localhost:11051 peer channel fetch 0 channel-artifacts/channel1.block -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" peer channel join -b channel-artifacts/channel1.block
  • 138. Install, define, and invoke chaincode 새 터미널을 열어서 체인코드를 배포(아래 명령을 통해 Org1과 Org2에 체인코드가 배포됨) ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go -c channel1 이제는 Org3로 환경설정하고, 체인코드(동일) 배포하여 사용한다. export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=$PWD/../config/ export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org3MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp export CORE_PEER_ADDRESS=localhost:11051 peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_1 peer lifecycle chaincode install basic.tar.gz peer lifecycle chaincode queryinstalled export CC_PACKAGE_ID=basic_1:5443b5b557efd3faece8723883d28d6f7026c0bf12245de109b89c5c4fe64887 peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --channelID channel1 --name basic --version 1.0 -- package-id $CC_PACKAGE_ID --sequence 1 peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --channelID channel1 --name basic --version 1.0 -- package-id $CC_PACKAGE_ID --sequence 1 peer lifecycle chaincode querycommitted --channelID channel1 --name basic Org3 can use the basic chaincode after it approves the chaincode definition that was committed to the channel peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C channel1 -n basic --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" --peerAddresses localhost:11051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt" -c '{"function":"InitLedger","Args":[]}' peer chaincode query -C channel1 -n basic -c '{"Args":["GetAllAssets"]}' 기존 채널 구성원이 이미 체인코드 정의를 채널에 커밋한 경우 새 조직은 체인코드 정의를 승인하여 체인코드 사용을 시작할 수 있습니다. 과반 이상 승인 (2/3)
  • 141. host #2 192.168.56.41 koposlave1 Deployment Environment host #1 192.168.56.40 kopomaster host #3 192.168.56.42 koposlave2 host #4 192.168.56.43 koposlave3 Orderer1 Orderer2 Orderer3 Orderer4 Orderer5 Peer0 Peer1 Peer0 Peer1 Org1 Org2 Gateway CA_Orderer CA_Org1 CA_Org2
  • 142. setting a network address
  • 143. setting a network address vi /etc/netplan/00-installer-config.yaml # This is the network config written by 'subiquity' network: ethernets: enp0s3: dhcp4: true enp0s8: addresses: - 192.168.56.40/24 nameservers: addresses: [8.8.8.8, 8.8.4.4] version: 2 192.168.56.40 → kopomaster 192.168.56.41 → koposlave1 192.168.56.42 → koposlave2 192.168.56.43 → koposlave3 netplan apply
  • 144. docker installation • apt-get -y install docker-compose • docker --version • docker-compose --version • systemctl start docker • systemctl enable docker
  • 145. Go 설치 • rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.2.linux-amd64.tar.gz • vi /etc/profile • 상기 파일에 환경변수 추가 export PATH=$PATH:/usr/local/go/bin • source /etc/profile • go version
  • 146. etc. • apt install tree • apt install jq • apt install net-tools • apt-get install openjdk-11-jdk vi ~/.bashrc 상기 파일에 환경변수 추가 export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java)))) export PATH=$PATH:$JAVA_HOME/bin • source ~/.bashrc • java -version hostnamectl set-hostname kopomaster 192.168.56.40 → kopomaster 192.168.56.41 → koposlave1 192.168.56.42 → koposlave2 192.168.56.43 → koposlave3
  • 147. [참조] 기본 아이디어 (1/2) https://kctheservant.medium.com/multi-host-setup-with-raft-based-ordering-service-29730788b171 https://kctheservant.medium.com/multi-host-deployment-for-first-network-hyperledger-fabric-v2-273b794ff3d docker swarm을 이용한 멀티 호스트 예제 - 인증서는 cryptogen을 이용해 생성 - v2.2 기준 다음과 같이 재구성 해보자. - Hyperledger fabric CA 서버로 인증서 생성 - 최신 예제와 환경으로 프로젝트 재구성(v2.5) v1.4기준 멀티호스트 예제 v2.2 기준 멀티호스트 예제
  • 148. [참조] 기본 아이디어 (2/2) 1. 앞 장의 2개의 가이드를 수행 테스트 https://github.com/wonyongHwang/4host-swarm https://kctheservant.medium.com/a-companion-guide-to-fabric-ca- operation-guide-c81591ef0321 https://kctheservant.medium.com/add-a-peer-to-an-organization-in- test-network-hyperledger-fabric-v2-2-4a08cb901c98 CA 서버 가이드 참조 peer 추가 가이드 참조
  • 149. docker swarm at host 1 : docker swarm init --advertise-addr 192.168.56.40 # docker swarm join at host2~4: docker swam join as below: ex> docker swarm join --token <토큰> 192.168.56.40:2377 at host 1: docker network create --attachable --driver overlay kopo-network docker node promote koposlave2 docker node promote koposlave3 docker node promote koposlave4
  • 150. 준비작업 - 인증서 발급 1번 서버 : cd fabric-samples/kopo-network ./network.sh up -ca 인증서(organizations) 디렉토리 복사 및 2~4번 서버 폴더에 복사(kopo-network/organizations) ./network down 인증서(organizations) 디렉토리 복사 및 1번 서버 폴더에 복사(kopo-network/organizations)
  • 151. 기동 1,4번 서버 : cd fabric-samples/kopo-network ./kopo-network.sh up 2,3번 서버 : cd fabric-samples/kopo-network ./kopo-network.sh up -s couchdb [참고] 1번 서버에서 차후에 별도로 CA서버 기동할 시 docker-compose -f compose/compose-ca.yaml -f compose/docker/docker-compose-ca.yaml up -d
  • 152. 채널 생성 1번 서버 : export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=${PWD}/configtx configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/channel1.block -channelID channel1 # 여기서 생성된 channel-artifacts 디렉토리를 2~4번 서버의 kopo-network/ 에 복사한다. (다른 오더러들도 채널에 조인하기 위함) export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com- cert.pem export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" 2번 서버 : export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=${PWD}/configtx export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/msp/tlscacerts/tlsca.example.com- cert.pem export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.key osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:8053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
  • 153. 3번 서버 : export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=${PWD}/configtx export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer3.example.com/msp/tlscacerts/tlsca.example.com-cert.pem export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.key osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:9053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" 4번 서버 : export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=${PWD}/configtx export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer4.example.com/msp/tlscacerts/tlsca.example.com-cert.pem export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.key osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:10053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer5.example.com/msp/tlscacerts/tlsca.example.com-cert.pem export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.key osnadmin channel join --channelID channel1 --config-block ./channel-artifacts/channel1.block -o localhost:11053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" 채널 생성