2. Public vs Private
2
퍼블릭 블록체인 컨소시엄(프라이빗) 블록체인
관리 주체 모든 거래 참여자 컨소시엄에 속한 참여자
데이터 접근 누구나 접근 가능 허가 받은 사용자만 접근 가능
합의 알고리즘 PoW, PoS 등 PBFT 등
보상/수수료 O X
구현 사례 Bitcoin, Ethereum Hyperledger Fabric, R3 Corda
3. Hyperledger Fabric의 특징
3
• Linux Foundation에 의해 설립된 오픈 소스 프로젝트
• 초기 IBM이 제공한 코드를 기반으로 현재 30여 조직에서 개발 참여 중
• 모듈화 및 구성이 가능한 아키텍처
• 범용 프로그래밍 언어로 작성된 Smart Contract(Chaincode)를 지원하는 최초의 분산 원장 플랫폼
- Java, Go, Node.js
• 허가형 블록체인(Permissioned Blockchain)
• 플러그 가능 컨센서스 프로토콜을 지원
• 암호 화폐 불필요
• 개인 정보 보호 및 기밀성 유지
4. Hyperledger Fabric 구성 요소
4
• 채널(Channel)
• 조직(Organization)
• 피어(Peer)
• 오더러(Orderer)
• 원장(Ledger)
• 체인코드(Chaincode)
7. Transaction Flow
8
B.C.N.W
Orderer
Endorser Peer #1
(Committer Peer)
Leader Peer #2
Anchor Peer #3
Peer #4
(Committer Peer)
Peer #5
(Committer Peer)
Channel #1
Application #1
① Tx 요청
③ 실행 결과 전달
② Tx 실행, 전자서명
④ Tx 등록 요청
⑤ 순서 지정, 전자서명, 블록생성
(대상 Channel 내의 Leading peer에게
블록 반영 요청)
⑦ 블록체인 반영 요청
broadcasting
Endorser Peer #12
(Committer Peer)
Leader Peer #12
Anchor Peer #13
Peer #14
(Committer Peer)
Peer #15
(Committer Peer)
Application #12
⑥ 블록 반영 요청
⑦ 블록체인 반영 요청
broadcasting
Ledger
① Tx 조회 요청
② 결과 전달
출처 : NDS Corporation
8. byfn(Build Your First Network) 구성
9
mychannel
peer
0
peer
1
orderer
peer
0
peer
1
byfn
org
1
org
2
mycc
mycc
mycc
mycc
genesis.block
mychannel.block
9. 1. 인증서 및 아티팩트 생성
10
• byfn.sh 스크립트의 generate 함수를 이용하면 손쉽게 생성 가능
• crypto-config.yaml 파일과 cryptogen 도구를 이용해 각 노드의 인증서 및 서명 키 생성
• configtx.yaml 파일과 configtxgen 도구를 이용해 구성 아티팩트 생성
- Orderer 제네시스 블록
- 채널 구성 트랜잭션
- 앵커 피어 트랜잭션
10. 1. 인증서 및 아티팩트 생성
11
• 인증서 생성
- cryptogen : Org와 해당 Org에 속한 구성 요소 모두에 대한 인증서 및 키 세트를 생성 (x509 방식)
- cryptogen 도구가 위치한 경로로 cryptogen 명령 실행 필요
- --config 옵션 : crypto-config.yaml 파일의 경로 지정
- --output 옵션 : 인증서 및 키가 생성될 디렉터리 지정 (default: "crypto-config")
# 인증서 생성
$ ../bin/cryptogen generate --config=./crypto-config.yaml
11. 1. 인증서 및 아티팩트 생성
12
• FABRIC_CFG_PATH 설정
- FABRIC_CFG_PATH : configtx.yaml 파일이 존재하는 경로
- configtxgen 도구가 위치한 경로로 configtxgen 명령 실행 필요
$ export FABRIC_CFG_PATH=$PWD
12. 1. 인증서 및 아티팩트 생성
13
• Orderer 제네시스 블록 생성
- Ordering 서비스를 위한 제네시스 블록
- Orderer 시스템 채널명을 byfn-sys-channel로 지정. (~v1.3: testchainid로 자동 설정)
- -profile 옵션 : configtx.yaml 파일의 Profiles 섹션에서 정의한 Orderer 제네시스 프로파일명
- -outputBlock 옵션 : 생성할 Orderer 제네시스 블록 파일명 및 경로 지정
- genesis.block 파일 생성
# Orderer 제네시스 블록 생성
$ ../bin/configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -
outputBlock ./channel-artifacts/genesis.block
13. 1. 인증서 및 아티팩트 생성
14
• 채널 구성 트랜잭션 생성
- -profile 옵션 : configtx.yaml 파일의 Profiles 섹션에서 정의한 채널 프로파일명
- -outputCreateChannelTx 옵션 : 생성할 채널 구성 트랜잭션 파일명 및 경로 지정
- -channelID 옵션 : 생성할 채널명
- channel.tx 파일 생성
# 채널 구성 트랜잭션 생성
$ export CHANNEL_NAME=mychannel && ../bin/configtxgen -profile TwoOrgsChannel -
outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
14. 1. 인증서 및 아티팩트 생성
15
• 앵커 피어 트랜잭션 생성
- -profile 옵션 : configtx.yaml 파일의 Profiles 섹션에서 정의한 채널 프로파일명
- -outputAnchorPeersUpdate 옵션 : 생성할 앵커 피어 트랜잭션 파일명 및 경로 지정
- -channelID 옵션 : 앵커피어를 지정할 채널명 (소문자여야함)
- -asOrg 옵션 : 앵커 피어의 Org 정의
- Org1MSPanchors.tx, Org2MSPanchors.tx 파일 생성
# 앵커 피어 트랜잭션 생성
$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-
artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-
artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
15. 2. 네트워크 실행
16
• byfn.sh 스크립트의 up 함수를 이용하면 손쉽게 실행 가능
• 인증서 및 아티팩트 생성부터 채널 및 체인코드 설정까지 모두 진행
• 기본적으로 다음 컨테이너들이 실행됨
- orderer.example.com
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com
- cli
16. 2. 네트워크 실행
17
• 수동으로 네트워크 실행
- -f 옵션을 통해 docker-compose.yaml 파일 지정 (다중 지정 가능)
- -d 옵션을 통해 백그라운드로 실행
- docker-compose-cli.yaml 파일을 사용해서 기본 네트워크 실행
# 블록체인 네트워크 컨테이너 실행
$ docker-compose -f docker-compose-cli.yaml up –d #기본 네트워크 실행
$ docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up –d
17. 3. 채널 설정
18
• 모든 peer 명령은 cli 컨테이너 내에서 실행 필요
• cli 컨테이너에서 실행하는 명령의 기본 대상은 peer0.org1.example.com
# cli 컨테이너 접속
$ docker container exec -it cli bash
# export CHANNEL_NAME=mychannel
# export
ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/
example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
18. 3. 채널 설정
19
• 채널 생성(peer channel create)
- peer channel create : 채널을 생성하고 제네시스 블록을 작성
- -o 옵션 : ordering 서비스의 endpoint 및 주소
- -c 옵션 : 생성할 채널 ID
- -f 옵션 : 채널 구성 트랜잭션 파일의 경로
- --tls 옵션 : TLS 통신 활성화 여부 (default: true)
- --cafile 옵션 : TLS 통신을 위한 orderer의 TLS 루트 인증서
- <채널ID>.block 이라는 파일명의 제네시스 블록 생성
# 채널 생성
# peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-
artifacts/channel.tx --tls --cafile $ORDERER_CA
20. 3. 채널 설정
21
• 채널 조인(peer channel join) - 계속
# peer0.org2.example.com을 채널에 조인
# CORE_PEER_ADDRESS=peer0.org2.example.com:9051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peer
Organizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/pee
rOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
peer channel join -b mychannel.block
21. 3. 채널 설정
22
• 채널 조인(peer channel join) - 계속
# peer1.org2.example.com을 채널에 조인
# CORE_PEER_ADDRESS=peer1.org2.example.com:10051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peer
Organizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/pee
rOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
peer channel join -b mychannel.block
22. 3. 채널 설정
23
• 채널 조인 확인(peer channel list)
- peer channel join : 채널에 peer를 조인
- peer 컨테이너 내에서 실행
- 해당 peer에 채널ID로 시작하는 체인이 생성
# 채널 조인 확인
# peer channel list
# ls /var/hyperledger/production/ledgersData/chains/chains
23. 3. 채널 설정
24
• 앵커 피어 업데이트(peer channel update)
- peer channel update : 파일에 정의된 구성 트랜잭션(.tx)을 사용하여 채널을 업데이트하고 구성
트랜잭션(.tx)을 채널의 모든 peer로 전송해 채널 구성 사본을 갱신
- -o 옵션 : ordering 서비스의 endpoint 및 주소
- -c 옵션 : 업데이트할 채널 ID
- -f 옵션 : 앵커 peer 트랜잭션 파일의 경로
- --tls 옵션 : TLS 통신 활성화 여부 (default: true)
- --cafile 옵션 : TLS 통신을 위한 orderer의 TLS 루트 인증서
# Org1의 앵커 피어 업데이트
# peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-
artifacts/Org1MSPanchors.tx --tls --cafile $ORDERER_CA
24. 3. 채널 설정
25
• 앵커 피어 업데이트(peer channel update) - 계속
# Org2의 앵커 피어 업데이트
#
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrg
anizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:9051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerO
rganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-
artifacts/Org2MSPanchors.tx --tls --cafile $ORDERER_CA
25. 4. 체인코드 설정
26
• 체인코드 설치(peer chaincode install)
- peer chaincode install : 지정된 체인코드를 패키징하고 이를 peer의 경로에 저장
- -n 옵션 : 설치할 체인코드 이름
- -v 옵션 : 설치할 체인코드 버전
- -p 옵션 : 설치할 체인코드 경로
- Go언어로 작성한 체인코드는 /opt/gopath/src 이후의 경로로 작성 필요
- Java/Node.js로 작성한 체인코드는 전체 경로로 작성 필요
# peer0.org1.example.com에 체인코드 설치
# peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
26. 4. 체인코드 설정
27
• 체인코드 설치(peer chaincode install) - 계속
# peer1.org1.example.com에 체인코드 설치
# CORE_PEER_ADDRESS=peer1.org1.example.com:8051
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
29. 4. 체인코드 설정
30
• 체인코드 설치 확인(peer chaincode list)
# 설치한 체인코드 확인
# peer chaincode list --installed
30. 4. 체인코드 설정
31
• 체인코드 인스턴스화(peer chaincode instantiate)
- peer chaincode instantiate : 지정된 체인코드를 네트워크에 배포
- -c 옵션(constructor) : JSON 형식의 체인코드 생성자 메시지 (default:"{}")
- -P 옵션(policy) : 인스턴스화할 체인코드와 연관된 보증 정책
- 보증 정책 검사 후 체인코드에 대한 컨테이너가 실행됨
# 체인코드 인스턴스화
# peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C
$CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR
('Org1MSP.peer','Org2MSP.peer')"
31. 4. 체인코드 설정
32
• 체인코드 인스턴스화 확인(peer chaincode list)
- 체인코드 컨테이너가 생성된 것을 확인
# 인스턴스화한 체인코드 확인
# peer chaincode list --instantiated -C $CHANNEL_NAME
# 체인코드 컨테이너 확인
# docker container ls
32. 4. 체인코드 설정
33
• 체인코드 Query 실행(peer chaincode query)
- peer chaincode query : 체인코드 함수 호출 결과 출력 (트랜잭션을 생성하지 않음)
- -C 옵션(channelID) : 채널 ID
- -n 옵션(name) : 체인코드 이름
- -c 옵션(constructor) : JSON 형식의 체인코드 생성자 메시지 (default:"{}")
# 자산 a에 대한 query result 값 조회
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
# 자산 b에 대한 query result 값 조회
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","b"]}'
33. 4. 체인코드 설정
34
• 체인코드 Invoke 실행(peer chaincode invoke)
- peer chaincode invoke : 지정된 체인코드 호출 (트랜잭션 생성)
- -o 옵션 : ordering 서비스의 endpoint 및 주소
- --tls 옵션 : TLS 통신 활성화 여부 (default: true)
- --cafile 옵션 : TLS 통신을 위한 orderer의 TLS 루트 인증서
- -C 옵션(channelID) : 채널 ID
- -n 옵션(name) : 체인코드 이름
- -c 옵션(constructor) : JSON 형식의 체인코드 생성자 메시지 (default:"{}")
# 체인코드 Invoke 실행
# peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C
$CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
34. 4. 체인코드 설정
35
• 체인코드 Query 실행(peer chaincode query)
- peer chaincode query : 체인코드 함수 호출 결과 출력 (트랜잭션을 생성하지 않음)
- -C 옵션(channelID) : 채널 ID
- -n 옵션(name) : 체인코드 이름
- -c 옵션(constructor) : JSON 형식의 체인코드 생성자 메시지 (default:"{}")
# 자산 a에 대한 query result 값 조회
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
# 자산 b에 대한 query result 값 조회
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","b"]}'
35. 5. 네트워크 종료
36
• byfn.sh 스크립트의 down 함수를 이용하면 손쉽게 종료 가능
• docker-compose.yaml 파일에 정의한 모든 컨테이너 중지 및 볼륨 제거
• 체인코드 컨테이너 및 이미지 정리
• 인증서 및 아티팩트 파일 제거
36. 5. 네트워크 종료
37
• 블록체인 네트워크 컨테이너 정리
- --volumes 옵션 : 볼륨도 함께 제거
- --remove-orphans 옵션 : 정의되지 않은 서비스에 대한 컨테이너도 함께 제거
- cli, peer, orderer, couchdb의 모든 컨테이너 및 볼륨 제거
- docker-compose.yaml 파일에서 정의한 Docker 네트워크도 제거
# 블록체인 네트워크 컨테이너 정리
$ docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml down --volumes --
remove-orphans
37. 5. 네트워크 종료
38
• 체인코드 컨테이너 정리
- 블록체인 네트워크 컨테이너를 종료한 후에도 체인코드 컨테이너는 남아있음
- Docker 컨테이너 이름 형식이 "dev-peer.*.mycc.*"인 컨테이너 제거
- mycc 대신 원하는 체인코드 이름을 넣을 경우, 해당 체인코드 컨테이너만 제거
# 체인코드 컨테이너 정리
$ docker container ls –a
$ docker container rm -f $(docker container ls -aq -f "name=dev-peer.*.mycc.*")
38. 5. 네트워크 종료
39
• 체인코드 이미지 정리
- 체인코드 컨테이너 실행을 위해 생성된 체인코드 이미지 제거
- 추출한 이미지 ID 값을 통해 Docker 이미지 제거
# 체인코드 이미지 정리
$ docker image ls
$ docker image rm -f $(docker image ls | grep "dev|none|test-vp|peer[0-9]-" | awk '{print $3}')
39. 5. 네트워크 종료
40
• 인증서 및 아티팩트 제거
- 인증서가 저장된 crypto-config 디렉터리 전체를 제거
- 구성 아티팩트인 *.block 파일과 *.tx 파일을 모두 제거
# 인증서 및 아티팩트 제거
$ rm -rf channel-artifacts/*.block channel-artifacts/*.tx crypto-config
0.6 버전에서는 PBFT 방식으로 합의 알고리즘이 구현.
속도를 위해 1.0에서부터 Endorsing – Ordering – Validating의 3단계 구조를 기반으로 한 합의 알고리즘 구현.
Endorsing Peer들이 트랜잭션을 실행하고 결과 값에 사인을 해서 클라이언트로 돌려준다.
이 값들을 Orderer에게 전달하면 Orderer는 트랜잭션에 순서를 매기고, 블록을 생성해서 Validator에게 전달.
Validator에서는 보증 정책에 맞는지 확인 후 만족하면 원장에 블록 저장.
채널명은 소문자로 지정해야함. 대문자가 포함될 경우, 추후 채널 생성(channel create) 과정에서 오류 발생.
※ docker-compose-cli.yaml 파일에서 cli 서비스에 대한 PEER 환경변수(CORE_PEER_*)를 peer0.org1.example.com을 기준으로 설정했기 때문에, peer0.org1.example.com이 기본 대상이 됨. (환경변수 값에 따라 대상이 달라짐)
※ 채널 ID는 모두 소문자로 구성되어야하며, 250자 미만
Org1과 Org2 내의 모든 peer가 orderer에 있는 mychannel에 조인
※ 채널의 제네시스 블록 상단에 추가 구성 정보를 추가
트랜잭션을 실행하고 보증할 모든 peer에 체인코드 설치 필요
해당 peer의 파일 시스템에 소스 코드를 저장
※ 체인코드를 설치했다고 해서 실제로 돌아가는 상황은 아님. instantiate로 실제 컨테이너를 돌려줘야 체인코드가 동작하게 됨.
※ 컨테이너가 만들어져야하니까 시간이 조금 걸림
※ escc : Endorser System Chaincode. 엔도싱 피어에 의해 호출. 트랜잭션 실행결과에 대한 검증
※ vscc : Validator System Chaincode. 커밋팅 피어에 의해 호출. 보증정책에 대한 유효성 검사
※ 자산 a, b에 대해 각각의 초기값 조회
※ a의 값에서 10을 b에게 줌.
Invoke 명령 시에는 트랜잭션이 생성되기 때문에 ordering 서비스를 거침
※ Invoke를 실행한 이후 자산 a, b의 결과값 조회
※ --remove-orphans 옵션은 docker-compose.yaml 파일에서 서비스를 제거하거나 이름을 변경한 경우에 적용됨
※ 간편하게 모든 컨테이너를 다 제거하는 방법도 있지만, 스크립트 작성 시 자신이 실행했던 네트워크만 종료시킬 수 있도록 이름 형식을 지정
※ 체인코드 이미지를 정리하지 않을 경우, 다른 네트워크에서 실행한 동일한 이름 및 버전의 체인코드에 대해 변경사항이 제대로 적용되지 않을 수 있음