Skip to content

Latest commit

 

History

History
798 lines (611 loc) · 40.7 KB

第三章.asciidoc

File metadata and controls

798 lines (611 loc) · 40.7 KB

Bitcoin Core:參考實作 (Bitcoin Core: The Reference Implementation)

比特幣是開源的專案,原始碼使用MIT授權方式,可以免費下載和使用。開源不僅意味著免費使用,也意味著比特幣是由開源志願者社群開發的。起初,這個社群只包括中本聰(Satoshi Nakamoto)。到2016年,比特幣的原始碼擁有超過400個貢獻者,大約有十幾位開發人員幾乎全職工作,另外幾十人兼職工作。任何人都可以貢獻程式碼,包括你!

當中本聰創造比特幣時,該軟體實際上已經在白皮書出現之前完成。在寫這篇文章之前,中本聰想確保它可以工作。第一版實現已經進行了大量修改和改進,已經發展成為所謂的 比特幣核心 (Bitcoin Core),以區別於其他相容的實現。Bitcoin Core 是比特幣系統的參考實作,這意味著它是關於如何實施每一部分技術的權威參考。Bitcoin Core 實現了比特幣的各個方面,包括錢包、交易和區塊驗證引擎,以及點對點比特幣網路中的完整網路節點。

Warning

儘管 Bitcoin Core 包含錢包的參考實作,但並不建議將其用作使用者或應用程式生產環境中的錢包。建議應用程式開發人員使用現代標準 (如 BIP-39 和 BIP-32 ) 開發錢包 (請參閱 [mnemonic_code_words][hd_wallets])。BIP 是 Bitcoin Improvement Proposal 的縮寫,即 Bitcoin 改進提案 的意思。

Bitcoin Core architecture (Source: Eric Lombrozo) 展示了 Bitcoin Core 的架構。

Bitcoin Core Architecture
Figure 1. Bitcoin Core architecture (Source: Eric Lombrozo)

比特幣開發環境

如果你是一名開發者,你需要建立一個開發環境,其中包含用於編寫比特幣應用程式的所有工具,函式庫和支援軟體。在這個高度技術性的章節中,我們將一步一步地介紹該過程。如果覺得過於複雜(並且你實際上沒有設定開發環境),請隨意跳到下一章,技術性較弱的章節。

透過原始碼編譯 Bitcoin Core

可以從 GitHub 下載 Bitcoin Core 的原始碼。例如,在 Bitcoin Core 下載頁面 上,選擇最新版本的原始碼壓縮檔,bitcoin-core-0.21.2/bitcoin-0.21.2.tar.gz。或者,使用 git clone 命令在本地建立一個備份。 Bitcoin Core - GitHub

Tip

在本章的許多範例中,我們將使用作業系統的命令列介面(也稱為“shell”),透過“終端”應用程式訪問它,shell 將顯示一個提示字元;你輸入一個命令;shell會為你的下一個命令返回一些文字和一個新的提示字元。提示可能在你的系統上看起來不同,但在以下範例中,它由 $ 號表示。在範例中,當你在 $ 符號後面看到文字時,請勿鍵入 $ 符號,而是在其後面緊接著輸入命令,然後按Enter執行該命令。在範例中,每條命令下面的行是作業系統對該命令的響應。當你看到下一個 $ 字首時,你應該知道這是一個新的命令列,你可以重複這個過程。

在這個例子中,我們使用 git 命令建立原始碼的本地副本。

$ git clone https://github.com/bitcoin/bitcoin.git
Cloning into 'bitcoin'...
remote: Counting objects: 102071, done.
remote: Compressing objects: 100% (10/10), done.
Receiving objects: 100% (102071/102071), 86.38 MiB | 730.00 KiB/s, done.
remote: Total 102071 (delta 4), reused 5 (delta 1), pack-reused 102060
Resolving deltas: 100% (76168/76168), done.
Checking connectivity... done.
$
Tip

Git是使用最廣泛的分散式版本控制系統,它是軟體開發人員工具箱的重要組成部分。如果你尚未安裝,請在作業系統上安裝 git 命令或git的圖形使用者介面。

當git複製操作完成後,你將在 bitcoin 目錄中擁有完整的原始碼函式庫本地副本。在提示字元處輸入 cd bitcoin 切換到此目錄:

$ cd bitcoin

選擇 Bitcoin Core 的發行版

預設情況下,本地副本將同步最新的程式碼,這可能是比特幣的不穩定版或 Beta 版。編譯程式碼之前,透過檢查 tag 來選擇特定版本。這將使本地副本與由關鍵字標記標識的程式碼儲存函式庫的特定快照同步。開發人員使用標籤透過版本號標記程式碼的特定版本。首先,為了找到可用的標籤,我們使用 git tag 命令:

