探索比特币源码9-顺藤摸瓜之通过RPC读源码
前言
閱讀像比特幣這樣規(guī)模的源碼,理清脈絡(luò)很重要,一個(gè)文件一個(gè)文件閱讀肯定不現(xiàn)實(shí)。
從比特幣系統(tǒng)的RPC接口入手,不失為一個(gè)學(xué)習(xí)源碼的好方法。
具體做法是,按照想要學(xué)習(xí)的功能,找到相應(yīng)的RPC命令,然后找到調(diào)用該命令的函數(shù),便可以順藤摸瓜,將一條線的脈絡(luò)理清。
例如,我最近在學(xué)習(xí)比特幣私鑰、公鑰、地址相關(guān)的源碼。
那么我們可以通過(guò)$ bitcoin-cli help命令,查詢所有的RPC接口
從中可以發(fā)現(xiàn),getnewaddress命令用于獲取一個(gè)新的比特幣地址
因此,順著該命令,我們可以查詢到比特幣系統(tǒng)如何生成一個(gè)私鑰,進(jìn)而計(jì)算出公鑰和比特幣地址。
下面我們來(lái)簡(jiǎn)單分析下RPC相關(guān)的源碼。
RPC 命令的定義
rpc/server.h中定義了有關(guān)RPC的服務(wù)器端接口
用于封裝RPC命令的類型CRPCCommand就定義在其中
class CRPCCommand { public:std::string category;std::string name;rpcfn_type actor;std::vector<std::string> argNames; };因此一個(gè)RPC命令包含4個(gè)屬性:
- category(類別)
RPC命令所屬類別,包括Blockchain、Control、Generating、Mining、Network、Rawtransactions、Util和Wallet這幾種類別 - name(名稱) RPC命令具體名稱,如getnewaddress
- actor(執(zhí)行者) RPC命令的具體執(zhí)行函數(shù)
- argNames(參數(shù)名) RPC命令的參數(shù)列表
其中,actor指向具體執(zhí)行RPC命令的函數(shù),rpcfn_type是一個(gè)回調(diào)函數(shù)類型,定義為:
typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest);其中,輸入?yún)?shù)為JSONRPCRequest類型,返回值為UniValue類型。
JSONRPCRequest的定義為:
class JSONRPCRequest { public:UniValue id;std::string strMethod;UniValue params;bool fHelp;std::string URI;std::string authUser;std::string peerAddr;JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {}void parse(const UniValue& valRequest); };再來(lái)看UniValue類型的定義,在univalue目錄下的README.md文件中,是這樣描述的:
A universal value class, with JSON encoding and decoding.UniValue is an abstract data type that may be a null, boolean, string, number, array container, or a key/value dictionary container, nested to an arbitrary depth.This class is aligned with the JSON standard, [RFC 7159](https://tools.ietf.org/html/rfc7159.html).UniValue是一個(gè)通用值類,通過(guò)JSON進(jìn)行編碼和解碼。UniValue是一種抽象數(shù)據(jù)類型,可以是null、boolean、string、數(shù)字,也可以是數(shù)組容器或鍵/值字典容器,可以嵌套到任意深度。
因此,大概理解為UniValue出現(xiàn)在回調(diào)函數(shù)類型rpcfn_type的返回值這里,是用一個(gè)統(tǒng)一的類型來(lái)替代任何的返回值類型。
CRPCCommand的實(shí)例
不同功能類別的RPC命令被分別定義在不同的文件中,文件一般以rpc開(kāi)頭。
例如錢(qián)包相關(guān)的RPC命令位于wallet/rpcwallet.cpp中:
static const CRPCCommand commands[] = { // category name actor (function) argNames// --------------------- ------------------------ ----------------------- ----------{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },{ "wallet", "walletprocesspsbt", &walletprocesspsbt, {"psbt","sign","sighashtype","bip32derivs"} },{ "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","replaceable","options","bip32derivs"} },{ "hidden", "resendwallettransactions", &resendwallettransactions, {} },{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },// ...{ "wallet", "getnewaddress", &getnewaddress, {"label|account","address_type"} },// ... }于是按照關(guān)心的命令,例如getnewaddress,通過(guò)其actor屬性的取值,可以知道相應(yīng)的功能實(shí)現(xiàn)于getnewaddress()函數(shù)中。(一般情況下RPC命令于具體實(shí)現(xiàn)函數(shù)的命名是一致的)
總結(jié)
以上是生活随笔為你收集整理的探索比特币源码9-顺藤摸瓜之通过RPC读源码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 实现Modbus ASCII多主站应用
- 下一篇: PC软件开发技术之二:用C#开发基于自动