Blockchain / Let's Create Your First Blockchain with BDK!
===================================================
Hey everyone! I wonder if you've noticed this news - Bitcoin recently hit a historic high, and Ethereum, which was previously showing weak trends, has strongly surged nearly thirty points in just one week (as of July 17, 2025). Blockchain really is a fascinating thing, isn't it!? However, today I'm not here to discuss financial markets or cryptocurrencies with you, but to introduce a very interesting tool I recently discovered: "Blockchain Development Kits (BDK)". It's an open-source blockchain deployment tool released on GitHub by Cathay Financial Holdings' blockchain team, aimed at helping industry partners and cross-industry partners quickly deploy through convenient commands, further accelerating the promotion of consortium chains!
Below, we'll use Golang and Docker-Compose to build a Hyperledger Fabric network on Ubuntu and write a smart contract to enable the entire network to support reading and writing data.
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
Before starting, please ensure that Golang, node.js, docker, and docker-compose are installed on your system!
:::
### 2.1 Compose Up Orderer & Peer
#### 2.1.1 Create `create.json` at `~/.bdk`
My configuration here is slightly different from the official documentation because during implementation, I found that the ports for `org0.peer0` and `org1.peer0` would conflict. Additionally, since we plan to use `org0.peer0` and `org1.peer1` as Anchor Peers later, I made the following modifications.
```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
The logic of `bdk` command syntax design is:
```
BDK, please execute [what action] on [what thing] on [what platform]
```
```bash
$ bdk fabric network create -f create.json --create-full
# @~/.bdk/fabric
```
#### 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's peer0 creates a new channel
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric channel create -i
# Org0's peer0 joins the channel
bdk fabric channel join -i
# Org0's peer1 joins the channel
export BDK_HOSTNAME='peer1'
bdk fabric channel join -i
# Org1's peer0 joins the channel
export BDK_ORG_NAME='Org1'
export BDK_ORG_DOMAIN='org1.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric channel join -i
# Org1's peer1 joins the channel
export BDK_HOSTNAME='peer1'
bdk fabric channel join -i
```
For the interactive mode options, consistently choose:
```bash
✔ What is your channel name? › test
✔ Ordering service endpoint › orderer0.orderer.org0.example.com:7050
```
### 2.3 Set Up Anchor Peers
```bash=
# Update Org0's anchor peer
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer0'
bdk fabric channel update-anchorpeer -i
# Update Org1's anchor peer
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
-------------------------
For detailed code, please refer to 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 Five Stages of Deployment & Commands
```mermaid
flowchart TB
A[Package<br/>Package] --> B[Install<br/>Install]
B --> C[Approve<br/>Approve]
C --> D[Commit<br/>Commit]
D --> E[Invoke<br/>Invoke]
A --> A1[Compile Code]
B --> B1[Copy to Each Node]
C --> C1[Organization Consensus]
D --> D1[Network-wide Deployment]
E --> E1[Actual Transaction Execution]
style A fill:#e1f5fe
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#fce4ec
style E fill:#f3e5f5
```
### 4.2 Participants in Each Stage
| Stage | Executor | Scope | Consensus Required |
| --- | --- | --- | --- |
| Package | Any Developer | Local | ❌ |
| Install | Each Peer Node | Node Level | ❌ |
| Approve | Each Organization | Organization Level | ❌ |
| Commit | Any Organization | Network-wide | ✅ |
| Invoke | Any Authorized User | Network-wide | ✅ |
### 4.3 Install & Approve
```bash=
# Org0's peer0 installs and approves 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's Anchor Peer does the same
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's peer1 installs chaincode
export BDK_ORG_NAME='Org0'
export BDK_ORG_DOMAIN='org0.example.com'
export BDK_HOSTNAME='peer1'
bdk fabric chaincode install -i
# Org1's peer0 does the same
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
```
---
Now you can execute functions in the contract with various custom arguments!
> BDK Official Document: https://github.com/cathayddt/bdk/tree/master
>
> GitHub Repo: https://github.com/marvelcn015/bdk-fabcar
>
> July 17, 2025, by Aaron Yeh