SlideShare a Scribd company logo
1 of 105
Download to read offline
hyperledger fabric
V2.0
Precondition
! Ubuntu 18.04 LTS or Above
! Docker Install (Latest version)
apt-get install libltdl-dev
! Docker Engine: Version 17.06.2-ce or higher
wget https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/
amd64/docker-ce_17.06.2~ce-0~ubuntu_amd64.deb
dpkg -i docker-ce_17.06.2~ce-0~ubuntu_amd64.deb
docker —version
! curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-
compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker–compose –version
https://phoenixnap.com/kb/install-docker-compose-ubuntu
environment setup
! ubuntu 16.04 or higher (we’ve installed ubuntu 18.04…)
! root 권한으로 설치
! apt-get update
! apt-get install curl
! apt-get install python-pip
! apt-get install make gcc g++ libtool
! apt-get install tree
environment setup
! git
apt-get install -y git
git version
! Python: 2.7.x
python –version
(apt-get install -y python)
! Go lang Version 1.11.x
wget https://dl.google.com/go/go1.13.12.linux-amd64.tar.gz
tar -C /usr/local/ -xvf go1.13.12.linux-amd64.tar.gz
! Go 환경변수 설정 vi /etc/profile
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
source /etc/profile
go version
environment setup
! Node.js (Version 8.9 or higher (no version 9.0 support) / npm (Version 6.x)
curl -sL http://deb.nodesource.com/setup_8.x | bash -
apt-get install nodejs
node -v
npm -v
environment setup
! Hyperledger Fabric
curl -sSL http://bit.ly/2ysbOFE | bash -s 1.4.0 1.4.0 0.4.10
(curl -sSL https://goo.gl/6wtTN5 | bash -s 1.4.1 1.4.1 0.4.10)
(curl -sSL https://bit.ly/2KLpv5d | bash -s 1.4.0 –d -s)
!
! vi /etc/profile
export FABRIC_HOME=/home/fabric/fabric-samples
export PATH=$PATH:$FABRIC_HOME/bin
source /etc/profile
[참고] 최신 버전 설치시(2.0) 아래 명령으로 실행
(V2.0에서는 본 교안에서 설명하는 예제가 정상 실행되지 않음. 예제의 버전이 2.0 기준으로 수정되어야 함)
v2.0은 체인코드 라이프싸이클이 더 상세해짐
curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s
curl -sSL https://bit.ly/2ysbOFE | bash -s
Build your first network
개요
! The build your first network (BYFN) scenario provisions a sample Hyperledger
Fabric network consisting of two organizations, each maintaining two peer
nodes. It also will deploy a “Solo” ordering service by default, though other
ordering service implementations are available.
source : https://hyperledger-fabric.readthedocs.io/en/release-1.4/build_network.html
Org1MSP - Peer 0
- Peer 1
Org2MSP - Peer 0
- Peer 1
crypto-config.yaml
! 인증서 생성을 위한 조직과 Peer 개수, 사용자(어드민 제외) 수 설정
Note that the crypto-config.yaml file lists five orderers as being tied to the orderer organization. While the cryptogen tool will create
certificates for all five of these orderers. 
Orderer
orderer2
orderer3
orderer4
orderer5
peer0.org0
peer1.org0
peer0.org1
peer1.org1
configtx.yaml
! 채널 생성을 위한 Peer 정보 ( Host, Port), MSP 정보,
Consortiums(몇 개의 Org로 구성할 것인지) 설정

- 블럭 생성 크기 등과 관련된 설정

BatchTimeout, 

BatchSize - MaxMessageCount

AbsoluteMaxBytes

PreferredMaxBytes
! 3가지 파일을 결과적으로 생성

- 최초 블록 정보 genesis.block
- 앵커 피어 정보 anchor.tx
(Org1MSPanchor.tx, Org2MSPanchor.tx)
- 채널 구성 정보 channel.tx
T
echo "##########################################################"
echo "######### Generating Orderer Genesis block ##############"
echo "##########################################################"
# Note: For some unknown reason (at least for now) the block file can't be
# named orderer.genesis.block or the orderer will fail to launch!
set -x
configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.bloc
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate orderer genesis block..."
exit 1
fi
echo
echo "#################################################################"
echo "### Generating channel configuration transaction 'channel.tx' ###"
echo "#################################################################"
set -x
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAM
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate channel configuration transaction..."
exit 1
fi
TwoOrgsChannel은 콘소시엄으로 구성된
Org1과 Org2의 채널에 관한 명세이며
SampleMultiNodeEtcdRaft는 블록체인을
구성하는 오더러의 정보를 명세하며 이 정보가
genesisBlock에 포함된다.
byfn.sh
echo "##########################################################"
echo "######### Generating Orderer Genesis block ##############"
echo "##########################################################"
# Note: For some unknown reason (at least for now) the block file can't be
# named orderer.genesis.block or the orderer will fail to launch!
configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
echo "#################################################################"
echo "### Generating channel configuration transaction 'channel.tx' ###"
echo "#################################################################"
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
echo "#################################################################"
echo "####### Generating anchor peer update for Org1MSP ##########"
echo "#################################################################"
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
echo "#################################################################"
echo "####### Generating anchor peer update for Org2MSP ##########"
echo "#################################################################"
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
+ res=0
+ set +x
Generate CCP files for Org1 and Org2
/root/fabric-samples/first-network/../bin/configtxgen
##########################################################
######### Generating Orderer Genesis block ##############
##########################################################
+ configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
2020-06-04 01:45:15.992 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2020-06-04 01:45:16.015 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: etcdraft
2020-06-04 01:45:16.015 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 Orderer.EtcdRaft.Options unset, setting to tick_interval:"500ms" election_tick:10 heartbeat_tick:1 max_inflight_blocks:5 snapshot_interval_size:16777216
2020-06-04 01:45:16.016 UTC [common.tools.configtxgen.localconfig] Load -> INFO 004 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml
2020-06-04 01:45:16.017 UTC [common.tools.configtxgen] doOutputBlock -> INFO 005 Generating genesis block
2020-06-04 01:45:16.018 UTC [common.tools.configtxgen] doOutputBlock -> INFO 006 Writing genesis block
+ res=0
+ set +x
#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
2020-06-04 01:45:16.033 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2020-06-04 01:45:16.053 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml
2020-06-04 01:45:16.054 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx
2020-06-04 01:45:16.056 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx
+ res=0
+ set +x
#################################################################
####### Generating anchor peer update for Org1MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2020-06-04 01:45:16.071 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2020-06-04 01:45:16.092 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml
2020-06-04 01:45:16.092 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Generating anchor peer update
2020-06-04 01:45:16.093 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 004 Writing anchor peer update
+ res=0
+ set +x
#################################################################
####### Generating anchor peer update for Org2MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2020-06-04 01:45:16.108 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2020-06-04 01:45:16.129 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml
2020-06-04 01:45:16.129 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Generating anchor peer update
2020-06-04 01:45:16.132 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 004 Writing anchor peer update
+ res=0
+ set +x
./byfn.sh generate
제네시스 블록 생성
채널 환결설정
앵커피어 설정
모두/channel-artifacts/ 하위에 결과파일로 저장
[results] ./byfn.sh generate
v2.0 부터 priv_sk 디렉토리로 변경
CA 심화
! 인증기관(CA), 공개키, 개인키, 인증서(CRT)
source : http://soul0.tistory.com/372
intro
CA 살펴보기
hyperledger의 인증
! 하이러페저는 모든 노드들이 자신들의 인증을 CA를 통해 받는다.
! Root CA ! 자식 CA ! *
! 앞서 살펴본 cryptogen 을 통해서 CA를 구성할 수 있음

(Fabric CA Server를 통해서도 CA구성 가능, Fabric-CA Client 또는 Fabric SDK를 통해
서도 인증서 발급 및 조회 등의 서비스 이용가능)
! 인증 대상

- 전체 네트워크, 채널, 조직(Org), 조직 관리자(Admin),
사용자(User), Peer
source : https://hyperledger-fabric-ca.readthedocs.io/en/latest/users-guide.html
CA 살펴보기
hyperledger MSP
! MSP (Membership Service Provider)는 멤버쉽 서비스 제공 목적의 컴포넌트
! 인증서를 발급/조회/검증하는 등 사용자 및 서비스의 인증에 대한 작업
! 조직마다 보통 하나의 MSP가 있으며 MSP ID로 구분된다.
- 전체 네트워크, 채널, 조직(Org), 조직 관리자(Admin),
사용자(User), Peer
// mspID 와 certCN 을 조건으로 검사하여 함수의 사용가능 여부를 판단할 수 있음
func authenticateOrg(mspID string, certCN string) bool {
return (mspID == "Org1MSP") && (certCN == "ca.example.com")
}
CA 살펴보기
source : https://github.com/hyperledger/fabric/blob/release-1.4/msp/msp.go
check private key
! root@ubuntu:~/fabric-samples/first-network# find | grep -E '/ca.*_sk' | sort
./crypto-config/ordererOrganizations/example.com/ca/d6c3aff453b6947f13e189a3d3cb60f1d42addf2295acca28aed14f3d4827c21_sk
./crypto-config/peerOrganizations/org1.example.com/ca/c9681f8d01403a2be7a2df7b2bd2ebdc691288d64ae0209b6270facf822fa7e1_sk
./crypto-config/peerOrganizations/org2.example.com/ca/36ea9dbed56ffa19a337c3f3b838682ebd11edd84b51fe6e0f700f7e1a3a4044_sk
CA 살펴보기
├── ordererOrganizations
│   └── example.com
│   ├── ca
│   │   ├── 5a4cfffc67e06260ef685ffa0559975f54912df5127d9bbf0ece4c7b83f9caeb_sk
│   │   └── ca.example.com-cert.pem
│   ├── msp
│   │   ├── admincerts
│   │   │   └── Admin@example.com-cert.pem
│   │   ├── cacerts
│   │   │   └── ca.example.com-cert.pem
│   │   └── tlscacerts
│   │   └── tlsca.example.com-cert.pem
│   ├── orderers
│   │   └── orderer.example.com
│   │   ├── msp
│   │   │   ├── admincerts
│   │   │   │   └── Admin@example.com-cert.pem
│   │   │   ├── cacerts
│   │   │   │   └── ca.example.com-cert.pem
│   │   │   ├── keystore
│   │   │   │   └── 829584340955b187ecc5b1cef386736fd3666ffcd0600ef3f4bc2015c2e36d34_sk
│   │   │   ├── signcerts
│   │   │   │   └── orderer.example.com-cert.pem
│   │   │   └── tlscacerts
│   │   │   └── tlsca.example.com-cert.pem
│   │   └── tls
│   │   ├── ca.crt
│   │   ├── server.crt
│   │   └── server.key
│   ├── tlsca
│   │   ├── 419de30afd02a9ac15cc62acf07509c9497c792cc938d19cbac7484c6ff7455b_sk
│   │   └── tlsca.example.com-cert.pem
│   └── users
│   └── Admin@example.com
│   ├── msp
│   │   ├── admincerts
│   │   │   └── Admin@example.com-cert.pem
│   │   ├── cacerts
│   │   │   └── ca.example.com-cert.pem
│   │   ├── keystore
│   │   │   └── cbd8cba235aafc20622a3056b153129a8dd7efea1a11c0b9b3d75cd94ea47ebd_sk
│   │   ├── signcerts
│   │   │   └── Admin@example.com-cert.pem
│   │   └── tlscacerts
│   │   └── tlsca.example.com-cert.pem
│   └── tls
│   ├── ca.crt
│   ├── client.crt
example.com의 비밀키와 인증서
[MSP] 관리자용 인증서
[MSP] CA식별 인증서
[MSP] TLS 통신용 인증서
orderer.example.com
example.com
상위 조직의 어드민 인증서와
CA 인증서를 복사
orderer.example.com의 비밀키와 인증서
각 노드의 HTTPS 통신용 인증서와 비밀키
각 사용자의의 HTTPS 통신용 인증서와 비밀키동일 파일
동일 파일
CA 살펴보기
Client -> sever request
Server send server.crt
Client verify server.crt with ca.crt(pub. Key included)
Client get public key of server
Client send encrypted message to server
Server decrypt message by its own private key(sercer.key)
server.key = 생성된 MSP의 개인키와 동일 파일
└── peerOrganizations
├── org1.example.com
│   ├── ca
│   │   ├── b6f3f5b3d200ec42cbbe11cff35d7d588b680a0fa10d650d99a7ef1b8470f855_sk
│   │   └── ca.org1.example.com-cert.pem
│   ├── msp
│   │   ├── admincerts
│   │   │   └── Admin@org1.example.com-cert.pem
│   │   ├── cacerts
│   │   │   └── ca.org1.example.com-cert.pem
│   │   ├── config.yaml
│   │   └── tlscacerts
│   │   └── tlsca.org1.example.com-cert.pem
│   ├── peers
│   │   ├── peer0.org1.example.com
│   │   │   ├── msp
│   │   │   │   ├── admincerts
│   │   │   │   │   └── Admin@org1.example.com-cert.pem
│   │   │   │   ├── cacerts
│   │   │   │   │   └── ca.org1.example.com-cert.pem
│   │   │   │   ├── config.yaml
│   │   │   │   ├── keystore
│   │   │   │   │   └── 81d0884d3094c1a56799c113a76a1ddb9989fda14d96e0f793d3e696f23dca2b_sk
│   │   │   │   ├── signcerts
│   │   │   │   │   └── peer0.org1.example.com-cert.pem
│   │   │   │   └── tlscacerts
│   │   │   │   └── tlsca.org1.example.com-cert.pem
│   │   │   └── tls
│   │   │   ├── ca.crt
│   │   │   ├── server.crt
│   │   │   └── server.key
│   │   └── peer1.org1.example.com
│   │   ├── msp
│   │   │   ├── admincerts
│   │   │   │   └── Admin@org1.example.com-cert.pem
│   │   │   ├── cacerts
│   │   │   │   └── ca.org1.example.com-cert.pem
│   │   │   ├── config.yaml
│   │   │   ├── keystore
│   │   │   │   └── dfc4d5a95b62a6fa6aa0a45f822d068139756b2b40e8b392173491e3f768f6f9_sk
│   │   │   ├── signcerts
│   │   │   │   └── peer1.org1.example.com-cert.pem
│   │   │   └── tlscacerts
│   │   │   └── tlsca.org1.example.com-cert.pem
│   │   └── tls
│   │   ├── ca.crt
│   │   ├── server.crt
│   │   └── server.key
org*.example.com
example.com
peer*.org*.example.com
└── users
│   ├── Admin@org1.example.com
│   │   ├── msp
│   │   │   ├── admincerts
│   │   │   │   └── Admin@org1.example.com-cert.pem
│   │   │   ├── cacerts
│   │   │   │   └── ca.org1.example.com-cert.pem
│   │   │   ├── keystore
│   │   │   │   └── 9e3ebb8985cc6f6c053297825d6bbef822f4c43ea5a7e7d277dd96be1f80e9ec_sk
│   │   │   ├── signcerts
│   │   │   │   └── Admin@org1.example.com-cert.pem
│   │   │   └── tlscacerts
│   │   │   └── tlsca.org1.example.com-cert.pem
│   │   └── tls
│   │   ├── ca.crt
│   │   ├── client.crt
│   │   └── client.key
│   └── User1@org1.example.com
│   ├── msp
│   │   ├── admincerts
│   │   │   └── User1@org1.example.com-cert.pem
│   │   ├── cacerts
│   │   │   └── ca.org1.example.com-cert.pem
│   │   ├── keystore
│   │   │   └── 0a9f665b540e722ea214dd280904f9a92cbac7b647b4853124174ecf2973c898_sk
│   │   ├── signcerts
│   │   │   └── User1@org1.example.com-cert.pem
│   │   └── tlscacerts
│   │   └── tlsca.org1.example.com-cert.pem
│   └── tls
│   ├── ca.crt
│   ├── client.crt
│   └── client.key
NodeOUs:
Enable: true
ClientOUIdentifier:
Certificate: cacerts/ca.org1.example.com-cert.pem
OrganizationalUnitIdentifier: client
PeerOUIdentifier:
Certificate: cacerts/ca.org1.example.com-cert.pem
OrganizationalUnitIdentifier: peer
CA 살펴보기
[참고] 인증서 살펴보기
root@fabric:/home/fabric/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/ca# openssl x509 -text -noout -in ca.example.com-cert.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
d9:d9:d3:61:6d:0d:28:6f:e2:5d:30:05:82:01:cd:38
Signature Algorithm: ecdsa-with-SHA256
Issuer: C = US, ST = California, L = San Francisco, O = example.com, CN = ca.example.com
Validity
Not Before: Mar 12 03:40:00 2020 GMT
Not After : Mar 10 03:40:00 2030 GMT
Subject: C = US, ST = California, L = San Francisco, O = example.com, CN = ca.example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:c1:e2:fd:33:bc:3d:b9:6b:1b:6a:da:5e:a0:36:
9a:dd:c2:23:9c:c8:7a:ec:b9:e7:54:c4:72:11:19:
85:33:1f:6a:62:e4:1d:c9:ae:e4:e0:2e:12:a0:5e:
7a:d6:c5:51:5c:70:21:29:27:5d:59:d0:17:2b:f9:
4c:0b:f6:9f:d4
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment, Certificate Sign, CRL Sign
X509v3 Extended Key Usage:
TLS Web Client Authentication, TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
A6:EE:42:3F:D2:81:13:DB:1A:12:3E:5D:57:75:92:43:BD:D8:C4:AE:8C:51:3D:86:28:F9:69:BD:B4:F7:37:0A
Signature Algorithm: ecdsa-with-SHA256
30:44:02:20:77:12:a9:2b:27:dd:7e:d7:a5:1f:f4:44:c2:00:
b5:e8:ff:b4:cf:07:aa:e4:e5:d2:68:0f:f3:f2:0b:6c:17:c4:
02:20:28:cc:a1:82:4b:e1:0c:38:fa:9e:e8:a9:62:27:29:16:
5a:20:e2:58:bb:b9:2d:ea:f9:f9:5f:a1:b8:c7:2e:e4
CA 살펴보기
[참고] hyperledger fabric ca 실습
! CA Server, Client 설치 및 실습
https://ovila.tistory.com/68
! Hyperledger Fabric 멀티호스트 환경 구축 
https://leejonggun.tistory.com/15
CA 살펴보기
peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls --cafile
~중략~/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
[채널 생성 요청] orderer에 생성 요청시 TLS 통신 사용하며
TLS인증서 위치를 지정함(tlsca.example.com-cert.pem)
CORE_PEER_MSPCONFIGPATH =~중략~/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE=~중략~/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
peer channel join -b mychannel.block
[채널 조인 요청]
CORE_PEER_MSPCONFIGPATH =~중략~/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE =~중략~/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CHANNEL_NAME=mychannel
peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile 
~중략~/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
[채널 업데이트 요청 ] orderer에 채널 업데이트 요청
org1의 peer0, peer1
org2의 peer0, peer1
방식 동일하게 모두 수행
/scripts/util.sh 의 setGlobals함수내
설정 코드 참조
전체 실행 순서 (1/5)
CA 살펴보기
cli컨테이너에서 수행하는 preface는 utils.sh에서 전달받은 파라미터에 따라
setGlobal함수내에서 재정의됨
peer lifecycle chaincode install mycc.tar.gz
[체인코드 인스톨]
peer lifecycle chaincode queryinstalled
[체인코드 설치확인] orderer를 통해 수행
Cli 컨테이너에서 수행, Org1-Peer0에 설치
peer lifecycle chaincode package mycc.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/abstore/go/ --lang golang --label mycc_1
[체인코드 패키징] peer를 통해 설치
각 org의 anchor peer에 설치

org1의 peer0
org2의 peer0
방식 동일하게 모두 수행
전체 실행 순서 (2/5)
CA 살펴보기
정상인 경우 패키징 고유번호 확인 가능
Package ID: mycc_1:0dcea8280752b53a2a534f280445e36fa4cb32f648c2d7729589821f300d74be, Label: mycc_1
peer lifecycle chaincode approveformyorg --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/
orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name mycc --version 1 --init-required --package-id
mycc_1:0dcea8280752b53a2a534f280445e36fa4cb32f648c2d7729589821f300d74be --sequence 1 --waitForEvent
[체인코드 승인] orderer를 통해 수행
예제에서는 Org1-Peer0 을 통해 승인 요청
전체 실행 순서 (3/5)
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name mycc --version 1 --sequence 1 --output json --init-required
[체인코드 커밋가능여부 확인]
예제에서는 Org1-Peer0 을 통해 승인(이전 장에서)했으므로
{
"approvals": {
"Org1MSP": true,
"Org2MSP": false
}
}
로 결과 출력
peer lifecycle chaincode approveformyorg -…
[체인코드 승인] orderer를 통해 수행
이제 Org2-Peer0 또한 승인 요청
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name mycc --version 1 --sequence 1 --output json --init-required
[체인코드 커밋가능여부 확인]
이제는 모두 커밋 true
{
"approvals": {
"Org1MSP": true,
"Org2MSP": true
}
}
로 결과 출력
peer lifecycle chaincode commit -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations
example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name mycc --peerAddresses
peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/
peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1 --sequence 1 --init-required
[체인코드 커밋] Org1 peer0, org2 peer0에 commit (anchor peer)
전체 실행 순서 (4/5)
peer lifecycle chaincode querycommitted --channelID mychannel --name mycc
[체인코드 커밋 성공여부 조회]
결과:
Committed chaincode definition for chaincode 'mycc' on channel 'mychannel':
Version: 1, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/
orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /op
gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses
peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/
peer0.org2.example.com/tls/ca.crt --isInit -c '{"Args":["Init","a","100","b","100"]}'
[체인코드 Invoke]
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
[체인코드 query]
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/
orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/
gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses
peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/
peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
[체인코드 Invoke]
A = 100
B = 100
A = ?
A에서 B로 10 이동
전체 실행 순서 (5/5)
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
[체인코드 Query] A == 90 ?
chaincode를 org2-peer1 에도 설치해서 조회해보자, 과연 같은 원장을 조회하여 A==90?
==================== Query successful on peer0.org1 on channel 'mychannel' =====================
Installing chaincode on peer1.org2...
peer lifecycle chaincode install mycc.tar.gz
===================== Querying on peer1.org2 on channel 'mychannel'... =====================
peer chaincode query -C mychannel -n mycc -c ‘{"Args":["query","a"]}'
90
org1, org2 에 모두 approve, commit 가능하므로 인스톨 후 바로 체인코드 조회 가능함
docker-compose 설정 파일 확인
docker-compose-cli.yaml의
base가 되는 base/docker-compose-base.yaml에서는
./byfn.sh generate를 통해 생성된 인증서 정보를 볼륨 마운트하고
마운트된 도커 이미지의 해당 디렉토리로 환경변수 설정을 함
docker-compose -f docker-compose-cli.yaml -f docker-compose-etcdraft2.yaml up -d
./byfn.sh up
===================== Chaincode is installed on peer0.org2 =====================
Instantiating chaincode on peer0.org2...
+ res=0
+ set +x
+ peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile 
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel 
-n mycc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('''Org1MSP.peer''','''Org2MSP.peer''')'
…. 생략 …
===================== Chaincode is instantiated on peer0.org2 on channel 'mychannel' =====================
Querying chaincode on peer0.org1...
===================== Querying on peer0.org1 on channel 'mychannel'... =====================
+ res=0
+ set +x
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Attempting to Query peer0.org1 ...3 secs
+ res=0
+ set +x
100
===================== Query successful on peer0.org1 on channel 'mychannel' =====================
Sending invoke transaction on peer0.org1 peer0.org2...
+ peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile 
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel 
-n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/
tls/ca.crt 
--peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
–c 
'{"Args":["invoke","a","b","10"]}'
2020-02-04 06:05:19.250 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
===================== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'mychannel' =====================
Installing chaincode on peer1.org2...
+ res=0
+ set +x
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
…. 생략 …
===================== Chaincode is installed on peer1.org2 =====================
Querying chaincode on peer1.org2...
===================== Querying on peer1.org2 on channel 'mychannel'... =====================
+ res=0
+ set +x
V1.4
docker-compose-cli 살펴보기
Org1의 Peer0인 피어에 접속하도록 환경변수가 설정됨
해당 피어에 채널 생성, 참가, 앵커 피어 갱신, 체인코드 설치/초기화/질의/호출을 수행한다.
(createChannel, joinChannel, updateAnchorPeers, packageChaincode, installChaincode, approveForMyOrg, checkCommitReadiness,
commitChaincodeDefinition, queryCommitted)
위의 수행함수는 byfn.sh의 networkUp함수내에서
docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE 로 호출됨
scripts.sh은 cli 도커에 볼륨 마운트됨으로 cli 에서 수행 가능함
chaincode lifecycle
https://hyperledger-fabric.readthedocs.io/en/release-2.0/chaincode_lifecycle.html#step-one-packaging-the-smart-contract
chaincode 위치 확인
environment:
- GOPATH=/opt/gopath
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
CC_SRC_PATH="github.com/hyperledger/fabric-samples/chaincode/abstore/go/"
peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH} >&log.txt
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v 1.0
-c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')
util.sh
script.sh
2개의 path를 조합하여 go 모듈을 실행
(go는 GOPATH/src 하위 폴더를 기준으로 프로젝트 경로를 잡는 규칙이 있음)
chaincode 살펴보기
./bynf.sh 에서 script.sh을 docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE
로 실행함. 즉, cli 도커에서 체인코드 install/instantiate를 수행함
체인코드를 수정
- invoke(stub shim.ChaincodeStubInterface, args []string) 함수에서

우측 그림과 같이 -10 을 추가
./byfn.sh down
./byfn.sh up
===================== Querying on peer1.org2 on channel 'mychannel'... =====================
+ res=0
+ set +x
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Attempting to Query peer1.org2 ...3 secs
+ res=0
+ set +x
80
!!!!!!!!!!!!!!! Query result on peer0.org1 is INVALID !!!!!!!!!!!!!!!!
================== ERROR !!! FAILED to execute End-2-End Scenario ==================
수행결과
util.sh의 chaincodeQuery함수에서
기대한 결과인 90을 충족하지 못하므로
에러로 표시하였으나,
체인코드를 수정한 의도와 부합하는 결과를 확인할 수 있음
docker-compose-cli.yaml에 cli 컨테이너 정의부분에
volumes:
../../chaincode/:/opt/gopath/src/github.com/chaincode
으로 변경한 체인코드를 그대로 cli 컨테이너에 볼륨 마운트하므로
도커를 시작하면 변경된 코드를 cli에서 install할 수 있음
couchdb 사용하기
! ./byfn.sh up -c mychannel -s couchdb
값 ’90’ 확인가능
couch db+fabric tutorial : https://hyperledger-fabric.readthedocs.io/en/release-1.4/couchdb_tutorial.html
4개의 couch db가 4개의 peer에 연결되는 구조로 컨테이너 기동
Virtual box port forwarding setting : inbound/outbound open 5984
Open db : ex> mychannel/mycc
[참고] block data (orderer)
docker cp -a orderer.example.com:/var/hyperledger/production/orderer ./
Docker-compose-base 에서
Volume create로 생성되었으므로 bind mount와는 다르게
운영체제>docker 전용 파일관리 영역에서 위와 같이 접근 가능하며
컨테이너간에도 사용가능하고 컨테이너가 종료되어도 사용가능함
[참고] block data (peer)
docker cp -a peer0.org1.example.com:/var/hyperledger/production ./
cd production/
more ledgersData/chains/chains/mychannel/blockfile_000000
chaincode docker devmode
사전 준비
! docker rm –f $(docker ps –a -q)
! 샘플예제가 있는 디렉토리로 이동(fabric-samples/chaincode-docker-devmode)
! 3개의 터미널을 오픈하여 상기 디렉토리로 이동
! docker-compose-simple.yaml 구성 확인

- orderer, peer, cli(체인코드 인스톨 및 인터랙션),
chaincode(체인코드 개발 환경) 컨테이너로 구성
cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
…중략…
working_dir: /opt/gopath/src/chaincodedev
command: /bin/bash -c './script.sh'
volumes:
…중략…
- ./../chaincode:/opt/gopath/src/chaincodedev/chaincode
- ./:/opt/gopath/src/chaincodedev/
chaincode:
container_name: chaincode
image: hyperledger/fabric-ccenv
tty: true
environment:
…중략…
- CORE_PEER_ADDRESS=peer:7051
…중략…
working_dir: /opt/gopath/src/chaincode
command: /bin/bash -c 'sleep 6000000'
volumes:
…중략…
- ./../chaincode:/opt/gopath/src/chaincode
source : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode
Terminal 1 - Start the network
! docker-compose -f docker-compose-simple.yaml up
source : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode
Terminal 2 - Build & start the
chaincode
! docker exec -it —user root chaincode sh
! cd abstore/go
! go build -o abstore
! CORE_CHAINCODE_ID_NAME=mycc:0 CORE_PEER_TLS_ENABLED=false ./abstore -peer.address peer:7052
source : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode
Normally chaincodes are started and maintained by peer. However in “dev mode",
chaincode is built and started by the user.
! BYFN 에서는 peer를 통해 시작/관리하고 cli 컨테이너에서 체인코드 설치 및 초기화를 하였으나,
본 예제에서는 사용자가 위 명령을 통해 체인코드를 먼저 실행 상태로 만든다.
docker-compose-simple.yaml 의 peer 컨테이너
Command 섹션에 —peer-chaincodedev = true 라고 설정됨
Terminal 3 - Use the chaincode
! docker exec -it cli bash
! peer chaincode install -p chaincodedev/chaincode/abstore/go -n mycc -v 0
! peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -C myc
! peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc
! peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc
source :https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode
source : https://nick-fabric.readthedocs.io/en/latest/commands/peerchaincode.html
여기까지는 Build Your First Network 체인코드와 동일하다.
이제 일부 코드를 추가하여 다시 배포해 보자.
terminal2 에서 chaincode를 실행하지 않으면 에러발생
local development env.
! 설치 후 터미널에서 go env 명령을 실행하여 GOPATH 경로를 확인
! GOPATH 경로 하단에 /go/src 디렉토리 생성
예>~iMac:src sf29$ pwd
/Users/sf29/go/src
! visual studio code 설치 + GO addon 추가 설치
! 우측 그림과 같이 $GOPATH/go/src 디렉토리에서
임의 go 파일 생성 및 테스트
사전에 GO 설치 필요
- https://golang.org/dl/
Visual studio
Go extension의 settings.jon 설정내용:
{
"go.formatTool": "goimports",
"go.useLanguageServer": true
}
local development env.
! visual studio code 에서 소스 추적 및 빌드 가능
! 개별 파일로 오픈 X, 폴더를 워크스페이로 추가해야 함(중요)
$GOROOT/src/ 에서 다음과 같이 hlf 라이브러리 추가
mkdir -p github.com/hyperledger
cd github.com/hyperledger/
git clone -b release-2.0 https://github.com/hyperledger/fabric.git
우측 그림의 소스는 $GOPATH/src/[임의 폴더명]/chiancode_example.go에 위치시킴
% pwd
/Users/hwang-won-yong/go/src/sacc
% go get
% go run sacc.go
상기 설정 이후 VS 재시작
—> 라이브러리에 밑 줄이 보이고, 해당 정의부로 이동도 가능하게 됨
chaincode download/upload via sftp
! ftp root access/login 허용
! Visual Studio Code에 ftp simple plugin 설치
! F1을 누른 다음  ftp-simple:Config - FTP connection setting 를 선택하고 우측

그림과 같이 편집
! F1을 누른 다음 tp-simple:Open - Open the file directly from FTP server를 선택

하고 localhost를 클릭하면 접속됨 (chaincode 디렉토리에서 abstore.go를 다운로드)
! 접속 이후 체인코드 클릭하여 편집창에서 오픈
! $GOPATHSRCabstore 폴더를 생성하고

해당 폴더 하위에 abstrore.go 파일로 save as… 한다. (소스 분석용)
visual studio code 플러그인 설치 출처 : https://www.manualfactory.net/10964
chaincode 수정
! 공식 튜토리얼을 참조하여 아래와 같이 수정
공식 튜토리얼 : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode
func (t *ABstore) Set(ctx contractapi.TransactionContextInterface, user string, value int) error {
fmt.Println("ABstore Set")
var A string
var Aval int
var err error
A = user
Aval = value
fmt.Printf("################### Aval = %d", Aval)
err = ctx.GetStub().PutState(A, []byte(strconv.Itoa(value)))
if err != nil {
return err
}
return nil
}
코드 수정 후 빌드 테스트 FTP upload (overwrite)
chaincode 배포 및 테스트
! docker-compose –f docker-compose-simple.yaml down
! docker-compose –f docker-compose-simple.yaml up
! 이전 terminal2, terminal3에서 수행했던 내용 동일 반복하고 코드에서 추가한 set 명령
에 대해 추가로 확인
peer chaincode install -p chaincodedev/chaincode/abstore/go -n mycc -v 0
peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -C myc
peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc
peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc
peer chaincode invoke -n mycc -c '{"Args":["Set","a","1000"]}' -C myc
peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc
ABstore Init
Aval = 100, Bval = 200
Aval = 90, Bval = 210
Query Response:{"Name":"a","Amount":"90"}
ABstore Set
################### Aval = 1000
Query Response:{“Name":"a","Amount":"1000"}
terminal2 terminal3
[참고] peer chaincode upgrade
! 모든 컨테이너 기동 상태에서 체인코드 업그레이드 실시
! VS CODE 에서 소스 변경 및 저장/업로드
terminal2
docker exec -it --user root chaincode sh
go build -o abstore
CORE_CHAINCODE_ID_NAME=mycc:1 CORE_PEER_TLS_ENABLED=false ./abstore -peer.address peer:7052
terminal3
peer chaincode install -p chaincodedev/chaincode/abstore/go -n mycc -v 1
peer chaincode upgrade -p chaincode/abstore/go -n mycc -v 1 -C myc -c '{"Args":["init","a","100","b","200"]}'
peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc
peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc
peer chaincode invoke -n mycc -c '{"Args":["Set","a","1000"]}' -C myc
소스 수정 -> 로컬 빌드 -> FTP 업로드
새로운 terminal을 띄워서 위 terminal2의 내용을 수행함
기존 terminal2는 업그레이드 완료시 peer에 대한 응답을 더 이상 하지 않게 됨
chaincode tutorial
Chaincode tutorial (Basic)
https://hyperledger-fabric.readthedocs.io/en/release-2.0/chaincode4ade.html#
HW
build & deploy
Add or modify chain code + build/deploy
Chaincode tutorial (Advance)
! Code review
! Build and deploy
- ftp upload (to newly created directory. Eg> saccnew)
- [Terminal 2] go get
- [Terminal 2] go build -o saccnew
- [Terminal 2] CORE_CHAINCODE_ID_NAME=mycc:0 CORE_PEER_TLS_ENABLED=false ./saccnew -peer.address peer:7052
! Chaincode install/run on Terminal 3
- go get github.com/hyperledger/fabric-chaincode-go/shim
Git hub : https://github.com/wonyongHwang/chaincode-tutorial/blob/master/kopoChainCode.go
peer chaincode install -p chaincodedev/chaincode/saccnew -n mycc -v 0
peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -C myc
peer chaincode invoke -n mycc -c '{"Args":["more","tt","Here your are, this is a book 2","1200"]}' -C myc
peer chaincode query -n mycc -c '{"Args":["morequery","tt"]}' -C myc
Chaincode tutorial (Advance)
PutState func (t *SimpleChaincode) more(stub shim.ChaincodeStubInterface, param []string) pb.Response {
if len(param) != 3 {
return shim.Error("# of parameter mismatching")
}
title, text, code := param[0], param[1], param[2]
codeNum, err := strconv.ParseInt(code, 10, 32)
if err != nil {
return shim.Error("code error")
}
if len(title) == 0 || len(text) == 0 || len(code) == 0 {
return shim.Error("value of paramter is not properly formatted")
}
// make my data of AdditionalInfo
addInfo := &AdditionalInfo{Title: title, Text: text, code: codeNum}
addInfoBytes, err := json.Marshal(addInfo)
if err != nil {
return shim.Error("failed to convert bytes " + err.Error())
}
err = stub.PutState(title, addInfoBytes) // key value에 공백 들어가면 조회시 값을 찾지 못함
if err != nil {
return shim.Error("PutState failure " + err.Error())
}
type AdditionalInfo struct {
Title string "json:"title""
Text string "json:"text""
code int64 "json:"code""
}
Chaincode tutorial (Advance)
- GetState, GetHistoryForKey
func (t *SimpleChaincode) morequery(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entities
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
A = args[0]
// Get the state from the ledger
valbytes, err := stub.GetState(A)
if err != nil {
jsonResp := "{"Error":"Failed to get state for " + A + ""}"
return shim.Error(jsonResp)
}
valueStr := &AdditionalInfo{}
err = json.Unmarshal(valbytes, &valueStr)
if err != nil {
jsonResp := "{"Error":"Failed to Unmarshal " + A + ""}"
return shim.Error(jsonResp)
}
jsonResp := "{"Title":"" + A + "","Text":"" + string(valueStr.Text) + ""}"
fmt.Printf("Query Response:%sn", jsonResp)
// history
iter, _ := stub.GetHistoryForKey(A)
fmt.Println("Here is History for " + A)
for iter.HasNext() {
kv, _ := iter.Next()
fmt.Println(string(kv.GetValue()) + " " + kv.GetTimestamp().String())
}
return shim.Success([]byte(string(valueStr.code)))
}
GetHistoryForKey 함수로 변경 이력 조회
기존에 변경된 이력이 있는 경우
모두 조회 가능
[참고] 공식 튜토리얼 체인코드에서…
source : https://hyperledger-fabric.readthedocs.io/en/release-2.0/chaincode4ade.html#chaincode-api
main 함수에서 fabric chaincode의 Start 함수를 호출
이 때 전달되는 파라미터는 type SimpleAsset struct{} 의
객체임. 소스코드상 SimpleAsset의 Init,Invoke 함수를
구현하였으므로 ChainCode 객체로 전달 가능
[참고] 체인코드 호출
! 동일 채널에서 같은/다른 Chaincode 호출(invoke/query) 가능
! 다른 채널의 chaincode는 조회(query)만 가능
-예시-
channel := stub.GetChannelID()
stub.InvokeChaincode(chaincodeName, args, channel)
Hyperledger fabric SDK
Balance transfer example (개요)
! 2 CA, 1 Orderer, 2Org (2 Peers on each Org.) 로 구성
! 기본적으로는 Build Your Network First와 유사한 구조이나, 여기서는 cli 컨테이너가 없음.
대신 Hyperledger fabric SDK를 이용한 node.js구현체를 통해서 채널생성, 체인코드 설치 등을
진행하게 됨.
! Build Your Network First의 기본 실행 구조에서는 CA 서버 없이 cryptogen을 통해 미리 생성해 놓은
인증서를 사용하여 통신 하였으나, 이번 예제는 미리 생성한 인증서 정보를 토대로 CA서버를 기동하고,
Node.js Client에서 요청하는 사용자 등록을 CA 서버에서 인증하고 처리하도록 구성 되었음
(org1 -> ca1, org2 -> ca2_
* 해당 예제 폴더에 위치한 ~e2e.yaml 로 실행시 ca 서버 기동됨
Balance transfer example (실행 준비)
! 노드 버전 확인(node -v)
balance transfer 예제는 노드 버전 10.x 이상에서 오류 발생 -> 8.* 또는 9.* 설치
기존 node.js 삭제시 : apt-get --purge remove nodejs
node.js 설치 : curl -sL http://deb.nodesource.com/setup_9.x | bash -
apt-get install node.js
* 해당 예제는 fabric 2.0 기본 샘플예제에서 삭제되었으나 2.0이 1.4의 SDK도 지원하므로 정상 실행 가능함
! 컨테이너 및 이미지 등 도커관련 파일 삭제 (충돌방지)
docker rm -f $(docker ps -a -q)
docker rmi -f $(docker images -a -q)
docker volume prune
docker system prune
docker network prune
git clone -b release-1.4 https://github.com/hyperledger/fabric-samples.git
Balance transfer example (fabric 실행)
! ./runApp.sh 실행
Balance transfer example (REST 호출)
./testAPIs.sh 을 실행하여 사용자 등록~체인코드 실행까지 정상 진행 되는지 확인
* chaincode instantiate 실행시 time out 으로 오류발생되는 경우,
아래 그림과 같이 testAPIs.sh의 일부분을 수정 (timeout 옵션 추가)
apt-get install jq 필요
[심화] 더 살펴볼 포인트
! ./testAPIs.sh 의 REST CALL 호출 순서와 내용을 확인
! Node 소스는 app.js가 시작점
! 사용자 등록을 위해 /users 호출시에는 fabric ca server를 통해 신규 사용자 등록을 하고 토큰을 부여함
! /users 이외의 호출 주소는 JWT 토큰 유효성 검사가 이루어짐
! Proposal을 먼저 endorsing peer에 보내고, 해당 피어에서 사전
검증한 결과를 확인하고 orderer에게 검증결과와 트랜잭션
반영요청을 하는 부분
—> invoke-tansaction.js의 sendTransactionProposal 및
sendTransaction 호출 코드 참조

[심화] sdk를 이용한 사용자 등록 과정
! 기 발급받은 인증서를 이용
!
app.post('/users', async function(req, res) {
…
let response = await helper.getRegisteredUser(username, orgName, true);
…}
app.js
Network-config.yaml과 org1.yaml 설정파일을 로딩하여
initCredential을 수행
등록된 사용자 없는 경우;
config.json의 admin/adminpw 계정정보를 이용해
새로운 사용자를 등록(getCertificateAuthority로 인증서 로딩)
[심화] fabric ca container
Node sdk client의 config.js에 설정된 계정정보와 일치해야 함
"admins":[
{
"username":"admin",
"secret":"adminpw"
}
]
fabric server <-> node.js(SDK) local
Fabric Server(Docker/Ubuntu/VM) Fabric SDK(local)
Client(local)
Fabric SDK를 로컬 개발환경에서
디버깅을 통해 분석해 보자.
fabric server <-> node.js(SDK) local
사전 준비사항
- local pc
visual studio code 설치
nvm 설치(https://gofnrk.tistory.com/32)
balance transfer 예제 local 복사 + npm rebuild
virtual box 포트 오픈
(유저 등록을 위해서 ca 서버 접속필요—> 7054 포트 연결 설정)
(체인코드 실행 및 쿼리 등을 위해서 오더러(7050) 등 필요시 추가로 포트 연결 설정해야 함)
- 수행 순서
fabric server 기동(./runApp.sh) -> 로컬에서 node 실행해야 하므로 서버측에서는 node 실행부분 주석처리
local의 balance transfer 예제 폴더 중 인증토큰과 관련된 폴더 삭제
rm -rf fabric-client-kv-org*
REST 호출 수행
hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST 
http://localhost:4000/users 
-H "content-type: application/x-www-form-urlencoded" 
-d 'username=Jim&orgName=Org1'
{"success":true,"secret":"","message":"Jim enrolled
Successfully","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjU1NjMsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxODk1NjN9.h2v6HzQJdDSUryGEsqPyUbV9SK91GGgTF4_7LCzg
"}%
사용자 등록 For mac>
Brew install jq
fabric server <-> node.js(SDK) local
—> 로컬에서 node.js 디버깅을 visual studio로 진행
hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST 
http://localhost:4000/channels 
-H "authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4v
cQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0" 
-H "content-type: application/json" 
-d '{
"channelName":"mychannel",
"channelConfigPath":"../artifacts/channel/mychannel.tx"
}'
{"success":true,"message":"Channel 'mychannel' created Successfully"}%
hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST 
http://localhost:4000/channels/mychannel/peers 
-H "authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4v
cQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0" 
-H "content-type: application/json" 
-d '{
"peers": ["peer0.org1.example.com","peer1.org1.example.com"]
}'
{"success":true,"message":"Successfully joined peers in organization Org1 to the channel:mychannel"}
Create channel을 위해서 오더러에 해당하는
7050 포트 설정 필요
Join channel을 위해서 피어에 해당하는
7051와 7056 포트 설정 필요
fabric server <-> node.js(SDK) local
hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST 
http://localhost:4000/channels/mychannel/anchorpeers 
-H "authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4v
cQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0" 
-H "content-type: application/json" 
-d '{
"configUpdatePath":"../artifacts/channel/Org1MSPanchors.tx"
}'
{"success":true,"message":"Successfully update anchor peers in organization Org1 to the channel 'mychannel'"}%
fabric server <-> node.js(SDK) local
Anchor Peer Update
hwang-won-yong@hwang-won-yong-ui-MacBookPro node % curl -s -X POST 
http://localhost:4000/chaincodes 
-H "authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4vcQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0"

-H "content-type: application/json" 
-d "{
"peers": ["peer0.org1.example.com","peer1.org1.example.com"],
"chaincodeName":"mycc",
"chaincodePath":"/github.com/example_cc/node",
"chaincodeType": "golang",
"chaincodeVersion":"v0"
}"
{"success":true,"message":"Successfully installed chaincode"}%
Install Chaincode
—> 나머지 REST Call도 필요시 포트 설정해가면서 테스트 및 디버깅 진행~
[참고] Mac - nvm 설치 (1/2)
! 본 예제는 node 8.x 에서 정상 수행 가능(node 10.x 는 tls 관련 오류 발생)
기존에 이미 설치한 노드 삭제
/usr/local/lib 에 있는 node와 node_modules를 삭제
/usr/local/include 에 있는 node와 node_modules를 삭제
Homebrew로 설치하셨다면, brew uninstall node를 실행
~/local 또는 ~/lib 또는 ~/include 디렉토리 밑에 존재하는 node와 node_modules 삭제
/usr/local/bin 에 있는 node 관련 실행파일들 삭제
추가로, 필요에 따라 아래 명령어들을 실행하시면 됩니다.
sudo rm /usr/local/bin/npm
sudo rm /usr/local/share/man/man1/node.1
sudo rm /usr/local/lib/dtrace/node.d
sudo rm -rf ~/.npm
sudo rm -rf ~/.node-gyp
sudo rm /opt/local/bin/node
sudo rm /opt/local/include/node
sudo rm -rf /opt/local/lib/node_modules
(출처 : http://junsikshim.github.io/2016/01/29/Mac%EC%97%90%EC%84%9C-Node.js-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0.html)
! Nvm 설치 (일반 계정, not root)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
source ~/.bash_profile
설치 후 .bash_profile 에 nvm관련 설정 수동 추가
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # This loads nvm bash_completion
[참고] Mac - nvm 설치 (2/2)
! Visual Studio CODE 에서 디버깅시 기존에 설치되었던 node를 찾을 수 없으므로
아래와 같이 launch.json에 node의 위치를 설정해야 함
(which node로 찾은 경로를 기입)
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/app.js"
"runtimeExecutable": "/Users/sf29/.nvm/versions/node/v8.17.0/bin/node"
}
]
}
[참고] port forwarding…
Visual Studio Code +
IBM BlockChain Platform
Install extension
Check dependencies
! VS Code version 1.38.0 or higher (code —version)
! Node v8.x or v10.x and npm v6.x or greater
node —version
npm —version
! Go version V1.12 or greater
go version
! Docker version v17.06.02-ce or greater
docker —version
! Docker Compose v1.14.0 or greater
docker-compose —version
nvm을 사용 중인 경우 사용할 노드 버전을 alias 설정하여
default나 global로 네이밍 해줘야 함
Let’s Test (1/4)
기본 체인코드를 확인한다.
기본 동작을 확인하기 위해 별도 코딩은 없이 진행한다.
Fabric Environments 섹션에 최상단 1 Org를 클릭하면
로컬환경에서 도커가 실행되고 fabric peer/orderer/ca 등이 실행된다.
이전 장에서 패키징한 체인코드를 인스톨 -> 인스턴스화 한다.
Let’s Test (2/4)
Fabric Gateways 섹션에서 mychannel을 확장하면
이전 장에서 인스턴스화에 성공한 스마트 컨트랙트가 보인다.
우측 마우스 버튼을 클릭하여 컨텍스트 메뉴를 열어서
Submit Transaction을 선택한다.
상단에서 함수명과 파라미터를 입력하는 창이 오픈될 때,
임의의 함수명(queryTest)과 임의의 파라미터([“query”,”eee”])를 입력한다.
체인코드가 실행되는 도커 컨테이너를 클릭하면
아래와 같이 위에서 입력한 함수명과 파라미터의 정상 출력을 확인 할 수 있음
- 체인코드에서 fmt.Println("Invoke()", fcn, params) 에 해당되는 부분
Let’s Test (3/4)
도커 컨테이너 정지
STOP
Let’s Test (4/4)
[practice] KopoVote
Git address : https://github.com/wonyongHwang/kopoVote.git
Overall Architecture
Node.js
Docker
runApp.sh로 구동
- docker run
prepareFabric.sh로
사용자 등록/채널 생성/체인코드 인스톨
Vue.js
Backend
VM
Frontend
Chaincode
invoke/query
! Balance Transfer를 활용한 블록체인 투표 시스템
Preparation
! Balance-Transfer example was built on SDK v1.4
! But at the fabric 2.0, we should use SDK v2.0
! Work around
1) remove docker images of ccenv 2.x and reinstall ccenv 1.4
docker pull hyperledger/fabric-ccenv:1.4
https://jira.hyperledger.org/browse/FABN-1357
Preview (KopoVote)
Frontend source reference : https://github.com/IBM/evote
https://www.youtube.com/watch?v=r6bnpPPif5E&t=10s
Local chaincode develop environment setup
! 1. VS CODE -> IBM BlockChain -> Create New Project
! 2 .프로젝트 저장 위치는 $GOPATH/src/ 하위에 임의 폴더명으로 위치시켜야 함
! 3. 테스트를 위해 IBM BlockChain 에서 Package Open Project -> Install -
Instantiate -> Fabric GateWay에서 admin role로 채널 생성
여기까지 문제 없으면 Good
! 4. Chaincode.go 파일의 내용을 우리가 원하는 투표 기록용 코드로 변경
! 5. 3번 다시 수행(Instantiate와 테스트 방법은 아래 참조)
Instantiate : Init -> [“A”,”100”,”B”,”100”]
Fabric G/W > Submit Tx : query -> [“A”]
> Evaluate Tx : query ->[“A”]
Chaincode
투표 항목 3개(A, B, C)에 대해
Init 함수를 통해 초기값 0으로 설정하고
vote함수를 통해 각 투표항목에 대해 +1을 기록하도록 함
Packaging project
Install Chaincode
Instantiate Chaincode
Invoke Chaincode
Query Chaincode
Upgrade Chaincode ! 체인코드 업그레이드 배포시 Init 함수를 호출하게 됨
-> Init 함수내 초기화 로직을 최초 배포시와 업그레이드시 2가지 모두 고려해야 함
Commit Chaincode
! Upload chaincode(chaincode.go & main.go) to servers(fabric server, node.js server)
Commit Chaincode
! 체인코드에서 필요한 최신 라이브러리 go get 명령어 추가(base.yaml)
command: >
sh -c "peer node start
&& go get github.com/hyperledger/fabric-chaincode-go/shim
&& go get github.com/hyperledger/fabric-protos-go/peer"
Prepare shell script for booting up
! POST request Enroll on Org1/Org2
! POST request Create channel …
! POST request Join channel on Org1/Org2
! POST request Update anchor peers on Org1/Org2
! POST Install chaincode on Org1/Org2
! POST instantiate chaincode on Org1
Frontend coding
! Vote
! queryAll
Source reference : https://github.com/IBM/evote
Frontend coding
! REST Call using Axios
사용자 등록
투표(invoke)
결과 조회(query)
Source reference : https://github.com/IBM/evote
Frontend coding
! 인증 토큰 처리
사용자 등록시 응답으로
받은 토큰을 저장하고 이를
투표화면으로 파라미터 전달
Source reference : https://github.com/IBM/evote
Frontend coding
! 인증 토큰 처리
이전 화면에서 파라미터로
전달한 토큰을 저장
토큰과 사용자가 선택한
투표 결과를 서버로 전달
서버에서 정상 응답인 경우,
투표조회 결과 화면으로 이동
(토큰을 파라미터로 전달)
Source reference : https://github.com/IBM/evote
Frontend coding
! 인증 토큰 처리
이전 화면에서 파라미터로
전달한 토큰을 저장
Fabric runtime에 query
(w/ auth. Token)
결과를 그래프로 표현서버의 chaincode 중
Query 응답 부분
Source reference : https://github.com/IBM/evote
Todo
! 사용자 데이터베이스 구축 및 인증 로직
! 원장에 투표한 사용자 기록 및 조회 (이중 투표 방지 목적)
! 투표 조직(org1)과 검증 조직(org2)의 분리
Git address : https://github.com/wonyongHwang/kopoVote.git
Source reference : https://github.com/IBM/evote
This doesn’t work well but it should be
okay.
! 체인코드 변경 (library hierarchy changed on fabric 2.0)
! GOPATH 설정 및 체인코드 라이브러리 설치
- 설정 후 source /etc/profile 실행
- go get
- go build
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
import (
"fmt"
"strconv"
“github.com/hyperledger/fabric-chaincode-go/shim"
pb "github.com/hyperledger/fabric-protos-go/peer"
)
export GOROOT=/usr/local/go
export GOPATH=$HOME
export GOBIN=$GOPATH/bin
export FABRIC_HOME=/root/fabric-samples
export PATH=$PATH:$GOROOT/bin:$FABRIC_HOME/bin
Thanks…
wyhwang@kopo.ac.kr
멀티 노드에서 하이퍼레저 패브릭 네트워크 구성하기 (1/3)
(Hyperledger Korea User Group https://github.com/hlkug/meetup/tree/master/201903)
! BYFN 예제를 기본으로 멀티 노드를 구성하는 방법을 익힌다.
! 사전 작업
- Virtual Box, Ubuntu, Docker, Docker-Compose, HLF 등 기본 설치
- 2 nodes 이므로 각 VM의 네트워크는 기본 NAT + 호스트 전용 어댑터이며, 각 호스트 정보 IP를 별도 설정해야 함
멀티 노드에서 하이퍼레저 패브릭 네트워크 구성하기 (2/3)
(Hyperledger Korea User Group https://github.com/hlkug/meetup/tree/master/201903)
멀티 노드에서 하이퍼레저 패브릭 네트워크 구성하기 (3/3)
(Hyperledger Korea User Group https://github.com/hlkug/meetup/tree/master/201903)
이후 진행은 BYFN과 유사함.
예제의 전체소스는 상단의 링크주소를 참조.

More Related Content

What's hot

The Zen of High Performance Messaging with NATS
The Zen of High Performance Messaging with NATS The Zen of High Performance Messaging with NATS
The Zen of High Performance Messaging with NATS NATS
 
Simplifying Your IT Workflow with Katello and Foreman
Simplifying Your IT Workflow with Katello and ForemanSimplifying Your IT Workflow with Katello and Foreman
Simplifying Your IT Workflow with Katello and ForemanNikhil Kathole
 
Docker 101: Introduction to Docker
Docker 101: Introduction to DockerDocker 101: Introduction to Docker
Docker 101: Introduction to DockerDocker, Inc.
 
Kubernetes Networking
Kubernetes NetworkingKubernetes Networking
Kubernetes NetworkingCJ Cullen
 
[KubeCon EU 2020] containerd Deep Dive
[KubeCon EU 2020] containerd Deep Dive[KubeCon EU 2020] containerd Deep Dive
[KubeCon EU 2020] containerd Deep DiveAkihiro Suda
 
Kubernetes Introduction
Kubernetes IntroductionKubernetes Introduction
Kubernetes IntroductionPeng Xiao
 
Shodan- That Device Search Engine
Shodan- That Device Search EngineShodan- That Device Search Engine
Shodan- That Device Search EngineInMobi Technology
 
Head First to Container&Kubernetes
Head First to Container&KubernetesHead First to Container&Kubernetes
Head First to Container&KubernetesHungWei Chiu
 
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기Hyperledger Korea User Group
 
Kafka Tutorial: Kafka Security
Kafka Tutorial: Kafka SecurityKafka Tutorial: Kafka Security
Kafka Tutorial: Kafka SecurityJean-Paul Azar
 
Packet Walk(s) In Kubernetes
Packet Walk(s) In KubernetesPacket Walk(s) In Kubernetes
Packet Walk(s) In KubernetesDon Jayakody
 
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2InfraEngineer
 
How to Prepare for CKA Exam
How to Prepare for CKA ExamHow to Prepare for CKA Exam
How to Prepare for CKA ExamAlfie Chen
 
Traffic Control with Envoy Proxy
Traffic Control with Envoy ProxyTraffic Control with Envoy Proxy
Traffic Control with Envoy ProxyMark McBride
 
Kubernetes internals (Kubernetes 해부하기)
Kubernetes internals (Kubernetes 해부하기)Kubernetes internals (Kubernetes 해부하기)
Kubernetes internals (Kubernetes 해부하기)DongHyeon Kim
 
Docker Networking with New Ipvlan and Macvlan Drivers
Docker Networking with New Ipvlan and Macvlan DriversDocker Networking with New Ipvlan and Macvlan Drivers
Docker Networking with New Ipvlan and Macvlan DriversBrent Salisbury
 
Kubernetes Probes (Liveness, Readyness, Startup) Introduction
Kubernetes Probes (Liveness, Readyness, Startup) IntroductionKubernetes Probes (Liveness, Readyness, Startup) Introduction
Kubernetes Probes (Liveness, Readyness, Startup) IntroductionAkhmadZakiAlsafi
 
Introduction to Docker Compose
Introduction to Docker ComposeIntroduction to Docker Compose
Introduction to Docker ComposeAjeet Singh Raina
 
OpenId Connect Protocol
OpenId Connect ProtocolOpenId Connect Protocol
OpenId Connect ProtocolMichael Furman
 

What's hot (20)

The Zen of High Performance Messaging with NATS
The Zen of High Performance Messaging with NATS The Zen of High Performance Messaging with NATS
The Zen of High Performance Messaging with NATS
 
Simplifying Your IT Workflow with Katello and Foreman
Simplifying Your IT Workflow with Katello and ForemanSimplifying Your IT Workflow with Katello and Foreman
Simplifying Your IT Workflow with Katello and Foreman
 
Docker 101: Introduction to Docker
Docker 101: Introduction to DockerDocker 101: Introduction to Docker
Docker 101: Introduction to Docker
 
Kubernetes Networking
Kubernetes NetworkingKubernetes Networking
Kubernetes Networking
 
[KubeCon EU 2020] containerd Deep Dive
[KubeCon EU 2020] containerd Deep Dive[KubeCon EU 2020] containerd Deep Dive
[KubeCon EU 2020] containerd Deep Dive
 
Kubernetes Introduction
Kubernetes IntroductionKubernetes Introduction
Kubernetes Introduction
 
Shodan- That Device Search Engine
Shodan- That Device Search EngineShodan- That Device Search Engine
Shodan- That Device Search Engine
 
Head First to Container&Kubernetes
Head First to Container&KubernetesHead First to Container&Kubernetes
Head First to Container&Kubernetes
 
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
[2019.04] 쿠버네티스 기반 하이퍼레저 패브릭 네트워크 구축하기
 
Kafka Tutorial: Kafka Security
Kafka Tutorial: Kafka SecurityKafka Tutorial: Kafka Security
Kafka Tutorial: Kafka Security
 
Packet Walk(s) In Kubernetes
Packet Walk(s) In KubernetesPacket Walk(s) In Kubernetes
Packet Walk(s) In Kubernetes
 
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
[MeetUp][2nd] 오리뎅이의_쿠버네티스_네트워킹_v1.2
 
How to Prepare for CKA Exam
How to Prepare for CKA ExamHow to Prepare for CKA Exam
How to Prepare for CKA Exam
 
Docker Introduction
Docker IntroductionDocker Introduction
Docker Introduction
 
Traffic Control with Envoy Proxy
Traffic Control with Envoy ProxyTraffic Control with Envoy Proxy
Traffic Control with Envoy Proxy
 
Kubernetes internals (Kubernetes 해부하기)
Kubernetes internals (Kubernetes 해부하기)Kubernetes internals (Kubernetes 해부하기)
Kubernetes internals (Kubernetes 해부하기)
 
Docker Networking with New Ipvlan and Macvlan Drivers
Docker Networking with New Ipvlan and Macvlan DriversDocker Networking with New Ipvlan and Macvlan Drivers
Docker Networking with New Ipvlan and Macvlan Drivers
 
Kubernetes Probes (Liveness, Readyness, Startup) Introduction
Kubernetes Probes (Liveness, Readyness, Startup) IntroductionKubernetes Probes (Liveness, Readyness, Startup) Introduction
Kubernetes Probes (Liveness, Readyness, Startup) Introduction
 
Introduction to Docker Compose
Introduction to Docker ComposeIntroduction to Docker Compose
Introduction to Docker Compose
 
OpenId Connect Protocol
OpenId Connect ProtocolOpenId Connect Protocol
OpenId Connect Protocol
 

Similar to Hyperledger Fabric practice (v2.0)

Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)wonyong hwang
 
20141029 하둡2.5와 hive설치 및 예제
20141029 하둡2.5와 hive설치 및 예제20141029 하둡2.5와 hive설치 및 예제
20141029 하둡2.5와 hive설치 및 예제Tae Young Lee
 
1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기
1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기
1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기Hyperledger Korea User Group
 
하이퍼레저 패브릭 데이터 구조
하이퍼레저 패브릭 데이터 구조하이퍼레저 패브릭 데이터 구조
하이퍼레저 패브릭 데이터 구조Logpresso
 
[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1Ji-Woong Choi
 
PCF Installation Guide
PCF Installation GuidePCF Installation Guide
PCF Installation Guideseungdon Choi
 
Deploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptxDeploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptxwonyong hwang
 
도커없이 컨테이너 만들기 1편
도커없이 컨테이너 만들기 1편도커없이 컨테이너 만들기 1편
도커없이 컨테이너 만들기 1편Sam Kim
 
Linux Kernel Boot Process , SOSCON 2015, By Mario Cho
Linux Kernel Boot Process , SOSCON 2015, By Mario ChoLinux Kernel Boot Process , SOSCON 2015, By Mario Cho
Linux Kernel Boot Process , SOSCON 2015, By Mario ChoMario Cho
 
Internship backend
Internship backendInternship backend
Internship backendYein Sim
 
Apache Tomcat ( 아파치 톰캣 ) 설치 가이드
Apache Tomcat ( 아파치 톰캣 ) 설치 가이드Apache Tomcat ( 아파치 톰캣 ) 설치 가이드
Apache Tomcat ( 아파치 톰캣 ) 설치 가이드Opennaru, inc.
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02정출 김
 
Puppet과 자동화된 시스템 관리
Puppet과 자동화된 시스템 관리Puppet과 자동화된 시스템 관리
Puppet과 자동화된 시스템 관리Keon Ahn
 
Build the OpenStack Cloud with Neutron Networing, IceHouse
Build the OpenStack Cloud with Neutron Networing, IceHouseBuild the OpenStack Cloud with Neutron Networing, IceHouse
Build the OpenStack Cloud with Neutron Networing, IceHousejieun kim
 
oVirt installation guide_v4.3
oVirt installation guide_v4.3oVirt installation guide_v4.3
oVirt installation guide_v4.3CheolHee Han
 
Tensorflow service & Machine Learning
Tensorflow service & Machine LearningTensorflow service & Machine Learning
Tensorflow service & Machine LearningJEEHYUN PAIK
 
개발사는 모르는 퍼블리셔의 뒷 이야기
개발사는 모르는 퍼블리셔의 뒷 이야기개발사는 모르는 퍼블리셔의 뒷 이야기
개발사는 모르는 퍼블리셔의 뒷 이야기David Kim
 
Nginx basic configurations
Nginx basic configurationsNginx basic configurations
Nginx basic configurationsJohn Kim
 

Similar to Hyperledger Fabric practice (v2.0) (20)

Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)Hyperledger fabric practice(pdf)
Hyperledger fabric practice(pdf)
 
20141029 하둡2.5와 hive설치 및 예제
20141029 하둡2.5와 hive설치 및 예제20141029 하둡2.5와 hive설치 및 예제
20141029 하둡2.5와 hive설치 및 예제
 
Kafka slideshare
Kafka   slideshareKafka   slideshare
Kafka slideshare
 
1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기
1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기
1908 Hyperledger Fabric 소개 및 첫 네트워크 구축하기
 
하이퍼레저 패브릭 데이터 구조
하이퍼레저 패브릭 데이터 구조하이퍼레저 패브릭 데이터 구조
하이퍼레저 패브릭 데이터 구조
 
[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1
 
PCF Installation Guide
PCF Installation GuidePCF Installation Guide
PCF Installation Guide
 
Deploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptxDeploying Hyperledger Fabric on Kubernetes.pptx
Deploying Hyperledger Fabric on Kubernetes.pptx
 
도커없이 컨테이너 만들기 1편
도커없이 컨테이너 만들기 1편도커없이 컨테이너 만들기 1편
도커없이 컨테이너 만들기 1편
 
Linux Kernel Boot Process , SOSCON 2015, By Mario Cho
Linux Kernel Boot Process , SOSCON 2015, By Mario ChoLinux Kernel Boot Process , SOSCON 2015, By Mario Cho
Linux Kernel Boot Process , SOSCON 2015, By Mario Cho
 
KAFKA 3.1.0.pdf
KAFKA 3.1.0.pdfKAFKA 3.1.0.pdf
KAFKA 3.1.0.pdf
 
Internship backend
Internship backendInternship backend
Internship backend
 
Apache Tomcat ( 아파치 톰캣 ) 설치 가이드
Apache Tomcat ( 아파치 톰캣 ) 설치 가이드Apache Tomcat ( 아파치 톰캣 ) 설치 가이드
Apache Tomcat ( 아파치 톰캣 ) 설치 가이드
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02
 
Puppet과 자동화된 시스템 관리
Puppet과 자동화된 시스템 관리Puppet과 자동화된 시스템 관리
Puppet과 자동화된 시스템 관리
 
Build the OpenStack Cloud with Neutron Networing, IceHouse
Build the OpenStack Cloud with Neutron Networing, IceHouseBuild the OpenStack Cloud with Neutron Networing, IceHouse
Build the OpenStack Cloud with Neutron Networing, IceHouse
 
oVirt installation guide_v4.3
oVirt installation guide_v4.3oVirt installation guide_v4.3
oVirt installation guide_v4.3
 
Tensorflow service & Machine Learning
Tensorflow service & Machine LearningTensorflow service & Machine Learning
Tensorflow service & Machine Learning
 
개발사는 모르는 퍼블리셔의 뒷 이야기
개발사는 모르는 퍼블리셔의 뒷 이야기개발사는 모르는 퍼블리셔의 뒷 이야기
개발사는 모르는 퍼블리셔의 뒷 이야기
 
Nginx basic configurations
Nginx basic configurationsNginx basic configurations
Nginx basic configurations
 

More from wonyong hwang

Hyperledger Explorer.pptx
Hyperledger Explorer.pptxHyperledger Explorer.pptx
Hyperledger Explorer.pptxwonyong hwang
 
하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회wonyong hwang
 
토큰 증권 개요.pptx
토큰 증권 개요.pptx토큰 증권 개요.pptx
토큰 증권 개요.pptxwonyong hwang
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptxwonyong hwang
 
k8s practice 2023.pptx
k8s practice 2023.pptxk8s practice 2023.pptx
k8s practice 2023.pptxwonyong hwang
 
Ngrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptxNgrok을 이용한 Nginx Https 적용하기.pptx
Ngrok을 이용한 Nginx Https 적용하기.pptxwonyong hwang
 
Nginx Https 적용하기.pptx
Nginx Https 적용하기.pptxNginx Https 적용하기.pptx
Nginx Https 적용하기.pptxwonyong hwang
 
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).pptxwonyong hwang
 
Nginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptxNginx Reverse Proxy with Kafka.pptx
Nginx Reverse Proxy with Kafka.pptxwonyong hwang
 
Kafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and GrafanaKafka monitoring using Prometheus and Grafana
Kafka monitoring using Prometheus and Grafanawonyong hwang
 
주가 정보 다루기.pdf
주가 정보 다루기.pdf주가 정보 다루기.pdf
주가 정보 다루기.pdfwonyong hwang
 
App development with quasar (pdf)
App development with quasar (pdf)App development with quasar (pdf)
App development with quasar (pdf)wonyong hwang
 
Hyperledger composer
Hyperledger composerHyperledger composer
Hyperledger composerwonyong hwang
 
BlockChain implementation by python
BlockChain implementation by pythonBlockChain implementation by python
BlockChain implementation by pythonwonyong hwang
 
Block chain introduction slideshare
Block chain introduction   slideshareBlock chain introduction   slideshare
Block chain introduction slidesharewonyong hwang
 

More from wonyong hwang (18)

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
 
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
 
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 composer
Hyperledger composerHyperledger composer
Hyperledger composer
 
BlockChain implementation by python
BlockChain implementation by pythonBlockChain implementation by python
BlockChain implementation by python
 
Block chain introduction slideshare
Block chain introduction   slideshareBlock chain introduction   slideshare
Block chain introduction slideshare
 

Hyperledger Fabric practice (v2.0)

  • 2. Precondition ! Ubuntu 18.04 LTS or Above ! Docker Install (Latest version) apt-get install libltdl-dev ! Docker Engine: Version 17.06.2-ce or higher wget https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/ amd64/docker-ce_17.06.2~ce-0~ubuntu_amd64.deb dpkg -i docker-ce_17.06.2~ce-0~ubuntu_amd64.deb docker —version ! curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker- compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose docker–compose –version https://phoenixnap.com/kb/install-docker-compose-ubuntu
  • 3. environment setup ! ubuntu 16.04 or higher (we’ve installed ubuntu 18.04…) ! root 권한으로 설치 ! apt-get update ! apt-get install curl ! apt-get install python-pip ! apt-get install make gcc g++ libtool ! apt-get install tree
  • 4. environment setup ! git apt-get install -y git git version ! Python: 2.7.x python –version (apt-get install -y python) ! Go lang Version 1.11.x wget https://dl.google.com/go/go1.13.12.linux-amd64.tar.gz tar -C /usr/local/ -xvf go1.13.12.linux-amd64.tar.gz ! Go 환경변수 설정 vi /etc/profile export GOROOT=/usr/local/go export PATH=$PATH:$GOROOT/bin source /etc/profile go version
  • 5. environment setup ! Node.js (Version 8.9 or higher (no version 9.0 support) / npm (Version 6.x) curl -sL http://deb.nodesource.com/setup_8.x | bash - apt-get install nodejs node -v npm -v
  • 6. environment setup ! Hyperledger Fabric curl -sSL http://bit.ly/2ysbOFE | bash -s 1.4.0 1.4.0 0.4.10 (curl -sSL https://goo.gl/6wtTN5 | bash -s 1.4.1 1.4.1 0.4.10) (curl -sSL https://bit.ly/2KLpv5d | bash -s 1.4.0 –d -s) ! ! vi /etc/profile export FABRIC_HOME=/home/fabric/fabric-samples export PATH=$PATH:$FABRIC_HOME/bin source /etc/profile [참고] 최신 버전 설치시(2.0) 아래 명령으로 실행 (V2.0에서는 본 교안에서 설명하는 예제가 정상 실행되지 않음. 예제의 버전이 2.0 기준으로 수정되어야 함) v2.0은 체인코드 라이프싸이클이 더 상세해짐 curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s curl -sSL https://bit.ly/2ysbOFE | bash -s
  • 8. 개요 ! The build your first network (BYFN) scenario provisions a sample Hyperledger Fabric network consisting of two organizations, each maintaining two peer nodes. It also will deploy a “Solo” ordering service by default, though other ordering service implementations are available. source : https://hyperledger-fabric.readthedocs.io/en/release-1.4/build_network.html Org1MSP - Peer 0 - Peer 1 Org2MSP - Peer 0 - Peer 1
  • 9. crypto-config.yaml ! 인증서 생성을 위한 조직과 Peer 개수, 사용자(어드민 제외) 수 설정 Note that the crypto-config.yaml file lists five orderers as being tied to the orderer organization. While the cryptogen tool will create certificates for all five of these orderers.  Orderer orderer2 orderer3 orderer4 orderer5 peer0.org0 peer1.org0 peer0.org1 peer1.org1
  • 10. configtx.yaml ! 채널 생성을 위한 Peer 정보 ( Host, Port), MSP 정보, Consortiums(몇 개의 Org로 구성할 것인지) 설정
 - 블럭 생성 크기 등과 관련된 설정
 BatchTimeout, 
 BatchSize - MaxMessageCount
 AbsoluteMaxBytes
 PreferredMaxBytes ! 3가지 파일을 결과적으로 생성
 - 최초 블록 정보 genesis.block - 앵커 피어 정보 anchor.tx (Org1MSPanchor.tx, Org2MSPanchor.tx) - 채널 구성 정보 channel.tx
  • 11. T echo "##########################################################" echo "######### Generating Orderer Genesis block ##############" echo "##########################################################" # Note: For some unknown reason (at least for now) the block file can't be # named orderer.genesis.block or the orderer will fail to launch! set -x configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.bloc res=$? set +x if [ $res -ne 0 ]; then echo "Failed to generate orderer genesis block..." exit 1 fi echo echo "#################################################################" echo "### Generating channel configuration transaction 'channel.tx' ###" echo "#################################################################" set -x configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAM res=$? set +x if [ $res -ne 0 ]; then echo "Failed to generate channel configuration transaction..." exit 1 fi TwoOrgsChannel은 콘소시엄으로 구성된 Org1과 Org2의 채널에 관한 명세이며 SampleMultiNodeEtcdRaft는 블록체인을 구성하는 오더러의 정보를 명세하며 이 정보가 genesisBlock에 포함된다.
  • 12. byfn.sh echo "##########################################################" echo "######### Generating Orderer Genesis block ##############" echo "##########################################################" # Note: For some unknown reason (at least for now) the block file can't be # named orderer.genesis.block or the orderer will fail to launch! configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block echo "#################################################################" echo "### Generating channel configuration transaction 'channel.tx' ###" echo "#################################################################" configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME echo "#################################################################" echo "####### Generating anchor peer update for Org1MSP ##########" echo "#################################################################" configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP echo "#################################################################" echo "####### Generating anchor peer update for Org2MSP ##########" echo "#################################################################" configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
  • 13. ########################################################## ##### Generate certificates using cryptogen tool ######### ########################################################## + cryptogen generate --config=./crypto-config.yaml org1.example.com org2.example.com + res=0 + set +x Generate CCP files for Org1 and Org2 /root/fabric-samples/first-network/../bin/configtxgen ########################################################## ######### Generating Orderer Genesis block ############## ########################################################## + configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block 2020-06-04 01:45:15.992 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration 2020-06-04 01:45:16.015 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: etcdraft 2020-06-04 01:45:16.015 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 Orderer.EtcdRaft.Options unset, setting to tick_interval:"500ms" election_tick:10 heartbeat_tick:1 max_inflight_blocks:5 snapshot_interval_size:16777216 2020-06-04 01:45:16.016 UTC [common.tools.configtxgen.localconfig] Load -> INFO 004 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml 2020-06-04 01:45:16.017 UTC [common.tools.configtxgen] doOutputBlock -> INFO 005 Generating genesis block 2020-06-04 01:45:16.018 UTC [common.tools.configtxgen] doOutputBlock -> INFO 006 Writing genesis block + res=0 + set +x ################################################################# ### Generating channel configuration transaction 'channel.tx' ### ################################################################# + configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel 2020-06-04 01:45:16.033 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration 2020-06-04 01:45:16.053 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml 2020-06-04 01:45:16.054 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx 2020-06-04 01:45:16.056 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx + res=0 + set +x ################################################################# ####### Generating anchor peer update for Org1MSP ########## ################################################################# + configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP 2020-06-04 01:45:16.071 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration 2020-06-04 01:45:16.092 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml 2020-06-04 01:45:16.092 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Generating anchor peer update 2020-06-04 01:45:16.093 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 004 Writing anchor peer update + res=0 + set +x ################################################################# ####### Generating anchor peer update for Org2MSP ########## ################################################################# + configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP 2020-06-04 01:45:16.108 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration 2020-06-04 01:45:16.129 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/fabric-samples/first-network/configtx.yaml 2020-06-04 01:45:16.129 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Generating anchor peer update 2020-06-04 01:45:16.132 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 004 Writing anchor peer update + res=0 + set +x ./byfn.sh generate 제네시스 블록 생성 채널 환결설정 앵커피어 설정 모두/channel-artifacts/ 하위에 결과파일로 저장
  • 15. v2.0 부터 priv_sk 디렉토리로 변경
  • 17. ! 인증기관(CA), 공개키, 개인키, 인증서(CRT) source : http://soul0.tistory.com/372 intro CA 살펴보기
  • 18. hyperledger의 인증 ! 하이러페저는 모든 노드들이 자신들의 인증을 CA를 통해 받는다. ! Root CA ! 자식 CA ! * ! 앞서 살펴본 cryptogen 을 통해서 CA를 구성할 수 있음
 (Fabric CA Server를 통해서도 CA구성 가능, Fabric-CA Client 또는 Fabric SDK를 통해 서도 인증서 발급 및 조회 등의 서비스 이용가능) ! 인증 대상
 - 전체 네트워크, 채널, 조직(Org), 조직 관리자(Admin), 사용자(User), Peer source : https://hyperledger-fabric-ca.readthedocs.io/en/latest/users-guide.html CA 살펴보기
  • 19. hyperledger MSP ! MSP (Membership Service Provider)는 멤버쉽 서비스 제공 목적의 컴포넌트 ! 인증서를 발급/조회/검증하는 등 사용자 및 서비스의 인증에 대한 작업 ! 조직마다 보통 하나의 MSP가 있으며 MSP ID로 구분된다. - 전체 네트워크, 채널, 조직(Org), 조직 관리자(Admin), 사용자(User), Peer // mspID 와 certCN 을 조건으로 검사하여 함수의 사용가능 여부를 판단할 수 있음 func authenticateOrg(mspID string, certCN string) bool { return (mspID == "Org1MSP") && (certCN == "ca.example.com") } CA 살펴보기 source : https://github.com/hyperledger/fabric/blob/release-1.4/msp/msp.go
  • 20. check private key ! root@ubuntu:~/fabric-samples/first-network# find | grep -E '/ca.*_sk' | sort ./crypto-config/ordererOrganizations/example.com/ca/d6c3aff453b6947f13e189a3d3cb60f1d42addf2295acca28aed14f3d4827c21_sk ./crypto-config/peerOrganizations/org1.example.com/ca/c9681f8d01403a2be7a2df7b2bd2ebdc691288d64ae0209b6270facf822fa7e1_sk ./crypto-config/peerOrganizations/org2.example.com/ca/36ea9dbed56ffa19a337c3f3b838682ebd11edd84b51fe6e0f700f7e1a3a4044_sk CA 살펴보기
  • 21. ├── ordererOrganizations │   └── example.com │   ├── ca │   │   ├── 5a4cfffc67e06260ef685ffa0559975f54912df5127d9bbf0ece4c7b83f9caeb_sk │   │   └── ca.example.com-cert.pem │   ├── msp │   │   ├── admincerts │   │   │   └── Admin@example.com-cert.pem │   │   ├── cacerts │   │   │   └── ca.example.com-cert.pem │   │   └── tlscacerts │   │   └── tlsca.example.com-cert.pem │   ├── orderers │   │   └── orderer.example.com │   │   ├── msp │   │   │   ├── admincerts │   │   │   │   └── Admin@example.com-cert.pem │   │   │   ├── cacerts │   │   │   │   └── ca.example.com-cert.pem │   │   │   ├── keystore │   │   │   │   └── 829584340955b187ecc5b1cef386736fd3666ffcd0600ef3f4bc2015c2e36d34_sk │   │   │   ├── signcerts │   │   │   │   └── orderer.example.com-cert.pem │   │   │   └── tlscacerts │   │   │   └── tlsca.example.com-cert.pem │   │   └── tls │   │   ├── ca.crt │   │   ├── server.crt │   │   └── server.key │   ├── tlsca │   │   ├── 419de30afd02a9ac15cc62acf07509c9497c792cc938d19cbac7484c6ff7455b_sk │   │   └── tlsca.example.com-cert.pem │   └── users │   └── Admin@example.com │   ├── msp │   │   ├── admincerts │   │   │   └── Admin@example.com-cert.pem │   │   ├── cacerts │   │   │   └── ca.example.com-cert.pem │   │   ├── keystore │   │   │   └── cbd8cba235aafc20622a3056b153129a8dd7efea1a11c0b9b3d75cd94ea47ebd_sk │   │   ├── signcerts │   │   │   └── Admin@example.com-cert.pem │   │   └── tlscacerts │   │   └── tlsca.example.com-cert.pem │   └── tls │   ├── ca.crt │   ├── client.crt example.com의 비밀키와 인증서 [MSP] 관리자용 인증서 [MSP] CA식별 인증서 [MSP] TLS 통신용 인증서 orderer.example.com example.com 상위 조직의 어드민 인증서와 CA 인증서를 복사 orderer.example.com의 비밀키와 인증서 각 노드의 HTTPS 통신용 인증서와 비밀키 각 사용자의의 HTTPS 통신용 인증서와 비밀키동일 파일 동일 파일 CA 살펴보기 Client -> sever request Server send server.crt Client verify server.crt with ca.crt(pub. Key included) Client get public key of server Client send encrypted message to server Server decrypt message by its own private key(sercer.key) server.key = 생성된 MSP의 개인키와 동일 파일
  • 22. └── peerOrganizations ├── org1.example.com │   ├── ca │   │   ├── b6f3f5b3d200ec42cbbe11cff35d7d588b680a0fa10d650d99a7ef1b8470f855_sk │   │   └── ca.org1.example.com-cert.pem │   ├── msp │   │   ├── admincerts │   │   │   └── Admin@org1.example.com-cert.pem │   │   ├── cacerts │   │   │   └── ca.org1.example.com-cert.pem │   │   ├── config.yaml │   │   └── tlscacerts │   │   └── tlsca.org1.example.com-cert.pem │   ├── peers │   │   ├── peer0.org1.example.com │   │   │   ├── msp │   │   │   │   ├── admincerts │   │   │   │   │   └── Admin@org1.example.com-cert.pem │   │   │   │   ├── cacerts │   │   │   │   │   └── ca.org1.example.com-cert.pem │   │   │   │   ├── config.yaml │   │   │   │   ├── keystore │   │   │   │   │   └── 81d0884d3094c1a56799c113a76a1ddb9989fda14d96e0f793d3e696f23dca2b_sk │   │   │   │   ├── signcerts │   │   │   │   │   └── peer0.org1.example.com-cert.pem │   │   │   │   └── tlscacerts │   │   │   │   └── tlsca.org1.example.com-cert.pem │   │   │   └── tls │   │   │   ├── ca.crt │   │   │   ├── server.crt │   │   │   └── server.key │   │   └── peer1.org1.example.com │   │   ├── msp │   │   │   ├── admincerts │   │   │   │   └── Admin@org1.example.com-cert.pem │   │   │   ├── cacerts │   │   │   │   └── ca.org1.example.com-cert.pem │   │   │   ├── config.yaml │   │   │   ├── keystore │   │   │   │   └── dfc4d5a95b62a6fa6aa0a45f822d068139756b2b40e8b392173491e3f768f6f9_sk │   │   │   ├── signcerts │   │   │   │   └── peer1.org1.example.com-cert.pem │   │   │   └── tlscacerts │   │   │   └── tlsca.org1.example.com-cert.pem │   │   └── tls │   │   ├── ca.crt │   │   ├── server.crt │   │   └── server.key org*.example.com example.com peer*.org*.example.com └── users │   ├── Admin@org1.example.com │   │   ├── msp │   │   │   ├── admincerts │   │   │   │   └── Admin@org1.example.com-cert.pem │   │   │   ├── cacerts │   │   │   │   └── ca.org1.example.com-cert.pem │   │   │   ├── keystore │   │   │   │   └── 9e3ebb8985cc6f6c053297825d6bbef822f4c43ea5a7e7d277dd96be1f80e9ec_sk │   │   │   ├── signcerts │   │   │   │   └── Admin@org1.example.com-cert.pem │   │   │   └── tlscacerts │   │   │   └── tlsca.org1.example.com-cert.pem │   │   └── tls │   │   ├── ca.crt │   │   ├── client.crt │   │   └── client.key │   └── User1@org1.example.com │   ├── msp │   │   ├── admincerts │   │   │   └── User1@org1.example.com-cert.pem │   │   ├── cacerts │   │   │   └── ca.org1.example.com-cert.pem │   │   ├── keystore │   │   │   └── 0a9f665b540e722ea214dd280904f9a92cbac7b647b4853124174ecf2973c898_sk │   │   ├── signcerts │   │   │   └── User1@org1.example.com-cert.pem │   │   └── tlscacerts │   │   └── tlsca.org1.example.com-cert.pem │   └── tls │   ├── ca.crt │   ├── client.crt │   └── client.key NodeOUs: Enable: true ClientOUIdentifier: Certificate: cacerts/ca.org1.example.com-cert.pem OrganizationalUnitIdentifier: client PeerOUIdentifier: Certificate: cacerts/ca.org1.example.com-cert.pem OrganizationalUnitIdentifier: peer CA 살펴보기
  • 23. [참고] 인증서 살펴보기 root@fabric:/home/fabric/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/ca# openssl x509 -text -noout -in ca.example.com-cert.pem Certificate: Data: Version: 3 (0x2) Serial Number: d9:d9:d3:61:6d:0d:28:6f:e2:5d:30:05:82:01:cd:38 Signature Algorithm: ecdsa-with-SHA256 Issuer: C = US, ST = California, L = San Francisco, O = example.com, CN = ca.example.com Validity Not Before: Mar 12 03:40:00 2020 GMT Not After : Mar 10 03:40:00 2030 GMT Subject: C = US, ST = California, L = San Francisco, O = example.com, CN = ca.example.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:c1:e2:fd:33:bc:3d:b9:6b:1b:6a:da:5e:a0:36: 9a:dd:c2:23:9c:c8:7a:ec:b9:e7:54:c4:72:11:19: 85:33:1f:6a:62:e4:1d:c9:ae:e4:e0:2e:12:a0:5e: 7a:d6:c5:51:5c:70:21:29:27:5d:59:d0:17:2b:f9: 4c:0b:f6:9f:d4 ASN1 OID: prime256v1 NIST CURVE: P-256 X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment, Certificate Sign, CRL Sign X509v3 Extended Key Usage: TLS Web Client Authentication, TLS Web Server Authentication X509v3 Basic Constraints: critical CA:TRUE X509v3 Subject Key Identifier: A6:EE:42:3F:D2:81:13:DB:1A:12:3E:5D:57:75:92:43:BD:D8:C4:AE:8C:51:3D:86:28:F9:69:BD:B4:F7:37:0A Signature Algorithm: ecdsa-with-SHA256 30:44:02:20:77:12:a9:2b:27:dd:7e:d7:a5:1f:f4:44:c2:00: b5:e8:ff:b4:cf:07:aa:e4:e5:d2:68:0f:f3:f2:0b:6c:17:c4: 02:20:28:cc:a1:82:4b:e1:0c:38:fa:9e:e8:a9:62:27:29:16: 5a:20:e2:58:bb:b9:2d:ea:f9:f9:5f:a1:b8:c7:2e:e4 CA 살펴보기
  • 24. [참고] hyperledger fabric ca 실습 ! CA Server, Client 설치 및 실습 https://ovila.tistory.com/68 ! Hyperledger Fabric 멀티호스트 환경 구축  https://leejonggun.tistory.com/15 CA 살펴보기
  • 25. peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls --cafile ~중략~/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem [채널 생성 요청] orderer에 생성 요청시 TLS 통신 사용하며 TLS인증서 위치를 지정함(tlsca.example.com-cert.pem) CORE_PEER_MSPCONFIGPATH =~중략~/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org1MSP" CORE_PEER_TLS_ROOTCERT_FILE=~중략~/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt peer channel join -b mychannel.block [채널 조인 요청] CORE_PEER_MSPCONFIGPATH =~중략~/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org1MSP" CORE_PEER_TLS_ROOTCERT_FILE =~중략~/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CHANNEL_NAME=mychannel peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile ~중략~/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem [채널 업데이트 요청 ] orderer에 채널 업데이트 요청 org1의 peer0, peer1 org2의 peer0, peer1 방식 동일하게 모두 수행 /scripts/util.sh 의 setGlobals함수내 설정 코드 참조 전체 실행 순서 (1/5) CA 살펴보기 cli컨테이너에서 수행하는 preface는 utils.sh에서 전달받은 파라미터에 따라 setGlobal함수내에서 재정의됨
  • 26. peer lifecycle chaincode install mycc.tar.gz [체인코드 인스톨] peer lifecycle chaincode queryinstalled [체인코드 설치확인] orderer를 통해 수행 Cli 컨테이너에서 수행, Org1-Peer0에 설치 peer lifecycle chaincode package mycc.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/abstore/go/ --lang golang --label mycc_1 [체인코드 패키징] peer를 통해 설치 각 org의 anchor peer에 설치
 org1의 peer0 org2의 peer0 방식 동일하게 모두 수행 전체 실행 순서 (2/5) CA 살펴보기 정상인 경우 패키징 고유번호 확인 가능 Package ID: mycc_1:0dcea8280752b53a2a534f280445e36fa4cb32f648c2d7729589821f300d74be, Label: mycc_1 peer lifecycle chaincode approveformyorg --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/ orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name mycc --version 1 --init-required --package-id mycc_1:0dcea8280752b53a2a534f280445e36fa4cb32f648c2d7729589821f300d74be --sequence 1 --waitForEvent [체인코드 승인] orderer를 통해 수행 예제에서는 Org1-Peer0 을 통해 승인 요청
  • 27. 전체 실행 순서 (3/5) peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name mycc --version 1 --sequence 1 --output json --init-required [체인코드 커밋가능여부 확인] 예제에서는 Org1-Peer0 을 통해 승인(이전 장에서)했으므로 { "approvals": { "Org1MSP": true, "Org2MSP": false } } 로 결과 출력 peer lifecycle chaincode approveformyorg -… [체인코드 승인] orderer를 통해 수행 이제 Org2-Peer0 또한 승인 요청 peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name mycc --version 1 --sequence 1 --output json --init-required [체인코드 커밋가능여부 확인] 이제는 모두 커밋 true { "approvals": { "Org1MSP": true, "Org2MSP": true } } 로 결과 출력 peer lifecycle chaincode commit -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/ peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1 --sequence 1 --init-required [체인코드 커밋] Org1 peer0, org2 peer0에 commit (anchor peer)
  • 28. 전체 실행 순서 (4/5) peer lifecycle chaincode querycommitted --channelID mychannel --name mycc [체인코드 커밋 성공여부 조회] 결과: Committed chaincode definition for chaincode 'mycc' on channel 'mychannel': Version: 1, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true] peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/ orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /op gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/ peer0.org2.example.com/tls/ca.crt --isInit -c '{"Args":["Init","a","100","b","100"]}' [체인코드 Invoke] peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' [체인코드 query] peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/ orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/ gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/ peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}' [체인코드 Invoke] A = 100 B = 100 A = ? A에서 B로 10 이동
  • 29. 전체 실행 순서 (5/5) peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' [체인코드 Query] A == 90 ? chaincode를 org2-peer1 에도 설치해서 조회해보자, 과연 같은 원장을 조회하여 A==90? ==================== Query successful on peer0.org1 on channel 'mychannel' ===================== Installing chaincode on peer1.org2... peer lifecycle chaincode install mycc.tar.gz ===================== Querying on peer1.org2 on channel 'mychannel'... ===================== peer chaincode query -C mychannel -n mycc -c ‘{"Args":["query","a"]}' 90 org1, org2 에 모두 approve, commit 가능하므로 인스톨 후 바로 체인코드 조회 가능함
  • 30. docker-compose 설정 파일 확인 docker-compose-cli.yaml의 base가 되는 base/docker-compose-base.yaml에서는 ./byfn.sh generate를 통해 생성된 인증서 정보를 볼륨 마운트하고 마운트된 도커 이미지의 해당 디렉토리로 환경변수 설정을 함 docker-compose -f docker-compose-cli.yaml -f docker-compose-etcdraft2.yaml up -d
  • 31. ./byfn.sh up ===================== Chaincode is installed on peer0.org2 ===================== Instantiating chaincode on peer0.org2... + res=0 + set +x + peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('''Org1MSP.peer''','''Org2MSP.peer''')' …. 생략 … ===================== Chaincode is instantiated on peer0.org2 on channel 'mychannel' ===================== Querying chaincode on peer0.org1... ===================== Querying on peer0.org1 on channel 'mychannel'... ===================== + res=0 + set +x + peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' Attempting to Query peer0.org1 ...3 secs + res=0 + set +x 100 ===================== Query successful on peer0.org1 on channel 'mychannel' ===================== Sending invoke transaction on peer0.org1 peer0.org2... + peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/ tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt –c '{"Args":["invoke","a","b","10"]}' 2020-02-04 06:05:19.250 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 ===================== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'mychannel' ===================== Installing chaincode on peer1.org2... + res=0 + set +x + peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/ …. 생략 … ===================== Chaincode is installed on peer1.org2 ===================== Querying chaincode on peer1.org2... ===================== Querying on peer1.org2 on channel 'mychannel'... ===================== + res=0 + set +x V1.4
  • 32. docker-compose-cli 살펴보기 Org1의 Peer0인 피어에 접속하도록 환경변수가 설정됨 해당 피어에 채널 생성, 참가, 앵커 피어 갱신, 체인코드 설치/초기화/질의/호출을 수행한다. (createChannel, joinChannel, updateAnchorPeers, packageChaincode, installChaincode, approveForMyOrg, checkCommitReadiness, commitChaincodeDefinition, queryCommitted) 위의 수행함수는 byfn.sh의 networkUp함수내에서 docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE 로 호출됨 scripts.sh은 cli 도커에 볼륨 마운트됨으로 cli 에서 수행 가능함
  • 34. chaincode 위치 확인 environment: - GOPATH=/opt/gopath working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer volumes: - /var/run/:/host/var/run/ - ./../chaincode/:/opt/gopath/src/github.com/chaincode - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts CC_SRC_PATH="github.com/hyperledger/fabric-samples/chaincode/abstore/go/" peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH} >&log.txt peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer') util.sh script.sh 2개의 path를 조합하여 go 모듈을 실행 (go는 GOPATH/src 하위 폴더를 기준으로 프로젝트 경로를 잡는 규칙이 있음)
  • 35. chaincode 살펴보기 ./bynf.sh 에서 script.sh을 docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE 로 실행함. 즉, cli 도커에서 체인코드 install/instantiate를 수행함 체인코드를 수정 - invoke(stub shim.ChaincodeStubInterface, args []string) 함수에서
 우측 그림과 같이 -10 을 추가 ./byfn.sh down ./byfn.sh up ===================== Querying on peer1.org2 on channel 'mychannel'... ===================== + res=0 + set +x + peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' Attempting to Query peer1.org2 ...3 secs + res=0 + set +x 80 !!!!!!!!!!!!!!! Query result on peer0.org1 is INVALID !!!!!!!!!!!!!!!! ================== ERROR !!! FAILED to execute End-2-End Scenario ================== 수행결과 util.sh의 chaincodeQuery함수에서 기대한 결과인 90을 충족하지 못하므로 에러로 표시하였으나, 체인코드를 수정한 의도와 부합하는 결과를 확인할 수 있음 docker-compose-cli.yaml에 cli 컨테이너 정의부분에 volumes: ../../chaincode/:/opt/gopath/src/github.com/chaincode 으로 변경한 체인코드를 그대로 cli 컨테이너에 볼륨 마운트하므로 도커를 시작하면 변경된 코드를 cli에서 install할 수 있음
  • 36. couchdb 사용하기 ! ./byfn.sh up -c mychannel -s couchdb 값 ’90’ 확인가능 couch db+fabric tutorial : https://hyperledger-fabric.readthedocs.io/en/release-1.4/couchdb_tutorial.html 4개의 couch db가 4개의 peer에 연결되는 구조로 컨테이너 기동 Virtual box port forwarding setting : inbound/outbound open 5984 Open db : ex> mychannel/mycc
  • 37. [참고] block data (orderer) docker cp -a orderer.example.com:/var/hyperledger/production/orderer ./ Docker-compose-base 에서 Volume create로 생성되었으므로 bind mount와는 다르게 운영체제>docker 전용 파일관리 영역에서 위와 같이 접근 가능하며 컨테이너간에도 사용가능하고 컨테이너가 종료되어도 사용가능함
  • 38. [참고] block data (peer) docker cp -a peer0.org1.example.com:/var/hyperledger/production ./ cd production/ more ledgersData/chains/chains/mychannel/blockfile_000000
  • 40. 사전 준비 ! docker rm –f $(docker ps –a -q) ! 샘플예제가 있는 디렉토리로 이동(fabric-samples/chaincode-docker-devmode) ! 3개의 터미널을 오픈하여 상기 디렉토리로 이동 ! docker-compose-simple.yaml 구성 확인
 - orderer, peer, cli(체인코드 인스톨 및 인터랙션), chaincode(체인코드 개발 환경) 컨테이너로 구성 cli: container_name: cli image: hyperledger/fabric-tools tty: true …중략… working_dir: /opt/gopath/src/chaincodedev command: /bin/bash -c './script.sh' volumes: …중략… - ./../chaincode:/opt/gopath/src/chaincodedev/chaincode - ./:/opt/gopath/src/chaincodedev/ chaincode: container_name: chaincode image: hyperledger/fabric-ccenv tty: true environment: …중략… - CORE_PEER_ADDRESS=peer:7051 …중략… working_dir: /opt/gopath/src/chaincode command: /bin/bash -c 'sleep 6000000' volumes: …중략… - ./../chaincode:/opt/gopath/src/chaincode source : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode
  • 41. Terminal 1 - Start the network ! docker-compose -f docker-compose-simple.yaml up source : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode
  • 42. Terminal 2 - Build & start the chaincode ! docker exec -it —user root chaincode sh ! cd abstore/go ! go build -o abstore ! CORE_CHAINCODE_ID_NAME=mycc:0 CORE_PEER_TLS_ENABLED=false ./abstore -peer.address peer:7052 source : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode Normally chaincodes are started and maintained by peer. However in “dev mode", chaincode is built and started by the user. ! BYFN 에서는 peer를 통해 시작/관리하고 cli 컨테이너에서 체인코드 설치 및 초기화를 하였으나, 본 예제에서는 사용자가 위 명령을 통해 체인코드를 먼저 실행 상태로 만든다. docker-compose-simple.yaml 의 peer 컨테이너 Command 섹션에 —peer-chaincodedev = true 라고 설정됨
  • 43. Terminal 3 - Use the chaincode ! docker exec -it cli bash ! peer chaincode install -p chaincodedev/chaincode/abstore/go -n mycc -v 0 ! peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -C myc ! peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc ! peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc source :https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode source : https://nick-fabric.readthedocs.io/en/latest/commands/peerchaincode.html 여기까지는 Build Your First Network 체인코드와 동일하다. 이제 일부 코드를 추가하여 다시 배포해 보자. terminal2 에서 chaincode를 실행하지 않으면 에러발생
  • 44. local development env. ! 설치 후 터미널에서 go env 명령을 실행하여 GOPATH 경로를 확인 ! GOPATH 경로 하단에 /go/src 디렉토리 생성 예>~iMac:src sf29$ pwd /Users/sf29/go/src ! visual studio code 설치 + GO addon 추가 설치 ! 우측 그림과 같이 $GOPATH/go/src 디렉토리에서 임의 go 파일 생성 및 테스트 사전에 GO 설치 필요 - https://golang.org/dl/ Visual studio Go extension의 settings.jon 설정내용: { "go.formatTool": "goimports", "go.useLanguageServer": true }
  • 45. local development env. ! visual studio code 에서 소스 추적 및 빌드 가능 ! 개별 파일로 오픈 X, 폴더를 워크스페이로 추가해야 함(중요) $GOROOT/src/ 에서 다음과 같이 hlf 라이브러리 추가 mkdir -p github.com/hyperledger cd github.com/hyperledger/ git clone -b release-2.0 https://github.com/hyperledger/fabric.git 우측 그림의 소스는 $GOPATH/src/[임의 폴더명]/chiancode_example.go에 위치시킴 % pwd /Users/hwang-won-yong/go/src/sacc % go get % go run sacc.go 상기 설정 이후 VS 재시작 —> 라이브러리에 밑 줄이 보이고, 해당 정의부로 이동도 가능하게 됨
  • 46. chaincode download/upload via sftp ! ftp root access/login 허용 ! Visual Studio Code에 ftp simple plugin 설치 ! F1을 누른 다음  ftp-simple:Config - FTP connection setting 를 선택하고 우측
 그림과 같이 편집 ! F1을 누른 다음 tp-simple:Open - Open the file directly from FTP server를 선택
 하고 localhost를 클릭하면 접속됨 (chaincode 디렉토리에서 abstore.go를 다운로드) ! 접속 이후 체인코드 클릭하여 편집창에서 오픈 ! $GOPATHSRCabstore 폴더를 생성하고
 해당 폴더 하위에 abstrore.go 파일로 save as… 한다. (소스 분석용) visual studio code 플러그인 설치 출처 : https://www.manualfactory.net/10964
  • 47. chaincode 수정 ! 공식 튜토리얼을 참조하여 아래와 같이 수정 공식 튜토리얼 : https://github.com/hyperledger/fabric-samples/tree/master/chaincode-docker-devmode func (t *ABstore) Set(ctx contractapi.TransactionContextInterface, user string, value int) error { fmt.Println("ABstore Set") var A string var Aval int var err error A = user Aval = value fmt.Printf("################### Aval = %d", Aval) err = ctx.GetStub().PutState(A, []byte(strconv.Itoa(value))) if err != nil { return err } return nil } 코드 수정 후 빌드 테스트 FTP upload (overwrite)
  • 48. chaincode 배포 및 테스트 ! docker-compose –f docker-compose-simple.yaml down ! docker-compose –f docker-compose-simple.yaml up ! 이전 terminal2, terminal3에서 수행했던 내용 동일 반복하고 코드에서 추가한 set 명령 에 대해 추가로 확인 peer chaincode install -p chaincodedev/chaincode/abstore/go -n mycc -v 0 peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -C myc peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc peer chaincode invoke -n mycc -c '{"Args":["Set","a","1000"]}' -C myc peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc ABstore Init Aval = 100, Bval = 200 Aval = 90, Bval = 210 Query Response:{"Name":"a","Amount":"90"} ABstore Set ################### Aval = 1000 Query Response:{“Name":"a","Amount":"1000"} terminal2 terminal3
  • 49. [참고] peer chaincode upgrade ! 모든 컨테이너 기동 상태에서 체인코드 업그레이드 실시 ! VS CODE 에서 소스 변경 및 저장/업로드 terminal2 docker exec -it --user root chaincode sh go build -o abstore CORE_CHAINCODE_ID_NAME=mycc:1 CORE_PEER_TLS_ENABLED=false ./abstore -peer.address peer:7052 terminal3 peer chaincode install -p chaincodedev/chaincode/abstore/go -n mycc -v 1 peer chaincode upgrade -p chaincode/abstore/go -n mycc -v 1 -C myc -c '{"Args":["init","a","100","b","200"]}' peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc peer chaincode invoke -n mycc -c '{"Args":["Set","a","1000"]}' -C myc 소스 수정 -> 로컬 빌드 -> FTP 업로드 새로운 terminal을 띄워서 위 terminal2의 내용을 수행함 기존 terminal2는 업그레이드 완료시 peer에 대한 응답을 더 이상 하지 않게 됨
  • 52. Chaincode tutorial (Advance) ! Code review ! Build and deploy - ftp upload (to newly created directory. Eg> saccnew) - [Terminal 2] go get - [Terminal 2] go build -o saccnew - [Terminal 2] CORE_CHAINCODE_ID_NAME=mycc:0 CORE_PEER_TLS_ENABLED=false ./saccnew -peer.address peer:7052 ! Chaincode install/run on Terminal 3 - go get github.com/hyperledger/fabric-chaincode-go/shim Git hub : https://github.com/wonyongHwang/chaincode-tutorial/blob/master/kopoChainCode.go peer chaincode install -p chaincodedev/chaincode/saccnew -n mycc -v 0 peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -C myc peer chaincode invoke -n mycc -c '{"Args":["more","tt","Here your are, this is a book 2","1200"]}' -C myc peer chaincode query -n mycc -c '{"Args":["morequery","tt"]}' -C myc
  • 53. Chaincode tutorial (Advance) PutState func (t *SimpleChaincode) more(stub shim.ChaincodeStubInterface, param []string) pb.Response { if len(param) != 3 { return shim.Error("# of parameter mismatching") } title, text, code := param[0], param[1], param[2] codeNum, err := strconv.ParseInt(code, 10, 32) if err != nil { return shim.Error("code error") } if len(title) == 0 || len(text) == 0 || len(code) == 0 { return shim.Error("value of paramter is not properly formatted") } // make my data of AdditionalInfo addInfo := &AdditionalInfo{Title: title, Text: text, code: codeNum} addInfoBytes, err := json.Marshal(addInfo) if err != nil { return shim.Error("failed to convert bytes " + err.Error()) } err = stub.PutState(title, addInfoBytes) // key value에 공백 들어가면 조회시 값을 찾지 못함 if err != nil { return shim.Error("PutState failure " + err.Error()) } type AdditionalInfo struct { Title string "json:"title"" Text string "json:"text"" code int64 "json:"code"" }
  • 54. Chaincode tutorial (Advance) - GetState, GetHistoryForKey func (t *SimpleChaincode) morequery(stub shim.ChaincodeStubInterface, args []string) pb.Response { var A string // Entities var err error if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting name of the person to query") } A = args[0] // Get the state from the ledger valbytes, err := stub.GetState(A) if err != nil { jsonResp := "{"Error":"Failed to get state for " + A + ""}" return shim.Error(jsonResp) } valueStr := &AdditionalInfo{} err = json.Unmarshal(valbytes, &valueStr) if err != nil { jsonResp := "{"Error":"Failed to Unmarshal " + A + ""}" return shim.Error(jsonResp) } jsonResp := "{"Title":"" + A + "","Text":"" + string(valueStr.Text) + ""}" fmt.Printf("Query Response:%sn", jsonResp) // history iter, _ := stub.GetHistoryForKey(A) fmt.Println("Here is History for " + A) for iter.HasNext() { kv, _ := iter.Next() fmt.Println(string(kv.GetValue()) + " " + kv.GetTimestamp().String()) } return shim.Success([]byte(string(valueStr.code))) } GetHistoryForKey 함수로 변경 이력 조회 기존에 변경된 이력이 있는 경우 모두 조회 가능
  • 55. [참고] 공식 튜토리얼 체인코드에서… source : https://hyperledger-fabric.readthedocs.io/en/release-2.0/chaincode4ade.html#chaincode-api main 함수에서 fabric chaincode의 Start 함수를 호출 이 때 전달되는 파라미터는 type SimpleAsset struct{} 의 객체임. 소스코드상 SimpleAsset의 Init,Invoke 함수를 구현하였으므로 ChainCode 객체로 전달 가능
  • 56. [참고] 체인코드 호출 ! 동일 채널에서 같은/다른 Chaincode 호출(invoke/query) 가능 ! 다른 채널의 chaincode는 조회(query)만 가능 -예시- channel := stub.GetChannelID() stub.InvokeChaincode(chaincodeName, args, channel)
  • 58. Balance transfer example (개요) ! 2 CA, 1 Orderer, 2Org (2 Peers on each Org.) 로 구성 ! 기본적으로는 Build Your Network First와 유사한 구조이나, 여기서는 cli 컨테이너가 없음. 대신 Hyperledger fabric SDK를 이용한 node.js구현체를 통해서 채널생성, 체인코드 설치 등을 진행하게 됨. ! Build Your Network First의 기본 실행 구조에서는 CA 서버 없이 cryptogen을 통해 미리 생성해 놓은 인증서를 사용하여 통신 하였으나, 이번 예제는 미리 생성한 인증서 정보를 토대로 CA서버를 기동하고, Node.js Client에서 요청하는 사용자 등록을 CA 서버에서 인증하고 처리하도록 구성 되었음 (org1 -> ca1, org2 -> ca2_ * 해당 예제 폴더에 위치한 ~e2e.yaml 로 실행시 ca 서버 기동됨
  • 59. Balance transfer example (실행 준비) ! 노드 버전 확인(node -v) balance transfer 예제는 노드 버전 10.x 이상에서 오류 발생 -> 8.* 또는 9.* 설치 기존 node.js 삭제시 : apt-get --purge remove nodejs node.js 설치 : curl -sL http://deb.nodesource.com/setup_9.x | bash - apt-get install node.js * 해당 예제는 fabric 2.0 기본 샘플예제에서 삭제되었으나 2.0이 1.4의 SDK도 지원하므로 정상 실행 가능함 ! 컨테이너 및 이미지 등 도커관련 파일 삭제 (충돌방지) docker rm -f $(docker ps -a -q) docker rmi -f $(docker images -a -q) docker volume prune docker system prune docker network prune git clone -b release-1.4 https://github.com/hyperledger/fabric-samples.git
  • 60. Balance transfer example (fabric 실행) ! ./runApp.sh 실행
  • 61. Balance transfer example (REST 호출) ./testAPIs.sh 을 실행하여 사용자 등록~체인코드 실행까지 정상 진행 되는지 확인 * chaincode instantiate 실행시 time out 으로 오류발생되는 경우, 아래 그림과 같이 testAPIs.sh의 일부분을 수정 (timeout 옵션 추가) apt-get install jq 필요
  • 62. [심화] 더 살펴볼 포인트 ! ./testAPIs.sh 의 REST CALL 호출 순서와 내용을 확인 ! Node 소스는 app.js가 시작점 ! 사용자 등록을 위해 /users 호출시에는 fabric ca server를 통해 신규 사용자 등록을 하고 토큰을 부여함 ! /users 이외의 호출 주소는 JWT 토큰 유효성 검사가 이루어짐 ! Proposal을 먼저 endorsing peer에 보내고, 해당 피어에서 사전 검증한 결과를 확인하고 orderer에게 검증결과와 트랜잭션 반영요청을 하는 부분 —> invoke-tansaction.js의 sendTransactionProposal 및 sendTransaction 호출 코드 참조

  • 63. [심화] sdk를 이용한 사용자 등록 과정 ! 기 발급받은 인증서를 이용 ! app.post('/users', async function(req, res) { … let response = await helper.getRegisteredUser(username, orgName, true); …} app.js Network-config.yaml과 org1.yaml 설정파일을 로딩하여 initCredential을 수행 등록된 사용자 없는 경우; config.json의 admin/adminpw 계정정보를 이용해 새로운 사용자를 등록(getCertificateAuthority로 인증서 로딩)
  • 64. [심화] fabric ca container Node sdk client의 config.js에 설정된 계정정보와 일치해야 함 "admins":[ { "username":"admin", "secret":"adminpw" } ]
  • 65. fabric server <-> node.js(SDK) local Fabric Server(Docker/Ubuntu/VM) Fabric SDK(local) Client(local) Fabric SDK를 로컬 개발환경에서 디버깅을 통해 분석해 보자.
  • 66. fabric server <-> node.js(SDK) local 사전 준비사항 - local pc visual studio code 설치 nvm 설치(https://gofnrk.tistory.com/32) balance transfer 예제 local 복사 + npm rebuild virtual box 포트 오픈 (유저 등록을 위해서 ca 서버 접속필요—> 7054 포트 연결 설정) (체인코드 실행 및 쿼리 등을 위해서 오더러(7050) 등 필요시 추가로 포트 연결 설정해야 함) - 수행 순서 fabric server 기동(./runApp.sh) -> 로컬에서 node 실행해야 하므로 서버측에서는 node 실행부분 주석처리 local의 balance transfer 예제 폴더 중 인증토큰과 관련된 폴더 삭제 rm -rf fabric-client-kv-org* REST 호출 수행 hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST http://localhost:4000/users -H "content-type: application/x-www-form-urlencoded" -d 'username=Jim&orgName=Org1' {"success":true,"secret":"","message":"Jim enrolled Successfully","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjU1NjMsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxODk1NjN9.h2v6HzQJdDSUryGEsqPyUbV9SK91GGgTF4_7LCzg "}% 사용자 등록 For mac> Brew install jq
  • 67. fabric server <-> node.js(SDK) local —> 로컬에서 node.js 디버깅을 visual studio로 진행
  • 68. hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST http://localhost:4000/channels -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4v cQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0" -H "content-type: application/json" -d '{ "channelName":"mychannel", "channelConfigPath":"../artifacts/channel/mychannel.tx" }' {"success":true,"message":"Channel 'mychannel' created Successfully"}% hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST http://localhost:4000/channels/mychannel/peers -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4v cQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0" -H "content-type: application/json" -d '{ "peers": ["peer0.org1.example.com","peer1.org1.example.com"] }' {"success":true,"message":"Successfully joined peers in organization Org1 to the channel:mychannel"} Create channel을 위해서 오더러에 해당하는 7050 포트 설정 필요 Join channel을 위해서 피어에 해당하는 7051와 7056 포트 설정 필요 fabric server <-> node.js(SDK) local
  • 69. hwang-won-yong@hwang-won-yong-ui-MacBookPro balance-transfer % curl -s -X POST http://localhost:4000/channels/mychannel/anchorpeers -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4v cQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0" -H "content-type: application/json" -d '{ "configUpdatePath":"../artifacts/channel/Org1MSPanchors.tx" }' {"success":true,"message":"Successfully update anchor peers in organization Org1 to the channel 'mychannel'"}% fabric server <-> node.js(SDK) local Anchor Peer Update hwang-won-yong@hwang-won-yong-ui-MacBookPro node % curl -s -X POST http://localhost:4000/chaincodes -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODQyMjc3OTIsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Ik9yZzEiLCJpYXQiOjE1ODQxOTE3OTJ9.dnZ7eBzsC4vcQtIiHSHtuLFY2U-E4FH2zcUJ2sftKP0" -H "content-type: application/json" -d "{ "peers": ["peer0.org1.example.com","peer1.org1.example.com"], "chaincodeName":"mycc", "chaincodePath":"/github.com/example_cc/node", "chaincodeType": "golang", "chaincodeVersion":"v0" }" {"success":true,"message":"Successfully installed chaincode"}% Install Chaincode —> 나머지 REST Call도 필요시 포트 설정해가면서 테스트 및 디버깅 진행~
  • 70. [참고] Mac - nvm 설치 (1/2) ! 본 예제는 node 8.x 에서 정상 수행 가능(node 10.x 는 tls 관련 오류 발생) 기존에 이미 설치한 노드 삭제 /usr/local/lib 에 있는 node와 node_modules를 삭제 /usr/local/include 에 있는 node와 node_modules를 삭제 Homebrew로 설치하셨다면, brew uninstall node를 실행 ~/local 또는 ~/lib 또는 ~/include 디렉토리 밑에 존재하는 node와 node_modules 삭제 /usr/local/bin 에 있는 node 관련 실행파일들 삭제 추가로, 필요에 따라 아래 명령어들을 실행하시면 됩니다. sudo rm /usr/local/bin/npm sudo rm /usr/local/share/man/man1/node.1 sudo rm /usr/local/lib/dtrace/node.d sudo rm -rf ~/.npm sudo rm -rf ~/.node-gyp sudo rm /opt/local/bin/node sudo rm /opt/local/include/node sudo rm -rf /opt/local/lib/node_modules (출처 : http://junsikshim.github.io/2016/01/29/Mac%EC%97%90%EC%84%9C-Node.js-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0.html) ! Nvm 설치 (일반 계정, not root) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash source ~/.bash_profile 설치 후 .bash_profile 에 nvm관련 설정 수동 추가 export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # This loads nvm bash_completion
  • 71. [참고] Mac - nvm 설치 (2/2) ! Visual Studio CODE 에서 디버깅시 기존에 설치되었던 node를 찾을 수 없으므로 아래와 같이 launch.json에 node의 위치를 설정해야 함 (which node로 찾은 경로를 기입) { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "<node_internals>/**" ], "program": "${workspaceFolder}/app.js" "runtimeExecutable": "/Users/sf29/.nvm/versions/node/v8.17.0/bin/node" } ] }
  • 73. Visual Studio Code + IBM BlockChain Platform
  • 75. Check dependencies ! VS Code version 1.38.0 or higher (code —version) ! Node v8.x or v10.x and npm v6.x or greater node —version npm —version ! Go version V1.12 or greater go version ! Docker version v17.06.02-ce or greater docker —version ! Docker Compose v1.14.0 or greater docker-compose —version nvm을 사용 중인 경우 사용할 노드 버전을 alias 설정하여 default나 global로 네이밍 해줘야 함
  • 76. Let’s Test (1/4) 기본 체인코드를 확인한다. 기본 동작을 확인하기 위해 별도 코딩은 없이 진행한다.
  • 77. Fabric Environments 섹션에 최상단 1 Org를 클릭하면 로컬환경에서 도커가 실행되고 fabric peer/orderer/ca 등이 실행된다. 이전 장에서 패키징한 체인코드를 인스톨 -> 인스턴스화 한다. Let’s Test (2/4)
  • 78. Fabric Gateways 섹션에서 mychannel을 확장하면 이전 장에서 인스턴스화에 성공한 스마트 컨트랙트가 보인다. 우측 마우스 버튼을 클릭하여 컨텍스트 메뉴를 열어서 Submit Transaction을 선택한다. 상단에서 함수명과 파라미터를 입력하는 창이 오픈될 때, 임의의 함수명(queryTest)과 임의의 파라미터([“query”,”eee”])를 입력한다. 체인코드가 실행되는 도커 컨테이너를 클릭하면 아래와 같이 위에서 입력한 함수명과 파라미터의 정상 출력을 확인 할 수 있음 - 체인코드에서 fmt.Println("Invoke()", fcn, params) 에 해당되는 부분 Let’s Test (3/4)
  • 80. [practice] KopoVote Git address : https://github.com/wonyongHwang/kopoVote.git
  • 81. Overall Architecture Node.js Docker runApp.sh로 구동 - docker run prepareFabric.sh로 사용자 등록/채널 생성/체인코드 인스톨 Vue.js Backend VM Frontend Chaincode invoke/query ! Balance Transfer를 활용한 블록체인 투표 시스템
  • 82. Preparation ! Balance-Transfer example was built on SDK v1.4 ! But at the fabric 2.0, we should use SDK v2.0 ! Work around 1) remove docker images of ccenv 2.x and reinstall ccenv 1.4 docker pull hyperledger/fabric-ccenv:1.4 https://jira.hyperledger.org/browse/FABN-1357
  • 83. Preview (KopoVote) Frontend source reference : https://github.com/IBM/evote https://www.youtube.com/watch?v=r6bnpPPif5E&t=10s
  • 84. Local chaincode develop environment setup ! 1. VS CODE -> IBM BlockChain -> Create New Project ! 2 .프로젝트 저장 위치는 $GOPATH/src/ 하위에 임의 폴더명으로 위치시켜야 함 ! 3. 테스트를 위해 IBM BlockChain 에서 Package Open Project -> Install - Instantiate -> Fabric GateWay에서 admin role로 채널 생성 여기까지 문제 없으면 Good ! 4. Chaincode.go 파일의 내용을 우리가 원하는 투표 기록용 코드로 변경 ! 5. 3번 다시 수행(Instantiate와 테스트 방법은 아래 참조) Instantiate : Init -> [“A”,”100”,”B”,”100”] Fabric G/W > Submit Tx : query -> [“A”] > Evaluate Tx : query ->[“A”]
  • 85. Chaincode 투표 항목 3개(A, B, C)에 대해 Init 함수를 통해 초기값 0으로 설정하고 vote함수를 통해 각 투표항목에 대해 +1을 기록하도록 함
  • 91. Upgrade Chaincode ! 체인코드 업그레이드 배포시 Init 함수를 호출하게 됨 -> Init 함수내 초기화 로직을 최초 배포시와 업그레이드시 2가지 모두 고려해야 함
  • 92. Commit Chaincode ! Upload chaincode(chaincode.go & main.go) to servers(fabric server, node.js server)
  • 93. Commit Chaincode ! 체인코드에서 필요한 최신 라이브러리 go get 명령어 추가(base.yaml) command: > sh -c "peer node start && go get github.com/hyperledger/fabric-chaincode-go/shim && go get github.com/hyperledger/fabric-protos-go/peer"
  • 94. Prepare shell script for booting up ! POST request Enroll on Org1/Org2 ! POST request Create channel … ! POST request Join channel on Org1/Org2 ! POST request Update anchor peers on Org1/Org2 ! POST Install chaincode on Org1/Org2 ! POST instantiate chaincode on Org1
  • 95. Frontend coding ! Vote ! queryAll Source reference : https://github.com/IBM/evote
  • 96. Frontend coding ! REST Call using Axios 사용자 등록 투표(invoke) 결과 조회(query) Source reference : https://github.com/IBM/evote
  • 97. Frontend coding ! 인증 토큰 처리 사용자 등록시 응답으로 받은 토큰을 저장하고 이를 투표화면으로 파라미터 전달 Source reference : https://github.com/IBM/evote
  • 98. Frontend coding ! 인증 토큰 처리 이전 화면에서 파라미터로 전달한 토큰을 저장 토큰과 사용자가 선택한 투표 결과를 서버로 전달 서버에서 정상 응답인 경우, 투표조회 결과 화면으로 이동 (토큰을 파라미터로 전달) Source reference : https://github.com/IBM/evote
  • 99. Frontend coding ! 인증 토큰 처리 이전 화면에서 파라미터로 전달한 토큰을 저장 Fabric runtime에 query (w/ auth. Token) 결과를 그래프로 표현서버의 chaincode 중 Query 응답 부분 Source reference : https://github.com/IBM/evote
  • 100. Todo ! 사용자 데이터베이스 구축 및 인증 로직 ! 원장에 투표한 사용자 기록 및 조회 (이중 투표 방지 목적) ! 투표 조직(org1)과 검증 조직(org2)의 분리 Git address : https://github.com/wonyongHwang/kopoVote.git Source reference : https://github.com/IBM/evote
  • 101. This doesn’t work well but it should be okay. ! 체인코드 변경 (library hierarchy changed on fabric 2.0) ! GOPATH 설정 및 체인코드 라이브러리 설치 - 설정 후 source /etc/profile 실행 - go get - go build import ( "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" ) import ( "fmt" "strconv" “github.com/hyperledger/fabric-chaincode-go/shim" pb "github.com/hyperledger/fabric-protos-go/peer" ) export GOROOT=/usr/local/go export GOPATH=$HOME export GOBIN=$GOPATH/bin export FABRIC_HOME=/root/fabric-samples export PATH=$PATH:$GOROOT/bin:$FABRIC_HOME/bin
  • 103. 멀티 노드에서 하이퍼레저 패브릭 네트워크 구성하기 (1/3) (Hyperledger Korea User Group https://github.com/hlkug/meetup/tree/master/201903) ! BYFN 예제를 기본으로 멀티 노드를 구성하는 방법을 익힌다.
  • 104. ! 사전 작업 - Virtual Box, Ubuntu, Docker, Docker-Compose, HLF 등 기본 설치 - 2 nodes 이므로 각 VM의 네트워크는 기본 NAT + 호스트 전용 어댑터이며, 각 호스트 정보 IP를 별도 설정해야 함 멀티 노드에서 하이퍼레저 패브릭 네트워크 구성하기 (2/3) (Hyperledger Korea User Group https://github.com/hlkug/meetup/tree/master/201903)
  • 105. 멀티 노드에서 하이퍼레저 패브릭 네트워크 구성하기 (3/3) (Hyperledger Korea User Group https://github.com/hlkug/meetup/tree/master/201903) 이후 진행은 BYFN과 유사함. 예제의 전체소스는 상단의 링크주소를 참조.