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