如果你想要在自己的環境裡架設一條區塊鏈,不管是研究用,還是要當作哪個產品的底層,大概你會碰到和我剛開始一樣的問題,就是不知道該選哪一條鏈。現今絕大部分的區塊鏈是開源的,任何人都可以下載自行編譯,但是記得,這些區塊鏈都是公鏈,在正常的情況下,你辛苦編譯完成後執行的其實是一個節點(Node),他會連上所謂的公鏈,下載所有的區塊交易資料,而非如你想像的在本地長出一條全新的私鏈。
針對幾條比較有名的公鏈,網路上多得是文章教你怎麼改原始碼和設定,強迫它不要連上公鏈,並且重新在本地建立一個新的區塊鏈供你使用,以我的經驗,這些過程都很辛苦,而且經常因為版本更新而出錯,直到我找到BitShares這個東西。
BitShares天生就設計成讓你可以架設自己的私鏈,無須改一行的原始碼,只要透過一定的程序和設定,它就會在你的電腦長出一條新的區塊鏈,這一系列的文章會從軟體本身開始說明,一步一步的讓你架出自己的區塊鏈,並且在上頭開發基本的應用。
- 關於BitShares主程式
區塊鏈和虛擬貨幣,讓發展了數十年的軟體中心化架構產生了新的想法,但在實作上,區塊鏈仍然只是一套電腦軟體,從開山始祖比特幣以來,這一點一直都沒有改變。
BitShares的軟體設計邏輯和比特幣非常類似,這可以從Daniel Larimer的創業過程略知一二,他當初就是對於比特幣的某些設計不以為然,在論壇中和中本聰針鋒相對,最後火大決定自己寫一套,才會有後來的BitShares。
為了避免過度相依系統Libraries造成的安全隱憂,BitShares也和比特幣一樣,都採取靜態連結方式(Static Linked)打包主要的執行檔,意思是把所有需要的Libraries都直接包進主程式裡,不然就自己寫,盡可能不呼叫系統提供的對應功能。這樣做的結果就是,當你編譯完成,會發現它是一個非常巨大的執行檔(witness_node),大概是100MB。
ubuntu@pc-vm-01:~/mychain/bitshares-workshop$ ll bin total 181144 drwxr-xr-x 3 ubuntu ubuntu 4096 Nov 30 15:17 ./ drwxr-xr-x 8 ubuntu ubuntu 4096 Apr 21 04:23 ../ -rw-r--r-- 1 ubuntu ubuntu 3135 Nov 30 15:17 CONTRIBUTORS.txt -rw-r--r-- 1 ubuntu ubuntu 3478 Nov 30 15:17 LICENSE.txt -rw-r--r-- 1 ubuntu ubuntu 1136 Nov 30 15:17 README.md -rwxr-xr-x 1 ubuntu ubuntu 77246432 Nov 30 15:17 cli_wallet* drwxr-xr-x 2 ubuntu ubuntu 4096 Nov 30 15:17 licenses/ -rwxr-xr-x 1 ubuntu ubuntu 108216528 Nov 30 15:17 witness_node*
確實BitShares只需要這個執行檔和幾個設定檔就可以建立完整的區塊鏈和發幣交易,與一般人聽到區塊鏈聯想到的複雜架構可以說是相去甚遠。魔鬼藏在細節裡,要靠一個執行檔和幾個設定檔完成去中心化的交易帳本驗證,發幣,交易所,這底下的複雜度,不會亞於目前任何主流的資料庫軟體。
如果你注意上面的截圖,會發現另一個執行檔叫做cli_wallet,這是BitShares提供的命令列錢包,不僅如此,它還提供不少主程式之外的輔助功能,讓開發應用此鏈的難度可以大幅降低,後面的範例會一步一步說明他們兩者之間的差異和關係。
有兩個途徑可以得到BitShares的軟體,第一是自己編譯,第二則是去Github下載已經編譯好的版本,目前的版本是6.x。
- 自己編譯BitShares
如果你熟悉Linux的操作環境,想要自行編譯BitShares,其實不會太難,官方建議使用Ubuntu 20.04以後的版本進行,比較不會遇到相依性的問題。BitShares和比特幣一樣,都是採用C++作為開發語言,底下是需要安裝的編譯工具:
sudo apt-get update sudo apt-get install autoconf cmake make automake libtool git libboost-all-dev libssl-dev g++ libcurl4-openssl-dev doxygen
編譯流程也算是簡單明瞭:
git clone https://github.com/bitshares/bitshares-core.git cd bitshares-core git checkout master # may substitute "master" with current release tag git submodule update --init --recursive mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release .. make
一般來說,編譯需要花20-30分鐘,編譯過程會有百分比,可以去先做別的事情。如上所述,最後我們只需要witness_node和cli_wallet兩個程式即可:
silver@we20:~/bitshares-core/build$ ll programs/witness_node/ total 136836 drwxrwxr-x 3 silver silver 4096 May 7 15:00 ./ drwxrwxr-x 10 silver silver 4096 May 7 12:13 ../ drwxrwxr-x 3 silver silver 4096 May 7 12:13 CMakeFiles/ -rw-rw-r-- 1 silver silver 1972 May 7 12:13 cmake_install.cmake -rw-rw-r-- 1 silver silver 7714 May 7 12:13 Makefile -rwxrwxr-x 1 silver silver 140088192 May 7 15:01 witness_node* silver@we20:~/bitshares-core/build$ ll programs/cli_wallet/ total 109364 drwxrwxr-x 3 silver silver 4096 May 7 16:56 ./ drwxrwxr-x 10 silver silver 4096 May 7 12:13 ../ -rwxrwxr-x 1 silver silver 111962824 May 7 16:56 cli_wallet* drwxrwxr-x 3 silver silver 4096 May 7 12:13 CMakeFiles/ -rw-rw-r-- 1 silver silver 1954 May 7 12:13 cmake_install.cmake -rw-rw-r-- 1 silver silver 7646 May 7 12:13 Makefile
至此你就完成了自己編譯的區塊鏈。
- 下載已經編譯好的軟體
BitShares的官方Repository有提供每次Release版本的執行檔,一般會有Linux/Mac/Windows三個平台,請參考:
https://github.com/bitshares/bitshares-core/releases
下載回來的壓縮檔裡,基本上也就是上面提到的兩個主程式:

