# Blockchain / 使用 BDK 來創建你的第一個區塊鏈吧!
嗨各位,不知道大家有沒有關注到這則新聞,比特幣最近創了歷史新高,原本走勢薄弱的以太幣也在短短一週內強勢拉盤了將近三十個點(撰文日期 2025.07.17),區塊鏈還真是個有趣的東西對吧!? 不過今天不和大家聊金融市場或加密貨幣,是想向大家介紹一個我最近發現的很有趣的工具: 「Blockchain Development Kits(BDK)」,它是由國泰金控區塊鏈團隊在 GitHub 上開源的區塊鏈部署工具,目的是協助同業與異業夥伴透過便捷的指令快速部署,進一步加快聯盟鏈推展速度!
以下我們將使用 Golang 以及 Docker-Compose,在 Ubuntu 中搭建起一個 Hyperledger Fabric,並撰寫一份智能合約使整個網路支援讀取與寫入資料。
## Chapter 1: Network Architecture Overview
```mermaid
graph TD
subgraph "Orderer Organization"
O1[orderer0:7050]
O2[orderer1:7150]
O1 <--> O2
end
subgraph "Org0"
P01[peer0:7051_Anchor]
P02[peer1]
end
subgraph "Org1"
P11[peer0]
P12[peer1:7151_Anchor]
end
subgraph "Channel: test"
CC[fabcar chaincode v1]
end
%% Orderers serve the channel
O1 -.-> CC
O2 -.-> CC
%% Peers join channel and run chaincode
P01 --> CC
P02 --> CC
P11 --> CC
P12 --> CC
%% Peer gossip within orgs
P01 <--> P02
P11 <--> P12
classDef orderer fill:#e1f5fe,stroke:#0277bd,stroke-width:2px
classDef peer fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef chaincode fill:#e8f5e8,stroke:#388e3c,stroke-width:2px
classDef external fill:#fff3e0,stroke:#f57900,stroke-width:2px
class O1,O2 orderer
class P01,P02,P11,P12 peer
class CC chaincode
class P01,P12 external
```
## Chapter 2: Fabric Network
:::danger
在開始前,請確認您的系統中已經安裝 Golang, node.js, docker 以及 docker-compose !
:::
### 2.1 compose up orderer & peer
#### 2.1.1 touch `create.json`@`~/.bdk`
我這邊的配置和官方文件不太一樣,因為在實作的過程中發現 `org0.peer0` 和 `org1.peer0` 兩個節點的端口會有衝突。另外,在之後我們是打算將 `org0.peer0` 和 `org1.peer1` 作為 Anchor Peer,所以做出了以下改動。
```json=
{
"ordererOrgs": [
{
"name": "Org0Orderer",
"domain": "orderer.org0.example.com",
"enableNodeOUs": true,
"hostname": [
"orderer0",
"orderer1"
],
"ports": [
{
"port": 7050,
"isPublishPort": true,
"operationPort": 8443,
"isPublishOperationPort": true
},
{
"port": 7150,
"isPublishPort": true,
"operationPort": 8543,
"isPublishOperationPort": true
}
]
}
],
"peerOrgs": [
{
"name": "Org0",
"domain": "org0.example.com",
"enableNodeOUs": true,
"peerCount": 2,
"userCount": 1,
"ports": [
{
"port": 7051,
"isPublishPort": true,
"operationPort": 9443,
"isPublishOperationPort": true
},
{
"port": 7051,
"isPublishPort": false,
"operationPort": 9443,
"isPublishOperationPort": false
}
]
},
{
"name": "Org1",
"domain": "org1.example.com",
"enableNodeOUs": true,
"peerCount": 2,
"userCount": 1,
"ports": [
{
"port": 7051,
"isPublishPort": false,
"operationPort": 9443,
"isPublishOperationPort": false
},
{
"port": 7151,
"isPublishPort": true,
"operationPort": 9543,
"isPublishOperationPort": true
}
]
}
]
}
```
#### 2.1.2 create network command
`bdk` 指令語法設計的邏輯是:
```tex
BDK,請在 [什麼平台] 上,對 [什麼東西] 執行 [什麼動作]
```
```bash
$ bdk fabric network create -f create.json --create-full
# @~/.bdk/fabri
```
#### 2.1.3 build nodes with interactive mode
```bash=
$ bdk fabric orderer up -i
$ bdk fabric peer up -i
```
### 2.2 build & join a channel
```bash=
# Org0 的 peer0 建立新的 channel
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric channel create -i
# Org0 的 peer0 加入 channel
bdk fabric channel join -i
# Org0 的 peer1 加入 channel
export BDK_HOSTNAME='peer1'
bdk fabric channel join -i
# Org1 的 peer0 加入 channel
export BDK_ORG_NAME='Org1'
export BDK_ORG_DOMAIN='org1.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric channel join -i
# Org1 的 peer1 加入 channel
export BDK_HOSTNAME='peer1'
bdk fabric channel join -i
```
互動模式的選項部分,則是統一選擇:
```bash=
✔ What is your channel name? › test
✔ Ordering service endpoint › orderer0.orderer.org0.example.com:7050
```
### 2.3 set up anchor peers
```bash=
# 更新 Org0 的 anchor peer
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric channel update-anchorpeer -i
# Org1 的 peer1 加入 channel
export BDK_ORG_NAME='Org1'
export BDK_ORG_DOMAIN='org1.example.com'
export BDK_HOSTNAME='peer1'
bdk fabric channel update-anchorpeer -i
```
## Chapter 3: Smart Contract
詳細程式碼請參見 GitHub Repo: https://github.com/marvelcn015/bdk-fabcar
### 3.1 File Structure
```
chaincode/fabric/go/
├── go.mod # Go module dependencies
├── main.go # Chaincode entry point
├── fabcar.go # Main chaincode structure and interface
├── business_logic.go # Core business operations (CRUD)
├── queries.go # Advanced query operations
├── utils.go # Validation and utility functions
├── fabcar_test.go # Comprehensive test suite
└── README.md # This documentation
```
### 3.2 API Methods
#### 3.2.1 Initialize Chaincode
```
Function: Init
Description: Initializes the chaincode with sample car data
```
#### 3.2.2 Query Single Car
```
Function: queryCar
Arguments: [carKey]
Example: queryCar "CAR0"
```
#### 3.2.3 Query All Cars
```
Function: queryAllCars
Arguments: []
Example: queryAllCars
```
#### 3.2.4 Create New Car
```
Function: createCar
Arguments: [carKey, make, model, color, owner, year, price]
Example: createCar "CAR100" "BMW" "X5" "black" "John Doe" "2022" "75000"
```
#### 3.2.5 Update Car
```
Function: updateCar
Arguments: [carKey, make, model, color, owner, year, price]
Example: updateCar "CAR0" "Toyota" "Prius" "green" "Tomoko" "2018" "26000"
```
#### 3.2.6 Change Car Owner
```
Function: changeCarOwner
Arguments: [carKey, newOwner]
Example: changeCarOwner "CAR0" "Alice Smith"
```
#### 3.2.7 Delete Car
```
Function: deleteCar
Arguments: [carKey]
Example: deleteCar "CAR0"
```
#### 3.2.8 Query Cars by Owner
```
Function: queryCarsByOwner
Arguments: [ownerName]
Example: queryCarsByOwner "John Doe"
```
#### 3.2.9 Query Cars by Range
```
Function: queryCarsByRange
Arguments: [startKey, endKey]
Example: queryCarsByRange "CAR0" "CAR9"
```
#### 3.2.10 Get Car History
```
Function: getCarHistory
Arguments: [carKey]
Example: getCarHistory "CAR0"
```
#### 3.2.11 Get Car Count
```
Function: getCarCount
Arguments: []
Example: getCarCount
```
## Chapter 4: Chaincode Deployment
### 4.1 部署的五個階段 & 指令
```mermaid
flowchart TB
A[Package<br/>打包] --> B[Install<br/>安裝]
B --> C[Approve<br/>批准]
C --> D[Commit<br/>部署]
D --> E[Invoke<br/>執行]
A --> A1[編譯程式碼]
B --> B1[複製到各節點]
C --> C1[組織決策階段]
D --> D1[全網路部署]
E --> E1[實際交易執行]
style A fill:#e1f5fe
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#fce4ec
style E fill:#f3e5f5
```
### 4.2 各階段參與者
| 階段 | 執行者 | 作用範圍 | 是否需要共識 |
|------|--------|----------|-------------|
| Package | 任一開發者 | 本地 | ❌ |
| Install | 各 Peer 節點 | 節點層級 | ❌ |
| Approve | 各組織 | 組織層級 | ❌ |
| Commit | 任一組織 | 全網路 | ✅ |
| Invoke | 任一授權用戶 | 全網路 | ✅ |
### 4.3 Install & Approve
```bash=
# Org0 的 peer0 安裝、同意 Chaincode
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric chaincode install -i
bdk fabric chaincode approve -i
# Org1 的 Anchor Peer 也這麼做
export BDK_ORG_NAME='Org1'
export BDK_ORG_DOMAIN='org1.example.com'
export BDK_HOSTNAME='peer1'
bdk fabric chaincode install -i
bdk fabric chaincode approve -i
# Org0 的 peer1 安裝 Chaincode
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer1'
bdk fabric chaincode install -i
# Org1 的 peer0 也這麼做
export BDK_ORG_NAME='Org1'
export BDK_ORG_DOMAIN='org1.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric chaincode install -i
```
### 4.4 Commit & Init Invoke
```bash=
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric chaincode commit -i
bdk fabric chaincode invoke -i
```
---
接下來,就可以搭配各種自訂好的 Arguments 執行合約中的函數囉~
> BDK Offical Document:
https://github.com/cathayddt/bdk/tree/master
>
> GitHub Repo:
https://github.com/marvelcn015/bdk-fabcar
>
> 2025 / 07 / 17, by Aaron Yeh