趣旨
手動マイニングゲームを作ってNodeと繋いでゲームのコントローラーでガチのマイニングネットワークに参加できるようにしようと思ってそのために必要そうな関数のひとつとしてRPCを準備しました。本記事はその備忘録です。
関数ごとに作ると複雑なコードも理解しやすい形で保存できるので便利ですね。関数の中身がブラックボックスになってしまってもとりあえず引数と返り値がわかれば使えるので。
ここではBitcoin NodeからRPC呼び出しする関数:rpc_call(url, userpwd, postData)
を宣言・定義してメイン関数にて1行で実行できるようにしてます。
rpc.h
ヘッダファイルで宣言。
#ifndef RPC_H
#define RPC_H
#include <string>
// Function to perform the RPC call
std::string rpc_call(const std::string& url, const std::string& userpwd, const std::string& postData);
#endif // RPC_H
rpc.cpp
関数ファイルで定義。
#include "rpc.h"
#include <curl/curl.h>
#include <iostream>
// Callback function for writing data received by libcurl
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
// Implementation of the RPC call
std::string rpc_call(const std::string& url, const std::string& userpwd, const std::string& postData) {
CURL *curl;
CURLcode res;
std::string readBuffer;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); // Turn off verbose output
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
}
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return readBuffer;
}
main.cpp
メイン関数で実行。
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
#include <memory>
#include "rpc.h"
int main() {
std::string url = "http://0.0.0.0”; // replace it with your local node ip
std::string userpwd = “user:password; // user be umbrel, password be your own node password
std::string postData = R"({"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": [] })";
// Perform RPC call
std::string response = rpc_call(url, userpwd, postData);
std::cout << "Received JSON: " << response << std::endl; // Print the received JSON string for verification
// Parse the JSON response
Json::Value root;
Json::CharReaderBuilder builder;
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
JSONCPP_STRING errs;
bool parsingSuccessful = reader->parse(response.c_str(), response.c_str() + response.size(), &root, &errs);
if (!parsingSuccessful) {
std::cerr << "Failed to parse JSON: " << errs << std::endl;
return 1;
}
// Extract the 'bestblockhash' and 'difficulty' values
std::string bestBlockHash = root["result"]["bestblockhash"].asString();
double difficulty = root["result"]["difficulty"].asDouble();
std::cout << "Best Block Hash: " << bestBlockHash << std::endl;
std::cout << "Difficulty: " << difficulty << std::endl;
return 0;
}
ライブラリはすでにインストール済みだと仮定します。以下のコマンドでコンパイルすれば起動できるようになります。
g++ -o rpc main.cpp rpc.cpp -lcurl -ljsoncpp
実行結果
0をここまで連続させるナンス値を見つける計算ってほんととんでもないですよね。僕の認知力で想像できる範囲を遥かに超えてます。理論としては理解できますが、実感はゼロです。
Received JSON: {"result":{"chain":"main","blocks":842667,"headers":842667,"bestblockhash":"000000000000000000007f3fed33050f1f21b666b16a7a446ea9fdfa8a0162e7","difficulty":88104191118793.16,"time":1715236598,"mediantime":1715232883,"verificationprogress":0.9999901552536505,"initialblockdownload":false,"chainwork":"0000000000000000000000000000000000000000787a926ea9c2cb0058095528","size_on_disk":647722229875,"pruned":false,"warnings":""},"error":null,"id":"curltest"}
Best Block Hash: 000000000000000000007f3fed33050f1f21b666b16a7a446ea9fdfa8a0162e7
bestblockhash
これがPrevBlocHashに該当するかと。
getblockchaininfoの詳細は以下で確認可能。
自分でNodeを準備できない場合はQuickNodeがおそらく使えるのでNodeを自宅で準備できなくても試せます。
便利で感激!