Bitcoin NodeからRPCでbestBlockHashを取得する

# 趣旨
手動マイニングゲームを作ってNodeと繋いでゲームのコントローラーでガチのマイニングネットワークに参加できるようにしようと思ってそのために必要そうな関数のひとつとしてRPCを準備しました。本記事はその備忘録です。

関数ごとに作ると複雑なコードも理解しやすい形で保存できるので便利ですね。関数の中身がブラックボックスになってしまってもとりあえず引数と返り値がわかれば使えるので。

ここではBitcoin NodeからRPC呼び出しする関数：`rpc_call(url, userpwd, postData)`を宣言・定義してメイン関数にて1行で実行できるようにしてます。

# rpc.h
ヘッダファイルで宣言。

```C++ 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
関数ファイルで定義。
```C++ 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
メイン関数で実行。
```C++ 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をここまで連続させるナンス値を見つける計算ってほんととんでもないですよね。僕の認知力で想像できる範囲を遥かに超えてます。理論としては理解できますが、実感はゼロです。

```JSON
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に該当するかと。

https://chainquery.com/bitcoin-cli/getbestblockhash

https://developer.bitcoin.org/reference/rpc/getbestblockhash.html

getblockchaininfoの詳細は以下で確認可能。

https://developer.bitcoin.org/reference/rpc/getblockchaininfo.html

自分でNodeを準備できない場合はQuickNodeがおそらく使えるのでNodeを自宅で準備できなくても試せます。

https://www.quicknode.com/docs/bitcoin

便利で感激！