Bring up the Test Network

Truy cập vào sample project fabric-samples/test-network. Tất cả các câu lệnh bên dưới đều được thực thi ở trong thư mục này.

Khởi chạy network bằng câu lệnh sau:

./network.sh up

Trước tiên, nó sẽ sử dụng công cụ cryptogen để tạo ra các file liên quan đến mã hóa (public key, private key, certificate, …) cho từng node dựa trên file cấu hình ở trong thư mụcorganizations/cryptogen. Điều này có thể thấy thông qua output sau:

/home/aleister/Repos/fabric-samples/bin/cryptogen
Generating certificates using cryptogen tool
Creating Org1 Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output=organizations
org1.example.com
+ res=0
Creating Org2 Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output=organizations
org2.example.com
+ res=0
Creating Orderer Org Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output=organizations
+ res=0

Sau đó, nó sẽ dùng Docker Compose với file cấu hình compose/compose-test-net.yaml để khởi chạy các container của các node:

 Network fabric_test                      Created             0.0s 
 Volume "compose_orderer.example.com"     Created             0.0s 
 Volume "compose_peer0.org1.example.com"  Created             0.0s 
 Volume "compose_peer0.org2.example.com"  Created             0.0s 
 Container orderer.example.com            Started             0.1s 
 Container peer0.org1.example.com         Started             0.0s 
 Container peer0.org2.example.com         Started             0.0s 
 Container cli                            Started             0.0s 

Sẽ có một orderer và hai peer được tạo ra. Một tổ chức có thể có nhiều peer node. Ở output trên, mỗi tổ chức có một peer node.

Creating a Channel

Channel là một kênh giao tiếp riêng tư giữa các node cụ thể và chỉ những node được mời vào channel mới có thể thấy những thông tin được trao đổi ở trong channel đó. Mỗi channel có một ledger riêng.

Tạo channel:

./network.sh createChannel

Câu lệnh trên sẽ tạo ra một channel mặc định có tên là mychannel.

Info

Thực chất, câu lệnh trên sẽ gọi đến script scripts/createChannel.sh. Script này sẽ dùng tool configtxgen để tạo ra genesis block của channel dựa vào file cấu hình configtx/configtx.yaml. Sau khi tạo ra channel, network.sh sẽ dùng chương trình ../bin/peer để join hai peer vào channel và móc nối chúng lại với nhau.

Tạo channel với tên tùy ý:

./network.sh createChannel -c channel1

Chúng ta có thể tạo nhiều channel với tên khác nhau. Quy ước đặt tên channel:

  • Chứa các chữ cái viết thường, số trong bảng ASCII, ký tự .-.
  • Độ dài ít hơn 250 ký tự.
  • Bắt đầu bằng một chữ cái.

Khởi chạy network đồng thời tạo channel:

./network.sh up createChannel

Starting a Chaincode on the Channel

Để đảm bảo các transaction của smart contract là hợp lệ, chúng cần phải được ký bởi một vài tổ chức được quy định bởi chính sách xác thực (endorsement policy) ở trong chaincode definition. Trong Fabric, trước khi được deploy thì chaincode definition cần phải được chấp thuận bởi các thành viên ở trong channel.

Cụ thể, đối với project này, tất cả các tổ chức đều cần phải thực thi smart contract và ký vào output của transaction. Sau khi được ký bởi đủ số lượng các tổ chức, transaction sẽ được commit xuống channel ledger.

Deploy chaincode như sau:

./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

Giải thích các flag:

  • Flag -ccn giúp chỉ định tên của chaincode.
  • Flag -ccp giúp chỉ định thư mục mã nguồn của chain code
  • Flag -ccl giúp chỉ định ngôn ngữ của chaincode.
  • Để chỉ định tên channel cần deploy chaincode, ta có thể dùng thêm flag -c.

Câu lệnh deployCC sẽ thực thi script scripts/deployCC.sh để cài đặt chaincode asset-transfer-basicpeer0.org1.example.compeer0.org2.example.com.

Kế đến, các node sẽ approve chaincode definition. Sau khi chaincode definition được commit xuống channel mychannel (channel mặc định), chương trình peer sẽ gọi thực thi phương thức Init của chaincode để khởi tạo ledger.

Mỗi peer node sẽ có một Docker container tương ứng dùng để chạy chaincode.

Error: endorsement failure during invoke. response: status:500 message:"Undefined contract called"

Lưu ý, nếu sử dụng chaincode viết bằng Java thì ta cần phải biên dịch bằng Java 11 để tránh lỗi này khi thực thi chaincode. Tham khảo: https://github.com/hyperledger/fabric-samples/issues/1077

Interacting with the Network

Sau khi deploy chaincode thì ta có thể dùng chương trìnhpeer ở trong thư mục bin của fabric-samples để tương tác với chaincode.

Thêm thư mục bin vào biến môi trường để có thể chạy ở bất cứ đâu:

export PATH=${PWD}/../bin:$PATH

Chúng ta cũng cần phải trỏ biến FABRIC_CFG_PATH đến file core.yaml ở trong fabric-samples:

export FABRIC_CFG_PATH=$PWD/../config/

Thiết lập các biến môi trường sau để chạy peer dưới danh nghĩa của Org1:

# Environment variables for 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

