[Hyperledger] Fabric 튜토리얼(3) - 네트워크 시작하기

Hyperledger Fabric 튜토리얼(3) - 네트워크 시작하기

지난 포스팅에서 예고한 대로 오늘은 채널 추가 이후 네트워크 시작 방법을 알아볼 것이다. 이번 포스팅 또한 공식 사이트의 네트워크 시작하기를 참고로 작성함을 알린다.


네트워크 시작

스크립트를 활용하여 네트워크를 spin up 해 보자. docker-compose 파일은 다운해 둔 이미지를 참조할 것이며, 부트스트랩은 이전에 생성된 genesis.block를 사용하여 orderer를 보호할 것이다.

먼저 네트워크를 시작하자.

1
docker-compose -f docker-compose-cli.yaml up -d

네트워크의 실시간 로그를 보고 싶다면 -d 플래그를 제외하면 된다. 로그 스트림을 보기 위해서는 터미널을 하나 더 열어야 한다.

CLI 컨테이너는 1000초 동안 유휴 상태를 유지한다. 만약 CLI가 사라졌다면 다음의 명령으로 다시 켤 수 있다.

1
docker start cli

환경 변수

실습이 목표인 분들은 환경 변수 파트는 진행하지 않아도 된다. 넘겨도 실습에는 아무 지장 없다.

peer0.org1.example.com에 관한 CLI 명령이 동작하기 위해서는 아래 네 가지 환경 변수로 명령을 시작해야 한다.

1
2
3
4
5
6
# Environment variables for PEER0

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/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=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

변수 peer0.org1.example.com는 CLI 컨테이너로 구워지므로(baked) 굳이 전달하지 않아도 잘 동작한다. 그러나 다른 peer나 orderer에게 값을 전달하고 싶다면 docker-compose-base.yaml의 경로를 살펴보고 적절하게 수정해야 할 것이다.


채널 생성 및 가입

이전 포스팅인 채널 구성 트랜잭션 만들기에서 configtxgen tool을 이용하여 트랜잭션을 생성했다. 이 프로세스를 반복하여 configtxgen 도구에 전달한 것과 동일하거나 다른 프로필을 사용하여 추가 채널 구성 트랜잭션을 생성할 수 있다. 그 다음 이 섹션에 정의된 다른 프로세스를 반복하면 된다.

일단 다음 명령으로 CLI 컨테이너에 들어가자.

1
docker exec -it cli bash

성공했다면 다음의 메시지가 나올 것이다.

1
root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer#

다음으로 생성한 채널 구성 트랜잭션 아티팩트(channel.tx)를 채널 생성 요청의 일부로 orderer에게 전달한다.

이번엔 채널 구성 트랜잭션 생성 섹션(채널 구성 트랜잭션 생성 섹션이라고 함)에서 생성한 채널 구성 트랜잭션 아티팩트를 채널 생성 요청의 한 파트로 주문자에게 전달한다.

-c 플래그로는 채널 구성 트랜잭션의 이름을, -f 플래그로는 채널 구성 트랜잭션을 지정할 수 있다. 이 경우, channel.tx 대신 다른 이름으로 마운트 가능하다.

아래의 명령을 실행하여 CHANNEL_NAME을 매번 전달할 필요가 없도록 CLI 컨테이너 내의 환경 변수를 설정해 보자.

1
2
3
4
5
6
7
8
export CHANNEL_NAME=mychannel

# the channel.tx file is mounted in the channel-artifacts directory within your CLI container
# as a result, we pass the full path for the file
# we also pass the path for the orderer ca-cert in order to verify the TLS handshake
# be sure to export or replace the $CHANNEL_NAME variable appropriately

peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

이 명령은 채널에 참여에 사용되는 초기 블록인<channel-ID.block>을 반환한다. 채널 이름을 바꾸지 않았다면 기본 값인 mychannel.block을 반환한다.

이제 peer0.org2.example.com에 가입하자.

1
2
3
4
5
# 기본적으로는 'peer0.org1.example.com'에만 가입된다.
# <channel-ID.block>은 이전 명령을 리턴한다.
# 채널 이름을 수정하지 않았다면 mychannel.block에 가입된다.
# 다른 이름의 채널을 만들었다면, 적절한 이름의 블록에 가입될 것이다.
peer channel join -b mychannel.block