$ git tag
v0.1.5
v0.1.6test1
v0.10.0
...
v0.11.2
v0.11.2rc1
v0.12.0rc1
v0.12.0rc2
...

標籤列表顯示比特幣的所有發行版本。按照慣例,用於測試的_發行預覽版(release candidates)_具有後綴“rc”。可以在生產系統上執行的穩定版本沒有後綴。從上面的列表中選擇最高版本的發行版本,在撰寫本文時是v0.15.0。要使原生代碼與此版本同步,請使用 git checkout 命令:

$ git checkout v0.15.0
HEAD is now at 3751912... Merge #11295: doc: Old fee_estimates.dat are discarded by 0.15.0

你可以透過命令 git status 來確認你已經“檢出”了所需的版本:

$ git status
HEAD detached at v0.15.0
nothing to commit, working directory clean

Bitcoin Core 的建構配置

原始碼包括文件,可以在許多檔案中找到。輸入 more README.md,檢視 bitcoin 目錄中的_README.md_主文件,可使用空格鍵進行翻頁。在本章中,我們將建構命令列比特幣客戶端(command-line bitcoin client),在Linux上也稱為 bitcoind。輸入 more doc/build-unix.md 來檢視在你的平臺上編譯 bitcoind 的說明。macOS和Windows的說明可以在_doc_目錄中找到,分別為_build-osx.md_或_build-windows.md_。

仔細檢視建構文件第一部分中的依賴函式庫,如 boost-devel, libevent-devel, openssl-devel, gcc-c++, libdb4-cxx-devel, autoconf, automake, libtool等。在你開始編譯比特幣之前,這些函式庫必須存在於你的系統中,否則建構過程將失敗。如果因為漏掉了某些依賴函式庫而導致失敗,可以安裝它,然後從之前停止的地方恢復建構過程。你可以透過使用 autogen.sh 指令碼產生一組建構指令碼來啟動建構過程。

$ ./autogen.sh
...
glibtoolize: copying file 'build-aux/m4/libtool.m4'
glibtoolize: copying file 'build-aux/m4/ltoptions.m4'
glibtoolize: copying file 'build-aux/m4/ltsugar.m4'
glibtoolize: copying file 'build-aux/m4/ltversion.m4'
...
configure.ac:10: installing 'build-aux/compile'
configure.ac:5: installing 'build-aux/config.guess'
configure.ac:5: installing 'build-aux/config.sub'
configure.ac:9: installing 'build-aux/install-sh'
configure.ac:9: installing 'build-aux/missing'
Makefile.am: installing 'build-aux/depcomp'
...

autogen.sh 指令碼建立一組自動配置指令碼,它們將詢問你的系統以發現正確的設定,並確保你擁有編譯程式碼所需的全部函式庫。其中最重要的是 configure 指令碼,它提供了許多不同的選項來訂製建構過程。鍵入 ./configure --help 檢視各種選項。

