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命令及其预期输出。

3.4.1 获得Bitcoin Core客户端状态的信息

Bitcoin Core通过JSON-RPC提供了不同模块的状态信息。其中最重要的命令有getblockchaininfo, getmempoolinfo, getnetworkinfo and 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": ""
}

数据返回的是JavaScript Object Notation (JSON)格式,这种格式很容易被所有编程语言“识别”,同时也方便人阅读。在上面数据中,我们看到比特币软件客户端版本号(150000)和比特币协议版本号(70015)。 还看到当前的连接数(8)。 后面还看到比特币网络和客户端设置的相关信息。

提示 比特币客户端“赶上”当前的blockchain高度需要一些时间,因为它要从其他比特币客户端下载区块。 可以使用getblockchaininfo检查进度,查看已已同步的区块的数量。

3.4.2 查看和解码交易

命令:getrawtransaction,decodeawtransaction

在买咖啡的故事中,Alice从Bob咖啡厅买了一杯咖啡。 她的交易ID(txid)0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2,已经被记录在区块链上。 使用API把交易ID作为参数可以进行检索和检查该交易:

$ bitcoin-cli getrawtransaction 0627052b6f28912f2703066a912ea577f2ce4da4caa5a↵
5fbd8a57286c345c2f2
0100000001186f9f998a5aa6f048e51dd8419a14d8a0f1a8a2836dd734d2804fe65fa35779000000008b483045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4↵
ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813014↵
10484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc54123363767↵
89d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adfffffffff0260e31600000000001976a914ab68025513c3dbd2f7b92a94e0581f5d50f654e788acd0ef8000000000001976a9↵
147f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a888ac00000000

提示 交易ID在交易被确认之前是没有意义的。 在区块链中缺少交易哈希并不意味着交易未被处理。 这被称为“交易延展性”,因为区块中的交易被确认之前是可以修改交易哈希的。 交易被确认后,txid是就是不可改变的和权威的。

命令getrawtransaction以十六进制形式返回序列化交易。 为了解码,使用decodeawtransaction命令,将十六进制数据作为参数。 可以复制getrawtransaction返回的十六进制,并将其作为参数粘贴到decodeawtransaction中:

$ 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"
        ]
      }
    }
  ]
}

交易解码展示这笔交易的所有成分,包括交易的输入及输出。在这个例子中,可以看到这笔给我们新地址存入 15mBTC的交易使用了一个输入并且产生两个输出。这笔交易的输入是前一笔确认交易的输出(以7957a35fe开头的 vin txid)。两个输出则是15mBTC转账金额和返回的找零金额。

可以使用相同命令(例如 gettransaction )检查本次交易txid前一笔交易,进一步探索区块链。通过从 一笔交易跳到另外一笔交易,我们可以追溯一连串的交易,因为币一定是从一个拥有者的地址传送到另一个拥有者的地址。

3.4.3 探索区块

命令: getblock 、 getblockhash

探索区块类似于探索交易。 不同之处是区块可以由区块高度或区块哈希引用。 首先,我们找一个区块的高度。 在买咖啡故事中,我们看到Alice的交易已被包含在277316区块中。

使用getblockhash命令,该命令用区块高度作为参数,并返回该区块的区块哈希值:

$ bitcoin-cli getblockhash 277316
0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4
既然知道要找的交易在这个区块中,我们可以使用getblock命令,把区块哈希值作为参数:

$ bitcoin-cli getblock 0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4
{
  "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的咖啡付款。 高度条目告诉我们这是区块链中的第277316区块。

3.4.4 使用Bitcoin Core的编程接口

bitcoin-cli 助手工具对于探索Bitcoin Core API和测试功能非常有用。 应用编程接口的全部要点是以编程方式访问软件功能。 在本节中,我们将演示从另一个程序访问Bitcoin Core的过程。

Bitcoin Core的API是一个JSON-RPC接口。 JSON代表JJavaScript Object Notation,它可以很方便地呈现出人类和程序都可以轻松阅读的数据格式。 RPC代表远程过程调用,这意味着我们通过网络协议调用远程(位于Bitcoin Core节点)的程序(函数)。 这里的网络协议是HTTP或HTTPS(加密连接)。

当我们使用bitcoin-cli助手获取命令的帮助时,它给了我们一个使用curl的例子,这是一个常用的JSON-RPC调用命令行HTTP客户端:

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

此命令显示curl向本地主机(127.0.0.1)提交HTTP请求,连接到默认比特币端口(8332),并使用text / plain编码向getinfo方法提交jsonrpc请求。

你会注意到curl随同请求会发出一个凭证。Bitcoin Core每次启动时会创建一个随机口令,放在数据目录下的.cookie文件中。bitcoin-cli助手会读取数据目录下的这个口令文件。同样你也可以复制这个口令发送给curl(或更高级别的Bitcoin Core RPC封装)。你还可以使用Bitcoin Core源码目录下的./share/rpcauth/rpcauth.py助手脚本创建一个静态口令。

如果您在自己的程序中部署JSON-RPC调用,可以使用通用的HTTP库构建调用,类似于前面的curl示例所示。

然而,大多数编程语言中都有“包装”在Bitcoin Core API中的库,这样使用起来更简单。 使用python-bitcoinlib库可以简化API访问。 记住,这需要一个正在运行的Bitcoin Core实例,用于JSON-RPC调用。

下面的例子中的Python脚本使用简单的getblockchaininfo调用,从Bitcoin Core返回的数据中显示了区块参数。

例3-3通过Bitcoin Core的JSON-RPC API运行getblockchaininfo

code/rpc_example.py[]

运行结果如下:

$ python rpc_example.py
394075

它告诉我们,我们的本地Bitcoin Core节点存储的区块链中有394075个区块。 虽然这个结果很简单,但它演示了使用库作为Bitcoin Core的JSON-RPC API的简化接口的基本用法。

接下来,我们使用getrawtransaction和decodetransaction调用来检索Alice咖啡付款的详细信息。 在下面的例子中,我们检索Alice的交易并列出交易的输出。 对于每个输出,我们显示收款地址和金额。 回忆一下,Alice的交易有一个输出支付Bob的咖啡馆,另一个输出是给Alice自己的找零。

例3-4检索交易并遍历输出

code/rpc_transaction.py[]

运行结果如下:

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

上述两个例子都比较简单。 你真的不需要一个程序来运行它们; 你可以很容易地使用bitcoin-cli 助手。 不过,下一个示例需要数百个RPC调用,并更清楚地说明了使用编程接口的方便。

在例5中,我们首先检索区块277316,然后通过引用每个交易ID来检索所有的419个交易。 接下来,我们遍历每个交易的输出累加起来。

例3-5检索区块并累加所有交易的输出

code/rpc_block.py[]

运行结果如下:

$ python rpc_block.py
('Total value in block: ', Decimal('10322.07722534'))

我们的示例代码计算出,此区块中交易的总价值为10,322.07722534 个BTC(包括25 BTC矿工费奖励和0.0909 BTC交易费)。 可以将这个结果与使用区块浏览器搜索区块哈希或高度的结果进行比较。 有些区块浏览器不包括矿工费奖励和交易费。 看看是否有不同。