이번 포스팅에서는 네트워크 확장과 관련된 eyfn 튜토리얼에 대해서 살펴보려고한다. 이전 byfn 튜토리얼 뜯어보기 포스팅에서는 최초로 organization들이 모여서 네트워크를 구성하는 것에 대해서 살펴보았다면 eyfn에서는 이미 구성된 네트워크에 새로운 organization을 추가하기 위해서 어떻게 하는지를 알려준다. 그래서 이번 포스팅에서는 Hyperledger Fabric 네트워크에서 어떻게 새로운 organization을 추가할 수 있는지를 위주로 작성해보려고 한다.
Generate Crypto Config
eyfn.sh
를 살펴보면 up
명령어를 사용해서 시작했을 때 엔트리 포인트가 networkUp
함수인 것을 알 수 있다. networkUp
에서 하는 일은 먼저 다음과 같다:
# generate artifacts if they don't exist
if [ ! -d "org3-artifacts/crypto-config" ]; then
generateCerts
generateChannelArtifacts
createConfigTx
fi
generateCerts
First-network 튜토리얼에서는 CA를 따로 사용하지 않으므로 crypto material을 생성하기 위해서 cryptogen
을 사용한다. 다음에 CA를 이용해서 어떻게 인증서를 발급받고 그것을 이용하는지 살펴보도록 하겠다.
cryptogen generate --config=./org3-crypto.yaml
org3-crypto.yaml
에 명시되어있는 Template
과 User
만큼 인증서를 생성한다. generateCerts
를 마치고 나면 org3-artifacts 디렉토리에 crypto-config
가 생긴다.
generateChannelArtifacts
이 함수에서는 configtxgen
툴을 사용하게되는데 기본적으로 configtxgen
은 Fabric 네트워크 channel config와 관련된 파일들을 생성할 수 있게 도와준다. 그리고 configtxgen
이 작동하기 위해선 사용자가 자신이 어떻게 config를 구성할 것인지 먼저 포맷에 맞게 yaml파일을 작성해야하는데 configtxgen
은 이 yaml 파일을 환경변수 FABRIC_CFG_PATH
에서 찾는다.
cd org3-artifacts
export FABRIC_CFG_PATH=$PWD
configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json
# copy orderer MSP to org3
cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/
eyfn에서 org3과 관련된 네트워크 config yaml 파일이 org3-artifacts 디렉토리에 config.yaml로 있기 때문에 해당 경로에 맞게 환경변수를 설정해준다.
다음으로 configtxgen -printOrg
를 이용해서 config.yaml
에 Org3MSP에 해당하는 organization의 설정을 org3.json
으로 쓴다. 나중에 이 org3.json
을 이용해서 기존에 존재하던 mychannel의 config를 수정하고 org3이 mychannel에 들어갈 수 있도록 할 것이다.
마지막으로 orderer의 MSP를 org3의 crypto crypto-config
로 복사를 하는데 이는 나중에 org3에서 ordering service를 이용하기 위해서이다.
Create Updated ConfigTx
이제 네트워크 밖에서 할 수 있는 사전작업은 모두 마쳤다. 다음으로 해야할 일은 mychannel의 config를 수정하고 mychannel에 속해있는 organization들에게 새로운 organization인 org3이 들어올 수 있도록 허가를 받아야한다. Hyperledger Fabric이 private chain이고 PoA이기 때문에 이와 같이 채널의 기존 그룹으로부터 허가를 받아야 들어올 수 있다.
docker exec cli scripts/step1org3.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE
그렇기 때문에 이제 위의 명령어처럼 도커로 직접 들어가서 작업하게된다. (여기서 조금 악랄한 부분이있다.. 좀 쉽게 만들 수 있었을 거 같은데..)
. scripts/utils.sh
apt-get -y update && apt-get -y install jq
step1org3.sh에서 위와 같이 먼저 필요한 모듈들 임포트하고 jq 패키지를 설치한다.
fetchChannelConfig
먼저 mychannel 채널의 config를 수정하기 위해서 채널의 config block을 가져와서 그 중에서도 config를 담고 있는 부분만 가져온다.
setOrdererGlobals
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL --tls --cafile $ORDERER_CA
채널의 configuration block을 가져오는 부분이다. 현재 우리는 cli 컨테이너에 들어와있고 네트워크에 떠있는 orderer MSP로 동작하기 위해서 setOrdererGlobals
를 사용했다. 그리고 peer channel
을 통해서 mychannel의 config block을 가져온다. 그리고 tls를 사용한다면 위와 같이 orderer의 tls certification도 같이 제출해야한다.
위의 명령을 실행시키고 현재 디렉토리를 확인해보면 config_block.pb
의 이름으로 config block이 존재하는 것을 확인할 수 있다.
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config >"${OUTPUT}"
configtxlator
는 기본적으로 json또는 protobuf 형식으로 되어있는 fabric transaction을 서로 반대의 형식으로 변환시켜준다. 또는 서로 다른 config transaction의 델타를 구하는데에도 사용된다. 이 두 번째 기능은 좀 더 나중에 사용된다.
지금은 먼저 configtxlator
를 이용해서 protobuf 형태로 되어있는 config block을 JSON 형태로 바꾼다. 그리고 JSON 파싱을 도와주는 jq를 이용해서 config 값을 담고 있는 부분만 파싱해서 ${OUTPUT}
에 저장한다.
위의 명령을 실행시키고 현재 디렉토리를 확인해보면 config.json
이 생성된 것을 확인할 수 있는데 vim이나 more을 통해서 확인해보면 org1, org2의 설정이 담겨있는 것을 확인할 수 있다.
Append the new organization to current configuration
이전 단계에서 현재 채널의 configuration을 가져왔으니 이제 generateChannelArtifacts
단계에서 만든 org3 configuration 파일인 org3.json
을 여기에 추가해야한다.
jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json
이 단계에서도 이전에 사용한 jq를 사용해서 JSON 파일을 수정하게된다. 위의 jq 명령어를 간단히 설명하면 우선 jq -s '<JSON_FILE_1> * <JSON_FILE_2>'
은 두 개의 JSON 파일의 합집합을 만들게 된다. 그래서 두 개의 JSON 파일을 비교해서 서로에게 없는 부분은 추가하게된다. 여기서 <JSON_FILE_1>
은 .[0]
이 되고 <JSON_FILE_2>
은 {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}
이 된다. 그리고 [0]
, [1]
은 각각 config.json
과 ./channel-artifacts/org3.json
으로 치환된다.
그래서 결과적으로 기존의 configuration에 channel_group.groups.Application.groups.Org3MSP
를 키로 가지고 org3.json
을 벨류로 가지는 필드를 추가하게된다.
createConfigUpdate
여기까지 우리가 생성한 파일을 정리해보면 다음과 같다.
config_block.pb
: 현재 채널의 configuration blockconfig.json
: 현재 채널의 configuration block에서 추출한 channel configuration txmodified_config.json
: org3 organization의 정의를 추가한 channel configuration tx
이제 createConfigUpdate
에서 하는 일은 (1) 먼저 config.json
와 modified_config.json
의 차이를 가지는 JSON 형태의 transaction을 만들고 (2) 두 번째로는 이 transaction을 ordering service에 제출하기 위해서 envelope 형태로 만들게 된다. 이 다음 단계에서 우리는 현재 mychannel에 속해있는 organization들에게 서명을 받게된다.
configtxlator proto_encode --input "${ORIGINAL}" --type common.Config >original_config.pb
configtxlator proto_encode --input "${MODIFIED}" --type common.Config >modified_config.pb
config.json
와 modified_config.json
의 차이를 가지는 transaction을 만들기 위해서 먼저 각각의 JSON 파일들을 protobuf 형태로 바꾼다. 그리고 각각은 original_config.pb
, modified_config.pb
의 이름을 가지게된다.
# calculate the delta between original_config.pb and modified_config.pb
configtxlator compute_update --channel_id "${CHANNEL}" --original original_config.pb --updated modified_config.pb >config_update.pb
# decode delta protobuf into JSON format
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate >config_update.json
# create envelope to submit to ordering service
echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json
# convert JSON format envelope into protobuf
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope >"${OUTPUT}"
위의 스크립트는 이전에 말한 과정을 풀어낸 것이다. 먼저 org3을 추가하기 이전과 추가한 후의 차이를 가지는 transaction을 configtxlator compute_update
를 통해서 구한 뒤 configtxlator proto_decode
를 통해서 JSON 형식으로 바꾼다. 다음으로 transaction을 ordering service에 제출하기 위해서 envelope 형태로 바꾸고 configtxlator proto_encode
를 통해서 protobuf 형식으로 바꾼다. 위 스크립트를 실행시키면 현재 디렉토리에 결과물인 org3_update_in_envelope.pb
가 생성된다.
이제 남은 과정은 org3_update_in_envelope.pb
에 mychannel에 속한 organization들에게 서명을 받은 뒤 ordering service에 제출하면 새로운 org3가 mychannel에 들어올 준비가 끝난다.
Signing to config transaction
setGlobals 0 1
peer channel signconfigtx -f "org3_update_in_envelope.pb"
setGlobals 0 2
peer channel update -f org3_update_in_envelope.pb -c ${CHANNEL_NAME} -o orderer.example.com:7050 --tls --cafile ${ORDERER_CA}
setGlobals
를 통해서 MSP를 바꾼다. 같은 cli 컨테이너 안이지만 MSP를 바꿈으로써 다른 노드(peer, orderer)의 역할을 할 수 있다. 먼저 setGlobals 0 1
을 통해서 org1이 이전 단계에서 만든 envelope에 peer channel signconfigtx
를 통해서 서명을 한다. 그리고 setGlobals 0 2
를 통해서 org2 MSP로 바꾸고 org1이 서명한 envelope을 ordering service에 제출하게 된다. 이 때 tls를 사용한다면 위의 명령어처럼 orderer의 ca certificate도 --cafile
옵션에 넣어서 같이 제출해야한다.
[channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
[channelCmd] update -> INFO 002 Successfully submitted channel update
유효한 envelope을 만들었다면 ordering service에 envelope을 제출했을 때 위와 같이 성공했다는 메세지가 나온다.
Join Org3’s peers to network
이제 eyfn의 핵심적인 내용은 거의 마무리되었다. 위의 과정이 엄청 복잡하지만 잘 생각해보면 결국에는 Org3의 정의를 담은 transaction을 만들고 orderer에게 제출하기 위한 envelope을 만들었다. 그래서 이제 mychannel 채널 configuration에 Org3이 등록되었기 때문에 org3이 직접 mychannel에 join 요청을 보낼 수 있다.
docker exec Org3cli ./scripts/step2org3.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE
그래서 이제 Org3cli 컨테이너로 들어간다. Hyperledger Fabric에서 채널로 들어가기 위해서는 해당 채널의 genesis block을 이용해야하다.
peer channel fetch 0 $CHANNEL_NAME.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
그래서 위와 같이 mychannel의 genesis block을 가져오기 위해서 orderer에게 요청을 한다. 이 때도 마찬가지로 tls를 사용한다면 orderer의 ca certificate도 같이 제출하여야한다. 위의 명령어를 실행하면 현재 디렉토리에 mychannel.block
이 생성된다. 이것이 mychannel의 genesis block이다.
setGlobals $PEER $ORG
peer channel join -b $CHANNEL_NAME.block
이제 setGlobals
로 MSP를 바꿔가면서 peer channel join
명령어를 실행시킨다. 그리고 실제로 피어들이 추가됐는지 확인하기 위해서 다음과 같은 방법을 쓸 수 있다.
setGlobals $PEER $ORG
peer channel list
root@9d1cb0c37108:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer channel list
[channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Channels peers has joined:
mychannel
위와 같이 setGlobals
로 확인하고 싶은 피어의 MSP를 설정한 뒤 peer channel list
로 현재 피어가 들어가 있는 채널을 확인해볼 수 있다.
Conclusion
이번 포스팅에서는 어떻게하면 Hyperledger Fabric 네트워크에 새로운 organization을 추가할 수 있는지에 대해서 eyfn 튜토리얼을 통해서 살펴보았다. Organization을 추가하기 위한 config transaction을 만드는 부분이 조금 복잡했다. 첫 번째로 기존의 channel config transaction에서 새로운 organization의 config를 추가했다. 두 번째로는 이전 것과 새로운 것의 델타를 이용해 config envelope을 만들었다. 마지막으로는 현재 채널에 존재하고 있는 organization들에게 서명을 받은 뒤 ordering service에 제출하였다. Hyperledger Fabric은 이와같이 프라이빗 체인이고 PoA이기 때문에 기존의 네트워크에서 허가를 해주어야 새로운 노드가 참여할 수 있다.
다음 포스팅에서는 생각해둔 Hyperledger Fabric와 관련된 튜토리얼이 있는데 그것에 대해서 작성해볼 예정이다.
Thanks to the wonderful guide