比特幣學習筆記——————3、比特幣客戶端

FLy_鵬程萬里發表於2018-06-12


3.1 比特幣核心:參考實現

你可以從bitcoin.org下載標準客戶端,即比特幣核心,也叫“中本聰客戶端”(satoshi client)。它實現了比特幣系統的所有方面,包括錢包、對整個交易賬簿(區塊鏈)完整拷貝的交易確認引擎,和點對點比特幣網路中的一個完整網路節點。


在Bitcoin網站的選擇錢包頁面,下載參考客戶端比特幣核心。根據作業系統不同,你將下載不同的可執行安裝工具。對於Windows,它是一個ZIP歸檔檔案或.exe格式的可執行檔案。對於Mac OS,它是一個.dmg格式的磁碟映像。Linux版本包括用於Ubuntu系統的PPA包,或是 tar.gz格式的壓縮包。圖3-1所示的Bitcoin.org頁面上列出了一些推薦的比特幣客戶端。


圖3-1 選擇比特幣客戶端

3.1.1 第一次執行比特幣核心

如果你下載了一個安裝包,比如.exe、.dmg、或PPA,你可以和安裝其它任何應用程式一樣,在你的作業系統上安裝它。對於Windows,執行.exe檔案,按照提示一步步操作。對於Mac OS,啟動.dmg檔案,然後將Bitcoin-QT 圖示拖拽到你的應用程式目錄就可以了。對於Ubuntu,在檔案資源管理器中雙擊PPA檔案,會開啟程式包管理器來安裝它。一旦完成了安裝,在你的應用程式列表中會有一個新的應用叫Bitcoin-QT。雙擊這個圖示就可以啟動比特幣客戶端了。

第一次執行比特幣核心時,它會開始下載整個區塊鏈,這個過程可能需要數天(見下圖)。讓它在後臺執行,直到顯示“已同步”,並且餘額旁邊不再顯示“資料同步中”。

比特幣核心擁有交易賬簿(區塊鏈)的一份完整拷貝,裡面記錄了自2009年比特幣網路被發明以來發生在比特幣網路上的每一筆交易。這個資料集有幾個GB(在2013年底大約是16GB),並且需要幾天的時間完成增量形式的下載(從區塊0順次下載到最新區塊)。在整個區塊鏈資料集下載完成前,客戶端將不能處理任何交易或是更新賬戶餘額。在下載資料集的過程中,客戶端賬戶餘額旁會顯示“資料同步中”,底部會顯示“正在同步”。請確保你有足夠的磁碟空間、頻寬和時間來完成初始同步。

3.1.2 從原始碼編譯比特幣核心

對於開發者,可以選擇下載包含完整原始碼的ZIP包,也可以從Github上克隆權威的原始碼倉庫。在面GitHub上的比特幣頁面,在側邊欄選擇下載ZIP。或者使用git命令列(git command line)在自己系統上建立原始碼的本地拷貝。在下面的例子中,我們將通過unix風格的命令列,在Linux或是Mac OS 上克隆原始碼:

$ git clone https://github.com/bitcoin/bitcoin.git
Cloning into 'bitcoin'...
remote: Counting objects: 31864, done.
remote: Compressing objects: 100% (12007/12007), done.
remote: Total 31864 (delta 24480), reused 26530 (delta 19621)
Receiving objects: 100% (31864/31864), 18.47 MiB | 119 KiB/s, done.
Resolving deltas: 100% (24480/24480), done.
$

終端上的提示和輸出結果可能會因版本有所不同。即使你的螢幕上輸出的內容跟這裡的例子有點不一樣,請遵照程式碼中的文件,這些都是正常的。

在git clone操作完成後,在你本地的bitcoin目錄就會有一份完整的原始碼拷貝。通過在命令提示行輸入cd bitcoin切換到這個目錄下:

$ cd bitcoin

預設情況下,本地拷貝將與最新的程式碼同步,這可能是bitcoin的一個不穩定或是 beta 版本。在編譯這些程式碼之前,簽出釋出標籤(realease tag)以選擇某一特定版本(a specific version)。 這將通過一個關鍵的標籤標記,讓本地拷貝與程式碼倉庫的特定快照同步。開發者用標籤來標記程式碼的特定發行版本號(version numBTCer)。首先,要找到可用的標籤,可以通過git tag命令:

$ git tag
v0.1.5
v0.1.6test1
v0.2.0
v0.2.10
v0.2.11
v0.2.12

[... many more tags ...]

v0.8.4rc2
v0.8.5
v0.8.6
v0.8.6rc1
v0.9.0rc1

列出的標籤是bitcoin的所有發行版本。按照約定,帶有rc字尾的是預發行版本,可以用來測試。沒有字尾的穩定版本可以直接在產品環境上執行。從上面的列表中,選擇最新的發行版本,目前是v0.9.0rc1。為了讓原生程式碼跟這個版本一致,我們需要用git checkout 命令:

$ git checkout v0.9.0rc1
Note: checking out 'v0.9.0rc1'.

HEAD is now at 15ec451... Merge pull request #3605
$

原始碼包含文件,可以在多個資料夾中找到。在命令提示行輸入more README.md可以在bitcoin目錄下的README.md中檢視主文件,用空格鍵可以翻頁。在這一章,我們將構建命令列的比特幣客戶端,在linux上稱作bitcoind。在您的平臺上,通過輸入more doc/build-unix.md,可以閱讀編譯bitcoind命令列客戶端的說明。Mac OSX和Windows平臺的說明可以在doc目錄下找到,分別是build-osx.md或是build-msw.md。

仔細閱讀build文件第一部分中build的必備條件。這些是在你編譯之前你的系統上必須具備的庫檔案。如果缺少這些必備條件,構建過程將會出現錯誤並導致失敗。如果因為缺少一個必備條件而發生這種情況,你可以先安裝它,然後在你停下的地方重新構建。假設這些必備條件已經具備,你就可以開始構建過程,通過authgen.sh指令碼,生成一組構建指令碼。

從v0.9版本開始,比特幣核心的構建過程改用autogen/configure/make 體系。舊版本是用一個簡單的Makefile,並且和下面的例子稍微有一點不同。請遵照你想要編譯版本的說明文件。v0.9版本引入的 autogen/configure/make 構建體系可能用於未來所有版本的程式碼,是下面的例子中演示的系統

$ ./autogen.sh
configure.ac:12: installing `src/build-aux/config.guess'
configure.ac:12: installing `src/build-aux/config.sub'
configure.ac:37: installing `src/build-aux/install-sh'
configure.ac:37: installing `src/build-aux/missing'
src/Makefile.am: installing `src/build-aux/depcomp'
$

autogen.sh指令碼建立了一系列的自動配置指令碼,會詢問你的系統以發現正確的設定,確保你已安裝必要的庫來編譯原始碼。這裡面最重要的是configure指令碼,它會提供許多不同的選項來定製構建過程。輸入./configure --help 可以檢視各種不同的選項:

$ ./configure --help

`configure' configures Bitcoin Core 0.9.0 to adapt to many kinds of systems.

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