$ ./configure --help
`configure' configures Bitcoin Core 0.15.0 to adapt to many kinds of systems.

Usage: ./configure [OPTION]... [VAR=VALUE]...

...
Optional Features:
  --disable-option-checking  ignore unrecognized --enable/--with options
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]

  --enable-wallet         enable wallet (default is yes)

  --with-gui[=no|qt4|qt5|auto]
...

configure 指令碼允許你透過使用 -enable-FEATURE 和 -disable-FEATURE 標誌啟用或禁用 bitcoind 的某些功能,其中 FEATURE 被替換為幫助輸出中列出的特徵名稱。在本章中,我們將建構帶有所有預設功能的 bi​​tcoind 客戶端。我們不會使用配置標誌,但你應該檢視它們以瞭解哪些可選功能是客戶端的一部分。如果你處於學術環境中,實驗室可能會要求你將應用程式安裝到你的主目錄中(例如,使用+-prefix=$HOME+)。

以下是覆蓋配置指令碼預設行為的一些有用選項:

--prefix=$HOME

覆蓋產生的可執行檔案的預設安裝位置 (/usr/local/)。使用$HOME以將所有內容放在你的主目錄,也可以使用其他路徑。

--disable-wallet

禁用錢包的參考實作。

--with-incompatible-bdb

如果你正在建構錢包,可以允許使用不相容Berkeley DB函式庫的版本。

--with-gui=no

不建構需要Qt函式庫的圖形使用者介面。這隻會建構伺服器和命令列。

接下來,執行 configure 指令碼,它會自動發現所有必要的函式庫,並為你的系統建立一個特定的建構指令碼:

$ ./configure
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
...
[many pages of configuration tests follow]
...
$

如果一切順利,configure 命令將建立允許我們編譯 bitcoind 的訂製建構指令碼並結束。如果有任何缺失的函式庫或錯誤,configure 命令將終止並顯示錯誤。如果發生錯誤,很可能是因為缺少或不相容的函式庫。再次檢視建構文件,並確保安裝缺少的先決條件。然後再次執行 configure 並檢視是否修復了錯誤。

建構 Bitcoin Core 可執行檔案

接下來,你將編譯原始碼,這個過程可能需要一個小時才能完成,具體取決於CPU的速度和可用記憶體。在編譯過程中,你應該每隔幾秒或幾分鐘看一次輸出。如果發生錯誤,或者編譯過程中斷,可以透過再次輸入 make 恢復。鍵入 make 開始編譯可執行應用程式:

$ make
Making all in src
  CXX      crypto/libbitcoinconsensus_la-hmac_sha512.lo
  CXX      crypto/libbitcoinconsensus_la-ripemd160.lo
  CXX      crypto/libbitcoinconsensus_la-sha1.lo
  CXX      crypto/libbitcoinconsensus_la-sha256.lo
  CXX      crypto/libbitcoinconsensus_la-sha512.lo
  CXX      libbitcoinconsensus_la-hash.lo
  CXX      primitives/libbitcoinconsensus_la-transaction.lo
  CXX      libbitcoinconsensus_la-pubkey.lo
  CXX      script/libbitcoinconsensus_la-bitcoinconsensus.lo
  CXX      script/libbitcoinconsensus_la-interpreter.lo

[... many more compilation messages follow ...]

$

在具有多個 CPU 的系統上,你可以設定並行編譯作業的核數。例如,make -j 2 將使用兩個 CPU 核心。如果一切順利,Bitcoin Core 已經編譯完成,你應該使用 make check 執行單元測試套件,以確保連結函式庫不會中斷。最後一步是使用 make install 命令在你的系統上安裝可執行檔案。系統可能會提示你輸入使用者密碼,因為此步驟需要管理許可權:

$ make check && sudo make install
Password:
Making install in src
 ../build-aux/install-sh -c -d '/usr/local/lib'
libtool: install: /usr/bin/install -c bitcoind /usr/local/bin/bitcoind
libtool: install: /usr/bin/install -c bitcoin-cli /usr/local/bin/bitcoin-cli
libtool: install: /usr/bin/install -c bitcoin-tx /usr/local/bin/bitcoin-tx
...
$

+bitcoind+預設安裝在 /usr/local/bin 中,你可以檢視:

$ which bitcoind
/usr/local/bin/bitcoind

$ which bitcoin-cli
/usr/local/bin/bitcoin-cli

執行Bitcoin Core節點

比特幣的點對點網路由網路“節點”組成,主要由志願者和一些建構比特幣應用的企業執行。那些執行比特幣節點的人對比特幣區塊鏈擁有直接和權威的視野,並擁有所有交易的本地副本,由他們自己的系統進行獨立驗證。透過執行節點,你可以不依靠任何第三方來驗證交易。此外,你還可以透過增強比特幣網路的能力,為比特幣網路做出貢獻。

然而,執行一個節點,需要有足夠資源來處理所有比特幣交易的永久的可連線的系統。取決於你是否選擇索引所有交易並儲存區塊鏈的完整副本,你可能還需要大量的磁碟空間和記憶體。在2018年初,一個全部索引的節點需要至少2GB記憶體和160GB硬碟空間(參見 https://blockchain.info/charts/blocks-size)。比特幣節點也需要網路頻寬來傳輸和接收比特幣交易和區塊。如果你的網路頻寬有限,則你可能不應該在其上執行比特幣節點,或者以限制其頻寬的方式執行它(參見 Sample configuration of a resource-constrained system)。

Tip

Bitcoin Core預設儲存完整的區塊鏈副本,包括2009年以來所有比特幣網路上發生的交易。該資料集的大小為幾十GB,可以在幾天或幾周內遞增下載,具體取決於你的CPU和網路速度。在完整的區塊鏈資料集下載完之前,Bitcoin Core將無法處理交易或更新帳戶餘額。確保你有足夠的磁碟空間,頻寬和時間來完成初始同步。你可以配置Bitcoin Core,透過丟棄舊塊來減少區塊鏈的大小。(參見 Sample configuration of a resource-constrained system), 但在丟棄資料之前它仍會下載整個資料集。

儘管存在資源限制,仍有數千志願者執行比特幣節點。有些系統像Raspberry Pi一樣簡單(35美元的紙盒大小的電腦)。許多志願者還在租用伺服器上執行比特幣節點,通常是Linux的一些變體。Virtual Private Server(VPS)或_Cloud Computing Server_實例可用於執行比特幣節點。這些伺服器可以每月25美元或50美元的價格從各種提供商處獲得。

為什麼要執行比特幣節點呢?以下是一些理由:

  • 你正在開發比特幣軟體,需要依靠比特幣節點進行網路和區塊鏈的API訪問。

  • 你正在建構必須根據比特幣的共識規則驗證交易的應用程式。例如,比特幣軟體公司通常執行多個節點。

  • 你想支援比特幣。執行一個節點可以使網路更強大,能夠服務更多的錢包,更多的使用者和更多的交易。

  • 你不想依賴任何第三方來處理或驗證你的交易。

如果你正在閱讀本書並且對開發比特幣軟體感興趣,那麼你應該執行自己的節點。

配置Bitcoin Core節點

Bitcoin Core在每次啟動時會在其資料目錄中查詢配置檔案。在本節中,我們將研究各種配置選項並進行配置。要找到配置檔案,請在終端中執行 bitcoind -printtoconsole 並檢視前幾行。

$ bitcoind -printtoconsole
Bitcoin version v0.15.0
Using the 'standard' SHA256 implementation
Using data directory /home/ubuntu/.bitcoin/
Using config file /home/ubuntu/.bitcoin/bitcoin.conf
...
[a lot more debug output]
...

確定了配置檔案的位置之後,你可以按Ctrl-C關閉該節點。通常配置檔案位於使用者主目錄下的_.bitcoin_資料目錄中。接下來在編輯器中開啟配置檔案。

Bitcoin Core提供了超過100種配置選項,可以修改網路節點的行為,區塊鏈的儲存以及許多其他方面。要檢視這些選項的列表,請執行 bitcoind --help:

$ bitcoind --help
Bitcoin Core Daemon version v0.15.0

Usage:
  bitcoind [options]                     Start Bitcoin Core Daemon

Options:

  -?
       Print this help message and exit

  -version
       Print version and exit

  -alertnotify=<cmd>
       Execute command when a relevant alert is received or we see a really
       long fork (%s in cmd is replaced by message)
...
[many more options]
...

  -rpcthreads=<n>
       Set the number of threads to service RPC calls (default: 4)

以下是你可以在配置檔案中設定的一些最重要的選項,也可以作為 bitcoind 的命令列引數:

alertnotify

執行指定的命令或指令碼,向該節點的擁有者傳送緊急警報,通常透過電子郵件的形式。

conf

配置檔案的替代位置。這僅適用於 bitcoind 的命令列引數。

datadir

放置所有區塊鏈資料的目錄。預設情況下,這是你的主目錄的 .bitcoin 目錄的子目錄。確保這個目錄所在的檔案系統有數GB的可用空間。

prune

透過刪除舊的塊,將磁碟空間需求減少到多少MB。在不適合存放完整區塊鏈的資源受限節點上使用它。

txindex

維護所有交易的索引。這意味著,允許你以程式設計方式透過ID檢索一個完整的區塊鏈副本的任何交易。

dbcache

UTXO快取的大小。預設值是300MB。在高階硬體上增加該值,在低端硬體上減少該值的大小以節省記憶體,但會導致更多磁碟開銷。

maxconnections

設定可以從最多多少個節點接受連線。將預設值減小將減少你的頻寬消耗。如果你有頻寬限制或按頻寬支付,請使用此選項。

maxmempool

將交易記憶體池的大小設定為多少MB。在記憶體受限的節點上使用。

maxreceivebuffer/maxsendbuffer

將每個連線的記憶體緩衝區限制為多少KB。在記憶體受限的節點上使用。

minrelaytxfee

設定你願意傳播的交易的最低費率。在此值以下,交易處理為非標準交易,從交易池中拒絕並且不轉發。

交易資料庫索引和txindex選項

預設情況下,Bitcoin Core只建立包含使用者的錢包相關交易的資料庫。如果你想使用 getrawtransaction 之類別的命令訪問任何交易,(參見 檢查並解碼交易), 你需要在配置檔案中設定 txindex=1 以使 Bitcoin Core 建立完整的交易索引。如果你一開始未設定此選項,在之後設定完成後需要使用 bitcoind -reindex 重啟並等待其重新建構索引。

Sample configuration of a full-index node 展示了如何將前面的選項與完全索引的節點相結合,作為比特幣應用程式的API後端執行。

Example 1. Sample configuration of a full-index node
alertnotify=myemailscript.sh "Alert: %s"
datadir=/lotsofspace/bitcoin
txindex=1

Sample configuration of a resource-constrained system 展示了資源受限節點的配置。

Example 2. Sample configuration of a resource-constrained system
alertnotify=myemailscript.sh "Alert: %s"
maxconnections=15
prune=5000
dbcache=150
maxmempool=150
maxreceivebuffer=2500
maxsendbuffer=500

在按照你需求編輯了配置檔案之後,可以執行 bitcoind -printtoconsole 來測試

$ bitcoind -printtoconsole

Bitcoin version v0.15.0
InitParameterInteraction: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1
Assuming ancestors of block 0000000000000000003b9ce759c2a087d52abc4266f8f4ebd6d768b89defa50a have valid signatures.
Using the 'standard' SHA256 implementation
Default data directory /home/ubuntu/.bitcoin
Using data directory /lotsofspace/.bitcoin
Using config file /home/ubuntu/.bitcoin/bitcoin.conf
Using at most 125 automatic connections (1048576 file descriptors available)
Using 16 MiB out of 32/2 requested for signature cache, able to store 524288 elements
Using 16 MiB out of 32/2 requested for script execution cache, able to store 524288 elements
Using 2 threads for script verification
HTTP: creating work queue of depth 16
No rpcpassword set - using random cookie authentication
Generated RPC authentication cookie /lotsofspace/.bitcoin/.cookie
HTTP: starting 4 worker threads
init message: Verifying wallet(s)...
Using BerkeleyDB version Berkeley DB 4.8.30: (April  9, 2010)
Using wallet wallet.dat
CDBEnv::Open: LogDir=/lotsofspace/.bitcoin/database ErrorFile=/lotsofspace/.bitcoin/db.log
scheduler thread start
Cache configuration:
* Using 250.0MiB for block index database
* Using 8.0MiB for chain state database
* Using 1742.0MiB for in-memory UTXO set (plus up to 286.1MiB of unused mempool space)
init message: Loading block index...
Opening LevelDB in /lotsofspace/.bitcoin/blocks/index
Opened LevelDB successfully

[... more startup messages ...]

確認配置正確被載入後可以按Ctrl-C結束程序。

要將Bitcoin Core作為後臺程序執行,可以使用 bitcoind -daemon.

要觀察節點的程序和執行時狀態,可使用 bitcoin-cli getblockchaininfo:

$ bitcoin-cli getblockchaininfo
{
  "chain": "main",
  "blocks": 0,
  "headers": 83999,
  "bestblockhash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
  "difficulty": 1,
  "mediantime": 1231006505,
  "verificationprogress": 3.783041623201835e-09,
  "chainwork": "0000000000000000000000000000000000000000000000000000000100010001",
  "pruned": false,
  [...]
}

這展示了區塊鏈高度為0個塊,有83999個區塊頭的節點。節點先獲取最佳鏈的區塊頭,然後繼續下載完整塊。

在你完成選項配置之後,應該將比特幣新增到作業系統中的啟動指令碼中,以便它可以持續執行並在作業系統重新啟動時重啟。你可以在 contrib/init 下找到比特幣源目錄中各種作業系統的啟動指令碼範例以及顯示哪個系統使用哪個指令碼的 README.md 檔案。

Bitcoin Core API

Bitcoin Core 客戶端實現了JSON-RPC介面,也可以使用命令列工具 bitcoin-cli 來訪問。命令列允許我們以互動的方式試驗透過API方式提供的功能。首先,呼叫 help 命令檢視可用比特幣RPC命令的列表:

$ bitcoin-cli help
addmultisigaddress nrequired ["key",...] ( "account" )
addnode "node" "add|remove|onetry"
backupwallet "destination"
createmultisig nrequired ["key",...]
createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,...}
decoderawtransaction "hexstring"
...
...
verifymessage "bitcoinaddress" "signature" "message"
walletlock
walletpassphrase "passphrase" timeout
walletpassphrasechange "oldpassphrase" "newpassphrase"

每個命令都可能需要許多引數。要獲得更詳細的引數資訊,請在 help 後新增命令名。例如,要檢視 getblockhash RPC命令的幫助:

$ bitcoin-cli help getblockhash
getblockhash height

Returns hash of block in best-block-chain at height provided.

Arguments:
1. height         (numeric, required) The height index

Result:
"hash"         (string) The block hash

Examples:
> bitcoin-cli getblockhash 1000
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockhash", "params": [1000] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/

在幫助資訊的末尾,你將看到兩個RPC命令的例子,分別使用 bitcoin-cli 和HTTP客戶端 curl。這些範例示範瞭如何呼叫該命令。複製第一個範例並檢視結果:

$ bitcoin-cli getblockhash 1000
00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09

結果是一個區塊的雜湊值,在下面的章節中有更詳細的描述。該命令應該在你的系統上返回相同的結果,表明你的Bitcoin Core節點正在執行,接受命令,並且將有關塊1000的資訊返回給你。

在接下來的部分中,我們將示範一些非常有用的RPC命令及其預期的輸出。

獲得Bitcoin Core客戶端的狀態資訊

Bitcoin Core 透過 JSON-RPC 介面提供不同模組的狀態報告。最重要的命令包括 getblockchaininfo, getmempoolinfo, getnetworkinfo 和 getwalletinfo。

比特幣的 getblockchaininfo RPC 命令之前已經介紹了。getnetworkinfo 命令用於展示比特幣網路節點的基本狀態資訊。使用 bitcoin-cli 呼叫:

$ bitcoin-cli getnetworkinfo
  "version": 150000,
  "subversion": "/Satoshi:0.15.0/",
  "protocolversion": 70015,
  "localservices": "000000000000000d",
  "localrelay": true,
  "timeoffset": 0,
  "networkactive": true,
  "connections": 8,
  "networks": [
    ...
    detailed information about all networks (ipv4, ipv6 or onion)
    ...
  ],
  "relayfee": 0.00001000,
  "incrementalfee": 0.00001000,
  "localaddresses": [
  ],
  "warnings": ""
}

資料透過JSON格式返回,可以被所有程式語言處理,而且是可讀的。在這些資料中,我們可以看到比特幣軟體客戶端版本號(150000)和比特幣協議版本號(70015),當前的連線數(8),以及有關比特幣網路的各種資訊與此客戶端相關的設定。

Tip

bitcoind+客戶端來說,它需要一段時間(或許超過一天的時間)“趕上”當前區塊鏈高度,因為它從其他比特幣客戶端下載區塊。你可以使用 +getblockchaininfo 來檢視其進度,以檢視已知區塊的數量。

檢查並解碼交易

命令: getrawtransaction, decoderawtransaction

[cup_of_coffee] 的案例中, Alice從Bob’s Cafe購買了一杯咖啡。她的交易ID (txid)為+0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2+。讓我們使用API,透過交易ID來檢索和檢視這筆交易:

$ bitcoin-cli getrawtransaction 0627052b6f28912f2703066a912ea577f2ce4da4caa5a↵
5fbd8a57286c345c2f2

0100000001186f9f998a5aa6f048e51dd8419a14d8a0f1a8a2836dd734d2804fe65fa35779000↵
000008b483045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4↵
ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813014↵
10484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc54123363767↵
89d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adfffffffff0260e3160000000↵
0001976a914ab68025513c3dbd2f7b92a94e0581f5d50f654e788acd0ef8000000000001976a9↵
147f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a888ac00000000
Tip

在交易確認之前,交易ID不是可信的。區塊鏈中沒有交易的雜湊值並不意味著交易未處理。這被稱為“交易可鍛性(transaction malleability)”,因為在區塊中確認之前,交易的雜湊可以被修改。確認後,txid 是不可變的和可信的。

getrawtransaction 命令以十六進位制返回一個序列化的交易。將它作為 decoderawtransaction 命令的引數可以解碼:

$ bitcoin-cli decoderawtransaction 0100000001186f9f998a5aa6f048e51dd8419a14d8↵
a0f1a8a2836dd734d2804fe65fa35779000000008b483045022100884d142d86652a3f47ba474↵
6ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298↵
cad530a863ea8f53982c09db8f6e381301410484ecc0d46f1918b30928fa0e4ed99f16a0fb4fd↵
e0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa↵
336a8d752adfffffffff0260e31600000000001976a914ab68025513c3dbd2f7b92a94e0581f5↵
d50f654e788acd0ef8000000000001976a9147f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8↵
88ac00000000

{
  "txid": "0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2",
  "size": 258,
  "version": 1,
  "locktime": 0,
  "vin": [
    {
      "txid": "7957a35fe64f80d234d76d83a2...8149a41d81de548f0a65a8a999f6f18",
      "vout": 0,
      "scriptSig": {
        "asm":"3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1decc...",
        "hex":"483045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1de..."
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 0.01500000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 ab68...5f654e7 OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914ab68025513c3dbd2f7b92a94e0581f5d50f654e788ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "1GdK9UzpHBzqzX2A9JFP3Di4weBwqgmoQA"
        ]
      }
    },
    {
      "value": 0.08450000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 7f9b1a...025a8 OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a9147f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a888ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK"
        ]
      }
    }
  ]
}

解碼後的交易展示了此交易的所有組成部分,包括交易的輸入和輸出。我們看到將15mBitcoin轉到新地址的交易使用了一個輸入併產生了兩個輸出。此交易的輸入是以前確認的交易的輸出(vin中的 txid ,以 7957a35fe 開頭 )。兩個輸出對應於15mBitcoin的款項,和返回給傳送者的零錢。

我們可以透過使用 getrawtransaction 檢查此交易中參考的前一個交易的 txid 來進一步探索區塊鏈。我們可以追蹤一筆比特幣在不同擁有者地址之間傳遞的交易鏈。

檢查區塊

命令: getblock, getblockhash

檢查區塊與檢查交易類似。區塊可以透過 區塊高度 (height) 或 區塊雜湊 (hash) 來參考。首先,我們根據高度找到一個塊。在 [cup_of_coffee] 中,我們看到Alice的交易包含在區塊#277316中。

將塊高度作為 getblockhash 命令的引數,將返回區塊的雜湊值:

$ bitcoin-cli getblockhash 277316
0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4

現在我們知道Alice的交易被包含在哪個塊中了,我們可以使用 getblock 命令,傳遞區塊雜湊值來查詢該塊。

$ bitcoin-cli getblock 0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b3↵
1b2cc7bdc4
{
  "hash": "0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4",
  "confirmations": 37371,
  "size": 218629,
  "height": 277316,
  "version": 2,
  "merkleroot": "c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e",
  "tx": [
    "d5ada064c6417ca25c4308bd158c34b77e1c0eca2a73cda16c737e7424afba2f",
    "b268b45c59b39d759614757718b9918caf0ba9d97c56f3b91956ff877c503fbe",
    "04905ff987ddd4cfe603b03cfb7ca50ee81d89d1f8f5f265c38f763eea4a21fd",
    "32467aab5d04f51940075055c2f20bbd1195727c961431bf0aff8443f9710f81",
    "561c5216944e21fa29dd12aaa1a45e3397f9c0d888359cb05e1f79fe73da37bd",
[... hundreds of transactions ...]
    "78b300b2a1d2d9449b58db7bc71c3884d6e0579617e0da4991b9734cef7ab23a",
    "6c87130ec283ab4c2c493b190c20de4b28ff3caf72d16ffa1ce3e96f2069aca9",
    "6f423dbc3636ef193fd8898dfdf7621dcade1bbe509e963ffbff91f696d81a62",
    "802ba8b2adabc5796a9471f25b02ae6aeee2439c679a5c33c4bbcee97e081196",
    "eaaf6a048588d9ad4d1c092539bd571dd8af30635c152a3b0e8b611e67d1a1af",
    "e67abc6bd5e2cac169821afc51b207127f42b92a841e976f9b752157879ba8bd",
    "d38985a6a1bfd35037cb7776b2dc86797abbb7a06630f5d03df2785d50d5a2ac",
    "45ea0a3f6016d2bb90ab92c34a7aac9767671a8a84b9bcce6c019e60197c134b",
    "c098445d748ced5f178ef2ff96f2758cbec9eb32cb0fc65db313bcac1d3bc98f"
  ],
  "time": 1388185914,
  "mediantime": 1388183675,
  "nonce": 924591752,
  "bits": "1903a30c",
  "difficulty": 1180923195.258026,
  "chainwork": "000000000000000000000000000000000000000000000934695e92aaf53afa1a",
  "previousblockhash": "0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569",
  "nextblockhash": "000000000000000010236c269dd6ed714dd5db39d36b33959079d78dfd431ba7"
}

這個區塊包含 419 筆交易,第64個交易(0627052b...)是Alice的交易。height 欄位告訴我們它是區塊鏈中的第277316個區塊。

使用Bitcoin Core的程式設計介面

bitcoin-cli 助手對於探索 Bitcoin Core API和測試功能非常有用。但API的重要功能是以程式設計方式訪問。在本節中,我們將示範如何透過另一個程式訪問 Bitcoin Core。

Bitcoin Core的API是JSON-RPC介面. JSON代表JavaScript Object Notation,是一種非常方便人類和程式閱讀的資料格式。RPC代表遠端過程呼叫,這意味著我們透過網路協議呼叫遠端(在 Bitcoin Core 節點上的)函式。在這種情況下,網路協議是HTTP或HTTPS(用於加密連線)。

當我們使用 bitcoin-cli 命令獲取命令幫助時,它向我們展示了使用 curl(常用的命令列HTTP客戶端)構造JSON-RPC呼叫的範例:

$ curl --user myusername --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/

此命令表示 curl 向本地主機(127.0.0.1)提交HTTP請求,連線到預設的比特幣埠(8332),並使用 text/plain 編碼為 getblockchaininfo 方法提交 jsonrpc 請求。

你可能會注意到curl會要求憑證隨請求一起傳送。Bitcoin Core在每次啟動時建立一個隨機密碼,並將其放置在名稱為 .cookie 的資料目錄中。bitcoin-cli 助手可以根據資料目錄讀取此密碼檔案。同樣,你可以複製密碼並將其傳遞給curl(或任何更高級別的Bitcoin Core RPC包裝器)。或者,你可以使用 Bitcoin Core 原始碼目錄中的 ./share/rpcuser/rpcuser.py 中提供的助手程式指令碼建立一個靜態密碼。

你可以正在自己的程式中使用HTTP函式庫來實現JSON-RPC呼叫,類似於前面的 curl 範例。

然而,大多數程式語言都有一些“包裝”了 Bitcoin Core API 的函式庫,簡便很多。我們將使用 python-bitcoinlib 函式庫來簡化API訪問。你需要有一個正在執行的Bitcoin Core實例,用於進行JSON-RPC呼叫。

Running getblockchaininfo via Bitcoin Core’s JSON-RPC API 中的 Python 指令碼呼叫 getblockchaininfo 並列印返回資料中的區塊個數。

Example 3. Running getblockchaininfo via Bitcoin Core’s JSON-RPC API
link:code/rpc_example.py[role=include]

執行它可以得到下面的結果:

$ python rpc_example.py
394075

它標明本地的Bitcoin Core節點在其區塊鏈中有394075個區塊。

接下來,讓我們使用 getrawtransaction 和 decodetransaction 呼叫來檢索Alice的咖啡交易細節。在Retrieving a transaction and iterating its outputs中,我們檢索Alice的交易並列出交易的輸出。對於每個輸出,我們顯示收件人地址和值。提醒一下,Alice 的交易有一個支付給 Bob’s Cafe 的輸出和一個返回給Alice的找零輸出。

Example 4. Retrieving a transaction and iterating its outputs
link:code/rpc_transaction.py[role=include]

執行這段程式碼:

$ python rpc_transaction.py
([u'1GdK9UzpHBzqzX2A9JFP3Di4weBwqgmoQA'], Decimal('0.01500000'))
([u'1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK'], Decimal('0.08450000'))

前面的兩個例子都很簡單。你並不需要寫程式來執行它們;你可以輕鬆使用 bitcoin-cli 助手。然而,下一個例子需要幾百次RPC呼叫,更清楚地說明了程式設計介面的作用。

Retrieving a block and adding all the transaction outputs 中,我們首先檢索第277316個區塊,然後使用交易ID檢索區塊內419個交易中的每一個。接下來,我們遍歷每筆交易的輸出並累加起來。

Example 5. Retrieving a block and adding all the transaction outputs
link:code/rpc_block.py[role=include]

執行這段程式碼:

$ python rpc_block.py

('Total value in block: ', Decimal('10322.07722534'))

我們的範例程式碼計算出此區塊的總價值為10322.07722534 BTC(包括25BTC獎勵和0.0909BTC費用)。透過在區塊瀏覽器中搜尋雜湊或高度,進行資料比較。一些區塊瀏覽器報告不包括獎勵和排除費用的總價值,看看你是否可以發現差異。

可選的客戶端、程式函式庫和工具套件

比特幣生態系統中有許多可選的客戶端,程式函式庫和工具套件,甚至是完整節點的實現。它們以各種程式語言實現,為程式設計師提供其首選程式語言的原生介面。

下面列出了一些:

C/C++

Bitcoin Core

比特幣的參考實作

libbitcoin

跨平臺的C++開發工具,節點和共識函式函式庫

bitcoin explorer

Libbitcoin的命令列工具

picocoin

Jeff Garzik寫的C語音的輕量級比特幣客戶端函式庫

JavaScript

bcoin

帶有API​​的模組化,可擴充套件的完整節點實現

Bitcore

Bitpay提供的完整節點,API和程式函式庫

BitcoinJS

用於node.js和瀏覽器的純JavaScript比特幣函式庫

Java

bitcoinj

Java版完整節點客戶端函式庫

Bits of Proof (BOP)

比特幣的Java企業級實現

PHP

bitwasp/bitcoin

PHP比特幣函式庫, 和相關的專案

Python

python-bitcoinlib

Python比特幣函式庫,共識函式庫,和Peter Todd寫的節點

pycoin

Richard Kiss寫的Python比特幣函式庫

pybitcointools

Vitalik Buterin寫的Python比特幣函式庫

Ruby

bitcoin-client

Ruby封裝的JSON-RPC API

Go

btcd

Go語言的完整節點客戶端

Rust

rust-bitcoin

用於序列化,解析和API呼叫的Rust比特幣函式庫

C#

NBitcoin

.NET框架的綜合比特幣函式庫

Objective-C

CoreBitcoin

為ObjC和Swift提供的比特幣工具套件

還有各種程式語言的函式庫存在,還有更多的函式庫在開發。