Biến CORE_PEER_TLS_ROOTCERT_FILE và biến CORE_PEER_MSPCONFIGPATH trỏ vào các file liên quan đến mã hóa (chẳng hạn như chứng chỉ) của Org1 ở trong thư mục organizations.

Chúng ta có thể dùng script setOrgEnv.sh để thiết lập biến môi trường nhanh hơn như sau:

export $(./setOrgEnv.sh Org1 | xargs)

Script setOrgEnv.sh sẽ trả về các cặp key-value của các biến môi trường cần thiết lập và sẽ được truyền vào chương trình xargs để export. Chương trình peer bây giờ sẽ được chạy dưới danh nghĩa của tổ chức Org1.

InitLedger

Trong chaincode basic sẽ có phương thức InitLedger dùng để khởi tạo các asset ban đầu. Chạy lệnh sau để thực thi phương thức InitLedger của 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":[]}'

Phân tích câu lệnh trên:

  • -o localhost:7050: IP và port của orderer.
  • --tls: sử dụng TLS.
  • --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem": public key của orderer.
  • -C mychannel: tên channel của chaincode.
  • --peerAddresses localhost:7051: IP và port của Org1.
  • --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt": chứng chỉ số của Org1.
  • --peerAddresses localhost:9051: IP và port của Org2.
  • --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt": chứng chỉ số của Org2.
  • -c '{"function":"InitLedger","Args":[]}': lời gọi phương thức. Có thể thấy, ta gọi thực thi phương thức InitLedger và không truyền vào đối số nào (thể hiện bằng mảng rỗng Args).

Do endorsement policy của chaincode asset-transfer-basic yêu cầu transaction cần phải được ký bởi Org1 và Org2 nên ta cần phải dùng flag --peerAddresses để chỉ định hai tổ chức này. Đồng thời, do network sử dụng TLS nên cần phải chỉ định chứng chỉ của từng peer thông qua flag --tlsRootCertFiles.

Summary

Tóm lại, câu lệnh trên sẽ gọi thực thi phương thức InitLedger() trong chaincode basic ở trên channel mychannel với hai peer của hai tổ chức và một orderer. Ứng với mỗi node sẽ có một public key/certificate kèm với địa chỉ IP và port.

Output mong muốn:

2024-01-21 20:16:46.007 +07 0001 INFO [chaincodeCmd] chaincodeInvokeOrQuery -> Chaincode invoke successful. result: status:200

GetAllAssets

Sau đó khi khởi tạo chaincode, ta có thể lấy ra danh sách các asset hiện có bằng cách dùng câu lệnh sau:

peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'

Trong câu lệnh trên, ta dùng subcommand query thay vì invoke như lúc khi ghi dữ liệu và ta truyền vào mảng Args tên phương thức dùng để truy vấn danh sách các asset.

Output mong muốn:

[
    { "AppraisedValue": 300, "Color": "blue", "ID": "asset1", "Owner": "Tomoko", "Size": 5 },
    { "AppraisedValue": 400, "Color": "red", "ID": "asset2", "Owner": "Brad", "Size": 5 },
    { "AppraisedValue": 500, "Color": "green", "ID": "asset3", "Owner": "Jin Soo", "Size": 10 },
    { "AppraisedValue": 600, "Color": "yellow", "ID": "asset4", "Owner": "Max", "Size": 10 },
    { "AppraisedValue": 700, "Color": "black", "ID": "asset5", "Owner": "Adriana", "Size": 15 },
    { "AppraisedValue": 800, "Color": "white", "ID": "asset6", "Owner": "Michel", "Size": 15 }
]

TransferAsset

Để chuyển quyền sở hữu của asset, ta gọi lệnh sau:

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":"TransferAsset","Args":["asset6","Christopher"]}'

Các option tương tự như khi khởi tạo chaincode ngoại trừ lời gọi thực thi phương thức. Lần này, ta sẽ gọi phương thức TransferAsset để chuyển tài sản asset6 sang cho Christopher.

Summary

Có thể thấy, bất cứ khi nào cần ghi dữ liệu lên ledger và tạo mới block, ta cần sử dụng subcommand invoke. Ngược lại, nếu chỉ cần truy vấn dữ liệu từ ledger thì ta dùng subcommand query.

Kết quả của câu lệnh trên sẽ là:

2024-01-21 20:31:15.762 +07 0001 INFO [chaincodeCmd] chaincodeInvokeOrQuery -> Chaincode invoke successful. result: status:200 payload:"Michel"

ReadAsset

Chúng ta có thể thay đổi biến môi trường để truy vấn danh sách các asset của chaincode từ peer của Org2:

export $(./setOrgEnv.sh Org2 | xargs)

Truy vấn thông tin củaasset6:

peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'

Kết quả:

{ 
	"AppraisedValue":800, 
	"Color":"white", 
	"ID":"asset6", 
	"Owner":"Christopher", 
	"Size":15 
}

Bring Down the Network

Chúng ta có thể dọn dẹp network của project test-network bằng cách dùng lệnh sau:

./network.sh down

Câu lệnh này sẽ xóa các file liên quan đến mã hóa, các Docker container cũng như là Docker image được tạo ra trong quá trình chạy network.

list
from [[Hyperledger Fabric - Using the Test Network]]
sort file.ctime asc

Resources