To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE.  

See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit

[... many more options and variables are displayed below ...]

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]

[... more options ...]

Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations.

Report bugs to <info@bitcoin.org>.

$

通過使用--enable-FEATURE和--disable-FEATURE選項,configure指令碼允許你啟用或是禁用某些功能,FEATURE需要被替換成功能名稱,在上面的幫助輸出中可以找到。在這一章,我們將用預設的功能來構建bitcoind客戶端。這裡不會使用配置選項,但是你應該檢查一遍,明白哪些可選的功能可以作為客戶端的一部分。下一次,執行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... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes

[... many more system features are tested ...]

configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating src/test/Makefile
config.status: creating src/qt/Makefile
config.status: creating src/qt/test/Makefile
config.status: creating share/setup.nsi
config.status: creating share/qt/Info.plist
config.status: creating qa/pull-tester/run-bitcoind-for-test.sh
config.status: creating qa/pull-tester/build-tests.sh
config.status: creating src/bitcoin-config.h
config.status: executing depfiles commands
$

如果一切順利,configure命令將會以建立可定製的構建指令碼結束。這些構建指令碼允許我們編譯bitcoind。如果有缺失的庫或是錯誤,configur命令將會以錯誤資訊終止。如果出現了錯誤,可能是因為缺少庫或是有不相容的庫。重新檢查構建文件,確認你已經安裝缺失的必備條件。然後執行configure,看看錯誤是否消失了。下一步,你將編譯原始碼,這個過程可能需要1個小時完成。在編譯的過程中,你應該過幾秒或是幾分鐘看一下輸出結果。如果出現了問題,你會看到錯誤。如果中斷了,編譯的過程可以在任何時候恢復。輸入make命令就可以開始編譯了:

$ make
Making all in src
make[1]: Entering directory `/home/ubuntu/bitcoin/src'
make  all-recursive
make[2]: Entering directory `/home/ubuntu/bitcoin/src'
Making all in .
make[3]: Entering directory `/home/ubuntu/bitcoin/src'
    CXX    addrman.o
    CXX    alert.o
    CXX    rpcserver.o
    CXX    bloom.o
    CXX    chainparams.o

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

    CXX    test_bitcoin-wallet_tests.o
    CXX    test_bitcoin-rpc_wallet_tests.o
    CXXLD  test_bitcoin
make[4]: Leaving directory `/home/ubuntu/bitcoin/src/test'
make[3]: Leaving directory `/home/ubuntu/bitcoin/src/test'
make[2]: Leaving directory `/home/ubuntu/bitcoin/src'
make[1]: Leaving directory `/home/ubuntu/bitcoin/src'
make[1]: Entering directory `/home/ubuntu/bitcoin'
make[1]: Nothing to be done for `all-am'.
make[1]: Leaving directory `/home/ubuntu/bitcoin'
$

如果一切順利,bitcoind現在已經編譯完成。最後一步就是通過make命令,安裝 bitcoind 可執行檔案到你的系統路徑下:

$ sudo make install
Making install in src
Making install in .
    /bin/mkdir -p '/usr/local/bin'
    /usr/bin/install -c bitcoind bitcoin-cli '/usr/local/bin'
Making install in test
make  install-am
 /bin/mkdir -p '/usr/local/bin'
  /usr/bin/install -c test_bitcoin '/usr/local/bin'
$

你可以通過詢問系統下面2個可執行檔案的路徑,來確認bitcoin是否安裝成功。

$ which bitcoind
/usr/local/bin/bitcoind

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

bitcoind 預設的安裝位置是/usr/local/bin。當你第一次執行bitcoind時,它會提醒你用一個安全密碼給JSON-RPC介面建立一個配置檔案。通過在終端輸入bitcoind就可以執行bitcoind了:

$ bitcoind
Error: To use the "-server" option, you must set a rpcpassword in the configuration file:
/home/ubuntu/.bitcoin/bitcoin.conf
It is recommended you use the following random password:
rpcuser=bitcoinrpc
rpcpassword=2XA4DuKNCbtZXsBQRRNDEwEY2nM6M4H9Tx5dFjoAVVbK
(you do not need to remember this password)
The username and password MUST NOT be the same.
If the file does not exist, create it with owner-readable-only file permissions.
It is also recommended to set alertnotify so you are notified of problems;
for example: alertnotify=echo %s | mail -s "Bitcoin Alert" admin@foo.com

在你喜歡的編輯器中編輯配置檔案並設定引數,將其中的密碼替換成bitcoind推薦的強密碼。不要使用出現在這裡的密碼。在.bitcoin目錄下建立一個名為.bitcoin/bitcoin.conf 的檔案,然後輸入使用者名稱和密碼:

rpcuser=bitcoinrpc
rpcpassword=2XA4DuKNCbtZXsBQRRNDEwEY2nM6M4H9Tx5dFjoAVVbK

當你正在編輯配置檔案的時候,你可能想要設定一些其他選項,例如txindex(見“交易資料庫索引及txindex選項”)。通過輸入bitcoind --help,可以檢視所有可用的選項列表。

現在可以執行比特幣核心客戶端。當你第一次執行的時候,它會下載所有的區塊,重新構建比特幣區塊鏈。這是一個好幾個GB的檔案,可能需要大約2天的時間全部下載完。你可以通過SourceForge上的BitTorrent客戶端下載區塊鏈的部分拷貝來縮短區塊鏈的初始化時間。

選項 -daemon 可以以後臺模式執行 bitcoind。

$ bitcoind -daemon

Bitcoin version v0.9.0rc1-beta (2014-01-31 09:30:15 +0100)
Using OpenSSL version OpenSSL 1.0.1c 10 May 2012
Default data directory /home/bitcoin/.bitcoin
Using data directory /bitcoin/
Using at most 4 connections (1024 file descriptors available)
init message: Verifying wallet...
dbenv.open LogDir=/bitcoin/database ErrorFile=/bitcoin/db.log
Bound to [::]:8333
Bound to 0.0.0.0:8333
init message: Loading block index...
Opening LevelDB in /bitcoin/blocks/index
Opened LevelDB successfully
Opening LevelDB in /bitcoin/chainstate
Opened LevelDB successfully

[... more startup messages ...]

3.2 通過命令列使用比特幣核心的JSON-RPC API介面

