Skip to content

Instantly share code, notes, and snippets.

@ismaelsadeeq
Created December 24, 2024 17:15
Show Gist options
  • Select an option

  • Save ismaelsadeeq/a5e3edb3fbf2d7f3c6698c1610622d22 to your computer and use it in GitHub Desktop.

Select an option

Save ismaelsadeeq/a5e3edb3fbf2d7f3c6698c1610622d22 to your computer and use it in GitHub Desktop.
Generate block on regtest concurrently
#include <curl/curl.h>
#include <future>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include "nlohmann/json.hpp"
using json = nlohmann::json;
static int ITERATIONS{1000};
struct Config {
std::string url;
std::string auth;
};
// Helper function for curl write callback
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
userp->append((char*)contents, size * nmemb);
return size * nmemb;
}
// RPC request class
class RPCRequest {
private:
CURL* curl;
std::string response;
struct curl_slist* headers;
Config config;
public:
RPCRequest(const Config& cfg) : config(cfg) {
curl = curl_easy_init();
headers = curl_slist_append(nullptr, "content-type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, config.url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_USERPWD, config.auth.c_str());
}
~RPCRequest() {
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
json makeRequest(const json& payload) {
std::string data = payload.dump();
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
response.clear();
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(res));
}
return json::parse(response)["result"];
}
CURL* getCurl() { return curl; }
};
class BlockGenerator {
protected:
int num_threads;
Config config;
public:
BlockGenerator(const Config& cfg) : num_threads(std::thread::hardware_concurrency()), config(cfg) {}
virtual ~BlockGenerator() = default;
virtual void generateBlocks(int number) = 0;
std::string getnewaddress(RPCRequest& rpc) {
json payload = {
{"method", "getnewaddress"},
{"params", {}},
{"id", 1}
};
return rpc.makeRequest(payload);
}
json generateBlock(RPCRequest& rpc, const std::string& address) {
json payload = {
{"method", "generateblock"},
{"params", {address, json::array()}},
{"id", 1}
};
return rpc.makeRequest(payload);
}
};
class ThreadPoolGenerator : public BlockGenerator {
public:
using BlockGenerator::BlockGenerator;
void generateBlocks(int number) override {
std::vector<std::future<void>> futures;
for (int i = 0; i < num_threads; ++i) {
futures.push_back(std::async(std::launch::async, [&, i]() {
RPCRequest rpc(config);
for (int j = i; j < number; j += num_threads) {
auto address = getnewaddress(rpc);
std::cout << "getting block " << j << std::endl;
auto block = generateBlock(rpc, address);
}
}));
}
for (auto& future : futures) {
future.wait();
}
}
};
int main() {
try {
Config config{"http://127.0.0.1:18443", "abubakar:sadeeq"};
ThreadPoolGenerator threadPool(config);
threadPool.generateBlocks(ITERATIONS);
} catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment