Bitcoin Core:參考實現

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

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

Warning

儘管Bitcoin Core包含錢包的參考實現,但並不建議將其用作用戶或應用程式生產環境中的錢包。建議應用程式開發人員使用現代標準(如BIP-39和BIP-32)開發錢包(請參閱[mnemonic_code_words][hd_wallets])。 BIP代表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 download page上, 選擇最新版本的源碼壓縮包,bitcoin-0.15.0.2.tar.gz。 或者, 使用git clone命令在本地創建一個備份。 GitHub bitcoin page.

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.mdbuild-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

將交易Memory pool的大小設置為多少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[]

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

$ 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[]

運行這段程式碼:

$ 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[]

運行這段程式碼:

$ 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提供的比特幣工具包

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