比特幣核心客戶端實現了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"
decodescript "hex"
dumpprivkey "bitcoinaddress"
dumpwallet "filename"
getaccount "bitcoinaddress"
getaccountaddress "account"
getaddednodeinfo dns ( "node" )
getaddressesbyaccount "account"
getbalance ( "account" minconf )
getbestblockhash
getblock "hash" ( verbose )
getblockchaininfo
getblockcount
getblockhash index
getblocktemplate ( "jsonrequestobject" )
getconnectioncount
getdifficulty
getgenerate
gethashespersec
getinfo
getmininginfo
getnettotals
getnetworkhashps ( blocks height )
getnetworkinfo
getnewaddress ( "account" )
getpeerinfo
getrawchangeaddress
getrawmempool ( verbose )
getrawtransaction "txid" ( verbose )
getreceivedbyaccount "account" ( minconf )
getreceivedbyaddress "bitcoinaddress" ( minconf )
gettransaction "txid"
gettxout "txid" n ( includemempool )
gettxoutsetinfo
getunconfirmedbalance
getwalletinfo
getwork ( "data" )
help ( "command" )
importprivkey "bitcoinprivkey" ( "label" rescan )
importwallet "filename"
keypoolrefill ( newsize )
listaccounts ( minconf )
listaddressgroupings
listlockunspent
listreceivedbyaccount ( minconf includeempty )
listreceivedbyaddress ( minconf includeempty )
listsinceblock ( "blockhash" target-confirmations )
listtransactions ( "account" count from )
listunspent ( minconf maxconf ["address",...] )
lockunspent unlock [{"txid":"txid","vout":n},...]
move "fromaccount" "toaccount" amount ( minconf "comment" )
ping
sendfrom "fromaccount" "tobitcoinaddress" amount ( minconf "comment" "commentto"
)
sendmany "fromaccount" {"address":amount,...} ( minconf "comment" )
sendrawtransaction "hexstring" ( allowhighfees )
sendtoaddress "bitcoinaddress" amount ( "comment" "comment-to" )
setaccount "bitcoinaddress" "account"
setgenerate generate ( genproclimit )
settxfee amount
signmessage "bitcoinaddress" "message"
signrawtransaction "hexstring" ( [{"txid":"id","vout":n,"scriptPub-
Key":"hex","redeemScript":"hex"},...] ["privatekey1",...] sighashtype )
stop
submitblock "hexdata" ( "jsonparametersobject" )
validateaddress "bitcoinaddress"
verifychain ( checklevel numBTClocks )
verifymessage "bitcoinaddress" "signature" "message"
walletlock
walletpassphrase "passphrase" timeout
walletpassphrasechange "oldpassphrase" "newpassphrase"

3.2.1 獲得比特幣核心客戶端狀態的資訊

命令:getinfo

比特幣getinfoRPC命令顯示關於比特幣網路節點、錢包、區塊鏈資料庫狀態的基礎資訊。使用bitcoin-cli執行它:

$ bitcoin-cli getinfo
{
"version" : 90000,
"protocolversion" : 70002,
"walletversion" : 60000,
"balance" : 0.00000000,
"blocks" : 286216,
"timeoffset" : -72,
"connections" : 4,
"proxy" : "",
"difficulty" : 2621404453.06461525,
"testnet" : false,
"keypoololdest" : 1374553827,
"keypoolsize" : 101,
"paytxfee" : 0.00000000,
"errors" : ""
}

資料以JSON格式顯示,JSON是一種可以很容易被程式語言“消耗”,但同時對人類可讀性也很高的格式。在這些資料中,我們看到比特幣軟體客戶端的版本編號(90000),協議編號(70002),錢包編號(60000)。我們看到錢包中的當前餘額是0。我們看到當前的區塊高度,這可以告訴我們有多少區塊對此客戶端已知(286216)。我們同樣看到關於比特幣網路和關於此客戶端的各種資料。我們將在其他章節中更具體地探索這些設定。


bitcoind客戶端需要花費可能超過一天的時間從其他比特幣客戶端下載區塊以“趕上”當前區塊鏈高度。你可以使用getinfo命令檢視已知區塊的數字以檢查同步進度。

3.2.2 錢包設定及加密

命令:encryptwalletwalletpassphrase

在你向前生成祕鑰和其他命令之前,你應當先用密碼加密錢包。對於本例,將使用encryptwallet命令,密碼為“foo”。很明顯,在你自己操作的時候記得使用強且複雜的密碼替換“foo”。

$ bitcoin-cli encryptwallet foo
wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet.
The keypool has been flushed, you need to make a new backup.
$

你可以再次使用getinfo命令以驗證錢包是否已經加密。這次你將發現有個叫做unlocked_until的新條目。這是一個計數器,告訴你保持錢包處於解鎖狀態的解密密碼將在記憶體中儲存多久。最初計數器設定為0,意味著錢包是被鎖定的:

$ bitcoin-cli getinfo
{
     "version" : 90000,
#[... other information...]
     "unlocked_until" : 0,
     "errors" : ""
}
$

想解鎖錢包,要使用walletpassphrase命令。walletpassphrase命令需要兩個引數——密碼,和多久錢包會再次被自動鎖定的秒數數字(計時器):

$ bitcoin-cli walletpassphrase foo 360
$

你可以確認錢包是解鎖狀態然後通過再次執行getinfo檢視超過時限:

$ bitcoin-cli getinfo
{
     "version" : 90000,
#[... other information ...]
     "unlocked_until" : 1392580909,
     "errors" : ""
}

3.2.3 錢包備份、純文字匯出及恢復

命令:backupwalletimportwalletdumpwallet

下一步,我們將練習建立錢包的備份檔案,然後從備份檔案重新載入錢包。使用backupwallet命令備份,提供檔名作為命令引數。這裡我們將錢包備份為檔案wallet.backup

$ bitcoin-cli backupwallet wallet.backup
$

現在,為了重新載入備份檔案,我們使用importwallet命令。如果你的錢包處於鎖定狀態,你將需要先將錢包解鎖(參考下一節的walletpassphrase)以匯入備份檔案:

$ bitcoin-cli importwallet wallet.backup
$

dumpwallet 命令用來將錢包轉儲為人類可讀的文字檔案:

$ bitcoin-cli dumpwallet wallet.txt
$ more wallet.txt
# Wallet dump created by Bitcoin v0.9.0rc1-beta (2014-01-31 09:30:15 +0100)
# * Created on 2014-02- 8dT20:34:55Z
# * Best block at time of backup was 286234
(0000000000000000f74f0bc9d3c186267bc45c7b91c49a0386538ac24c0d3a44),
# mined on 2014-02- 8dT20:24:01Z

KzTg2wn6Z8s7ai5NA9MVX4vstHRsqP26QKJCzLg4JvFrp6mMaGB9 2013-07- 4dT04:30:27Z
change=1 # addr=16pJ6XkwSQv5ma5FSXMRPaXEYrENCEg47F
Kz3dVz7R6mUpXzdZy4gJEVZxXJwA15f198eVui4CUivXotzLBDKY 2013-07- 4dT04:30:27Z
change=1 # addr=17oJds8kaN8LP8kuAkWTco6ZM7BGXFC3gk
[... many more keys ...]

$

3.2.4 錢包地址及接收交易

命令:getnewaddressgetreceivedbyaddresslisttransactionsgetaddressesbyaccountgetbalance

比特幣參考客戶端維護了一個地址池,地址池的大小可以用getinfo命令keypoolsize引數獲取。這些地址是自動生成的,可以被用作公開接收地址或零錢地址。使用getnewaddress命令可以獲得其中的一個地址:

$ bitcoin-cli getnewaddress
1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL

現在我們可以使用這個地址從一個外部錢包(假設你在其他交易所、線上錢包或其他bitcoind錢包有一些比特幣)向我們的bitcoind錢包傳送一小筆比特幣。在本例中,我們將向下面的地址中傳送50mBTC(0.050比特幣)。

我們可以詢問bitcoind客戶端此地址已經接收到的比特幣數額,以及指定該數額要被加到餘額中所需要的確認數。在本例中,我們指定只需要0個確認。在從另一個錢包傳送比特幣數秒之後,我們將在這個錢包看到反應。我們用getreceivedbyaddress命令、這個地址及設定確認數為0:

$ bitcoin-cli getreceivedbyaddress 1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL 0
0.05000000

如果我們忽略這個命令後面的0,我們將只能在至少minconf個確認之後才能看到數額,minconf是想要某筆交易出現在餘額中所設定的最少確認數。minconf設定在bitcoind配置檔案指定。由於這筆傳送比特幣的交易僅在數秒之前完成,它還沒有被確認,因而我們將看到餘額是0:

$ bitcoin-cli getreceivedbyaddress 1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL
0.00000000

整個錢包接收到的交易可以通過使用listtransactions命令展示出來:

$ bitcoin-cli listtransactions
[
  {
      "account" : "",
      "address":"1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",
      "category" : "receive",
      "amount" : 0.05000000,
      "confirmations" : 0,
      "txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309ac
bae2c14ae3",
      "time" : 1392660908,
      "timereceived" : 1392660908
  }
]

我們可以使用getaddressesbyaccount命令列出整個錢包的所有地址:

$ bitcoin-cli getaddressesbyaccount ""
[
     "1LQoTPYy1TyERbNV4zZbhEmgyfAipC6eqL",
     "17vrg8uwMQUibkvS2ECRX4zpcVJ78iFaZS",
     "1FvRHWhHBBZA8cGRRsGiAeqEzUmjJkJQWR",
     "1NVJK3JsL41BF1KyxrUyJW5XHjunjfp2jz",
     "14MZqqzCxjc99M5ipsQSRfieT7qPZcM7Df",
     "1BhrGvtKFjTAhGdPGbrEwP3xvFjkJBuFCa",
     "15nem8CX91XtQE8B1Hdv97jE8X44H3DQMT",
     "1Q3q6taTsUiv3mMemEuQQJ9sGLEGaSjo81",
     "1HoSiTg8sb16oE6SrmazQEwcGEv8obv9ns",
     "13fE8BGhBvnoy68yZKuWJ2hheYKovSDjqM",
     "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",
     "1KHUmVfCJteJ21LmRXHSpPoe23rXKifAb2",
     "1LqJZz1D9yHxG4cLkdujnqG5jNNGmPeAMD"
]

最後,getbalance命令將顯示所有經過至少minconf個確認的交易加和後的餘額:

$ bitcoin-cli getbalance
0.05000000


如果交易還未被確認,getbalance返回的餘額將為0。配置項“minconf”決定了交易在餘額中體現的最少確認數。

3.2.5 探索及解碼交易

命令:gettransactiongetrawtransactiondecoderawtransaction

我們將使用gettransaction命令探索前面列出的入賬交易。我們使用gettransaction命令通過交易雜湊值獲取一筆交易,交易雜湊值出現在前面的txid條目:

$ bitcoin-cli gettransaction
9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3
{
     "amount" : 0.05000000,
     "confirmations" : 0,
     "txid":"9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
     "time" : 1392660908,
     "timereceived" : 1392660908,
     "details" : [
    {
     "account" : "",
     "address":"1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",
     "category" : "receive",
     "amount" : 0.05000000
    }
  ]
}


交易ID在交易確認之前並不權威。區塊鏈中找不到交易雜湊值並不意味著此筆交易沒有進行。這被稱作“交易延展性”,因為交易雜湊值在區塊確認之前是可以更改的。在確認之後txid是不變且權威的。

gettransaction命令顯示的交易格式為簡化格式。若要得到整個交易程式碼並且將之解碼,我們將使用兩個命令:getrawtransactiondecoderawtransaction。第一,getrawtransaction把交易雜湊值(txid)當做一個引數,並且把整個交易以一個“原始”的十六進位制字串的形式返回,而這也正是交易在比特幣網路上存在的形式:

$ bitcoin-cli getrawtransaction 9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae30100000001d717279515f88e2f56ce4e8a31e2ae3e9f00ba1d0add648e80c480ea22e0c7d3000000008b483045022100a4ebbeec83225dedead659bbde7da3d026c8b8e12e61a2df0dd0758e227383b302203301768ef878007e9ef7c304f70ffaf1f2c975b192d34c5b9b2ac1bd193dfba2014104793ac8a58ea751f9710e39aad2e296cc14daa44fa59248be58ede65e4c4b884ac5b5b6dede05ba84727e34c8fd3ee1d6929d7a44b6e111d41cc79e05dbfe5ceaffffffff02404b4c00000000001976a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac1f312906000000001976a914107b7086b31518935c8d28703d66d09b3623134388ac00000000

要解碼這個十六進位制字串,我們使用decoderawtransaction命令。複製貼上這個十六進位制字串作為decoderawtransaction的第一個引數以將整個內容解讀為JSON資料格式(由於格式原因,在下面例子中十六進位制字串被縮短):

$ bitcoin-cli decoderawtransaction 0100000001d717...388ac00000000
{
    "txid":"9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
    "version" : 1,
    "locktime" : 0,
    "vin" : [
        {
                "txid":"d3c7e022ea80c4808e64dd0a1dba009f3eaee2318a4ece562f8ef815952717d7",
            "vout" : 0,
            "scriptSig" : {
                "asm" : "3045022100a4ebbeec83225dedead659bbde7da3d026c8b8e12e61a2df0dd0758e227383b302203301768ef878007e9ef7c304f70ffaf1f2c975b192d34c5b9b2ac1bd193dfba20104793ac8a58ea751f9710e39aad2e296cc14daa44fa59248be58ede65e4c4b↵
884ac5b5b6dede05ba84727e34c8fd3ee1d6929d7a44b6e111d41cc79e05dbfe5cea",
                "hex": "483045022100a4ebbeec83225dedead659bbde7da3d026c8b8e12e61a2df0dd0758e227383b302203301768ef878007e9ef7c304f70ffaf1f2c975b192d34c5b9b2ac1bd193dfba2014104793ac8a58ea751f9710e39aad2e296cc14daa44fa59248be58ede65e4c4b884ac5b5b6dede05ba84727e34c8fd3ee1d6929d7a44b6e111d41cc79e05dbfe5cea"
            },
            "sequence" : 4294967295
        }
    ],
    "vout" : [
        {
            "value" : 0.05000000,
            "n" : 0,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 07bdb518fa2e6089fd810235cf1100c9c13d1fd2 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" :"76a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL"
                ]
            }
        },
        {
            "value" : 1.03362847,
            "n" : 1,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 107b7086b31518935c8d28703d66d09b36231343 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a914107b7086b31518935c8d28703d66d09b3623134388ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "12W9goQ3P7Waw5JH8fRVs1e2rVAKoGnvoy"
                ]
            }
        }
    ]
}