- BitShares設定檔
光有主程式並不能建立自己的區塊鏈,你還需要至少底下兩個設定檔:
- genesis.json,就是所謂的創世區塊,這名詞是從比特幣借用過來的,但意義上完全不同,可以把它當成初始化私鏈的參數(initial parameters)
- config.ini,這是每一個節點(witness_node)啟動時都需要的設定檔,裡面定義了這個節點的行為和限制,大部分可以用命令列參數的方式指定,但寫成設定檔比較簡單。
這裡又要抱怨BitShares的開發者,官方幾乎沒有對於這兩個檔案的任何說明,早期的BitShares軟體包含一個產生genesis.json樣板的工具程式,後期不知道為什麼就沒有了,所以要弄出一個可以創建私鏈的genesis.json,還真的是要廢一番功夫。至於config.ini也沒有好到哪裡去,目前取得這個檔案的作法是啟動一個公鏈節點,讓它自己產生一份config.ini,然後停掉這個節點,再修改符合私鏈使用。這樣產生的config.ini會包含每個設定參數的簡短說明,這也是目前能夠找到唯一比較完整的說明了,當你熟悉這個區塊鏈生態後,自然會漸漸了解每個設定的意義,但對於初學者而言,那些說明說了等於沒說。
這裡放了兩個檔案的下載位置,可以讓你啟動私鏈:
https://silverchen.me/wp-content/uploads/2022/05/config.ini
https://silverchen.me/wp-content/uploads/2022/05/genesis.json
再來我們要做的事情就很簡單了,開始建立你的區塊鏈吧。這裡先不解釋檔案的內容,以後再搭配應用說明。
- 啟動BitShares私鏈
我們有了執行檔和設定檔,現在可以來啟動你的第一個私鏈的節點了。雖然說區塊鏈是去中心化架構,但總是要有第一個節點執行起來,開始產生第一個區塊,這樣第二個以後的節點才有可能加入這個架構,形成完整的p2p網路。
為了良好的佈署習慣,我們把檔案如下圖放置:
258340 4 drwxrwxr-x 4 ubuntu ubuntu 4096 May 28 22:24 . 258353 4 drwxrwxr-x 2 ubuntu ubuntu 4096 May 28 22:24 ./bin 267031 75440 -rwxr-xr-x 1 ubuntu ubuntu 77246432 May 28 22:24 ./bin/cli_wallet 267037 105684 -rwxr-xr-x 1 ubuntu ubuntu 108216528 May 28 22:24 ./bin/witness_node 267040 8 -rw-rw-r-- 1 ubuntu ubuntu 7876 May 28 22:24 ./genesis.json 267041 4 drwxrwxr-x 2 ubuntu ubuntu 4096 May 28 22:24 ./node_dir 267042 4 -rw-rw-r-- 1 ubuntu ubuntu 543 May 28 22:24 ./node_dir/config.ini
接著執行以下指令啟動第一個節點:
bin/witness_node --data-dir node_dir
如果一切正常,你會看到以下一大串的輸出,並且會持續產生新的區塊:
1671247ms th_a config_util.cpp:243 load_logging_config_ ] Error parsing logging config from logging config file /home/ubuntu/mychain/a/node_dir/config.ini, using default config 1671247ms th_a application.cpp:1288 initialize ] Initializing application 1671247ms th_a application.cpp:1081 initialize_plugins ] Initializing plugin account_history 1671247ms th_a application.cpp:1083 initialize_plugins ] Initialized plugin account_history 1671247ms th_a application.cpp:1081 initialize_plugins ] Initializing plugin api_helper_indexes 1671247ms th_a application.cpp:1083 initialize_plugins ] Initialized plugin api_helper_indexes 1671247ms th_a application.cpp:1081 initialize_plugins ] Initializing plugin custom_operations 1671247ms th_a application.cpp:1083 initialize_plugins ] Initialized plugin custom_operations 1671248ms th_a application.cpp:1081 initialize_plugins ] Initializing plugin grouped_orders 1671248ms th_a application.cpp:1083 initialize_plugins ] Initialized plugin grouped_orders 1671248ms th_a application.cpp:1081 initialize_plugins ] Initializing plugin market_history 1671248ms th_a application.cpp:1083 initialize_plugins ] Initialized plugin market_history 1671248ms th_a application.cpp:1081 initialize_plugins ] Initializing plugin witness 1671248ms th_a witness.cpp:121 plugin_initialize ] witness plugin: plugin_initialize() begin 1671248ms th_a witness.cpp:114 add_private_key ] Public Key: BTS6WqFcNmb8DA8SG2HJDL23TzSKk67HrCf6qTeqXhbCcohi11epm 1671248ms th_a witness.cpp:163 plugin_initialize ] witness plugin: Warning - Low required participation of 0% found 1671248ms th_a witness.cpp:167 plugin_initialize ] witness plugin: plugin_initialize() end 1671248ms th_a application.cpp:1083 initialize_plugins ] Initialized plugin witness 1671248ms th_a application.cpp:1290 initialize ] Done initializing application 1671248ms th_a application.cpp:1296 startup ] Starting up application 1671248ms th_a db_management.cpp:193 open ] Wiping object_database due to missing or wrong version 1671248ms th_a object_database.cpp:127 wipe ] Wiping object database... 1671248ms th_a object_database.cpp:129 wipe ] Done wiping object database. 1671249ms th_a object_database.cpp:150 open ] Opening object database from /home/ubuntu/mychain/a/node_dir/blockchain ... 1671251ms th_a object_database.cpp:160 open ] Done opening object database. 1671251ms th_a application.cpp:442 initialize_genesis_s ] Initializing database... 1671277ms th_a application.cpp:1091 startup_plugins ] Starting plugin account_history 1671277ms th_a application.cpp:1093 startup_plugins ] Started plugin account_history 1671277ms th_a application.cpp:1091 startup_plugins ] Starting plugin api_helper_indexes 1671277ms th_a api_helper_indexes.cpp:182 plugin_startup ] api_helper_indexes: plugin_startup() begin 1671277ms th_a application.cpp:1093 startup_plugins ] Started plugin api_helper_indexes 1671277ms th_a application.cpp:1091 startup_plugins ] Starting plugin custom_operations 1671277ms th_a custom_operations_plugin.cpp:149 plugin_startup ] custom_operations: plugin_startup() begin 1671277ms th_a application.cpp:1093 startup_plugins ] Started plugin custom_operations 1671277ms th_a application.cpp:1091 startup_plugins ] Starting plugin grouped_orders 1671277ms th_a application.cpp:1093 startup_plugins ] Started plugin grouped_orders 1671277ms th_a application.cpp:1091 startup_plugins ] Starting plugin market_history 1671277ms th_a application.cpp:1093 startup_plugins ] Started plugin market_history 1671277ms th_a application.cpp:1091 startup_plugins ] Starting plugin witness 1671277ms th_a witness.cpp:172 plugin_startup ] witness plugin: plugin_startup() begin 1671277ms th_a witness.cpp:176 plugin_startup ] Launching block production for 3 witnesses. 1671277ms th_a witness.cpp:54 new_chain_banner ] ******************************** * * * ------- NEW CHAIN ------ * * - Welcome to BitShares! - * * ------------------------ * * * ******************************** 1671277ms th_a witness.cpp:57 new_chain_banner ] Your genesis seems to have an old timestamp 1671277ms th_a witness.cpp:58 new_chain_banner ] Please consider using the --genesis-timestamp option to give your genesis a recent timestamp 1671277ms th_a witness.cpp:195 plugin_startup ] witness plugin: plugin_startup() end 1671277ms th_a application.cpp:1093 startup_plugins ] Started plugin witness 1671279ms th_a application.cpp:155 reset_p2p_node ] Configured p2p node to listen on 0.0.0.0:40101 1671280ms th_a application.cpp:207 reset_websocket_serv ] Configured websocket rpc to listen on 0.0.0.0:40201 1671280ms th_a application.cpp:1298 startup ] Done starting up application 1671280ms th_a main.cpp:230 main ] Started BitShares node on a chain with 0 blocks. 1671280ms th_a main.cpp:231 main ] Chain ID is 59af7726129cb6bb72bb607724882469a47912acb08319a1e65ecc88b0d6b974 1672000ms th_a db_maint.cpp:897 update_call_orders_h ] Updating all call orders for hardfork core-343 at block 1 1672001ms th_a db_maint.cpp:915 update_call_orders_h ] Done updating all call orders for hardfork core-343 at block 1 1672001ms th_a db_maint.cpp:936 match_call_orders ] Matching call orders at block 1 1672001ms th_a db_maint.cpp:947 match_call_orders ] Done matching call orders at block 1 1672001ms th_a db_maint.cpp:936 match_call_orders ] Matching call orders at block 1 1672001ms th_a db_maint.cpp:947 match_call_orders ] Done matching call orders at block 1 1672001ms th_a db_maint.cpp:936 match_call_orders ] Matching call orders at block 1 1672001ms th_a db_maint.cpp:947 match_call_orders ] Done matching call orders at block 1 1672001ms th_a witness.cpp:272 block_production_loo ] Generated block #1 with 0 transaction(s) and timestamp 2022-05-28T14:27:50 at time 2022-05-28T14:27:52 1690000ms th_a witness.cpp:272 block_production_loo ] Generated block #2 with 0 transaction(s) and timestamp 2022-05-28T14:28:10 at time 2022-05-28T14:28:10 1695000ms th_a witness.cpp:272 block_production_loo ] Generated block #3 with 0 transaction(s) and timestamp 2022-05-28T14:28:15 at time 2022-05-28T14:28:15 1700001ms th_a witness.cpp:272 block_production_loo ] Generated block #4 with 0 transaction(s) and timestamp 2022-05-28T14:28:20 at time 2022-05-28T14:28:20 1705000ms th_a witness.cpp:272 block_production_loo ] Generated block #5 with 0 transaction(s) and timestamp 2022-05-28T14:28:25 at time 2022-05-28T14:28:25 1710001ms th_a witness.cpp:272 block_production_loo ] Generated block #6 with 0 transaction(s) and timestamp 2022-05-28T14:28:30 at time 2022-05-28T14:28:30 1715001ms th_a witness.cpp:272 block_production_loo ] Generated block #7 with 0 transaction(s) and timestamp 2022-05-28T14:28:35 at time 2022-05-28T14:28:35 1720000ms th_a witness.cpp:272 block_production_loo ] Generated block #8 with 0 transaction(s) and timestamp 2022-05-28T14:28:40 at time 2022-05-28T14:28:40 1725001ms th_a witness.cpp:272 block_production_loo ] Generated block #9 with 0 transaction(s) and timestamp 2022-05-28T14:28:45 at time 2022-05-28T14:28:45 1730000ms th_a witness.cpp:272 block_production_loo ] Generated block #10 with 0 transaction(s) and timestamp 2022-05-28T14:28:50 at time 2022-05-28T14:28:50 1735000ms th_a witness.cpp:272 block_production_loo ] Generated block #11 with 0 transaction(s) and timestamp 2022-05-28T14:28:55 at time 2022-05-28T14:28:55 1740001ms th_a witness.cpp:272 block_production_loo ] Generated block #12 with 0 transaction(s) and timestamp 2022-05-28T14:29:00 at time 2022-05-28T14:29:00
到這裡你已經成功建立了一條自己的區塊鏈,和目前公鏈上的諸多區塊鏈並沒有不同,BitShare採取的共識機制是DPOS,因此無須挖礦,每個幾秒區塊鏈自己會產生新的區塊,並將驗證過的交易寫入,目前我們還沒有任何交易,因此這些區塊的內容都是空的。
下一篇我們會教你如何建立錢包,並且透過cli_wallet進行真正的區塊鏈交易。