환경 변수 섹션에서 소개한 네 가지 변수를 적절히 변경하면 필요에 따라 다른 peer가 채널에 참여하도록 만들 수 있다.

채널의 anchor peer 정의를 업데이트하는 것만으로도 모든 peer를 peer0.org2.example.com에 가입시킬 수 있다. CLI 컨테이너에 포함된 기본 환경 변수를 제정의하는 명령은 다음과 같다.

1
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt peer channel join -b mychannel.block

전체 문자열을 전달하는 대신 이러한 환경 변수를 개별적으로 설정할 수 있다. 설정 완료 후 peer channel join명령을 다시 실행하기만 하면 CLI컨테이너가 peer0.org2.example.com 대신 동작한다.


anchor peer 업데이트

채널을 업데이트할 때에는 다음의 명령을 사용하면 된다. 해당 채널의 genesis block 상단에 정보를 추가하는 형식이다.

채널 정의를 업데이트해서 Org1의 anchor peer(peer0.org1.example.com)를 정의하자.

1
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

마찬가지로, 채널 정의를 업데이트하여 Org2에 대한 앵커 피어(peer0.org2.example.com)를 정의한다. Org2 peer에 관한 명령(peer channel join)의 특성상, 적절한 환경 변수를 사용해야 한다.

1
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/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 /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

체인 코드 설치 및 인스턴스화

Go 또는 Node.js로 작성된 샘플 체인 코드를 네 개의 피어 노드 중 하나에 설치해 보자.

Golang

1
2
# this installs the Go chaincode
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/

Node.js

1
2
3
# this installs the Node.js chaincode
# make note of the -l flag; we use this to specify the language
peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/

그 다음 채널에서 체인 코드를 인스턴스화한다. 그러면 채널의 체인 코드가 초기화되고, 체인 코드 승인 정책이 실행되며, 대상 peer에 대한 체인 노드 컨테이너가 실행된다.

Golang

1
2
3
4
# be sure to replace the $CHANNEL_NAME environment variable if you have not exported it
# if you did not install your chaincode with a name of mycc, then modify that argument as well

peer chaincode instantiate -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"

Node.js

1
2
3
4
5
# be sure to replace the $CHANNEL_NAME environment variable if you have not exported it
# if you did not install your chaincode with a name of mycc, then modify that argument as well
# notice that we must pass the -l flag after the chaincode name to identify the language

peer chaincode instantiate -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -l node -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"

Query

chaincode가 제대로 설치되고 상태 DB가 채워지는지 확인하기 위해 a의 값을 쿼리로 불러 보자.

1
2
3
# be sure to set the -C and -n flags appropriately

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

Invoke

이제 10a에서 b로 이동시키자. 이 트랜잭션은 새 블록을 자르고 상태 DB를 업데이트한다.

1
2
3
# be sure to set the -C and -n flags appropriately

peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'

Query

이전 호출이 제대로 실행되었는지 확인하자. 값이 100인 키 A를 초기화하고 이전 호출을 통해 10을 옮겼다. 따라서 아래 쿼리의 실행 결과는 90이 나와야 한다.

1
2
3
# be sure to set the -C and -n flags appropriately

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

결과는 다음과 같다

1
Query Result: 90

트랜잭션은 어떻게 볼 수 있나요?

CLI 도커 컨테이너의 로그를 확인하면 된다.

1
docker logs -f cli

다음과 비슷한 로그가 출력될 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161
2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54
Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query on peer1.org2 on channel 'mychannel' is successful =====================

===================== All GOOD, BYFN execution completed =====================


_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/

체인 코드 로그는 어떻게 확인하나요?

개별 체인 컨테이너를 검사하여 각 컨테이너에 대해 실행된 별도의 트랜잭션을 확인한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker logs dev-peer0.org2.example.com-mycc-1.0
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Init
Aval = 100, Bval = 200

$ docker logs dev-peer0.org1.example.com-mycc-1.0
04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210

$ docker logs dev-peer1.org2.example.com-mycc-1.0
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
Share