交易解碼展示這筆交易的所有成分,包括交易的輸入及輸出。在這個例子中,我們可以看到這筆給我們新地址存入50mBTC的交易使用了一個輸入並且產生兩個輸出。這筆交易的輸入是前一筆確認交易的輸出(展示位以d3c7開頭的vin txid)。兩個輸出則是50mBTC存入額度及返回給傳送者的找零。

我們可以使用相同命令(例如gettransaction)通過檢查由本次交易的txid索引的前一筆交易進一步探索區塊鏈。通過從一筆交易跳到另外一筆交易,我們可以追溯一連串的交易,因為幣值一定是從一個擁有者的地址傳送到另一個擁有者的地址。

一旦我們接收到的交易以記錄在區塊中的方式被確認,gettransaction命令將返回附加資訊,顯示包含交易的區塊的雜湊值(識別符號)。

$ bitcoin-cli gettransaction 9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3
{
    "amount" : 0.05000000,
    "confirmations" : 1,
    "blockhash" : "000000000000000051d2e759c63a26e247f185ecb7926ed7a6624bc31c2a717b",
    "blockindex" : 18,
    "blocktime" : 1392660808,
    "txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
    "time" : 1392660908,
    "timereceived" : 1392660908,
    "details" : [
        {
            "account" : "",
            "address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",
            "category" : "receive",
            "amount" : 0.05000000
        }
    ]
}

這裡,我們在區塊雜湊值(這筆交易所在區塊的雜湊值)條目看到新資訊,以及值為18的區塊索引(表明我們的交易為此區塊的第18筆交易)。

交易資料庫索引及txindex選項

比特幣核心預設建立包含僅與使用者錢包相關交易的資料庫。若你想使用類似gettransaction的命令訪問所有交易,你需要配置比特幣核心去建立一個完整的交易索引,這個可以通過txindex選項實現。在比特幣核心配置檔案中將txindex賦值為1(通常在安裝目錄的.bitcoin/bitcoin.conf中可以找到)。一旦你改變了此引數,你需要重啟bitcoind,並等待其重建索引。

3.2.6 探索區塊

命令:getblockgetblockhash

既然我們知道我們的交易在哪個區塊中,我們可以使用getblock命令,並把區塊雜湊值作為引數來查詢對應的區塊:

$ bitcoin-cli getblock 000000000000000051d2e759c63a26e247f185ecb7926ed7a6624b↵ c31c2a717b true
{
    "hash" : "000000000000000051d2e759c63a26e247f185ecb7926ed7a6624bc31c2a717
b",
    "confirmations" : 2,
    "size" : 248758,
    "height" : 286384,
    "version" : 2,
    "merkleroot" : "9891747e37903016c3b77c7a0ef10acf467c530de52d84735bd55538719f9916",
    "tx" : [
        "46e130ab3c67d31d2b2c7f8fbc1ca71604a72e6bc504c8a35f777286c6d89bf0",
        "2d5625725b66d6c1da88b80b41e8c07dc5179ae2553361c96b14bcf1ce2c3868",
        "923392fc41904894f32d7c127059bed27dbb3cfd550d87b9a2dc03824f249c80",
        "f983739510a0f75837a82bfd9c96cd72090b15fa3928efb9cce95f6884203214",
        "190e1b010d5a53161aa0733b953eb29ef1074070658aaa656f933ded1a177952",
        "ee791ec8161440262f6e9144d5702f0057cef7e5767bc043879b7c2ff3ff5277",
        "4c45449ff56582664abfadeb1907756d9bc90601d32387d9cfd4f1ef813b46be",
        "3b031ed886c6d5220b3e3a28e3261727f3b4f0b29de5f93bc2de3e97938a8a53",
        "14b533283751e34a8065952fd1cd2c954e3d37aaa69d4b183ac6483481e5497d",
        "57b28365adaff61aaf60462e917a7cc9931904258127685c18f136eeaebd5d35",
        "8c0cc19fff6b66980f90af39bee20294bc745baf32cd83199aa83a1f0cd6ca51",
        "1b408640d54a1409d66ddaf3915a9dc2e8a6227439e8d91d2f74e704ba1cdae2",
        "0568f4fad1fdeff4dc70b106b0f0ec7827642c05fe5d2295b9deba4f5c5f5168",
        "9194bfe5756c7ec04743341a3605da285752685b9c7eebb594c6ed9ec9145f86",
        "765038fc1d444c5d5db9163ba1cc74bba2b4f87dd87985342813bd24021b6faf",
        "bff1caa9c20fa4eef33877765ee0a7d599fd1962417871ca63a2486476637136",
        "d76aa89083f56fcce4d5bf7fcf20c0406abdac0375a2d3c62007f64aa80bed74",
        "e57a4c70f91c8d9ba0ff0a55987ea578affb92daaa59c76820125f31a9584dfc",
        "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",

#[... many more transactions ...]

    ],
    "time" : 1392660808,
    "nonce" : 3888130470,
    "bits" : "19015f53",
    "difficulty" : 3129573174.52228737,
    "chainwork" : "000000000000000000000000000000000000000000001931d1658fc04879e466",
    "previousblockhash" : "0000000000000000177e61d5f6ba6b9450e0dade9f39c257b4d48b4941ac77e7",
    "nextblockhash" : "0000000000000001239d2c3bf7f4c68a4ca673e434702a57da8fe0d829a92eb6"

這個區塊包含367筆交易,並且如你所見,列出的第18筆交易(9ca8f9…)就是存入50mBTC到我們地址的txid我們可以通過heigh條目來判斷:這就是整個區塊鏈中第286,384個區塊。

我們同樣可以使用getblockhash命令通過區塊高度來檢索一個區塊,這樣需要將區塊高度作為引數,並返回那個區塊的區塊雜湊值。

$ bitcoin-cli getblockhash 0
$ bitcoin-cli 0000000000019d6689c085ae165831e934ff763ae46a2a6c17↵
    2b3f1b60a8ce26f

這裡,我們獲得了“創世區塊”的區塊雜湊值,這是被中本聰所挖的第一個區塊,高度為0。所獲得的區塊資訊如下:

$ bitcoin-cli getblock 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1↵
b60a8ce26f
{
    "hash" : "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26↵f",
    "confirmations" : 286388,
    "size" : 285,
    "height" : 0,
    "version" : 1,
    "merkleroot" : "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7af↵
    deda33b",
    "tx" : [
        "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
    ],
    "time" : 1231006505,
    "nonce" : 2083236893,
    "bits" : "1d00ffff",
    "difficulty" : 1.00000000,
    "chainwork" : "0000000000000000000000000000000000000000000000000000000100010001",
    "nextblockhash" : "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048"
    }

getblockgetblockhashgettransaction命令可以按照一定程式設計準則,去探索區塊鏈資料庫。

3.2.7 基於UTXO(未花費的交易輸出)的建立、簽名與提交

命令:listunspentgettxoutcreaterawtransactiondecoderawtransactionsignrawtransactionsendrawtransaction

比特幣的交易是基於花費“輸出”上的,即上一筆交易的支出,整個交易在地址之間轉移所有權。我們的錢包現在收到了一筆向我們錢包地址發來的錢(輸出)。一旦它被確定之後,那筆錢就屬於我們了。

首先,我們可以使用listunspent命令去檢視我們錢包中所有剩餘的從之前交易中已確認的支出:

$ bitcoin-cli listunspent
[
    { 
        "txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
        "vout" : 0,
        "address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",
        "account" : "",
        "scriptPubKey" : "76a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac",
        "amount" : 0.05000000,
        "confirmations" : 7
    } 
]

我們發現交易9ca8f9建立了一個被指派到1hvzSo地址的輸出(“vout”一項為0)對於50mBTC數量的比特幣在這個時間點已經收到了7次確認。通過參考交易之前的txit和vout指數,交易系統將先前的輸出變為本次的輸入。我們現在可以創立一個花費第0個vout的易9ca8f9的賬單。利用他的輸入分配成新的輸出,即給新地址賦值。

首先,讓我們仔細觀察輸出的結果。我們可以使用gettxout命令來得到未花費的輸出的詳細細節。交易輸出通常可以參考txid和vout兩個指標。以下就是我們通過gettxout命令得到的結果:

$ bitcoin-cli gettxout 9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3 0
{
    "bestblock" : "0000000000000001405ce69bd4ceebcdfdb537749cebe89d371eb37e13899fd9",
    "confirmations" : 7,
    "value" : 0.05000000,
    "scriptPubKey" : {
        "asm" : "OP_DUP OP_HASH160 07bdb518fa2e6089fd810235cf1100c9c13d1fd2
        OP_EQUALVERIFY OP_CHECKSIG",
        "hex" : "76a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac",
        "reqSigs" : 1,
        "type" : "pubkeyhash",
        "addresses" : [
            "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL"
        ]
    },
    "version" : 1,
    "coinbase" : false
}

在這裡我們看到由50mBTC分配到我們的賬戶地址1hvz…中。如果我們想用掉剩餘的比特幣,我們要重新建立一筆新的交易。首先,我們為這筆交易建立一個新的地址,告訴它將去往哪裡:

$ bitcoin-cli getnewaddress 1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb

我們將25mBTC送往我們錢包中新的地址1LnfTn…。在這筆新的交易中,我們將要花費50mBTC並且放入25mBTC到這個新地址中。因為我們必須花費所有之前交易的輸出,同時我們必然產生一些找零。我們將產生的找零放回1hvz…的地址之中,即將找零放回到原先產生比特幣的地址之中。最後,我們必須為這次交易支出一些費用——我們將0.5mBTC作為交易費,最終再存入24.5mBTC的找零。新的輸出(25mBTC+24.5mBTC=49.5mBTC)和輸入(50 mBTC)之間的差額就是獎勵給礦工的交易費。

我們用createrawtransaction命令去建立一筆交易。我們將交易的收入(50已確認未支出的mBTC)和兩筆交易的輸出(送往新地址的比特幣和從原先賬戶找回的零錢)作為createrawtransaction的引數。

$ bitcoin-cli createrawtransaction '[{"txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3", "vout" : 0}]' '{"1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb": 0.025, "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL": 0.0245}'

0100000001e34ac1e2baac09c366fce1c2245536bda8f7db0f6685862aecf53ebd69f9a89c0000000000ffffffff02a0252600000000001976a914d90d36e98f62968d2bc9bbd68107564a156a9bcf88ac50622500000000001976a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac00000000

createrawtransaction命令產生了一個原始十六進位制字串,其中編碼了這筆交易的諸多細節。我們首先要通過decoderawtransaction命令來解碼這個字串,以確認所有的細節準確無誤:

 $ bitcoin-cli decoderawtransaction 0100000001e34ac1e2baac09c366fce1c2245536bda8f7db0f6685862aecf53ebd69f9a89c0000000000ffffffff02a0252600000000001976a914d90d36e98f62968d2bc9bbd68107564a156a9bcf88ac50622500000000001976a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac00000000
{
    "txid" : "0793299cb26246a8d24e468ec285a9520a1c30fcb5b6125a102e3fc05d4f3cba",
    "version" : 1,
    "locktime" : 0,
    "vin" : [
        {
            "txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
            "vout" : 0,
            "scriptSig" : {
                "asm" : "",
                "hex" : "" 
            },
            "sequence" : 4294967295
        }
    ],
    "vout" : [
        {
            "value" : 0.02500000,
            "n" : 0,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 d90d36e98f62968d2bc9bbd68107564a156a9bcf OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a914d90d36e98f62968d2bc9bbd68107564a156a9bcf88ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb"
                ]
            }
        },
        {
            "value" : 0.02450000,
            "n" : 1,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 07bdb518fa2e6089fd810235cf1100c9c13d1fd2 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL"
                ]
            } 
        }
    ] 
}

