มาขึ้นระบบ Blockchain Network ของ Hyperledger Fabric กันเถอะ
“หากการปริ้นท์ Hello World คือจุดเริ่มต้นของการเขียน Program ฉันใด การขึ้นระบบ Test Network คือจุดเริ่มต้นของ Hyperledger Fabric ฉันนั้น”
วันนี้เราจะมาเริ่มขึ้นระบบ network ของ Fabric กัน โดยหัวข้อที่แล้วผมได้กล่าวถึง concept คร่าวๆของ Fabric ว่ามีอะไรบ้าง หากใครที่ยังไม่ได้อ่าน สามารถกลับไปอ่านได้ตามลิงค์ด้านล่างเลยครับ
Test Network เป็นตัวอย่างที่ทาง Hyperledger Fabric เตรียมไว้ให้เราเพื่อใช้ศึกษาการทำงานของระบบ โดยภายในตัว Test Network นั้นมี script ชื่อว่า network.sh ซึ่งภายใน script จะมี option ต่างๆ โดยมี 4 ส่วนหลักๆ ดังนี้
- การสร้าง certificate และ private key (crypto materials) รวมถึง genesis block และ channel configuration (channel artifacts) หรือการใช้ Fabric CA สำหรับสร้าง certificate ให้แต่ละ organization
- การขึ้น node peer ต่างๆ(orderer peer, organization peer) ภายในระบบ
- การสร้าง channel และ join peer ของแต่ละ organization เข้าไปใน channel
- การ Deploy chaincode (install chaincode ลงใน peer และ commit chaincode ไปบน channel)
เนื่องจากผมใช้ macbook (ของบริษัท) ทุกขั้นตอนจะอิงจาก mac os ครับ
Prerequisites
ก่อนที่จะเริ่มกันให้ทำการติดตั้ง Programs ตาม list ด้านล่างกันก่อน สำหรับใครที่มีแล้วก็ข้ามไปยังขั้นตอนถัดไปได้เลย
- Git — version 2.22 หรือสูงกว่า
- cURL — version 7.64.1 หรือสูงกว่า
- Docker — version 17.06.2-ce หรือสูงกว่า
- Docker Compose — version 1.14.0 หรือสูงกว่า
- Golang — version 1.14 หรือสูงกว่า
Samples, Binaries, and Docker Images
- เลือกโฟลเดอร์ที่เราต้องการ download repository มาไว้บนเครื่อง แล้วใช้คำสั่ง
curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.2.2 1.4.9
2.2.2 คือเลข version ของ Fabric Node(peer, orderer, tools, baseos และ ccenv) ส่วน 1.4.9 คือเลข version ของ Fabric CA (เป็น version ล่าสุดของ Fabric CA)
ลอง list directory ดูเราจะได้ fabric-samples มา พร้อมโฟลเดอร์ bin ข้างใน
ลองใช้คำสั่งตามด้านล่างเพื่อดู image ของ Fabric
docker images
ต่อมาให้ add binaries ของ Fabric ไว้ใน Path environment variable เพื่อเรียกใช้ binary ได้จากทุกๆที่
export PATH=<path to download location>/bin:$PATH
ตัวอย่างของผม download ไว้ในโฟลเดอร์ที่ชื่อ hyperledger/ver2.2.2/ ก็จะได้ประมาณนี้
export PATH=~/hyperledger/ver2.2.2/fabric-samples/bin:$PATH
หลังจากเสร็จแล้วลองใช้คำสั่ง cryptogen version เพื่อตรวจสอบว่าเป็น version 2.2.2 หรือยัง
Fabric Test Network
เราจะมาเริ่มขึ้นระบบ Test Network กันครับ โดยสำหรับ blog นี้จะประกอบไปด้วย
- มี 2 organizations (Org1 and Org2) และแต่ละ org จะมีแค่ 1 node peer (peer0)
- มี 1 ordering organization และจะมีแค่ 1 node (orderer peer) ประเภท Raft สำหรับทำหน้าที่เป็น ordering service
- ไม่ขึ้น Fabric CA เนื่องจากเราจะสร้าง certificate และ private key ผ่านคำสั่ง cryptogen ของ Fabric
- ใช้ default database สำหรับ world state นั่นก็คือ levelDB
Bring up Test Network
ไปยังโฟลเดอร์ test-network กัน
cd fabric-samples/test-network
ข้างในนี้เราจะเจอ script ชื่อว่า network.sh ที่ใช้สำหรับขึ้นระบบ หรือ down ระบบ รวมไปถึงการ create channel และ deploy chaincode หากเราลอง run คำสั่ง ./network.sh -h จะแสดง command ต่างๆ มาให้ดู
เรามาเริ่มขึ้นระบบ Test Network ด้วยคำสั่ง
./network.sh up
หลังจากเสร็จแล้วจะมี list ของ container ขึ้นมาให้เราดู
- เราจะได้มา 2 orgs ด้วยกันนั่นคือ org1 และ org2 โดยแต่ละ org จะมี peer0.org1.example.com และ peer0.org2.example.com เป็น node ของตัวเอง
- มี orderer.example.com คือ orderer node สำหรับเป็น ordering service ของ Test Network นี้
- cli เป็น tool peer ที่ใช้สำหรับเชื่อมไปยัง network โดยเราสามารถทำการ update channel หรือ deploy chaincode ผ่านตัวนี้ได้เช่นเดียวกัน (ในกรณี Test Network นี้ใช้สำหรับอัพเดท anchor peer ไปยัง configuration ของ channel)
Create Channel
ขั้นตอนนี้จะเป็นการสร้าง channel เพื่อให้ Org1 และ Org2 สามารถ communicate กันได้ รวมถึงการ join Org1 และ Org2 เข้าไปใน channel ที่สร้างขึ้นมา ด้วยคำสั่ง
./network.sh createChannel
โดย default เราจะได้ channel ที่มีชื่อว่า mychannel
หลังจากที่ join channel เสร็จแล้ว ถ้าเราสังเกตดีๆ จะเห็นว่ามีการ set anchor peer ของ org1 (และ org2 ด้วย) ในกรอบสีแดงตามภาพ
anchor peer คือ peer ของ org ที่เรา run ขึ้นมา เปรียบได้กับ peer หน้าด่าน เพื่อให้ peer ของ org อื่นๆ สามารถตรวจค้น(discover) และสื่อสาร (communicate) กันได้ การ set ตัว anchor peerนั้นเราต้องอัพเดท configเข้าไปใน channel โดย anchor peer สามารถมีได้หลายตัว เพื่อป้องกัน single point of failure
Deploy Chaincode
เราสามารถ deploy chaincode ด้วยคำสั่ง
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
- -ccn (chaincode name) สำหรับตั้งชื่อ chaincode
- -ccp (chaincode path) สำหรับบอกว่า chaincode อยู่ที่ path ไหน
- -ccl (chaincode language) สำหรับบอกว่า source code ของ chaincode เป็นภาษาอะไร
หากใครติดปัญหา checksum mismatch ของตัว godog ให้แก้ปัญหาด้วยการ export GOPROXY=”proxy.golang.org,direct” แล้วเข้าไปลบบรรทัดที่เป็น checksum ของ godogใน go.sum ซึ่งจะอยู่ในโฟลเดอร์ fabric-samples/asset-transfer-basic/chaincode-go จากนั้นลองใช้คำสั่ง deploy chaincode ดูอีกรอบ (special thanks to พี่ยอด เทพ golang ของเรานั่นเอง)
เท่านี้เราก็ deploy chaincode ลงบน mychannel ได้สำเร็จแล้ว ต่อไปเราลองมา invoke ตัว chaincode ที่เรา deploy ขึ้นไปกันดู
เริ่มแรกให้ export Fabric config ชี้ไปยัง core.yaml ที่อยู่ในโฟลเดอร์ fabric-samples/
export FABRIC_CFG_PATH=$PWD/../config/
จากนั้นเราต้อง export environment เพื่อบอกว่า เราจะใช้ peer0 ของ Org1 ในการทำงาน
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
run คำสั่งข้างล่างเพื่อ invoke chaincode
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'
หากสำเร็จจะขึ้น log มาตามภาพ
จากนั้นเราลอง query chaincode ดูข้อมูลที่ได้จากการ InitLedger ตามคำสั่ง
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
หากสำเร็จจะขึ้นข้อมูลที่เรา InitLedger ตอน invoke ขึ้นมาให้ดู
เท่านี้เราก็ได้ Fabric Network ที่มี consortium อยู่ 2 organizations ด้วยกันได้แก่ Org1 และ Org2 และมี orderer organization ทำหน้าที่เป็น ordering service อยู่ 1 peer ประเภท Raft พร้อมด้วย channel ชื่อว่า mychannel และ chaincode ที่ deploy ไว้มีชื่อว่า basic
Bring down Test Network
หากเราต้องการที่จะ down ระบบ Test Network สามารถใช้คำสั่งตามด้านล่าง
./network.sh down
คำสั่งนี้จะทำการลบทุก node peer และ chaincode รวมไปถึง crypto material และ channel artifact เพื่อล้างข้อมูลทั้งหมดออก ย้อนกลับไปเหมือนว่ายังไม่ได้ขึ้นระบบ Test Network
Step by Step
หลังจากที่เราขึ้นระบบ Test Network ด้วย script ชื่อ network.sh กันไปแล้ว ทีนี้เรามาดูกันว่าภายใน script นั้นมันทำอะไรบ้าง ด้วยการขึ้นระบบแบบ manual กันทีละ step (อย่าลืม down ระบบ Test Network ก่อน)
Generate Certificate and Private Key (Crypto Materials)
ก่อนอื่นเลยอย่าลืม export Fabric binary และ Fabric config
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/configtx
ถัดมาเราจะสร้าง crypto material กัน โดยเริ่มจาก orderer org กันก่อน
cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations"
จากนั้นต่อด้วย Org1
cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output="organizations"
และสุดท้ายที่ Org2
cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations"
เมื่อเราเข้าไปดูในโฟลเดอร์ organizations/ จะมี directory ที่ถูก generate ขึ้นมามากมายพร้อมด้วย certificate และ private key
เราได้เตรียม crypto materials ไว้สำหรับขึ้นระบบ Test Network เรียบร้อยแล้ว ซึ่งเราจะได้หน้าตาของ Test Network ที่ยังไม่มีอะไรตามภาพด้านล่าง
Create a Channel Genesis Block
ถัดมาเราจะสร้าง genesis block ตามคำสั่งด้านล่าง
configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block
-profile คือชื่อของ config ที่ถูก set ไว้ใน configtx.yaml ตามภาพ
สังเกตว่าเราใช้ channelID ชื่อว่า system-channel ก่อน ยังไม่ใช่ mychannel เพื่อทำการสร้าง genesis block
system channel คือ channel ตั้งต้นที่ใช้สำหรับ config channel อื่นๆ ใช้กำหนดว่าจะมี orderer และ organizationใดอยู่ในระบบบ้าง
ลองไปดูในโฟลเดอร์ system-genesis-block/ จะเจอ genesis.block อยู่ข้างใน
genesis.block คือ block ตั้งต้นซึ่งจะเก็บ configuration เบื้องต้นต่างๆที่จำเป็นต้องใช้ในการขึ้นระบบ Network
Bring up Node and Network
ขั้นตอนนี้เราจะขึ้นระบบ network ด้วยคำสั่ง
IMAGE_TAG=latest docker-compose -f ./docker/docker-compose-test-net.yaml up -d
หลังจากนั้นลอง docker ps ดูจะเห็นว่ามี container ขึ้นมาเรียบร้อยแล้ว
เราได้มีการ run ตัว orderer node ที่ใช้ genesis.block สำหรับ config network ขึ้นมา ทำให้ Test Network ของเราก็มีหน้าตาเพิ่มเติมตามภาพด้านล่าง
Create an Application Channel
เราจะมาสร้าง channel ที่ชื่อว่า mychannel กันแต่ก่อนอื่นเลยจะต้องมี directory สำหรับเก็บ channel artifact กันก่อน
mkdir channel-artifacts
จากนั้นประกาศ channel name เป็น environment variable ไว้
export CHANNEL_NAME="mychannel"
แต่ก่อนที่เราจะเริ่มสร้าง channel artifact กัน ผมอยากให้เข้าไปแก้ไฟล์ configtx.yaml ที่อยู่ในโฟลเดอร์ configtx/ กันก่อนโดยใส่ config แทรกไปยังบรรทัดที่ 73 ของ Org1 และ บรรทัดที่ 103 (หลังจากแทรกบรรทัดของ Org1 แล้ว) ของ Org2 ตามภาพ
ที่ต้องเพิ่ม config แบบนี้เนื่องจากเราจะสร้างไฟล์ config ที่ใช้สำหรับอัพเดท anchor peer ด้วยคำสั่ง configtx กันไว้ก่อนเลย โดยไม่จำเป็นที่จะต้อง fetch ตัว channel config จาก Network แล้วมาทำการอัพเดท channel configในภายหลัง เหมือนที่ใน script ของ network.sh กระทำ (เนื่องจากการแก้ไขใน channel config จะมีขั้นตอนที่ซับซ้อน ผมจึงขออนุญาตทำแบบนี้เพราะจะทำให้เข้าใจได้ง่ายกว่า ส่วนเรื่องการแก้ไข channel config นั้นขอยกไปอธิบายในส่วนของการ add organization ที่ 3 เข้าไปในระบบ Test Network ที่กำลัง run อยู่ครับ)
เมื่อแก้ไข configtx.yaml เรียบร้อยแล้วให้ใช้คำสั่งตามด้านล่างเพื่อสร้างไฟล์ config ของ mychannel
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/${CHANNEL_NAME}.tx -channelID $CHANNEL_NAME
-profile คือชื่อของ config ที่ set ไว้ใน configtx.yaml ตามภาพ
เราจะได้ไฟล์ mychannel.tx มา
mychannel.tx คือ ไฟล์ config ของ application channel สำหรับเอาไว้สร้าง channel ที่มีชื่อว่า mychannel ขึ้นมา
จากนั้นให้เราสร้างไฟล์ config ของ anchor peer ด้วยคำสั่ง (อย่าลืม edit configtx.yaml ตามที่บอกไปด้านบน)
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/${CHANNEL_NAME}Org1MSPanchor.tx -channelID ${CHANNEL_NAME} -asOrg Org1MSP
และสำหรับ Org2
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/${CHANNEL_NAME}Org2MSPanchor.tx -channelID ${CHANNEL_NAME} -asOrg Org2MSP
เราจะได้ไฟล์เพิ่มขึ้นมาใน channel-artifacts ตามภาพ
mychannelOrg1MSPanchor.tx คือ ไฟล์ config สำหรับอัพเดท anchor peer เข้าไปใน channel
เมื่อเราได้ channel artifact ครบแล้ว เราจะเริ่มทำการ create mychannel ผ่านทาง peer0 ของ Org1 แต่ก่อนอื่นเราจะต้อง export Fabric config ให้ชี้ไปยังไฟล์ core.yaml ที่อยู่ใน fabric-samples ก่อน
export FABRIC_CFG_PATH=$PWD/../config/
core.yaml คือไฟล์ basic config ที่ทุกๆ peer มีไว้ใช้สำหรับตั้งค่าเริ่มต้น ซึ่งเราสามารถ override config ผ่านทาง environment variable ที่เริ่มต้นด้วยคำว่า CORE เช่น CORE_PEER_LOCALMSPID=”Org1MSP”
จากนั้นให้ export environment variable เพื่อบอกว่า เราจะใช้ peer0 ของ Org1 ในการทำงาน
export CORE_PEER_TLS_ENABLED=true
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
- CORE_PEER_TLS_ENABLED ใช้ระบุว่าให้คุยกันด้วย TLS
- ORDERER_CA ใช้ระบุถึง TLS Certificate ของ orderer
- CORE_PEER_LOCALMSPID ใช้ระบุ MSP ID ของ Org1
- CORE_PEER_TLS_ROOTCERT_FILE ใช้ระบุถึง TLS Certificate ของ peer0 Org1
- CORE_PEER_MSPCONFIGPATH ใช้ระบุถึง MSP directory ของ Admin ของ Org1
- CORE_PEER_ADDRESS ใช้ระบุถึง address ของ peer0 Org1
จากนั้นก็สร้าง mychannel ด้วยคำสั่ง
peer channel create -o localhost:7050 -c $CHANNEL_NAME --ordererTLSHostnameOverride orderer.example.com -f ./channel-artifacts/${CHANNEL_NAME}.tx --outputBlock ./channel-artifacts/${CHANNEL_NAME}.block --tls --cafile $ORDERER_CA
เราจะได้ไฟล์ mychannel.block มาตามภาพ
เราได้ config mychannel เตรียมไว้แล้ว ก็จะได้หน้าตา Test Network แบบนี้
Join Peer to the Channel
ต่อไปเราจะนำ node peer ของแต่ละ org มา join ใน mychannel โดยเริ่มจาก Org1 ด้วยคำสั่ง
peer channel join -b ./channel-artifacts/${CHANNEL_NAME}.block
เราสามารถตรวจสอบได้ว่า peer0 ของ Org1 นั้น join ใน mychannel หรือยังด้วยคำสั่ง
peer channel getinfo -c ${CHANNEL_NAME}
หากสามารถดู block height ได้ตามภาพแสดงว่า join ใน mychannel เรียบร้อยแล้ว
หน้าตาของ Test Network ก็จะมี peer0 ของ Org1 ได้ join มาแล้วตามภาพ
จากนั้นสลับไปใช้งานด้วย Org2 กัน
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
คราวนี้เราลองตรวจสอบกันก่อนว่า Org2 ได้ join ใน mychannel หรือยัง ด้วยคำสั่งเดียวกันกับที่ใช้ตอนเราเป็น Org1
peer channel getinfo -c ${CHANNEL_NAME}
ผลปรากฎว่าเราไม่สามารถดู block height ได้ตามภาพ แสดงว่า Org2 ยังไม่ได้ join ใน mychannel
ให้เรานำ Org2 join เข้า mychannel ด้วยคำสั่ง
peer channel join -b ./channel-artifacts/${CHANNEL_NAME}.block
คราวนี้ Test Network ก็มี peer0 ของ Org2 เข้ามา join ด้วยตามภาพ
Update Anchor Peer
หลังจากที่ได้นำทั้ง 2 Orgs join ไปที่ mychannel เรียบร้อยแล้ว เราจะมาอัพเดท anchor peer ไปที่ mychannel กัน โดยก่อนอื่นให้เริ่มจาก export environment variable ของ Org1 กัน
export CORE_PEER_TLS_ENABLED=true
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
จากนั้นใช้คำสั่งตามด้านล่างเพื่ออัพเดท anchor peer ของ Org1
peer channel update -o localhost:7050 -c $CHANNEL_NAME -f ./channel-artifacts/mychannelOrg1MSPanchor.tx --tls --cafile $ORDERER_CA
หากสำเร็จจะมี log ขึ้นมาว่า Successfully submitted channel update ตามภาพ
จากนั้นสลับไปใช้ Org2
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
อัพเดท anchor peer ด้วยคำสั่ง
peer channel update -o localhost:7050 -c $CHANNEL_NAME -f ./channel-artifacts/mychannelOrg2MSPanchor.tx --tls --cafile $ORDERER_CA
เท่านี้เราก็อัพเดทให้ peer0 ของ Org1 และ peer0 ของ Org2 เป็น anchor peer เรียบร้อยแล้ว
Chaincode Lifecycle
ใน Fabric version 2 ขึ้นไปมีการปรับเปลี่ยนในส่วนของการ deploy chaincode โดย chaincode ที่จะ deploy นั้นจะต้องได้รับการ approve จาก Org ต่างๆ ที่อยู่ภายใน channel นั้นก่อน ซึ่งจำนวนของ Org ที่ต้อง Approve นั้นก็ขึ้นอยู่กับ lifecycle endorsement ที่ถูก setup ไว้ใน configtx.yaml อีกทีหนึ่ง ผิดกับ Fabric version 1 ที่ไม่มี lifecycle endorsement นี้ ทำให้ Org ใดๆ ก็ตามสามารถ deploy chaincode ได้โดยไม่ต้องได้รับการ approve จาก Org อื่นใน channel
chaincode lifecycle มีอยู่ด้วยกัน 4 ขั้นตอนคือ
- Package the chaincode
- Install the chaincode on your peer
- Approve the chaincode definition for your organization
- Commit the chaincode definition to the channel
ใน manual step นี้เราจะเปลี่ยนไปใช้ chaincode ที่ชื่อว่า marble02 ในการ deploy กัน
Package the chaincode
ก่อนอื่นเลยเราจะต้องทำการ package ตัว source code ของ chaincode โดยให้เราเข้าไปที่ project marble02 กันก่อน
cd ../chaincode/marbles02/go
จากนั้นก็สร้าง vendor ด้วยคำสั่ง
GO111MODULE=on go mod vendor
เราก็จะได้ directory ที่มีชื่อว่า vendor มาตามภาพ
จากนั้นกลับไปที่ directory ของ Test Network
cd ../../../test-network
export environment รอไว้ก่อนเลย
export CHANNEL_NAME="mychannel"
export CC_NAME="marble"
export CC_VERSION="1.0"
CC_NAME คือชื่อ chaincode ที่จะ deploy และ CC_VERSION คือ version ของ chaincode ที่จะ deploy
จากนั้นทำการ package chaincode ด้วยคำสั่ง
peer lifecycle chaincode package ${CC_NAME}.tar.gz --path ../chaincode/marbles02/go --lang golang --label ${CC_NAME}_${CC_VERSION}
เราจะได้ไฟล์ที่มีชื่อว่า marble.tar.gz ตามภาพ
Install the chaincode on your peer
เมื่อเราได้ package ของ chaincode แล้วก็มาเริ่ม install chaincode กันเลยโดยเริ่มจากการเรียกใช้งาน Org1
export CORE_PEER_TLS_ENABLED=true
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
จากนั้นใช้คำสั่งตามด้านล่างเพื่อ install chaincode
peer lifecycle chaincode install ${CC_NAME}.tar.gz
หากสำเร็จจะมี log ขึ้นมาตามภาพ
สลับไปใช้งาน Org2 แล้ว install chaincode
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051peer lifecycle chaincode install ${CC_NAME}.tar.gz
หากเราลอง run คำสั่ง docker images จะเห็น image ของ chaincode ถูกสร้างขึ้นมาหลังจากการ install ของทั้ง 2 Orgs
สามารถตรวจสอบ chaincode ที่ install ไปแล้วได้ด้วยคำสั่ง
peer lifecycle chaincode queryinstalled
เราจะได้ข้อมูลกลับมาตามภาพ
ให้เรา copy เอา Package ID ออกมา export ไว้เพื่อใช้สำหรับการทำ approve
export PACKAGE_ID=marble_1.0:2f985e43e021b044a5a6f774b201c47b79669ef593c0b4fc36398c7b68c9c63a
Approve the chaincode definition for your organization
ให้ Org2 ทำการ approve chaincode ก่อนด้วยคำสั่ง
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --package-id ${PACKAGE_ID} --sequence 1
สามารถตรวจสอบได้ว่ามี Org ไหน Approve มาแล้วบ้างด้วยคำสั่ง
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --sequence 1 --output json
จะเห็นได้ว่าตอนนี้มีแค่ Org2 ที่ approve แล้วตามภาพ
สลับไปใช้ Org1 แล้วทำการ approve chaincode
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --package-id ${PACKAGE_ID} --sequence 1
ลองตรวจสอบดูอีกครั้งว่ามี Org ไหน Approve มาแล้วบ้างด้วยคำสั่ง
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --sequence 1 --output json
จะเห็นว่า chaincode ได้ถูก approve โดย Org1 และ Org2 เรียบร้อยแล้วตามภาพ
Commit the chaincode definition to the channel
คราวนี้เราก็สามารถ commit chaincode ได้แล้วด้วยคำสั่ง
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --sequence 1 --tls --cafile $ORDERER_CA --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
ถ้าเราสังเกตจะเห็นว่าตอน commit เราจะต้องระบุ peer address ทั้ง 2 Orgs เนื่องมาจาก lifecycle endorsement policy ที่อยู่ใน configtx.yaml ระบุไว้ว่าเป็น MAJORITY ตามภาพด้านล่าง นั่นหมายความว่าจะต้องได้รับ signature ของทั้ง 2 Org ถึงจะสามารถ commit chaincode ได้ (หากมี 3 Orgs จะต้องได้รับ signature 2 ใน 3 ถึงจะสามารถ commit ได้)
เราสามารถตรวจสอบ chaincode ที่ commit ไปแล้วได้ด้วยคำสั่ง
peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name ${CC_NAME}
เราจะได้ข้อมูลมาตามภาพ แสดงว่า chaincode สามารถทำงานได้แล้ว
หากลอง docker ps เราจะเห็น container ของ chaincode ถูก run ขึ้นมาตามภาพ
สุดท้ายแล้วเราก็จะได้หน้าตาของ Test Network ตามภาพด้านล่าง
Invoke & Query Chaincode
คราวนี้ลองมาทำการ invoke chaincode โดยการเพิ่มข้อมูลลง ledger กันด้วยคำสั่ง
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n ${CC_NAME} --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
จะเห็น log แสดงว่า invoke successful ตามภาพ แสดงว่าเราเพิ่มข้อมูลลง ledger สำเร็จ
ลอง query ข้อมูลที่เราเพิ่งเพิ่มลงใน ledger กันดูด้วยคำสั่ง
peer chaincode query -C $CHANNEL_NAME -n ${CC_NAME} -c '{"Args":["readMarble","marble1"]}'
ก็จะแสดงข้อมูลที่อยู่ใน ledger มาตามภาพด้านล่าง
จบกันไปแล้วครับสำหรับการขึ้นระบบ Network ของ Hyperledger Fabric ซึ่งเห็นได้ว่ามีขั้นตอนอยู่มากมายเพื่อที่จะได้ระบบที่พร้อมให้ใช้งาน แต่ทาง Hyperledger Fabric ก็ได้ทำ script ที่ใช้สำหรับขึ้นระบบแบบง่ายๆ มาให้เราได้ศึกษากัน
ตอนแรกผมตั้งใจไว้ว่าจะเขียนการขึ้นระบบของ version 1.4 แต่ปัจจุบันนั้นมีไปถึง version 2.3 แล้ว และเป็นโอกาสที่ดีที่ผมจะได้ลองขึ้นระบบของ version 2 ด้วย ซึ่งระหว่าง version 1.4 กับ version 2.X ก็ได้มี feature หลายอย่างที่แตกต่างกัน ไม่ว่าจะเป็นเรื่องของ Chaincode Lifecycle ที่มีขั้นตอนในการ deploy chaincode เพิ่มเข้ามา หรือจะเรื่องของ ordering service ที่ orderer type แบบ solo และ kafka ได้ถูกยกเลิก(deprecated)ใช้งานไปแล้ว แต่ทั้งนี้ใน version 1.4 ก็เป็น LTS (Long Term Support) ยังคงสามารถใช้ในการพัฒนาระบบได้ หากใครต้องการดูเพิ่มเติมว่า version 2.X นั้นมีอะไรเพิ่มเข้ามาบ้าง สามารถเข้าไปดูได้ ที่นี่ ครับ