探索比特币源码9-顺藤摸瓜之通过RPC读源码
前言
閱讀像比特幣這樣規模的源碼,理清脈絡很重要,一個文件一個文件閱讀肯定不現實。
從比特幣系統的RPC接口入手,不失為一個學習源碼的好方法。
具體做法是,按照想要學習的功能,找到相應的RPC命令,然后找到調用該命令的函數,便可以順藤摸瓜,將一條線的脈絡理清。
例如,我最近在學習比特幣私鑰、公鑰、地址相關的源碼。
那么我們可以通過$ bitcoin-cli help命令,查詢所有的RPC接口
從中可以發現,getnewaddress命令用于獲取一個新的比特幣地址
因此,順著該命令,我們可以查詢到比特幣系統如何生成一個私鑰,進而計算出公鑰和比特幣地址。
下面我們來簡單分析下RPC相關的源碼。
RPC 命令的定義
rpc/server.h中定義了有關RPC的服務器端接口
用于封裝RPC命令的類型CRPCCommand就定義在其中
class CRPCCommand { public:std::string category;std::string name;rpcfn_type actor;std::vector<std::string> argNames; };因此一個RPC命令包含4個屬性:
- category(類別)
RPC命令所屬類別,包括Blockchain、Control、Generating、Mining、Network、Rawtransactions、Util和Wallet這幾種類別 - name(名稱) RPC命令具體名稱,如getnewaddress
- actor(執行者) RPC命令的具體執行函數
- argNames(參數名) RPC命令的參數列表
其中,actor指向具體執行RPC命令的函數,rpcfn_type是一個回調函數類型,定義為:
typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest);其中,輸入參數為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); };再來看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是一個通用值類,通過JSON進行編碼和解碼。UniValue是一種抽象數據類型,可以是null、boolean、string、數字,也可以是數組容器或鍵/值字典容器,可以嵌套到任意深度。
因此,大概理解為UniValue出現在回調函數類型rpcfn_type的返回值這里,是用一個統一的類型來替代任何的返回值類型。
CRPCCommand的實例
不同功能類別的RPC命令被分別定義在不同的文件中,文件一般以rpc開頭。
例如錢包相關的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"} },// ... }于是按照關心的命令,例如getnewaddress,通過其actor屬性的取值,可以知道相應的功能實現于getnewaddress()函數中。(一般情況下RPC命令于具體實現函數的命名是一致的)
總結
以上是生活随笔為你收集整理的探索比特币源码9-顺藤摸瓜之通过RPC读源码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现Modbus ASCII多主站应用
- 下一篇: Modbus协议栈应用实例之四:Modb