結果無誤!我們的交易“消耗了”從我們已確認的交易中未花費的輸出,然後將它變成兩筆輸出,一個是走向了新地址的25mBTC,另一個是從原來地址返回的24.5mBTC零錢。這之間0.5mBTC的差額作為交易費,以獎勵挖出包含我們這筆交易區塊的礦工。

你有可能注意到,交易中包含一個空的條目scriptSig,因為我們並沒有給它簽名。如果沒有簽名,那麼交易是沒有意義的;同時我們也不能證明我們擁有未花費的輸出的來源地址的所有權。通過簽名,我們移除了輸出上的障礙同時證明了我們的輸出可靠。我們使用signrawtransaction 命令去簽名交易。它需要原始十六進位制的字串作為引數:

一個加密的錢包在簽名之前必須解密,因為簽名需要利用錢包中的祕鑰。

$ bitcoin-cli walletpassphrase foo 360
$ bitcoin-cli signrawtransaction 0100000001e34ac1e2baac09c366fce1c2245536bda8↵
f7db0f6685862aecf53ebd69f9a89c0000000000ffffffff02a0252600000000001976a914d90↵
d36e98f62968d2bc9bbd68107564a156a9bcf88ac50622500000000001976a91407bdb518fa2e↵
6089fd810235cf1100c9c13d1fd288ac00000000
{
    "hex" : "0100000001e34ac1e2baac09c366fce1c2245536bda8f7db0f6685862aecf53ebd69f9a89c000000006a47304402203e8a16522da80cef66bacfbc0c800c6d52c4a26d1d86a54e0a1b76d661f020c9022010397f00149f2a8fb2bc5bca52f2d7a7f87e3897a273ef54b277e4af52051a06012103c9700559f690c4a9182faa8bed88ad8a0c563777ac1d3f00fd44ea6c71dc5127ffffffff02a0252600000000001976a914d90d36e98f62968d2bc9bbd68107564a156a9bcf88ac50622500000000001976a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac00000000",
    "complete" : true
    }

輸入signrawtransaction命令後,得到另一串十六進位制的原始加密交易。我們要對它進行解密,然後去檢視發生的變化,請輸入decoderawtransaction命令:

$ bitcoin-cli decoderawtransaction0100000001e34ac1e2baac09c366fce1c2245536bda8f7db0f6685862aecf53ebd69f9a89c000000006a47304402203e8a16522da80cef66bacfbc0c800c6d52c4a26d1d86a54e0a1b76d661f020c9022010397f00149f2a8fb2bc5bca52f2d7a7f87e3897a273ef54b277e4af52051a06012103c9700559f690c4a9182faa8bed88ad8a0c563777ac1d3f00fd44ea6c71dc5127ffffffff02a0252600000000001976a914d90d36e98f62968d2bc9bbd68107564a156a9bcf88ac50622500000000001976a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac00000000
{
    "txid" : "ae74538baa914f3799081ba78429d5d84f36a0127438e9f721dff584ac17b346",
    "version" : 1,
    "locktime" : 0,
    "vin" : [
        {
            "txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
            "vout" : 0,
            "scriptSig" : {
                "asm" : "304402203e8a16522da80cef66bacfbc0c800c6d52c4a26d1d86a54e0a1b76d661f020c9022010397f00149f2a8fb2bc5bca52f2d7a7f87e3897a273ef54b277e4af52051a0601 03c9700559f690c4a9182faa8bed88ad8a0c563777ac1d3f00fd44ea6c71dc5127",
                "hex" : "47304402203e8a16522da80cef66bacfbc0c800c6d52c4a26d1d86a54e0a1b76d661f020c9022010397f00149f2a8fb2bc5bca52f2d7a7f87e3897a273ef54b277e4af52051a06012103c9700559f690c4a9182faa8bed88ad8a0c563777ac1d3f00fd44ea6c71dc5127"
}, 
            "sequence" : 4294967295
        }
    ],
    "vout" : [ 
        {
            "value" : 0.02500000,
            "n" : 0,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 d90d36e98f62968d2bc9bbd68107564a156a9bcf OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a914d90d36e98f62968d2bc9bbd68107564a156a9bcf88ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb"
                ]
            } 
        }, 
        {
            "value" : 0.02450000,
            "n" : 1,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 07bdb518fa2e6089fd810235cf1100c9c13d1fd2 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL"
                ]
            } 
        } 
    ] 
}

現在,交易中的收入包含了scritSig,一串證明錢包地址1hvz…所有權的數字簽名,同時移除了支出上的障礙,然後我們可以對錢包中的錢進行消費。簽名可以讓這筆交易被比特幣交易網路中的任何節點驗證,使他們變得可靠。

現在,該是提交新交易到比特幣網路的時候了。我們使用由原始十六進位制signrawtransaction命令生成的sendrawtransaction命令。以下就是和剛才解碼時類似的字串:

$ bitcoin-cli sendrawtransaction 0100000001e34ac1e2baac09c366fce1c2245536bda8f7db0f6685862aecf53ebd69f9a89c000000006a47304402203e8a16522da80cef66bacfbc0c800c6d52c4a26d1d86a54e0a1b76d661f020c9022010397f00149f2a8fb2bc5bca52f2d7a7f87e3897a273ef54b277e4af52051a06012103c9700559f690c4a9182faa8bed88ad8a0c563777ac1d3f00fd44ea6c71dc5127ffffffff02a0252600000000001976a914d90d36e98f62968d2bc9bbd68107564a156a9bcf88ac50622500000000001976a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac00000000ae74538baa914f3799081ba78429d5d84f36a0127438e9f721dff584ac17b346

當使用sendrawtransaction命令釋出交易到比特幣網路時,它會返回交易的雜湊值。我們現在可以通過gettransaction命令查詢交易ID:

 $ bitcoin-cli gettransaction ae74538baa914f3799081ba78429d5d84f36a0127438e9f721dff584ac17b346
{
    "amount" : 0.00000000,
    "fee" : -0.00050000,
    "confirmations" : 0,
    "txid" : "ae74538baa914f3799081ba78429d5d84f36a0127438e9f721dff584ac17b346", 
    "time" : 1392666702,
    "timereceived" : 1392666702,
    "details" : [
        {
            "account" : "",
            "address" : "1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb",                "category" : "send",
            "amount" : -0.02500000,
            "fee" : -0.00050000
        }, 
        {
            "account" : "",
            "address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",                 "category" : "send",
            "amount" : -0.02450000,
            "fee" : -0.00050000
        }, 
        {
            "account" : "",
            "address" : "1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb",                "category" : "receive",
            "amount" : 0.02500000
        }, 
        {
            "account" : "",
            "address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",                 "category" : "receive",
            "amount" : 0.02450000
        }
    ]
}

和以前一樣,我們同樣可以通過使用getrawtransactiondecodetransaction命令來檢查交易中的細節。這些命令會得到一個在傳送到比特幣網路之前進行編碼和解碼並且十分精準的原始十六進位制字串。

3.3 其他替代客戶端、資料庫、工具包

除了參考客戶端(bitcoind),還可以使用其他的客戶端和資料庫去連線比特幣網路和資料結構。這些工具都由一系列的程式語言執行,用他們各自的語言為比特幣程式提供原生的互動。

其他的執行方式包括:

▷ libbitcoin和sx tools 
一款C++,通過命令列完成的全節點多執行緒客戶端與程式庫

▷ bitcoinj 
一款全節點java客戶端和程式庫

▷ btcd 
一款全節點GO 語言的比特幣客戶端

▷ Bits of Proof(BOP) 
一款Java企業級平臺的比特幣工具

▷ picocoin 
一款輕量級比特幣執行客戶端

▷ pybitcointools 
一款Python語言的比特幣程式庫

▷ pycoin 
另一款Python語言的比特幣程式庫

在其他的程式語言中,還有許多形式的比特幣(程式)庫。開發者也盡其所能,一直在盡力創造新的比特幣工具。

3.3.1 Libbitcoin和sx Tools

Libbitcoin程式是一款基於C++層面,可擴充套件、多執行緒、模組化的執行工具。它可以支援全節點客戶端和一款叫做sx的命令列工具,並可以提供我們本章所討論的比特幣命令相同的功能。Sx工具同時提供了管理和操作工具,是bitcoind所不能提供的,包括type-2型確定性金鑰和密碼助記工具。

安裝sx

若要安裝sx工具以及相關libbitcoin庫,請在Linux作業系統中下載並安裝線上安裝包:

$ wget http://sx.dyne.org/install-sx.sh
$ sudo bash ./install-sx.sh

現在你應當已經安裝好了sx工具。輸入沒有引數的sx命令來顯示幫助文件,幫助文件列出了所有可用的命令(詳見附錄4)。

sx工具提供了許多實用的編碼與解碼地址的命令,可以從不同的編碼方式轉化,也可以轉化成不同的方式。通過他們,可以探索更多的編碼方式,比如Base58,Base58Check,hex,等等。

3.3.2 pycoin

pycoin最初由Richard Kiss創立並維護,是一款基於Python庫,並可以支援比特幣金鑰的操作和交易的客戶端,甚至可以支援編譯語言從而處理非標準交易。

Pycoin庫同時支援Python2(2.7x)與Python3,以及一些便於使用的命令列工具,比如ku和tx。如果在Python3的虛擬環境下安裝 pycoin0.42,請輸入以下命令:

$ python3 -m venv /tmp/pycoin
$ . /tmp/pycoin/bin/activate
$ pip install pycoin==0.42
Downloading/unpacking pycoin==0.42
  Downloading pycoin-0.42.tar.gz (66kB): 66kB downloaded
  Running setup.py (path:/tmp/pycoin/build/pycoin/setup.py) egg_info for pack-age pycoin

Installing collected packages: pycoin
  Running setup.py install for pycoin

    Installing tx script to /tmp/pycoin/bin
    Installing cache_tx script to /tmp/pycoin/bin
    Installing bu script to /tmp/pycoin/bin
    Installing fetch_unspent script to /tmp/pycoin/bin
    Installing block script to /tmp/pycoin/bin
    Installing spend script to /tmp/pycoin/bin
    Installing ku script to /tmp/pycoin/bin
    Installing genwallet script to /tmp/pycoin/bin
Successfully installed pycoin
Cleaning up...
$

這裡有一個簡單的Python指令碼,通過pycoin庫來交易比特幣:

#!/usr/bin/env python

from pycoin.key import Key 
from pycoin.key.validate import is_address_valid, is_wif_valid from pycoin.services import spendables_for_address
from pycoin.tx.tx_utils import create_signed_tx 

def get_address(which): 
    while 1: 
        print("enter the %s address=> " % which, end='') 
        address = input()
        is_valid = is_address_valid(address)
        if is_valid: 
            return address
        print("invalid address, please try again") 

src_address = get_address("source")
spendables = spendables_for_address(src_address) print(spendables) 

while 1:
    print("enter the WIF for %s=> " % src_address, end='') 
    wif = input()
    is_valid = is_wif_valid(wif)
    if is_valid: 
        break
    print("invalid wif, please try again") 

key = Key.from_text(wif)
if src_address not in (key.address(use_uncompressed=False), key.address(use_un compressed=True)): 
    print("** WIF doesn't correspond to %s" % src_address) 
print("The secret exponent is %d" % key.secret_exponent()) 

dst_address = get_address("destination")

tx = create_signed_tx(spendables, payables=[dst_address], wifs=[wif])

print("here is the signed output transaction") 
print(tx.as_hex())

更多的ku與tx命令列樣例,請參考附錄2。

3.3.3 btcd

btcd是一款基於Go語言的全節點比特幣工具。目前,它通過使用精準的規則(包括bugs),下載、驗證和服務區塊鏈。它同時依靠新發掘出來的區塊來維持交易池,同時依賴沒有形成區塊的單獨交易。在縝密的規則以及檢查下,確保了每筆獨立交易的安全,並且可以過濾基於礦工需求的交易。

btcd與bitcoind的一個主要區別是btcd不包含比特幣錢包的功能,其實這是一個精心的設計。這意味著你不能直接通過btcd進行比特幣交易。然而這項功能可以由正在研發的btcwallet與btcgui兩個專案提供。另一個顯著的區別是btcd同時支援HTTP POST(比如bitcoind)與推薦使用的Websockets兩種通訊協議的請求。並且btcd的RPC連線預設設定為TLS-開啟。

安裝btcd

若要安裝Windows版btcd,請從GitHub下載並執行msi;如果你已經安裝了Go語言,請在Linux中輸入以下命令列:

$ go get github.com/conformal/btcd/...

若要更新btcd到最新版本,請輸入:

$ go get -u -v github.com/conformal/btcd/...

除錯btcd

btcd擁有許多配置選項,可以通過以下命令來檢視:

$ btcd --help

btcd預裝了許多好用的功能包,比如btcctl。它是一種可以通過RPC來控制和查詢的令行工具。Btcd並沒有預設開啟了RPC伺服器,你必須通過以下命令列來配置RPC使用者名稱及密碼:

▷ btcd.conf:

[Application Options]
rpcuser=myuser
rpcpass=SomeDecentp4ssw0rd

▷btcctl.conf:

[Application Options]
rpcuser=myuser
rpcpass=SomeDecentp4ssw0rd

若果你想要重寫配置,請輸入以下命令:

$ btcd -u myuser -P SomeDecentp4ssw0rd
$ btcctl -u myuser -P SomeDecentp4ssw0rd

可以通過以下命令來查詢一系列的選項:

$ btcctl --help

相關文章